babylon.ellipse2d.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355
  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, true);
  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, true);
  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, true);
  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. this.effectFill = null;
  124. this.effectFillInstanced = null;
  125. this.effectBorder = null;
  126. this.effectBorderInstanced = null;
  127. if (this.borderVB) {
  128. this._engine._releaseBuffer(this.borderVB);
  129. this.borderVB = null;
  130. }
  131. if (this.borderIB) {
  132. this._engine._releaseBuffer(this.borderIB);
  133. this.borderIB = null;
  134. }
  135. return true;
  136. };
  137. return Ellipse2DRenderCache;
  138. }(BABYLON.ModelRenderCache));
  139. BABYLON.Ellipse2DRenderCache = Ellipse2DRenderCache;
  140. var Ellipse2DInstanceData = (function (_super) {
  141. __extends(Ellipse2DInstanceData, _super);
  142. function Ellipse2DInstanceData(partId) {
  143. _super.call(this, partId, 1);
  144. }
  145. Object.defineProperty(Ellipse2DInstanceData.prototype, "properties", {
  146. get: function () {
  147. return null;
  148. },
  149. set: function (value) {
  150. },
  151. enumerable: true,
  152. configurable: true
  153. });
  154. __decorate([
  155. BABYLON.instanceData()
  156. ], Ellipse2DInstanceData.prototype, "properties", null);
  157. return Ellipse2DInstanceData;
  158. }(BABYLON.Shape2DInstanceData));
  159. BABYLON.Ellipse2DInstanceData = Ellipse2DInstanceData;
  160. var Ellipse2D = (function (_super) {
  161. __extends(Ellipse2D, _super);
  162. /**
  163. * Create an Ellipse 2D Shape primitive
  164. * @param settings a combination of settings, possible ones are
  165. * - 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)
  166. * - children: an array of direct children
  167. * - id: a text identifier, for information purpose
  168. * - position: the X & Y positions relative to its parent. Alternatively the x and y properties can be set. Default is [0;0]
  169. * - rotation: the initial rotation (in radian) of the primitive. default is 0
  170. * - scale: the initial scale of the primitive. default is 1. You can alternatively use scaleX &| scaleY to apply non uniform scale
  171. * - dontInheritParentScale: if set the parent's scale won't be taken into consideration to compute the actualScale property
  172. * - opacity: set the overall opacity of the primitive, 1 to be opaque (default), less than 1 to be transparent.
  173. * - zOrder: override the zOrder with the specified value
  174. * - origin: define the normalized origin point location, default [0.5;0.5]
  175. * - size: the size of the group. Alternatively the width and height properties can be set. Default will be [10;10].
  176. * - subdivision: the number of subdivision to create the ellipse perimeter, default is 64.
  177. * - 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)
  178. * - 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)
  179. * - borderThickness: the thickness of the drawn border, default is 1.
  180. * - isVisible: true if the group must be visible, false for hidden. Default is true.
  181. * - isPickable: if true the Primitive can be used with interaction mode and will issue Pointer Event. If false it will be ignored for interaction/intersection test. Default value is true.
  182. * - isContainer: if true the Primitive acts as a container for interaction, if the primitive is not pickable or doesn't intersection, no further test will be perform on its children. If set to false, children will always be considered for intersection/interaction. Default value is true.
  183. * - 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!
  184. * - marginTop: top margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  185. * - marginLeft: left margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  186. * - marginRight: right margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  187. * - marginBottom: bottom margin, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  188. * - margin: top, left, right and bottom margin formatted as a single string (see PrimitiveThickness.fromString)
  189. * - marginHAlignment: one value of the PrimitiveAlignment type's static properties
  190. * - marginVAlignment: one value of the PrimitiveAlignment type's static properties
  191. * - marginAlignment: a string defining the alignment, see PrimitiveAlignment.fromString
  192. * - paddingTop: top padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  193. * - paddingLeft: left padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  194. * - paddingRight: right padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  195. * - paddingBottom: bottom padding, can be a number (will be pixels) or a string (see PrimitiveThickness.fromString)
  196. * - padding: top, left, right and bottom padding formatted as a single string (see PrimitiveThickness.fromString)
  197. */
  198. function Ellipse2D(settings) {
  199. // Avoid checking every time if the object exists
  200. if (settings == null) {
  201. settings = {};
  202. }
  203. _super.call(this, settings);
  204. if (settings.size != null) {
  205. this.size = settings.size;
  206. }
  207. else if (settings.width || settings.height) {
  208. var size = new BABYLON.Size(settings.width, settings.height);
  209. this.size = size;
  210. }
  211. var sub = (settings.subdivisions == null) ? 64 : settings.subdivisions;
  212. this.subdivisions = sub;
  213. }
  214. Object.defineProperty(Ellipse2D.prototype, "actualSize", {
  215. get: function () {
  216. if (this._actualSize) {
  217. return this._actualSize;
  218. }
  219. return this.size;
  220. },
  221. set: function (value) {
  222. this._actualSize = value;
  223. },
  224. enumerable: true,
  225. configurable: true
  226. });
  227. Object.defineProperty(Ellipse2D.prototype, "subdivisions", {
  228. get: function () {
  229. return this._subdivisions;
  230. },
  231. set: function (value) {
  232. this._subdivisions = value;
  233. },
  234. enumerable: true,
  235. configurable: true
  236. });
  237. Ellipse2D.prototype.levelIntersect = function (intersectInfo) {
  238. var w = this.size.width / 2;
  239. var h = this.size.height / 2;
  240. var x = intersectInfo._localPickPosition.x - w;
  241. var y = intersectInfo._localPickPosition.y - h;
  242. return ((x * x) / (w * w) + (y * y) / (h * h)) <= 1;
  243. };
  244. Ellipse2D.prototype.updateLevelBoundingInfo = function () {
  245. BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.actualSize, this._levelBoundingInfo);
  246. };
  247. Ellipse2D.prototype.createModelRenderCache = function (modelKey) {
  248. var renderCache = new Ellipse2DRenderCache(this.owner.engine, modelKey);
  249. return renderCache;
  250. };
  251. Ellipse2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  252. var renderCache = modelRenderCache;
  253. var engine = this.owner.engine;
  254. // Need to create WebGL resources for fill part?
  255. if (this.fill) {
  256. var vbSize = this.subdivisions + 1;
  257. var vb = new Float32Array(vbSize);
  258. for (var i = 0; i < vbSize; i++) {
  259. vb[i] = i;
  260. }
  261. renderCache.fillVB = engine.createVertexBuffer(vb);
  262. var triCount = vbSize - 1;
  263. var ib = new Float32Array(triCount * 3);
  264. for (var i = 0; i < triCount; i++) {
  265. ib[i * 3 + 0] = 0;
  266. ib[i * 3 + 2] = i + 1;
  267. ib[i * 3 + 1] = i + 2;
  268. }
  269. ib[triCount * 3 - 2] = 1;
  270. renderCache.fillIB = engine.createIndexBuffer(ib);
  271. renderCache.fillIndicesCount = triCount * 3;
  272. // 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
  273. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], null, true);
  274. if (ei) {
  275. renderCache.effectFillInstanced = engine.createEffect({ vertex: "ellipse2d", fragment: "ellipse2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  276. }
  277. // Get the non instanced version
  278. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"], null, false);
  279. renderCache.effectFill = engine.createEffect({ vertex: "ellipse2d", fragment: "ellipse2d" }, ei.attributes, ei.uniforms, [], ei.defines, null);
  280. }
  281. // Need to create WebGL resource for border part?
  282. if (this.border) {
  283. var vbSize = this.subdivisions * 2;
  284. var vb = new Float32Array(vbSize);
  285. for (var i = 0; i < vbSize; i++) {
  286. vb[i] = i;
  287. }
  288. renderCache.borderVB = engine.createVertexBuffer(vb);
  289. var triCount = vbSize;
  290. var rs = triCount / 2;
  291. var ib = new Float32Array(triCount * 3);
  292. for (var i = 0; i < rs; i++) {
  293. var r0 = i;
  294. var r1 = (i + 1) % rs;
  295. ib[i * 6 + 0] = rs + r1;
  296. ib[i * 6 + 1] = rs + r0;
  297. ib[i * 6 + 2] = r0;
  298. ib[i * 6 + 3] = r1;
  299. ib[i * 6 + 4] = rs + r1;
  300. ib[i * 6 + 5] = r0;
  301. }
  302. renderCache.borderIB = engine.createIndexBuffer(ib);
  303. renderCache.borderIndicesCount = (triCount * 3);
  304. // 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
  305. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], null, true);
  306. if (ei) {
  307. renderCache.effectBorderInstanced = engine.createEffect("ellipse2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  308. }
  309. // Get the non instanced version
  310. ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"], null, false);
  311. renderCache.effectBorder = engine.createEffect("ellipse2d", ei.attributes, ei.uniforms, [], ei.defines, null);
  312. }
  313. return renderCache;
  314. };
  315. Ellipse2D.prototype.createInstanceDataParts = function () {
  316. var res = new Array();
  317. if (this.border) {
  318. res.push(new Ellipse2DInstanceData(BABYLON.Shape2D.SHAPE2D_BORDERPARTID));
  319. }
  320. if (this.fill) {
  321. res.push(new Ellipse2DInstanceData(BABYLON.Shape2D.SHAPE2D_FILLPARTID));
  322. }
  323. return res;
  324. };
  325. Ellipse2D.prototype.refreshInstanceDataPart = function (part) {
  326. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  327. return false;
  328. }
  329. if (part.id === BABYLON.Shape2D.SHAPE2D_BORDERPARTID) {
  330. var d = part;
  331. var size = this.actualSize;
  332. var s = this.actualScale;
  333. d.properties = new BABYLON.Vector3(size.width * s.x, size.height * s.y, this.subdivisions);
  334. }
  335. else if (part.id === BABYLON.Shape2D.SHAPE2D_FILLPARTID) {
  336. var d = part;
  337. var size = this.actualSize;
  338. var s = this.actualScale;
  339. d.properties = new BABYLON.Vector3(size.width * s.x, size.height * s.y, this.subdivisions);
  340. }
  341. return true;
  342. };
  343. __decorate([
  344. BABYLON.instanceLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 1, function (pi) { return Ellipse2D.acutalSizeProperty = pi; }, false, true)
  345. ], Ellipse2D.prototype, "actualSize", null);
  346. __decorate([
  347. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 2, function (pi) { return Ellipse2D.subdivisionsProperty = pi; })
  348. ], Ellipse2D.prototype, "subdivisions", null);
  349. Ellipse2D = __decorate([
  350. BABYLON.className("Ellipse2D")
  351. ], Ellipse2D);
  352. return Ellipse2D;
  353. }(BABYLON.Shape2D));
  354. BABYLON.Ellipse2D = Ellipse2D;
  355. })(BABYLON || (BABYLON = {}));