babylon.ellipse2d.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. var __extends = (this && this.__extends) || function (d, b) {
  2. for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
  3. function __() { this.constructor = d; }
  4. d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
  5. };
  6. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  7. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  8. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  9. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  10. return c > 3 && r && Object.defineProperty(target, key, r), r;
  11. };
  12. var BABYLON;
  13. (function (BABYLON) {
  14. var Ellipse2DRenderCache = (function (_super) {
  15. __extends(Ellipse2DRenderCache, _super);
  16. function Ellipse2DRenderCache(engine, modelKey) {
  17. _super.call(this, engine, modelKey);
  18. this.effectsReady = false;
  19. this.fillVB = null;
  20. this.fillIB = null;
  21. this.fillIndicesCount = 0;
  22. this.instancingFillAttributes = null;
  23. this.effectFillInstanced = null;
  24. this.effectFill = null;
  25. this.borderVB = null;
  26. this.borderIB = null;
  27. this.borderIndicesCount = 0;
  28. this.instancingBorderAttributes = null;
  29. this.effectBorderInstanced = null;
  30. this.effectBorder = null;
  31. }
  32. Ellipse2DRenderCache.prototype.render = function (instanceInfo, context) {
  33. // Do nothing if the shader is still loading/preparing
  34. if (!this.effectsReady) {
  35. if ((this.effectFill && (!this.effectFill.isReady() || (this.effectFillInstanced && !this.effectFillInstanced.isReady()))) ||
  36. (this.effectBorder && (!this.effectBorder.isReady() || (this.effectBorderInstanced && !this.effectBorderInstanced.isReady())))) {
  37. return false;
  38. }
  39. this.effectsReady = true;
  40. }
  41. var canvas = instanceInfo.owner.owner;
  42. var engine = canvas.engine;
  43. var depthFunction = 0;
  44. if (this.effectFill && this.effectBorder) {
  45. depthFunction = engine.getDepthFunction();
  46. engine.setDepthFunctionToLessOrEqual();
  47. }
  48. var curAlphaMode = engine.getAlphaMode();
  49. if (this.effectFill) {
  50. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_FILLPARTID.toString());
  51. var pid = context.groupInfoPartData[partIndex];
  52. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  53. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
  54. }
  55. var effect = context.useInstancing ? this.effectFillInstanced : this.effectFill;
  56. engine.enableEffect(effect);
  57. engine.bindBuffersDirectly(this.fillVB, this.fillIB, [1], 4, effect);
  58. if (context.useInstancing) {
  59. if (!this.instancingFillAttributes) {
  60. this.instancingFillAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_FILLPARTID, effect);
  61. }
  62. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  63. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  64. canvas._addDrawCallCount(1, context.renderMode);
  65. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingFillAttributes);
  66. engine.draw(true, 0, this.fillIndicesCount, count);
  67. engine.unbindInstanceAttributes();
  68. }
  69. else {
  70. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  71. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  72. this.setupUniforms(effect, partIndex, pid._partData, i);
  73. engine.draw(true, 0, this.fillIndicesCount);
  74. }
  75. }
  76. }
  77. if (this.effectBorder) {
  78. var partIndex = instanceInfo.partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_BORDERPARTID.toString());
  79. var pid = context.groupInfoPartData[partIndex];
  80. if (context.renderMode !== BABYLON.Render2DContext.RenderModeOpaque) {
  81. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
  82. }
  83. var effect = context.useInstancing ? this.effectBorderInstanced : this.effectBorder;
  84. engine.enableEffect(effect);
  85. engine.bindBuffersDirectly(this.borderVB, this.borderIB, [1], 4, effect);
  86. if (context.useInstancing) {
  87. if (!this.instancingBorderAttributes) {
  88. this.instancingBorderAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, effect);
  89. }
  90. var glBuffer = context.instancedBuffers ? context.instancedBuffers[partIndex] : pid._partBuffer;
  91. var count = context.instancedBuffers ? context.instancesCount : pid._partData.usedElementCount;
  92. canvas._addDrawCallCount(1, context.renderMode);
  93. engine.updateAndBindInstancesBuffer(glBuffer, null, this.instancingBorderAttributes);
  94. engine.draw(true, 0, this.borderIndicesCount, count);
  95. engine.unbindInstanceAttributes();
  96. }
  97. else {
  98. canvas._addDrawCallCount(context.partDataEndIndex - context.partDataStartIndex, context.renderMode);
  99. for (var i = context.partDataStartIndex; i < context.partDataEndIndex; i++) {
  100. this.setupUniforms(effect, partIndex, pid._partData, i);
  101. engine.draw(true, 0, this.borderIndicesCount);
  102. }
  103. }
  104. }
  105. engine.setAlphaMode(curAlphaMode);
  106. if (this.effectFill && this.effectBorder) {
  107. engine.setDepthFunction(depthFunction);
  108. }
  109. return true;
  110. };
  111. Ellipse2DRenderCache.prototype.dispose = function () {
  112. if (!_super.prototype.dispose.call(this)) {
  113. return false;
  114. }
  115. if (this.fillVB) {
  116. this._engine._releaseBuffer(this.fillVB);
  117. this.fillVB = null;
  118. }
  119. if (this.fillIB) {
  120. this._engine._releaseBuffer(this.fillIB);
  121. this.fillIB = null;
  122. }
  123. if (this.effectFill) {
  124. this._engine._releaseEffect(this.effectFill);
  125. this.effectFill = null;
  126. }
  127. if (this.effectFillInstanced) {
  128. this._engine._releaseEffect(this.effectFillInstanced);
  129. this.effectFillInstanced = null;
  130. }
  131. if (this.borderVB) {
  132. this._engine._releaseBuffer(this.borderVB);
  133. this.borderVB = null;
  134. }
  135. if (this.borderIB) {
  136. this._engine._releaseBuffer(this.borderIB);
  137. this.borderIB = null;
  138. }
  139. if (this.effectBorder) {
  140. this._engine._releaseEffect(this.effectBorder);
  141. this.effectBorder = null;
  142. }
  143. if (this.effectBorderInstanced) {
  144. this._engine._releaseEffect(this.effectBorderInstanced);
  145. this.effectBorderInstanced = null;
  146. }
  147. return true;
  148. };
  149. return Ellipse2DRenderCache;
  150. }(BABYLON.ModelRenderCache));
  151. BABYLON.Ellipse2DRenderCache = Ellipse2DRenderCache;
  152. var Ellipse2DInstanceData = (function (_super) {
  153. __extends(Ellipse2DInstanceData, _super);
  154. function Ellipse2DInstanceData(partId) {
  155. _super.call(this, partId, 1);
  156. }
  157. Object.defineProperty(Ellipse2DInstanceData.prototype, "properties", {
  158. get: function () {
  159. return null;
  160. },
  161. enumerable: true,
  162. configurable: true
  163. });
  164. __decorate([
  165. BABYLON.instanceData()
  166. ], Ellipse2DInstanceData.prototype, "properties", null);
  167. return Ellipse2DInstanceData;
  168. }(BABYLON.Shape2DInstanceData));
  169. BABYLON.Ellipse2DInstanceData = Ellipse2DInstanceData;
  170. var Ellipse2D = (function (_super) {
  171. __extends(Ellipse2D, _super);
  172. /**
  173. * Create an Ellipse 2D Shape primitive
  174. * @param settings a combination of settings, possible ones are
  175. * - parent: the parent primitive/canvas, must be specified if the primitive is not constructed as a child of another one (i.e. as part of the children array setting)
  176. * - children: an array of direct children
  177. * - id: a text identifier, for information purpose
  178. * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
  179. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  180. * - scale: the initial scale of the primitive. default is 1
  181. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  182. * - origin: define the normalized origin point location, default [0.5;0.5]
  183. * - size: the size of the group. Alternatively the width and height properties can be set. Default will be [10;10].
  184. * - subdivision: the number of subdivision to create the ellipse perimeter, default is 64.
  185. * - fill: the brush used to draw the fill content of the ellipse, you can set null to draw nothing (but you will have to set a border brush), default is a SolidColorBrush of plain white. can also be a string value (see Canvas2D.GetBrushFromString)
  186. * - border: the brush used to draw the border of the ellipse, you can set null to draw nothing (but you will have to set a fill brush), default is null. can be a string value (see Canvas2D.GetBrushFromString)
  187. * - borderThickness: the thickness of the drawn border, default is 1.
  188. * - isVisible: true if the group must be visible, false for hidden. Default is true.
  189. * - childrenFlatZOrder: if true all the children (direct and indirect) will share the same Z-Order. Use this when there's a lot of children which don't overlap. The drawing order IS NOT GUARANTED!
  190. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  191. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  192. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  193. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  194. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  195. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  196. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  197. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  198. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  199. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  200. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  201. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  202. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  203. */
  204. function Ellipse2D(settings) {
  205. // Avoid checking every time if the object exists
  206. if (settings == null) {
  207. settings = {};
  208. }
  209. _super.call(this, settings);
  210. if (settings.size != null) {
  211. this.size = settings.size;
  212. }
  213. else if (settings.width || settings.height) {
  214. var size = new BABYLON.Size(settings.width, settings.height);
  215. this.size = size;
  216. }
  217. var sub = (settings.subdivisions == null) ? 64 : settings.subdivisions;
  218. this.subdivisions = sub;
  219. }
  220. Object.defineProperty(Ellipse2D.prototype, "actualSize", {
  221. get: function () {
  222. if (this._actualSize) {
  223. return this._actualSize;
  224. }
  225. return this.size;
  226. },
  227. set: function (value) {
  228. this._actualSize = value;
  229. },
  230. enumerable: true,
  231. configurable: true
  232. });
  233. Object.defineProperty(Ellipse2D.prototype, "subdivisions", {
  234. get: function () {
  235. return this._subdivisions;
  236. },
  237. set: function (value) {
  238. this._subdivisions = value;
  239. },
  240. enumerable: true,
  241. configurable: true
  242. });
  243. Ellipse2D.prototype.levelIntersect = function (intersectInfo) {
  244. var w = this.size.width / 2;
  245. var h = this.size.height / 2;
  246. var x = intersectInfo._localPickPosition.x - w;
  247. var y = intersectInfo._localPickPosition.y - h;
  248. return ((x * x) / (w * w) + (y * y) / (h * h)) <= 1;
  249. };
  250. Ellipse2D.prototype.updateLevelBoundingInfo = function () {
  251. BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.actualSize, this._levelBoundingInfo);
  252. };
  253. Ellipse2D.prototype.createModelRenderCache = function (modelKey) {
  254. var renderCache = new Ellipse2DRenderCache(this.owner.engine, modelKey);
  255. return renderCache;
  256. };
  257. Ellipse2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  258. var renderCache = modelRenderCache;
  259. var engine = this.owner.engine;
  260. // Need to create WebGL resources for fill part?
  261. if (this.fill) {
  262. var vbSize = this.subdivisions + 1;
  263. var vb = new Float32Array(vbSize);
  264. for (var i = 0; i < vbSize; i++) {
  265. vb[i] = i;
  266. }
  267. renderCache.fillVB = engine.createVertexBuffer(vb);
  268. var triCount = vbSize - 1;
  269. var ib = new Float32Array(triCount * 3);
  270. for (var i = 0; i < triCount; i++) {
  271. ib[i * 3 + 0] = 0;
  272. ib[i * 3 + 2] = i + 1;
  273. ib[i * 3 + 1] = i + 2;
  274. }
  275. ib[triCount * 3 - 2] = 1;
  276. renderCache.fillIB = engine.createIndexBuffer(ib);
  277. renderCache.fillIndicesCount = triCount * 3;
  278. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  279. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], true);
  280. if (ei) {
  281. renderCache.effectFillInstanced = engine.createEffect({ vertex: "ellipse2d", fragment: "ellipse2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  282. }
  283. // Get the non instanced version
  284. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], false);
  285. renderCache.effectFill = engine.createEffect({ vertex: "ellipse2d", fragment: "ellipse2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  286. }
  287. // Need to create WebGL resource for border part?
  288. if (this.border) {
  289. var vbSize = this.subdivisions * 2;
  290. var vb = new Float32Array(vbSize);
  291. for (var i = 0; i < vbSize; i++) {
  292. vb[i] = i;
  293. }
  294. renderCache.borderVB = engine.createVertexBuffer(vb);
  295. var triCount = vbSize;
  296. var rs = triCount / 2;
  297. var ib = new Float32Array(triCount * 3);
  298. for (var i = 0; i < rs; i++) {
  299. var r0 = i;
  300. var r1 = (i + 1) % rs;
  301. ib[i * 6 + 0] = rs + r1;
  302. ib[i * 6 + 1] = rs + r0;
  303. ib[i * 6 + 2] = r0;
  304. ib[i * 6 + 3] = r1;
  305. ib[i * 6 + 4] = rs + r1;
  306. ib[i * 6 + 5] = r0;
  307. }
  308. renderCache.borderIB = engine.createIndexBuffer(ib);
  309. renderCache.borderIndicesCount = (triCount * 3);
  310. // Get the instanced version of the effect, if the engine does not support it, null is return and we'll only draw on by one
  311. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], true);
  312. if (ei) {
  313. renderCache.effectBorderInstanced = engine.createEffect("ellipse2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  314. }
  315. // Get the non instanced version
  316. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], false);
  317. renderCache.effectBorder = engine.createEffect("ellipse2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  318. }
  319. return renderCache;
  320. };
  321. Ellipse2D.prototype.createInstanceDataParts = function () {
  322. var res = new Array();
  323. if (this.border) {
  324. res.push(new Ellipse2DInstanceData(BABYLON.Shape2D.SHAPE2D_BORDERPARTID));
  325. }
  326. if (this.fill) {
  327. res.push(new Ellipse2DInstanceData(BABYLON.Shape2D.SHAPE2D_FILLPARTID));
  328. }
  329. return res;
  330. };
  331. Ellipse2D.prototype.refreshInstanceDataPart = function (part) {
  332. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  333. return false;
  334. }
  335. if (part.id === BABYLON.Shape2D.SHAPE2D_BORDERPARTID) {
  336. var d = part;
  337. var size = this.actualSize;
  338. d.properties = new BABYLON.Vector3(size.width, size.height, this.subdivisions);
  339. }
  340. else if (part.id === BABYLON.Shape2D.SHAPE2D_FILLPARTID) {
  341. var d = part;
  342. var size = this.actualSize;
  343. d.properties = new BABYLON.Vector3(size.width, size.height, this.subdivisions);
  344. }
  345. return true;
  346. };
  347. __decorate([
  348. BABYLON.instanceLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 1, function (pi) { return Ellipse2D.acutalSizeProperty = pi; }, false, true)
  349. ], Ellipse2D.prototype, "actualSize", null);
  350. __decorate([
  351. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 2, function (pi) { return Ellipse2D.subdivisionsProperty = pi; })
  352. ], Ellipse2D.prototype, "subdivisions", null);
  353. Ellipse2D = __decorate([
  354. BABYLON.className("Ellipse2D")
  355. ], Ellipse2D);
  356. return Ellipse2D;
  357. }(BABYLON.Shape2D));
  358. BABYLON.Ellipse2D = Ellipse2D;
  359. })(BABYLON || (BABYLON = {}));