CCDrawNode.js 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804
  1. /****************************************************************************
  2. Copyright (c) 2010-2012 cocos2d-x.org
  3. Copyright (c) 2008-2010 Ricardo Quesada
  4. Copyright (c) 2011 Zynga Inc.
  5. Copyright (c) 2012 Scott Lembcke and Howling Moon Software
  6. http://www.cocos2d-x.org
  7. Permission is hereby granted, free of charge, to any person obtaining a copy
  8. of this software and associated documentation files (the "Software"), to deal
  9. in the Software without restriction, including without limitation the rights
  10. to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. copies of the Software, and to permit persons to whom the Software is
  12. furnished to do so, subject to the following conditions:
  13. The above copyright notice and this permission notice shall be included in
  14. all copies or substantial portions of the Software.
  15. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. THE SOFTWARE.
  22. ****************************************************************************/
  23. /*
  24. * Code copied & pasted from SpacePatrol game https://github.com/slembcke/SpacePatrol
  25. *
  26. * Renamed and added some changes for cocos2d
  27. *
  28. */
  29. cc.v2fzero = function () {
  30. return {x: 0, y: 0};
  31. };
  32. cc.v2f = function (x, y) {
  33. return {x: x, y: y};
  34. };
  35. cc.v2fadd = function (v0, v1) {
  36. return cc.v2f(v0.x + v1.x, v0.y + v1.y);
  37. };
  38. cc.v2fsub = function (v0, v1) {
  39. return cc.v2f(v0.x - v1.x, v0.y - v1.y);
  40. };
  41. cc.v2fmult = function (v, s) {
  42. return cc.v2f(v.x * s, v.y * s);
  43. };
  44. cc.v2fperp = function (p0) {
  45. return cc.v2f(-p0.y, p0.x);
  46. };
  47. cc.v2fneg = function (p0) {
  48. return cc.v2f(-p0.x, -p0.y);
  49. };
  50. cc.v2fdot = function (p0, p1) {
  51. return p0.x * p1.x + p0.y * p1.y;
  52. };
  53. cc.v2fforangle = function (_a_) {
  54. return cc.v2f(Math.cos(_a_), Math.sin(_a_));
  55. };
  56. cc.v2fnormalize = function (p) {
  57. var r = cc.pNormalize(cc.p(p.x, p.y));
  58. return cc.v2f(r.x, r.y);
  59. };
  60. cc.__v2f = function (v) {
  61. return cc.v2f(v.x, v.y);
  62. };
  63. cc.__t = function (v) {
  64. return {u: v.x, v: v.y};
  65. };
  66. /**
  67. * <p>CCDrawNode for Canvas <br/>
  68. * Node that draws dots, segments and polygons. <br/>
  69. * Faster than the "drawing primitives" since they it draws everything in one single batch.</p>
  70. * @class
  71. * @extends cc.Node
  72. */
  73. cc.DrawNodeCanvas = cc.Node.extend(/** @lends cc.DrawNodeCanvas# */{
  74. _buffer: null,
  75. _blendFunc: null,
  76. _lineWidth: 0,
  77. _drawColor: null,
  78. ctor: function () {
  79. cc.Node.prototype.ctor.call(this);
  80. this._buffer = [];
  81. this._lineWidth = 1;
  82. this._drawColor = new cc.Color4F(255, 255, 255, 255);
  83. this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
  84. },
  85. // ----common function start ----
  86. getBlendFunc: function () {
  87. return this._blendFunc;
  88. },
  89. setBlendFunc: function (blendFunc) {
  90. this._blendFunc = blendFunc;
  91. },
  92. /**
  93. * line width setter
  94. * @param {Number} width
  95. */
  96. setLineWidth: function (width) {
  97. this._lineWidth = width;
  98. },
  99. /**
  100. * line width getter
  101. * @returns {Number}
  102. */
  103. getLineWidth: function () {
  104. return this._lineWidth;
  105. },
  106. /**
  107. * draw color setter
  108. * @param {cc.Color4F} color
  109. */
  110. setDrawColor: function (color) {
  111. this._drawColor.r = color.r;
  112. this._drawColor.g = color.g;
  113. this._drawColor.b = color.b;
  114. this._drawColor.a = color.a;
  115. },
  116. /**
  117. * draw color getter
  118. * @returns {cc.Color4F}
  119. */
  120. getDrawColor: function () {
  121. return new cc.Color4F(this._drawColor.r, this._drawColor.g, this._drawColor.b, this._drawColor.a);
  122. },
  123. // ----common function end ----
  124. /**
  125. * draws a rectangle given the origin and destination point measured in points.
  126. * @param {cc.Point} origin
  127. * @param {cc.Point} destination
  128. * @param {cc.Color4F} fillColor
  129. * @param {Number} lineWidth
  130. * @param {cc.Color4F} lineColor
  131. */
  132. drawRect: function (origin, destination, fillColor, lineWidth, lineColor) {
  133. lineWidth = lineWidth || this._lineWidth;
  134. lineColor = lineColor || this.getDrawColor();
  135. var vertices = [
  136. origin,
  137. cc.p(destination.x, origin.y),
  138. destination,
  139. cc.p(origin.x, destination.y)
  140. ];
  141. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
  142. element.verts = vertices;
  143. element.lineWidth = lineWidth;
  144. element.lineColor = lineColor;
  145. element.isClosePolygon = true;
  146. element.isStroke = true;
  147. element.lineCap = "butt";
  148. element.fillColor = fillColor;
  149. if (fillColor) {
  150. element.isFill = true;
  151. }
  152. this._buffer.push(element);
  153. },
  154. /**
  155. * draws a circle given the center, radius and number of segments.
  156. * @override
  157. * @param {cc.Point} center center of circle
  158. * @param {Number} radius
  159. * @param {Number} angle angle in radians
  160. * @param {Number} segments
  161. * @param {Boolean} drawLineToCenter
  162. * @param {Number} lineWidth
  163. * @param {cc.Color4F} color
  164. */
  165. drawCircle: function (center, radius, angle, segments, drawLineToCenter, lineWidth, color) {
  166. lineWidth = lineWidth || this._lineWidth;
  167. color = color || this.getDrawColor();
  168. var coef = 2.0 * Math.PI / segments;
  169. var vertices = [];
  170. for (var i = 0; i <= segments; i++) {
  171. var rads = i * coef;
  172. var j = radius * Math.cos(rads + angle) + center.x;
  173. var k = radius * Math.sin(rads + angle) + center.y;
  174. vertices.push(cc.p(j, k));
  175. }
  176. if (drawLineToCenter) {
  177. vertices.push(cc.p(center.x, center.y));
  178. }
  179. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
  180. element.verts = vertices;
  181. element.lineWidth = lineWidth;
  182. element.lineColor = color;
  183. element.isClosePolygon = true;
  184. element.isStroke = true;
  185. this._buffer.push(element);
  186. },
  187. /**
  188. * draws a quad bezier path
  189. * @override
  190. * @param {cc.Point} origin
  191. * @param {cc.Point} control
  192. * @param {cc.Point} destination
  193. * @param {Number} segments
  194. * @param {Number} lineWidth
  195. * @param {cc.Color4F} color
  196. */
  197. drawQuadBezier: function (origin, control, destination, segments, lineWidth, color) {
  198. lineWidth = lineWidth || this._lineWidth;
  199. color = color || this.getDrawColor();
  200. var vertices = [];
  201. var t = 0.0;
  202. for (var i = 0; i < segments; i++) {
  203. var x = Math.pow(1 - t, 2) * origin.x + 2.0 * (1 - t) * t * control.x + t * t * destination.x;
  204. var y = Math.pow(1 - t, 2) * origin.y + 2.0 * (1 - t) * t * control.y + t * t * destination.y;
  205. vertices.push(cc.p(x, y));
  206. t += 1.0 / segments;
  207. }
  208. vertices.push(cc.p(destination.x, destination.y));
  209. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
  210. element.verts = vertices;
  211. element.lineWidth = lineWidth;
  212. element.lineColor = color;
  213. element.isStroke = true;
  214. element.lineCap = "round";
  215. this._buffer.push(element);
  216. },
  217. /**
  218. * draws a cubic bezier path
  219. * @override
  220. * @param {cc.Point} origin
  221. * @param {cc.Point} control1
  222. * @param {cc.Point} control2
  223. * @param {cc.Point} destination
  224. * @param {Number} segments
  225. * @param {Number} lineWidth
  226. * @param {cc.Color4F} color
  227. */
  228. drawCubicBezier: function (origin, control1, control2, destination, segments, lineWidth, color) {
  229. lineWidth = lineWidth || this._lineWidth;
  230. color = color || this.getDrawColor();
  231. var vertices = [];
  232. var t = 0;
  233. for (var i = 0; i < segments; i++) {
  234. var x = Math.pow(1 - t, 3) * origin.x + 3.0 * Math.pow(1 - t, 2) * t * control1.x + 3.0 * (1 - t) * t * t * control2.x + t * t * t * destination.x;
  235. var y = Math.pow(1 - t, 3) * origin.y + 3.0 * Math.pow(1 - t, 2) * t * control1.y + 3.0 * (1 - t) * t * t * control2.y + t * t * t * destination.y;
  236. vertices.push(cc.p(x, y));
  237. t += 1.0 / segments;
  238. }
  239. vertices.push(cc.p(destination.x, destination.y));
  240. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
  241. element.verts = vertices;
  242. element.lineWidth = lineWidth;
  243. element.lineColor = color;
  244. element.isStroke = true;
  245. element.lineCap = "round";
  246. this._buffer.push(element);
  247. },
  248. /**
  249. * draw a CatmullRom curve
  250. * @override
  251. * @param {Array} points
  252. * @param {Number} segments
  253. * @param {Number} lineWidth
  254. * @param {cc.Color4F} color
  255. */
  256. drawCatmullRom: function (points, segments, lineWidth, color) {
  257. this.drawCardinalSpline(points, 0.5, segments, lineWidth, color);
  258. },
  259. /**
  260. * draw a cardinal spline path
  261. * @override
  262. * @param {Array} config
  263. * @param {Number} tension
  264. * @param {Number} segments
  265. * @param {Number} lineWidth
  266. * @param {cc.Color4F} color
  267. */
  268. drawCardinalSpline: function (config, tension, segments, lineWidth, color) {
  269. lineWidth = lineWidth || this._lineWidth;
  270. color = color || this.getDrawColor();
  271. var vertices = [];
  272. var p, lt;
  273. var deltaT = 1.0 / config.length;
  274. for (var i = 0; i < segments + 1; i++) {
  275. var dt = i / segments;
  276. // border
  277. if (dt == 1) {
  278. p = config.length - 1;
  279. lt = 1;
  280. } else {
  281. p = 0 | (dt / deltaT);
  282. lt = (dt - deltaT * p) / deltaT;
  283. }
  284. // Interpolate
  285. var newPos = cc.CardinalSplineAt(
  286. cc.getControlPointAt(config, p - 1),
  287. cc.getControlPointAt(config, p - 0),
  288. cc.getControlPointAt(config, p + 1),
  289. cc.getControlPointAt(config, p + 2),
  290. tension, lt);
  291. vertices.push(newPos);
  292. }
  293. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
  294. element.verts = vertices;
  295. element.lineWidth = lineWidth;
  296. element.lineColor = color;
  297. element.isStroke = true;
  298. element.lineCap = "round";
  299. this._buffer.push(element);
  300. },
  301. /**
  302. * draw a dot at a position, with a given radius and color
  303. * @param {cc.Point} pos
  304. * @param {Number} radius
  305. * @param {cc.Color4F} color
  306. */
  307. drawDot: function (pos, radius, color) {
  308. color = color || this.getDrawColor();
  309. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_DOT);
  310. element.verts = [pos];
  311. element.lineWidth = radius;
  312. element.fillColor = color;
  313. this._buffer.push(element);
  314. },
  315. /**
  316. * draw a segment with a radius and color
  317. * @param {cc.Point} from
  318. * @param {cc.Point} to
  319. * @param {Number} lineWidth
  320. * @param {cc.Color4F} color
  321. */
  322. drawSegment: function (from, to, lineWidth, color) {
  323. lineWidth = lineWidth || this._lineWidth;
  324. color = color || this.getDrawColor();
  325. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
  326. element.verts = [from, to];
  327. element.lineWidth = lineWidth;
  328. element.lineColor = color;
  329. element.isStroke = true;
  330. element.lineCap = "round";
  331. this._buffer.push(element);
  332. },
  333. /**
  334. * draw a polygon with a fill color and line color without copying the vertex list
  335. * @param {Array} verts
  336. * @param {cc.Color4F} fillColor
  337. * @param {Number} lineWidth
  338. * @param {cc.Color4F} color
  339. */
  340. drawPoly_: function (verts, fillColor, lineWidth, color) {
  341. lineWidth = lineWidth || this._lineWidth;
  342. color = color || this.getDrawColor();
  343. var element = new cc._DrawNodeElement(cc.DrawNode.TYPE_POLY);
  344. element.verts = verts;
  345. element.fillColor = fillColor;
  346. element.lineWidth = lineWidth;
  347. element.lineColor = color;
  348. element.isClosePolygon = true;
  349. element.isStroke = true;
  350. element.lineCap = "round";
  351. if (fillColor) {
  352. element.isFill = true;
  353. }
  354. this._buffer.push(element);
  355. },
  356. /**
  357. * draw a polygon with a fill color and line color, copying the vertex list
  358. * @param {Array} verts
  359. * @param {cc.Color4F} fillColor
  360. * @param {Number} lineWidth
  361. * @param {cc.Color4F} color
  362. */
  363. drawPoly: function (verts, fillColor, lineWidth, color) {
  364. var vertsCopy = [];
  365. for (var i=0; i < verts.length; i++) {
  366. vertsCopy.push(cc.p(verts[i].x, verts[i].y));
  367. }
  368. return this.drawPoly_(vertsCopy, fillColor, lineWidth, color);
  369. },
  370. draw: function (ctx) {
  371. var context = ctx || cc.renderContext;
  372. if ((this._blendFunc && (this._blendFunc.src == gl.SRC_ALPHA) && (this._blendFunc.dst == gl.ONE)))
  373. context.globalCompositeOperation = 'lighter';
  374. for (var i = 0; i < this._buffer.length; i++) {
  375. var element = this._buffer[i];
  376. switch (element.type) {
  377. case cc.DrawNode.TYPE_DOT:
  378. this._drawDot(context, element);
  379. break;
  380. case cc.DrawNode.TYPE_SEGMENT:
  381. this._drawSegment(context, element);
  382. break;
  383. case cc.DrawNode.TYPE_POLY:
  384. this._drawPoly(context, element);
  385. break;
  386. }
  387. }
  388. },
  389. _drawDot: function (ctx, element) {
  390. var locColor = element.fillColor;
  391. var locPos = element.verts[0];
  392. var locRadius = element.lineWidth;
  393. var locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
  394. ctx.fillStyle = "rgba(" + (0 | (locColor.r * 255)) + "," + (0 | (locColor.g * 255)) + "," + (0 | (locColor.b * 255)) + "," + locColor.a + ")";
  395. ctx.beginPath();
  396. ctx.arc(locPos.x * locScaleX, -locPos.y * locScaleY, locRadius * locScaleX, 0, Math.PI * 2, false);
  397. ctx.closePath();
  398. ctx.fill();
  399. },
  400. _drawSegment: function (ctx, element) {
  401. var locColor = element.lineColor;
  402. var locFrom = element.verts[0];
  403. var locTo = element.verts[1];
  404. var locLineWidth = element.lineWidth;
  405. var locLineCap = element.lineCap;
  406. var locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
  407. ctx.strokeStyle = "rgba(" + (0 | (locColor.r * 255)) + "," + (0 | (locColor.g * 255)) + "," + (0 | (locColor.b * 255)) + "," + locColor.a + ")";
  408. ctx.lineWidth = locLineWidth * locScaleX;
  409. ctx.beginPath();
  410. ctx.lineCap = locLineCap;
  411. ctx.moveTo(locFrom.x * locScaleX, -locFrom.y * locScaleY);
  412. ctx.lineTo(locTo.x * locScaleX, -locTo.y * locScaleY);
  413. ctx.stroke();
  414. },
  415. _drawPoly: function (ctx, element) {
  416. var locVertices = element.verts;
  417. var locLineCap = element.lineCap;
  418. var locFillColor = element.fillColor;
  419. var locLineWidth = element.lineWidth;
  420. var locLineColor = element.lineColor;
  421. var locIsClosePolygon = element.isClosePolygon;
  422. var locIsFill = element.isFill;
  423. var locIsStroke = element.isStroke;
  424. if (locVertices == null)
  425. return;
  426. var firstPoint = locVertices[0];
  427. var locScaleX = cc.EGLView.getInstance().getScaleX(), locScaleY = cc.EGLView.getInstance().getScaleY();
  428. ctx.lineCap = locLineCap;
  429. if (locFillColor) {
  430. ctx.fillStyle = "rgba(" + (0 | (locFillColor.r * 255)) + "," + (0 | (locFillColor.g * 255)) + ","
  431. + (0 | (locFillColor.b * 255)) + "," + locFillColor.a + ")";
  432. }
  433. if (locLineWidth) {
  434. ctx.lineWidth = locLineWidth * locScaleX;
  435. }
  436. if (locLineColor) {
  437. ctx.strokeStyle = "rgba(" + (0 | (locLineColor.r * 255)) + "," + (0 | (locLineColor.g * 255)) + ","
  438. + (0 | (locLineColor.b * 255)) + "," + locLineColor.a + ")";
  439. }
  440. ctx.beginPath();
  441. ctx.moveTo(firstPoint.x * locScaleX, -firstPoint.y * locScaleY);
  442. for (var i = 1, len = locVertices.length; i < len; i++)
  443. ctx.lineTo(locVertices[i].x * locScaleX, -locVertices[i].y * locScaleY);
  444. if (locIsClosePolygon)
  445. ctx.closePath();
  446. if (locIsFill)
  447. ctx.fill();
  448. if (locIsStroke)
  449. ctx.stroke();
  450. },
  451. /**
  452. * Clear the geometry in the node's buffer.
  453. */
  454. clear: function () {
  455. this._buffer.length = 0;
  456. }
  457. });
  458. /**
  459. * <p>CCDrawNode for WebGL <br/>
  460. * Node that draws dots, segments and polygons. <br/>
  461. * Faster than the "drawing primitives" since they it draws everything in one single batch.</p>
  462. * @class
  463. * @extends cc.Node
  464. */
  465. cc.DrawNodeWebGL = cc.Node.extend(/** @lends cc.DrawNodeWebGL# */{
  466. _bufferCapacity:0,
  467. _buffer:null,
  468. _trianglesArrayBuffer:null,
  469. _trianglesWebBuffer:null,
  470. _trianglesReader:null,
  471. _blendFunc:null,
  472. _dirty:false,
  473. // ----common function start ----
  474. getBlendFunc:function () {
  475. return this._blendFunc;
  476. },
  477. setBlendFunc:function (blendFunc) {
  478. this._blendFunc = blendFunc;
  479. },
  480. // ----common function end ----
  481. ctor:function () {
  482. cc.Node.prototype.ctor.call(this);
  483. this._buffer = [];
  484. this._blendFunc = new cc.BlendFunc(cc.BLEND_SRC, cc.BLEND_DST);
  485. },
  486. init:function () {
  487. if (cc.Node.prototype.init.call(this)) {
  488. this.setShaderProgram(cc.ShaderCache.getInstance().programForKey(cc.SHADER_POSITION_LENGTHTEXTURECOLOR));
  489. this._ensureCapacity(512);
  490. this._trianglesWebBuffer = cc.renderContext.createBuffer();
  491. this._dirty = true;
  492. return true;
  493. }
  494. return false;
  495. },
  496. _render:function () {
  497. var gl = cc.renderContext;
  498. cc.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX);
  499. gl.bindBuffer(gl.ARRAY_BUFFER, this._trianglesWebBuffer);
  500. if (this._dirty) {
  501. gl.bufferData(gl.ARRAY_BUFFER, this._trianglesArrayBuffer, gl.STREAM_DRAW);
  502. this._dirty = false;
  503. }
  504. var triangleSize = cc.V2F_C4B_T2F.BYTES_PER_ELEMENT;
  505. // vertex
  506. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, triangleSize, 0);
  507. // color
  508. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.UNSIGNED_BYTE, true, triangleSize, 8);
  509. // texcood
  510. gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORDS, 2, gl.FLOAT, false, triangleSize, 12);
  511. gl.drawArrays(gl.TRIANGLES, 0, this._buffer.length * 3);
  512. cc.INCREMENT_GL_DRAWS(1);
  513. //cc.CHECK_GL_ERROR_DEBUG();
  514. },
  515. _ensureCapacity:function(count){
  516. if(this._buffer.length + count > this._bufferCapacity){
  517. var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT;
  518. this._bufferCapacity += Math.max(this._bufferCapacity, count);
  519. //re alloc
  520. if((this._buffer == null) || (this._buffer.length === 0)){
  521. //init
  522. this._buffer = [];
  523. this._trianglesArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity);
  524. this._trianglesReader = new Uint8Array(this._trianglesArrayBuffer);
  525. } else {
  526. var newTriangles = this._buffer;
  527. newTriangles.length = 0;
  528. var newArrayBuffer = new ArrayBuffer(TriangleLength * this._bufferCapacity);
  529. for(var i = 0; i < this._buffer.length;i++){
  530. newTriangles[i] = new cc.V2F_C4B_T2F_Triangle(this._buffer[i].a,this._buffer[i].b,this._buffer[i].c,
  531. newArrayBuffer,i * TriangleLength);
  532. }
  533. this._trianglesReader = new Uint8Array(newArrayBuffer);
  534. this._trianglesArrayBuffer = newArrayBuffer;
  535. }
  536. }
  537. },
  538. draw:function () {
  539. cc.glBlendFunc(this._blendFunc.src, this._blendFunc.dst);
  540. this._shaderProgram.use();
  541. this._shaderProgram.setUniformsForBuiltins();
  542. this._render();
  543. },
  544. /**
  545. * draw a dot at a position, with a given radius and color
  546. * @param {cc.Point} pos
  547. * @param {Number} radius
  548. * @param {cc.Color4F} color
  549. */
  550. drawDot:function (pos, radius, color) {
  551. var c4bColor = {r: 0 | (color.r * 255), g: 0 | (color.g * 255), b: 0 | (color.b * 255), a: 0 | (color.a * 255)};
  552. var a = {vertices: {x: pos.x - radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: -1.0, v: -1.0}};
  553. var b = {vertices: {x: pos.x - radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: -1.0, v: 1.0}};
  554. var c = {vertices: {x: pos.x + radius, y: pos.y + radius}, colors: c4bColor, texCoords: {u: 1.0, v: 1.0}};
  555. var d = {vertices: {x: pos.x + radius, y: pos.y - radius}, colors: c4bColor, texCoords: {u: 1.0, v: -1.0}};
  556. this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, b, c, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT));
  557. this._buffer.push(new cc.V2F_C4B_T2F_Triangle(a, c, d, this._trianglesArrayBuffer, this._buffer.length * cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT));
  558. this._dirty = true;
  559. },
  560. /**
  561. * draw a segment with a radius and color
  562. * @param {cc.Point} from
  563. * @param {cc.Point} to
  564. * @param {Number} radius
  565. * @param {cc.Color4F} color
  566. */
  567. drawSegment:function (from, to, radius, color) {
  568. var vertexCount = 6*3;
  569. this._ensureCapacity(vertexCount);
  570. var c4bColor = {r: 0 | (color.r * 255), g: 0 | (color.g * 255), b: 0 | (color.b * 255), a: 0 | (color.a * 255)};
  571. var a = cc.__v2f(from);
  572. var b = cc.__v2f(to);
  573. var n = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(b, a)));
  574. var t = cc.v2fperp(n);
  575. var nw = cc.v2fmult(n, radius);
  576. var tw = cc.v2fmult(t, radius);
  577. var v0 = cc.v2fsub(b, cc.v2fadd(nw, tw));
  578. var v1 = cc.v2fadd(b, cc.v2fsub(nw, tw));
  579. var v2 = cc.v2fsub(b, nw);
  580. var v3 = cc.v2fadd(b, nw);
  581. var v4 = cc.v2fsub(a, nw);
  582. var v5 = cc.v2fadd(a, nw);
  583. var v6 = cc.v2fsub(a, cc.v2fsub(nw, tw));
  584. var v7 = cc.v2fadd(a, cc.v2fadd(nw, tw));
  585. var TriangleLength = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, triangleBuffer = this._trianglesArrayBuffer;
  586. this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(cc.v2fadd(n, t)))},
  587. {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
  588. triangleBuffer, this._buffer.length * TriangleLength));
  589. this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
  590. {vertices: v1, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(n, t))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
  591. triangleBuffer, this._buffer.length * TriangleLength));
  592. this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
  593. {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v2, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))},
  594. triangleBuffer, this._buffer.length * TriangleLength));
  595. this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v3, colors: c4bColor, texCoords: cc.__t(n)},
  596. {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
  597. triangleBuffer, this._buffer.length * TriangleLength));
  598. this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))},
  599. {vertices: v4, colors: c4bColor, texCoords: cc.__t(cc.v2fneg(n))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
  600. triangleBuffer, this._buffer.length * TriangleLength));
  601. this._buffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v6, colors: c4bColor, texCoords: cc.__t(cc.v2fsub(t, n))},
  602. {vertices: v7, colors: c4bColor, texCoords: cc.__t(cc.v2fadd(n, t))}, {vertices: v5, colors: c4bColor, texCoords: cc.__t(n)},
  603. triangleBuffer, this._buffer.length * TriangleLength));
  604. this._dirty = true;
  605. },
  606. /**
  607. * draw a polygon with a fill color and line color
  608. * @param {Array} verts
  609. * @param {cc.Color4F} fillColor
  610. * @param {Number} borderWidth
  611. * @param {cc.Color4F} borderColor
  612. */
  613. drawPoly:function (verts, fillColor, borderWidth, borderColor) {
  614. var c4bFillColor = {r: 0 | (fillColor.r * 255), g: 0 | (fillColor.g * 255), b: 0 | (fillColor.b * 255), a: 0 | (fillColor.a * 255)};
  615. var c4bBorderColor = {r: 0 | (borderColor.r * 255), g: 0 | (borderColor.g * 255), b: 0 | (borderColor.b * 255), a: 0 | (borderColor.a * 255)};
  616. var extrude = [], i;
  617. var v0, v1, v2;
  618. var count = verts.length;
  619. for (i = 0; i < count; i++) {
  620. v0 = cc.__v2f(verts[(i - 1 + count) % count]);
  621. v1 = cc.__v2f(verts[i]);
  622. v2 = cc.__v2f(verts[(i + 1) % count]);
  623. var n1 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v1, v0)));
  624. var n2 = cc.v2fnormalize(cc.v2fperp(cc.v2fsub(v2, v1)));
  625. var offset = cc.v2fmult(cc.v2fadd(n1, n2), 1.0 / (cc.v2fdot(n1, n2) + 1.0));
  626. extrude[i] = {offset: offset, n: n2};
  627. }
  628. var outline = (borderWidth > 0.0);
  629. var triangleCount = 3 * count -2;
  630. var vertexCount = 3 * triangleCount;
  631. this._ensureCapacity(vertexCount);
  632. var triangleBytesLen = cc.V2F_C4B_T2F_Triangle.BYTES_PER_ELEMENT, trianglesBuffer = this._trianglesArrayBuffer;
  633. var locBuffer = this._buffer;
  634. var inset = (outline == false ? 0.5 : 0.0);
  635. for (i = 0; i < count - 2; i++) {
  636. v0 = cc.v2fsub(cc.__v2f(verts[0]), cc.v2fmult(extrude[0].offset, inset));
  637. v1 = cc.v2fsub(cc.__v2f(verts[i + 1]), cc.v2fmult(extrude[i + 1].offset, inset));
  638. v2 = cc.v2fsub(cc.__v2f(verts[i + 2]), cc.v2fmult(extrude[i + 2].offset, inset));
  639. locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: v0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
  640. {vertices: v1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: v2, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
  641. trianglesBuffer, locBuffer.length * triangleBytesLen));
  642. }
  643. for (i = 0; i < count; i++) {
  644. var j = (i + 1) % count;
  645. v0 = cc.__v2f(verts[i]);
  646. v1 = cc.__v2f(verts[j]);
  647. var n0 = extrude[i].n;
  648. var offset0 = extrude[i].offset;
  649. var offset1 = extrude[j].offset;
  650. var inner0 = outline ? cc.v2fsub(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fsub(v0, cc.v2fmult(offset0, 0.5));
  651. var inner1 = outline ? cc.v2fsub(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fsub(v1, cc.v2fmult(offset1, 0.5));
  652. var outer0 = outline ? cc.v2fadd(v0, cc.v2fmult(offset0, borderWidth)) : cc.v2fadd(v0, cc.v2fmult(offset0, 0.5));
  653. var outer1 = outline ? cc.v2fadd(v1, cc.v2fmult(offset1, borderWidth)) : cc.v2fadd(v1, cc.v2fmult(offset1, 0.5));
  654. if (outline) {
  655. locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
  656. {vertices: inner1, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
  657. trianglesBuffer, locBuffer.length * triangleBytesLen));
  658. locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bBorderColor, texCoords: cc.__t(cc.v2fneg(n0))},
  659. {vertices: outer0, colors: c4bBorderColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bBorderColor, texCoords: cc.__t(n0)},
  660. trianglesBuffer, locBuffer.length * triangleBytesLen));
  661. } else {
  662. locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
  663. {vertices: inner1, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)},
  664. trianglesBuffer, locBuffer.length * triangleBytesLen));
  665. locBuffer.push(new cc.V2F_C4B_T2F_Triangle({vertices: inner0, colors: c4bFillColor, texCoords: cc.__t(cc.v2fzero())},
  666. {vertices: outer0, colors: c4bFillColor, texCoords: cc.__t(n0)}, {vertices: outer1, colors: c4bFillColor, texCoords: cc.__t(n0)},
  667. trianglesBuffer, locBuffer.length * triangleBytesLen));
  668. }
  669. }
  670. extrude = null;
  671. this._dirty = true;
  672. },
  673. /**
  674. * Clear the geometry in the node's buffer.
  675. */
  676. clear:function () {
  677. this._buffer.length = 0;
  678. this._dirty = true;
  679. }
  680. });
  681. cc.DrawNode = cc.Browser.supportWebGL ? cc.DrawNodeWebGL : cc.DrawNodeCanvas;
  682. /**
  683. * Creates a DrawNode
  684. * @return {cc.DrawNode}
  685. */
  686. cc.DrawNode.create = function () {
  687. var ret = new cc.DrawNode();
  688. if (ret && ret.init())
  689. return ret;
  690. return null;
  691. };
  692. cc._DrawNodeElement = function (type, verts, fillColor, lineWidth, lineColor, lineCap, isClosePolygon, isFill, isStroke) {
  693. this.type = type;
  694. this.verts = verts || null;
  695. this.fillColor = fillColor || null;
  696. this.lineWidth = lineWidth || 0;
  697. this.lineColor = lineColor || null;
  698. this.lineCap = lineCap || "butt";
  699. this.isClosePolygon = isClosePolygon || false;
  700. this.isFill = isFill || false;
  701. this.isStroke = isStroke || false;
  702. };
  703. cc.DrawNode.TYPE_DOT = 0;
  704. cc.DrawNode.TYPE_SEGMENT = 1;
  705. cc.DrawNode.TYPE_POLY = 2;