babylon.rectangle2d.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  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 Rectangle2DRenderCache = (function (_super) {
  15. __extends(Rectangle2DRenderCache, _super);
  16. function Rectangle2DRenderCache(engine, modelKey, isTransparent) {
  17. _super.call(this, engine, modelKey, isTransparent);
  18. }
  19. Rectangle2DRenderCache.prototype.render = function (instanceInfo, context) {
  20. // Do nothing if the shader is still loading/preparing
  21. if ((this.effectFill && !this.effectFill.isReady()) || (this.effectBorder && !this.effectBorder.isReady())) {
  22. return false;
  23. }
  24. var engine = instanceInfo._owner.owner.engine;
  25. var depthFunction = 0;
  26. if (this.effectFill && this.effectBorder) {
  27. depthFunction = engine.getDepthFunction();
  28. engine.setDepthFunctionToLessOrEqual();
  29. }
  30. var cur;
  31. if (this.isTransparent) {
  32. cur = engine.getAlphaMode();
  33. engine.setAlphaMode(BABYLON.Engine.ALPHA_COMBINE);
  34. }
  35. if (this.effectFill) {
  36. var partIndex = instanceInfo._partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_FILLPARTID.toString());
  37. engine.enableEffect(this.effectFill);
  38. engine.bindBuffers(this.fillVB, this.fillIB, [1], 4, this.effectFill);
  39. var count = instanceInfo._instancesPartsData[partIndex].usedElementCount;
  40. if (instanceInfo._owner.owner.supportInstancedArray) {
  41. if (!this.instancingFillAttributes) {
  42. // Compute the offset locations of the attributes in the vertex shader that will be mapped to the instance buffer data
  43. this.instancingFillAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_FILLPARTID, this.effectFill);
  44. }
  45. engine.updateAndBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], null, this.instancingFillAttributes);
  46. engine.draw(true, 0, this.fillIndicesCount, count);
  47. engine.unBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], this.instancingFillAttributes);
  48. }
  49. else {
  50. for (var i = 0; i < count; i++) {
  51. this.setupUniforms(this.effectFill, partIndex, instanceInfo._instancesPartsData[partIndex], i);
  52. engine.draw(true, 0, this.fillIndicesCount);
  53. }
  54. }
  55. }
  56. if (this.effectBorder) {
  57. var partIndex = instanceInfo._partIndexFromId.get(BABYLON.Shape2D.SHAPE2D_BORDERPARTID.toString());
  58. engine.enableEffect(this.effectBorder);
  59. engine.bindBuffers(this.borderVB, this.borderIB, [1], 4, this.effectBorder);
  60. var count = instanceInfo._instancesPartsData[partIndex].usedElementCount;
  61. if (instanceInfo._owner.owner.supportInstancedArray) {
  62. if (!this.instancingBorderAttributes) {
  63. this.instancingBorderAttributes = this.loadInstancingAttributes(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, this.effectBorder);
  64. }
  65. engine.updateAndBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], null, this.instancingBorderAttributes);
  66. engine.draw(true, 0, this.borderIndicesCount, count);
  67. engine.unBindInstancesBuffer(instanceInfo._instancesPartsBuffer[partIndex], this.instancingBorderAttributes);
  68. }
  69. else {
  70. for (var i = 0; i < count; i++) {
  71. this.setupUniforms(this.effectBorder, partIndex, instanceInfo._instancesPartsData[partIndex], i);
  72. engine.draw(true, 0, this.borderIndicesCount);
  73. }
  74. }
  75. }
  76. if (this.isTransparent) {
  77. engine.setAlphaMode(cur);
  78. }
  79. if (this.effectFill && this.effectBorder) {
  80. engine.setDepthFunction(depthFunction);
  81. }
  82. return true;
  83. };
  84. Rectangle2DRenderCache.prototype.dispose = function () {
  85. if (!_super.prototype.dispose.call(this)) {
  86. return false;
  87. }
  88. if (this.fillVB) {
  89. this._engine._releaseBuffer(this.fillVB);
  90. this.fillVB = null;
  91. }
  92. if (this.fillIB) {
  93. this._engine._releaseBuffer(this.fillIB);
  94. this.fillIB = null;
  95. }
  96. if (this.effectFill) {
  97. this._engine._releaseEffect(this.effectFill);
  98. this.effectFill = null;
  99. }
  100. if (this.borderVB) {
  101. this._engine._releaseBuffer(this.borderVB);
  102. this.borderVB = null;
  103. }
  104. if (this.borderIB) {
  105. this._engine._releaseBuffer(this.borderIB);
  106. this.borderIB = null;
  107. }
  108. if (this.effectBorder) {
  109. this._engine._releaseEffect(this.effectBorder);
  110. this.effectBorder = null;
  111. }
  112. return true;
  113. };
  114. return Rectangle2DRenderCache;
  115. })(BABYLON.ModelRenderCache);
  116. BABYLON.Rectangle2DRenderCache = Rectangle2DRenderCache;
  117. var Rectangle2DInstanceData = (function (_super) {
  118. __extends(Rectangle2DInstanceData, _super);
  119. function Rectangle2DInstanceData(partId) {
  120. _super.call(this, partId, 1);
  121. }
  122. Object.defineProperty(Rectangle2DInstanceData.prototype, "properties", {
  123. get: function () {
  124. return null;
  125. },
  126. enumerable: true,
  127. configurable: true
  128. });
  129. __decorate([
  130. BABYLON.instanceData()
  131. ], Rectangle2DInstanceData.prototype, "properties", null);
  132. return Rectangle2DInstanceData;
  133. })(BABYLON.Shape2DInstanceData);
  134. BABYLON.Rectangle2DInstanceData = Rectangle2DInstanceData;
  135. var Rectangle2D = (function (_super) {
  136. __extends(Rectangle2D, _super);
  137. function Rectangle2D() {
  138. _super.apply(this, arguments);
  139. }
  140. Object.defineProperty(Rectangle2D.prototype, "actualSize", {
  141. get: function () {
  142. return this.size;
  143. },
  144. enumerable: true,
  145. configurable: true
  146. });
  147. Object.defineProperty(Rectangle2D.prototype, "size", {
  148. get: function () {
  149. return this._size;
  150. },
  151. set: function (value) {
  152. this._size = value;
  153. },
  154. enumerable: true,
  155. configurable: true
  156. });
  157. Object.defineProperty(Rectangle2D.prototype, "notRounded", {
  158. get: function () {
  159. return this._notRounded;
  160. },
  161. set: function (value) {
  162. this._notRounded = value;
  163. },
  164. enumerable: true,
  165. configurable: true
  166. });
  167. Object.defineProperty(Rectangle2D.prototype, "roundRadius", {
  168. get: function () {
  169. return this._roundRadius;
  170. },
  171. set: function (value) {
  172. this._roundRadius = value;
  173. this.notRounded = value === 0;
  174. },
  175. enumerable: true,
  176. configurable: true
  177. });
  178. Rectangle2D.prototype.levelIntersect = function (intersectInfo) {
  179. // If we got there it mean the boundingInfo intersection succeed, if the rectangle has not roundRadius, it means it succeed!
  180. if (this.notRounded) {
  181. return true;
  182. }
  183. // Well, for now we neglect the area where the pickPosition could be outside due to the roundRadius...
  184. // TODO make REAL intersection test here!
  185. return true;
  186. };
  187. Rectangle2D.prototype.updateLevelBoundingInfo = function () {
  188. BABYLON.BoundingInfo2D.CreateFromSizeToRef(this.size, this._levelBoundingInfo, this.origin);
  189. };
  190. Rectangle2D.prototype.setupRectangle2D = function (owner, parent, id, position, origin, size, roundRadius, fill, border, borderThickness) {
  191. if (roundRadius === void 0) { roundRadius = 0; }
  192. if (borderThickness === void 0) { borderThickness = 1; }
  193. this.setupShape2D(owner, parent, id, position, origin, true, fill, border, borderThickness);
  194. this.size = size;
  195. this.notRounded = !roundRadius;
  196. this.roundRadius = roundRadius;
  197. };
  198. /**
  199. * Create an Rectangle 2D Shape primitive. May be a sharp rectangle (with sharp corners), or a rounded one.
  200. * @param parent the parent primitive, must be a valid primitive (or the Canvas)
  201. * options:
  202. * - id a text identifier, for information purpose
  203. * - x: the X position relative to its parent, default is 0
  204. * - y: the Y position relative to its parent, default is 0
  205. * - origin: define the normalized origin point location, default [0.5;0.5]
  206. * - width: the width of the rectangle, default is 10
  207. * - height: the height of the rectangle, default is 10
  208. * - roundRadius: if the rectangle has rounded corner, set their radius, default is 0 (to get a sharp rectangle).
  209. * - 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.
  210. * - 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.
  211. * - borderThickness: the thickness of the drawn border, default is 1.
  212. */
  213. Rectangle2D.Create = function (parent, options) {
  214. BABYLON.Prim2DBase.CheckParent(parent);
  215. var rect = new Rectangle2D();
  216. rect.setupRectangle2D(parent.owner, parent, options && options.id || null, new BABYLON.Vector2(options && options.x || 0, options && options.y || 0), options && options.origin || null, new BABYLON.Size(options && options.width || 10, options && options.height || 10), options && options.roundRadius || 0);
  217. if (options && options.fill !== undefined) {
  218. rect.fill = options.fill;
  219. }
  220. else {
  221. rect.fill = BABYLON.Canvas2D.GetSolidColorBrushFromHex("#FFFFFFFF");
  222. }
  223. rect.border = options && options.border || null;
  224. rect.borderThickness = options && options.borderThickness || 1;
  225. return rect;
  226. };
  227. Rectangle2D.prototype.createModelRenderCache = function (modelKey, isTransparent) {
  228. var renderCache = new Rectangle2DRenderCache(this.owner.engine, modelKey, isTransparent);
  229. return renderCache;
  230. };
  231. Rectangle2D.prototype.setupModelRenderCache = function (modelRenderCache) {
  232. var renderCache = modelRenderCache;
  233. var engine = this.owner.engine;
  234. // Need to create WebGL resources for fill part?
  235. if (this.fill) {
  236. var vbSize = ((this.notRounded ? 1 : Rectangle2D.roundSubdivisions) * 4) + 1;
  237. var vb = new Float32Array(vbSize);
  238. for (var i = 0; i < vbSize; i++) {
  239. vb[i] = i;
  240. }
  241. renderCache.fillVB = engine.createVertexBuffer(vb);
  242. var triCount = vbSize - 1;
  243. var ib = new Float32Array(triCount * 3);
  244. for (var i = 0; i < triCount; i++) {
  245. ib[i * 3 + 0] = 0;
  246. ib[i * 3 + 2] = i + 1;
  247. ib[i * 3 + 1] = i + 2;
  248. }
  249. ib[triCount * 3 - 2] = 1;
  250. renderCache.fillIB = engine.createIndexBuffer(ib);
  251. renderCache.fillIndicesCount = triCount * 3;
  252. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_FILLPARTID, ["index"]);
  253. renderCache.effectFill = engine.createEffect({ vertex: "rect2d", fragment: "rect2d" }, ei.attributes, ei.uniforms, [], ei.defines, null, function (e) {
  254. // renderCache.setupUniformsLocation(e, ei.uniforms, Shape2D.SHAPE2D_FILLPARTID);
  255. });
  256. }
  257. // Need to create WebGL resource for border part?
  258. if (this.border) {
  259. var vbSize = (this.notRounded ? 1 : Rectangle2D.roundSubdivisions) * 4 * 2;
  260. var vb = new Float32Array(vbSize);
  261. for (var i = 0; i < vbSize; i++) {
  262. vb[i] = i;
  263. }
  264. renderCache.borderVB = engine.createVertexBuffer(vb);
  265. var triCount = vbSize;
  266. var rs = triCount / 2;
  267. var ib = new Float32Array(triCount * 3);
  268. for (var i = 0; i < rs; i++) {
  269. var r0 = i;
  270. var r1 = (i + 1) % rs;
  271. ib[i * 6 + 0] = rs + r1;
  272. ib[i * 6 + 1] = rs + r0;
  273. ib[i * 6 + 2] = r0;
  274. ib[i * 6 + 3] = r1;
  275. ib[i * 6 + 4] = rs + r1;
  276. ib[i * 6 + 5] = r0;
  277. }
  278. renderCache.borderIB = engine.createIndexBuffer(ib);
  279. renderCache.borderIndicesCount = triCount * 3;
  280. var ei = this.getDataPartEffectInfo(BABYLON.Shape2D.SHAPE2D_BORDERPARTID, ["index"]);
  281. renderCache.effectBorder = engine.createEffect({ vertex: "rect2d", fragment: "rect2d" }, ei.attributes, ei.uniforms, [], ei.defines, null, function (e) {
  282. // renderCache.setupUniformsLocation(e, ei.uniforms, Shape2D.SHAPE2D_BORDERPARTID);
  283. });
  284. }
  285. return renderCache;
  286. };
  287. Rectangle2D.prototype.createInstanceDataParts = function () {
  288. var res = new Array();
  289. if (this.border) {
  290. res.push(new Rectangle2DInstanceData(BABYLON.Shape2D.SHAPE2D_BORDERPARTID));
  291. }
  292. if (this.fill) {
  293. res.push(new Rectangle2DInstanceData(BABYLON.Shape2D.SHAPE2D_FILLPARTID));
  294. }
  295. return res;
  296. };
  297. Rectangle2D.prototype.refreshInstanceDataPart = function (part) {
  298. if (!_super.prototype.refreshInstanceDataPart.call(this, part)) {
  299. return false;
  300. }
  301. if (part.id === BABYLON.Shape2D.SHAPE2D_BORDERPARTID) {
  302. var d = part;
  303. var size = this.size;
  304. d.properties = new BABYLON.Vector3(size.width, size.height, this.roundRadius || 0);
  305. }
  306. else if (part.id === BABYLON.Shape2D.SHAPE2D_FILLPARTID) {
  307. var d = part;
  308. var size = this.size;
  309. d.properties = new BABYLON.Vector3(size.width, size.height, this.roundRadius || 0);
  310. }
  311. return true;
  312. };
  313. Rectangle2D.roundSubdivisions = 16;
  314. __decorate([
  315. BABYLON.instanceLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 1, function (pi) { return Rectangle2D.sizeProperty = pi; }, false, true)
  316. ], Rectangle2D.prototype, "size", null);
  317. __decorate([
  318. BABYLON.modelLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 2, function (pi) { return Rectangle2D.notRoundedProperty = pi; })
  319. ], Rectangle2D.prototype, "notRounded", null);
  320. __decorate([
  321. BABYLON.instanceLevelProperty(BABYLON.Shape2D.SHAPE2D_PROPCOUNT + 3, function (pi) { return Rectangle2D.roundRadiusProperty = pi; })
  322. ], Rectangle2D.prototype, "roundRadius", null);
  323. Rectangle2D = __decorate([
  324. BABYLON.className("Rectangle2D")
  325. ], Rectangle2D);
  326. return Rectangle2D;
  327. })(BABYLON.Shape2D);
  328. BABYLON.Rectangle2D = Rectangle2D;
  329. })(BABYLON || (BABYLON = {}));