Advertisement
Guest User

game

a guest
Jan 14th, 2019
692
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 493.58 KB | None | 0 0
  1. // Generated by Construct 2, the HTML5 game and app creator :: http://www.scirra.com
  2. var cr = {};
  3. cr.plugins_ = {};
  4. cr.behaviors = {};
  5. if (typeof Object.getPrototypeOf !== "function")
  6. {
  7. if (typeof "test".__proto__ === "object")
  8. {
  9. Object.getPrototypeOf = function(object) {
  10. return object.__proto__;
  11. };
  12. }
  13. else
  14. {
  15. Object.getPrototypeOf = function(object) {
  16. return object.constructor.prototype;
  17. };
  18. }
  19. }
  20. (function(){
  21. cr.logexport = function (msg)
  22. {
  23. if (window.console && window.console.log)
  24. window.console.log(msg);
  25. };
  26. cr.logerror = function (msg)
  27. {
  28. if (window.console && window.console.error)
  29. window.console.error(msg);
  30. };
  31. cr.seal = function(x)
  32. {
  33. return x;
  34. };
  35. cr.freeze = function(x)
  36. {
  37. return x;
  38. };
  39. cr.is_undefined = function (x)
  40. {
  41. return typeof x === "undefined";
  42. };
  43. cr.is_number = function (x)
  44. {
  45. return typeof x === "number";
  46. };
  47. cr.is_string = function (x)
  48. {
  49. return typeof x === "string";
  50. };
  51. cr.isPOT = function (x)
  52. {
  53. return x > 0 && ((x - 1) & x) === 0;
  54. };
  55. cr.nextHighestPowerOfTwo = function(x) {
  56. --x;
  57. for (var i = 1; i < 32; i <<= 1) {
  58. x = x | x >> i;
  59. }
  60. return x + 1;
  61. }
  62. cr.abs = function (x)
  63. {
  64. return (x < 0 ? -x : x);
  65. };
  66. cr.max = function (a, b)
  67. {
  68. return (a > b ? a : b);
  69. };
  70. cr.min = function (a, b)
  71. {
  72. return (a < b ? a : b);
  73. };
  74. cr.PI = Math.PI;
  75. cr.round = function (x)
  76. {
  77. return (x + 0.5) | 0;
  78. };
  79. cr.floor = function (x)
  80. {
  81. if (x >= 0)
  82. return x | 0;
  83. else
  84. return (x | 0) - 1; // correctly round down when negative
  85. };
  86. cr.ceil = function (x)
  87. {
  88. var f = x | 0;
  89. return (f === x ? f : f + 1);
  90. };
  91. function Vector2(x, y)
  92. {
  93. this.x = x;
  94. this.y = y;
  95. cr.seal(this);
  96. };
  97. Vector2.prototype.offset = function (px, py)
  98. {
  99. this.x += px;
  100. this.y += py;
  101. return this;
  102. };
  103. Vector2.prototype.mul = function (px, py)
  104. {
  105. this.x *= px;
  106. this.y *= py;
  107. return this;
  108. };
  109. cr.vector2 = Vector2;
  110. cr.segments_intersect = function(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)
  111. {
  112. var max_ax, min_ax, max_ay, min_ay, max_bx, min_bx, max_by, min_by;
  113. if (a1x < a2x)
  114. {
  115. min_ax = a1x;
  116. max_ax = a2x;
  117. }
  118. else
  119. {
  120. min_ax = a2x;
  121. max_ax = a1x;
  122. }
  123. if (b1x < b2x)
  124. {
  125. min_bx = b1x;
  126. max_bx = b2x;
  127. }
  128. else
  129. {
  130. min_bx = b2x;
  131. max_bx = b1x;
  132. }
  133. if (max_ax < min_bx || min_ax > max_bx)
  134. return false;
  135. if (a1y < a2y)
  136. {
  137. min_ay = a1y;
  138. max_ay = a2y;
  139. }
  140. else
  141. {
  142. min_ay = a2y;
  143. max_ay = a1y;
  144. }
  145. if (b1y < b2y)
  146. {
  147. min_by = b1y;
  148. max_by = b2y;
  149. }
  150. else
  151. {
  152. min_by = b2y;
  153. max_by = b1y;
  154. }
  155. if (max_ay < min_by || min_ay > max_by)
  156. return false;
  157. var dpx = b1x - a1x + b2x - a2x;
  158. var dpy = b1y - a1y + b2y - a2y;
  159. var qax = a2x - a1x;
  160. var qay = a2y - a1y;
  161. var qbx = b2x - b1x;
  162. var qby = b2y - b1y;
  163. var d = cr.abs(qay * qbx - qby * qax);
  164. var la = qbx * dpy - qby * dpx;
  165. if (cr.abs(la) > d)
  166. return false;
  167. var lb = qax * dpy - qay * dpx;
  168. return cr.abs(lb) <= d;
  169. };
  170. function Rect(left, top, right, bottom)
  171. {
  172. this.set(left, top, right, bottom);
  173. cr.seal(this);
  174. };
  175. Rect.prototype.set = function (left, top, right, bottom)
  176. {
  177. this.left = left;
  178. this.top = top;
  179. this.right = right;
  180. this.bottom = bottom;
  181. };
  182. Rect.prototype.copy = function (r)
  183. {
  184. this.left = r.left;
  185. this.top = r.top;
  186. this.right = r.right;
  187. this.bottom = r.bottom;
  188. };
  189. Rect.prototype.width = function ()
  190. {
  191. return this.right - this.left;
  192. };
  193. Rect.prototype.height = function ()
  194. {
  195. return this.bottom - this.top;
  196. };
  197. Rect.prototype.offset = function (px, py)
  198. {
  199. this.left += px;
  200. this.top += py;
  201. this.right += px;
  202. this.bottom += py;
  203. return this;
  204. };
  205. Rect.prototype.normalize = function ()
  206. {
  207. var temp = 0;
  208. if (this.left > this.right)
  209. {
  210. temp = this.left;
  211. this.left = this.right;
  212. this.right = temp;
  213. }
  214. if (this.top > this.bottom)
  215. {
  216. temp = this.top;
  217. this.top = this.bottom;
  218. this.bottom = temp;
  219. }
  220. };
  221. Rect.prototype.intersects_rect = function (rc)
  222. {
  223. return !(rc.right < this.left || rc.bottom < this.top || rc.left > this.right || rc.top > this.bottom);
  224. };
  225. Rect.prototype.intersects_rect_off = function (rc, ox, oy)
  226. {
  227. return !(rc.right + ox < this.left || rc.bottom + oy < this.top || rc.left + ox > this.right || rc.top + oy > this.bottom);
  228. };
  229. Rect.prototype.contains_pt = function (x, y)
  230. {
  231. return (x >= this.left && x <= this.right) && (y >= this.top && y <= this.bottom);
  232. };
  233. Rect.prototype.equals = function (r)
  234. {
  235. return this.left === r.left && this.top === r.top && this.right === r.right && this.bottom === r.bottom;
  236. };
  237. cr.rect = Rect;
  238. function Quad()
  239. {
  240. this.tlx = 0;
  241. this.tly = 0;
  242. this.trx = 0;
  243. this.try_ = 0; // is a keyword otherwise!
  244. this.brx = 0;
  245. this.bry = 0;
  246. this.blx = 0;
  247. this.bly = 0;
  248. cr.seal(this);
  249. };
  250. Quad.prototype.set_from_rect = function (rc)
  251. {
  252. this.tlx = rc.left;
  253. this.tly = rc.top;
  254. this.trx = rc.right;
  255. this.try_ = rc.top;
  256. this.brx = rc.right;
  257. this.bry = rc.bottom;
  258. this.blx = rc.left;
  259. this.bly = rc.bottom;
  260. };
  261. Quad.prototype.set_from_rotated_rect = function (rc, a)
  262. {
  263. if (a === 0)
  264. {
  265. this.set_from_rect(rc);
  266. }
  267. else
  268. {
  269. var sin_a = Math.sin(a);
  270. var cos_a = Math.cos(a);
  271. var left_sin_a = rc.left * sin_a;
  272. var top_sin_a = rc.top * sin_a;
  273. var right_sin_a = rc.right * sin_a;
  274. var bottom_sin_a = rc.bottom * sin_a;
  275. var left_cos_a = rc.left * cos_a;
  276. var top_cos_a = rc.top * cos_a;
  277. var right_cos_a = rc.right * cos_a;
  278. var bottom_cos_a = rc.bottom * cos_a;
  279. this.tlx = left_cos_a - top_sin_a;
  280. this.tly = top_cos_a + left_sin_a;
  281. this.trx = right_cos_a - top_sin_a;
  282. this.try_ = top_cos_a + right_sin_a;
  283. this.brx = right_cos_a - bottom_sin_a;
  284. this.bry = bottom_cos_a + right_sin_a;
  285. this.blx = left_cos_a - bottom_sin_a;
  286. this.bly = bottom_cos_a + left_sin_a;
  287. }
  288. };
  289. Quad.prototype.offset = function (px, py)
  290. {
  291. this.tlx += px;
  292. this.tly += py;
  293. this.trx += px;
  294. this.try_ += py;
  295. this.brx += px;
  296. this.bry += py;
  297. this.blx += px;
  298. this.bly += py;
  299. return this;
  300. };
  301. var minresult = 0;
  302. var maxresult = 0;
  303. function minmax4(a, b, c, d)
  304. {
  305. if (a < b)
  306. {
  307. if (c < d)
  308. {
  309. if (a < c)
  310. minresult = a;
  311. else
  312. minresult = c;
  313. if (b > d)
  314. maxresult = b;
  315. else
  316. maxresult = d;
  317. }
  318. else
  319. {
  320. if (a < d)
  321. minresult = a;
  322. else
  323. minresult = d;
  324. if (b > c)
  325. maxresult = b;
  326. else
  327. maxresult = c;
  328. }
  329. }
  330. else
  331. {
  332. if (c < d)
  333. {
  334. if (b < c)
  335. minresult = b;
  336. else
  337. minresult = c;
  338. if (a > d)
  339. maxresult = a;
  340. else
  341. maxresult = d;
  342. }
  343. else
  344. {
  345. if (b < d)
  346. minresult = b;
  347. else
  348. minresult = d;
  349. if (a > c)
  350. maxresult = a;
  351. else
  352. maxresult = c;
  353. }
  354. }
  355. };
  356. Quad.prototype.bounding_box = function (rc)
  357. {
  358. minmax4(this.tlx, this.trx, this.brx, this.blx);
  359. rc.left = minresult;
  360. rc.right = maxresult;
  361. minmax4(this.tly, this.try_, this.bry, this.bly);
  362. rc.top = minresult;
  363. rc.bottom = maxresult;
  364. };
  365. Quad.prototype.contains_pt = function (x, y)
  366. {
  367. var tlx = this.tlx;
  368. var tly = this.tly;
  369. var v0x = this.trx - tlx;
  370. var v0y = this.try_ - tly;
  371. var v1x = this.brx - tlx;
  372. var v1y = this.bry - tly;
  373. var v2x = x - tlx;
  374. var v2y = y - tly;
  375. var dot00 = v0x * v0x + v0y * v0y
  376. var dot01 = v0x * v1x + v0y * v1y
  377. var dot02 = v0x * v2x + v0y * v2y
  378. var dot11 = v1x * v1x + v1y * v1y
  379. var dot12 = v1x * v2x + v1y * v2y
  380. var invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01);
  381. var u = (dot11 * dot02 - dot01 * dot12) * invDenom;
  382. var v = (dot00 * dot12 - dot01 * dot02) * invDenom;
  383. if ((u >= 0.0) && (v > 0.0) && (u + v < 1))
  384. return true;
  385. v0x = this.blx - tlx;
  386. v0y = this.bly - tly;
  387. var dot00 = v0x * v0x + v0y * v0y
  388. var dot01 = v0x * v1x + v0y * v1y
  389. var dot02 = v0x * v2x + v0y * v2y
  390. invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01);
  391. u = (dot11 * dot02 - dot01 * dot12) * invDenom;
  392. v = (dot00 * dot12 - dot01 * dot02) * invDenom;
  393. return (u >= 0.0) && (v > 0.0) && (u + v < 1);
  394. };
  395. Quad.prototype.at = function (i, xory)
  396. {
  397. if (xory)
  398. {
  399. switch (i)
  400. {
  401. case 0: return this.tlx;
  402. case 1: return this.trx;
  403. case 2: return this.brx;
  404. case 3: return this.blx;
  405. case 4: return this.tlx;
  406. default: return this.tlx;
  407. }
  408. }
  409. else
  410. {
  411. switch (i)
  412. {
  413. case 0: return this.tly;
  414. case 1: return this.try_;
  415. case 2: return this.bry;
  416. case 3: return this.bly;
  417. case 4: return this.tly;
  418. default: return this.tly;
  419. }
  420. }
  421. };
  422. Quad.prototype.midX = function ()
  423. {
  424. return (this.tlx + this.trx + this.brx + this.blx) / 4;
  425. };
  426. Quad.prototype.midY = function ()
  427. {
  428. return (this.tly + this.try_ + this.bry + this.bly) / 4;
  429. };
  430. Quad.prototype.intersects_segment = function (x1, y1, x2, y2)
  431. {
  432. if (this.contains_pt(x1, y1) || this.contains_pt(x2, y2))
  433. return true;
  434. var a1x, a1y, a2x, a2y;
  435. var i;
  436. for (i = 0; i < 4; i++)
  437. {
  438. a1x = this.at(i, true);
  439. a1y = this.at(i, false);
  440. a2x = this.at(i + 1, true);
  441. a2y = this.at(i + 1, false);
  442. if (cr.segments_intersect(x1, y1, x2, y2, a1x, a1y, a2x, a2y))
  443. return true;
  444. }
  445. return false;
  446. };
  447. Quad.prototype.intersects_quad = function (rhs)
  448. {
  449. var midx = rhs.midX();
  450. var midy = rhs.midY();
  451. if (this.contains_pt(midx, midy))
  452. return true;
  453. midx = this.midX();
  454. midy = this.midY();
  455. if (rhs.contains_pt(midx, midy))
  456. return true;
  457. var a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y;
  458. var i, j;
  459. for (i = 0; i < 4; i++)
  460. {
  461. for (j = 0; j < 4; j++)
  462. {
  463. a1x = this.at(i, true);
  464. a1y = this.at(i, false);
  465. a2x = this.at(i + 1, true);
  466. a2y = this.at(i + 1, false);
  467. b1x = rhs.at(j, true);
  468. b1y = rhs.at(j, false);
  469. b2x = rhs.at(j + 1, true);
  470. b2y = rhs.at(j + 1, false);
  471. if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y))
  472. return true;
  473. }
  474. }
  475. return false;
  476. };
  477. cr.quad = Quad;
  478. cr.RGB = function (red, green, blue)
  479. {
  480. return Math.max(Math.min(red, 255), 0)
  481. | (Math.max(Math.min(green, 255), 0) << 8)
  482. | (Math.max(Math.min(blue, 255), 0) << 16);
  483. };
  484. cr.GetRValue = function (rgb)
  485. {
  486. return rgb & 0xFF;
  487. };
  488. cr.GetGValue = function (rgb)
  489. {
  490. return (rgb & 0xFF00) >> 8;
  491. };
  492. cr.GetBValue = function (rgb)
  493. {
  494. return (rgb & 0xFF0000) >> 16;
  495. };
  496. cr.shallowCopy = function (a, b, allowOverwrite)
  497. {
  498. var attr;
  499. for (attr in b)
  500. {
  501. if (b.hasOwnProperty(attr))
  502. {
  503. ;
  504. a[attr] = b[attr];
  505. }
  506. }
  507. return a;
  508. };
  509. cr.arrayRemove = function (arr, index)
  510. {
  511. var i, len;
  512. index = cr.floor(index);
  513. if (index < 0 || index >= arr.length)
  514. return; // index out of bounds
  515. for (i = index, len = arr.length - 1; i < len; i++)
  516. arr[i] = arr[i + 1];
  517. cr.truncateArray(arr, len);
  518. };
  519. cr.truncateArray = function (arr, index)
  520. {
  521. arr.length = index;
  522. };
  523. cr.clearArray = function (arr)
  524. {
  525. cr.truncateArray(arr, 0);
  526. };
  527. cr.shallowAssignArray = function (dest, src)
  528. {
  529. cr.clearArray(dest);
  530. var i, len;
  531. for (i = 0, len = src.length; i < len; ++i)
  532. dest[i] = src[i];
  533. };
  534. cr.appendArray = function (a, b)
  535. {
  536. a.push.apply(a, b);
  537. };
  538. cr.fastIndexOf = function (arr, item)
  539. {
  540. var i, len;
  541. for (i = 0, len = arr.length; i < len; ++i)
  542. {
  543. if (arr[i] === item)
  544. return i;
  545. }
  546. return -1;
  547. };
  548. cr.arrayFindRemove = function (arr, item)
  549. {
  550. var index = cr.fastIndexOf(arr, item);
  551. if (index !== -1)
  552. cr.arrayRemove(arr, index);
  553. };
  554. cr.clamp = function(x, a, b)
  555. {
  556. if (x < a)
  557. return a;
  558. else if (x > b)
  559. return b;
  560. else
  561. return x;
  562. };
  563. cr.to_radians = function(x)
  564. {
  565. return x / (180.0 / cr.PI);
  566. };
  567. cr.to_degrees = function(x)
  568. {
  569. return x * (180.0 / cr.PI);
  570. };
  571. cr.clamp_angle_degrees = function (a)
  572. {
  573. a %= 360; // now in (-360, 360) range
  574. if (a < 0)
  575. a += 360; // now in [0, 360) range
  576. return a;
  577. };
  578. cr.clamp_angle = function (a)
  579. {
  580. a %= 2 * cr.PI; // now in (-2pi, 2pi) range
  581. if (a < 0)
  582. a += 2 * cr.PI; // now in [0, 2pi) range
  583. return a;
  584. };
  585. cr.to_clamped_degrees = function (x)
  586. {
  587. return cr.clamp_angle_degrees(cr.to_degrees(x));
  588. };
  589. cr.to_clamped_radians = function (x)
  590. {
  591. return cr.clamp_angle(cr.to_radians(x));
  592. };
  593. cr.angleTo = function(x1, y1, x2, y2)
  594. {
  595. var dx = x2 - x1;
  596. var dy = y2 - y1;
  597. return Math.atan2(dy, dx);
  598. };
  599. cr.angleDiff = function (a1, a2)
  600. {
  601. if (a1 === a2)
  602. return 0;
  603. var s1 = Math.sin(a1);
  604. var c1 = Math.cos(a1);
  605. var s2 = Math.sin(a2);
  606. var c2 = Math.cos(a2);
  607. var n = s1 * s2 + c1 * c2;
  608. if (n >= 1)
  609. return 0;
  610. if (n <= -1)
  611. return cr.PI;
  612. return Math.acos(n);
  613. };
  614. cr.angleRotate = function (start, end, step)
  615. {
  616. var ss = Math.sin(start);
  617. var cs = Math.cos(start);
  618. var se = Math.sin(end);
  619. var ce = Math.cos(end);
  620. if (Math.acos(ss * se + cs * ce) > step)
  621. {
  622. if (cs * se - ss * ce > 0)
  623. return cr.clamp_angle(start + step);
  624. else
  625. return cr.clamp_angle(start - step);
  626. }
  627. else
  628. return cr.clamp_angle(end);
  629. };
  630. cr.angleClockwise = function (a1, a2)
  631. {
  632. var s1 = Math.sin(a1);
  633. var c1 = Math.cos(a1);
  634. var s2 = Math.sin(a2);
  635. var c2 = Math.cos(a2);
  636. return c1 * s2 - s1 * c2 <= 0;
  637. };
  638. cr.rotatePtAround = function (px, py, a, ox, oy, getx)
  639. {
  640. if (a === 0)
  641. return getx ? px : py;
  642. var sin_a = Math.sin(a);
  643. var cos_a = Math.cos(a);
  644. px -= ox;
  645. py -= oy;
  646. var left_sin_a = px * sin_a;
  647. var top_sin_a = py * sin_a;
  648. var left_cos_a = px * cos_a;
  649. var top_cos_a = py * cos_a;
  650. px = left_cos_a - top_sin_a;
  651. py = top_cos_a + left_sin_a;
  652. px += ox;
  653. py += oy;
  654. return getx ? px : py;
  655. }
  656. cr.distanceTo = function(x1, y1, x2, y2)
  657. {
  658. var dx = x2 - x1;
  659. var dy = y2 - y1;
  660. return Math.sqrt(dx*dx + dy*dy);
  661. };
  662. cr.xor = function (x, y)
  663. {
  664. return !x !== !y;
  665. };
  666. cr.lerp = function (a, b, x)
  667. {
  668. return a + (b - a) * x;
  669. };
  670. cr.unlerp = function (a, b, c)
  671. {
  672. if (a === b)
  673. return 0; // avoid divide by 0
  674. return (c - a) / (b - a);
  675. };
  676. cr.anglelerp = function (a, b, x)
  677. {
  678. var diff = cr.angleDiff(a, b);
  679. if (cr.angleClockwise(b, a))
  680. {
  681. return a + diff * x;
  682. }
  683. else
  684. {
  685. return a - diff * x;
  686. }
  687. };
  688. cr.qarp = function (a, b, c, x)
  689. {
  690. return cr.lerp(cr.lerp(a, b, x), cr.lerp(b, c, x), x);
  691. };
  692. cr.cubic = function (a, b, c, d, x)
  693. {
  694. return cr.lerp(cr.qarp(a, b, c, x), cr.qarp(b, c, d, x), x);
  695. };
  696. cr.cosp = function (a, b, x)
  697. {
  698. return (a + b + (a - b) * Math.cos(x * Math.PI)) / 2;
  699. };
  700. cr.hasAnyOwnProperty = function (o)
  701. {
  702. var p;
  703. for (p in o)
  704. {
  705. if (o.hasOwnProperty(p))
  706. return true;
  707. }
  708. return false;
  709. };
  710. cr.wipe = function (obj)
  711. {
  712. var p;
  713. for (p in obj)
  714. {
  715. if (obj.hasOwnProperty(p))
  716. delete obj[p];
  717. }
  718. };
  719. var startup_time = +(new Date());
  720. cr.performance_now = function()
  721. {
  722. if (typeof window["performance"] !== "undefined")
  723. {
  724. var winperf = window["performance"];
  725. if (typeof winperf.now !== "undefined")
  726. return winperf.now();
  727. else if (typeof winperf["webkitNow"] !== "undefined")
  728. return winperf["webkitNow"]();
  729. else if (typeof winperf["mozNow"] !== "undefined")
  730. return winperf["mozNow"]();
  731. else if (typeof winperf["msNow"] !== "undefined")
  732. return winperf["msNow"]();
  733. }
  734. return Date.now() - startup_time;
  735. };
  736. var isChrome = false;
  737. var isSafari = false;
  738. var isiOS = false;
  739. var isEjecta = false;
  740. if (typeof window !== "undefined") // not c2 editor
  741. {
  742. isChrome = /chrome/i.test(navigator.userAgent) || /chromium/i.test(navigator.userAgent);
  743. isSafari = !isChrome && /safari/i.test(navigator.userAgent);
  744. isiOS = /(iphone|ipod|ipad)/i.test(navigator.userAgent);
  745. isEjecta = window["c2ejecta"];
  746. }
  747. var supports_set = ((!isSafari && !isEjecta && !isiOS) && (typeof Set !== "undefined" && typeof Set.prototype["forEach"] !== "undefined"));
  748. function ObjectSet_()
  749. {
  750. this.s = null;
  751. this.items = null; // lazy allocated (hopefully results in better GC performance)
  752. this.item_count = 0;
  753. if (supports_set)
  754. {
  755. this.s = new Set();
  756. }
  757. this.values_cache = [];
  758. this.cache_valid = true;
  759. cr.seal(this);
  760. };
  761. ObjectSet_.prototype.contains = function (x)
  762. {
  763. if (this.isEmpty())
  764. return false;
  765. if (supports_set)
  766. return this.s["has"](x);
  767. else
  768. return (this.items && this.items.hasOwnProperty(x));
  769. };
  770. ObjectSet_.prototype.add = function (x)
  771. {
  772. if (supports_set)
  773. {
  774. if (!this.s["has"](x))
  775. {
  776. this.s["add"](x);
  777. this.cache_valid = false;
  778. }
  779. }
  780. else
  781. {
  782. var str = x.toString();
  783. var items = this.items;
  784. if (!items)
  785. {
  786. this.items = {};
  787. this.items[str] = x;
  788. this.item_count = 1;
  789. this.cache_valid = false;
  790. }
  791. else if (!items.hasOwnProperty(str))
  792. {
  793. items[str] = x;
  794. this.item_count++;
  795. this.cache_valid = false;
  796. }
  797. }
  798. };
  799. ObjectSet_.prototype.remove = function (x)
  800. {
  801. if (this.isEmpty())
  802. return;
  803. if (supports_set)
  804. {
  805. if (this.s["has"](x))
  806. {
  807. this.s["delete"](x);
  808. this.cache_valid = false;
  809. }
  810. }
  811. else if (this.items)
  812. {
  813. var str = x.toString();
  814. var items = this.items;
  815. if (items.hasOwnProperty(str))
  816. {
  817. delete items[str];
  818. this.item_count--;
  819. this.cache_valid = false;
  820. }
  821. }
  822. };
  823. ObjectSet_.prototype.clear = function (/*wipe_*/)
  824. {
  825. if (this.isEmpty())
  826. return;
  827. if (supports_set)
  828. {
  829. this.s["clear"](); // best!
  830. }
  831. else
  832. {
  833. this.items = null; // creates garbage; will lazy allocate on next add()
  834. this.item_count = 0;
  835. }
  836. cr.clearArray(this.values_cache);
  837. this.cache_valid = true;
  838. };
  839. ObjectSet_.prototype.isEmpty = function ()
  840. {
  841. return this.count() === 0;
  842. };
  843. ObjectSet_.prototype.count = function ()
  844. {
  845. if (supports_set)
  846. return this.s["size"];
  847. else
  848. return this.item_count;
  849. };
  850. var current_arr = null;
  851. var current_index = 0;
  852. function set_append_to_arr(x)
  853. {
  854. current_arr[current_index++] = x;
  855. };
  856. ObjectSet_.prototype.update_cache = function ()
  857. {
  858. if (this.cache_valid)
  859. return;
  860. if (supports_set)
  861. {
  862. cr.clearArray(this.values_cache);
  863. current_arr = this.values_cache;
  864. current_index = 0;
  865. this.s["forEach"](set_append_to_arr);
  866. ;
  867. current_arr = null;
  868. current_index = 0;
  869. }
  870. else
  871. {
  872. var values_cache = this.values_cache;
  873. cr.clearArray(values_cache);
  874. var p, n = 0, items = this.items;
  875. if (items)
  876. {
  877. for (p in items)
  878. {
  879. if (items.hasOwnProperty(p))
  880. values_cache[n++] = items[p];
  881. }
  882. }
  883. ;
  884. }
  885. this.cache_valid = true;
  886. };
  887. ObjectSet_.prototype.valuesRef = function ()
  888. {
  889. this.update_cache();
  890. return this.values_cache;
  891. };
  892. cr.ObjectSet = ObjectSet_;
  893. var tmpSet = new cr.ObjectSet();
  894. cr.removeArrayDuplicates = function (arr)
  895. {
  896. var i, len;
  897. for (i = 0, len = arr.length; i < len; ++i)
  898. {
  899. tmpSet.add(arr[i]);
  900. }
  901. cr.shallowAssignArray(arr, tmpSet.valuesRef());
  902. tmpSet.clear();
  903. };
  904. cr.arrayRemoveAllFromObjectSet = function (arr, remset)
  905. {
  906. if (supports_set)
  907. cr.arrayRemoveAll_set(arr, remset.s);
  908. else
  909. cr.arrayRemoveAll_arr(arr, remset.valuesRef());
  910. };
  911. cr.arrayRemoveAll_set = function (arr, s)
  912. {
  913. var i, j, len, item;
  914. for (i = 0, j = 0, len = arr.length; i < len; ++i)
  915. {
  916. item = arr[i];
  917. if (!s["has"](item)) // not an item to remove
  918. arr[j++] = item; // keep it
  919. }
  920. cr.truncateArray(arr, j);
  921. };
  922. cr.arrayRemoveAll_arr = function (arr, rem)
  923. {
  924. var i, j, len, item;
  925. for (i = 0, j = 0, len = arr.length; i < len; ++i)
  926. {
  927. item = arr[i];
  928. if (cr.fastIndexOf(rem, item) === -1) // not an item to remove
  929. arr[j++] = item; // keep it
  930. }
  931. cr.truncateArray(arr, j);
  932. };
  933. function KahanAdder_()
  934. {
  935. this.c = 0;
  936. this.y = 0;
  937. this.t = 0;
  938. this.sum = 0;
  939. cr.seal(this);
  940. };
  941. KahanAdder_.prototype.add = function (v)
  942. {
  943. this.y = v - this.c;
  944. this.t = this.sum + this.y;
  945. this.c = (this.t - this.sum) - this.y;
  946. this.sum = this.t;
  947. };
  948. KahanAdder_.prototype.reset = function ()
  949. {
  950. this.c = 0;
  951. this.y = 0;
  952. this.t = 0;
  953. this.sum = 0;
  954. };
  955. cr.KahanAdder = KahanAdder_;
  956. cr.regexp_escape = function(text)
  957. {
  958. return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
  959. };
  960. function CollisionPoly_(pts_array_)
  961. {
  962. this.pts_cache = [];
  963. this.bboxLeft = 0;
  964. this.bboxTop = 0;
  965. this.bboxRight = 0;
  966. this.bboxBottom = 0;
  967. this.convexpolys = null; // for physics behavior to cache separated polys
  968. this.set_pts(pts_array_);
  969. cr.seal(this);
  970. };
  971. CollisionPoly_.prototype.set_pts = function(pts_array_)
  972. {
  973. this.pts_array = pts_array_;
  974. this.pts_count = pts_array_.length / 2; // x, y, x, y... in array
  975. this.pts_cache.length = pts_array_.length;
  976. this.cache_width = -1;
  977. this.cache_height = -1;
  978. this.cache_angle = 0;
  979. };
  980. CollisionPoly_.prototype.is_empty = function()
  981. {
  982. return !this.pts_array.length;
  983. };
  984. CollisionPoly_.prototype.update_bbox = function ()
  985. {
  986. var myptscache = this.pts_cache;
  987. var bboxLeft_ = myptscache[0];
  988. var bboxRight_ = bboxLeft_;
  989. var bboxTop_ = myptscache[1];
  990. var bboxBottom_ = bboxTop_;
  991. var x, y, i = 1, i2, len = this.pts_count;
  992. for ( ; i < len; ++i)
  993. {
  994. i2 = i*2;
  995. x = myptscache[i2];
  996. y = myptscache[i2+1];
  997. if (x < bboxLeft_)
  998. bboxLeft_ = x;
  999. if (x > bboxRight_)
  1000. bboxRight_ = x;
  1001. if (y < bboxTop_)
  1002. bboxTop_ = y;
  1003. if (y > bboxBottom_)
  1004. bboxBottom_ = y;
  1005. }
  1006. this.bboxLeft = bboxLeft_;
  1007. this.bboxRight = bboxRight_;
  1008. this.bboxTop = bboxTop_;
  1009. this.bboxBottom = bboxBottom_;
  1010. };
  1011. CollisionPoly_.prototype.set_from_rect = function(rc, offx, offy)
  1012. {
  1013. this.pts_cache.length = 8;
  1014. this.pts_count = 4;
  1015. var myptscache = this.pts_cache;
  1016. myptscache[0] = rc.left - offx;
  1017. myptscache[1] = rc.top - offy;
  1018. myptscache[2] = rc.right - offx;
  1019. myptscache[3] = rc.top - offy;
  1020. myptscache[4] = rc.right - offx;
  1021. myptscache[5] = rc.bottom - offy;
  1022. myptscache[6] = rc.left - offx;
  1023. myptscache[7] = rc.bottom - offy;
  1024. this.cache_width = rc.right - rc.left;
  1025. this.cache_height = rc.bottom - rc.top;
  1026. this.update_bbox();
  1027. };
  1028. CollisionPoly_.prototype.set_from_quad = function(q, offx, offy, w, h)
  1029. {
  1030. this.pts_cache.length = 8;
  1031. this.pts_count = 4;
  1032. var myptscache = this.pts_cache;
  1033. myptscache[0] = q.tlx - offx;
  1034. myptscache[1] = q.tly - offy;
  1035. myptscache[2] = q.trx - offx;
  1036. myptscache[3] = q.try_ - offy;
  1037. myptscache[4] = q.brx - offx;
  1038. myptscache[5] = q.bry - offy;
  1039. myptscache[6] = q.blx - offx;
  1040. myptscache[7] = q.bly - offy;
  1041. this.cache_width = w;
  1042. this.cache_height = h;
  1043. this.update_bbox();
  1044. };
  1045. CollisionPoly_.prototype.set_from_poly = function (r)
  1046. {
  1047. this.pts_count = r.pts_count;
  1048. cr.shallowAssignArray(this.pts_cache, r.pts_cache);
  1049. this.bboxLeft = r.bboxLeft;
  1050. this.bboxTop - r.bboxTop;
  1051. this.bboxRight = r.bboxRight;
  1052. this.bboxBottom = r.bboxBottom;
  1053. };
  1054. CollisionPoly_.prototype.cache_poly = function(w, h, a)
  1055. {
  1056. if (this.cache_width === w && this.cache_height === h && this.cache_angle === a)
  1057. return; // cache up-to-date
  1058. this.cache_width = w;
  1059. this.cache_height = h;
  1060. this.cache_angle = a;
  1061. var i, i2, i21, len, x, y;
  1062. var sina = 0;
  1063. var cosa = 1;
  1064. var myptsarray = this.pts_array;
  1065. var myptscache = this.pts_cache;
  1066. if (a !== 0)
  1067. {
  1068. sina = Math.sin(a);
  1069. cosa = Math.cos(a);
  1070. }
  1071. for (i = 0, len = this.pts_count; i < len; i++)
  1072. {
  1073. i2 = i*2;
  1074. i21 = i2+1;
  1075. x = myptsarray[i2] * w;
  1076. y = myptsarray[i21] * h;
  1077. myptscache[i2] = (x * cosa) - (y * sina);
  1078. myptscache[i21] = (y * cosa) + (x * sina);
  1079. }
  1080. this.update_bbox();
  1081. };
  1082. CollisionPoly_.prototype.contains_pt = function (a2x, a2y)
  1083. {
  1084. var myptscache = this.pts_cache;
  1085. if (a2x === myptscache[0] && a2y === myptscache[1])
  1086. return true;
  1087. var i, i2, imod, len = this.pts_count;
  1088. var a1x = this.bboxLeft - 110;
  1089. var a1y = this.bboxTop - 101;
  1090. var a3x = this.bboxRight + 131
  1091. var a3y = this.bboxBottom + 120;
  1092. var b1x, b1y, b2x, b2y;
  1093. var count1 = 0, count2 = 0;
  1094. for (i = 0; i < len; i++)
  1095. {
  1096. i2 = i*2;
  1097. imod = ((i+1)%len)*2;
  1098. b1x = myptscache[i2];
  1099. b1y = myptscache[i2+1];
  1100. b2x = myptscache[imod];
  1101. b2y = myptscache[imod+1];
  1102. if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y))
  1103. count1++;
  1104. if (cr.segments_intersect(a3x, a3y, a2x, a2y, b1x, b1y, b2x, b2y))
  1105. count2++;
  1106. }
  1107. return (count1 % 2 === 1) || (count2 % 2 === 1);
  1108. };
  1109. CollisionPoly_.prototype.intersects_poly = function (rhs, offx, offy)
  1110. {
  1111. var rhspts = rhs.pts_cache;
  1112. var mypts = this.pts_cache;
  1113. if (this.contains_pt(rhspts[0] + offx, rhspts[1] + offy))
  1114. return true;
  1115. if (rhs.contains_pt(mypts[0] - offx, mypts[1] - offy))
  1116. return true;
  1117. var i, i2, imod, leni, j, j2, jmod, lenj;
  1118. var a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y;
  1119. for (i = 0, leni = this.pts_count; i < leni; i++)
  1120. {
  1121. i2 = i*2;
  1122. imod = ((i+1)%leni)*2;
  1123. a1x = mypts[i2];
  1124. a1y = mypts[i2+1];
  1125. a2x = mypts[imod];
  1126. a2y = mypts[imod+1];
  1127. for (j = 0, lenj = rhs.pts_count; j < lenj; j++)
  1128. {
  1129. j2 = j*2;
  1130. jmod = ((j+1)%lenj)*2;
  1131. b1x = rhspts[j2] + offx;
  1132. b1y = rhspts[j2+1] + offy;
  1133. b2x = rhspts[jmod] + offx;
  1134. b2y = rhspts[jmod+1] + offy;
  1135. if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y))
  1136. return true;
  1137. }
  1138. }
  1139. return false;
  1140. };
  1141. CollisionPoly_.prototype.intersects_segment = function (offx, offy, x1, y1, x2, y2)
  1142. {
  1143. var mypts = this.pts_cache;
  1144. if (this.contains_pt(x1 - offx, y1 - offy))
  1145. return true;
  1146. var i, leni, i2, imod;
  1147. var a1x, a1y, a2x, a2y;
  1148. for (i = 0, leni = this.pts_count; i < leni; i++)
  1149. {
  1150. i2 = i*2;
  1151. imod = ((i+1)%leni)*2;
  1152. a1x = mypts[i2] + offx;
  1153. a1y = mypts[i2+1] + offy;
  1154. a2x = mypts[imod] + offx;
  1155. a2y = mypts[imod+1] + offy;
  1156. if (cr.segments_intersect(x1, y1, x2, y2, a1x, a1y, a2x, a2y))
  1157. return true;
  1158. }
  1159. return false;
  1160. };
  1161. CollisionPoly_.prototype.mirror = function (px)
  1162. {
  1163. var i, leni, i2;
  1164. for (i = 0, leni = this.pts_count; i < leni; ++i)
  1165. {
  1166. i2 = i*2;
  1167. this.pts_cache[i2] = px * 2 - this.pts_cache[i2];
  1168. }
  1169. };
  1170. CollisionPoly_.prototype.flip = function (py)
  1171. {
  1172. var i, leni, i21;
  1173. for (i = 0, leni = this.pts_count; i < leni; ++i)
  1174. {
  1175. i21 = i*2+1;
  1176. this.pts_cache[i21] = py * 2 - this.pts_cache[i21];
  1177. }
  1178. };
  1179. CollisionPoly_.prototype.diag = function ()
  1180. {
  1181. var i, leni, i2, i21, temp;
  1182. for (i = 0, leni = this.pts_count; i < leni; ++i)
  1183. {
  1184. i2 = i*2;
  1185. i21 = i2+1;
  1186. temp = this.pts_cache[i2];
  1187. this.pts_cache[i2] = this.pts_cache[i21];
  1188. this.pts_cache[i21] = temp;
  1189. }
  1190. };
  1191. cr.CollisionPoly = CollisionPoly_;
  1192. function SparseGrid_(cellwidth_, cellheight_)
  1193. {
  1194. this.cellwidth = cellwidth_;
  1195. this.cellheight = cellheight_;
  1196. this.cells = {};
  1197. };
  1198. SparseGrid_.prototype.totalCellCount = 0;
  1199. SparseGrid_.prototype.getCell = function (x_, y_, create_if_missing)
  1200. {
  1201. var ret;
  1202. var col = this.cells[x_];
  1203. if (!col)
  1204. {
  1205. if (create_if_missing)
  1206. {
  1207. ret = allocGridCell(this, x_, y_);
  1208. this.cells[x_] = {};
  1209. this.cells[x_][y_] = ret;
  1210. return ret;
  1211. }
  1212. else
  1213. return null;
  1214. }
  1215. ret = col[y_];
  1216. if (ret)
  1217. return ret;
  1218. else if (create_if_missing)
  1219. {
  1220. ret = allocGridCell(this, x_, y_);
  1221. this.cells[x_][y_] = ret;
  1222. return ret;
  1223. }
  1224. else
  1225. return null;
  1226. };
  1227. SparseGrid_.prototype.XToCell = function (x_)
  1228. {
  1229. return cr.floor(x_ / this.cellwidth);
  1230. };
  1231. SparseGrid_.prototype.YToCell = function (y_)
  1232. {
  1233. return cr.floor(y_ / this.cellheight);
  1234. };
  1235. SparseGrid_.prototype.update = function (inst, oldrange, newrange)
  1236. {
  1237. var x, lenx, y, leny, cell;
  1238. if (oldrange)
  1239. {
  1240. for (x = oldrange.left, lenx = oldrange.right; x <= lenx; ++x)
  1241. {
  1242. for (y = oldrange.top, leny = oldrange.bottom; y <= leny; ++y)
  1243. {
  1244. if (newrange && newrange.contains_pt(x, y))
  1245. continue; // is still in this cell
  1246. cell = this.getCell(x, y, false); // don't create if missing
  1247. if (!cell)
  1248. continue; // cell does not exist yet
  1249. cell.remove(inst);
  1250. if (cell.isEmpty())
  1251. {
  1252. freeGridCell(cell);
  1253. this.cells[x][y] = null;
  1254. }
  1255. }
  1256. }
  1257. }
  1258. if (newrange)
  1259. {
  1260. for (x = newrange.left, lenx = newrange.right; x <= lenx; ++x)
  1261. {
  1262. for (y = newrange.top, leny = newrange.bottom; y <= leny; ++y)
  1263. {
  1264. if (oldrange && oldrange.contains_pt(x, y))
  1265. continue; // is still in this cell
  1266. this.getCell(x, y, true).insert(inst);
  1267. }
  1268. }
  1269. }
  1270. };
  1271. SparseGrid_.prototype.queryRange = function (rc, result)
  1272. {
  1273. var x, lenx, ystart, y, leny, cell;
  1274. x = this.XToCell(rc.left);
  1275. ystart = this.YToCell(rc.top);
  1276. lenx = this.XToCell(rc.right);
  1277. leny = this.YToCell(rc.bottom);
  1278. for ( ; x <= lenx; ++x)
  1279. {
  1280. for (y = ystart; y <= leny; ++y)
  1281. {
  1282. cell = this.getCell(x, y, false);
  1283. if (!cell)
  1284. continue;
  1285. cell.dump(result);
  1286. }
  1287. }
  1288. };
  1289. cr.SparseGrid = SparseGrid_;
  1290. function RenderGrid_(cellwidth_, cellheight_)
  1291. {
  1292. this.cellwidth = cellwidth_;
  1293. this.cellheight = cellheight_;
  1294. this.cells = {};
  1295. };
  1296. RenderGrid_.prototype.totalCellCount = 0;
  1297. RenderGrid_.prototype.getCell = function (x_, y_, create_if_missing)
  1298. {
  1299. var ret;
  1300. var col = this.cells[x_];
  1301. if (!col)
  1302. {
  1303. if (create_if_missing)
  1304. {
  1305. ret = allocRenderCell(this, x_, y_);
  1306. this.cells[x_] = {};
  1307. this.cells[x_][y_] = ret;
  1308. return ret;
  1309. }
  1310. else
  1311. return null;
  1312. }
  1313. ret = col[y_];
  1314. if (ret)
  1315. return ret;
  1316. else if (create_if_missing)
  1317. {
  1318. ret = allocRenderCell(this, x_, y_);
  1319. this.cells[x_][y_] = ret;
  1320. return ret;
  1321. }
  1322. else
  1323. return null;
  1324. };
  1325. RenderGrid_.prototype.XToCell = function (x_)
  1326. {
  1327. return cr.floor(x_ / this.cellwidth);
  1328. };
  1329. RenderGrid_.prototype.YToCell = function (y_)
  1330. {
  1331. return cr.floor(y_ / this.cellheight);
  1332. };
  1333. RenderGrid_.prototype.update = function (inst, oldrange, newrange)
  1334. {
  1335. var x, lenx, y, leny, cell;
  1336. if (oldrange)
  1337. {
  1338. for (x = oldrange.left, lenx = oldrange.right; x <= lenx; ++x)
  1339. {
  1340. for (y = oldrange.top, leny = oldrange.bottom; y <= leny; ++y)
  1341. {
  1342. if (newrange && newrange.contains_pt(x, y))
  1343. continue; // is still in this cell
  1344. cell = this.getCell(x, y, false); // don't create if missing
  1345. if (!cell)
  1346. continue; // cell does not exist yet
  1347. cell.remove(inst);
  1348. if (cell.isEmpty())
  1349. {
  1350. freeRenderCell(cell);
  1351. this.cells[x][y] = null;
  1352. }
  1353. }
  1354. }
  1355. }
  1356. if (newrange)
  1357. {
  1358. for (x = newrange.left, lenx = newrange.right; x <= lenx; ++x)
  1359. {
  1360. for (y = newrange.top, leny = newrange.bottom; y <= leny; ++y)
  1361. {
  1362. if (oldrange && oldrange.contains_pt(x, y))
  1363. continue; // is still in this cell
  1364. this.getCell(x, y, true).insert(inst);
  1365. }
  1366. }
  1367. }
  1368. };
  1369. RenderGrid_.prototype.queryRange = function (left, top, right, bottom, result)
  1370. {
  1371. var x, lenx, ystart, y, leny, cell;
  1372. x = this.XToCell(left);
  1373. ystart = this.YToCell(top);
  1374. lenx = this.XToCell(right);
  1375. leny = this.YToCell(bottom);
  1376. for ( ; x <= lenx; ++x)
  1377. {
  1378. for (y = ystart; y <= leny; ++y)
  1379. {
  1380. cell = this.getCell(x, y, false);
  1381. if (!cell)
  1382. continue;
  1383. cell.dump(result);
  1384. }
  1385. }
  1386. };
  1387. RenderGrid_.prototype.markRangeChanged = function (rc)
  1388. {
  1389. var x, lenx, ystart, y, leny, cell;
  1390. x = rc.left;
  1391. ystart = rc.top;
  1392. lenx = rc.right;
  1393. leny = rc.bottom;
  1394. for ( ; x <= lenx; ++x)
  1395. {
  1396. for (y = ystart; y <= leny; ++y)
  1397. {
  1398. cell = this.getCell(x, y, false);
  1399. if (!cell)
  1400. continue;
  1401. cell.is_sorted = false;
  1402. }
  1403. }
  1404. };
  1405. cr.RenderGrid = RenderGrid_;
  1406. var gridcellcache = [];
  1407. function allocGridCell(grid_, x_, y_)
  1408. {
  1409. var ret;
  1410. SparseGrid_.prototype.totalCellCount++;
  1411. if (gridcellcache.length)
  1412. {
  1413. ret = gridcellcache.pop();
  1414. ret.grid = grid_;
  1415. ret.x = x_;
  1416. ret.y = y_;
  1417. return ret;
  1418. }
  1419. else
  1420. return new cr.GridCell(grid_, x_, y_);
  1421. };
  1422. function freeGridCell(c)
  1423. {
  1424. SparseGrid_.prototype.totalCellCount--;
  1425. c.objects.clear();
  1426. if (gridcellcache.length < 1000)
  1427. gridcellcache.push(c);
  1428. };
  1429. function GridCell_(grid_, x_, y_)
  1430. {
  1431. this.grid = grid_;
  1432. this.x = x_;
  1433. this.y = y_;
  1434. this.objects = new cr.ObjectSet();
  1435. };
  1436. GridCell_.prototype.isEmpty = function ()
  1437. {
  1438. return this.objects.isEmpty();
  1439. };
  1440. GridCell_.prototype.insert = function (inst)
  1441. {
  1442. this.objects.add(inst);
  1443. };
  1444. GridCell_.prototype.remove = function (inst)
  1445. {
  1446. this.objects.remove(inst);
  1447. };
  1448. GridCell_.prototype.dump = function (result)
  1449. {
  1450. cr.appendArray(result, this.objects.valuesRef());
  1451. };
  1452. cr.GridCell = GridCell_;
  1453. var rendercellcache = [];
  1454. function allocRenderCell(grid_, x_, y_)
  1455. {
  1456. var ret;
  1457. RenderGrid_.prototype.totalCellCount++;
  1458. if (rendercellcache.length)
  1459. {
  1460. ret = rendercellcache.pop();
  1461. ret.grid = grid_;
  1462. ret.x = x_;
  1463. ret.y = y_;
  1464. return ret;
  1465. }
  1466. else
  1467. return new cr.RenderCell(grid_, x_, y_);
  1468. };
  1469. function freeRenderCell(c)
  1470. {
  1471. RenderGrid_.prototype.totalCellCount--;
  1472. c.reset();
  1473. if (rendercellcache.length < 1000)
  1474. rendercellcache.push(c);
  1475. };
  1476. function RenderCell_(grid_, x_, y_)
  1477. {
  1478. this.grid = grid_;
  1479. this.x = x_;
  1480. this.y = y_;
  1481. this.objects = []; // array which needs to be sorted by Z order
  1482. this.is_sorted = true; // whether array is in correct sort order or not
  1483. this.pending_removal = new cr.ObjectSet();
  1484. this.any_pending_removal = false;
  1485. };
  1486. RenderCell_.prototype.isEmpty = function ()
  1487. {
  1488. if (!this.objects.length)
  1489. {
  1490. ;
  1491. ;
  1492. return true;
  1493. }
  1494. if (this.objects.length > this.pending_removal.count())
  1495. return false;
  1496. ;
  1497. this.flush_pending(); // takes fast path and just resets state
  1498. return true;
  1499. };
  1500. RenderCell_.prototype.insert = function (inst)
  1501. {
  1502. if (this.pending_removal.contains(inst))
  1503. {
  1504. this.pending_removal.remove(inst);
  1505. if (this.pending_removal.isEmpty())
  1506. this.any_pending_removal = false;
  1507. return;
  1508. }
  1509. if (this.objects.length)
  1510. {
  1511. var top = this.objects[this.objects.length - 1];
  1512. if (top.get_zindex() > inst.get_zindex())
  1513. this.is_sorted = false; // 'inst' should be somewhere beneath 'top'
  1514. this.objects.push(inst);
  1515. }
  1516. else
  1517. {
  1518. this.objects.push(inst);
  1519. this.is_sorted = true;
  1520. }
  1521. ;
  1522. };
  1523. RenderCell_.prototype.remove = function (inst)
  1524. {
  1525. this.pending_removal.add(inst);
  1526. this.any_pending_removal = true;
  1527. if (this.pending_removal.count() >= 30)
  1528. this.flush_pending();
  1529. };
  1530. RenderCell_.prototype.flush_pending = function ()
  1531. {
  1532. ;
  1533. if (!this.any_pending_removal)
  1534. return; // not changed
  1535. if (this.pending_removal.count() === this.objects.length)
  1536. {
  1537. this.reset();
  1538. return;
  1539. }
  1540. cr.arrayRemoveAllFromObjectSet(this.objects, this.pending_removal);
  1541. this.pending_removal.clear();
  1542. this.any_pending_removal = false;
  1543. };
  1544. function sortByInstanceZIndex(a, b)
  1545. {
  1546. return a.zindex - b.zindex;
  1547. };
  1548. RenderCell_.prototype.ensure_sorted = function ()
  1549. {
  1550. if (this.is_sorted)
  1551. return; // already sorted
  1552. this.objects.sort(sortByInstanceZIndex);
  1553. this.is_sorted = true;
  1554. };
  1555. RenderCell_.prototype.reset = function ()
  1556. {
  1557. cr.clearArray(this.objects);
  1558. this.is_sorted = true;
  1559. this.pending_removal.clear();
  1560. this.any_pending_removal = false;
  1561. };
  1562. RenderCell_.prototype.dump = function (result)
  1563. {
  1564. this.flush_pending();
  1565. this.ensure_sorted();
  1566. if (this.objects.length)
  1567. result.push(this.objects);
  1568. };
  1569. cr.RenderCell = RenderCell_;
  1570. var fxNames = [ "lighter",
  1571. "xor",
  1572. "copy",
  1573. "destination-over",
  1574. "source-in",
  1575. "destination-in",
  1576. "source-out",
  1577. "destination-out",
  1578. "source-atop",
  1579. "destination-atop"];
  1580. cr.effectToCompositeOp = function(effect)
  1581. {
  1582. if (effect <= 0 || effect >= 11)
  1583. return "source-over";
  1584. return fxNames[effect - 1]; // not including "none" so offset by 1
  1585. };
  1586. cr.setGLBlend = function(this_, effect, gl)
  1587. {
  1588. if (!gl)
  1589. return;
  1590. this_.srcBlend = gl.ONE;
  1591. this_.destBlend = gl.ONE_MINUS_SRC_ALPHA;
  1592. switch (effect) {
  1593. case 1: // lighter (additive)
  1594. this_.srcBlend = gl.ONE;
  1595. this_.destBlend = gl.ONE;
  1596. break;
  1597. case 2: // xor
  1598. break; // todo
  1599. case 3: // copy
  1600. this_.srcBlend = gl.ONE;
  1601. this_.destBlend = gl.ZERO;
  1602. break;
  1603. case 4: // destination-over
  1604. this_.srcBlend = gl.ONE_MINUS_DST_ALPHA;
  1605. this_.destBlend = gl.ONE;
  1606. break;
  1607. case 5: // source-in
  1608. this_.srcBlend = gl.DST_ALPHA;
  1609. this_.destBlend = gl.ZERO;
  1610. break;
  1611. case 6: // destination-in
  1612. this_.srcBlend = gl.ZERO;
  1613. this_.destBlend = gl.SRC_ALPHA;
  1614. break;
  1615. case 7: // source-out
  1616. this_.srcBlend = gl.ONE_MINUS_DST_ALPHA;
  1617. this_.destBlend = gl.ZERO;
  1618. break;
  1619. case 8: // destination-out
  1620. this_.srcBlend = gl.ZERO;
  1621. this_.destBlend = gl.ONE_MINUS_SRC_ALPHA;
  1622. break;
  1623. case 9: // source-atop
  1624. this_.srcBlend = gl.DST_ALPHA;
  1625. this_.destBlend = gl.ONE_MINUS_SRC_ALPHA;
  1626. break;
  1627. case 10: // destination-atop
  1628. this_.srcBlend = gl.ONE_MINUS_DST_ALPHA;
  1629. this_.destBlend = gl.SRC_ALPHA;
  1630. break;
  1631. }
  1632. };
  1633. cr.round6dp = function (x)
  1634. {
  1635. return Math.round(x * 1000000) / 1000000;
  1636. };
  1637. /*
  1638. var localeCompare_options = {
  1639. "usage": "search",
  1640. "sensitivity": "accent"
  1641. };
  1642. var has_localeCompare = !!"a".localeCompare;
  1643. var localeCompare_works1 = (has_localeCompare && "a".localeCompare("A", undefined, localeCompare_options) === 0);
  1644. var localeCompare_works2 = (has_localeCompare && "a".localeCompare("á", undefined, localeCompare_options) !== 0);
  1645. var supports_localeCompare = (has_localeCompare && localeCompare_works1 && localeCompare_works2);
  1646. */
  1647. cr.equals_nocase = function (a, b)
  1648. {
  1649. if (typeof a !== "string" || typeof b !== "string")
  1650. return false;
  1651. if (a.length !== b.length)
  1652. return false;
  1653. if (a === b)
  1654. return true;
  1655. /*
  1656. if (supports_localeCompare)
  1657. {
  1658. return (a.localeCompare(b, undefined, localeCompare_options) === 0);
  1659. }
  1660. else
  1661. {
  1662. */
  1663. return a.toLowerCase() === b.toLowerCase();
  1664. };
  1665. cr.isCanvasInputEvent = function (e)
  1666. {
  1667. var target = e.target;
  1668. if (!target)
  1669. return true;
  1670. if (target === document || target === window)
  1671. return true;
  1672. if (document && document.body && target === document.body)
  1673. return true;
  1674. if (cr.equals_nocase(target.tagName, "canvas"))
  1675. return true;
  1676. return false;
  1677. };
  1678. }());
  1679. var MatrixArray=typeof Float32Array!=="undefined"?Float32Array:Array,glMatrixArrayType=MatrixArray,vec3={},mat3={},mat4={},quat4={};vec3.create=function(a){var b=new MatrixArray(3);a&&(b[0]=a[0],b[1]=a[1],b[2]=a[2]);return b};vec3.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];return b};vec3.add=function(a,b,c){if(!c||a===c)return a[0]+=b[0],a[1]+=b[1],a[2]+=b[2],a;c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];return c};
  1680. vec3.subtract=function(a,b,c){if(!c||a===c)return a[0]-=b[0],a[1]-=b[1],a[2]-=b[2],a;c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];return c};vec3.negate=function(a,b){b||(b=a);b[0]=-a[0];b[1]=-a[1];b[2]=-a[2];return b};vec3.scale=function(a,b,c){if(!c||a===c)return a[0]*=b,a[1]*=b,a[2]*=b,a;c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;return c};
  1681. vec3.normalize=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=Math.sqrt(c*c+d*d+e*e);if(g){if(g===1)return b[0]=c,b[1]=d,b[2]=e,b}else return b[0]=0,b[1]=0,b[2]=0,b;g=1/g;b[0]=c*g;b[1]=d*g;b[2]=e*g;return b};vec3.cross=function(a,b,c){c||(c=a);var d=a[0],e=a[1],a=a[2],g=b[0],f=b[1],b=b[2];c[0]=e*b-a*f;c[1]=a*g-d*b;c[2]=d*f-e*g;return c};vec3.length=function(a){var b=a[0],c=a[1],a=a[2];return Math.sqrt(b*b+c*c+a*a)};vec3.dot=function(a,b){return a[0]*b[0]+a[1]*b[1]+a[2]*b[2]};
  1682. vec3.direction=function(a,b,c){c||(c=a);var d=a[0]-b[0],e=a[1]-b[1],a=a[2]-b[2],b=Math.sqrt(d*d+e*e+a*a);if(!b)return c[0]=0,c[1]=0,c[2]=0,c;b=1/b;c[0]=d*b;c[1]=e*b;c[2]=a*b;return c};vec3.lerp=function(a,b,c,d){d||(d=a);d[0]=a[0]+c*(b[0]-a[0]);d[1]=a[1]+c*(b[1]-a[1]);d[2]=a[2]+c*(b[2]-a[2]);return d};vec3.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+"]"};
  1683. mat3.create=function(a){var b=new MatrixArray(9);a&&(b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8]);return b};mat3.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];return b};mat3.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=1;a[5]=0;a[6]=0;a[7]=0;a[8]=1;return a};
  1684. mat3.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[5];a[1]=a[3];a[2]=a[6];a[3]=c;a[5]=a[7];a[6]=d;a[7]=e;return a}b[0]=a[0];b[1]=a[3];b[2]=a[6];b[3]=a[1];b[4]=a[4];b[5]=a[7];b[6]=a[2];b[7]=a[5];b[8]=a[8];return b};mat3.toMat4=function(a,b){b||(b=mat4.create());b[15]=1;b[14]=0;b[13]=0;b[12]=0;b[11]=0;b[10]=a[8];b[9]=a[7];b[8]=a[6];b[7]=0;b[6]=a[5];b[5]=a[4];b[4]=a[3];b[3]=0;b[2]=a[2];b[1]=a[1];b[0]=a[0];return b};
  1685. mat3.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+"]"};mat4.create=function(a){var b=new MatrixArray(16);a&&(b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3],b[4]=a[4],b[5]=a[5],b[6]=a[6],b[7]=a[7],b[8]=a[8],b[9]=a[9],b[10]=a[10],b[11]=a[11],b[12]=a[12],b[13]=a[13],b[14]=a[14],b[15]=a[15]);return b};
  1686. mat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=a[12];b[13]=a[13];b[14]=a[14];b[15]=a[15];return b};mat4.identity=function(a){a[0]=1;a[1]=0;a[2]=0;a[3]=0;a[4]=0;a[5]=1;a[6]=0;a[7]=0;a[8]=0;a[9]=0;a[10]=1;a[11]=0;a[12]=0;a[13]=0;a[14]=0;a[15]=1;return a};
  1687. mat4.transpose=function(a,b){if(!b||a===b){var c=a[1],d=a[2],e=a[3],g=a[6],f=a[7],h=a[11];a[1]=a[4];a[2]=a[8];a[3]=a[12];a[4]=c;a[6]=a[9];a[7]=a[13];a[8]=d;a[9]=g;a[11]=a[14];a[12]=e;a[13]=f;a[14]=h;return a}b[0]=a[0];b[1]=a[4];b[2]=a[8];b[3]=a[12];b[4]=a[1];b[5]=a[5];b[6]=a[9];b[7]=a[13];b[8]=a[2];b[9]=a[6];b[10]=a[10];b[11]=a[14];b[12]=a[3];b[13]=a[7];b[14]=a[11];b[15]=a[15];return b};
  1688. mat4.determinant=function(a){var b=a[0],c=a[1],d=a[2],e=a[3],g=a[4],f=a[5],h=a[6],i=a[7],j=a[8],k=a[9],l=a[10],n=a[11],o=a[12],m=a[13],p=a[14],a=a[15];return o*k*h*e-j*m*h*e-o*f*l*e+g*m*l*e+j*f*p*e-g*k*p*e-o*k*d*i+j*m*d*i+o*c*l*i-b*m*l*i-j*c*p*i+b*k*p*i+o*f*d*n-g*m*d*n-o*c*h*n+b*m*h*n+g*c*p*n-b*f*p*n-j*f*d*a+g*k*d*a+j*c*h*a-b*k*h*a-g*c*l*a+b*f*l*a};
  1689. mat4.inverse=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=a[3],f=a[4],h=a[5],i=a[6],j=a[7],k=a[8],l=a[9],n=a[10],o=a[11],m=a[12],p=a[13],r=a[14],s=a[15],A=c*h-d*f,B=c*i-e*f,t=c*j-g*f,u=d*i-e*h,v=d*j-g*h,w=e*j-g*i,x=k*p-l*m,y=k*r-n*m,z=k*s-o*m,C=l*r-n*p,D=l*s-o*p,E=n*s-o*r,q=1/(A*E-B*D+t*C+u*z-v*y+w*x);b[0]=(h*E-i*D+j*C)*q;b[1]=(-d*E+e*D-g*C)*q;b[2]=(p*w-r*v+s*u)*q;b[3]=(-l*w+n*v-o*u)*q;b[4]=(-f*E+i*z-j*y)*q;b[5]=(c*E-e*z+g*y)*q;b[6]=(-m*w+r*t-s*B)*q;b[7]=(k*w-n*t+o*B)*q;b[8]=(f*D-h*z+j*x)*q;
  1690. b[9]=(-c*D+d*z-g*x)*q;b[10]=(m*v-p*t+s*A)*q;b[11]=(-k*v+l*t-o*A)*q;b[12]=(-f*C+h*y-i*x)*q;b[13]=(c*C-d*y+e*x)*q;b[14]=(-m*u+p*B-r*A)*q;b[15]=(k*u-l*B+n*A)*q;return b};mat4.toRotationMat=function(a,b){b||(b=mat4.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];b[4]=a[4];b[5]=a[5];b[6]=a[6];b[7]=a[7];b[8]=a[8];b[9]=a[9];b[10]=a[10];b[11]=a[11];b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b};
  1691. mat4.toMat3=function(a,b){b||(b=mat3.create());b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[4];b[4]=a[5];b[5]=a[6];b[6]=a[8];b[7]=a[9];b[8]=a[10];return b};mat4.toInverseMat3=function(a,b){var c=a[0],d=a[1],e=a[2],g=a[4],f=a[5],h=a[6],i=a[8],j=a[9],k=a[10],l=k*f-h*j,n=-k*g+h*i,o=j*g-f*i,m=c*l+d*n+e*o;if(!m)return null;m=1/m;b||(b=mat3.create());b[0]=l*m;b[1]=(-k*d+e*j)*m;b[2]=(h*d-e*f)*m;b[3]=n*m;b[4]=(k*c-e*i)*m;b[5]=(-h*c+e*g)*m;b[6]=o*m;b[7]=(-j*c+d*i)*m;b[8]=(f*c-d*g)*m;return b};
  1692. mat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],g=a[2],f=a[3],h=a[4],i=a[5],j=a[6],k=a[7],l=a[8],n=a[9],o=a[10],m=a[11],p=a[12],r=a[13],s=a[14],a=a[15],A=b[0],B=b[1],t=b[2],u=b[3],v=b[4],w=b[5],x=b[6],y=b[7],z=b[8],C=b[9],D=b[10],E=b[11],q=b[12],F=b[13],G=b[14],b=b[15];c[0]=A*d+B*h+t*l+u*p;c[1]=A*e+B*i+t*n+u*r;c[2]=A*g+B*j+t*o+u*s;c[3]=A*f+B*k+t*m+u*a;c[4]=v*d+w*h+x*l+y*p;c[5]=v*e+w*i+x*n+y*r;c[6]=v*g+w*j+x*o+y*s;c[7]=v*f+w*k+x*m+y*a;c[8]=z*d+C*h+D*l+E*p;c[9]=z*e+C*i+D*n+E*r;c[10]=z*g+C*
  1693. j+D*o+E*s;c[11]=z*f+C*k+D*m+E*a;c[12]=q*d+F*h+G*l+b*p;c[13]=q*e+F*i+G*n+b*r;c[14]=q*g+F*j+G*o+b*s;c[15]=q*f+F*k+G*m+b*a;return c};mat4.multiplyVec3=function(a,b,c){c||(c=b);var d=b[0],e=b[1],b=b[2];c[0]=a[0]*d+a[4]*e+a[8]*b+a[12];c[1]=a[1]*d+a[5]*e+a[9]*b+a[13];c[2]=a[2]*d+a[6]*e+a[10]*b+a[14];return c};
  1694. mat4.multiplyVec4=function(a,b,c){c||(c=b);var d=b[0],e=b[1],g=b[2],b=b[3];c[0]=a[0]*d+a[4]*e+a[8]*g+a[12]*b;c[1]=a[1]*d+a[5]*e+a[9]*g+a[13]*b;c[2]=a[2]*d+a[6]*e+a[10]*g+a[14]*b;c[3]=a[3]*d+a[7]*e+a[11]*g+a[15]*b;return c};
  1695. mat4.translate=function(a,b,c){var d=b[0],e=b[1],b=b[2],g,f,h,i,j,k,l,n,o,m,p,r;if(!c||a===c)return a[12]=a[0]*d+a[4]*e+a[8]*b+a[12],a[13]=a[1]*d+a[5]*e+a[9]*b+a[13],a[14]=a[2]*d+a[6]*e+a[10]*b+a[14],a[15]=a[3]*d+a[7]*e+a[11]*b+a[15],a;g=a[0];f=a[1];h=a[2];i=a[3];j=a[4];k=a[5];l=a[6];n=a[7];o=a[8];m=a[9];p=a[10];r=a[11];c[0]=g;c[1]=f;c[2]=h;c[3]=i;c[4]=j;c[5]=k;c[6]=l;c[7]=n;c[8]=o;c[9]=m;c[10]=p;c[11]=r;c[12]=g*d+j*e+o*b+a[12];c[13]=f*d+k*e+m*b+a[13];c[14]=h*d+l*e+p*b+a[14];c[15]=i*d+n*e+r*b+a[15];
  1696. return c};mat4.scale=function(a,b,c){var d=b[0],e=b[1],b=b[2];if(!c||a===c)return a[0]*=d,a[1]*=d,a[2]*=d,a[3]*=d,a[4]*=e,a[5]*=e,a[6]*=e,a[7]*=e,a[8]*=b,a[9]*=b,a[10]*=b,a[11]*=b,a;c[0]=a[0]*d;c[1]=a[1]*d;c[2]=a[2]*d;c[3]=a[3]*d;c[4]=a[4]*e;c[5]=a[5]*e;c[6]=a[6]*e;c[7]=a[7]*e;c[8]=a[8]*b;c[9]=a[9]*b;c[10]=a[10]*b;c[11]=a[11]*b;c[12]=a[12];c[13]=a[13];c[14]=a[14];c[15]=a[15];return c};
  1697. mat4.rotate=function(a,b,c,d){var e=c[0],g=c[1],c=c[2],f=Math.sqrt(e*e+g*g+c*c),h,i,j,k,l,n,o,m,p,r,s,A,B,t,u,v,w,x,y,z;if(!f)return null;f!==1&&(f=1/f,e*=f,g*=f,c*=f);h=Math.sin(b);i=Math.cos(b);j=1-i;b=a[0];f=a[1];k=a[2];l=a[3];n=a[4];o=a[5];m=a[6];p=a[7];r=a[8];s=a[9];A=a[10];B=a[11];t=e*e*j+i;u=g*e*j+c*h;v=c*e*j-g*h;w=e*g*j-c*h;x=g*g*j+i;y=c*g*j+e*h;z=e*c*j+g*h;e=g*c*j-e*h;g=c*c*j+i;d?a!==d&&(d[12]=a[12],d[13]=a[13],d[14]=a[14],d[15]=a[15]):d=a;d[0]=b*t+n*u+r*v;d[1]=f*t+o*u+s*v;d[2]=k*t+m*u+A*
  1698. v;d[3]=l*t+p*u+B*v;d[4]=b*w+n*x+r*y;d[5]=f*w+o*x+s*y;d[6]=k*w+m*x+A*y;d[7]=l*w+p*x+B*y;d[8]=b*z+n*e+r*g;d[9]=f*z+o*e+s*g;d[10]=k*z+m*e+A*g;d[11]=l*z+p*e+B*g;return d};mat4.rotateX=function(a,b,c){var d=Math.sin(b),b=Math.cos(b),e=a[4],g=a[5],f=a[6],h=a[7],i=a[8],j=a[9],k=a[10],l=a[11];c?a!==c&&(c[0]=a[0],c[1]=a[1],c[2]=a[2],c[3]=a[3],c[12]=a[12],c[13]=a[13],c[14]=a[14],c[15]=a[15]):c=a;c[4]=e*b+i*d;c[5]=g*b+j*d;c[6]=f*b+k*d;c[7]=h*b+l*d;c[8]=e*-d+i*b;c[9]=g*-d+j*b;c[10]=f*-d+k*b;c[11]=h*-d+l*b;return c};
  1699. mat4.rotateY=function(a,b,c){var d=Math.sin(b),b=Math.cos(b),e=a[0],g=a[1],f=a[2],h=a[3],i=a[8],j=a[9],k=a[10],l=a[11];c?a!==c&&(c[4]=a[4],c[5]=a[5],c[6]=a[6],c[7]=a[7],c[12]=a[12],c[13]=a[13],c[14]=a[14],c[15]=a[15]):c=a;c[0]=e*b+i*-d;c[1]=g*b+j*-d;c[2]=f*b+k*-d;c[3]=h*b+l*-d;c[8]=e*d+i*b;c[9]=g*d+j*b;c[10]=f*d+k*b;c[11]=h*d+l*b;return c};
  1700. mat4.rotateZ=function(a,b,c){var d=Math.sin(b),b=Math.cos(b),e=a[0],g=a[1],f=a[2],h=a[3],i=a[4],j=a[5],k=a[6],l=a[7];c?a!==c&&(c[8]=a[8],c[9]=a[9],c[10]=a[10],c[11]=a[11],c[12]=a[12],c[13]=a[13],c[14]=a[14],c[15]=a[15]):c=a;c[0]=e*b+i*d;c[1]=g*b+j*d;c[2]=f*b+k*d;c[3]=h*b+l*d;c[4]=e*-d+i*b;c[5]=g*-d+j*b;c[6]=f*-d+k*b;c[7]=h*-d+l*b;return c};
  1701. mat4.frustum=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=e*2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=e*2/i;f[6]=0;f[7]=0;f[8]=(b+a)/h;f[9]=(d+c)/i;f[10]=-(g+e)/j;f[11]=-1;f[12]=0;f[13]=0;f[14]=-(g*e*2)/j;f[15]=0;return f};mat4.perspective=function(a,b,c,d,e){a=c*Math.tan(a*Math.PI/360);b*=a;return mat4.frustum(-b,b,-a,a,c,d,e)};
  1702. mat4.ortho=function(a,b,c,d,e,g,f){f||(f=mat4.create());var h=b-a,i=d-c,j=g-e;f[0]=2/h;f[1]=0;f[2]=0;f[3]=0;f[4]=0;f[5]=2/i;f[6]=0;f[7]=0;f[8]=0;f[9]=0;f[10]=-2/j;f[11]=0;f[12]=-(a+b)/h;f[13]=-(d+c)/i;f[14]=-(g+e)/j;f[15]=1;return f};
  1703. mat4.lookAt=function(a,b,c,d){d||(d=mat4.create());var e,g,f,h,i,j,k,l,n=a[0],o=a[1],a=a[2];g=c[0];f=c[1];e=c[2];c=b[1];j=b[2];if(n===b[0]&&o===c&&a===j)return mat4.identity(d);c=n-b[0];j=o-b[1];k=a-b[2];l=1/Math.sqrt(c*c+j*j+k*k);c*=l;j*=l;k*=l;b=f*k-e*j;e=e*c-g*k;g=g*j-f*c;(l=Math.sqrt(b*b+e*e+g*g))?(l=1/l,b*=l,e*=l,g*=l):g=e=b=0;f=j*g-k*e;h=k*b-c*g;i=c*e-j*b;(l=Math.sqrt(f*f+h*h+i*i))?(l=1/l,f*=l,h*=l,i*=l):i=h=f=0;d[0]=b;d[1]=f;d[2]=c;d[3]=0;d[4]=e;d[5]=h;d[6]=j;d[7]=0;d[8]=g;d[9]=i;d[10]=k;d[11]=
  1704. 0;d[12]=-(b*n+e*o+g*a);d[13]=-(f*n+h*o+i*a);d[14]=-(c*n+j*o+k*a);d[15]=1;return d};mat4.fromRotationTranslation=function(a,b,c){c||(c=mat4.create());var d=a[0],e=a[1],g=a[2],f=a[3],h=d+d,i=e+e,j=g+g,a=d*h,k=d*i;d*=j;var l=e*i;e*=j;g*=j;h*=f;i*=f;f*=j;c[0]=1-(l+g);c[1]=k+f;c[2]=d-i;c[3]=0;c[4]=k-f;c[5]=1-(a+g);c[6]=e+h;c[7]=0;c[8]=d+i;c[9]=e-h;c[10]=1-(a+l);c[11]=0;c[12]=b[0];c[13]=b[1];c[14]=b[2];c[15]=1;return c};
  1705. mat4.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+", "+a[4]+", "+a[5]+", "+a[6]+", "+a[7]+", "+a[8]+", "+a[9]+", "+a[10]+", "+a[11]+", "+a[12]+", "+a[13]+", "+a[14]+", "+a[15]+"]"};quat4.create=function(a){var b=new MatrixArray(4);a&&(b[0]=a[0],b[1]=a[1],b[2]=a[2],b[3]=a[3]);return b};quat4.set=function(a,b){b[0]=a[0];b[1]=a[1];b[2]=a[2];b[3]=a[3];return b};
  1706. quat4.calculateW=function(a,b){var c=a[0],d=a[1],e=a[2];if(!b||a===b)return a[3]=-Math.sqrt(Math.abs(1-c*c-d*d-e*e)),a;b[0]=c;b[1]=d;b[2]=e;b[3]=-Math.sqrt(Math.abs(1-c*c-d*d-e*e));return b};quat4.inverse=function(a,b){if(!b||a===b)return a[0]*=-1,a[1]*=-1,a[2]*=-1,a;b[0]=-a[0];b[1]=-a[1];b[2]=-a[2];b[3]=a[3];return b};quat4.length=function(a){var b=a[0],c=a[1],d=a[2],a=a[3];return Math.sqrt(b*b+c*c+d*d+a*a)};
  1707. quat4.normalize=function(a,b){b||(b=a);var c=a[0],d=a[1],e=a[2],g=a[3],f=Math.sqrt(c*c+d*d+e*e+g*g);if(f===0)return b[0]=0,b[1]=0,b[2]=0,b[3]=0,b;f=1/f;b[0]=c*f;b[1]=d*f;b[2]=e*f;b[3]=g*f;return b};quat4.multiply=function(a,b,c){c||(c=a);var d=a[0],e=a[1],g=a[2],a=a[3],f=b[0],h=b[1],i=b[2],b=b[3];c[0]=d*b+a*f+e*i-g*h;c[1]=e*b+a*h+g*f-d*i;c[2]=g*b+a*i+d*h-e*f;c[3]=a*b-d*f-e*h-g*i;return c};
  1708. quat4.multiplyVec3=function(a,b,c){c||(c=b);var d=b[0],e=b[1],g=b[2],b=a[0],f=a[1],h=a[2],a=a[3],i=a*d+f*g-h*e,j=a*e+h*d-b*g,k=a*g+b*e-f*d,d=-b*d-f*e-h*g;c[0]=i*a+d*-b+j*-h-k*-f;c[1]=j*a+d*-f+k*-b-i*-h;c[2]=k*a+d*-h+i*-f-j*-b;return c};quat4.toMat3=function(a,b){b||(b=mat3.create());var c=a[0],d=a[1],e=a[2],g=a[3],f=c+c,h=d+d,i=e+e,j=c*f,k=c*h;c*=i;var l=d*h;d*=i;e*=i;f*=g;h*=g;g*=i;b[0]=1-(l+e);b[1]=k+g;b[2]=c-h;b[3]=k-g;b[4]=1-(j+e);b[5]=d+f;b[6]=c+h;b[7]=d-f;b[8]=1-(j+l);return b};
  1709. quat4.toMat4=function(a,b){b||(b=mat4.create());var c=a[0],d=a[1],e=a[2],g=a[3],f=c+c,h=d+d,i=e+e,j=c*f,k=c*h;c*=i;var l=d*h;d*=i;e*=i;f*=g;h*=g;g*=i;b[0]=1-(l+e);b[1]=k+g;b[2]=c-h;b[3]=0;b[4]=k-g;b[5]=1-(j+e);b[6]=d+f;b[7]=0;b[8]=c+h;b[9]=d-f;b[10]=1-(j+l);b[11]=0;b[12]=0;b[13]=0;b[14]=0;b[15]=1;return b};
  1710. quat4.slerp=function(a,b,c,d){d||(d=a);var e=a[0]*b[0]+a[1]*b[1]+a[2]*b[2]+a[3]*b[3],g,f;if(Math.abs(e)>=1)return d!==a&&(d[0]=a[0],d[1]=a[1],d[2]=a[2],d[3]=a[3]),d;g=Math.acos(e);f=Math.sqrt(1-e*e);if(Math.abs(f)<0.001)return d[0]=a[0]*0.5+b[0]*0.5,d[1]=a[1]*0.5+b[1]*0.5,d[2]=a[2]*0.5+b[2]*0.5,d[3]=a[3]*0.5+b[3]*0.5,d;e=Math.sin((1-c)*g)/f;c=Math.sin(c*g)/f;d[0]=a[0]*e+b[0]*c;d[1]=a[1]*e+b[1]*c;d[2]=a[2]*e+b[2]*c;d[3]=a[3]*e+b[3]*c;return d};
  1711. quat4.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+"]"};
  1712. (function()
  1713. {
  1714. var MAX_VERTICES = 8000; // equates to 2500 objects being drawn
  1715. var MAX_INDICES = (MAX_VERTICES / 2) * 3; // 6 indices for every 4 vertices
  1716. var MAX_POINTS = 8000;
  1717. var MULTI_BUFFERS = 4; // cycle 4 buffers to try and avoid blocking
  1718. var BATCH_NULL = 0;
  1719. var BATCH_QUAD = 1;
  1720. var BATCH_SETTEXTURE = 2;
  1721. var BATCH_SETOPACITY = 3;
  1722. var BATCH_SETBLEND = 4;
  1723. var BATCH_UPDATEMODELVIEW = 5;
  1724. var BATCH_RENDERTOTEXTURE = 6;
  1725. var BATCH_CLEAR = 7;
  1726. var BATCH_POINTS = 8;
  1727. var BATCH_SETPROGRAM = 9;
  1728. var BATCH_SETPROGRAMPARAMETERS = 10;
  1729. var BATCH_SETTEXTURE1 = 11;
  1730. var BATCH_SETCOLOR = 12;
  1731. var BATCH_SETDEPTHTEST = 13;
  1732. var BATCH_SETEARLYZMODE = 14;
  1733. /*
  1734. var lose_ext = null;
  1735. window.lose_context = function ()
  1736. {
  1737. if (!lose_ext)
  1738. {
  1739. console.log("WEBGL_lose_context not supported");
  1740. return;
  1741. }
  1742. lose_ext.loseContext();
  1743. };
  1744. window.restore_context = function ()
  1745. {
  1746. if (!lose_ext)
  1747. {
  1748. console.log("WEBGL_lose_context not supported");
  1749. return;
  1750. }
  1751. lose_ext.restoreContext();
  1752. };
  1753. */
  1754. var tempMat4 = mat4.create();
  1755. function GLWrap_(gl, isMobile, enableFrontToBack)
  1756. {
  1757. this.isIE = /msie/i.test(navigator.userAgent) || /trident/i.test(navigator.userAgent);
  1758. this.width = 0; // not yet known, wait for call to setSize()
  1759. this.height = 0;
  1760. this.enableFrontToBack = !!enableFrontToBack;
  1761. this.isEarlyZPass = false;
  1762. this.isBatchInEarlyZPass = false;
  1763. this.currentZ = 0;
  1764. this.zNear = 1;
  1765. this.zFar = 1000;
  1766. this.zIncrement = ((this.zFar - this.zNear) / 32768);
  1767. this.zA = this.zFar / (this.zFar - this.zNear);
  1768. this.zB = this.zFar * this.zNear / (this.zNear - this.zFar);
  1769. this.kzA = 65536 * this.zA;
  1770. this.kzB = 65536 * this.zB;
  1771. this.cam = vec3.create([0, 0, 100]); // camera position
  1772. this.look = vec3.create([0, 0, 0]); // lookat position
  1773. this.up = vec3.create([0, 1, 0]); // up vector
  1774. this.worldScale = vec3.create([1, 1, 1]); // world scaling factor
  1775. this.enable_mipmaps = true;
  1776. this.matP = mat4.create(); // perspective matrix
  1777. this.matMV = mat4.create(); // model view matrix
  1778. this.lastMV = mat4.create();
  1779. this.currentMV = mat4.create();
  1780. this.gl = gl;
  1781. this.version = (this.gl.getParameter(this.gl.VERSION).indexOf("WebGL 2") === 0 ? 2 : 1);
  1782. this.initState();
  1783. };
  1784. GLWrap_.prototype.initState = function ()
  1785. {
  1786. var gl = this.gl;
  1787. var i, len;
  1788. this.lastOpacity = 1;
  1789. this.lastTexture0 = null; // last bound to TEXTURE0
  1790. this.lastTexture1 = null; // last bound to TEXTURE1
  1791. this.currentOpacity = 1;
  1792. gl.clearColor(0, 0, 0, 0);
  1793. gl.clear(gl.COLOR_BUFFER_BIT);
  1794. gl.enable(gl.BLEND);
  1795. gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
  1796. gl.disable(gl.CULL_FACE);
  1797. gl.disable(gl.STENCIL_TEST);
  1798. gl.disable(gl.DITHER);
  1799. if (this.enableFrontToBack)
  1800. {
  1801. gl.enable(gl.DEPTH_TEST);
  1802. gl.depthFunc(gl.LEQUAL);
  1803. }
  1804. else
  1805. {
  1806. gl.disable(gl.DEPTH_TEST);
  1807. }
  1808. this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
  1809. this.lastSrcBlend = gl.ONE;
  1810. this.lastDestBlend = gl.ONE_MINUS_SRC_ALPHA;
  1811. this.vertexData = new Float32Array(MAX_VERTICES * (this.enableFrontToBack ? 3 : 2));
  1812. this.texcoordData = new Float32Array(MAX_VERTICES * 2);
  1813. this.pointData = new Float32Array(MAX_POINTS * 4);
  1814. this.pointBuffer = gl.createBuffer();
  1815. gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
  1816. gl.bufferData(gl.ARRAY_BUFFER, this.pointData.byteLength, gl.DYNAMIC_DRAW);
  1817. this.vertexBuffers = new Array(MULTI_BUFFERS);
  1818. this.texcoordBuffers = new Array(MULTI_BUFFERS);
  1819. for (i = 0; i < MULTI_BUFFERS; i++)
  1820. {
  1821. this.vertexBuffers[i] = gl.createBuffer();
  1822. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffers[i]);
  1823. gl.bufferData(gl.ARRAY_BUFFER, this.vertexData.byteLength, gl.DYNAMIC_DRAW);
  1824. this.texcoordBuffers[i] = gl.createBuffer();
  1825. gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffers[i]);
  1826. gl.bufferData(gl.ARRAY_BUFFER, this.texcoordData.byteLength, gl.DYNAMIC_DRAW);
  1827. }
  1828. this.curBuffer = 0;
  1829. this.indexBuffer = gl.createBuffer();
  1830. gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer);
  1831. var indexData = new Uint16Array(MAX_INDICES);
  1832. i = 0, len = MAX_INDICES;
  1833. var fv = 0;
  1834. while (i < len)
  1835. {
  1836. indexData[i++] = fv; // top left
  1837. indexData[i++] = fv + 1; // top right
  1838. indexData[i++] = fv + 2; // bottom right (first tri)
  1839. indexData[i++] = fv; // top left
  1840. indexData[i++] = fv + 2; // bottom right
  1841. indexData[i++] = fv + 3; // bottom left
  1842. fv += 4;
  1843. }
  1844. gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW);
  1845. this.vertexPtr = 0;
  1846. this.texPtr = 0;
  1847. this.pointPtr = 0;
  1848. var fsSource, vsSource;
  1849. this.shaderPrograms = [];
  1850. fsSource = [
  1851. "varying mediump vec2 vTex;",
  1852. "uniform lowp float opacity;",
  1853. "uniform lowp sampler2D samplerFront;",
  1854. "void main(void) {",
  1855. " gl_FragColor = texture2D(samplerFront, vTex);",
  1856. " gl_FragColor *= opacity;",
  1857. "}"
  1858. ].join("\n");
  1859. if (this.enableFrontToBack)
  1860. {
  1861. vsSource = [
  1862. "attribute highp vec3 aPos;",
  1863. "attribute mediump vec2 aTex;",
  1864. "varying mediump vec2 vTex;",
  1865. "uniform highp mat4 matP;",
  1866. "uniform highp mat4 matMV;",
  1867. "void main(void) {",
  1868. " gl_Position = matP * matMV * vec4(aPos.x, aPos.y, aPos.z, 1.0);",
  1869. " vTex = aTex;",
  1870. "}"
  1871. ].join("\n");
  1872. }
  1873. else
  1874. {
  1875. vsSource = [
  1876. "attribute highp vec2 aPos;",
  1877. "attribute mediump vec2 aTex;",
  1878. "varying mediump vec2 vTex;",
  1879. "uniform highp mat4 matP;",
  1880. "uniform highp mat4 matMV;",
  1881. "void main(void) {",
  1882. " gl_Position = matP * matMV * vec4(aPos.x, aPos.y, 0.0, 1.0);",
  1883. " vTex = aTex;",
  1884. "}"
  1885. ].join("\n");
  1886. }
  1887. var shaderProg = this.createShaderProgram({src: fsSource}, vsSource, "<default>");
  1888. ;
  1889. this.shaderPrograms.push(shaderProg); // Default shader is always shader 0
  1890. fsSource = [
  1891. "uniform mediump sampler2D samplerFront;",
  1892. "varying lowp float opacity;",
  1893. "void main(void) {",
  1894. " gl_FragColor = texture2D(samplerFront, gl_PointCoord);",
  1895. " gl_FragColor *= opacity;",
  1896. "}"
  1897. ].join("\n");
  1898. var pointVsSource = [
  1899. "attribute vec4 aPos;",
  1900. "varying float opacity;",
  1901. "uniform mat4 matP;",
  1902. "uniform mat4 matMV;",
  1903. "void main(void) {",
  1904. " gl_Position = matP * matMV * vec4(aPos.x, aPos.y, 0.0, 1.0);",
  1905. " gl_PointSize = aPos.z;",
  1906. " opacity = aPos.w;",
  1907. "}"
  1908. ].join("\n");
  1909. shaderProg = this.createShaderProgram({src: fsSource}, pointVsSource, "<point>");
  1910. ;
  1911. this.shaderPrograms.push(shaderProg); // Point shader is always shader 1
  1912. fsSource = [
  1913. "varying mediump vec2 vTex;",
  1914. "uniform lowp sampler2D samplerFront;",
  1915. "void main(void) {",
  1916. " if (texture2D(samplerFront, vTex).a < 1.0)",
  1917. " discard;", // discarding non-opaque fragments
  1918. "}"
  1919. ].join("\n");
  1920. var shaderProg = this.createShaderProgram({src: fsSource}, vsSource, "<earlyz>");
  1921. ;
  1922. this.shaderPrograms.push(shaderProg); // Early-Z shader is always shader 2
  1923. fsSource = [
  1924. "uniform lowp vec4 colorFill;",
  1925. "void main(void) {",
  1926. " gl_FragColor = colorFill;",
  1927. "}"
  1928. ].join("\n");
  1929. var shaderProg = this.createShaderProgram({src: fsSource}, vsSource, "<fill>");
  1930. ;
  1931. this.shaderPrograms.push(shaderProg); // Fill-color shader is always shader 3
  1932. for (var shader_name in cr.shaders)
  1933. {
  1934. if (cr.shaders.hasOwnProperty(shader_name))
  1935. this.shaderPrograms.push(this.createShaderProgram(cr.shaders[shader_name], vsSource, shader_name));
  1936. }
  1937. gl.activeTexture(gl.TEXTURE0);
  1938. gl.bindTexture(gl.TEXTURE_2D, null);
  1939. this.batch = [];
  1940. this.batchPtr = 0;
  1941. this.hasQuadBatchTop = false;
  1942. this.hasPointBatchTop = false;
  1943. this.lastProgram = -1; // start -1 so first switchProgram can do work
  1944. this.currentProgram = -1; // current program during batch execution
  1945. this.currentShader = null;
  1946. this.fbo = gl.createFramebuffer();
  1947. this.renderToTex = null;
  1948. this.depthBuffer = null;
  1949. this.attachedDepthBuffer = false; // wait until first size call to attach, otherwise it has no storage
  1950. if (this.enableFrontToBack)
  1951. {
  1952. this.depthBuffer = gl.createRenderbuffer();
  1953. }
  1954. this.tmpVec3 = vec3.create([0, 0, 0]);
  1955. ;
  1956. var pointsizes = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE);
  1957. this.minPointSize = pointsizes[0];
  1958. this.maxPointSize = pointsizes[1];
  1959. if (this.maxPointSize > 2048)
  1960. this.maxPointSize = 2048;
  1961. ;
  1962. this.switchProgram(0);
  1963. cr.seal(this);
  1964. };
  1965. function GLShaderProgram(gl, shaderProgram, name)
  1966. {
  1967. this.gl = gl;
  1968. this.shaderProgram = shaderProgram;
  1969. this.name = name;
  1970. this.locAPos = gl.getAttribLocation(shaderProgram, "aPos");
  1971. this.locATex = gl.getAttribLocation(shaderProgram, "aTex");
  1972. this.locMatP = gl.getUniformLocation(shaderProgram, "matP");
  1973. this.locMatMV = gl.getUniformLocation(shaderProgram, "matMV");
  1974. this.locOpacity = gl.getUniformLocation(shaderProgram, "opacity");
  1975. this.locColorFill = gl.getUniformLocation(shaderProgram, "colorFill");
  1976. this.locSamplerFront = gl.getUniformLocation(shaderProgram, "samplerFront");
  1977. this.locSamplerBack = gl.getUniformLocation(shaderProgram, "samplerBack");
  1978. this.locDestStart = gl.getUniformLocation(shaderProgram, "destStart");
  1979. this.locDestEnd = gl.getUniformLocation(shaderProgram, "destEnd");
  1980. this.locSeconds = gl.getUniformLocation(shaderProgram, "seconds");
  1981. this.locPixelWidth = gl.getUniformLocation(shaderProgram, "pixelWidth");
  1982. this.locPixelHeight = gl.getUniformLocation(shaderProgram, "pixelHeight");
  1983. this.locLayerScale = gl.getUniformLocation(shaderProgram, "layerScale");
  1984. this.locLayerAngle = gl.getUniformLocation(shaderProgram, "layerAngle");
  1985. this.locViewOrigin = gl.getUniformLocation(shaderProgram, "viewOrigin");
  1986. this.locScrollPos = gl.getUniformLocation(shaderProgram, "scrollPos");
  1987. this.hasAnyOptionalUniforms = !!(this.locPixelWidth || this.locPixelHeight || this.locSeconds || this.locSamplerBack || this.locDestStart || this.locDestEnd || this.locLayerScale || this.locLayerAngle || this.locViewOrigin || this.locScrollPos);
  1988. this.lpPixelWidth = -999; // set to something unlikely so never counts as cached on first set
  1989. this.lpPixelHeight = -999;
  1990. this.lpOpacity = 1;
  1991. this.lpDestStartX = 0.0;
  1992. this.lpDestStartY = 0.0;
  1993. this.lpDestEndX = 1.0;
  1994. this.lpDestEndY = 1.0;
  1995. this.lpLayerScale = 1.0;
  1996. this.lpLayerAngle = 0.0;
  1997. this.lpViewOriginX = 0.0;
  1998. this.lpViewOriginY = 0.0;
  1999. this.lpScrollPosX = 0.0;
  2000. this.lpScrollPosY = 0.0;
  2001. this.lpSeconds = 0.0;
  2002. this.lastCustomParams = [];
  2003. this.lpMatMV = mat4.create();
  2004. if (this.locOpacity)
  2005. gl.uniform1f(this.locOpacity, 1);
  2006. if (this.locColorFill)
  2007. gl.uniform4f(this.locColorFill, 1.0, 1.0, 1.0, 1.0);
  2008. if (this.locSamplerFront)
  2009. gl.uniform1i(this.locSamplerFront, 0);
  2010. if (this.locSamplerBack)
  2011. gl.uniform1i(this.locSamplerBack, 1);
  2012. if (this.locDestStart)
  2013. gl.uniform2f(this.locDestStart, 0.0, 0.0);
  2014. if (this.locDestEnd)
  2015. gl.uniform2f(this.locDestEnd, 1.0, 1.0);
  2016. if (this.locLayerScale)
  2017. gl.uniform1f(this.locLayerScale, 1.0);
  2018. if (this.locLayerAngle)
  2019. gl.uniform1f(this.locLayerAngle, 0.0);
  2020. if (this.locViewOrigin)
  2021. gl.uniform2f(this.locViewOrigin, 0.0, 0.0);
  2022. if (this.locScrollPos)
  2023. gl.uniform2f(this.locScrollPos, 0.0, 0.0);
  2024. if (this.locSeconds)
  2025. gl.uniform1f(this.locSeconds, 0.0);
  2026. this.hasCurrentMatMV = false; // matMV needs updating
  2027. };
  2028. function areMat4sEqual(a, b)
  2029. {
  2030. return a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&&
  2031. a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&&
  2032. a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&&
  2033. a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15];
  2034. };
  2035. GLShaderProgram.prototype.updateMatMV = function (mv)
  2036. {
  2037. if (areMat4sEqual(this.lpMatMV, mv))
  2038. return; // no change, save the expensive GL call
  2039. mat4.set(mv, this.lpMatMV);
  2040. this.gl.uniformMatrix4fv(this.locMatMV, false, mv);
  2041. };
  2042. GLWrap_.prototype.createShaderProgram = function(shaderEntry, vsSource, name)
  2043. {
  2044. var gl = this.gl;
  2045. var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
  2046. gl.shaderSource(fragmentShader, shaderEntry.src);
  2047. gl.compileShader(fragmentShader);
  2048. if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS))
  2049. {
  2050. var compilationlog = gl.getShaderInfoLog(fragmentShader);
  2051. gl.deleteShader(fragmentShader);
  2052. throw new Error("error compiling fragment shader: " + compilationlog);
  2053. }
  2054. var vertexShader = gl.createShader(gl.VERTEX_SHADER);
  2055. gl.shaderSource(vertexShader, vsSource);
  2056. gl.compileShader(vertexShader);
  2057. if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS))
  2058. {
  2059. var compilationlog = gl.getShaderInfoLog(vertexShader);
  2060. gl.deleteShader(fragmentShader);
  2061. gl.deleteShader(vertexShader);
  2062. throw new Error("error compiling vertex shader: " + compilationlog);
  2063. }
  2064. var shaderProgram = gl.createProgram();
  2065. gl.attachShader(shaderProgram, fragmentShader);
  2066. gl.attachShader(shaderProgram, vertexShader);
  2067. gl.linkProgram(shaderProgram);
  2068. if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS))
  2069. {
  2070. var compilationlog = gl.getProgramInfoLog(shaderProgram);
  2071. gl.deleteShader(fragmentShader);
  2072. gl.deleteShader(vertexShader);
  2073. gl.deleteProgram(shaderProgram);
  2074. throw new Error("error linking shader program: " + compilationlog);
  2075. }
  2076. gl.useProgram(shaderProgram);
  2077. gl.deleteShader(fragmentShader);
  2078. gl.deleteShader(vertexShader);
  2079. var ret = new GLShaderProgram(gl, shaderProgram, name);
  2080. ret.extendBoxHorizontal = shaderEntry.extendBoxHorizontal || 0;
  2081. ret.extendBoxVertical = shaderEntry.extendBoxVertical || 0;
  2082. ret.crossSampling = !!shaderEntry.crossSampling;
  2083. ret.preservesOpaqueness = !!shaderEntry.preservesOpaqueness;
  2084. ret.animated = !!shaderEntry.animated;
  2085. ret.parameters = shaderEntry.parameters || [];
  2086. var i, len;
  2087. for (i = 0, len = ret.parameters.length; i < len; i++)
  2088. {
  2089. ret.parameters[i][1] = gl.getUniformLocation(shaderProgram, ret.parameters[i][0]);
  2090. ret.lastCustomParams.push(0);
  2091. gl.uniform1f(ret.parameters[i][1], 0);
  2092. }
  2093. cr.seal(ret);
  2094. return ret;
  2095. };
  2096. GLWrap_.prototype.getShaderIndex = function(name_)
  2097. {
  2098. var i, len;
  2099. for (i = 0, len = this.shaderPrograms.length; i < len; i++)
  2100. {
  2101. if (this.shaderPrograms[i].name === name_)
  2102. return i;
  2103. }
  2104. return -1;
  2105. };
  2106. GLWrap_.prototype.project = function (x, y, out)
  2107. {
  2108. var mv = this.matMV;
  2109. var proj = this.matP;
  2110. var fTempo = [0, 0, 0, 0, 0, 0, 0, 0];
  2111. fTempo[0] = mv[0]*x+mv[4]*y+mv[12];
  2112. fTempo[1] = mv[1]*x+mv[5]*y+mv[13];
  2113. fTempo[2] = mv[2]*x+mv[6]*y+mv[14];
  2114. fTempo[3] = mv[3]*x+mv[7]*y+mv[15];
  2115. fTempo[4] = proj[0]*fTempo[0]+proj[4]*fTempo[1]+proj[8]*fTempo[2]+proj[12]*fTempo[3];
  2116. fTempo[5] = proj[1]*fTempo[0]+proj[5]*fTempo[1]+proj[9]*fTempo[2]+proj[13]*fTempo[3];
  2117. fTempo[6] = proj[2]*fTempo[0]+proj[6]*fTempo[1]+proj[10]*fTempo[2]+proj[14]*fTempo[3];
  2118. fTempo[7] = -fTempo[2];
  2119. if(fTempo[7]===0.0) //The w value
  2120. return;
  2121. fTempo[7]=1.0/fTempo[7];
  2122. fTempo[4]*=fTempo[7];
  2123. fTempo[5]*=fTempo[7];
  2124. fTempo[6]*=fTempo[7];
  2125. out[0]=(fTempo[4]*0.5+0.5)*this.width;
  2126. out[1]=(fTempo[5]*0.5+0.5)*this.height;
  2127. };
  2128. GLWrap_.prototype.setSize = function(w, h, force)
  2129. {
  2130. if (this.width === w && this.height === h && !force)
  2131. return;
  2132. this.endBatch();
  2133. var gl = this.gl;
  2134. this.width = w;
  2135. this.height = h;
  2136. gl.viewport(0, 0, w, h);
  2137. mat4.lookAt(this.cam, this.look, this.up, this.matMV);
  2138. if (this.enableFrontToBack)
  2139. {
  2140. mat4.ortho(-w/2, w/2, h/2, -h/2, this.zNear, this.zFar, this.matP);
  2141. this.worldScale[0] = 1;
  2142. this.worldScale[1] = 1;
  2143. }
  2144. else
  2145. {
  2146. mat4.perspective(45, w / h, this.zNear, this.zFar, this.matP);
  2147. var tl = [0, 0];
  2148. var br = [0, 0];
  2149. this.project(0, 0, tl);
  2150. this.project(1, 1, br);
  2151. this.worldScale[0] = 1 / (br[0] - tl[0]);
  2152. this.worldScale[1] = -1 / (br[1] - tl[1]);
  2153. }
  2154. var i, len, s;
  2155. for (i = 0, len = this.shaderPrograms.length; i < len; i++)
  2156. {
  2157. s = this.shaderPrograms[i];
  2158. s.hasCurrentMatMV = false;
  2159. if (s.locMatP)
  2160. {
  2161. gl.useProgram(s.shaderProgram);
  2162. gl.uniformMatrix4fv(s.locMatP, false, this.matP);
  2163. }
  2164. }
  2165. gl.useProgram(this.shaderPrograms[this.lastProgram].shaderProgram);
  2166. gl.bindTexture(gl.TEXTURE_2D, null);
  2167. gl.activeTexture(gl.TEXTURE1);
  2168. gl.bindTexture(gl.TEXTURE_2D, null);
  2169. gl.activeTexture(gl.TEXTURE0);
  2170. this.lastTexture0 = null;
  2171. this.lastTexture1 = null;
  2172. if (this.depthBuffer)
  2173. {
  2174. gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo);
  2175. gl.bindRenderbuffer(gl.RENDERBUFFER, this.depthBuffer);
  2176. gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.width, this.height);
  2177. if (!this.attachedDepthBuffer)
  2178. {
  2179. gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.depthBuffer);
  2180. this.attachedDepthBuffer = true;
  2181. }
  2182. gl.bindRenderbuffer(gl.RENDERBUFFER, null);
  2183. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  2184. this.renderToTex = null;
  2185. }
  2186. };
  2187. GLWrap_.prototype.resetModelView = function ()
  2188. {
  2189. mat4.lookAt(this.cam, this.look, this.up, this.matMV);
  2190. mat4.scale(this.matMV, this.worldScale);
  2191. };
  2192. GLWrap_.prototype.translate = function (x, y)
  2193. {
  2194. if (x === 0 && y === 0)
  2195. return;
  2196. this.tmpVec3[0] = x;// * this.worldScale[0];
  2197. this.tmpVec3[1] = y;// * this.worldScale[1];
  2198. this.tmpVec3[2] = 0;
  2199. mat4.translate(this.matMV, this.tmpVec3);
  2200. };
  2201. GLWrap_.prototype.scale = function (x, y)
  2202. {
  2203. if (x === 1 && y === 1)
  2204. return;
  2205. this.tmpVec3[0] = x;
  2206. this.tmpVec3[1] = y;
  2207. this.tmpVec3[2] = 1;
  2208. mat4.scale(this.matMV, this.tmpVec3);
  2209. };
  2210. GLWrap_.prototype.rotateZ = function (a)
  2211. {
  2212. if (a === 0)
  2213. return;
  2214. mat4.rotateZ(this.matMV, a);
  2215. };
  2216. GLWrap_.prototype.updateModelView = function()
  2217. {
  2218. if (areMat4sEqual(this.lastMV, this.matMV))
  2219. return;
  2220. var b = this.pushBatch();
  2221. b.type = BATCH_UPDATEMODELVIEW;
  2222. if (b.mat4param)
  2223. mat4.set(this.matMV, b.mat4param);
  2224. else
  2225. b.mat4param = mat4.create(this.matMV);
  2226. mat4.set(this.matMV, this.lastMV);
  2227. this.hasQuadBatchTop = false;
  2228. this.hasPointBatchTop = false;
  2229. };
  2230. /*
  2231. var debugBatch = false;
  2232. jQuery(document).mousedown(
  2233. function(info) {
  2234. if (info.which === 2)
  2235. debugBatch = true;
  2236. }
  2237. );
  2238. */
  2239. GLWrap_.prototype.setEarlyZIndex = function (i)
  2240. {
  2241. if (!this.enableFrontToBack)
  2242. return;
  2243. if (i > 32760)
  2244. i = 32760;
  2245. this.currentZ = this.cam[2] - this.zNear - i * this.zIncrement;
  2246. };
  2247. function GLBatchJob(type_, glwrap_)
  2248. {
  2249. this.type = type_;
  2250. this.glwrap = glwrap_;
  2251. this.gl = glwrap_.gl;
  2252. this.opacityParam = 0; // for setOpacity()
  2253. this.startIndex = 0; // for quad()
  2254. this.indexCount = 0; // "
  2255. this.texParam = null; // for setTexture()
  2256. this.mat4param = null; // for updateModelView()
  2257. this.shaderParams = []; // for user parameters
  2258. cr.seal(this);
  2259. };
  2260. GLBatchJob.prototype.doSetEarlyZPass = function ()
  2261. {
  2262. var gl = this.gl;
  2263. var glwrap = this.glwrap;
  2264. if (this.startIndex !== 0) // enable
  2265. {
  2266. gl.depthMask(true); // enable depth writes
  2267. gl.colorMask(false, false, false, false); // disable color writes
  2268. gl.disable(gl.BLEND); // no color writes so disable blend
  2269. gl.bindFramebuffer(gl.FRAMEBUFFER, glwrap.fbo);
  2270. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
  2271. gl.clear(gl.DEPTH_BUFFER_BIT); // auto-clear depth buffer
  2272. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  2273. glwrap.isBatchInEarlyZPass = true;
  2274. }
  2275. else
  2276. {
  2277. gl.depthMask(false); // disable depth writes, only test existing depth values
  2278. gl.colorMask(true, true, true, true); // enable color writes
  2279. gl.enable(gl.BLEND); // turn blending back on
  2280. glwrap.isBatchInEarlyZPass = false;
  2281. }
  2282. };
  2283. GLBatchJob.prototype.doSetTexture = function ()
  2284. {
  2285. this.gl.bindTexture(this.gl.TEXTURE_2D, this.texParam);
  2286. };
  2287. GLBatchJob.prototype.doSetTexture1 = function ()
  2288. {
  2289. var gl = this.gl;
  2290. gl.activeTexture(gl.TEXTURE1);
  2291. gl.bindTexture(gl.TEXTURE_2D, this.texParam);
  2292. gl.activeTexture(gl.TEXTURE0);
  2293. };
  2294. GLBatchJob.prototype.doSetOpacity = function ()
  2295. {
  2296. var o = this.opacityParam;
  2297. var glwrap = this.glwrap;
  2298. glwrap.currentOpacity = o;
  2299. var curProg = glwrap.currentShader;
  2300. if (curProg.locOpacity && curProg.lpOpacity !== o)
  2301. {
  2302. curProg.lpOpacity = o;
  2303. this.gl.uniform1f(curProg.locOpacity, o);
  2304. }
  2305. };
  2306. GLBatchJob.prototype.doQuad = function ()
  2307. {
  2308. this.gl.drawElements(this.gl.TRIANGLES, this.indexCount, this.gl.UNSIGNED_SHORT, this.startIndex);
  2309. };
  2310. GLBatchJob.prototype.doSetBlend = function ()
  2311. {
  2312. this.gl.blendFunc(this.startIndex, this.indexCount);
  2313. };
  2314. GLBatchJob.prototype.doUpdateModelView = function ()
  2315. {
  2316. var i, len, s, shaderPrograms = this.glwrap.shaderPrograms, currentProgram = this.glwrap.currentProgram;
  2317. for (i = 0, len = shaderPrograms.length; i < len; i++)
  2318. {
  2319. s = shaderPrograms[i];
  2320. if (i === currentProgram && s.locMatMV)
  2321. {
  2322. s.updateMatMV(this.mat4param);
  2323. s.hasCurrentMatMV = true;
  2324. }
  2325. else
  2326. s.hasCurrentMatMV = false;
  2327. }
  2328. mat4.set(this.mat4param, this.glwrap.currentMV);
  2329. };
  2330. GLBatchJob.prototype.doRenderToTexture = function ()
  2331. {
  2332. var gl = this.gl;
  2333. var glwrap = this.glwrap;
  2334. if (this.texParam)
  2335. {
  2336. if (glwrap.lastTexture1 === this.texParam)
  2337. {
  2338. gl.activeTexture(gl.TEXTURE1);
  2339. gl.bindTexture(gl.TEXTURE_2D, null);
  2340. glwrap.lastTexture1 = null;
  2341. gl.activeTexture(gl.TEXTURE0);
  2342. }
  2343. gl.bindFramebuffer(gl.FRAMEBUFFER, glwrap.fbo);
  2344. if (!glwrap.isBatchInEarlyZPass)
  2345. {
  2346. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texParam, 0);
  2347. }
  2348. }
  2349. else
  2350. {
  2351. if (!glwrap.enableFrontToBack)
  2352. {
  2353. gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
  2354. }
  2355. gl.bindFramebuffer(gl.FRAMEBUFFER, null);
  2356. }
  2357. };
  2358. GLBatchJob.prototype.doClear = function ()
  2359. {
  2360. var gl = this.gl;
  2361. var mode = this.startIndex;
  2362. if (mode === 0) // clear whole surface
  2363. {
  2364. gl.clearColor(this.mat4param[0], this.mat4param[1], this.mat4param[2], this.mat4param[3]);
  2365. gl.clear(gl.COLOR_BUFFER_BIT);
  2366. }
  2367. else if (mode === 1) // clear rectangle
  2368. {
  2369. gl.enable(gl.SCISSOR_TEST);
  2370. gl.scissor(this.mat4param[0], this.mat4param[1], this.mat4param[2], this.mat4param[3]);
  2371. gl.clearColor(0, 0, 0, 0);
  2372. gl.clear(gl.COLOR_BUFFER_BIT);
  2373. gl.disable(gl.SCISSOR_TEST);
  2374. }
  2375. else // clear depth
  2376. {
  2377. gl.clear(gl.DEPTH_BUFFER_BIT);
  2378. }
  2379. };
  2380. GLBatchJob.prototype.doSetDepthTestEnabled = function ()
  2381. {
  2382. var gl = this.gl;
  2383. var enable = this.startIndex;
  2384. if (enable !== 0)
  2385. {
  2386. gl.enable(gl.DEPTH_TEST);
  2387. }
  2388. else
  2389. {
  2390. gl.disable(gl.DEPTH_TEST);
  2391. }
  2392. };
  2393. GLBatchJob.prototype.doPoints = function ()
  2394. {
  2395. var gl = this.gl;
  2396. var glwrap = this.glwrap;
  2397. if (glwrap.enableFrontToBack)
  2398. gl.disable(gl.DEPTH_TEST);
  2399. var s = glwrap.shaderPrograms[1];
  2400. gl.useProgram(s.shaderProgram);
  2401. if (!s.hasCurrentMatMV && s.locMatMV)
  2402. {
  2403. s.updateMatMV(glwrap.currentMV);
  2404. s.hasCurrentMatMV = true;
  2405. }
  2406. gl.enableVertexAttribArray(s.locAPos);
  2407. gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.pointBuffer);
  2408. gl.vertexAttribPointer(s.locAPos, 4, gl.FLOAT, false, 0, 0);
  2409. gl.drawArrays(gl.POINTS, this.startIndex / 4, this.indexCount);
  2410. s = glwrap.currentShader;
  2411. gl.useProgram(s.shaderProgram);
  2412. if (s.locAPos >= 0)
  2413. {
  2414. gl.enableVertexAttribArray(s.locAPos);
  2415. gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.vertexBuffers[glwrap.curBuffer]);
  2416. gl.vertexAttribPointer(s.locAPos, glwrap.enableFrontToBack ? 3 : 2, gl.FLOAT, false, 0, 0);
  2417. }
  2418. if (s.locATex >= 0)
  2419. {
  2420. gl.enableVertexAttribArray(s.locATex);
  2421. gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.texcoordBuffers[glwrap.curBuffer]);
  2422. gl.vertexAttribPointer(s.locATex, 2, gl.FLOAT, false, 0, 0);
  2423. }
  2424. if (glwrap.enableFrontToBack)
  2425. gl.enable(gl.DEPTH_TEST);
  2426. };
  2427. GLBatchJob.prototype.doSetProgram = function ()
  2428. {
  2429. var gl = this.gl;
  2430. var glwrap = this.glwrap;
  2431. var s = glwrap.shaderPrograms[this.startIndex]; // recycled param to save memory
  2432. glwrap.currentProgram = this.startIndex; // current batch program
  2433. glwrap.currentShader = s;
  2434. gl.useProgram(s.shaderProgram); // switch to
  2435. if (!s.hasCurrentMatMV && s.locMatMV)
  2436. {
  2437. s.updateMatMV(glwrap.currentMV);
  2438. s.hasCurrentMatMV = true;
  2439. }
  2440. if (s.locOpacity && s.lpOpacity !== glwrap.currentOpacity)
  2441. {
  2442. s.lpOpacity = glwrap.currentOpacity;
  2443. gl.uniform1f(s.locOpacity, glwrap.currentOpacity);
  2444. }
  2445. if (s.locAPos >= 0)
  2446. {
  2447. gl.enableVertexAttribArray(s.locAPos);
  2448. gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.vertexBuffers[glwrap.curBuffer]);
  2449. gl.vertexAttribPointer(s.locAPos, glwrap.enableFrontToBack ? 3 : 2, gl.FLOAT, false, 0, 0);
  2450. }
  2451. if (s.locATex >= 0)
  2452. {
  2453. gl.enableVertexAttribArray(s.locATex);
  2454. gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.texcoordBuffers[glwrap.curBuffer]);
  2455. gl.vertexAttribPointer(s.locATex, 2, gl.FLOAT, false, 0, 0);
  2456. }
  2457. }
  2458. GLBatchJob.prototype.doSetColor = function ()
  2459. {
  2460. var s = this.glwrap.currentShader;
  2461. var mat4param = this.mat4param;
  2462. this.gl.uniform4f(s.locColorFill, mat4param[0], mat4param[1], mat4param[2], mat4param[3]);
  2463. };
  2464. GLBatchJob.prototype.doSetProgramParameters = function ()
  2465. {
  2466. var i, len, s = this.glwrap.currentShader;
  2467. var gl = this.gl;
  2468. var mat4param = this.mat4param;
  2469. if (s.locSamplerBack && this.glwrap.lastTexture1 !== this.texParam)
  2470. {
  2471. gl.activeTexture(gl.TEXTURE1);
  2472. gl.bindTexture(gl.TEXTURE_2D, this.texParam);
  2473. this.glwrap.lastTexture1 = this.texParam;
  2474. gl.activeTexture(gl.TEXTURE0);
  2475. }
  2476. var v = mat4param[0];
  2477. var v2;
  2478. if (s.locPixelWidth && v !== s.lpPixelWidth)
  2479. {
  2480. s.lpPixelWidth = v;
  2481. gl.uniform1f(s.locPixelWidth, v);
  2482. }
  2483. v = mat4param[1];
  2484. if (s.locPixelHeight && v !== s.lpPixelHeight)
  2485. {
  2486. s.lpPixelHeight = v;
  2487. gl.uniform1f(s.locPixelHeight, v);
  2488. }
  2489. v = mat4param[2];
  2490. v2 = mat4param[3];
  2491. if (s.locDestStart && (v !== s.lpDestStartX || v2 !== s.lpDestStartY))
  2492. {
  2493. s.lpDestStartX = v;
  2494. s.lpDestStartY = v2;
  2495. gl.uniform2f(s.locDestStart, v, v2);
  2496. }
  2497. v = mat4param[4];
  2498. v2 = mat4param[5];
  2499. if (s.locDestEnd && (v !== s.lpDestEndX || v2 !== s.lpDestEndY))
  2500. {
  2501. s.lpDestEndX = v;
  2502. s.lpDestEndY = v2;
  2503. gl.uniform2f(s.locDestEnd, v, v2);
  2504. }
  2505. v = mat4param[6];
  2506. if (s.locLayerScale && v !== s.lpLayerScale)
  2507. {
  2508. s.lpLayerScale = v;
  2509. gl.uniform1f(s.locLayerScale, v);
  2510. }
  2511. v = mat4param[7];
  2512. if (s.locLayerAngle && v !== s.lpLayerAngle)
  2513. {
  2514. s.lpLayerAngle = v;
  2515. gl.uniform1f(s.locLayerAngle, v);
  2516. }
  2517. v = mat4param[8];
  2518. v2 = mat4param[9];
  2519. if (s.locViewOrigin && (v !== s.lpViewOriginX || v2 !== s.lpViewOriginY))
  2520. {
  2521. s.lpViewOriginX = v;
  2522. s.lpViewOriginY = v2;
  2523. gl.uniform2f(s.locViewOrigin, v, v2);
  2524. }
  2525. v = mat4param[10];
  2526. v2 = mat4param[11];
  2527. if (s.locScrollPos && (v !== s.lpScrollPosX || v2 !== s.lpScrollPosY))
  2528. {
  2529. s.lpScrollPosX = v;
  2530. s.lpScrollPosY = v2;
  2531. gl.uniform2f(s.locScrollPos, v, v2);
  2532. }
  2533. v = mat4param[12];
  2534. if (s.locSeconds && v !== s.lpSeconds)
  2535. {
  2536. s.lpSeconds = v;
  2537. gl.uniform1f(s.locSeconds, v);
  2538. }
  2539. if (s.parameters.length)
  2540. {
  2541. for (i = 0, len = s.parameters.length; i < len; i++)
  2542. {
  2543. v = this.shaderParams[i];
  2544. if (v !== s.lastCustomParams[i])
  2545. {
  2546. s.lastCustomParams[i] = v;
  2547. gl.uniform1f(s.parameters[i][1], v);
  2548. }
  2549. }
  2550. }
  2551. };
  2552. GLWrap_.prototype.pushBatch = function ()
  2553. {
  2554. if (this.batchPtr === this.batch.length)
  2555. this.batch.push(new GLBatchJob(BATCH_NULL, this));
  2556. return this.batch[this.batchPtr++];
  2557. };
  2558. GLWrap_.prototype.endBatch = function ()
  2559. {
  2560. if (this.batchPtr === 0)
  2561. return;
  2562. if (this.gl.isContextLost())
  2563. return;
  2564. var gl = this.gl;
  2565. if (this.pointPtr > 0)
  2566. {
  2567. gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer);
  2568. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.pointData.subarray(0, this.pointPtr));
  2569. if (s && s.locAPos >= 0 && s.name === "<point>")
  2570. gl.vertexAttribPointer(s.locAPos, 4, gl.FLOAT, false, 0, 0);
  2571. }
  2572. if (this.vertexPtr > 0)
  2573. {
  2574. var s = this.currentShader;
  2575. gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffers[this.curBuffer]);
  2576. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexData.subarray(0, this.vertexPtr));
  2577. if (s && s.locAPos >= 0 && s.name !== "<point>")
  2578. gl.vertexAttribPointer(s.locAPos, this.enableFrontToBack ? 3 : 2, gl.FLOAT, false, 0, 0);
  2579. gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffers[this.curBuffer]);
  2580. gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.texcoordData.subarray(0, this.texPtr));
  2581. if (s && s.locATex >= 0 && s.name !== "<point>")
  2582. gl.vertexAttribPointer(s.locATex, 2, gl.FLOAT, false, 0, 0);
  2583. }
  2584. var i, len, b;
  2585. for (i = 0, len = this.batchPtr; i < len; i++)
  2586. {
  2587. b = this.batch[i];
  2588. switch (b.type) {
  2589. case 1:
  2590. b.doQuad();
  2591. break;
  2592. case 2:
  2593. b.doSetTexture();
  2594. break;
  2595. case 3:
  2596. b.doSetOpacity();
  2597. break;
  2598. case 4:
  2599. b.doSetBlend();
  2600. break;
  2601. case 5:
  2602. b.doUpdateModelView();
  2603. break;
  2604. case 6:
  2605. b.doRenderToTexture();
  2606. break;
  2607. case 7:
  2608. b.doClear();
  2609. break;
  2610. case 8:
  2611. b.doPoints();
  2612. break;
  2613. case 9:
  2614. b.doSetProgram();
  2615. break;
  2616. case 10:
  2617. b.doSetProgramParameters();
  2618. break;
  2619. case 11:
  2620. b.doSetTexture1();
  2621. break;
  2622. case 12:
  2623. b.doSetColor();
  2624. break;
  2625. case 13:
  2626. b.doSetDepthTestEnabled();
  2627. break;
  2628. case 14:
  2629. b.doSetEarlyZPass();
  2630. break;
  2631. }
  2632. }
  2633. this.batchPtr = 0;
  2634. this.vertexPtr = 0;
  2635. this.texPtr = 0;
  2636. this.pointPtr = 0;
  2637. this.hasQuadBatchTop = false;
  2638. this.hasPointBatchTop = false;
  2639. this.isBatchInEarlyZPass = false;
  2640. this.curBuffer++;
  2641. if (this.curBuffer >= MULTI_BUFFERS)
  2642. this.curBuffer = 0;
  2643. };
  2644. GLWrap_.prototype.setOpacity = function (op)
  2645. {
  2646. if (op === this.lastOpacity)
  2647. return;
  2648. if (this.isEarlyZPass)
  2649. return; // ignore
  2650. var b = this.pushBatch();
  2651. b.type = BATCH_SETOPACITY;
  2652. b.opacityParam = op;
  2653. this.lastOpacity = op;
  2654. this.hasQuadBatchTop = false;
  2655. this.hasPointBatchTop = false;
  2656. };
  2657. GLWrap_.prototype.setTexture = function (tex)
  2658. {
  2659. if (tex === this.lastTexture0)
  2660. return;
  2661. ;
  2662. var b = this.pushBatch();
  2663. b.type = BATCH_SETTEXTURE;
  2664. b.texParam = tex;
  2665. this.lastTexture0 = tex;
  2666. this.hasQuadBatchTop = false;
  2667. this.hasPointBatchTop = false;
  2668. };
  2669. GLWrap_.prototype.setBlend = function (s, d)
  2670. {
  2671. if (s === this.lastSrcBlend && d === this.lastDestBlend)
  2672. return;
  2673. if (this.isEarlyZPass)
  2674. return; // ignore
  2675. var b = this.pushBatch();
  2676. b.type = BATCH_SETBLEND;
  2677. b.startIndex = s; // recycle params to save memory
  2678. b.indexCount = d;
  2679. this.lastSrcBlend = s;
  2680. this.lastDestBlend = d;
  2681. this.hasQuadBatchTop = false;
  2682. this.hasPointBatchTop = false;
  2683. };
  2684. GLWrap_.prototype.isPremultipliedAlphaBlend = function ()
  2685. {
  2686. return (this.lastSrcBlend === this.gl.ONE && this.lastDestBlend === this.gl.ONE_MINUS_SRC_ALPHA);
  2687. };
  2688. GLWrap_.prototype.setAlphaBlend = function ()
  2689. {
  2690. this.setBlend(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA);
  2691. };
  2692. GLWrap_.prototype.setNoPremultiplyAlphaBlend = function ()
  2693. {
  2694. this.setBlend(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
  2695. };
  2696. var LAST_VERTEX = MAX_VERTICES * 2 - 8;
  2697. GLWrap_.prototype.quad = function(tlx, tly, trx, try_, brx, bry, blx, bly)
  2698. {
  2699. if (this.vertexPtr >= LAST_VERTEX)
  2700. this.endBatch();
  2701. var v = this.vertexPtr; // vertex cursor
  2702. var t = this.texPtr;
  2703. var vd = this.vertexData; // vertex data array
  2704. var td = this.texcoordData; // texture coord data array
  2705. var currentZ = this.currentZ;
  2706. if (this.hasQuadBatchTop)
  2707. {
  2708. this.batch[this.batchPtr - 1].indexCount += 6;
  2709. }
  2710. else
  2711. {
  2712. var b = this.pushBatch();
  2713. b.type = BATCH_QUAD;
  2714. b.startIndex = this.enableFrontToBack ? v : (v / 2) * 3;
  2715. b.indexCount = 6;
  2716. this.hasQuadBatchTop = true;
  2717. this.hasPointBatchTop = false;
  2718. }
  2719. if (this.enableFrontToBack)
  2720. {
  2721. vd[v++] = tlx;
  2722. vd[v++] = tly;
  2723. vd[v++] = currentZ;
  2724. vd[v++] = trx;
  2725. vd[v++] = try_;
  2726. vd[v++] = currentZ;
  2727. vd[v++] = brx;
  2728. vd[v++] = bry;
  2729. vd[v++] = currentZ;
  2730. vd[v++] = blx;
  2731. vd[v++] = bly;
  2732. vd[v++] = currentZ;
  2733. }
  2734. else
  2735. {
  2736. vd[v++] = tlx;
  2737. vd[v++] = tly;
  2738. vd[v++] = trx;
  2739. vd[v++] = try_;
  2740. vd[v++] = brx;
  2741. vd[v++] = bry;
  2742. vd[v++] = blx;
  2743. vd[v++] = bly;
  2744. }
  2745. td[t++] = 0;
  2746. td[t++] = 0;
  2747. td[t++] = 1;
  2748. td[t++] = 0;
  2749. td[t++] = 1;
  2750. td[t++] = 1;
  2751. td[t++] = 0;
  2752. td[t++] = 1;
  2753. this.vertexPtr = v;
  2754. this.texPtr = t;
  2755. };
  2756. GLWrap_.prototype.quadTex = function(tlx, tly, trx, try_, brx, bry, blx, bly, rcTex)
  2757. {
  2758. if (this.vertexPtr >= LAST_VERTEX)
  2759. this.endBatch();
  2760. var v = this.vertexPtr; // vertex cursor
  2761. var t = this.texPtr;
  2762. var vd = this.vertexData; // vertex data array
  2763. var td = this.texcoordData; // texture coord data array
  2764. var currentZ = this.currentZ;
  2765. if (this.hasQuadBatchTop)
  2766. {
  2767. this.batch[this.batchPtr - 1].indexCount += 6;
  2768. }
  2769. else
  2770. {
  2771. var b = this.pushBatch();
  2772. b.type = BATCH_QUAD;
  2773. b.startIndex = this.enableFrontToBack ? v : (v / 2) * 3;
  2774. b.indexCount = 6;
  2775. this.hasQuadBatchTop = true;
  2776. this.hasPointBatchTop = false;
  2777. }
  2778. var rc_left = rcTex.left;
  2779. var rc_top = rcTex.top;
  2780. var rc_right = rcTex.right;
  2781. var rc_bottom = rcTex.bottom;
  2782. if (this.enableFrontToBack)
  2783. {
  2784. vd[v++] = tlx;
  2785. vd[v++] = tly;
  2786. vd[v++] = currentZ;
  2787. vd[v++] = trx;
  2788. vd[v++] = try_;
  2789. vd[v++] = currentZ;
  2790. vd[v++] = brx;
  2791. vd[v++] = bry;
  2792. vd[v++] = currentZ;
  2793. vd[v++] = blx;
  2794. vd[v++] = bly;
  2795. vd[v++] = currentZ;
  2796. }
  2797. else
  2798. {
  2799. vd[v++] = tlx;
  2800. vd[v++] = tly;
  2801. vd[v++] = trx;
  2802. vd[v++] = try_;
  2803. vd[v++] = brx;
  2804. vd[v++] = bry;
  2805. vd[v++] = blx;
  2806. vd[v++] = bly;
  2807. }
  2808. td[t++] = rc_left;
  2809. td[t++] = rc_top;
  2810. td[t++] = rc_right;
  2811. td[t++] = rc_top;
  2812. td[t++] = rc_right;
  2813. td[t++] = rc_bottom;
  2814. td[t++] = rc_left;
  2815. td[t++] = rc_bottom;
  2816. this.vertexPtr = v;
  2817. this.texPtr = t;
  2818. };
  2819. GLWrap_.prototype.quadTexUV = function(tlx, tly, trx, try_, brx, bry, blx, bly, tlu, tlv, tru, trv, bru, brv, blu, blv)
  2820. {
  2821. if (this.vertexPtr >= LAST_VERTEX)
  2822. this.endBatch();
  2823. var v = this.vertexPtr; // vertex cursor
  2824. var t = this.texPtr;
  2825. var vd = this.vertexData; // vertex data array
  2826. var td = this.texcoordData; // texture coord data array
  2827. var currentZ = this.currentZ;
  2828. if (this.hasQuadBatchTop)
  2829. {
  2830. this.batch[this.batchPtr - 1].indexCount += 6;
  2831. }
  2832. else
  2833. {
  2834. var b = this.pushBatch();
  2835. b.type = BATCH_QUAD;
  2836. b.startIndex = this.enableFrontToBack ? v : (v / 2) * 3;
  2837. b.indexCount = 6;
  2838. this.hasQuadBatchTop = true;
  2839. this.hasPointBatchTop = false;
  2840. }
  2841. if (this.enableFrontToBack)
  2842. {
  2843. vd[v++] = tlx;
  2844. vd[v++] = tly;
  2845. vd[v++] = currentZ;
  2846. vd[v++] = trx;
  2847. vd[v++] = try_;
  2848. vd[v++] = currentZ;
  2849. vd[v++] = brx;
  2850. vd[v++] = bry;
  2851. vd[v++] = currentZ;
  2852. vd[v++] = blx;
  2853. vd[v++] = bly;
  2854. vd[v++] = currentZ;
  2855. }
  2856. else
  2857. {
  2858. vd[v++] = tlx;
  2859. vd[v++] = tly;
  2860. vd[v++] = trx;
  2861. vd[v++] = try_;
  2862. vd[v++] = brx;
  2863. vd[v++] = bry;
  2864. vd[v++] = blx;
  2865. vd[v++] = bly;
  2866. }
  2867. td[t++] = tlu;
  2868. td[t++] = tlv;
  2869. td[t++] = tru;
  2870. td[t++] = trv;
  2871. td[t++] = bru;
  2872. td[t++] = brv;
  2873. td[t++] = blu;
  2874. td[t++] = blv;
  2875. this.vertexPtr = v;
  2876. this.texPtr = t;
  2877. };
  2878. GLWrap_.prototype.convexPoly = function(pts)
  2879. {
  2880. var pts_count = pts.length / 2;
  2881. ;
  2882. var tris = pts_count - 2; // 3 points = 1 tri, 4 points = 2 tris, 5 points = 3 tris etc.
  2883. var last_tri = tris - 1;
  2884. var p0x = pts[0];
  2885. var p0y = pts[1];
  2886. var i, i2, p1x, p1y, p2x, p2y, p3x, p3y;
  2887. for (i = 0; i < tris; i += 2) // draw 2 triangles at a time
  2888. {
  2889. i2 = i * 2;
  2890. p1x = pts[i2 + 2];
  2891. p1y = pts[i2 + 3];
  2892. p2x = pts[i2 + 4];
  2893. p2y = pts[i2 + 5];
  2894. if (i === last_tri)
  2895. {
  2896. this.quad(p0x, p0y, p1x, p1y, p2x, p2y, p2x, p2y);
  2897. }
  2898. else
  2899. {
  2900. p3x = pts[i2 + 6];
  2901. p3y = pts[i2 + 7];
  2902. this.quad(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y);
  2903. }
  2904. }
  2905. };
  2906. var LAST_POINT = MAX_POINTS - 4;
  2907. GLWrap_.prototype.point = function(x_, y_, size_, opacity_)
  2908. {
  2909. if (this.pointPtr >= LAST_POINT)
  2910. this.endBatch();
  2911. var p = this.pointPtr; // point cursor
  2912. var pd = this.pointData; // point data array
  2913. if (this.hasPointBatchTop)
  2914. {
  2915. this.batch[this.batchPtr - 1].indexCount++;
  2916. }
  2917. else
  2918. {
  2919. var b = this.pushBatch();
  2920. b.type = BATCH_POINTS;
  2921. b.startIndex = p;
  2922. b.indexCount = 1;
  2923. this.hasPointBatchTop = true;
  2924. this.hasQuadBatchTop = false;
  2925. }
  2926. pd[p++] = x_;
  2927. pd[p++] = y_;
  2928. pd[p++] = size_;
  2929. pd[p++] = opacity_;
  2930. this.pointPtr = p;
  2931. };
  2932. GLWrap_.prototype.switchProgram = function (progIndex)
  2933. {
  2934. if (this.lastProgram === progIndex)
  2935. return; // no change
  2936. var shaderProg = this.shaderPrograms[progIndex];
  2937. if (!shaderProg)
  2938. {
  2939. if (this.lastProgram === 0)
  2940. return; // already on default shader
  2941. progIndex = 0;
  2942. shaderProg = this.shaderPrograms[0];
  2943. }
  2944. var b = this.pushBatch();
  2945. b.type = BATCH_SETPROGRAM;
  2946. b.startIndex = progIndex;
  2947. this.lastProgram = progIndex;
  2948. this.hasQuadBatchTop = false;
  2949. this.hasPointBatchTop = false;
  2950. };
  2951. GLWrap_.prototype.programUsesDest = function (progIndex)
  2952. {
  2953. var s = this.shaderPrograms[progIndex];
  2954. return !!(s.locDestStart || s.locDestEnd);
  2955. };
  2956. GLWrap_.prototype.programUsesCrossSampling = function (progIndex)
  2957. {
  2958. var s = this.shaderPrograms[progIndex];
  2959. return !!(s.locDestStart || s.locDestEnd || s.crossSampling);
  2960. };
  2961. GLWrap_.prototype.programPreservesOpaqueness = function (progIndex)
  2962. {
  2963. return this.shaderPrograms[progIndex].preservesOpaqueness;
  2964. };
  2965. GLWrap_.prototype.programExtendsBox = function (progIndex)
  2966. {
  2967. var s = this.shaderPrograms[progIndex];
  2968. return s.extendBoxHorizontal !== 0 || s.extendBoxVertical !== 0;
  2969. };
  2970. GLWrap_.prototype.getProgramBoxExtendHorizontal = function (progIndex)
  2971. {
  2972. return this.shaderPrograms[progIndex].extendBoxHorizontal;
  2973. };
  2974. GLWrap_.prototype.getProgramBoxExtendVertical = function (progIndex)
  2975. {
  2976. return this.shaderPrograms[progIndex].extendBoxVertical;
  2977. };
  2978. GLWrap_.prototype.getProgramParameterType = function (progIndex, paramIndex)
  2979. {
  2980. return this.shaderPrograms[progIndex].parameters[paramIndex][2];
  2981. };
  2982. GLWrap_.prototype.programIsAnimated = function (progIndex)
  2983. {
  2984. return this.shaderPrograms[progIndex].animated;
  2985. };
  2986. GLWrap_.prototype.setProgramParameters = function (backTex, pixelWidth, pixelHeight, destStartX, destStartY, destEndX, destEndY, layerScale, layerAngle, viewOriginLeft, viewOriginTop, scrollPosX, scrollPosY, seconds, params)
  2987. {
  2988. var i, len;
  2989. var s = this.shaderPrograms[this.lastProgram];
  2990. var b, mat4param, shaderParams;
  2991. if (s.hasAnyOptionalUniforms || params.length)
  2992. {
  2993. b = this.pushBatch();
  2994. b.type = BATCH_SETPROGRAMPARAMETERS;
  2995. if (b.mat4param)
  2996. mat4.set(this.matMV, b.mat4param);
  2997. else
  2998. b.mat4param = mat4.create();
  2999. mat4param = b.mat4param;
  3000. mat4param[0] = pixelWidth;
  3001. mat4param[1] = pixelHeight;
  3002. mat4param[2] = destStartX;
  3003. mat4param[3] = destStartY;
  3004. mat4param[4] = destEndX;
  3005. mat4param[5] = destEndY;
  3006. mat4param[6] = layerScale;
  3007. mat4param[7] = layerAngle;
  3008. mat4param[8] = viewOriginLeft;
  3009. mat4param[9] = viewOriginTop;
  3010. mat4param[10] = scrollPosX;
  3011. mat4param[11] = scrollPosY;
  3012. mat4param[12] = seconds;
  3013. if (s.locSamplerBack)
  3014. {
  3015. ;
  3016. b.texParam = backTex;
  3017. }
  3018. else
  3019. b.texParam = null;
  3020. if (params.length)
  3021. {
  3022. shaderParams = b.shaderParams;
  3023. shaderParams.length = params.length;
  3024. for (i = 0, len = params.length; i < len; i++)
  3025. shaderParams[i] = params[i];
  3026. }
  3027. this.hasQuadBatchTop = false;
  3028. this.hasPointBatchTop = false;
  3029. }
  3030. };
  3031. GLWrap_.prototype.clear = function (r, g, b_, a)
  3032. {
  3033. var b = this.pushBatch();
  3034. b.type = BATCH_CLEAR;
  3035. b.startIndex = 0; // clear all mode
  3036. if (!b.mat4param)
  3037. b.mat4param = mat4.create();
  3038. b.mat4param[0] = r;
  3039. b.mat4param[1] = g;
  3040. b.mat4param[2] = b_;
  3041. b.mat4param[3] = a;
  3042. this.hasQuadBatchTop = false;
  3043. this.hasPointBatchTop = false;
  3044. };
  3045. GLWrap_.prototype.clearRect = function (x, y, w, h)
  3046. {
  3047. if (w < 0 || h < 0)
  3048. return; // invalid clear area
  3049. var b = this.pushBatch();
  3050. b.type = BATCH_CLEAR;
  3051. b.startIndex = 1; // clear rect mode
  3052. if (!b.mat4param)
  3053. b.mat4param = mat4.create();
  3054. b.mat4param[0] = x;
  3055. b.mat4param[1] = y;
  3056. b.mat4param[2] = w;
  3057. b.mat4param[3] = h;
  3058. this.hasQuadBatchTop = false;
  3059. this.hasPointBatchTop = false;
  3060. };
  3061. GLWrap_.prototype.clearDepth = function ()
  3062. {
  3063. var b = this.pushBatch();
  3064. b.type = BATCH_CLEAR;
  3065. b.startIndex = 2; // clear depth mode
  3066. this.hasQuadBatchTop = false;
  3067. this.hasPointBatchTop = false;
  3068. };
  3069. GLWrap_.prototype.setEarlyZPass = function (e)
  3070. {
  3071. if (!this.enableFrontToBack)
  3072. return; // no depth buffer in use
  3073. e = !!e;
  3074. if (this.isEarlyZPass === e)
  3075. return; // no change
  3076. var b = this.pushBatch();
  3077. b.type = BATCH_SETEARLYZMODE;
  3078. b.startIndex = (e ? 1 : 0);
  3079. this.hasQuadBatchTop = false;
  3080. this.hasPointBatchTop = false;
  3081. this.isEarlyZPass = e;
  3082. this.renderToTex = null;
  3083. if (this.isEarlyZPass)
  3084. {
  3085. this.switchProgram(2); // early Z program
  3086. }
  3087. else
  3088. {
  3089. this.switchProgram(0); // normal rendering
  3090. }
  3091. };
  3092. GLWrap_.prototype.setDepthTestEnabled = function (e)
  3093. {
  3094. if (!this.enableFrontToBack)
  3095. return; // no depth buffer in use
  3096. var b = this.pushBatch();
  3097. b.type = BATCH_SETDEPTHTEST;
  3098. b.startIndex = (e ? 1 : 0);
  3099. this.hasQuadBatchTop = false;
  3100. this.hasPointBatchTop = false;
  3101. };
  3102. GLWrap_.prototype.fullscreenQuad = function ()
  3103. {
  3104. mat4.set(this.lastMV, tempMat4);
  3105. this.resetModelView();
  3106. this.updateModelView();
  3107. var halfw = this.width / 2;
  3108. var halfh = this.height / 2;
  3109. this.quad(-halfw, halfh, halfw, halfh, halfw, -halfh, -halfw, -halfh);
  3110. mat4.set(tempMat4, this.matMV);
  3111. this.updateModelView();
  3112. };
  3113. GLWrap_.prototype.setColorFillMode = function (r_, g_, b_, a_)
  3114. {
  3115. this.switchProgram(3);
  3116. var b = this.pushBatch();
  3117. b.type = BATCH_SETCOLOR;
  3118. if (!b.mat4param)
  3119. b.mat4param = mat4.create();
  3120. b.mat4param[0] = r_;
  3121. b.mat4param[1] = g_;
  3122. b.mat4param[2] = b_;
  3123. b.mat4param[3] = a_;
  3124. this.hasQuadBatchTop = false;
  3125. this.hasPointBatchTop = false;
  3126. };
  3127. GLWrap_.prototype.setTextureFillMode = function ()
  3128. {
  3129. ;
  3130. this.switchProgram(0);
  3131. };
  3132. GLWrap_.prototype.restoreEarlyZMode = function ()
  3133. {
  3134. ;
  3135. this.switchProgram(2);
  3136. };
  3137. GLWrap_.prototype.present = function ()
  3138. {
  3139. this.endBatch();
  3140. this.gl.flush();
  3141. /*
  3142. if (debugBatch)
  3143. {
  3144. ;
  3145. debugBatch = false;
  3146. }
  3147. */
  3148. };
  3149. function nextHighestPowerOfTwo(x) {
  3150. --x;
  3151. for (var i = 1; i < 32; i <<= 1) {
  3152. x = x | x >> i;
  3153. }
  3154. return x + 1;
  3155. }
  3156. var all_textures = [];
  3157. var textures_by_src = {};
  3158. GLWrap_.prototype.contextLost = function ()
  3159. {
  3160. cr.clearArray(all_textures);
  3161. textures_by_src = {};
  3162. };
  3163. var BF_RGBA8 = 0;
  3164. var BF_RGB8 = 1;
  3165. var BF_RGBA4 = 2;
  3166. var BF_RGB5_A1 = 3;
  3167. var BF_RGB565 = 4;
  3168. GLWrap_.prototype.loadTexture = function (img, tiling, linearsampling, pixelformat, tiletype, nomip)
  3169. {
  3170. tiling = !!tiling;
  3171. linearsampling = !!linearsampling;
  3172. var tex_key = img.src + "," + tiling + "," + linearsampling + (tiling ? ("," + tiletype) : "");
  3173. var webGL_texture = null;
  3174. if (typeof img.src !== "undefined" && textures_by_src.hasOwnProperty(tex_key))
  3175. {
  3176. webGL_texture = textures_by_src[tex_key];
  3177. webGL_texture.c2refcount++;
  3178. return webGL_texture;
  3179. }
  3180. this.endBatch();
  3181. ;
  3182. var gl = this.gl;
  3183. var isPOT = (cr.isPOT(img.width) && cr.isPOT(img.height));
  3184. webGL_texture = gl.createTexture();
  3185. gl.bindTexture(gl.TEXTURE_2D, webGL_texture);
  3186. gl.pixelStorei(gl["UNPACK_PREMULTIPLY_ALPHA_WEBGL"], true);
  3187. var internalformat = gl.RGBA;
  3188. var format = gl.RGBA;
  3189. var type = gl.UNSIGNED_BYTE;
  3190. if (pixelformat && !this.isIE)
  3191. {
  3192. switch (pixelformat) {
  3193. case BF_RGB8:
  3194. internalformat = gl.RGB;
  3195. format = gl.RGB;
  3196. break;
  3197. case BF_RGBA4:
  3198. type = gl.UNSIGNED_SHORT_4_4_4_4;
  3199. break;
  3200. case BF_RGB5_A1:
  3201. type = gl.UNSIGNED_SHORT_5_5_5_1;
  3202. break;
  3203. case BF_RGB565:
  3204. internalformat = gl.RGB;
  3205. format = gl.RGB;
  3206. type = gl.UNSIGNED_SHORT_5_6_5;
  3207. break;
  3208. }
  3209. }
  3210. if (this.version === 1 && !isPOT && tiling)
  3211. {
  3212. var canvas = document.createElement("canvas");
  3213. canvas.width = cr.nextHighestPowerOfTwo(img.width);
  3214. canvas.height = cr.nextHighestPowerOfTwo(img.height);
  3215. var ctx = canvas.getContext("2d");
  3216. if (typeof ctx["imageSmoothingEnabled"] !== "undefined")
  3217. {
  3218. ctx["imageSmoothingEnabled"] = linearsampling;
  3219. }
  3220. else
  3221. {
  3222. ctx["webkitImageSmoothingEnabled"] = linearsampling;
  3223. ctx["mozImageSmoothingEnabled"] = linearsampling;
  3224. ctx["msImageSmoothingEnabled"] = linearsampling;
  3225. }
  3226. ctx.drawImage(img,
  3227. 0, 0, img.width, img.height,
  3228. 0, 0, canvas.width, canvas.height);
  3229. gl.texImage2D(gl.TEXTURE_2D, 0, internalformat, format, type, canvas);
  3230. }
  3231. else
  3232. gl.texImage2D(gl.TEXTURE_2D, 0, internalformat, format, type, img);
  3233. if (tiling)
  3234. {
  3235. if (tiletype === "repeat-x")
  3236. {
  3237. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  3238. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  3239. }
  3240. else if (tiletype === "repeat-y")
  3241. {
  3242. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  3243. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  3244. }
  3245. else
  3246. {
  3247. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  3248. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  3249. }
  3250. }
  3251. else
  3252. {
  3253. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  3254. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  3255. }
  3256. if (linearsampling)
  3257. {
  3258. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
  3259. if ((isPOT || this.version >= 2) && this.enable_mipmaps && !nomip)
  3260. {
  3261. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
  3262. gl.generateMipmap(gl.TEXTURE_2D);
  3263. }
  3264. else
  3265. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
  3266. }
  3267. else
  3268. {
  3269. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
  3270. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
  3271. }
  3272. gl.bindTexture(gl.TEXTURE_2D, null);
  3273. this.lastTexture0 = null;
  3274. webGL_texture.c2width = img.width;
  3275. webGL_texture.c2height = img.height;
  3276. webGL_texture.c2refcount = 1;
  3277. webGL_texture.c2texkey = tex_key;
  3278. all_textures.push(webGL_texture);
  3279. textures_by_src[tex_key] = webGL_texture;
  3280. return webGL_texture;
  3281. };
  3282. GLWrap_.prototype.createEmptyTexture = function (w, h, linearsampling, _16bit, tiling)
  3283. {
  3284. this.endBatch();
  3285. var gl = this.gl;
  3286. if (this.isIE)
  3287. _16bit = false;
  3288. var webGL_texture = gl.createTexture();
  3289. gl.bindTexture(gl.TEXTURE_2D, webGL_texture);
  3290. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, w, h, 0, gl.RGBA, _16bit ? gl.UNSIGNED_SHORT_4_4_4_4 : gl.UNSIGNED_BYTE, null);
  3291. if (tiling)
  3292. {
  3293. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT);
  3294. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT);
  3295. }
  3296. else
  3297. {
  3298. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
  3299. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
  3300. }
  3301. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linearsampling ? gl.LINEAR : gl.NEAREST);
  3302. gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linearsampling ? gl.LINEAR : gl.NEAREST);
  3303. gl.bindTexture(gl.TEXTURE_2D, null);
  3304. this.lastTexture0 = null;
  3305. webGL_texture.c2width = w;
  3306. webGL_texture.c2height = h;
  3307. all_textures.push(webGL_texture);
  3308. return webGL_texture;
  3309. };
  3310. GLWrap_.prototype.videoToTexture = function (video_, texture_, _16bit)
  3311. {
  3312. this.endBatch();
  3313. var gl = this.gl;
  3314. if (this.isIE)
  3315. _16bit = false;
  3316. gl.bindTexture(gl.TEXTURE_2D, texture_);
  3317. gl.pixelStorei(gl["UNPACK_PREMULTIPLY_ALPHA_WEBGL"], true);
  3318. try {
  3319. gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, _16bit ? gl.UNSIGNED_SHORT_4_4_4_4 : gl.UNSIGNED_BYTE, video_);
  3320. }
  3321. catch (e)
  3322. {
  3323. if (console && console.error)
  3324. console.error("Error updating WebGL texture: ", e);
  3325. }
  3326. gl.bindTexture(gl.TEXTURE_2D, null);
  3327. this.lastTexture0 = null;
  3328. };
  3329. GLWrap_.prototype.deleteTexture = function (tex)
  3330. {
  3331. if (!tex)
  3332. return;
  3333. if (typeof tex.c2refcount !== "undefined" && tex.c2refcount > 1)
  3334. {
  3335. tex.c2refcount--;
  3336. return;
  3337. }
  3338. this.endBatch();
  3339. if (tex === this.lastTexture0)
  3340. {
  3341. this.gl.bindTexture(this.gl.TEXTURE_2D, null);
  3342. this.lastTexture0 = null;
  3343. }
  3344. if (tex === this.lastTexture1)
  3345. {
  3346. this.gl.activeTexture(this.gl.TEXTURE1);
  3347. this.gl.bindTexture(this.gl.TEXTURE_2D, null);
  3348. this.gl.activeTexture(this.gl.TEXTURE0);
  3349. this.lastTexture1 = null;
  3350. }
  3351. cr.arrayFindRemove(all_textures, tex);
  3352. if (typeof tex.c2texkey !== "undefined")
  3353. delete textures_by_src[tex.c2texkey];
  3354. this.gl.deleteTexture(tex);
  3355. };
  3356. GLWrap_.prototype.estimateVRAM = function ()
  3357. {
  3358. var total = this.width * this.height * 4 * 2;
  3359. var i, len, t;
  3360. for (i = 0, len = all_textures.length; i < len; i++)
  3361. {
  3362. t = all_textures[i];
  3363. total += (t.c2width * t.c2height * 4);
  3364. }
  3365. return total;
  3366. };
  3367. GLWrap_.prototype.textureCount = function ()
  3368. {
  3369. return all_textures.length;
  3370. };
  3371. GLWrap_.prototype.setRenderingToTexture = function (tex)
  3372. {
  3373. if (tex === this.renderToTex)
  3374. return;
  3375. ;
  3376. var b = this.pushBatch();
  3377. b.type = BATCH_RENDERTOTEXTURE;
  3378. b.texParam = tex;
  3379. this.renderToTex = tex;
  3380. this.hasQuadBatchTop = false;
  3381. this.hasPointBatchTop = false;
  3382. };
  3383. cr.GLWrap = GLWrap_;
  3384. }());
  3385. ;
  3386. (function()
  3387. {
  3388. var raf = window["requestAnimationFrame"] ||
  3389. window["mozRequestAnimationFrame"] ||
  3390. window["webkitRequestAnimationFrame"] ||
  3391. window["msRequestAnimationFrame"] ||
  3392. window["oRequestAnimationFrame"];
  3393. function Runtime(canvas)
  3394. {
  3395. if (!canvas || (!canvas.getContext && !canvas["dc"]))
  3396. return;
  3397. if (canvas["c2runtime"])
  3398. return;
  3399. else
  3400. canvas["c2runtime"] = this;
  3401. var self = this;
  3402. this.isCrosswalk = /crosswalk/i.test(navigator.userAgent) || /xwalk/i.test(navigator.userAgent) || !!(typeof window["c2isCrosswalk"] !== "undefined" && window["c2isCrosswalk"]);
  3403. this.isCordova = this.isCrosswalk || (typeof window["device"] !== "undefined" && (typeof window["device"]["cordova"] !== "undefined" || typeof window["device"]["phonegap"] !== "undefined")) || (typeof window["c2iscordova"] !== "undefined" && window["c2iscordova"]);
  3404. this.isPhoneGap = this.isCordova;
  3405. this.isDirectCanvas = !!canvas["dc"];
  3406. this.isAppMobi = (typeof window["AppMobi"] !== "undefined" || this.isDirectCanvas);
  3407. this.isCocoonJs = !!window["c2cocoonjs"];
  3408. this.isEjecta = !!window["c2ejecta"];
  3409. if (this.isCocoonJs)
  3410. {
  3411. CocoonJS["App"]["onSuspended"].addEventListener(function() {
  3412. self["setSuspended"](true);
  3413. });
  3414. CocoonJS["App"]["onActivated"].addEventListener(function () {
  3415. self["setSuspended"](false);
  3416. });
  3417. }
  3418. if (this.isEjecta)
  3419. {
  3420. document.addEventListener("pagehide", function() {
  3421. self["setSuspended"](true);
  3422. });
  3423. document.addEventListener("pageshow", function() {
  3424. self["setSuspended"](false);
  3425. });
  3426. document.addEventListener("resize", function () {
  3427. self["setSize"](window.innerWidth, window.innerHeight);
  3428. });
  3429. }
  3430. this.isDomFree = (this.isDirectCanvas || this.isCocoonJs || this.isEjecta);
  3431. this.isMicrosoftEdge = /edge\//i.test(navigator.userAgent);
  3432. this.isIE = (/msie/i.test(navigator.userAgent) || /trident/i.test(navigator.userAgent) || /iemobile/i.test(navigator.userAgent)) && !this.isMicrosoftEdge;
  3433. this.isTizen = /tizen/i.test(navigator.userAgent);
  3434. this.isAndroid = /android/i.test(navigator.userAgent) && !this.isTizen && !this.isIE && !this.isMicrosoftEdge; // IE mobile and Tizen masquerade as Android
  3435. this.isiPhone = (/iphone/i.test(navigator.userAgent) || /ipod/i.test(navigator.userAgent)) && !this.isIE && !this.isMicrosoftEdge; // treat ipod as an iphone; IE mobile masquerades as iPhone
  3436. this.isiPad = /ipad/i.test(navigator.userAgent);
  3437. this.isiOS = this.isiPhone || this.isiPad || this.isEjecta;
  3438. this.isiPhoneiOS6 = (this.isiPhone && /os\s6/i.test(navigator.userAgent));
  3439. this.isChrome = (/chrome/i.test(navigator.userAgent) || /chromium/i.test(navigator.userAgent)) && !this.isIE && !this.isMicrosoftEdge; // note true on Chromium-based webview on Android 4.4+; IE 'Edge' mode also pretends to be Chrome
  3440. this.isAmazonWebApp = /amazonwebappplatform/i.test(navigator.userAgent);
  3441. this.isFirefox = /firefox/i.test(navigator.userAgent);
  3442. this.isSafari = /safari/i.test(navigator.userAgent) && !this.isChrome && !this.isIE && !this.isMicrosoftEdge; // Chrome and IE Mobile masquerade as Safari
  3443. this.isWindows = /windows/i.test(navigator.userAgent);
  3444. this.isNWjs = (typeof window["c2nodewebkit"] !== "undefined" || typeof window["c2nwjs"] !== "undefined" || /nodewebkit/i.test(navigator.userAgent) || /nwjs/i.test(navigator.userAgent));
  3445. this.isNodeWebkit = this.isNWjs; // old name for backwards compat
  3446. this.isArcade = (typeof window["is_scirra_arcade"] !== "undefined");
  3447. this.isWindows8App = !!(typeof window["c2isWindows8"] !== "undefined" && window["c2isWindows8"]);
  3448. this.isWindows8Capable = !!(typeof window["c2isWindows8Capable"] !== "undefined" && window["c2isWindows8Capable"]);
  3449. this.isWindowsPhone8 = !!(typeof window["c2isWindowsPhone8"] !== "undefined" && window["c2isWindowsPhone8"]);
  3450. this.isWindowsPhone81 = !!(typeof window["c2isWindowsPhone81"] !== "undefined" && window["c2isWindowsPhone81"]);
  3451. this.isWindows10 = !!window["cr_windows10"];
  3452. this.isWinJS = (this.isWindows8App || this.isWindows8Capable || this.isWindowsPhone81 || this.isWindows10); // note not WP8.0
  3453. this.isBlackberry10 = !!(typeof window["c2isBlackberry10"] !== "undefined" && window["c2isBlackberry10"]);
  3454. this.isAndroidStockBrowser = (this.isAndroid && !this.isChrome && !this.isCrosswalk && !this.isFirefox && !this.isAmazonWebApp && !this.isDomFree);
  3455. this.devicePixelRatio = 1;
  3456. this.isMobile = (this.isCordova || this.isCrosswalk || this.isAppMobi || this.isCocoonJs || this.isAndroid || this.isiOS || this.isWindowsPhone8 || this.isWindowsPhone81 || this.isBlackberry10 || this.isTizen || this.isEjecta);
  3457. if (!this.isMobile)
  3458. {
  3459. this.isMobile = /(blackberry|bb10|playbook|palm|symbian|nokia|windows\s+ce|phone|mobile|tablet|kindle|silk)/i.test(navigator.userAgent);
  3460. }
  3461. this.isWKWebView = !!(this.isiOS && this.isCordova && window["webkit"]);
  3462. if (typeof cr_is_preview !== "undefined" && !this.isNWjs && (window.location.search === "?nw" || /nodewebkit/i.test(navigator.userAgent) || /nwjs/i.test(navigator.userAgent)))
  3463. {
  3464. this.isNWjs = true;
  3465. }
  3466. this.isDebug = (typeof cr_is_preview !== "undefined" && window.location.search.indexOf("debug") > -1);
  3467. this.canvas = canvas;
  3468. this.canvasdiv = document.getElementById("c2canvasdiv");
  3469. this.gl = null;
  3470. this.glwrap = null;
  3471. this.glUnmaskedRenderer = "(unavailable)";
  3472. this.enableFrontToBack = false;
  3473. this.earlyz_index = 0;
  3474. this.ctx = null;
  3475. this.firstInFullscreen = false;
  3476. this.oldWidth = 0; // for restoring non-fullscreen canvas after fullscreen
  3477. this.oldHeight = 0;
  3478. this.canvas.oncontextmenu = function (e) { if (e.preventDefault) e.preventDefault(); return false; };
  3479. this.canvas.onselectstart = function (e) { if (e.preventDefault) e.preventDefault(); return false; };
  3480. this.canvas.ontouchstart = function (e) { if(e.preventDefault) e.preventDefault(); return false; };
  3481. if (this.isDirectCanvas)
  3482. window["c2runtime"] = this;
  3483. if (this.isNWjs)
  3484. {
  3485. window["ondragover"] = function(e) { e.preventDefault(); return false; };
  3486. window["ondrop"] = function(e) { e.preventDefault(); return false; };
  3487. if (window["nwgui"] && window["nwgui"]["App"]["clearCache"])
  3488. window["nwgui"]["App"]["clearCache"]();
  3489. }
  3490. if (this.isAndroidStockBrowser && typeof jQuery !== "undefined")
  3491. {
  3492. jQuery("canvas").parents("*").css("overflow", "visible");
  3493. }
  3494. this.width = canvas.width;
  3495. this.height = canvas.height;
  3496. this.draw_width = this.width;
  3497. this.draw_height = this.height;
  3498. this.cssWidth = this.width;
  3499. this.cssHeight = this.height;
  3500. this.lastWindowWidth = window.innerWidth;
  3501. this.lastWindowHeight = window.innerHeight;
  3502. this.forceCanvasAlpha = false; // note: now unused, left for backwards compat since plugins could modify it
  3503. this.redraw = true;
  3504. this.isSuspended = false;
  3505. if (!Date.now) {
  3506. Date.now = function now() {
  3507. return +new Date();
  3508. };
  3509. }
  3510. this.plugins = [];
  3511. this.types = {};
  3512. this.types_by_index = [];
  3513. this.behaviors = [];
  3514. this.layouts = {};
  3515. this.layouts_by_index = [];
  3516. this.eventsheets = {};
  3517. this.eventsheets_by_index = [];
  3518. this.wait_for_textures = []; // for blocking until textures loaded
  3519. this.triggers_to_postinit = [];
  3520. this.all_global_vars = [];
  3521. this.all_local_vars = [];
  3522. this.solidBehavior = null;
  3523. this.jumpthruBehavior = null;
  3524. this.shadowcasterBehavior = null;
  3525. this.deathRow = {};
  3526. this.hasPendingInstances = false; // true if anything exists in create row or death row
  3527. this.isInClearDeathRow = false;
  3528. this.isInOnDestroy = 0; // needs to support recursion so increments and decrements and is true if > 0
  3529. this.isRunningEvents = false;
  3530. this.isEndingLayout = false;
  3531. this.createRow = [];
  3532. this.isLoadingState = false;
  3533. this.saveToSlot = "";
  3534. this.loadFromSlot = "";
  3535. this.loadFromJson = null; // set to string when there is something to try to load
  3536. this.lastSaveJson = "";
  3537. this.signalledContinuousPreview = false;
  3538. this.suspendDrawing = false; // for hiding display until continuous preview loads
  3539. this.fireOnCreateAfterLoad = []; // for delaying "On create" triggers until loading complete
  3540. this.dt = 0;
  3541. this.dt1 = 0;
  3542. this.minimumFramerate = 30;
  3543. this.logictime = 0; // used to calculate CPUUtilisation
  3544. this.cpuutilisation = 0;
  3545. this.timescale = 1.0;
  3546. this.kahanTime = new cr.KahanAdder();
  3547. this.wallTime = new cr.KahanAdder();
  3548. this.last_tick_time = 0;
  3549. this.fps = 0;
  3550. this.last_fps_time = 0;
  3551. this.tickcount = 0;
  3552. this.tickcount_nosave = 0; // same as tickcount but never saved/loaded
  3553. this.execcount = 0;
  3554. this.framecount = 0; // for fps
  3555. this.objectcount = 0;
  3556. this.changelayout = null;
  3557. this.destroycallbacks = [];
  3558. this.event_stack = [];
  3559. this.event_stack_index = -1;
  3560. this.localvar_stack = [[]];
  3561. this.localvar_stack_index = 0;
  3562. this.trigger_depth = 0; // recursion depth for triggers
  3563. this.pushEventStack(null);
  3564. this.loop_stack = [];
  3565. this.loop_stack_index = -1;
  3566. this.next_uid = 0;
  3567. this.next_puid = 0; // permanent unique ids
  3568. this.layout_first_tick = true;
  3569. this.family_count = 0;
  3570. this.suspend_events = [];
  3571. this.raf_id = -1;
  3572. this.timeout_id = -1;
  3573. this.isloading = true;
  3574. this.loadingprogress = 0;
  3575. this.isNodeFullscreen = false;
  3576. this.stackLocalCount = 0; // number of stack-based local vars for recursion
  3577. this.audioInstance = null;
  3578. this.had_a_click = false;
  3579. this.isInUserInputEvent = false;
  3580. this.objects_to_pretick = new cr.ObjectSet();
  3581. this.objects_to_tick = new cr.ObjectSet();
  3582. this.objects_to_tick2 = new cr.ObjectSet();
  3583. this.registered_collisions = [];
  3584. this.temp_poly = new cr.CollisionPoly([]);
  3585. this.temp_poly2 = new cr.CollisionPoly([]);
  3586. this.allGroups = []; // array of all event groups
  3587. this.groups_by_name = {};
  3588. this.cndsBySid = {};
  3589. this.actsBySid = {};
  3590. this.varsBySid = {};
  3591. this.blocksBySid = {};
  3592. this.running_layout = null; // currently running layout
  3593. this.layer_canvas = null; // for layers "render-to-texture"
  3594. this.layer_ctx = null;
  3595. this.layer_tex = null;
  3596. this.layout_tex = null;
  3597. this.layout_canvas = null;
  3598. this.layout_ctx = null;
  3599. this.is_WebGL_context_lost = false;
  3600. this.uses_background_blending = false; // if any shader uses background blending, so entire layout renders to texture
  3601. this.fx_tex = [null, null];
  3602. this.fullscreen_scaling = 0;
  3603. this.files_subfolder = ""; // path with project files
  3604. this.objectsByUid = {}; // maps every in-use UID (as a string) to its instance
  3605. this.loaderlogos = null;
  3606. this.snapshotCanvas = null;
  3607. this.snapshotData = "";
  3608. this.objectRefTable = [];
  3609. this.requestProjectData();
  3610. };
  3611. Runtime.prototype.requestProjectData = function ()
  3612. {
  3613. var self = this;
  3614. if (this.isWKWebView)
  3615. {
  3616. this.fetchLocalFileViaCordovaAsText("data.js", function (str)
  3617. {
  3618. self.loadProject(JSON.parse(str));
  3619. }, function (err)
  3620. {
  3621. alert("Error fetching data.js");
  3622. });
  3623. return;
  3624. }
  3625. var xhr;
  3626. if (this.isWindowsPhone8)
  3627. xhr = new ActiveXObject("Microsoft.XMLHTTP");
  3628. else
  3629. xhr = new XMLHttpRequest();
  3630. var datajs_filename = "data.js";
  3631. if (this.isWindows8App || this.isWindowsPhone8 || this.isWindowsPhone81 || this.isWindows10)
  3632. datajs_filename = "data.json";
  3633. xhr.open("GET", datajs_filename, true);
  3634. var supportsJsonResponse = false;
  3635. if (!this.isDomFree && ("response" in xhr) && ("responseType" in xhr))
  3636. {
  3637. try {
  3638. xhr["responseType"] = "json";
  3639. supportsJsonResponse = (xhr["responseType"] === "json");
  3640. }
  3641. catch (e) {
  3642. supportsJsonResponse = false;
  3643. }
  3644. }
  3645. if (!supportsJsonResponse && ("responseType" in xhr))
  3646. {
  3647. try {
  3648. xhr["responseType"] = "text";
  3649. }
  3650. catch (e) {}
  3651. }
  3652. if ("overrideMimeType" in xhr)
  3653. {
  3654. try {
  3655. xhr["overrideMimeType"]("application/json; charset=utf-8");
  3656. }
  3657. catch (e) {}
  3658. }
  3659. if (this.isWindowsPhone8)
  3660. {
  3661. xhr.onreadystatechange = function ()
  3662. {
  3663. if (xhr.readyState !== 4)
  3664. return;
  3665. self.loadProject(JSON.parse(xhr["responseText"]));
  3666. };
  3667. }
  3668. else
  3669. {
  3670. xhr.onload = function ()
  3671. {
  3672. if (supportsJsonResponse)
  3673. {
  3674. self.loadProject(xhr["response"]); // already parsed by browser
  3675. }
  3676. else
  3677. {
  3678. if (self.isEjecta)
  3679. {
  3680. var str = xhr["responseText"];
  3681. str = str.substr(str.indexOf("{")); // trim any BOM
  3682. self.loadProject(JSON.parse(str));
  3683. }
  3684. else
  3685. {
  3686. self.loadProject(JSON.parse(xhr["responseText"])); // forced to sync parse JSON
  3687. }
  3688. }
  3689. };
  3690. xhr.onerror = function (e)
  3691. {
  3692. cr.logerror("Error requesting " + datajs_filename + ":");
  3693. cr.logerror(e);
  3694. };
  3695. }
  3696. xhr.send();
  3697. };
  3698. Runtime.prototype.initRendererAndLoader = function ()
  3699. {
  3700. var self = this;
  3701. var i, len, j, lenj, k, lenk, t, s, l, y;
  3702. this.isRetina = ((!this.isDomFree || this.isEjecta || this.isCordova) && this.useHighDpi && !this.isAndroidStockBrowser);
  3703. if (this.fullscreen_mode === 0 && this.isiOS)
  3704. this.isRetina = false;
  3705. this.devicePixelRatio = (this.isRetina ? (window["devicePixelRatio"] || window["webkitDevicePixelRatio"] || window["mozDevicePixelRatio"] || window["msDevicePixelRatio"] || 1) : 1);
  3706. this.ClearDeathRow();
  3707. var attribs;
  3708. if (this.fullscreen_mode > 0)
  3709. this["setSize"](window.innerWidth, window.innerHeight, true);
  3710. this.canvas.addEventListener("webglcontextlost", function (ev) {
  3711. ev.preventDefault();
  3712. self.onContextLost();
  3713. cr.logexport("[Construct 2] WebGL context lost");
  3714. window["cr_setSuspended"](true); // stop rendering
  3715. }, false);
  3716. this.canvas.addEventListener("webglcontextrestored", function (ev) {
  3717. self.glwrap.initState();
  3718. self.glwrap.setSize(self.glwrap.width, self.glwrap.height, true);
  3719. self.layer_tex = null;
  3720. self.layout_tex = null;
  3721. self.fx_tex[0] = null;
  3722. self.fx_tex[1] = null;
  3723. self.onContextRestored();
  3724. self.redraw = true;
  3725. cr.logexport("[Construct 2] WebGL context restored");
  3726. window["cr_setSuspended"](false); // resume rendering
  3727. }, false);
  3728. try {
  3729. if (this.enableWebGL && (this.isCocoonJs || this.isEjecta || !this.isDomFree))
  3730. {
  3731. attribs = {
  3732. "alpha": true,
  3733. "depth": false,
  3734. "antialias": false,
  3735. "powerPreference": "high-performance",
  3736. "failIfMajorPerformanceCaveat": true
  3737. };
  3738. if (!this.isAndroid)
  3739. this.gl = this.canvas.getContext("webgl2", attribs);
  3740. if (!this.gl)
  3741. {
  3742. this.gl = (this.canvas.getContext("webgl", attribs) ||
  3743. this.canvas.getContext("experimental-webgl", attribs));
  3744. }
  3745. }
  3746. }
  3747. catch (e) {
  3748. }
  3749. if (this.gl)
  3750. {
  3751. var isWebGL2 = (this.gl.getParameter(this.gl.VERSION).indexOf("WebGL 2") === 0);
  3752. var debug_ext = this.gl.getExtension("WEBGL_debug_renderer_info");
  3753. if (debug_ext)
  3754. {
  3755. var unmasked_vendor = this.gl.getParameter(debug_ext.UNMASKED_VENDOR_WEBGL);
  3756. var unmasked_renderer = this.gl.getParameter(debug_ext.UNMASKED_RENDERER_WEBGL);
  3757. this.glUnmaskedRenderer = unmasked_renderer + " [" + unmasked_vendor + "]";
  3758. }
  3759. if (this.enableFrontToBack)
  3760. this.glUnmaskedRenderer += " [front-to-back enabled]";
  3761. ;
  3762. if (!this.isDomFree)
  3763. {
  3764. this.overlay_canvas = document.createElement("canvas");
  3765. jQuery(this.overlay_canvas).appendTo(this.canvas.parentNode);
  3766. this.overlay_canvas.oncontextmenu = function (e) { return false; };
  3767. this.overlay_canvas.onselectstart = function (e) { return false; };
  3768. this.overlay_canvas.width = Math.round(this.cssWidth * this.devicePixelRatio);
  3769. this.overlay_canvas.height = Math.round(this.cssHeight * this.devicePixelRatio);
  3770. jQuery(this.overlay_canvas).css({"width": this.cssWidth + "px",
  3771. "height": this.cssHeight + "px"});
  3772. this.positionOverlayCanvas();
  3773. this.overlay_ctx = this.overlay_canvas.getContext("2d");
  3774. }
  3775. this.glwrap = new cr.GLWrap(this.gl, this.isMobile, this.enableFrontToBack);
  3776. this.glwrap.setSize(this.canvas.width, this.canvas.height);
  3777. this.glwrap.enable_mipmaps = (this.downscalingQuality !== 0);
  3778. this.ctx = null;
  3779. for (i = 0, len = this.types_by_index.length; i < len; i++)
  3780. {
  3781. t = this.types_by_index[i];
  3782. for (j = 0, lenj = t.effect_types.length; j < lenj; j++)
  3783. {
  3784. s = t.effect_types[j];
  3785. s.shaderindex = this.glwrap.getShaderIndex(s.id);
  3786. s.preservesOpaqueness = this.glwrap.programPreservesOpaqueness(s.shaderindex);
  3787. this.uses_background_blending = this.uses_background_blending || this.glwrap.programUsesDest(s.shaderindex);
  3788. }
  3789. }
  3790. for (i = 0, len = this.layouts_by_index.length; i < len; i++)
  3791. {
  3792. l = this.layouts_by_index[i];
  3793. for (j = 0, lenj = l.effect_types.length; j < lenj; j++)
  3794. {
  3795. s = l.effect_types[j];
  3796. s.shaderindex = this.glwrap.getShaderIndex(s.id);
  3797. s.preservesOpaqueness = this.glwrap.programPreservesOpaqueness(s.shaderindex);
  3798. }
  3799. l.updateActiveEffects(); // update preserves opaqueness flag
  3800. for (j = 0, lenj = l.layers.length; j < lenj; j++)
  3801. {
  3802. y = l.layers[j];
  3803. for (k = 0, lenk = y.effect_types.length; k < lenk; k++)
  3804. {
  3805. s = y.effect_types[k];
  3806. s.shaderindex = this.glwrap.getShaderIndex(s.id);
  3807. s.preservesOpaqueness = this.glwrap.programPreservesOpaqueness(s.shaderindex);
  3808. this.uses_background_blending = this.uses_background_blending || this.glwrap.programUsesDest(s.shaderindex);
  3809. }
  3810. y.updateActiveEffects(); // update preserves opaqueness flag
  3811. }
  3812. }
  3813. }
  3814. else
  3815. {
  3816. if (this.fullscreen_mode > 0 && this.isDirectCanvas)
  3817. {
  3818. ;
  3819. this.canvas = null;
  3820. document.oncontextmenu = function (e) { return false; };
  3821. document.onselectstart = function (e) { return false; };
  3822. this.ctx = AppMobi["canvas"]["getContext"]("2d");
  3823. try {
  3824. this.ctx["samplingMode"] = this.linearSampling ? "smooth" : "sharp";
  3825. this.ctx["globalScale"] = 1;
  3826. this.ctx["HTML5CompatibilityMode"] = true;
  3827. this.ctx["imageSmoothingEnabled"] = this.linearSampling;
  3828. } catch(e){}
  3829. if (this.width !== 0 && this.height !== 0)
  3830. {
  3831. this.ctx.width = this.width;
  3832. this.ctx.height = this.height;
  3833. }
  3834. }
  3835. if (!this.ctx)
  3836. {
  3837. ;
  3838. if (this.isCocoonJs)
  3839. {
  3840. attribs = {
  3841. "antialias": !!this.linearSampling,
  3842. "alpha": true
  3843. };
  3844. this.ctx = this.canvas.getContext("2d", attribs);
  3845. }
  3846. else
  3847. {
  3848. attribs = {
  3849. "alpha": true
  3850. };
  3851. this.ctx = this.canvas.getContext("2d", attribs);
  3852. }
  3853. this.setCtxImageSmoothingEnabled(this.ctx, this.linearSampling);
  3854. }
  3855. this.overlay_canvas = null;
  3856. this.overlay_ctx = null;
  3857. }
  3858. this.tickFunc = function (timestamp) { self.tick(false, timestamp); };
  3859. if (window != window.top && !this.isDomFree && !this.isWinJS && !this.isWindowsPhone8)
  3860. {
  3861. document.addEventListener("mousedown", function () {
  3862. window.focus();
  3863. }, true);
  3864. document.addEventListener("touchstart", function () {
  3865. window.focus();
  3866. }, true);
  3867. }
  3868. if (typeof cr_is_preview !== "undefined")
  3869. {
  3870. if (this.isCocoonJs)
  3871. console.log("[Construct 2] In preview-over-wifi via CocoonJS mode");
  3872. if (window.location.search.indexOf("continuous") > -1)
  3873. {
  3874. cr.logexport("Reloading for continuous preview");
  3875. this.loadFromSlot = "__c2_continuouspreview";
  3876. this.suspendDrawing = true;
  3877. }
  3878. if (this.pauseOnBlur && !this.isMobile)
  3879. {
  3880. jQuery(window).focus(function ()
  3881. {
  3882. self["setSuspended"](false);
  3883. });
  3884. jQuery(window).blur(function ()
  3885. {
  3886. var parent = window.parent;
  3887. if (!parent || !parent.document.hasFocus())
  3888. self["setSuspended"](true);
  3889. });
  3890. }
  3891. }
  3892. window.addEventListener("blur", function () {
  3893. self.onWindowBlur();
  3894. });
  3895. if (!this.isDomFree)
  3896. {
  3897. var unfocusFormControlFunc = function (e) {
  3898. if (cr.isCanvasInputEvent(e) && document["activeElement"] && document["activeElement"] !== document.getElementsByTagName("body")[0] && document["activeElement"].blur)
  3899. {
  3900. try {
  3901. document["activeElement"].blur();
  3902. }
  3903. catch (e) {}
  3904. }
  3905. }
  3906. if (typeof PointerEvent !== "undefined")
  3907. {
  3908. document.addEventListener("pointerdown", unfocusFormControlFunc);
  3909. }
  3910. else if (window.navigator["msPointerEnabled"])
  3911. {
  3912. document.addEventListener("MSPointerDown", unfocusFormControlFunc);
  3913. }
  3914. else
  3915. {
  3916. document.addEventListener("touchstart", unfocusFormControlFunc);
  3917. }
  3918. document.addEventListener("mousedown", unfocusFormControlFunc);
  3919. }
  3920. if (this.fullscreen_mode === 0 && this.isRetina && this.devicePixelRatio > 1)
  3921. {
  3922. this["setSize"](this.original_width, this.original_height, true);
  3923. }
  3924. this.tryLockOrientation();
  3925. this.getready(); // determine things to preload
  3926. this.go(); // run loading screen
  3927. this.extra = {};
  3928. cr.seal(this);
  3929. };
  3930. var webkitRepaintFlag = false;
  3931. Runtime.prototype["setSize"] = function (w, h, force)
  3932. {
  3933. var offx = 0, offy = 0;
  3934. var neww = 0, newh = 0, intscale = 0;
  3935. if (this.lastWindowWidth === w && this.lastWindowHeight === h && !force)
  3936. return;
  3937. this.lastWindowWidth = w;
  3938. this.lastWindowHeight = h;
  3939. var mode = this.fullscreen_mode;
  3940. var orig_aspect, cur_aspect;
  3941. var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || !!document["msFullscreenElement"] || document["fullScreen"] || this.isNodeFullscreen) && !this.isCordova;
  3942. if (!isfullscreen && this.fullscreen_mode === 0 && !force)
  3943. return; // ignore size events when not fullscreen and not using a fullscreen-in-browser mode
  3944. if (isfullscreen)
  3945. mode = this.fullscreen_scaling;
  3946. var dpr = this.devicePixelRatio;
  3947. if (mode >= 4)
  3948. {
  3949. orig_aspect = this.original_width / this.original_height;
  3950. cur_aspect = w / h;
  3951. if (cur_aspect > orig_aspect)
  3952. {
  3953. neww = h * orig_aspect;
  3954. if (mode === 5) // integer scaling
  3955. {
  3956. intscale = (neww * dpr) / this.original_width;
  3957. if (intscale > 1)
  3958. intscale = Math.floor(intscale);
  3959. else if (intscale < 1)
  3960. intscale = 1 / Math.ceil(1 / intscale);
  3961. neww = this.original_width * intscale / dpr;
  3962. newh = this.original_height * intscale / dpr;
  3963. offx = (w - neww) / 2;
  3964. offy = (h - newh) / 2;
  3965. w = neww;
  3966. h = newh;
  3967. }
  3968. else
  3969. {
  3970. offx = (w - neww) / 2;
  3971. w = neww;
  3972. }
  3973. }
  3974. else
  3975. {
  3976. newh = w / orig_aspect;
  3977. if (mode === 5) // integer scaling
  3978. {
  3979. intscale = (newh * dpr) / this.original_height;
  3980. if (intscale > 1)
  3981. intscale = Math.floor(intscale);
  3982. else if (intscale < 1)
  3983. intscale = 1 / Math.ceil(1 / intscale);
  3984. neww = this.original_width * intscale / dpr;
  3985. newh = this.original_height * intscale / dpr;
  3986. offx = (w - neww) / 2;
  3987. offy = (h - newh) / 2;
  3988. w = neww;
  3989. h = newh;
  3990. }
  3991. else
  3992. {
  3993. offy = (h - newh) / 2;
  3994. h = newh;
  3995. }
  3996. }
  3997. }
  3998. else if (isfullscreen && mode === 0)
  3999. {
  4000. offx = Math.floor((w - this.original_width) / 2);
  4001. offy = Math.floor((h - this.original_height) / 2);
  4002. w = this.original_width;
  4003. h = this.original_height;
  4004. }
  4005. if (mode < 2)
  4006. this.aspect_scale = dpr;
  4007. this.cssWidth = Math.round(w);
  4008. this.cssHeight = Math.round(h);
  4009. this.width = Math.round(w * dpr);
  4010. this.height = Math.round(h * dpr);
  4011. this.redraw = true;
  4012. if (this.wantFullscreenScalingQuality)
  4013. {
  4014. this.draw_width = this.width;
  4015. this.draw_height = this.height;
  4016. this.fullscreenScalingQuality = true;
  4017. }
  4018. else
  4019. {
  4020. if ((this.width < this.original_width && this.height < this.original_height) || mode === 1)
  4021. {
  4022. this.draw_width = this.width;
  4023. this.draw_height = this.height;
  4024. this.fullscreenScalingQuality = true;
  4025. }
  4026. else
  4027. {
  4028. this.draw_width = this.original_width;
  4029. this.draw_height = this.original_height;
  4030. this.fullscreenScalingQuality = false;
  4031. /*var orig_aspect = this.original_width / this.original_height;
  4032. var cur_aspect = this.width / this.height;
  4033. if ((this.fullscreen_mode !== 2 && cur_aspect > orig_aspect) || (this.fullscreen_mode === 2 && cur_aspect < orig_aspect))
  4034. this.aspect_scale = this.height / this.original_height;
  4035. else
  4036. this.aspect_scale = this.width / this.original_width;*/
  4037. if (mode === 2) // scale inner
  4038. {
  4039. orig_aspect = this.original_width / this.original_height;
  4040. cur_aspect = this.lastWindowWidth / this.lastWindowHeight;
  4041. if (cur_aspect < orig_aspect)
  4042. this.draw_width = this.draw_height * cur_aspect;
  4043. else if (cur_aspect > orig_aspect)
  4044. this.draw_height = this.draw_width / cur_aspect;
  4045. }
  4046. else if (mode === 3)
  4047. {
  4048. orig_aspect = this.original_width / this.original_height;
  4049. cur_aspect = this.lastWindowWidth / this.lastWindowHeight;
  4050. if (cur_aspect > orig_aspect)
  4051. this.draw_width = this.draw_height * cur_aspect;
  4052. else if (cur_aspect < orig_aspect)
  4053. this.draw_height = this.draw_width / cur_aspect;
  4054. }
  4055. }
  4056. }
  4057. if (this.canvasdiv && !this.isDomFree)
  4058. {
  4059. jQuery(this.canvasdiv).css({"width": Math.round(w) + "px",
  4060. "height": Math.round(h) + "px",
  4061. "margin-left": Math.floor(offx) + "px",
  4062. "margin-top": Math.floor(offy) + "px"});
  4063. if (typeof cr_is_preview !== "undefined")
  4064. {
  4065. jQuery("#borderwrap").css({"width": Math.round(w) + "px",
  4066. "height": Math.round(h) + "px"});
  4067. }
  4068. }
  4069. if (this.canvas)
  4070. {
  4071. this.canvas.width = Math.round(w * dpr);
  4072. this.canvas.height = Math.round(h * dpr);
  4073. if (this.isEjecta)
  4074. {
  4075. this.canvas.style.left = Math.floor(offx) + "px";
  4076. this.canvas.style.top = Math.floor(offy) + "px";
  4077. this.canvas.style.width = Math.round(w) + "px";
  4078. this.canvas.style.height = Math.round(h) + "px";
  4079. }
  4080. else if (this.isRetina && !this.isDomFree)
  4081. {
  4082. this.canvas.style.width = Math.round(w) + "px";
  4083. this.canvas.style.height = Math.round(h) + "px";
  4084. }
  4085. }
  4086. if (this.overlay_canvas)
  4087. {
  4088. this.overlay_canvas.width = Math.round(w * dpr);
  4089. this.overlay_canvas.height = Math.round(h * dpr);
  4090. this.overlay_canvas.style.width = this.cssWidth + "px";
  4091. this.overlay_canvas.style.height = this.cssHeight + "px";
  4092. }
  4093. if (this.glwrap)
  4094. {
  4095. this.glwrap.setSize(Math.round(w * dpr), Math.round(h * dpr));
  4096. }
  4097. if (this.isDirectCanvas && this.ctx)
  4098. {
  4099. this.ctx.width = Math.round(w);
  4100. this.ctx.height = Math.round(h);
  4101. }
  4102. if (this.ctx)
  4103. {
  4104. this.setCtxImageSmoothingEnabled(this.ctx, this.linearSampling);
  4105. }
  4106. this.tryLockOrientation();
  4107. if (this.isiPhone && !this.isCordova)
  4108. {
  4109. window.scrollTo(0, 0);
  4110. }
  4111. };
  4112. Runtime.prototype.tryLockOrientation = function ()
  4113. {
  4114. if (!this.autoLockOrientation || this.orientations === 0)
  4115. return;
  4116. var orientation = "portrait";
  4117. if (this.orientations === 2)
  4118. orientation = "landscape";
  4119. try {
  4120. if (screen["orientation"] && screen["orientation"]["lock"])
  4121. screen["orientation"]["lock"](orientation).catch(function(){});
  4122. else if (screen["lockOrientation"])
  4123. screen["lockOrientation"](orientation);
  4124. else if (screen["webkitLockOrientation"])
  4125. screen["webkitLockOrientation"](orientation);
  4126. else if (screen["mozLockOrientation"])
  4127. screen["mozLockOrientation"](orientation);
  4128. else if (screen["msLockOrientation"])
  4129. screen["msLockOrientation"](orientation);
  4130. }
  4131. catch (e)
  4132. {
  4133. if (console && console.warn)
  4134. console.warn("Failed to lock orientation: ", e);
  4135. }
  4136. };
  4137. Runtime.prototype.onContextLost = function ()
  4138. {
  4139. this.glwrap.contextLost();
  4140. this.is_WebGL_context_lost = true;
  4141. var i, len, t;
  4142. for (i = 0, len = this.types_by_index.length; i < len; i++)
  4143. {
  4144. t = this.types_by_index[i];
  4145. if (t.onLostWebGLContext)
  4146. t.onLostWebGLContext();
  4147. }
  4148. };
  4149. Runtime.prototype.onContextRestored = function ()
  4150. {
  4151. this.is_WebGL_context_lost = false;
  4152. var i, len, t;
  4153. for (i = 0, len = this.types_by_index.length; i < len; i++)
  4154. {
  4155. t = this.types_by_index[i];
  4156. if (t.onRestoreWebGLContext)
  4157. t.onRestoreWebGLContext();
  4158. }
  4159. };
  4160. Runtime.prototype.positionOverlayCanvas = function()
  4161. {
  4162. if (this.isDomFree)
  4163. return;
  4164. var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || document["fullScreen"] || !!document["msFullscreenElement"] || this.isNodeFullscreen) && !this.isCordova;
  4165. var overlay_position = isfullscreen ? jQuery(this.canvas).offset() : jQuery(this.canvas).position();
  4166. overlay_position.position = "absolute";
  4167. jQuery(this.overlay_canvas).css(overlay_position);
  4168. };
  4169. var caf = window["cancelAnimationFrame"] ||
  4170. window["mozCancelAnimationFrame"] ||
  4171. window["webkitCancelAnimationFrame"] ||
  4172. window["msCancelAnimationFrame"] ||
  4173. window["oCancelAnimationFrame"];
  4174. Runtime.prototype["setSuspended"] = function (s)
  4175. {
  4176. var i, len;
  4177. var self = this;
  4178. if (s && !this.isSuspended)
  4179. {
  4180. cr.logexport("[Construct 2] Suspending");
  4181. this.isSuspended = true; // next tick will be last
  4182. if (this.raf_id !== -1 && caf) // note: CocoonJS does not implement cancelAnimationFrame
  4183. caf(this.raf_id);
  4184. if (this.timeout_id !== -1)
  4185. clearTimeout(this.timeout_id);
  4186. for (i = 0, len = this.suspend_events.length; i < len; i++)
  4187. this.suspend_events[i](true);
  4188. }
  4189. else if (!s && this.isSuspended)
  4190. {
  4191. cr.logexport("[Construct 2] Resuming");
  4192. this.isSuspended = false;
  4193. this.last_tick_time = cr.performance_now(); // ensure first tick is a zero-dt one
  4194. this.last_fps_time = cr.performance_now(); // reset FPS counter
  4195. this.framecount = 0;
  4196. this.logictime = 0;
  4197. for (i = 0, len = this.suspend_events.length; i < len; i++)
  4198. this.suspend_events[i](false);
  4199. this.tick(false); // kick off runtime again
  4200. }
  4201. };
  4202. Runtime.prototype.addSuspendCallback = function (f)
  4203. {
  4204. this.suspend_events.push(f);
  4205. };
  4206. Runtime.prototype.GetObjectReference = function (i)
  4207. {
  4208. ;
  4209. return this.objectRefTable[i];
  4210. };
  4211. Runtime.prototype.loadProject = function (data_response)
  4212. {
  4213. ;
  4214. if (!data_response || !data_response["project"])
  4215. cr.logerror("Project model unavailable");
  4216. var pm = data_response["project"];
  4217. this.name = pm[0];
  4218. this.first_layout = pm[1];
  4219. this.fullscreen_mode = pm[12]; // 0 = off, 1 = crop, 2 = scale inner, 3 = scale outer, 4 = letterbox scale, 5 = integer letterbox scale
  4220. this.fullscreen_mode_set = pm[12];
  4221. this.original_width = pm[10];
  4222. this.original_height = pm[11];
  4223. this.parallax_x_origin = this.original_width / 2;
  4224. this.parallax_y_origin = this.original_height / 2;
  4225. if (this.isDomFree && !this.isEjecta && (pm[12] >= 4 || pm[12] === 0))
  4226. {
  4227. cr.logexport("[Construct 2] Letterbox scale fullscreen modes are not supported on this platform - falling back to 'Scale outer'");
  4228. this.fullscreen_mode = 3;
  4229. this.fullscreen_mode_set = 3;
  4230. }
  4231. this.uses_loader_layout = pm[18];
  4232. this.loaderstyle = pm[19];
  4233. if (this.loaderstyle === 0)
  4234. {
  4235. var loaderImage = new Image();
  4236. loaderImage.crossOrigin = "anonymous";
  4237. this.setImageSrc(loaderImage, "loading-logo.png");
  4238. this.loaderlogos = {
  4239. logo: loaderImage
  4240. };
  4241. }
  4242. else if (this.loaderstyle === 4) // c2 splash
  4243. {
  4244. var loaderC2logo_1024 = new Image();
  4245. loaderC2logo_1024.src = "";
  4246. var loaderC2logo_512 = new Image();
  4247. loaderC2logo_512.src = "";
  4248. var loaderC2logo_256 = new Image();
  4249. loaderC2logo_256.src = "";
  4250. var loaderC2logo_128 = new Image();
  4251. loaderC2logo_128.src = "";
  4252. var loaderPowered_1024 = new Image();
  4253. loaderPowered_1024.src = "";
  4254. var loaderPowered_512 = new Image();
  4255. loaderPowered_512.src = "";
  4256. var loaderPowered_256 = new Image();
  4257. loaderPowered_256.src = "";
  4258. var loaderPowered_128 = new Image();
  4259. loaderPowered_128.src = "";
  4260. var loaderWebsite_1024 = new Image();
  4261. loaderWebsite_1024.src = "";
  4262. var loaderWebsite_512 = new Image();
  4263. loaderWebsite_512.src = "";
  4264. var loaderWebsite_256 = new Image();
  4265. loaderWebsite_256.src = "";
  4266. var loaderWebsite_128 = new Image();
  4267. loaderWebsite_128.src = "";
  4268. this.loaderlogos = {
  4269. logo: [loaderC2logo_1024, loaderC2logo_512, loaderC2logo_256, loaderC2logo_128],
  4270. powered: [loaderPowered_1024, loaderPowered_512, loaderPowered_256, loaderPowered_128],
  4271. website: [loaderWebsite_1024, loaderWebsite_512, loaderWebsite_256, loaderWebsite_128]
  4272. };
  4273. }
  4274. this.next_uid = pm[21];
  4275. this.objectRefTable = cr.getObjectRefTable();
  4276. this.system = new cr.system_object(this);
  4277. var i, len, j, lenj, k, lenk, idstr, m, b, t, f, p;
  4278. var plugin, plugin_ctor;
  4279. for (i = 0, len = pm[2].length; i < len; i++)
  4280. {
  4281. m = pm[2][i];
  4282. p = this.GetObjectReference(m[0]);
  4283. ;
  4284. cr.add_common_aces(m, p.prototype);
  4285. plugin = new p(this);
  4286. plugin.singleglobal = m[1];
  4287. plugin.is_world = m[2];
  4288. plugin.is_rotatable = m[5];
  4289. plugin.must_predraw = m[9];
  4290. if (plugin.onCreate)
  4291. plugin.onCreate(); // opportunity to override default ACEs
  4292. cr.seal(plugin);
  4293. this.plugins.push(plugin);
  4294. }
  4295. this.objectRefTable = cr.getObjectRefTable();
  4296. for (i = 0, len = pm[3].length; i < len; i++)
  4297. {
  4298. m = pm[3][i];
  4299. plugin_ctor = this.GetObjectReference(m[1]);
  4300. ;
  4301. plugin = null;
  4302. for (j = 0, lenj = this.plugins.length; j < lenj; j++)
  4303. {
  4304. if (this.plugins[j] instanceof plugin_ctor)
  4305. {
  4306. plugin = this.plugins[j];
  4307. break;
  4308. }
  4309. }
  4310. ;
  4311. ;
  4312. var type_inst = new plugin.Type(plugin);
  4313. ;
  4314. type_inst.name = m[0];
  4315. type_inst.is_family = m[2];
  4316. type_inst.instvar_sids = m[3].slice(0);
  4317. type_inst.vars_count = m[3].length;
  4318. type_inst.behs_count = m[4];
  4319. type_inst.fx_count = m[5];
  4320. type_inst.sid = m[11];
  4321. if (type_inst.is_family)
  4322. {
  4323. type_inst.members = []; // types in this family
  4324. type_inst.family_index = this.family_count++;
  4325. type_inst.families = null;
  4326. }
  4327. else
  4328. {
  4329. type_inst.members = null;
  4330. type_inst.family_index = -1;
  4331. type_inst.families = []; // families this type belongs to
  4332. }
  4333. type_inst.family_var_map = null;
  4334. type_inst.family_beh_map = null;
  4335. type_inst.family_fx_map = null;
  4336. type_inst.is_contained = false;
  4337. type_inst.container = null;
  4338. if (m[6])
  4339. {
  4340. type_inst.texture_file = m[6][0];
  4341. type_inst.texture_filesize = m[6][1];
  4342. type_inst.texture_pixelformat = m[6][2];
  4343. }
  4344. else
  4345. {
  4346. type_inst.texture_file = null;
  4347. type_inst.texture_filesize = 0;
  4348. type_inst.texture_pixelformat = 0; // rgba8
  4349. }
  4350. if (m[7])
  4351. {
  4352. type_inst.animations = m[7];
  4353. }
  4354. else
  4355. {
  4356. type_inst.animations = null;
  4357. }
  4358. type_inst.index = i; // save index in to types array in type
  4359. type_inst.instances = []; // all instances of this type
  4360. type_inst.deadCache = []; // destroyed instances to recycle next create
  4361. type_inst.solstack = [new cr.selection(type_inst)]; // initialise SOL stack with one empty SOL
  4362. type_inst.cur_sol = 0;
  4363. type_inst.default_instance = null;
  4364. type_inst.default_layerindex = 0;
  4365. type_inst.stale_iids = true;
  4366. type_inst.updateIIDs = cr.type_updateIIDs;
  4367. type_inst.getFirstPicked = cr.type_getFirstPicked;
  4368. type_inst.getPairedInstance = cr.type_getPairedInstance;
  4369. type_inst.getCurrentSol = cr.type_getCurrentSol;
  4370. type_inst.pushCleanSol = cr.type_pushCleanSol;
  4371. type_inst.pushCopySol = cr.type_pushCopySol;
  4372. type_inst.popSol = cr.type_popSol;
  4373. type_inst.getBehaviorByName = cr.type_getBehaviorByName;
  4374. type_inst.getBehaviorIndexByName = cr.type_getBehaviorIndexByName;
  4375. type_inst.getEffectIndexByName = cr.type_getEffectIndexByName;
  4376. type_inst.applySolToContainer = cr.type_applySolToContainer;
  4377. type_inst.getInstanceByIID = cr.type_getInstanceByIID;
  4378. type_inst.collision_grid = new cr.SparseGrid(this.original_width, this.original_height);
  4379. type_inst.any_cell_changed = true;
  4380. type_inst.any_instance_parallaxed = false;
  4381. type_inst.extra = {};
  4382. type_inst.toString = cr.type_toString;
  4383. type_inst.behaviors = [];
  4384. for (j = 0, lenj = m[8].length; j < lenj; j++)
  4385. {
  4386. b = m[8][j];
  4387. var behavior_ctor = this.GetObjectReference(b[1]);
  4388. var behavior_plugin = null;
  4389. for (k = 0, lenk = this.behaviors.length; k < lenk; k++)
  4390. {
  4391. if (this.behaviors[k] instanceof behavior_ctor)
  4392. {
  4393. behavior_plugin = this.behaviors[k];
  4394. break;
  4395. }
  4396. }
  4397. if (!behavior_plugin)
  4398. {
  4399. behavior_plugin = new behavior_ctor(this);
  4400. behavior_plugin.my_types = []; // types using this behavior
  4401. behavior_plugin.my_instances = new cr.ObjectSet(); // instances of this behavior
  4402. if (behavior_plugin.onCreate)
  4403. behavior_plugin.onCreate();
  4404. cr.seal(behavior_plugin);
  4405. this.behaviors.push(behavior_plugin);
  4406. if (cr.behaviors.solid && behavior_plugin instanceof cr.behaviors.solid)
  4407. this.solidBehavior = behavior_plugin;
  4408. if (cr.behaviors.jumpthru && behavior_plugin instanceof cr.behaviors.jumpthru)
  4409. this.jumpthruBehavior = behavior_plugin;
  4410. if (cr.behaviors.shadowcaster && behavior_plugin instanceof cr.behaviors.shadowcaster)
  4411. this.shadowcasterBehavior = behavior_plugin;
  4412. }
  4413. if (behavior_plugin.my_types.indexOf(type_inst) === -1)
  4414. behavior_plugin.my_types.push(type_inst);
  4415. var behavior_type = new behavior_plugin.Type(behavior_plugin, type_inst);
  4416. behavior_type.name = b[0];
  4417. behavior_type.sid = b[2];
  4418. behavior_type.onCreate();
  4419. cr.seal(behavior_type);
  4420. type_inst.behaviors.push(behavior_type);
  4421. }
  4422. type_inst.global = m[9];
  4423. type_inst.isOnLoaderLayout = m[10];
  4424. type_inst.effect_types = [];
  4425. for (j = 0, lenj = m[12].length; j < lenj; j++)
  4426. {
  4427. type_inst.effect_types.push({
  4428. id: m[12][j][0],
  4429. name: m[12][j][1],
  4430. shaderindex: -1,
  4431. preservesOpaqueness: false,
  4432. active: true,
  4433. index: j
  4434. });
  4435. }
  4436. type_inst.tile_poly_data = m[13];
  4437. if (!this.uses_loader_layout || type_inst.is_family || type_inst.isOnLoaderLayout || !plugin.is_world)
  4438. {
  4439. type_inst.onCreate();
  4440. cr.seal(type_inst);
  4441. }
  4442. if (type_inst.name)
  4443. this.types[type_inst.name] = type_inst;
  4444. this.types_by_index.push(type_inst);
  4445. if (plugin.singleglobal)
  4446. {
  4447. var instance = new plugin.Instance(type_inst);
  4448. instance.uid = this.next_uid++;
  4449. instance.puid = this.next_puid++;
  4450. instance.iid = 0;
  4451. instance.get_iid = cr.inst_get_iid;
  4452. instance.toString = cr.inst_toString;
  4453. instance.properties = m[14];
  4454. instance.onCreate();
  4455. cr.seal(instance);
  4456. type_inst.instances.push(instance);
  4457. this.objectsByUid[instance.uid.toString()] = instance;
  4458. }
  4459. }
  4460. for (i = 0, len = pm[4].length; i < len; i++)
  4461. {
  4462. var familydata = pm[4][i];
  4463. var familytype = this.types_by_index[familydata[0]];
  4464. var familymember;
  4465. for (j = 1, lenj = familydata.length; j < lenj; j++)
  4466. {
  4467. familymember = this.types_by_index[familydata[j]];
  4468. familymember.families.push(familytype);
  4469. familytype.members.push(familymember);
  4470. }
  4471. }
  4472. for (i = 0, len = pm[28].length; i < len; i++)
  4473. {
  4474. var containerdata = pm[28][i];
  4475. var containertypes = [];
  4476. for (j = 0, lenj = containerdata.length; j < lenj; j++)
  4477. containertypes.push(this.types_by_index[containerdata[j]]);
  4478. for (j = 0, lenj = containertypes.length; j < lenj; j++)
  4479. {
  4480. containertypes[j].is_contained = true;
  4481. containertypes[j].container = containertypes;
  4482. }
  4483. }
  4484. if (this.family_count > 0)
  4485. {
  4486. for (i = 0, len = this.types_by_index.length; i < len; i++)
  4487. {
  4488. t = this.types_by_index[i];
  4489. if (t.is_family || !t.families.length)
  4490. continue;
  4491. t.family_var_map = new Array(this.family_count);
  4492. t.family_beh_map = new Array(this.family_count);
  4493. t.family_fx_map = new Array(this.family_count);
  4494. var all_fx = [];
  4495. var varsum = 0;
  4496. var behsum = 0;
  4497. var fxsum = 0;
  4498. for (j = 0, lenj = t.families.length; j < lenj; j++)
  4499. {
  4500. f = t.families[j];
  4501. t.family_var_map[f.family_index] = varsum;
  4502. varsum += f.vars_count;
  4503. t.family_beh_map[f.family_index] = behsum;
  4504. behsum += f.behs_count;
  4505. t.family_fx_map[f.family_index] = fxsum;
  4506. fxsum += f.fx_count;
  4507. for (k = 0, lenk = f.effect_types.length; k < lenk; k++)
  4508. all_fx.push(cr.shallowCopy({}, f.effect_types[k]));
  4509. }
  4510. t.effect_types = all_fx.concat(t.effect_types);
  4511. for (j = 0, lenj = t.effect_types.length; j < lenj; j++)
  4512. t.effect_types[j].index = j;
  4513. }
  4514. }
  4515. for (i = 0, len = pm[5].length; i < len; i++)
  4516. {
  4517. m = pm[5][i];
  4518. var layout = new cr.layout(this, m);
  4519. cr.seal(layout);
  4520. this.layouts[layout.name] = layout;
  4521. this.layouts_by_index.push(layout);
  4522. }
  4523. for (i = 0, len = pm[6].length; i < len; i++)
  4524. {
  4525. m = pm[6][i];
  4526. var sheet = new cr.eventsheet(this, m);
  4527. cr.seal(sheet);
  4528. this.eventsheets[sheet.name] = sheet;
  4529. this.eventsheets_by_index.push(sheet);
  4530. }
  4531. for (i = 0, len = this.eventsheets_by_index.length; i < len; i++)
  4532. this.eventsheets_by_index[i].postInit();
  4533. for (i = 0, len = this.eventsheets_by_index.length; i < len; i++)
  4534. this.eventsheets_by_index[i].updateDeepIncludes();
  4535. for (i = 0, len = this.triggers_to_postinit.length; i < len; i++)
  4536. this.triggers_to_postinit[i].postInit();
  4537. cr.clearArray(this.triggers_to_postinit)
  4538. this.audio_to_preload = pm[7];
  4539. this.files_subfolder = pm[8];
  4540. this.pixel_rounding = pm[9];
  4541. this.aspect_scale = 1.0;
  4542. this.enableWebGL = pm[13];
  4543. this.linearSampling = pm[14];
  4544. this.clearBackground = pm[15];
  4545. this.versionstr = pm[16];
  4546. this.useHighDpi = pm[17];
  4547. this.orientations = pm[20]; // 0 = any, 1 = portrait, 2 = landscape
  4548. this.autoLockOrientation = (this.orientations > 0);
  4549. this.pauseOnBlur = pm[22];
  4550. this.wantFullscreenScalingQuality = pm[23]; // false = low quality, true = high quality
  4551. this.fullscreenScalingQuality = this.wantFullscreenScalingQuality;
  4552. this.downscalingQuality = pm[24]; // 0 = low (mips off), 1 = medium (mips on, dense spritesheet), 2 = high (mips on, sparse spritesheet)
  4553. this.preloadSounds = pm[25]; // 0 = no, 1 = yes
  4554. this.projectName = pm[26];
  4555. this.enableFrontToBack = pm[27] && !this.isIE; // front-to-back renderer disabled in IE (but not Edge)
  4556. this.start_time = Date.now();
  4557. cr.clearArray(this.objectRefTable);
  4558. this.initRendererAndLoader();
  4559. };
  4560. var anyImageHadError = false;
  4561. var MAX_PARALLEL_IMAGE_LOADS = 100;
  4562. var currentlyActiveImageLoads = 0;
  4563. var imageLoadQueue = []; // array of [img, srcToSet]
  4564. Runtime.prototype.queueImageLoad = function (img_, src_)
  4565. {
  4566. var self = this;
  4567. var doneFunc = function ()
  4568. {
  4569. currentlyActiveImageLoads--;
  4570. self.maybeLoadNextImages();
  4571. };
  4572. img_.addEventListener("load", doneFunc);
  4573. img_.addEventListener("error", doneFunc);
  4574. imageLoadQueue.push([img_, src_]);
  4575. this.maybeLoadNextImages();
  4576. };
  4577. Runtime.prototype.maybeLoadNextImages = function ()
  4578. {
  4579. var next;
  4580. while (imageLoadQueue.length && currentlyActiveImageLoads < MAX_PARALLEL_IMAGE_LOADS)
  4581. {
  4582. currentlyActiveImageLoads++;
  4583. next = imageLoadQueue.shift();
  4584. this.setImageSrc(next[0], next[1]);
  4585. }
  4586. };
  4587. Runtime.prototype.waitForImageLoad = function (img_, src_)
  4588. {
  4589. img_["cocoonLazyLoad"] = true;
  4590. img_.onerror = function (e)
  4591. {
  4592. img_.c2error = true;
  4593. anyImageHadError = true;
  4594. if (console && console.error)
  4595. console.error("Error loading image '" + img_.src + "': ", e);
  4596. };
  4597. if (this.isEjecta)
  4598. {
  4599. img_.src = src_;
  4600. }
  4601. else if (!img_.src)
  4602. {
  4603. if (typeof XAPKReader !== "undefined")
  4604. {
  4605. XAPKReader.get(src_, function (expanded_url)
  4606. {
  4607. img_.src = expanded_url;
  4608. }, function (e)
  4609. {
  4610. img_.c2error = true;
  4611. anyImageHadError = true;
  4612. if (console && console.error)
  4613. console.error("Error extracting image '" + src_ + "' from expansion file: ", e);
  4614. });
  4615. }
  4616. else
  4617. {
  4618. img_.crossOrigin = "anonymous"; // required for Arcade sandbox compatibility
  4619. this.queueImageLoad(img_, src_); // use a queue to avoid requesting all images simultaneously
  4620. }
  4621. }
  4622. this.wait_for_textures.push(img_);
  4623. };
  4624. Runtime.prototype.findWaitingTexture = function (src_)
  4625. {
  4626. var i, len;
  4627. for (i = 0, len = this.wait_for_textures.length; i < len; i++)
  4628. {
  4629. if (this.wait_for_textures[i].cr_src === src_)
  4630. return this.wait_for_textures[i];
  4631. }
  4632. return null;
  4633. };
  4634. var audio_preload_totalsize = 0;
  4635. var audio_preload_started = false;
  4636. Runtime.prototype.getready = function ()
  4637. {
  4638. if (!this.audioInstance)
  4639. return;
  4640. audio_preload_totalsize = this.audioInstance.setPreloadList(this.audio_to_preload);
  4641. };
  4642. Runtime.prototype.areAllTexturesAndSoundsLoaded = function ()
  4643. {
  4644. var totalsize = audio_preload_totalsize;
  4645. var completedsize = 0;
  4646. var audiocompletedsize = 0;
  4647. var ret = true;
  4648. var i, len, img;
  4649. for (i = 0, len = this.wait_for_textures.length; i < len; i++)
  4650. {
  4651. img = this.wait_for_textures[i];
  4652. var filesize = img.cr_filesize;
  4653. if (!filesize || filesize <= 0)
  4654. filesize = 50000;
  4655. totalsize += filesize;
  4656. if (!!img.src && (img.complete || img["loaded"]) && !img.c2error)
  4657. completedsize += filesize;
  4658. else
  4659. ret = false; // not all textures loaded
  4660. }
  4661. if (ret && this.preloadSounds && this.audioInstance)
  4662. {
  4663. if (!audio_preload_started)
  4664. {
  4665. this.audioInstance.startPreloads();
  4666. audio_preload_started = true;
  4667. }
  4668. audiocompletedsize = this.audioInstance.getPreloadedSize();
  4669. completedsize += audiocompletedsize;
  4670. if (audiocompletedsize < audio_preload_totalsize)
  4671. ret = false; // not done yet
  4672. }
  4673. if (totalsize == 0)
  4674. this.progress = 1; // indicate to C2 splash loader that it can finish now
  4675. else
  4676. this.progress = (completedsize / totalsize);
  4677. return ret;
  4678. };
  4679. var isC2SplashDone = false;
  4680. Runtime.prototype.go = function ()
  4681. {
  4682. if (!this.ctx && !this.glwrap)
  4683. return;
  4684. var ctx = this.ctx || this.overlay_ctx;
  4685. if (this.overlay_canvas)
  4686. this.positionOverlayCanvas();
  4687. var curwidth = window.innerWidth;
  4688. var curheight = window.innerHeight;
  4689. if (this.lastWindowWidth !== curwidth || this.lastWindowHeight !== curheight)
  4690. {
  4691. this["setSize"](curwidth, curheight);
  4692. }
  4693. this.progress = 0;
  4694. this.last_progress = -1;
  4695. var self = this;
  4696. if (this.areAllTexturesAndSoundsLoaded() && (this.loaderstyle !== 4 || isC2SplashDone))
  4697. {
  4698. this.go_loading_finished();
  4699. }
  4700. else
  4701. {
  4702. var ms_elapsed = Date.now() - this.start_time;
  4703. if (ctx)
  4704. {
  4705. var overlay_width = this.width;
  4706. var overlay_height = this.height;
  4707. var dpr = this.devicePixelRatio;
  4708. if (this.loaderstyle < 3 && (this.isCocoonJs || (ms_elapsed >= 500 && this.last_progress != this.progress)))
  4709. {
  4710. ctx.clearRect(0, 0, overlay_width, overlay_height);
  4711. var mx = overlay_width / 2;
  4712. var my = overlay_height / 2;
  4713. var haslogo = (this.loaderstyle === 0 && this.loaderlogos.logo.complete);
  4714. var hlw = 40 * dpr;
  4715. var hlh = 0;
  4716. var logowidth = 80 * dpr;
  4717. var logoheight;
  4718. if (haslogo)
  4719. {
  4720. var loaderLogoImage = this.loaderlogos.logo;
  4721. logowidth = loaderLogoImage.width * dpr;
  4722. logoheight = loaderLogoImage.height * dpr;
  4723. hlw = logowidth / 2;
  4724. hlh = logoheight / 2;
  4725. ctx.drawImage(loaderLogoImage, cr.floor(mx - hlw), cr.floor(my - hlh), logowidth, logoheight);
  4726. }
  4727. if (this.loaderstyle <= 1)
  4728. {
  4729. my += hlh + (haslogo ? 12 * dpr : 0);
  4730. mx -= hlw;
  4731. mx = cr.floor(mx) + 0.5;
  4732. my = cr.floor(my) + 0.5;
  4733. ctx.fillStyle = anyImageHadError ? "red" : "DodgerBlue";
  4734. ctx.fillRect(mx, my, Math.floor(logowidth * this.progress), 6 * dpr);
  4735. ctx.strokeStyle = "black";
  4736. ctx.strokeRect(mx, my, logowidth, 6 * dpr);
  4737. ctx.strokeStyle = "white";
  4738. ctx.strokeRect(mx - 1 * dpr, my - 1 * dpr, logowidth + 2 * dpr, 8 * dpr);
  4739. }
  4740. else if (this.loaderstyle === 2)
  4741. {
  4742. ctx.font = (this.isEjecta ? "12pt ArialMT" : "12pt Arial");
  4743. ctx.fillStyle = anyImageHadError ? "#f00" : "#999";
  4744. ctx.textBaseLine = "middle";
  4745. var percent_text = Math.round(this.progress * 100) + "%";
  4746. var text_dim = ctx.measureText ? ctx.measureText(percent_text) : null;
  4747. var text_width = text_dim ? text_dim.width : 0;
  4748. ctx.fillText(percent_text, mx - (text_width / 2), my);
  4749. }
  4750. this.last_progress = this.progress;
  4751. }
  4752. else if (this.loaderstyle === 4)
  4753. {
  4754. this.draw_c2_splash_loader(ctx);
  4755. if (raf)
  4756. raf(function() { self.go(); });
  4757. else
  4758. setTimeout(function() { self.go(); }, 16);
  4759. return;
  4760. }
  4761. }
  4762. setTimeout(function() { self.go(); }, (this.isCocoonJs ? 10 : 100));
  4763. }
  4764. };
  4765. var splashStartTime = -1;
  4766. var splashFadeInDuration = 300;
  4767. var splashFadeOutDuration = 300;
  4768. var splashAfterFadeOutWait = (typeof cr_is_preview === "undefined" ? 200 : 0);
  4769. var splashIsFadeIn = true;
  4770. var splashIsFadeOut = false;
  4771. var splashFadeInFinish = 0;
  4772. var splashFadeOutStart = 0;
  4773. var splashMinDisplayTime = (typeof cr_is_preview === "undefined" ? 3000 : 0);
  4774. var renderViaCanvas = null;
  4775. var renderViaCtx = null;
  4776. var splashFrameNumber = 0;
  4777. function maybeCreateRenderViaCanvas(w, h)
  4778. {
  4779. if (!renderViaCanvas || renderViaCanvas.width !== w || renderViaCanvas.height !== h)
  4780. {
  4781. renderViaCanvas = document.createElement("canvas");
  4782. renderViaCanvas.width = w;
  4783. renderViaCanvas.height = h;
  4784. renderViaCtx = renderViaCanvas.getContext("2d");
  4785. }
  4786. };
  4787. function mipImage(arr, size)
  4788. {
  4789. if (size <= 128)
  4790. return arr[3];
  4791. else if (size <= 256)
  4792. return arr[2];
  4793. else if (size <= 512)
  4794. return arr[1];
  4795. else
  4796. return arr[0];
  4797. };
  4798. Runtime.prototype.draw_c2_splash_loader = function(ctx)
  4799. {
  4800. if (isC2SplashDone)
  4801. return;
  4802. var w = Math.ceil(this.width);
  4803. var h = Math.ceil(this.height);
  4804. var dpr = this.devicePixelRatio;
  4805. var logoimages = this.loaderlogos.logo;
  4806. var poweredimages = this.loaderlogos.powered;
  4807. var websiteimages = this.loaderlogos.website;
  4808. for (var i = 0; i < 4; ++i)
  4809. {
  4810. if (!logoimages[i].complete || !poweredimages[i].complete || !websiteimages[i].complete)
  4811. return;
  4812. }
  4813. if (splashFrameNumber === 0)
  4814. splashStartTime = Date.now();
  4815. var nowTime = Date.now();
  4816. var isRenderingVia = false;
  4817. var renderToCtx = ctx;
  4818. var drawW, drawH;
  4819. if (splashIsFadeIn || splashIsFadeOut)
  4820. {
  4821. ctx.clearRect(0, 0, w, h);
  4822. maybeCreateRenderViaCanvas(w, h);
  4823. renderToCtx = renderViaCtx;
  4824. isRenderingVia = true;
  4825. if (splashIsFadeIn && splashFrameNumber === 1)
  4826. splashStartTime = Date.now();
  4827. }
  4828. else
  4829. {
  4830. ctx.globalAlpha = 1;
  4831. }
  4832. renderToCtx.fillStyle = "#333333";
  4833. renderToCtx.fillRect(0, 0, w, h);
  4834. if (this.cssHeight > 256)
  4835. {
  4836. drawW = cr.clamp(h * 0.22, 105, w * 0.6);
  4837. drawH = drawW * 0.25;
  4838. renderToCtx.drawImage(mipImage(poweredimages, drawW), w * 0.5 - drawW/2, h * 0.2 - drawH/2, drawW, drawH);
  4839. drawW = Math.min(h * 0.395, w * 0.95);
  4840. drawH = drawW;
  4841. renderToCtx.drawImage(mipImage(logoimages, drawW), w * 0.5 - drawW/2, h * 0.485 - drawH/2, drawW, drawH);
  4842. drawW = cr.clamp(h * 0.22, 105, w * 0.6);
  4843. drawH = drawW * 0.25;
  4844. renderToCtx.drawImage(mipImage(websiteimages, drawW), w * 0.5 - drawW/2, h * 0.868 - drawH/2, drawW, drawH);
  4845. renderToCtx.fillStyle = "#3C3C3C";
  4846. drawW = w;
  4847. drawH = Math.max(h * 0.005, 2);
  4848. renderToCtx.fillRect(0, h * 0.8 - drawH/2, drawW, drawH);
  4849. renderToCtx.fillStyle = anyImageHadError ? "red" : "#E0FF65";
  4850. drawW = w * this.progress;
  4851. renderToCtx.fillRect(w * 0.5 - drawW/2, h * 0.8 - drawH/2, drawW, drawH);
  4852. }
  4853. else
  4854. {
  4855. drawW = h * 0.55;
  4856. drawH = drawW;
  4857. renderToCtx.drawImage(mipImage(logoimages, drawW), w * 0.5 - drawW/2, h * 0.45 - drawH/2, drawW, drawH);
  4858. renderToCtx.fillStyle = "#3C3C3C";
  4859. drawW = w;
  4860. drawH = Math.max(h * 0.005, 2);
  4861. renderToCtx.fillRect(0, h * 0.85 - drawH/2, drawW, drawH);
  4862. renderToCtx.fillStyle = anyImageHadError ? "red" : "#E0FF65";
  4863. drawW = w * this.progress;
  4864. renderToCtx.fillRect(w * 0.5 - drawW/2, h * 0.85 - drawH/2, drawW, drawH);
  4865. }
  4866. if (isRenderingVia)
  4867. {
  4868. if (splashIsFadeIn)
  4869. {
  4870. if (splashFrameNumber === 0)
  4871. ctx.globalAlpha = 0;
  4872. else
  4873. ctx.globalAlpha = Math.min((nowTime - splashStartTime) / splashFadeInDuration, 1);
  4874. }
  4875. else if (splashIsFadeOut)
  4876. {
  4877. ctx.globalAlpha = Math.max(1 - (nowTime - splashFadeOutStart) / splashFadeOutDuration, 0);
  4878. }
  4879. ctx.drawImage(renderViaCanvas, 0, 0, w, h);
  4880. }
  4881. if (splashIsFadeIn && nowTime - splashStartTime >= splashFadeInDuration && splashFrameNumber >= 2)
  4882. {
  4883. splashIsFadeIn = false;
  4884. splashFadeInFinish = nowTime;
  4885. }
  4886. if (!splashIsFadeIn && nowTime - splashFadeInFinish >= splashMinDisplayTime && !splashIsFadeOut && this.progress >= 1)
  4887. {
  4888. splashIsFadeOut = true;
  4889. splashFadeOutStart = nowTime;
  4890. }
  4891. if ((splashIsFadeOut && nowTime - splashFadeOutStart >= splashFadeOutDuration + splashAfterFadeOutWait) ||
  4892. (typeof cr_is_preview !== "undefined" && this.progress >= 1 && Date.now() - splashStartTime < 500))
  4893. {
  4894. isC2SplashDone = true;
  4895. splashIsFadeIn = false;
  4896. splashIsFadeOut = false;
  4897. renderViaCanvas = null;
  4898. renderViaCtx = null;
  4899. this.loaderlogos = null;
  4900. }
  4901. ++splashFrameNumber;
  4902. };
  4903. Runtime.prototype.go_loading_finished = function ()
  4904. {
  4905. if (this.overlay_canvas)
  4906. {
  4907. this.canvas.parentNode.removeChild(this.overlay_canvas);
  4908. this.overlay_ctx = null;
  4909. this.overlay_canvas = null;
  4910. }
  4911. this.start_time = Date.now();
  4912. this.last_fps_time = cr.performance_now(); // for counting framerate
  4913. var i, len, t;
  4914. if (this.uses_loader_layout)
  4915. {
  4916. for (i = 0, len = this.types_by_index.length; i < len; i++)
  4917. {
  4918. t = this.types_by_index[i];
  4919. if (!t.is_family && !t.isOnLoaderLayout && t.plugin.is_world)
  4920. {
  4921. t.onCreate();
  4922. cr.seal(t);
  4923. }
  4924. }
  4925. }
  4926. else
  4927. this.isloading = false;
  4928. for (i = 0, len = this.layouts_by_index.length; i < len; i++)
  4929. {
  4930. this.layouts_by_index[i].createGlobalNonWorlds();
  4931. }
  4932. if (this.fullscreen_mode >= 2)
  4933. {
  4934. var orig_aspect = this.original_width / this.original_height;
  4935. var cur_aspect = this.width / this.height;
  4936. if ((this.fullscreen_mode !== 2 && cur_aspect > orig_aspect) || (this.fullscreen_mode === 2 && cur_aspect < orig_aspect))
  4937. this.aspect_scale = this.height / this.original_height;
  4938. else
  4939. this.aspect_scale = this.width / this.original_width;
  4940. }
  4941. if (this.first_layout)
  4942. this.layouts[this.first_layout].startRunning();
  4943. else
  4944. this.layouts_by_index[0].startRunning();
  4945. ;
  4946. if (!this.uses_loader_layout)
  4947. {
  4948. this.loadingprogress = 1;
  4949. this.trigger(cr.system_object.prototype.cnds.OnLoadFinished, null);
  4950. if (window["C2_RegisterSW"]) // note not all platforms use SW
  4951. window["C2_RegisterSW"]();
  4952. }
  4953. if (navigator["splashscreen"] && navigator["splashscreen"]["hide"])
  4954. navigator["splashscreen"]["hide"]();
  4955. for (i = 0, len = this.types_by_index.length; i < len; i++)
  4956. {
  4957. t = this.types_by_index[i];
  4958. if (t.onAppBegin)
  4959. t.onAppBegin();
  4960. }
  4961. if (document["hidden"] || document["webkitHidden"] || document["mozHidden"] || document["msHidden"])
  4962. {
  4963. window["cr_setSuspended"](true); // stop rendering
  4964. }
  4965. else
  4966. {
  4967. this.tick(false);
  4968. }
  4969. if (this.isDirectCanvas)
  4970. AppMobi["webview"]["execute"]("onGameReady();");
  4971. };
  4972. Runtime.prototype.tick = function (background_wake, timestamp, debug_step)
  4973. {
  4974. if (!this.running_layout)
  4975. return;
  4976. var nowtime = cr.performance_now();
  4977. var logic_start = nowtime;
  4978. if (!debug_step && this.isSuspended && !background_wake)
  4979. return;
  4980. if (!background_wake)
  4981. {
  4982. if (raf)
  4983. this.raf_id = raf(this.tickFunc);
  4984. else
  4985. {
  4986. this.timeout_id = setTimeout(this.tickFunc, this.isMobile ? 1 : 16);
  4987. }
  4988. }
  4989. var raf_time = timestamp || nowtime;
  4990. var fsmode = this.fullscreen_mode;
  4991. var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || document["fullScreen"] || !!document["msFullscreenElement"]) && !this.isCordova;
  4992. if ((isfullscreen || this.isNodeFullscreen) && this.fullscreen_scaling > 0)
  4993. fsmode = this.fullscreen_scaling;
  4994. if (fsmode > 0) // r222: experimentally enabling this workaround for all platforms
  4995. {
  4996. var curwidth = window.innerWidth;
  4997. var curheight = window.innerHeight;
  4998. if (this.lastWindowWidth !== curwidth || this.lastWindowHeight !== curheight)
  4999. {
  5000. this["setSize"](curwidth, curheight);
  5001. }
  5002. }
  5003. if (!this.isDomFree)
  5004. {
  5005. if (isfullscreen)
  5006. {
  5007. if (!this.firstInFullscreen)
  5008. this.firstInFullscreen = true;
  5009. }
  5010. else
  5011. {
  5012. if (this.firstInFullscreen)
  5013. {
  5014. this.firstInFullscreen = false;
  5015. if (this.fullscreen_mode === 0)
  5016. {
  5017. this["setSize"](Math.round(this.oldWidth / this.devicePixelRatio), Math.round(this.oldHeight / this.devicePixelRatio), true);
  5018. }
  5019. }
  5020. else
  5021. {
  5022. this.oldWidth = this.width;
  5023. this.oldHeight = this.height;
  5024. }
  5025. }
  5026. }
  5027. if (this.isloading)
  5028. {
  5029. var done = this.areAllTexturesAndSoundsLoaded(); // updates this.progress
  5030. this.loadingprogress = this.progress;
  5031. if (done)
  5032. {
  5033. this.isloading = false;
  5034. this.progress = 1;
  5035. this.trigger(cr.system_object.prototype.cnds.OnLoadFinished, null);
  5036. if (window["C2_RegisterSW"])
  5037. window["C2_RegisterSW"]();
  5038. }
  5039. }
  5040. this.logic(raf_time);
  5041. if ((this.redraw || this.isCocoonJs) && !this.is_WebGL_context_lost && !this.suspendDrawing && !background_wake)
  5042. {
  5043. this.redraw = false;
  5044. if (this.glwrap)
  5045. this.drawGL();
  5046. else
  5047. this.draw();
  5048. if (this.snapshotCanvas)
  5049. {
  5050. if (this.canvas && this.canvas.toDataURL)
  5051. {
  5052. this.snapshotData = this.canvas.toDataURL(this.snapshotCanvas[0], this.snapshotCanvas[1]);
  5053. if (window["cr_onSnapshot"])
  5054. window["cr_onSnapshot"](this.snapshotData);
  5055. this.trigger(cr.system_object.prototype.cnds.OnCanvasSnapshot, null);
  5056. }
  5057. this.snapshotCanvas = null;
  5058. }
  5059. }
  5060. if (!this.hit_breakpoint)
  5061. {
  5062. this.tickcount++;
  5063. this.tickcount_nosave++;
  5064. this.execcount++;
  5065. this.framecount++;
  5066. }
  5067. this.logictime += cr.performance_now() - logic_start;
  5068. };
  5069. Runtime.prototype.logic = function (cur_time)
  5070. {
  5071. var i, leni, j, lenj, k, lenk, type, inst, binst;
  5072. if (cur_time - this.last_fps_time >= 1000) // every 1 second
  5073. {
  5074. this.last_fps_time += 1000;
  5075. if (cur_time - this.last_fps_time >= 1000)
  5076. this.last_fps_time = cur_time;
  5077. this.fps = this.framecount;
  5078. this.framecount = 0;
  5079. this.cpuutilisation = this.logictime;
  5080. this.logictime = 0;
  5081. }
  5082. var wallDt = 0;
  5083. if (this.last_tick_time !== 0)
  5084. {
  5085. var ms_diff = cur_time - this.last_tick_time;
  5086. if (ms_diff < 0)
  5087. ms_diff = 0;
  5088. wallDt = ms_diff / 1000.0; // dt measured in seconds
  5089. this.dt1 = wallDt;
  5090. if (this.dt1 > 0.5)
  5091. this.dt1 = 0;
  5092. else if (this.dt1 > 1 / this.minimumFramerate)
  5093. this.dt1 = 1 / this.minimumFramerate;
  5094. }
  5095. this.last_tick_time = cur_time;
  5096. this.dt = this.dt1 * this.timescale;
  5097. this.kahanTime.add(this.dt);
  5098. this.wallTime.add(wallDt); // prevent min/max framerate affecting wall clock
  5099. var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || document["fullScreen"] || !!document["msFullscreenElement"] || this.isNodeFullscreen) && !this.isCordova;
  5100. if (this.fullscreen_mode >= 2 /* scale */ || (isfullscreen && this.fullscreen_scaling > 0))
  5101. {
  5102. var orig_aspect = this.original_width / this.original_height;
  5103. var cur_aspect = this.width / this.height;
  5104. var mode = this.fullscreen_mode;
  5105. if (isfullscreen && this.fullscreen_scaling > 0)
  5106. mode = this.fullscreen_scaling;
  5107. if ((mode !== 2 && cur_aspect > orig_aspect) || (mode === 2 && cur_aspect < orig_aspect))
  5108. {
  5109. this.aspect_scale = this.height / this.original_height;
  5110. }
  5111. else
  5112. {
  5113. this.aspect_scale = this.width / this.original_width;
  5114. }
  5115. if (this.running_layout)
  5116. {
  5117. this.running_layout.scrollToX(this.running_layout.scrollX);
  5118. this.running_layout.scrollToY(this.running_layout.scrollY);
  5119. }
  5120. }
  5121. else
  5122. this.aspect_scale = (this.isRetina ? this.devicePixelRatio : 1);
  5123. this.ClearDeathRow();
  5124. this.isInOnDestroy++;
  5125. this.system.runWaits(); // prevent instance list changing
  5126. this.isInOnDestroy--;
  5127. this.ClearDeathRow(); // allow instance list changing
  5128. this.isInOnDestroy++;
  5129. var tickarr = this.objects_to_pretick.valuesRef();
  5130. for (i = 0, leni = tickarr.length; i < leni; i++)
  5131. tickarr[i].pretick();
  5132. for (i = 0, leni = this.types_by_index.length; i < leni; i++)
  5133. {
  5134. type = this.types_by_index[i];
  5135. if (type.is_family || (!type.behaviors.length && !type.families.length))
  5136. continue;
  5137. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  5138. {
  5139. inst = type.instances[j];
  5140. for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++)
  5141. {
  5142. inst.behavior_insts[k].tick();
  5143. }
  5144. }
  5145. }
  5146. for (i = 0, leni = this.types_by_index.length; i < leni; i++)
  5147. {
  5148. type = this.types_by_index[i];
  5149. if (type.is_family || (!type.behaviors.length && !type.families.length))
  5150. continue; // type doesn't have any behaviors
  5151. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  5152. {
  5153. inst = type.instances[j];
  5154. for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++)
  5155. {
  5156. binst = inst.behavior_insts[k];
  5157. if (binst.posttick)
  5158. binst.posttick();
  5159. }
  5160. }
  5161. }
  5162. tickarr = this.objects_to_tick.valuesRef();
  5163. for (i = 0, leni = tickarr.length; i < leni; i++)
  5164. tickarr[i].tick();
  5165. this.isInOnDestroy--; // end preventing instance lists from being changed
  5166. this.handleSaveLoad(); // save/load now if queued
  5167. i = 0;
  5168. while (this.changelayout && i++ < 10)
  5169. {
  5170. this.doChangeLayout(this.changelayout);
  5171. }
  5172. for (i = 0, leni = this.eventsheets_by_index.length; i < leni; i++)
  5173. this.eventsheets_by_index[i].hasRun = false;
  5174. if (this.running_layout.event_sheet)
  5175. this.running_layout.event_sheet.run();
  5176. cr.clearArray(this.registered_collisions);
  5177. this.layout_first_tick = false;
  5178. this.isInOnDestroy++; // prevent instance lists from being changed
  5179. for (i = 0, leni = this.types_by_index.length; i < leni; i++)
  5180. {
  5181. type = this.types_by_index[i];
  5182. if (type.is_family || (!type.behaviors.length && !type.families.length))
  5183. continue; // type doesn't have any behaviors
  5184. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  5185. {
  5186. var inst = type.instances[j];
  5187. for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++)
  5188. {
  5189. binst = inst.behavior_insts[k];
  5190. if (binst.tick2)
  5191. binst.tick2();
  5192. }
  5193. }
  5194. }
  5195. tickarr = this.objects_to_tick2.valuesRef();
  5196. for (i = 0, leni = tickarr.length; i < leni; i++)
  5197. tickarr[i].tick2();
  5198. this.isInOnDestroy--; // end preventing instance lists from being changed
  5199. };
  5200. Runtime.prototype.onWindowBlur = function ()
  5201. {
  5202. var i, leni, j, lenj, k, lenk, type, inst, binst;
  5203. for (i = 0, leni = this.types_by_index.length; i < leni; i++)
  5204. {
  5205. type = this.types_by_index[i];
  5206. if (type.is_family)
  5207. continue;
  5208. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  5209. {
  5210. inst = type.instances[j];
  5211. if (inst.onWindowBlur)
  5212. inst.onWindowBlur();
  5213. if (!inst.behavior_insts)
  5214. continue; // single-globals don't have behavior_insts
  5215. for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++)
  5216. {
  5217. binst = inst.behavior_insts[k];
  5218. if (binst.onWindowBlur)
  5219. binst.onWindowBlur();
  5220. }
  5221. }
  5222. }
  5223. };
  5224. Runtime.prototype.doChangeLayout = function (changeToLayout)
  5225. {
  5226. var prev_layout = this.running_layout;
  5227. this.running_layout.stopRunning();
  5228. var i, len, j, lenj, k, lenk, type, inst, binst;
  5229. if (this.glwrap)
  5230. {
  5231. for (i = 0, len = this.types_by_index.length; i < len; i++)
  5232. {
  5233. type = this.types_by_index[i];
  5234. if (type.is_family)
  5235. continue;
  5236. if (type.unloadTextures && (!type.global || type.instances.length === 0) && changeToLayout.initial_types.indexOf(type) === -1)
  5237. {
  5238. type.unloadTextures();
  5239. }
  5240. }
  5241. }
  5242. if (prev_layout == changeToLayout)
  5243. cr.clearArray(this.system.waits);
  5244. cr.clearArray(this.registered_collisions);
  5245. this.runLayoutChangeMethods(true);
  5246. changeToLayout.startRunning();
  5247. this.runLayoutChangeMethods(false);
  5248. this.redraw = true;
  5249. this.layout_first_tick = true;
  5250. this.ClearDeathRow();
  5251. };
  5252. Runtime.prototype.runLayoutChangeMethods = function (isBeforeChange)
  5253. {
  5254. var i, len, beh, type, j, lenj, inst, k, lenk, binst;
  5255. for (i = 0, len = this.behaviors.length; i < len; i++)
  5256. {
  5257. beh = this.behaviors[i];
  5258. if (isBeforeChange)
  5259. {
  5260. if (beh.onBeforeLayoutChange)
  5261. beh.onBeforeLayoutChange();
  5262. }
  5263. else
  5264. {
  5265. if (beh.onLayoutChange)
  5266. beh.onLayoutChange();
  5267. }
  5268. }
  5269. for (i = 0, len = this.types_by_index.length; i < len; i++)
  5270. {
  5271. type = this.types_by_index[i];
  5272. if (!type.global && !type.plugin.singleglobal)
  5273. continue;
  5274. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  5275. {
  5276. inst = type.instances[j];
  5277. if (isBeforeChange)
  5278. {
  5279. if (inst.onBeforeLayoutChange)
  5280. inst.onBeforeLayoutChange();
  5281. }
  5282. else
  5283. {
  5284. if (inst.onLayoutChange)
  5285. inst.onLayoutChange();
  5286. }
  5287. if (inst.behavior_insts)
  5288. {
  5289. for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++)
  5290. {
  5291. binst = inst.behavior_insts[k];
  5292. if (isBeforeChange)
  5293. {
  5294. if (binst.onBeforeLayoutChange)
  5295. binst.onBeforeLayoutChange();
  5296. }
  5297. else
  5298. {
  5299. if (binst.onLayoutChange)
  5300. binst.onLayoutChange();
  5301. }
  5302. }
  5303. }
  5304. }
  5305. }
  5306. };
  5307. Runtime.prototype.pretickMe = function (inst)
  5308. {
  5309. this.objects_to_pretick.add(inst);
  5310. };
  5311. Runtime.prototype.unpretickMe = function (inst)
  5312. {
  5313. this.objects_to_pretick.remove(inst);
  5314. };
  5315. Runtime.prototype.tickMe = function (inst)
  5316. {
  5317. this.objects_to_tick.add(inst);
  5318. };
  5319. Runtime.prototype.untickMe = function (inst)
  5320. {
  5321. this.objects_to_tick.remove(inst);
  5322. };
  5323. Runtime.prototype.tick2Me = function (inst)
  5324. {
  5325. this.objects_to_tick2.add(inst);
  5326. };
  5327. Runtime.prototype.untick2Me = function (inst)
  5328. {
  5329. this.objects_to_tick2.remove(inst);
  5330. };
  5331. Runtime.prototype.getDt = function (inst)
  5332. {
  5333. if (!inst || inst.my_timescale === -1.0)
  5334. return this.dt;
  5335. return this.dt1 * inst.my_timescale;
  5336. };
  5337. Runtime.prototype.draw = function ()
  5338. {
  5339. this.running_layout.draw(this.ctx);
  5340. if (this.isDirectCanvas)
  5341. this.ctx["present"]();
  5342. };
  5343. Runtime.prototype.drawGL = function ()
  5344. {
  5345. if (this.enableFrontToBack)
  5346. {
  5347. this.earlyz_index = 1; // start from front, 1-based to avoid exactly equalling near plane Z value
  5348. this.running_layout.drawGL_earlyZPass(this.glwrap);
  5349. }
  5350. this.running_layout.drawGL(this.glwrap);
  5351. this.glwrap.present();
  5352. };
  5353. Runtime.prototype.addDestroyCallback = function (f)
  5354. {
  5355. if (f)
  5356. this.destroycallbacks.push(f);
  5357. };
  5358. Runtime.prototype.removeDestroyCallback = function (f)
  5359. {
  5360. cr.arrayFindRemove(this.destroycallbacks, f);
  5361. };
  5362. Runtime.prototype.getObjectByUID = function (uid_)
  5363. {
  5364. ;
  5365. var uidstr = uid_.toString();
  5366. if (this.objectsByUid.hasOwnProperty(uidstr))
  5367. return this.objectsByUid[uidstr];
  5368. else
  5369. return null;
  5370. };
  5371. var objectset_cache = [];
  5372. function alloc_objectset()
  5373. {
  5374. if (objectset_cache.length)
  5375. return objectset_cache.pop();
  5376. else
  5377. return new cr.ObjectSet();
  5378. };
  5379. function free_objectset(s)
  5380. {
  5381. s.clear();
  5382. objectset_cache.push(s);
  5383. };
  5384. Runtime.prototype.DestroyInstance = function (inst)
  5385. {
  5386. var i, len;
  5387. var type = inst.type;
  5388. var typename = type.name;
  5389. var has_typename = this.deathRow.hasOwnProperty(typename);
  5390. var obj_set = null;
  5391. if (has_typename)
  5392. {
  5393. obj_set = this.deathRow[typename];
  5394. if (obj_set.contains(inst))
  5395. return; // already had DestroyInstance called
  5396. }
  5397. else
  5398. {
  5399. obj_set = alloc_objectset();
  5400. this.deathRow[typename] = obj_set;
  5401. }
  5402. obj_set.add(inst);
  5403. this.hasPendingInstances = true;
  5404. if (inst.is_contained)
  5405. {
  5406. for (i = 0, len = inst.siblings.length; i < len; i++)
  5407. {
  5408. this.DestroyInstance(inst.siblings[i]);
  5409. }
  5410. }
  5411. if (this.isInClearDeathRow)
  5412. obj_set.values_cache.push(inst);
  5413. if (!this.isEndingLayout)
  5414. {
  5415. this.isInOnDestroy++; // support recursion
  5416. this.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnDestroyed, inst);
  5417. this.isInOnDestroy--;
  5418. }
  5419. };
  5420. Runtime.prototype.ClearDeathRow = function ()
  5421. {
  5422. if (!this.hasPendingInstances)
  5423. return;
  5424. var inst, type, instances;
  5425. var i, j, leni, lenj, obj_set;
  5426. this.isInClearDeathRow = true;
  5427. for (i = 0, leni = this.createRow.length; i < leni; ++i)
  5428. {
  5429. inst = this.createRow[i];
  5430. type = inst.type;
  5431. type.instances.push(inst);
  5432. for (j = 0, lenj = type.families.length; j < lenj; ++j)
  5433. {
  5434. type.families[j].instances.push(inst);
  5435. type.families[j].stale_iids = true;
  5436. }
  5437. }
  5438. cr.clearArray(this.createRow);
  5439. this.IterateDeathRow(); // moved to separate function so for-in performance doesn't hobble entire function
  5440. cr.wipe(this.deathRow); // all objectsets have already been recycled
  5441. this.isInClearDeathRow = false;
  5442. this.hasPendingInstances = false;
  5443. };
  5444. Runtime.prototype.IterateDeathRow = function ()
  5445. {
  5446. for (var p in this.deathRow)
  5447. {
  5448. if (this.deathRow.hasOwnProperty(p))
  5449. {
  5450. this.ClearDeathRowForType(this.deathRow[p]);
  5451. }
  5452. }
  5453. };
  5454. Runtime.prototype.ClearDeathRowForType = function (obj_set)
  5455. {
  5456. var arr = obj_set.valuesRef(); // get array of items from set
  5457. ;
  5458. var type = arr[0].type;
  5459. ;
  5460. ;
  5461. var i, len, j, lenj, w, f, layer_instances, inst;
  5462. cr.arrayRemoveAllFromObjectSet(type.instances, obj_set);
  5463. type.stale_iids = true;
  5464. if (type.instances.length === 0)
  5465. type.any_instance_parallaxed = false;
  5466. for (i = 0, len = type.families.length; i < len; ++i)
  5467. {
  5468. f = type.families[i];
  5469. cr.arrayRemoveAllFromObjectSet(f.instances, obj_set);
  5470. f.stale_iids = true;
  5471. }
  5472. for (i = 0, len = this.system.waits.length; i < len; ++i)
  5473. {
  5474. w = this.system.waits[i];
  5475. if (w.sols.hasOwnProperty(type.index))
  5476. cr.arrayRemoveAllFromObjectSet(w.sols[type.index].insts, obj_set);
  5477. if (!type.is_family)
  5478. {
  5479. for (j = 0, lenj = type.families.length; j < lenj; ++j)
  5480. {
  5481. f = type.families[j];
  5482. if (w.sols.hasOwnProperty(f.index))
  5483. cr.arrayRemoveAllFromObjectSet(w.sols[f.index].insts, obj_set);
  5484. }
  5485. }
  5486. }
  5487. var first_layer = arr[0].layer;
  5488. if (first_layer)
  5489. {
  5490. if (first_layer.useRenderCells)
  5491. {
  5492. layer_instances = first_layer.instances;
  5493. for (i = 0, len = layer_instances.length; i < len; ++i)
  5494. {
  5495. inst = layer_instances[i];
  5496. if (!obj_set.contains(inst))
  5497. continue; // not destroying this instance
  5498. inst.update_bbox();
  5499. first_layer.render_grid.update(inst, inst.rendercells, null);
  5500. inst.rendercells.set(0, 0, -1, -1);
  5501. }
  5502. }
  5503. cr.arrayRemoveAllFromObjectSet(first_layer.instances, obj_set);
  5504. first_layer.setZIndicesStaleFrom(0);
  5505. }
  5506. for (i = 0; i < arr.length; ++i) // check array length every time in case it changes
  5507. {
  5508. this.ClearDeathRowForSingleInstance(arr[i], type);
  5509. }
  5510. free_objectset(obj_set);
  5511. this.redraw = true;
  5512. };
  5513. Runtime.prototype.ClearDeathRowForSingleInstance = function (inst, type)
  5514. {
  5515. var i, len, binst;
  5516. for (i = 0, len = this.destroycallbacks.length; i < len; ++i)
  5517. this.destroycallbacks[i](inst);
  5518. if (inst.collcells)
  5519. {
  5520. type.collision_grid.update(inst, inst.collcells, null);
  5521. }
  5522. var layer = inst.layer;
  5523. if (layer)
  5524. {
  5525. layer.removeFromInstanceList(inst, true); // remove from both instance list and render grid
  5526. }
  5527. if (inst.behavior_insts)
  5528. {
  5529. for (i = 0, len = inst.behavior_insts.length; i < len; ++i)
  5530. {
  5531. binst = inst.behavior_insts[i];
  5532. if (binst.onDestroy)
  5533. binst.onDestroy();
  5534. binst.behavior.my_instances.remove(inst);
  5535. }
  5536. }
  5537. this.objects_to_pretick.remove(inst);
  5538. this.objects_to_tick.remove(inst);
  5539. this.objects_to_tick2.remove(inst);
  5540. if (inst.onDestroy)
  5541. inst.onDestroy();
  5542. if (this.objectsByUid.hasOwnProperty(inst.uid.toString()))
  5543. delete this.objectsByUid[inst.uid.toString()];
  5544. this.objectcount--;
  5545. if (type.deadCache.length < 100)
  5546. type.deadCache.push(inst);
  5547. };
  5548. Runtime.prototype.createInstance = function (type, layer, sx, sy)
  5549. {
  5550. if (type.is_family)
  5551. {
  5552. var i = cr.floor(Math.random() * type.members.length);
  5553. return this.createInstance(type.members[i], layer, sx, sy);
  5554. }
  5555. if (!type.default_instance)
  5556. {
  5557. return null;
  5558. }
  5559. return this.createInstanceFromInit(type.default_instance, layer, false, sx, sy, false);
  5560. };
  5561. var all_behaviors = [];
  5562. Runtime.prototype.createInstanceFromInit = function (initial_inst, layer, is_startup_instance, sx, sy, skip_siblings)
  5563. {
  5564. var i, len, j, lenj, p, effect_fallback, x, y;
  5565. if (!initial_inst)
  5566. return null;
  5567. var type = this.types_by_index[initial_inst[1]];
  5568. ;
  5569. ;
  5570. var is_world = type.plugin.is_world;
  5571. ;
  5572. if (this.isloading && is_world && !type.isOnLoaderLayout)
  5573. return null;
  5574. if (is_world && !this.glwrap && initial_inst[0][11] === 11)
  5575. return null;
  5576. var original_layer = layer;
  5577. if (!is_world)
  5578. layer = null;
  5579. var inst;
  5580. if (type.deadCache.length)
  5581. {
  5582. inst = type.deadCache.pop();
  5583. inst.recycled = true;
  5584. type.plugin.Instance.call(inst, type);
  5585. }
  5586. else
  5587. {
  5588. inst = new type.plugin.Instance(type);
  5589. inst.recycled = false;
  5590. }
  5591. if (is_startup_instance && !skip_siblings && !this.objectsByUid.hasOwnProperty(initial_inst[2].toString()))
  5592. inst.uid = initial_inst[2];
  5593. else
  5594. inst.uid = this.next_uid++;
  5595. this.objectsByUid[inst.uid.toString()] = inst;
  5596. inst.puid = this.next_puid++;
  5597. inst.iid = type.instances.length;
  5598. for (i = 0, len = this.createRow.length; i < len; ++i)
  5599. {
  5600. if (this.createRow[i].type === type)
  5601. inst.iid++;
  5602. }
  5603. inst.get_iid = cr.inst_get_iid;
  5604. inst.toString = cr.inst_toString;
  5605. var initial_vars = initial_inst[3];
  5606. if (inst.recycled)
  5607. {
  5608. cr.wipe(inst.extra);
  5609. }
  5610. else
  5611. {
  5612. inst.extra = {};
  5613. if (typeof cr_is_preview !== "undefined")
  5614. {
  5615. inst.instance_var_names = [];
  5616. inst.instance_var_names.length = initial_vars.length;
  5617. for (i = 0, len = initial_vars.length; i < len; i++)
  5618. inst.instance_var_names[i] = initial_vars[i][1];
  5619. }
  5620. inst.instance_vars = [];
  5621. inst.instance_vars.length = initial_vars.length;
  5622. }
  5623. for (i = 0, len = initial_vars.length; i < len; i++)
  5624. inst.instance_vars[i] = initial_vars[i][0];
  5625. if (is_world)
  5626. {
  5627. var wm = initial_inst[0];
  5628. ;
  5629. inst.x = cr.is_undefined(sx) ? wm[0] : sx;
  5630. inst.y = cr.is_undefined(sy) ? wm[1] : sy;
  5631. inst.z = wm[2];
  5632. inst.width = wm[3];
  5633. inst.height = wm[4];
  5634. inst.depth = wm[5];
  5635. inst.angle = wm[6];
  5636. inst.opacity = wm[7];
  5637. inst.hotspotX = wm[8];
  5638. inst.hotspotY = wm[9];
  5639. inst.blend_mode = wm[10];
  5640. effect_fallback = wm[11];
  5641. if (!this.glwrap && type.effect_types.length) // no WebGL renderer and shaders used
  5642. inst.blend_mode = effect_fallback; // use fallback blend mode - destroy mode was handled above
  5643. inst.compositeOp = cr.effectToCompositeOp(inst.blend_mode);
  5644. if (this.gl)
  5645. cr.setGLBlend(inst, inst.blend_mode, this.gl);
  5646. if (inst.recycled)
  5647. {
  5648. for (i = 0, len = wm[12].length; i < len; i++)
  5649. {
  5650. for (j = 0, lenj = wm[12][i].length; j < lenj; j++)
  5651. inst.effect_params[i][j] = wm[12][i][j];
  5652. }
  5653. inst.bbox.set(0, 0, 0, 0);
  5654. inst.collcells.set(0, 0, -1, -1);
  5655. inst.rendercells.set(0, 0, -1, -1);
  5656. inst.bquad.set_from_rect(inst.bbox);
  5657. cr.clearArray(inst.bbox_changed_callbacks);
  5658. }
  5659. else
  5660. {
  5661. inst.effect_params = wm[12].slice(0);
  5662. for (i = 0, len = inst.effect_params.length; i < len; i++)
  5663. inst.effect_params[i] = wm[12][i].slice(0);
  5664. inst.active_effect_types = [];
  5665. inst.active_effect_flags = [];
  5666. inst.active_effect_flags.length = type.effect_types.length;
  5667. inst.bbox = new cr.rect(0, 0, 0, 0);
  5668. inst.collcells = new cr.rect(0, 0, -1, -1);
  5669. inst.rendercells = new cr.rect(0, 0, -1, -1);
  5670. inst.bquad = new cr.quad();
  5671. inst.bbox_changed_callbacks = [];
  5672. inst.set_bbox_changed = cr.set_bbox_changed;
  5673. inst.add_bbox_changed_callback = cr.add_bbox_changed_callback;
  5674. inst.contains_pt = cr.inst_contains_pt;
  5675. inst.update_bbox = cr.update_bbox;
  5676. inst.update_render_cell = cr.update_render_cell;
  5677. inst.update_collision_cell = cr.update_collision_cell;
  5678. inst.get_zindex = cr.inst_get_zindex;
  5679. }
  5680. inst.tilemap_exists = false;
  5681. inst.tilemap_width = 0;
  5682. inst.tilemap_height = 0;
  5683. inst.tilemap_data = null;
  5684. if (wm.length === 14)
  5685. {
  5686. inst.tilemap_exists = true;
  5687. inst.tilemap_width = wm[13][0];
  5688. inst.tilemap_height = wm[13][1];
  5689. inst.tilemap_data = wm[13][2];
  5690. }
  5691. for (i = 0, len = type.effect_types.length; i < len; i++)
  5692. inst.active_effect_flags[i] = true;
  5693. inst.shaders_preserve_opaqueness = true;
  5694. inst.updateActiveEffects = cr.inst_updateActiveEffects;
  5695. inst.updateActiveEffects();
  5696. inst.uses_shaders = !!inst.active_effect_types.length;
  5697. inst.bbox_changed = true;
  5698. inst.cell_changed = true;
  5699. type.any_cell_changed = true;
  5700. inst.visible = true;
  5701. inst.my_timescale = -1.0;
  5702. inst.layer = layer;
  5703. inst.zindex = layer.instances.length; // will be placed at top of current layer
  5704. inst.earlyz_index = 0;
  5705. if (typeof inst.collision_poly === "undefined")
  5706. inst.collision_poly = null;
  5707. inst.collisionsEnabled = true;
  5708. this.redraw = true;
  5709. }
  5710. var initial_props, binst;
  5711. cr.clearArray(all_behaviors);
  5712. for (i = 0, len = type.families.length; i < len; i++)
  5713. {
  5714. all_behaviors.push.apply(all_behaviors, type.families[i].behaviors);
  5715. }
  5716. all_behaviors.push.apply(all_behaviors, type.behaviors);
  5717. if (inst.recycled)
  5718. {
  5719. for (i = 0, len = all_behaviors.length; i < len; i++)
  5720. {
  5721. var btype = all_behaviors[i];
  5722. binst = inst.behavior_insts[i];
  5723. binst.recycled = true;
  5724. btype.behavior.Instance.call(binst, btype, inst);
  5725. initial_props = initial_inst[4][i];
  5726. for (j = 0, lenj = initial_props.length; j < lenj; j++)
  5727. binst.properties[j] = initial_props[j];
  5728. binst.onCreate();
  5729. btype.behavior.my_instances.add(inst);
  5730. }
  5731. }
  5732. else
  5733. {
  5734. inst.behavior_insts = [];
  5735. for (i = 0, len = all_behaviors.length; i < len; i++)
  5736. {
  5737. var btype = all_behaviors[i];
  5738. var binst = new btype.behavior.Instance(btype, inst);
  5739. binst.recycled = false;
  5740. binst.properties = initial_inst[4][i].slice(0);
  5741. binst.onCreate();
  5742. cr.seal(binst);
  5743. inst.behavior_insts.push(binst);
  5744. btype.behavior.my_instances.add(inst);
  5745. }
  5746. }
  5747. initial_props = initial_inst[5];
  5748. if (inst.recycled)
  5749. {
  5750. for (i = 0, len = initial_props.length; i < len; i++)
  5751. inst.properties[i] = initial_props[i];
  5752. }
  5753. else
  5754. inst.properties = initial_props.slice(0);
  5755. this.createRow.push(inst);
  5756. this.hasPendingInstances = true;
  5757. if (layer)
  5758. {
  5759. ;
  5760. layer.appendToInstanceList(inst, true);
  5761. if (layer.parallaxX !== 1 || layer.parallaxY !== 1)
  5762. type.any_instance_parallaxed = true;
  5763. }
  5764. this.objectcount++;
  5765. if (type.is_contained)
  5766. {
  5767. inst.is_contained = true;
  5768. if (inst.recycled)
  5769. cr.clearArray(inst.siblings);
  5770. else
  5771. inst.siblings = []; // note: should not include self in siblings
  5772. if (!is_startup_instance && !skip_siblings) // layout links initial instances
  5773. {
  5774. for (i = 0, len = type.container.length; i < len; i++)
  5775. {
  5776. if (type.container[i] === type)
  5777. continue;
  5778. if (!type.container[i].default_instance)
  5779. {
  5780. return null;
  5781. }
  5782. inst.siblings.push(this.createInstanceFromInit(type.container[i].default_instance, original_layer, false, is_world ? inst.x : sx, is_world ? inst.y : sy, true));
  5783. }
  5784. for (i = 0, len = inst.siblings.length; i < len; i++)
  5785. {
  5786. inst.siblings[i].siblings.push(inst);
  5787. for (j = 0; j < len; j++)
  5788. {
  5789. if (i !== j)
  5790. inst.siblings[i].siblings.push(inst.siblings[j]);
  5791. }
  5792. }
  5793. }
  5794. }
  5795. else
  5796. {
  5797. inst.is_contained = false;
  5798. inst.siblings = null;
  5799. }
  5800. inst.onCreate();
  5801. if (!inst.recycled)
  5802. cr.seal(inst);
  5803. for (i = 0, len = inst.behavior_insts.length; i < len; i++)
  5804. {
  5805. if (inst.behavior_insts[i].postCreate)
  5806. inst.behavior_insts[i].postCreate();
  5807. }
  5808. return inst;
  5809. };
  5810. Runtime.prototype.getLayerByName = function (layer_name)
  5811. {
  5812. var i, len;
  5813. for (i = 0, len = this.running_layout.layers.length; i < len; i++)
  5814. {
  5815. var layer = this.running_layout.layers[i];
  5816. if (cr.equals_nocase(layer.name, layer_name))
  5817. return layer;
  5818. }
  5819. return null;
  5820. };
  5821. Runtime.prototype.getLayerByNumber = function (index)
  5822. {
  5823. index = cr.floor(index);
  5824. if (index < 0)
  5825. index = 0;
  5826. if (index >= this.running_layout.layers.length)
  5827. index = this.running_layout.layers.length - 1;
  5828. return this.running_layout.layers[index];
  5829. };
  5830. Runtime.prototype.getLayer = function (l)
  5831. {
  5832. if (cr.is_number(l))
  5833. return this.getLayerByNumber(l);
  5834. else
  5835. return this.getLayerByName(l.toString());
  5836. };
  5837. Runtime.prototype.clearSol = function (solModifiers)
  5838. {
  5839. var i, len;
  5840. for (i = 0, len = solModifiers.length; i < len; i++)
  5841. {
  5842. solModifiers[i].getCurrentSol().select_all = true;
  5843. }
  5844. };
  5845. Runtime.prototype.pushCleanSol = function (solModifiers)
  5846. {
  5847. var i, len;
  5848. for (i = 0, len = solModifiers.length; i < len; i++)
  5849. {
  5850. solModifiers[i].pushCleanSol();
  5851. }
  5852. };
  5853. Runtime.prototype.pushCopySol = function (solModifiers)
  5854. {
  5855. var i, len;
  5856. for (i = 0, len = solModifiers.length; i < len; i++)
  5857. {
  5858. solModifiers[i].pushCopySol();
  5859. }
  5860. };
  5861. Runtime.prototype.popSol = function (solModifiers)
  5862. {
  5863. var i, len;
  5864. for (i = 0, len = solModifiers.length; i < len; i++)
  5865. {
  5866. solModifiers[i].popSol();
  5867. }
  5868. };
  5869. Runtime.prototype.updateAllCells = function (type)
  5870. {
  5871. if (!type.any_cell_changed)
  5872. return; // all instances must already be up-to-date
  5873. var i, len, instances = type.instances;
  5874. for (i = 0, len = instances.length; i < len; ++i)
  5875. {
  5876. instances[i].update_collision_cell();
  5877. }
  5878. var createRow = this.createRow;
  5879. for (i = 0, len = createRow.length; i < len; ++i)
  5880. {
  5881. if (createRow[i].type === type)
  5882. createRow[i].update_collision_cell();
  5883. }
  5884. type.any_cell_changed = false;
  5885. };
  5886. Runtime.prototype.getCollisionCandidates = function (layer, rtype, bbox, candidates)
  5887. {
  5888. var i, len, t;
  5889. var is_parallaxed = (layer ? (layer.parallaxX !== 1 || layer.parallaxY !== 1) : false);
  5890. if (rtype.is_family)
  5891. {
  5892. for (i = 0, len = rtype.members.length; i < len; ++i)
  5893. {
  5894. t = rtype.members[i];
  5895. if (is_parallaxed || t.any_instance_parallaxed)
  5896. {
  5897. cr.appendArray(candidates, t.instances);
  5898. }
  5899. else
  5900. {
  5901. this.updateAllCells(t);
  5902. t.collision_grid.queryRange(bbox, candidates);
  5903. }
  5904. }
  5905. }
  5906. else
  5907. {
  5908. if (is_parallaxed || rtype.any_instance_parallaxed)
  5909. {
  5910. cr.appendArray(candidates, rtype.instances);
  5911. }
  5912. else
  5913. {
  5914. this.updateAllCells(rtype);
  5915. rtype.collision_grid.queryRange(bbox, candidates);
  5916. }
  5917. }
  5918. };
  5919. Runtime.prototype.getTypesCollisionCandidates = function (layer, types, bbox, candidates)
  5920. {
  5921. var i, len;
  5922. for (i = 0, len = types.length; i < len; ++i)
  5923. {
  5924. this.getCollisionCandidates(layer, types[i], bbox, candidates);
  5925. }
  5926. };
  5927. Runtime.prototype.getSolidCollisionCandidates = function (layer, bbox, candidates)
  5928. {
  5929. var solid = this.getSolidBehavior();
  5930. if (!solid)
  5931. return null;
  5932. this.getTypesCollisionCandidates(layer, solid.my_types, bbox, candidates);
  5933. };
  5934. Runtime.prototype.getJumpthruCollisionCandidates = function (layer, bbox, candidates)
  5935. {
  5936. var jumpthru = this.getJumpthruBehavior();
  5937. if (!jumpthru)
  5938. return null;
  5939. this.getTypesCollisionCandidates(layer, jumpthru.my_types, bbox, candidates);
  5940. };
  5941. Runtime.prototype.testAndSelectCanvasPointOverlap = function (type, ptx, pty, inverted)
  5942. {
  5943. var sol = type.getCurrentSol();
  5944. var i, j, inst, len;
  5945. var orblock = this.getCurrentEventStack().current_event.orblock;
  5946. var lx, ly, arr;
  5947. if (sol.select_all)
  5948. {
  5949. if (!inverted)
  5950. {
  5951. sol.select_all = false;
  5952. cr.clearArray(sol.instances); // clear contents
  5953. }
  5954. for (i = 0, len = type.instances.length; i < len; i++)
  5955. {
  5956. inst = type.instances[i];
  5957. inst.update_bbox();
  5958. lx = inst.layer.canvasToLayer(ptx, pty, true);
  5959. ly = inst.layer.canvasToLayer(ptx, pty, false);
  5960. if (inst.contains_pt(lx, ly))
  5961. {
  5962. if (inverted)
  5963. return false;
  5964. else
  5965. sol.instances.push(inst);
  5966. }
  5967. else if (orblock)
  5968. sol.else_instances.push(inst);
  5969. }
  5970. }
  5971. else
  5972. {
  5973. j = 0;
  5974. arr = (orblock ? sol.else_instances : sol.instances);
  5975. for (i = 0, len = arr.length; i < len; i++)
  5976. {
  5977. inst = arr[i];
  5978. inst.update_bbox();
  5979. lx = inst.layer.canvasToLayer(ptx, pty, true);
  5980. ly = inst.layer.canvasToLayer(ptx, pty, false);
  5981. if (inst.contains_pt(lx, ly))
  5982. {
  5983. if (inverted)
  5984. return false;
  5985. else if (orblock)
  5986. sol.instances.push(inst);
  5987. else
  5988. {
  5989. sol.instances[j] = sol.instances[i];
  5990. j++;
  5991. }
  5992. }
  5993. }
  5994. if (!inverted)
  5995. arr.length = j;
  5996. }
  5997. type.applySolToContainer();
  5998. if (inverted)
  5999. return true; // did not find anything overlapping
  6000. else
  6001. return sol.hasObjects();
  6002. };
  6003. Runtime.prototype.testOverlap = function (a, b)
  6004. {
  6005. if (!a || !b || a === b || !a.collisionsEnabled || !b.collisionsEnabled)
  6006. return false;
  6007. a.update_bbox();
  6008. b.update_bbox();
  6009. var layera = a.layer;
  6010. var layerb = b.layer;
  6011. var different_layers = (layera !== layerb && (layera.parallaxX !== layerb.parallaxX || layerb.parallaxY !== layerb.parallaxY || layera.scale !== layerb.scale || layera.angle !== layerb.angle || layera.zoomRate !== layerb.zoomRate));
  6012. var i, len, i2, i21, x, y, haspolya, haspolyb, polya, polyb;
  6013. if (!different_layers) // same layers: easy check
  6014. {
  6015. if (!a.bbox.intersects_rect(b.bbox))
  6016. return false;
  6017. if (!a.bquad.intersects_quad(b.bquad))
  6018. return false;
  6019. if (a.tilemap_exists && b.tilemap_exists)
  6020. return false;
  6021. if (a.tilemap_exists)
  6022. return this.testTilemapOverlap(a, b);
  6023. if (b.tilemap_exists)
  6024. return this.testTilemapOverlap(b, a);
  6025. haspolya = (a.collision_poly && !a.collision_poly.is_empty());
  6026. haspolyb = (b.collision_poly && !b.collision_poly.is_empty());
  6027. if (!haspolya && !haspolyb)
  6028. return true;
  6029. if (haspolya)
  6030. {
  6031. a.collision_poly.cache_poly(a.width, a.height, a.angle);
  6032. polya = a.collision_poly;
  6033. }
  6034. else
  6035. {
  6036. this.temp_poly.set_from_quad(a.bquad, a.x, a.y, a.width, a.height);
  6037. polya = this.temp_poly;
  6038. }
  6039. if (haspolyb)
  6040. {
  6041. b.collision_poly.cache_poly(b.width, b.height, b.angle);
  6042. polyb = b.collision_poly;
  6043. }
  6044. else
  6045. {
  6046. this.temp_poly.set_from_quad(b.bquad, b.x, b.y, b.width, b.height);
  6047. polyb = this.temp_poly;
  6048. }
  6049. return polya.intersects_poly(polyb, b.x - a.x, b.y - a.y);
  6050. }
  6051. else // different layers: need to do full translated check
  6052. {
  6053. haspolya = (a.collision_poly && !a.collision_poly.is_empty());
  6054. haspolyb = (b.collision_poly && !b.collision_poly.is_empty());
  6055. if (haspolya)
  6056. {
  6057. a.collision_poly.cache_poly(a.width, a.height, a.angle);
  6058. this.temp_poly.set_from_poly(a.collision_poly);
  6059. }
  6060. else
  6061. {
  6062. this.temp_poly.set_from_quad(a.bquad, a.x, a.y, a.width, a.height);
  6063. }
  6064. polya = this.temp_poly;
  6065. if (haspolyb)
  6066. {
  6067. b.collision_poly.cache_poly(b.width, b.height, b.angle);
  6068. this.temp_poly2.set_from_poly(b.collision_poly);
  6069. }
  6070. else
  6071. {
  6072. this.temp_poly2.set_from_quad(b.bquad, b.x, b.y, b.width, b.height);
  6073. }
  6074. polyb = this.temp_poly2;
  6075. for (i = 0, len = polya.pts_count; i < len; i++)
  6076. {
  6077. i2 = i * 2;
  6078. i21 = i2 + 1;
  6079. x = polya.pts_cache[i2];
  6080. y = polya.pts_cache[i21];
  6081. polya.pts_cache[i2] = layera.layerToCanvas(x + a.x, y + a.y, true);
  6082. polya.pts_cache[i21] = layera.layerToCanvas(x + a.x, y + a.y, false);
  6083. }
  6084. polya.update_bbox();
  6085. for (i = 0, len = polyb.pts_count; i < len; i++)
  6086. {
  6087. i2 = i * 2;
  6088. i21 = i2 + 1;
  6089. x = polyb.pts_cache[i2];
  6090. y = polyb.pts_cache[i21];
  6091. polyb.pts_cache[i2] = layerb.layerToCanvas(x + b.x, y + b.y, true);
  6092. polyb.pts_cache[i21] = layerb.layerToCanvas(x + b.x, y + b.y, false);
  6093. }
  6094. polyb.update_bbox();
  6095. return polya.intersects_poly(polyb, 0, 0);
  6096. }
  6097. };
  6098. var tmpQuad = new cr.quad();
  6099. var tmpRect = new cr.rect(0, 0, 0, 0);
  6100. var collrect_candidates = [];
  6101. Runtime.prototype.testTilemapOverlap = function (tm, a)
  6102. {
  6103. var i, len, c, rc;
  6104. var bbox = a.bbox;
  6105. var tmx = tm.x;
  6106. var tmy = tm.y;
  6107. tm.getCollisionRectCandidates(bbox, collrect_candidates);
  6108. var collrects = collrect_candidates;
  6109. var haspolya = (a.collision_poly && !a.collision_poly.is_empty());
  6110. for (i = 0, len = collrects.length; i < len; ++i)
  6111. {
  6112. c = collrects[i];
  6113. rc = c.rc;
  6114. if (bbox.intersects_rect_off(rc, tmx, tmy))
  6115. {
  6116. tmpQuad.set_from_rect(rc);
  6117. tmpQuad.offset(tmx, tmy);
  6118. if (tmpQuad.intersects_quad(a.bquad))
  6119. {
  6120. if (haspolya)
  6121. {
  6122. a.collision_poly.cache_poly(a.width, a.height, a.angle);
  6123. if (c.poly)
  6124. {
  6125. if (c.poly.intersects_poly(a.collision_poly, a.x - (tmx + rc.left), a.y - (tmy + rc.top)))
  6126. {
  6127. cr.clearArray(collrect_candidates);
  6128. return true;
  6129. }
  6130. }
  6131. else
  6132. {
  6133. this.temp_poly.set_from_quad(tmpQuad, 0, 0, rc.right - rc.left, rc.bottom - rc.top);
  6134. if (this.temp_poly.intersects_poly(a.collision_poly, a.x, a.y))
  6135. {
  6136. cr.clearArray(collrect_candidates);
  6137. return true;
  6138. }
  6139. }
  6140. }
  6141. else
  6142. {
  6143. if (c.poly)
  6144. {
  6145. this.temp_poly.set_from_quad(a.bquad, 0, 0, a.width, a.height);
  6146. if (c.poly.intersects_poly(this.temp_poly, -(tmx + rc.left), -(tmy + rc.top)))
  6147. {
  6148. cr.clearArray(collrect_candidates);
  6149. return true;
  6150. }
  6151. }
  6152. else
  6153. {
  6154. cr.clearArray(collrect_candidates);
  6155. return true;
  6156. }
  6157. }
  6158. }
  6159. }
  6160. }
  6161. cr.clearArray(collrect_candidates);
  6162. return false;
  6163. };
  6164. Runtime.prototype.testRectOverlap = function (r, b)
  6165. {
  6166. if (!b || !b.collisionsEnabled)
  6167. return false;
  6168. b.update_bbox();
  6169. var layerb = b.layer;
  6170. var haspolyb, polyb;
  6171. if (!b.bbox.intersects_rect(r))
  6172. return false;
  6173. if (b.tilemap_exists)
  6174. {
  6175. b.getCollisionRectCandidates(r, collrect_candidates);
  6176. var collrects = collrect_candidates;
  6177. var i, len, c, tilerc;
  6178. var tmx = b.x;
  6179. var tmy = b.y;
  6180. for (i = 0, len = collrects.length; i < len; ++i)
  6181. {
  6182. c = collrects[i];
  6183. tilerc = c.rc;
  6184. if (r.intersects_rect_off(tilerc, tmx, tmy))
  6185. {
  6186. if (c.poly)
  6187. {
  6188. this.temp_poly.set_from_rect(r, 0, 0);
  6189. if (c.poly.intersects_poly(this.temp_poly, -(tmx + tilerc.left), -(tmy + tilerc.top)))
  6190. {
  6191. cr.clearArray(collrect_candidates);
  6192. return true;
  6193. }
  6194. }
  6195. else
  6196. {
  6197. cr.clearArray(collrect_candidates);
  6198. return true;
  6199. }
  6200. }
  6201. }
  6202. cr.clearArray(collrect_candidates);
  6203. return false;
  6204. }
  6205. else
  6206. {
  6207. tmpQuad.set_from_rect(r);
  6208. if (!b.bquad.intersects_quad(tmpQuad))
  6209. return false;
  6210. haspolyb = (b.collision_poly && !b.collision_poly.is_empty());
  6211. if (!haspolyb)
  6212. return true;
  6213. b.collision_poly.cache_poly(b.width, b.height, b.angle);
  6214. tmpQuad.offset(-r.left, -r.top);
  6215. this.temp_poly.set_from_quad(tmpQuad, 0, 0, 1, 1);
  6216. return b.collision_poly.intersects_poly(this.temp_poly, r.left - b.x, r.top - b.y);
  6217. }
  6218. };
  6219. Runtime.prototype.testSegmentOverlap = function (x1, y1, x2, y2, b)
  6220. {
  6221. if (!b || !b.collisionsEnabled)
  6222. return false;
  6223. b.update_bbox();
  6224. var layerb = b.layer;
  6225. var haspolyb, polyb;
  6226. tmpRect.set(cr.min(x1, x2), cr.min(y1, y2), cr.max(x1, x2), cr.max(y1, y2));
  6227. if (!b.bbox.intersects_rect(tmpRect))
  6228. return false;
  6229. if (b.tilemap_exists)
  6230. {
  6231. b.getCollisionRectCandidates(tmpRect, collrect_candidates);
  6232. var collrects = collrect_candidates;
  6233. var i, len, c, tilerc;
  6234. var tmx = b.x;
  6235. var tmy = b.y;
  6236. for (i = 0, len = collrects.length; i < len; ++i)
  6237. {
  6238. c = collrects[i];
  6239. tilerc = c.rc;
  6240. if (tmpRect.intersects_rect_off(tilerc, tmx, tmy))
  6241. {
  6242. tmpQuad.set_from_rect(tilerc);
  6243. tmpQuad.offset(tmx, tmy);
  6244. if (tmpQuad.intersects_segment(x1, y1, x2, y2))
  6245. {
  6246. if (c.poly)
  6247. {
  6248. if (c.poly.intersects_segment(tmx + tilerc.left, tmy + tilerc.top, x1, y1, x2, y2))
  6249. {
  6250. cr.clearArray(collrect_candidates);
  6251. return true;
  6252. }
  6253. }
  6254. else
  6255. {
  6256. cr.clearArray(collrect_candidates);
  6257. return true;
  6258. }
  6259. }
  6260. }
  6261. }
  6262. cr.clearArray(collrect_candidates);
  6263. return false;
  6264. }
  6265. else
  6266. {
  6267. if (!b.bquad.intersects_segment(x1, y1, x2, y2))
  6268. return false;
  6269. haspolyb = (b.collision_poly && !b.collision_poly.is_empty());
  6270. if (!haspolyb)
  6271. return true;
  6272. b.collision_poly.cache_poly(b.width, b.height, b.angle);
  6273. return b.collision_poly.intersects_segment(b.x, b.y, x1, y1, x2, y2);
  6274. }
  6275. };
  6276. Runtime.prototype.typeHasBehavior = function (t, b)
  6277. {
  6278. if (!b)
  6279. return false;
  6280. var i, len, j, lenj, f;
  6281. for (i = 0, len = t.behaviors.length; i < len; i++)
  6282. {
  6283. if (t.behaviors[i].behavior instanceof b)
  6284. return true;
  6285. }
  6286. if (!t.is_family)
  6287. {
  6288. for (i = 0, len = t.families.length; i < len; i++)
  6289. {
  6290. f = t.families[i];
  6291. for (j = 0, lenj = f.behaviors.length; j < lenj; j++)
  6292. {
  6293. if (f.behaviors[j].behavior instanceof b)
  6294. return true;
  6295. }
  6296. }
  6297. }
  6298. return false;
  6299. };
  6300. Runtime.prototype.typeHasNoSaveBehavior = function (t)
  6301. {
  6302. return this.typeHasBehavior(t, cr.behaviors.NoSave);
  6303. };
  6304. Runtime.prototype.typeHasPersistBehavior = function (t)
  6305. {
  6306. return this.typeHasBehavior(t, cr.behaviors.Persist);
  6307. };
  6308. Runtime.prototype.getSolidBehavior = function ()
  6309. {
  6310. return this.solidBehavior;
  6311. };
  6312. Runtime.prototype.getJumpthruBehavior = function ()
  6313. {
  6314. return this.jumpthruBehavior;
  6315. };
  6316. var candidates = [];
  6317. Runtime.prototype.testOverlapSolid = function (inst)
  6318. {
  6319. var i, len, s;
  6320. inst.update_bbox();
  6321. this.getSolidCollisionCandidates(inst.layer, inst.bbox, candidates);
  6322. for (i = 0, len = candidates.length; i < len; ++i)
  6323. {
  6324. s = candidates[i];
  6325. if (!s.extra["solidEnabled"])
  6326. continue;
  6327. if (this.testOverlap(inst, s))
  6328. {
  6329. cr.clearArray(candidates);
  6330. return s;
  6331. }
  6332. }
  6333. cr.clearArray(candidates);
  6334. return null;
  6335. };
  6336. Runtime.prototype.testRectOverlapSolid = function (r)
  6337. {
  6338. var i, len, s;
  6339. this.getSolidCollisionCandidates(null, r, candidates);
  6340. for (i = 0, len = candidates.length; i < len; ++i)
  6341. {
  6342. s = candidates[i];
  6343. if (!s.extra["solidEnabled"])
  6344. continue;
  6345. if (this.testRectOverlap(r, s))
  6346. {
  6347. cr.clearArray(candidates);
  6348. return s;
  6349. }
  6350. }
  6351. cr.clearArray(candidates);
  6352. return null;
  6353. };
  6354. var jumpthru_array_ret = [];
  6355. Runtime.prototype.testOverlapJumpThru = function (inst, all)
  6356. {
  6357. var ret = null;
  6358. if (all)
  6359. {
  6360. ret = jumpthru_array_ret;
  6361. cr.clearArray(ret);
  6362. }
  6363. inst.update_bbox();
  6364. this.getJumpthruCollisionCandidates(inst.layer, inst.bbox, candidates);
  6365. var i, len, j;
  6366. for (i = 0, len = candidates.length; i < len; ++i)
  6367. {
  6368. j = candidates[i];
  6369. if (!j.extra["jumpthruEnabled"])
  6370. continue;
  6371. if (this.testOverlap(inst, j))
  6372. {
  6373. if (all)
  6374. ret.push(j);
  6375. else
  6376. {
  6377. cr.clearArray(candidates);
  6378. return j;
  6379. }
  6380. }
  6381. }
  6382. cr.clearArray(candidates);
  6383. return ret;
  6384. };
  6385. Runtime.prototype.pushOutSolid = function (inst, xdir, ydir, dist, include_jumpthrus, specific_jumpthru)
  6386. {
  6387. var push_dist = dist || 50;
  6388. var oldx = inst.x
  6389. var oldy = inst.y;
  6390. var i;
  6391. var last_overlapped = null, secondlast_overlapped = null;
  6392. for (i = 0; i < push_dist; i++)
  6393. {
  6394. inst.x = (oldx + (xdir * i));
  6395. inst.y = (oldy + (ydir * i));
  6396. inst.set_bbox_changed();
  6397. if (!this.testOverlap(inst, last_overlapped))
  6398. {
  6399. last_overlapped = this.testOverlapSolid(inst);
  6400. if (last_overlapped)
  6401. secondlast_overlapped = last_overlapped;
  6402. if (!last_overlapped)
  6403. {
  6404. if (include_jumpthrus)
  6405. {
  6406. if (specific_jumpthru)
  6407. last_overlapped = (this.testOverlap(inst, specific_jumpthru) ? specific_jumpthru : null);
  6408. else
  6409. last_overlapped = this.testOverlapJumpThru(inst);
  6410. if (last_overlapped)
  6411. secondlast_overlapped = last_overlapped;
  6412. }
  6413. if (!last_overlapped)
  6414. {
  6415. if (secondlast_overlapped)
  6416. this.pushInFractional(inst, xdir, ydir, secondlast_overlapped, 16);
  6417. return true;
  6418. }
  6419. }
  6420. }
  6421. }
  6422. inst.x = oldx;
  6423. inst.y = oldy;
  6424. inst.set_bbox_changed();
  6425. return false;
  6426. };
  6427. Runtime.prototype.pushOutSolidAxis = function(inst, xdir, ydir, dist)
  6428. {
  6429. dist = dist || 50;
  6430. var oldX = inst.x;
  6431. var oldY = inst.y;
  6432. var lastOverlapped = null;
  6433. var secondLastOverlapped = null;
  6434. var i, which, sign;
  6435. for (i = 0; i < dist; ++i)
  6436. {
  6437. for (which = 0; which < 2; ++which)
  6438. {
  6439. sign = which * 2 - 1; // -1 or 1
  6440. inst.x = oldX + (xdir * i * sign);
  6441. inst.y = oldY + (ydir * i * sign);
  6442. inst.set_bbox_changed();
  6443. if (!this.testOverlap(inst, lastOverlapped))
  6444. {
  6445. lastOverlapped = this.testOverlapSolid(inst);
  6446. if (lastOverlapped)
  6447. {
  6448. secondLastOverlapped = lastOverlapped;
  6449. }
  6450. else
  6451. {
  6452. if (secondLastOverlapped)
  6453. this.pushInFractional(inst, xdir * sign, ydir * sign, secondLastOverlapped, 16);
  6454. return true;
  6455. }
  6456. }
  6457. }
  6458. }
  6459. inst.x = oldX;
  6460. inst.y = oldY;
  6461. inst.set_bbox_changed();
  6462. return false;
  6463. };
  6464. Runtime.prototype.pushOut = function (inst, xdir, ydir, dist, otherinst)
  6465. {
  6466. var push_dist = dist || 50;
  6467. var oldx = inst.x
  6468. var oldy = inst.y;
  6469. var i;
  6470. for (i = 0; i < push_dist; i++)
  6471. {
  6472. inst.x = (oldx + (xdir * i));
  6473. inst.y = (oldy + (ydir * i));
  6474. inst.set_bbox_changed();
  6475. if (!this.testOverlap(inst, otherinst))
  6476. return true;
  6477. }
  6478. inst.x = oldx;
  6479. inst.y = oldy;
  6480. inst.set_bbox_changed();
  6481. return false;
  6482. };
  6483. Runtime.prototype.pushInFractional = function (inst, xdir, ydir, obj, limit)
  6484. {
  6485. var divisor = 2;
  6486. var frac;
  6487. var forward = false;
  6488. var overlapping = false;
  6489. var bestx = inst.x;
  6490. var besty = inst.y;
  6491. while (divisor <= limit)
  6492. {
  6493. frac = 1 / divisor;
  6494. divisor *= 2;
  6495. inst.x += xdir * frac * (forward ? 1 : -1);
  6496. inst.y += ydir * frac * (forward ? 1 : -1);
  6497. inst.set_bbox_changed();
  6498. if (this.testOverlap(inst, obj))
  6499. {
  6500. forward = true;
  6501. overlapping = true;
  6502. }
  6503. else
  6504. {
  6505. forward = false;
  6506. overlapping = false;
  6507. bestx = inst.x;
  6508. besty = inst.y;
  6509. }
  6510. }
  6511. if (overlapping)
  6512. {
  6513. inst.x = bestx;
  6514. inst.y = besty;
  6515. inst.set_bbox_changed();
  6516. }
  6517. };
  6518. Runtime.prototype.pushOutSolidNearest = function (inst, max_dist_)
  6519. {
  6520. var max_dist = (cr.is_undefined(max_dist_) ? 100 : max_dist_);
  6521. var dist = 0;
  6522. var oldx = inst.x
  6523. var oldy = inst.y;
  6524. var dir = 0;
  6525. var dx = 0, dy = 0;
  6526. var last_overlapped = this.testOverlapSolid(inst);
  6527. if (!last_overlapped)
  6528. return true; // already clear of solids
  6529. while (dist <= max_dist)
  6530. {
  6531. switch (dir) {
  6532. case 0: dx = 0; dy = -1; dist++; break;
  6533. case 1: dx = 1; dy = -1; break;
  6534. case 2: dx = 1; dy = 0; break;
  6535. case 3: dx = 1; dy = 1; break;
  6536. case 4: dx = 0; dy = 1; break;
  6537. case 5: dx = -1; dy = 1; break;
  6538. case 6: dx = -1; dy = 0; break;
  6539. case 7: dx = -1; dy = -1; break;
  6540. }
  6541. dir = (dir + 1) % 8;
  6542. inst.x = cr.floor(oldx + (dx * dist));
  6543. inst.y = cr.floor(oldy + (dy * dist));
  6544. inst.set_bbox_changed();
  6545. if (!this.testOverlap(inst, last_overlapped))
  6546. {
  6547. last_overlapped = this.testOverlapSolid(inst);
  6548. if (!last_overlapped)
  6549. return true;
  6550. }
  6551. }
  6552. inst.x = oldx;
  6553. inst.y = oldy;
  6554. inst.set_bbox_changed();
  6555. return false;
  6556. };
  6557. Runtime.prototype.registerCollision = function (a, b)
  6558. {
  6559. if (!a.collisionsEnabled || !b.collisionsEnabled)
  6560. return;
  6561. this.registered_collisions.push([a, b]);
  6562. };
  6563. Runtime.prototype.addRegisteredCollisionCandidates = function (inst, otherType, arr)
  6564. {
  6565. var i, len, r, otherInst;
  6566. for (i = 0, len = this.registered_collisions.length; i < len; ++i)
  6567. {
  6568. r = this.registered_collisions[i];
  6569. if (r[0] === inst)
  6570. otherInst = r[1];
  6571. else if (r[1] === inst)
  6572. otherInst = r[0];
  6573. else
  6574. continue;
  6575. if (otherType.is_family)
  6576. {
  6577. if (otherType.members.indexOf(otherType) === -1)
  6578. continue;
  6579. }
  6580. else
  6581. {
  6582. if (otherInst.type !== otherType)
  6583. continue;
  6584. }
  6585. if (arr.indexOf(otherInst) === -1)
  6586. arr.push(otherInst);
  6587. }
  6588. };
  6589. Runtime.prototype.checkRegisteredCollision = function (a, b)
  6590. {
  6591. var i, len, x;
  6592. for (i = 0, len = this.registered_collisions.length; i < len; i++)
  6593. {
  6594. x = this.registered_collisions[i];
  6595. if ((x[0] === a && x[1] === b) || (x[0] === b && x[1] === a))
  6596. return true;
  6597. }
  6598. return false;
  6599. };
  6600. Runtime.prototype.calculateSolidBounceAngle = function(inst, startx, starty, obj)
  6601. {
  6602. var objx = inst.x;
  6603. var objy = inst.y;
  6604. var radius = cr.max(10, cr.distanceTo(startx, starty, objx, objy));
  6605. var startangle = cr.angleTo(startx, starty, objx, objy);
  6606. var firstsolid = obj || this.testOverlapSolid(inst);
  6607. if (!firstsolid)
  6608. return cr.clamp_angle(startangle + cr.PI);
  6609. var cursolid = firstsolid;
  6610. var i, curangle, anticlockwise_free_angle, clockwise_free_angle;
  6611. var increment = cr.to_radians(5); // 5 degree increments
  6612. for (i = 1; i < 36; i++)
  6613. {
  6614. curangle = startangle - i * increment;
  6615. inst.x = startx + Math.cos(curangle) * radius;
  6616. inst.y = starty + Math.sin(curangle) * radius;
  6617. inst.set_bbox_changed();
  6618. if (!this.testOverlap(inst, cursolid))
  6619. {
  6620. cursolid = obj ? null : this.testOverlapSolid(inst);
  6621. if (!cursolid)
  6622. {
  6623. anticlockwise_free_angle = curangle;
  6624. break;
  6625. }
  6626. }
  6627. }
  6628. if (i === 36)
  6629. anticlockwise_free_angle = cr.clamp_angle(startangle + cr.PI);
  6630. var cursolid = firstsolid;
  6631. for (i = 1; i < 36; i++)
  6632. {
  6633. curangle = startangle + i * increment;
  6634. inst.x = startx + Math.cos(curangle) * radius;
  6635. inst.y = starty + Math.sin(curangle) * radius;
  6636. inst.set_bbox_changed();
  6637. if (!this.testOverlap(inst, cursolid))
  6638. {
  6639. cursolid = obj ? null : this.testOverlapSolid(inst);
  6640. if (!cursolid)
  6641. {
  6642. clockwise_free_angle = curangle;
  6643. break;
  6644. }
  6645. }
  6646. }
  6647. if (i === 36)
  6648. clockwise_free_angle = cr.clamp_angle(startangle + cr.PI);
  6649. inst.x = objx;
  6650. inst.y = objy;
  6651. inst.set_bbox_changed();
  6652. if (clockwise_free_angle === anticlockwise_free_angle)
  6653. return clockwise_free_angle;
  6654. var half_diff = cr.angleDiff(clockwise_free_angle, anticlockwise_free_angle) / 2;
  6655. var normal;
  6656. if (cr.angleClockwise(clockwise_free_angle, anticlockwise_free_angle))
  6657. {
  6658. normal = cr.clamp_angle(anticlockwise_free_angle + half_diff + cr.PI);
  6659. }
  6660. else
  6661. {
  6662. normal = cr.clamp_angle(clockwise_free_angle + half_diff);
  6663. }
  6664. ;
  6665. var vx = Math.cos(startangle);
  6666. var vy = Math.sin(startangle);
  6667. var nx = Math.cos(normal);
  6668. var ny = Math.sin(normal);
  6669. var v_dot_n = vx * nx + vy * ny;
  6670. var rx = vx - 2 * v_dot_n * nx;
  6671. var ry = vy - 2 * v_dot_n * ny;
  6672. return cr.angleTo(0, 0, rx, ry);
  6673. };
  6674. var triggerSheetIndex = -1;
  6675. Runtime.prototype.trigger = function (method, inst, value /* for fast triggers */)
  6676. {
  6677. ;
  6678. if (!this.running_layout)
  6679. return false;
  6680. var sheet = this.running_layout.event_sheet;
  6681. if (!sheet)
  6682. return false; // no event sheet active; nothing to trigger
  6683. var ret = false;
  6684. var r, i, len;
  6685. triggerSheetIndex++;
  6686. var deep_includes = sheet.deep_includes;
  6687. for (i = 0, len = deep_includes.length; i < len; ++i)
  6688. {
  6689. r = this.triggerOnSheet(method, inst, deep_includes[i], value);
  6690. ret = ret || r;
  6691. }
  6692. r = this.triggerOnSheet(method, inst, sheet, value);
  6693. ret = ret || r;
  6694. triggerSheetIndex--;
  6695. return ret;
  6696. };
  6697. Runtime.prototype.triggerOnSheet = function (method, inst, sheet, value)
  6698. {
  6699. var ret = false;
  6700. var i, leni, r, families;
  6701. if (!inst)
  6702. {
  6703. r = this.triggerOnSheetForTypeName(method, inst, "system", sheet, value);
  6704. ret = ret || r;
  6705. }
  6706. else
  6707. {
  6708. r = this.triggerOnSheetForTypeName(method, inst, inst.type.name, sheet, value);
  6709. ret = ret || r;
  6710. families = inst.type.families;
  6711. for (i = 0, leni = families.length; i < leni; ++i)
  6712. {
  6713. r = this.triggerOnSheetForTypeName(method, inst, families[i].name, sheet, value);
  6714. ret = ret || r;
  6715. }
  6716. }
  6717. return ret; // true if anything got triggered
  6718. };
  6719. Runtime.prototype.triggerOnSheetForTypeName = function (method, inst, type_name, sheet, value)
  6720. {
  6721. var i, leni;
  6722. var ret = false, ret2 = false;
  6723. var trig, index;
  6724. var fasttrigger = (typeof value !== "undefined");
  6725. var triggers = (fasttrigger ? sheet.fasttriggers : sheet.triggers);
  6726. var obj_entry = triggers[type_name];
  6727. if (!obj_entry)
  6728. return ret;
  6729. var triggers_list = null;
  6730. for (i = 0, leni = obj_entry.length; i < leni; ++i)
  6731. {
  6732. if (obj_entry[i].method == method)
  6733. {
  6734. triggers_list = obj_entry[i].evs;
  6735. break;
  6736. }
  6737. }
  6738. if (!triggers_list)
  6739. return ret;
  6740. var triggers_to_fire;
  6741. if (fasttrigger)
  6742. {
  6743. triggers_to_fire = triggers_list[value];
  6744. }
  6745. else
  6746. {
  6747. triggers_to_fire = triggers_list;
  6748. }
  6749. if (!triggers_to_fire)
  6750. return null;
  6751. for (i = 0, leni = triggers_to_fire.length; i < leni; i++)
  6752. {
  6753. trig = triggers_to_fire[i][0];
  6754. index = triggers_to_fire[i][1];
  6755. ret2 = this.executeSingleTrigger(inst, type_name, trig, index);
  6756. ret = ret || ret2;
  6757. }
  6758. return ret;
  6759. };
  6760. Runtime.prototype.executeSingleTrigger = function (inst, type_name, trig, index)
  6761. {
  6762. var i, leni;
  6763. var ret = false;
  6764. this.trigger_depth++;
  6765. var current_event = this.getCurrentEventStack().current_event;
  6766. if (current_event)
  6767. this.pushCleanSol(current_event.solModifiersIncludingParents);
  6768. var isrecursive = (this.trigger_depth > 1); // calling trigger from inside another trigger
  6769. this.pushCleanSol(trig.solModifiersIncludingParents);
  6770. if (isrecursive)
  6771. this.pushLocalVarStack();
  6772. var event_stack = this.pushEventStack(trig);
  6773. event_stack.current_event = trig;
  6774. if (inst)
  6775. {
  6776. var sol = this.types[type_name].getCurrentSol();
  6777. sol.select_all = false;
  6778. cr.clearArray(sol.instances);
  6779. sol.instances[0] = inst;
  6780. this.types[type_name].applySolToContainer();
  6781. }
  6782. var ok_to_run = true;
  6783. if (trig.parent)
  6784. {
  6785. var temp_parents_arr = event_stack.temp_parents_arr;
  6786. var cur_parent = trig.parent;
  6787. while (cur_parent)
  6788. {
  6789. temp_parents_arr.push(cur_parent);
  6790. cur_parent = cur_parent.parent;
  6791. }
  6792. temp_parents_arr.reverse();
  6793. for (i = 0, leni = temp_parents_arr.length; i < leni; i++)
  6794. {
  6795. if (!temp_parents_arr[i].run_pretrigger()) // parent event failed
  6796. {
  6797. ok_to_run = false;
  6798. break;
  6799. }
  6800. }
  6801. }
  6802. if (ok_to_run)
  6803. {
  6804. this.execcount++;
  6805. if (trig.orblock)
  6806. trig.run_orblocktrigger(index);
  6807. else
  6808. trig.run();
  6809. ret = ret || event_stack.last_event_true;
  6810. }
  6811. this.popEventStack();
  6812. if (isrecursive)
  6813. this.popLocalVarStack();
  6814. this.popSol(trig.solModifiersIncludingParents);
  6815. if (current_event)
  6816. this.popSol(current_event.solModifiersIncludingParents);
  6817. if (this.hasPendingInstances && this.isInOnDestroy === 0 && triggerSheetIndex === 0 && !this.isRunningEvents)
  6818. {
  6819. this.ClearDeathRow();
  6820. }
  6821. this.trigger_depth--;
  6822. return ret;
  6823. };
  6824. Runtime.prototype.getCurrentCondition = function ()
  6825. {
  6826. var evinfo = this.getCurrentEventStack();
  6827. return evinfo.current_event.conditions[evinfo.cndindex];
  6828. };
  6829. Runtime.prototype.getCurrentConditionObjectType = function ()
  6830. {
  6831. var cnd = this.getCurrentCondition();
  6832. return cnd.type;
  6833. };
  6834. Runtime.prototype.isCurrentConditionFirst = function ()
  6835. {
  6836. var evinfo = this.getCurrentEventStack();
  6837. return evinfo.cndindex === 0;
  6838. };
  6839. Runtime.prototype.getCurrentAction = function ()
  6840. {
  6841. var evinfo = this.getCurrentEventStack();
  6842. return evinfo.current_event.actions[evinfo.actindex];
  6843. };
  6844. Runtime.prototype.pushLocalVarStack = function ()
  6845. {
  6846. this.localvar_stack_index++;
  6847. if (this.localvar_stack_index >= this.localvar_stack.length)
  6848. this.localvar_stack.push([]);
  6849. };
  6850. Runtime.prototype.popLocalVarStack = function ()
  6851. {
  6852. ;
  6853. this.localvar_stack_index--;
  6854. };
  6855. Runtime.prototype.getCurrentLocalVarStack = function ()
  6856. {
  6857. return this.localvar_stack[this.localvar_stack_index];
  6858. };
  6859. Runtime.prototype.pushEventStack = function (cur_event)
  6860. {
  6861. this.event_stack_index++;
  6862. if (this.event_stack_index >= this.event_stack.length)
  6863. this.event_stack.push(new cr.eventStackFrame());
  6864. var ret = this.getCurrentEventStack();
  6865. ret.reset(cur_event);
  6866. return ret;
  6867. };
  6868. Runtime.prototype.popEventStack = function ()
  6869. {
  6870. ;
  6871. this.event_stack_index--;
  6872. };
  6873. Runtime.prototype.getCurrentEventStack = function ()
  6874. {
  6875. return this.event_stack[this.event_stack_index];
  6876. };
  6877. Runtime.prototype.pushLoopStack = function (name_)
  6878. {
  6879. this.loop_stack_index++;
  6880. if (this.loop_stack_index >= this.loop_stack.length)
  6881. {
  6882. this.loop_stack.push(cr.seal({ name: name_, index: 0, stopped: false }));
  6883. }
  6884. var ret = this.getCurrentLoop();
  6885. ret.name = name_;
  6886. ret.index = 0;
  6887. ret.stopped = false;
  6888. return ret;
  6889. };
  6890. Runtime.prototype.popLoopStack = function ()
  6891. {
  6892. ;
  6893. this.loop_stack_index--;
  6894. };
  6895. Runtime.prototype.getCurrentLoop = function ()
  6896. {
  6897. return this.loop_stack[this.loop_stack_index];
  6898. };
  6899. Runtime.prototype.getEventVariableByName = function (name, scope)
  6900. {
  6901. var i, leni, j, lenj, sheet, e;
  6902. while (scope)
  6903. {
  6904. for (i = 0, leni = scope.subevents.length; i < leni; i++)
  6905. {
  6906. e = scope.subevents[i];
  6907. if (e instanceof cr.eventvariable && cr.equals_nocase(name, e.name))
  6908. return e;
  6909. }
  6910. scope = scope.parent;
  6911. }
  6912. for (i = 0, leni = this.eventsheets_by_index.length; i < leni; i++)
  6913. {
  6914. sheet = this.eventsheets_by_index[i];
  6915. for (j = 0, lenj = sheet.events.length; j < lenj; j++)
  6916. {
  6917. e = sheet.events[j];
  6918. if (e instanceof cr.eventvariable && cr.equals_nocase(name, e.name))
  6919. return e;
  6920. }
  6921. }
  6922. return null;
  6923. };
  6924. Runtime.prototype.getLayoutBySid = function (sid_)
  6925. {
  6926. var i, len;
  6927. for (i = 0, len = this.layouts_by_index.length; i < len; i++)
  6928. {
  6929. if (this.layouts_by_index[i].sid === sid_)
  6930. return this.layouts_by_index[i];
  6931. }
  6932. return null;
  6933. };
  6934. Runtime.prototype.getObjectTypeBySid = function (sid_)
  6935. {
  6936. var i, len;
  6937. for (i = 0, len = this.types_by_index.length; i < len; i++)
  6938. {
  6939. if (this.types_by_index[i].sid === sid_)
  6940. return this.types_by_index[i];
  6941. }
  6942. return null;
  6943. };
  6944. Runtime.prototype.getGroupBySid = function (sid_)
  6945. {
  6946. var i, len;
  6947. for (i = 0, len = this.allGroups.length; i < len; i++)
  6948. {
  6949. if (this.allGroups[i].sid === sid_)
  6950. return this.allGroups[i];
  6951. }
  6952. return null;
  6953. };
  6954. Runtime.prototype.doCanvasSnapshot = function (format_, quality_)
  6955. {
  6956. this.snapshotCanvas = [format_, quality_];
  6957. this.redraw = true; // force redraw so snapshot is always taken
  6958. };
  6959. function IsIndexedDBAvailable()
  6960. {
  6961. try {
  6962. return !!window.indexedDB;
  6963. }
  6964. catch (e)
  6965. {
  6966. return false;
  6967. }
  6968. };
  6969. function makeSaveDb(e)
  6970. {
  6971. var db = e.target.result;
  6972. db.createObjectStore("saves", { keyPath: "slot" });
  6973. };
  6974. function IndexedDB_WriteSlot(slot_, data_, oncomplete_, onerror_)
  6975. {
  6976. try {
  6977. var request = indexedDB.open("_C2SaveStates");
  6978. request.onupgradeneeded = makeSaveDb;
  6979. request.onerror = onerror_;
  6980. request.onsuccess = function (e)
  6981. {
  6982. var db = e.target.result;
  6983. db.onerror = onerror_;
  6984. var transaction = db.transaction(["saves"], "readwrite");
  6985. var objectStore = transaction.objectStore("saves");
  6986. var putReq = objectStore.put({"slot": slot_, "data": data_ });
  6987. putReq.onsuccess = oncomplete_;
  6988. };
  6989. }
  6990. catch (err)
  6991. {
  6992. onerror_(err);
  6993. }
  6994. };
  6995. function IndexedDB_ReadSlot(slot_, oncomplete_, onerror_)
  6996. {
  6997. try {
  6998. var request = indexedDB.open("_C2SaveStates");
  6999. request.onupgradeneeded = makeSaveDb;
  7000. request.onerror = onerror_;
  7001. request.onsuccess = function (e)
  7002. {
  7003. var db = e.target.result;
  7004. db.onerror = onerror_;
  7005. var transaction = db.transaction(["saves"]);
  7006. var objectStore = transaction.objectStore("saves");
  7007. var readReq = objectStore.get(slot_);
  7008. readReq.onsuccess = function (e)
  7009. {
  7010. if (readReq.result)
  7011. oncomplete_(readReq.result["data"]);
  7012. else
  7013. oncomplete_(null);
  7014. };
  7015. };
  7016. }
  7017. catch (err)
  7018. {
  7019. onerror_(err);
  7020. }
  7021. };
  7022. Runtime.prototype.signalContinuousPreview = function ()
  7023. {
  7024. this.signalledContinuousPreview = true;
  7025. };
  7026. function doContinuousPreviewReload()
  7027. {
  7028. cr.logexport("Reloading for continuous preview");
  7029. if (!!window["c2cocoonjs"])
  7030. {
  7031. CocoonJS["App"]["reload"]();
  7032. }
  7033. else
  7034. {
  7035. if (window.location.search.indexOf("continuous") > -1)
  7036. window.location.reload(true);
  7037. else
  7038. window.location = window.location + "?continuous";
  7039. }
  7040. };
  7041. Runtime.prototype.handleSaveLoad = function ()
  7042. {
  7043. var self = this;
  7044. var savingToSlot = this.saveToSlot;
  7045. var savingJson = this.lastSaveJson;
  7046. var loadingFromSlot = this.loadFromSlot;
  7047. var continuous = false;
  7048. if (this.signalledContinuousPreview)
  7049. {
  7050. continuous = true;
  7051. savingToSlot = "__c2_continuouspreview";
  7052. this.signalledContinuousPreview = false;
  7053. }
  7054. if (savingToSlot.length)
  7055. {
  7056. this.ClearDeathRow();
  7057. savingJson = this.saveToJSONString();
  7058. if (IsIndexedDBAvailable() && !this.isCocoonJs)
  7059. {
  7060. IndexedDB_WriteSlot(savingToSlot, savingJson, function ()
  7061. {
  7062. cr.logexport("Saved state to IndexedDB storage (" + savingJson.length + " bytes)");
  7063. self.lastSaveJson = savingJson;
  7064. self.trigger(cr.system_object.prototype.cnds.OnSaveComplete, null);
  7065. self.lastSaveJson = "";
  7066. if (continuous)
  7067. doContinuousPreviewReload();
  7068. }, function (e)
  7069. {
  7070. try {
  7071. localStorage.setItem("__c2save_" + savingToSlot, savingJson);
  7072. cr.logexport("Saved state to WebStorage (" + savingJson.length + " bytes)");
  7073. self.lastSaveJson = savingJson;
  7074. self.trigger(cr.system_object.prototype.cnds.OnSaveComplete, null);
  7075. self.lastSaveJson = "";
  7076. if (continuous)
  7077. doContinuousPreviewReload();
  7078. }
  7079. catch (f)
  7080. {
  7081. cr.logexport("Failed to save game state: " + e + "; " + f);
  7082. self.trigger(cr.system_object.prototype.cnds.OnSaveFailed, null);
  7083. }
  7084. });
  7085. }
  7086. else
  7087. {
  7088. try {
  7089. localStorage.setItem("__c2save_" + savingToSlot, savingJson);
  7090. cr.logexport("Saved state to WebStorage (" + savingJson.length + " bytes)");
  7091. self.lastSaveJson = savingJson;
  7092. this.trigger(cr.system_object.prototype.cnds.OnSaveComplete, null);
  7093. self.lastSaveJson = "";
  7094. if (continuous)
  7095. doContinuousPreviewReload();
  7096. }
  7097. catch (e)
  7098. {
  7099. cr.logexport("Error saving to WebStorage: " + e);
  7100. self.trigger(cr.system_object.prototype.cnds.OnSaveFailed, null);
  7101. }
  7102. }
  7103. this.saveToSlot = "";
  7104. this.loadFromSlot = "";
  7105. this.loadFromJson = null;
  7106. }
  7107. if (loadingFromSlot.length)
  7108. {
  7109. if (IsIndexedDBAvailable() && !this.isCocoonJs)
  7110. {
  7111. IndexedDB_ReadSlot(loadingFromSlot, function (result_)
  7112. {
  7113. if (result_)
  7114. {
  7115. self.loadFromJson = result_;
  7116. cr.logexport("Loaded state from IndexedDB storage (" + self.loadFromJson.length + " bytes)");
  7117. }
  7118. else
  7119. {
  7120. self.loadFromJson = localStorage.getItem("__c2save_" + loadingFromSlot) || "";
  7121. cr.logexport("Loaded state from WebStorage (" + self.loadFromJson.length + " bytes)");
  7122. }
  7123. self.suspendDrawing = false;
  7124. if (!self.loadFromJson)
  7125. {
  7126. self.loadFromJson = null;
  7127. self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null);
  7128. }
  7129. }, function (e)
  7130. {
  7131. self.loadFromJson = localStorage.getItem("__c2save_" + loadingFromSlot) || "";
  7132. cr.logexport("Loaded state from WebStorage (" + self.loadFromJson.length + " bytes)");
  7133. self.suspendDrawing = false;
  7134. if (!self.loadFromJson)
  7135. {
  7136. self.loadFromJson = null;
  7137. self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null);
  7138. }
  7139. });
  7140. }
  7141. else
  7142. {
  7143. try {
  7144. this.loadFromJson = localStorage.getItem("__c2save_" + loadingFromSlot) || "";
  7145. cr.logexport("Loaded state from WebStorage (" + this.loadFromJson.length + " bytes)");
  7146. }
  7147. catch (e)
  7148. {
  7149. this.loadFromJson = null;
  7150. }
  7151. this.suspendDrawing = false;
  7152. if (!self.loadFromJson)
  7153. {
  7154. self.loadFromJson = null;
  7155. self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null);
  7156. }
  7157. }
  7158. this.loadFromSlot = "";
  7159. this.saveToSlot = "";
  7160. }
  7161. if (this.loadFromJson !== null)
  7162. {
  7163. this.ClearDeathRow();
  7164. var ok = this.loadFromJSONString(this.loadFromJson);
  7165. if (ok)
  7166. {
  7167. this.lastSaveJson = this.loadFromJson;
  7168. this.trigger(cr.system_object.prototype.cnds.OnLoadComplete, null);
  7169. this.lastSaveJson = "";
  7170. }
  7171. else
  7172. {
  7173. self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null);
  7174. }
  7175. this.loadFromJson = null;
  7176. }
  7177. };
  7178. function CopyExtraObject(extra)
  7179. {
  7180. var p, ret = {};
  7181. for (p in extra)
  7182. {
  7183. if (extra.hasOwnProperty(p))
  7184. {
  7185. if (extra[p] instanceof cr.ObjectSet)
  7186. continue;
  7187. if (extra[p] && typeof extra[p].c2userdata !== "undefined")
  7188. continue;
  7189. if (p === "spriteCreatedDestroyCallback")
  7190. continue;
  7191. ret[p] = extra[p];
  7192. }
  7193. }
  7194. return ret;
  7195. };
  7196. Runtime.prototype.saveToJSONString = function()
  7197. {
  7198. var i, len, j, lenj, type, layout, typeobj, g, c, a, v, p;
  7199. var o = {
  7200. "c2save": true,
  7201. "version": 1,
  7202. "rt": {
  7203. "time": this.kahanTime.sum,
  7204. "walltime": this.wallTime.sum,
  7205. "timescale": this.timescale,
  7206. "tickcount": this.tickcount,
  7207. "execcount": this.execcount,
  7208. "next_uid": this.next_uid,
  7209. "running_layout": this.running_layout.sid,
  7210. "start_time_offset": (Date.now() - this.start_time)
  7211. },
  7212. "types": {},
  7213. "layouts": {},
  7214. "events": {
  7215. "groups": {},
  7216. "cnds": {},
  7217. "acts": {},
  7218. "vars": {}
  7219. }
  7220. };
  7221. for (i = 0, len = this.types_by_index.length; i < len; i++)
  7222. {
  7223. type = this.types_by_index[i];
  7224. if (type.is_family || this.typeHasNoSaveBehavior(type))
  7225. continue;
  7226. typeobj = {
  7227. "instances": []
  7228. };
  7229. if (cr.hasAnyOwnProperty(type.extra))
  7230. typeobj["ex"] = CopyExtraObject(type.extra);
  7231. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  7232. {
  7233. typeobj["instances"].push(this.saveInstanceToJSON(type.instances[j]));
  7234. }
  7235. o["types"][type.sid.toString()] = typeobj;
  7236. }
  7237. for (i = 0, len = this.layouts_by_index.length; i < len; i++)
  7238. {
  7239. layout = this.layouts_by_index[i];
  7240. o["layouts"][layout.sid.toString()] = layout.saveToJSON();
  7241. }
  7242. var ogroups = o["events"]["groups"];
  7243. for (i = 0, len = this.allGroups.length; i < len; i++)
  7244. {
  7245. g = this.allGroups[i];
  7246. ogroups[g.sid.toString()] = this.groups_by_name[g.group_name].group_active;
  7247. }
  7248. var ocnds = o["events"]["cnds"];
  7249. for (p in this.cndsBySid)
  7250. {
  7251. if (this.cndsBySid.hasOwnProperty(p))
  7252. {
  7253. c = this.cndsBySid[p];
  7254. if (cr.hasAnyOwnProperty(c.extra))
  7255. ocnds[p] = { "ex": CopyExtraObject(c.extra) };
  7256. }
  7257. }
  7258. var oacts = o["events"]["acts"];
  7259. for (p in this.actsBySid)
  7260. {
  7261. if (this.actsBySid.hasOwnProperty(p))
  7262. {
  7263. a = this.actsBySid[p];
  7264. if (cr.hasAnyOwnProperty(a.extra))
  7265. oacts[p] = { "ex": CopyExtraObject(a.extra) };
  7266. }
  7267. }
  7268. var ovars = o["events"]["vars"];
  7269. for (p in this.varsBySid)
  7270. {
  7271. if (this.varsBySid.hasOwnProperty(p))
  7272. {
  7273. v = this.varsBySid[p];
  7274. if (!v.is_constant && (!v.parent || v.is_static))
  7275. ovars[p] = v.data;
  7276. }
  7277. }
  7278. o["system"] = this.system.saveToJSON();
  7279. return JSON.stringify(o);
  7280. };
  7281. Runtime.prototype.refreshUidMap = function ()
  7282. {
  7283. var i, len, type, j, lenj, inst;
  7284. this.objectsByUid = {};
  7285. for (i = 0, len = this.types_by_index.length; i < len; i++)
  7286. {
  7287. type = this.types_by_index[i];
  7288. if (type.is_family)
  7289. continue;
  7290. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  7291. {
  7292. inst = type.instances[j];
  7293. this.objectsByUid[inst.uid.toString()] = inst;
  7294. }
  7295. }
  7296. };
  7297. Runtime.prototype.loadFromJSONString = function (str)
  7298. {
  7299. var o;
  7300. try {
  7301. o = JSON.parse(str);
  7302. }
  7303. catch (e) {
  7304. return false;
  7305. }
  7306. if (!o["c2save"])
  7307. return false; // probably not a c2 save state
  7308. if (o["version"] > 1)
  7309. return false; // from future version of c2; assume not compatible
  7310. this.isLoadingState = true;
  7311. var rt = o["rt"];
  7312. this.kahanTime.reset();
  7313. this.kahanTime.sum = rt["time"];
  7314. this.wallTime.reset();
  7315. this.wallTime.sum = rt["walltime"] || 0;
  7316. this.timescale = rt["timescale"];
  7317. this.tickcount = rt["tickcount"];
  7318. this.execcount = rt["execcount"];
  7319. this.start_time = Date.now() - rt["start_time_offset"];
  7320. var layout_sid = rt["running_layout"];
  7321. if (layout_sid !== this.running_layout.sid)
  7322. {
  7323. var changeToLayout = this.getLayoutBySid(layout_sid);
  7324. if (changeToLayout)
  7325. this.doChangeLayout(changeToLayout);
  7326. else
  7327. return; // layout that was saved on has gone missing (deleted?)
  7328. }
  7329. var i, len, j, lenj, k, lenk, p, type, existing_insts, load_insts, inst, binst, layout, layer, g, iid, t;
  7330. var otypes = o["types"];
  7331. for (p in otypes)
  7332. {
  7333. if (otypes.hasOwnProperty(p))
  7334. {
  7335. type = this.getObjectTypeBySid(parseInt(p, 10));
  7336. if (!type || type.is_family || this.typeHasNoSaveBehavior(type))
  7337. continue;
  7338. if (otypes[p]["ex"])
  7339. type.extra = otypes[p]["ex"];
  7340. else
  7341. cr.wipe(type.extra);
  7342. existing_insts = type.instances;
  7343. load_insts = otypes[p]["instances"];
  7344. for (i = 0, len = cr.min(existing_insts.length, load_insts.length); i < len; i++)
  7345. {
  7346. this.loadInstanceFromJSON(existing_insts[i], load_insts[i]);
  7347. }
  7348. for (i = load_insts.length, len = existing_insts.length; i < len; i++)
  7349. this.DestroyInstance(existing_insts[i]);
  7350. for (i = existing_insts.length, len = load_insts.length; i < len; i++)
  7351. {
  7352. layer = null;
  7353. if (type.plugin.is_world)
  7354. {
  7355. layer = this.running_layout.getLayerBySid(load_insts[i]["w"]["l"]);
  7356. if (!layer)
  7357. continue;
  7358. }
  7359. inst = this.createInstanceFromInit(type.default_instance, layer, false, 0, 0, true);
  7360. this.loadInstanceFromJSON(inst, load_insts[i]);
  7361. }
  7362. type.stale_iids = true;
  7363. }
  7364. }
  7365. this.ClearDeathRow();
  7366. this.refreshUidMap();
  7367. var olayouts = o["layouts"];
  7368. for (p in olayouts)
  7369. {
  7370. if (olayouts.hasOwnProperty(p))
  7371. {
  7372. layout = this.getLayoutBySid(parseInt(p, 10));
  7373. if (!layout)
  7374. continue; // must've gone missing
  7375. layout.loadFromJSON(olayouts[p]);
  7376. }
  7377. }
  7378. var ogroups = o["events"]["groups"];
  7379. for (p in ogroups)
  7380. {
  7381. if (ogroups.hasOwnProperty(p))
  7382. {
  7383. g = this.getGroupBySid(parseInt(p, 10));
  7384. if (g && this.groups_by_name[g.group_name])
  7385. this.groups_by_name[g.group_name].setGroupActive(ogroups[p]);
  7386. }
  7387. }
  7388. var ocnds = o["events"]["cnds"];
  7389. for (p in this.cndsBySid)
  7390. {
  7391. if (this.cndsBySid.hasOwnProperty(p))
  7392. {
  7393. if (ocnds.hasOwnProperty(p))
  7394. {
  7395. this.cndsBySid[p].extra = ocnds[p]["ex"];
  7396. }
  7397. else
  7398. {
  7399. this.cndsBySid[p].extra = {};
  7400. }
  7401. }
  7402. }
  7403. var oacts = o["events"]["acts"];
  7404. for (p in this.actsBySid)
  7405. {
  7406. if (this.actsBySid.hasOwnProperty(p))
  7407. {
  7408. if (oacts.hasOwnProperty(p))
  7409. {
  7410. this.actsBySid[p].extra = oacts[p]["ex"];
  7411. }
  7412. else
  7413. {
  7414. this.actsBySid[p].extra = {};
  7415. }
  7416. }
  7417. }
  7418. var ovars = o["events"]["vars"];
  7419. for (p in ovars)
  7420. {
  7421. if (ovars.hasOwnProperty(p) && this.varsBySid.hasOwnProperty(p))
  7422. {
  7423. this.varsBySid[p].data = ovars[p];
  7424. }
  7425. }
  7426. this.next_uid = rt["next_uid"];
  7427. this.isLoadingState = false;
  7428. for (i = 0, len = this.fireOnCreateAfterLoad.length; i < len; ++i)
  7429. {
  7430. inst = this.fireOnCreateAfterLoad[i];
  7431. this.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnCreated, inst);
  7432. }
  7433. cr.clearArray(this.fireOnCreateAfterLoad);
  7434. this.system.loadFromJSON(o["system"]);
  7435. for (i = 0, len = this.types_by_index.length; i < len; i++)
  7436. {
  7437. type = this.types_by_index[i];
  7438. if (type.is_family || this.typeHasNoSaveBehavior(type))
  7439. continue;
  7440. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  7441. {
  7442. inst = type.instances[j];
  7443. if (type.is_contained)
  7444. {
  7445. iid = inst.get_iid();
  7446. cr.clearArray(inst.siblings);
  7447. for (k = 0, lenk = type.container.length; k < lenk; k++)
  7448. {
  7449. t = type.container[k];
  7450. if (type === t)
  7451. continue;
  7452. ;
  7453. inst.siblings.push(t.instances[iid]);
  7454. }
  7455. }
  7456. if (inst.afterLoad)
  7457. inst.afterLoad();
  7458. if (inst.behavior_insts)
  7459. {
  7460. for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++)
  7461. {
  7462. binst = inst.behavior_insts[k];
  7463. if (binst.afterLoad)
  7464. binst.afterLoad();
  7465. }
  7466. }
  7467. }
  7468. }
  7469. this.redraw = true;
  7470. return true;
  7471. };
  7472. Runtime.prototype.saveInstanceToJSON = function(inst, state_only)
  7473. {
  7474. var i, len, world, behinst, et;
  7475. var type = inst.type;
  7476. var plugin = type.plugin;
  7477. var o = {};
  7478. if (state_only)
  7479. o["c2"] = true; // mark as known json data from Construct 2
  7480. else
  7481. o["uid"] = inst.uid;
  7482. if (cr.hasAnyOwnProperty(inst.extra))
  7483. o["ex"] = CopyExtraObject(inst.extra);
  7484. if (inst.instance_vars && inst.instance_vars.length)
  7485. {
  7486. o["ivs"] = {};
  7487. for (i = 0, len = inst.instance_vars.length; i < len; i++)
  7488. {
  7489. o["ivs"][inst.type.instvar_sids[i].toString()] = inst.instance_vars[i];
  7490. }
  7491. }
  7492. if (plugin.is_world)
  7493. {
  7494. world = {
  7495. "x": inst.x,
  7496. "y": inst.y,
  7497. "w": inst.width,
  7498. "h": inst.height,
  7499. "l": inst.layer.sid,
  7500. "zi": inst.get_zindex()
  7501. };
  7502. if (inst.angle !== 0)
  7503. world["a"] = inst.angle;
  7504. if (inst.opacity !== 1)
  7505. world["o"] = inst.opacity;
  7506. if (inst.hotspotX !== 0.5)
  7507. world["hX"] = inst.hotspotX;
  7508. if (inst.hotspotY !== 0.5)
  7509. world["hY"] = inst.hotspotY;
  7510. if (inst.blend_mode !== 0)
  7511. world["bm"] = inst.blend_mode;
  7512. if (!inst.visible)
  7513. world["v"] = inst.visible;
  7514. if (!inst.collisionsEnabled)
  7515. world["ce"] = inst.collisionsEnabled;
  7516. if (inst.my_timescale !== -1)
  7517. world["mts"] = inst.my_timescale;
  7518. if (type.effect_types.length)
  7519. {
  7520. world["fx"] = [];
  7521. for (i = 0, len = type.effect_types.length; i < len; i++)
  7522. {
  7523. et = type.effect_types[i];
  7524. world["fx"].push({"name": et.name,
  7525. "active": inst.active_effect_flags[et.index],
  7526. "params": inst.effect_params[et.index] });
  7527. }
  7528. }
  7529. o["w"] = world;
  7530. }
  7531. if (inst.behavior_insts && inst.behavior_insts.length)
  7532. {
  7533. o["behs"] = {};
  7534. for (i = 0, len = inst.behavior_insts.length; i < len; i++)
  7535. {
  7536. behinst = inst.behavior_insts[i];
  7537. if (behinst.saveToJSON)
  7538. o["behs"][behinst.type.sid.toString()] = behinst.saveToJSON();
  7539. }
  7540. }
  7541. if (inst.saveToJSON)
  7542. o["data"] = inst.saveToJSON();
  7543. return o;
  7544. };
  7545. Runtime.prototype.getInstanceVarIndexBySid = function (type, sid_)
  7546. {
  7547. var i, len;
  7548. for (i = 0, len = type.instvar_sids.length; i < len; i++)
  7549. {
  7550. if (type.instvar_sids[i] === sid_)
  7551. return i;
  7552. }
  7553. return -1;
  7554. };
  7555. Runtime.prototype.getBehaviorIndexBySid = function (inst, sid_)
  7556. {
  7557. var i, len;
  7558. for (i = 0, len = inst.behavior_insts.length; i < len; i++)
  7559. {
  7560. if (inst.behavior_insts[i].type.sid === sid_)
  7561. return i;
  7562. }
  7563. return -1;
  7564. };
  7565. Runtime.prototype.loadInstanceFromJSON = function(inst, o, state_only)
  7566. {
  7567. var p, i, len, iv, oivs, world, fxindex, obehs, behindex, value;
  7568. var oldlayer;
  7569. var type = inst.type;
  7570. var plugin = type.plugin;
  7571. if (state_only)
  7572. {
  7573. if (!o["c2"])
  7574. return;
  7575. }
  7576. else
  7577. inst.uid = o["uid"];
  7578. if (o["ex"])
  7579. inst.extra = o["ex"];
  7580. else
  7581. cr.wipe(inst.extra);
  7582. oivs = o["ivs"];
  7583. if (oivs)
  7584. {
  7585. for (p in oivs)
  7586. {
  7587. if (oivs.hasOwnProperty(p))
  7588. {
  7589. iv = this.getInstanceVarIndexBySid(type, parseInt(p, 10));
  7590. if (iv < 0 || iv >= inst.instance_vars.length)
  7591. continue; // must've gone missing
  7592. value = oivs[p];
  7593. if (value === null)
  7594. value = NaN;
  7595. inst.instance_vars[iv] = value;
  7596. }
  7597. }
  7598. }
  7599. if (plugin.is_world)
  7600. {
  7601. world = o["w"];
  7602. if (inst.layer.sid !== world["l"])
  7603. {
  7604. oldlayer = inst.layer;
  7605. inst.layer = this.running_layout.getLayerBySid(world["l"]);
  7606. if (inst.layer)
  7607. {
  7608. oldlayer.removeFromInstanceList(inst, true);
  7609. inst.layer.appendToInstanceList(inst, true);
  7610. inst.set_bbox_changed();
  7611. inst.layer.setZIndicesStaleFrom(0);
  7612. }
  7613. else
  7614. {
  7615. inst.layer = oldlayer;
  7616. if (!state_only)
  7617. this.DestroyInstance(inst);
  7618. }
  7619. }
  7620. inst.x = world["x"];
  7621. inst.y = world["y"];
  7622. inst.width = world["w"];
  7623. inst.height = world["h"];
  7624. inst.zindex = world["zi"];
  7625. inst.angle = world.hasOwnProperty("a") ? world["a"] : 0;
  7626. inst.opacity = world.hasOwnProperty("o") ? world["o"] : 1;
  7627. inst.hotspotX = world.hasOwnProperty("hX") ? world["hX"] : 0.5;
  7628. inst.hotspotY = world.hasOwnProperty("hY") ? world["hY"] : 0.5;
  7629. inst.visible = world.hasOwnProperty("v") ? world["v"] : true;
  7630. inst.collisionsEnabled = world.hasOwnProperty("ce") ? world["ce"] : true;
  7631. inst.my_timescale = world.hasOwnProperty("mts") ? world["mts"] : -1;
  7632. inst.blend_mode = world.hasOwnProperty("bm") ? world["bm"] : 0;;
  7633. inst.compositeOp = cr.effectToCompositeOp(inst.blend_mode);
  7634. if (this.gl)
  7635. cr.setGLBlend(inst, inst.blend_mode, this.gl);
  7636. inst.set_bbox_changed();
  7637. if (world.hasOwnProperty("fx"))
  7638. {
  7639. for (i = 0, len = world["fx"].length; i < len; i++)
  7640. {
  7641. fxindex = type.getEffectIndexByName(world["fx"][i]["name"]);
  7642. if (fxindex < 0)
  7643. continue; // must've gone missing
  7644. inst.active_effect_flags[fxindex] = world["fx"][i]["active"];
  7645. inst.effect_params[fxindex] = world["fx"][i]["params"];
  7646. }
  7647. }
  7648. inst.updateActiveEffects();
  7649. }
  7650. obehs = o["behs"];
  7651. if (obehs)
  7652. {
  7653. for (p in obehs)
  7654. {
  7655. if (obehs.hasOwnProperty(p))
  7656. {
  7657. behindex = this.getBehaviorIndexBySid(inst, parseInt(p, 10));
  7658. if (behindex < 0)
  7659. continue; // must've gone missing
  7660. inst.behavior_insts[behindex].loadFromJSON(obehs[p]);
  7661. }
  7662. }
  7663. }
  7664. if (o["data"])
  7665. inst.loadFromJSON(o["data"]);
  7666. };
  7667. Runtime.prototype.fetchLocalFileViaCordova = function (filename, successCallback, errorCallback)
  7668. {
  7669. var path = cordova["file"]["applicationDirectory"] + "www/" + filename;
  7670. window["resolveLocalFileSystemURL"](path, function (entry)
  7671. {
  7672. entry.file(successCallback, errorCallback);
  7673. }, errorCallback);
  7674. };
  7675. Runtime.prototype.fetchLocalFileViaCordovaAsText = function (filename, successCallback, errorCallback)
  7676. {
  7677. this.fetchLocalFileViaCordova(filename, function (file)
  7678. {
  7679. var reader = new FileReader();
  7680. reader.onload = function (e)
  7681. {
  7682. successCallback(e.target.result);
  7683. };
  7684. reader.onerror = errorCallback;
  7685. reader.readAsText(file);
  7686. }, errorCallback);
  7687. };
  7688. var queuedArrayBufferReads = [];
  7689. var activeArrayBufferReads = 0;
  7690. var MAX_ARRAYBUFFER_READS = 8;
  7691. Runtime.prototype.maybeStartNextArrayBufferRead = function()
  7692. {
  7693. if (!queuedArrayBufferReads.length)
  7694. return; // none left
  7695. if (activeArrayBufferReads >= MAX_ARRAYBUFFER_READS)
  7696. return; // already got maximum number in-flight
  7697. activeArrayBufferReads++;
  7698. var job = queuedArrayBufferReads.shift();
  7699. this.doFetchLocalFileViaCordovaAsArrayBuffer(job.filename, job.successCallback, job.errorCallback);
  7700. };
  7701. Runtime.prototype.fetchLocalFileViaCordovaAsArrayBuffer = function (filename, successCallback_, errorCallback_)
  7702. {
  7703. var self = this;
  7704. queuedArrayBufferReads.push({
  7705. filename: filename,
  7706. successCallback: function (result)
  7707. {
  7708. activeArrayBufferReads--;
  7709. self.maybeStartNextArrayBufferRead();
  7710. successCallback_(result);
  7711. },
  7712. errorCallback: function (err)
  7713. {
  7714. activeArrayBufferReads--;
  7715. self.maybeStartNextArrayBufferRead();
  7716. errorCallback_(err);
  7717. }
  7718. });
  7719. this.maybeStartNextArrayBufferRead();
  7720. };
  7721. Runtime.prototype.doFetchLocalFileViaCordovaAsArrayBuffer = function (filename, successCallback, errorCallback)
  7722. {
  7723. this.fetchLocalFileViaCordova(filename, function (file)
  7724. {
  7725. var reader = new FileReader();
  7726. reader.onload = function (e)
  7727. {
  7728. successCallback(e.target.result);
  7729. };
  7730. reader.readAsArrayBuffer(file);
  7731. }, errorCallback);
  7732. };
  7733. Runtime.prototype.fetchLocalFileViaCordovaAsURL = function (filename, successCallback, errorCallback)
  7734. {
  7735. var blobType = "";
  7736. var lowername = filename.toLowerCase();
  7737. var ext3 = lowername.substr(lowername.length - 4);
  7738. var ext4 = lowername.substr(lowername.length - 5);
  7739. if (ext3 === ".mp4")
  7740. blobType = "video/mp4";
  7741. else if (ext4 === ".webm")
  7742. blobType = "video/webm"; // use video type but hopefully works with audio too
  7743. else if (ext3 === ".m4a")
  7744. blobType = "audio/mp4";
  7745. else if (ext3 === ".mp3")
  7746. blobType = "audio/mpeg";
  7747. this.fetchLocalFileViaCordovaAsArrayBuffer(filename, function (arrayBuffer)
  7748. {
  7749. var blob = new Blob([arrayBuffer], { type: blobType });
  7750. var url = URL.createObjectURL(blob);
  7751. successCallback(url);
  7752. }, errorCallback);
  7753. };
  7754. Runtime.prototype.isAbsoluteUrl = function (url)
  7755. {
  7756. return /^(?:[a-z]+:)?\/\//.test(url) || url.substr(0, 5) === "data:" || url.substr(0, 5) === "blob:";
  7757. };
  7758. Runtime.prototype.setImageSrc = function (img, src)
  7759. {
  7760. if (this.isWKWebView && !this.isAbsoluteUrl(src))
  7761. {
  7762. this.fetchLocalFileViaCordovaAsURL(src, function (url)
  7763. {
  7764. img.src = url;
  7765. }, function (err)
  7766. {
  7767. alert("Failed to load image: " + err);
  7768. });
  7769. }
  7770. else
  7771. {
  7772. img.src = src;
  7773. }
  7774. };
  7775. Runtime.prototype.setCtxImageSmoothingEnabled = function (ctx, e)
  7776. {
  7777. if (typeof ctx["imageSmoothingEnabled"] !== "undefined")
  7778. {
  7779. ctx["imageSmoothingEnabled"] = e;
  7780. }
  7781. else
  7782. {
  7783. ctx["webkitImageSmoothingEnabled"] = e;
  7784. ctx["mozImageSmoothingEnabled"] = e;
  7785. ctx["msImageSmoothingEnabled"] = e;
  7786. }
  7787. };
  7788. cr.runtime = Runtime;
  7789. cr.createRuntime = function (canvasid)
  7790. {
  7791. return new Runtime(document.getElementById(canvasid));
  7792. };
  7793. cr.createDCRuntime = function (w, h)
  7794. {
  7795. return new Runtime({ "dc": true, "width": w, "height": h });
  7796. };
  7797. window["cr_createRuntime"] = cr.createRuntime;
  7798. window["cr_createDCRuntime"] = cr.createDCRuntime;
  7799. window["createCocoonJSRuntime"] = function ()
  7800. {
  7801. window["c2cocoonjs"] = true;
  7802. var canvas = document.createElement("screencanvas") || document.createElement("canvas");
  7803. canvas.screencanvas = true;
  7804. document.body.appendChild(canvas);
  7805. var rt = new Runtime(canvas);
  7806. window["c2runtime"] = rt;
  7807. window.addEventListener("orientationchange", function () {
  7808. window["c2runtime"]["setSize"](window.innerWidth, window.innerHeight);
  7809. });
  7810. window["c2runtime"]["setSize"](window.innerWidth, window.innerHeight);
  7811. return rt;
  7812. };
  7813. window["createEjectaRuntime"] = function ()
  7814. {
  7815. var canvas = document.getElementById("canvas");
  7816. var rt = new Runtime(canvas);
  7817. window["c2runtime"] = rt;
  7818. window["c2runtime"]["setSize"](window.innerWidth, window.innerHeight);
  7819. return rt;
  7820. };
  7821. }());
  7822. window["cr_getC2Runtime"] = function()
  7823. {
  7824. var canvas = document.getElementById("c2canvas");
  7825. if (canvas)
  7826. return canvas["c2runtime"];
  7827. else if (window["c2runtime"])
  7828. return window["c2runtime"];
  7829. else
  7830. return null;
  7831. }
  7832. window["cr_getSnapshot"] = function (format_, quality_)
  7833. {
  7834. var runtime = window["cr_getC2Runtime"]();
  7835. if (runtime)
  7836. runtime.doCanvasSnapshot(format_, quality_);
  7837. }
  7838. window["cr_sizeCanvas"] = function(w, h)
  7839. {
  7840. if (w === 0 || h === 0)
  7841. return;
  7842. var runtime = window["cr_getC2Runtime"]();
  7843. if (runtime)
  7844. runtime["setSize"](w, h);
  7845. }
  7846. window["cr_setSuspended"] = function(s)
  7847. {
  7848. var runtime = window["cr_getC2Runtime"]();
  7849. if (runtime)
  7850. runtime["setSuspended"](s);
  7851. }
  7852. ;
  7853. (function()
  7854. {
  7855. function Layout(runtime, m)
  7856. {
  7857. this.runtime = runtime;
  7858. this.event_sheet = null;
  7859. this.scrollX = (this.runtime.original_width / 2);
  7860. this.scrollY = (this.runtime.original_height / 2);
  7861. this.scale = 1.0;
  7862. this.angle = 0;
  7863. this.first_visit = true;
  7864. this.name = m[0];
  7865. this.originalWidth = m[1];
  7866. this.originalHeight = m[2];
  7867. this.width = m[1];
  7868. this.height = m[2];
  7869. this.unbounded_scrolling = m[3];
  7870. this.sheetname = m[4];
  7871. this.sid = m[5];
  7872. var lm = m[6];
  7873. var i, len;
  7874. this.layers = [];
  7875. this.initial_types = [];
  7876. for (i = 0, len = lm.length; i < len; i++)
  7877. {
  7878. var layer = new cr.layer(this, lm[i]);
  7879. layer.number = i;
  7880. cr.seal(layer);
  7881. this.layers.push(layer);
  7882. }
  7883. var im = m[7];
  7884. this.initial_nonworld = [];
  7885. for (i = 0, len = im.length; i < len; i++)
  7886. {
  7887. var inst = im[i];
  7888. var type = this.runtime.types_by_index[inst[1]];
  7889. ;
  7890. if (!type.default_instance)
  7891. type.default_instance = inst;
  7892. this.initial_nonworld.push(inst);
  7893. if (this.initial_types.indexOf(type) === -1)
  7894. this.initial_types.push(type);
  7895. }
  7896. this.effect_types = [];
  7897. this.active_effect_types = [];
  7898. this.shaders_preserve_opaqueness = true;
  7899. this.effect_params = [];
  7900. for (i = 0, len = m[8].length; i < len; i++)
  7901. {
  7902. this.effect_types.push({
  7903. id: m[8][i][0],
  7904. name: m[8][i][1],
  7905. shaderindex: -1,
  7906. preservesOpaqueness: false,
  7907. active: true,
  7908. index: i
  7909. });
  7910. this.effect_params.push(m[8][i][2].slice(0));
  7911. }
  7912. this.updateActiveEffects();
  7913. this.rcTex = new cr.rect(0, 0, 1, 1);
  7914. this.rcTex2 = new cr.rect(0, 0, 1, 1);
  7915. this.persist_data = {};
  7916. };
  7917. Layout.prototype.saveObjectToPersist = function (inst)
  7918. {
  7919. var sidStr = inst.type.sid.toString();
  7920. if (!this.persist_data.hasOwnProperty(sidStr))
  7921. this.persist_data[sidStr] = [];
  7922. var type_persist = this.persist_data[sidStr];
  7923. type_persist.push(this.runtime.saveInstanceToJSON(inst));
  7924. };
  7925. Layout.prototype.hasOpaqueBottomLayer = function ()
  7926. {
  7927. var layer = this.layers[0];
  7928. return !layer.transparent && layer.opacity === 1.0 && !layer.forceOwnTexture && layer.visible;
  7929. };
  7930. Layout.prototype.updateActiveEffects = function ()
  7931. {
  7932. cr.clearArray(this.active_effect_types);
  7933. this.shaders_preserve_opaqueness = true;
  7934. var i, len, et;
  7935. for (i = 0, len = this.effect_types.length; i < len; i++)
  7936. {
  7937. et = this.effect_types[i];
  7938. if (et.active)
  7939. {
  7940. this.active_effect_types.push(et);
  7941. if (!et.preservesOpaqueness)
  7942. this.shaders_preserve_opaqueness = false;
  7943. }
  7944. }
  7945. };
  7946. Layout.prototype.getEffectByName = function (name_)
  7947. {
  7948. var i, len, et;
  7949. for (i = 0, len = this.effect_types.length; i < len; i++)
  7950. {
  7951. et = this.effect_types[i];
  7952. if (et.name === name_)
  7953. return et;
  7954. }
  7955. return null;
  7956. };
  7957. var created_instances = [];
  7958. function sort_by_zindex(a, b)
  7959. {
  7960. return a.zindex - b.zindex;
  7961. };
  7962. var first_layout = true;
  7963. Layout.prototype.startRunning = function ()
  7964. {
  7965. if (this.sheetname)
  7966. {
  7967. this.event_sheet = this.runtime.eventsheets[this.sheetname];
  7968. ;
  7969. this.event_sheet.updateDeepIncludes();
  7970. }
  7971. this.runtime.running_layout = this;
  7972. this.width = this.originalWidth;
  7973. this.height = this.originalHeight;
  7974. this.scrollX = (this.runtime.original_width / 2);
  7975. this.scrollY = (this.runtime.original_height / 2);
  7976. var i, k, len, lenk, type, type_instances, initial_inst, inst, iid, t, s, p, q, type_data, layer;
  7977. for (i = 0, len = this.runtime.types_by_index.length; i < len; i++)
  7978. {
  7979. type = this.runtime.types_by_index[i];
  7980. if (type.is_family)
  7981. continue; // instances are only transferred for their real type
  7982. type_instances = type.instances;
  7983. for (k = 0, lenk = type_instances.length; k < lenk; k++)
  7984. {
  7985. inst = type_instances[k];
  7986. if (inst.layer)
  7987. {
  7988. var num = inst.layer.number;
  7989. if (num >= this.layers.length)
  7990. num = this.layers.length - 1;
  7991. inst.layer = this.layers[num];
  7992. if (inst.layer.instances.indexOf(inst) === -1)
  7993. inst.layer.instances.push(inst);
  7994. inst.layer.zindices_stale = true;
  7995. }
  7996. }
  7997. }
  7998. if (!first_layout)
  7999. {
  8000. for (i = 0, len = this.layers.length; i < len; ++i)
  8001. {
  8002. this.layers[i].instances.sort(sort_by_zindex);
  8003. }
  8004. }
  8005. var layer;
  8006. cr.clearArray(created_instances);
  8007. this.boundScrolling();
  8008. for (i = 0, len = this.layers.length; i < len; i++)
  8009. {
  8010. layer = this.layers[i];
  8011. layer.createInitialInstances(); // fills created_instances
  8012. layer.updateViewport(null);
  8013. }
  8014. var uids_changed = false;
  8015. if (!this.first_visit)
  8016. {
  8017. for (p in this.persist_data)
  8018. {
  8019. if (this.persist_data.hasOwnProperty(p))
  8020. {
  8021. type = this.runtime.getObjectTypeBySid(parseInt(p, 10));
  8022. if (!type || type.is_family || !this.runtime.typeHasPersistBehavior(type))
  8023. continue;
  8024. type_data = this.persist_data[p];
  8025. for (i = 0, len = type_data.length; i < len; i++)
  8026. {
  8027. layer = null;
  8028. if (type.plugin.is_world)
  8029. {
  8030. layer = this.getLayerBySid(type_data[i]["w"]["l"]);
  8031. if (!layer)
  8032. continue;
  8033. }
  8034. inst = this.runtime.createInstanceFromInit(type.default_instance, layer, false, 0, 0, true);
  8035. this.runtime.loadInstanceFromJSON(inst, type_data[i]);
  8036. uids_changed = true;
  8037. created_instances.push(inst);
  8038. }
  8039. cr.clearArray(type_data);
  8040. }
  8041. }
  8042. for (i = 0, len = this.layers.length; i < len; i++)
  8043. {
  8044. this.layers[i].instances.sort(sort_by_zindex);
  8045. this.layers[i].zindices_stale = true; // in case of duplicates/holes
  8046. }
  8047. }
  8048. if (uids_changed)
  8049. {
  8050. this.runtime.ClearDeathRow();
  8051. this.runtime.refreshUidMap();
  8052. }
  8053. for (i = 0; i < created_instances.length; i++)
  8054. {
  8055. inst = created_instances[i];
  8056. if (!inst.type.is_contained)
  8057. continue;
  8058. iid = inst.get_iid();
  8059. for (k = 0, lenk = inst.type.container.length; k < lenk; k++)
  8060. {
  8061. t = inst.type.container[k];
  8062. if (inst.type === t)
  8063. continue;
  8064. if (t.instances.length > iid)
  8065. inst.siblings.push(t.instances[iid]);
  8066. else
  8067. {
  8068. if (!t.default_instance)
  8069. {
  8070. }
  8071. else
  8072. {
  8073. s = this.runtime.createInstanceFromInit(t.default_instance, inst.layer, true, inst.x, inst.y, true);
  8074. this.runtime.ClearDeathRow();
  8075. t.updateIIDs();
  8076. inst.siblings.push(s);
  8077. created_instances.push(s); // come back around and link up its own instances too
  8078. }
  8079. }
  8080. }
  8081. }
  8082. for (i = 0, len = this.initial_nonworld.length; i < len; i++)
  8083. {
  8084. initial_inst = this.initial_nonworld[i];
  8085. type = this.runtime.types_by_index[initial_inst[1]];
  8086. if (!type.is_contained)
  8087. {
  8088. inst = this.runtime.createInstanceFromInit(this.initial_nonworld[i], null, true);
  8089. }
  8090. ;
  8091. }
  8092. this.runtime.changelayout = null;
  8093. this.runtime.ClearDeathRow();
  8094. if (this.runtime.ctx && !this.runtime.isDomFree)
  8095. {
  8096. for (i = 0, len = this.runtime.types_by_index.length; i < len; i++)
  8097. {
  8098. t = this.runtime.types_by_index[i];
  8099. if (t.is_family || !t.instances.length || !t.preloadCanvas2D)
  8100. continue;
  8101. t.preloadCanvas2D(this.runtime.ctx);
  8102. }
  8103. }
  8104. /*
  8105. if (this.runtime.glwrap)
  8106. {
  8107. console.log("Estimated VRAM at layout start: " + this.runtime.glwrap.textureCount() + " textures, approx. " + Math.round(this.runtime.glwrap.estimateVRAM() / 1024) + " kb");
  8108. }
  8109. */
  8110. if (this.runtime.isLoadingState)
  8111. {
  8112. cr.shallowAssignArray(this.runtime.fireOnCreateAfterLoad, created_instances);
  8113. }
  8114. else
  8115. {
  8116. for (i = 0, len = created_instances.length; i < len; i++)
  8117. {
  8118. inst = created_instances[i];
  8119. this.runtime.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnCreated, inst);
  8120. }
  8121. }
  8122. cr.clearArray(created_instances);
  8123. if (!this.runtime.isLoadingState)
  8124. {
  8125. this.runtime.trigger(cr.system_object.prototype.cnds.OnLayoutStart, null);
  8126. }
  8127. this.first_visit = false;
  8128. };
  8129. Layout.prototype.createGlobalNonWorlds = function ()
  8130. {
  8131. var i, k, len, initial_inst, inst, type;
  8132. for (i = 0, k = 0, len = this.initial_nonworld.length; i < len; i++)
  8133. {
  8134. initial_inst = this.initial_nonworld[i];
  8135. type = this.runtime.types_by_index[initial_inst[1]];
  8136. if (type.global)
  8137. {
  8138. if (!type.is_contained)
  8139. {
  8140. inst = this.runtime.createInstanceFromInit(initial_inst, null, true);
  8141. }
  8142. }
  8143. else
  8144. {
  8145. this.initial_nonworld[k] = initial_inst;
  8146. k++;
  8147. }
  8148. }
  8149. cr.truncateArray(this.initial_nonworld, k);
  8150. };
  8151. Layout.prototype.stopRunning = function ()
  8152. {
  8153. ;
  8154. /*
  8155. if (this.runtime.glwrap)
  8156. {
  8157. console.log("Estimated VRAM at layout end: " + this.runtime.glwrap.textureCount() + " textures, approx. " + Math.round(this.runtime.glwrap.estimateVRAM() / 1024) + " kb");
  8158. }
  8159. */
  8160. if (!this.runtime.isLoadingState)
  8161. {
  8162. this.runtime.trigger(cr.system_object.prototype.cnds.OnLayoutEnd, null);
  8163. }
  8164. this.runtime.isEndingLayout = true;
  8165. cr.clearArray(this.runtime.system.waits);
  8166. var i, leni, j, lenj;
  8167. var layer_instances, inst, type;
  8168. if (!this.first_visit)
  8169. {
  8170. for (i = 0, leni = this.layers.length; i < leni; i++)
  8171. {
  8172. this.layers[i].updateZIndices();
  8173. layer_instances = this.layers[i].instances;
  8174. for (j = 0, lenj = layer_instances.length; j < lenj; j++)
  8175. {
  8176. inst = layer_instances[j];
  8177. if (!inst.type.global)
  8178. {
  8179. if (this.runtime.typeHasPersistBehavior(inst.type))
  8180. this.saveObjectToPersist(inst);
  8181. }
  8182. }
  8183. }
  8184. }
  8185. for (i = 0, leni = this.layers.length; i < leni; i++)
  8186. {
  8187. layer_instances = this.layers[i].instances;
  8188. for (j = 0, lenj = layer_instances.length; j < lenj; j++)
  8189. {
  8190. inst = layer_instances[j];
  8191. if (!inst.type.global)
  8192. {
  8193. this.runtime.DestroyInstance(inst);
  8194. }
  8195. }
  8196. this.runtime.ClearDeathRow();
  8197. cr.clearArray(layer_instances);
  8198. this.layers[i].zindices_stale = true;
  8199. }
  8200. for (i = 0, leni = this.runtime.types_by_index.length; i < leni; i++)
  8201. {
  8202. type = this.runtime.types_by_index[i];
  8203. if (type.global || type.plugin.is_world || type.plugin.singleglobal || type.is_family)
  8204. continue;
  8205. for (j = 0, lenj = type.instances.length; j < lenj; j++)
  8206. this.runtime.DestroyInstance(type.instances[j]);
  8207. this.runtime.ClearDeathRow();
  8208. }
  8209. first_layout = false;
  8210. this.runtime.isEndingLayout = false;
  8211. };
  8212. var temp_rect = new cr.rect(0, 0, 0, 0);
  8213. Layout.prototype.recreateInitialObjects = function (type, x1, y1, x2, y2)
  8214. {
  8215. temp_rect.set(x1, y1, x2, y2);
  8216. var i, len;
  8217. for (i = 0, len = this.layers.length; i < len; i++)
  8218. {
  8219. this.layers[i].recreateInitialObjects(type, temp_rect);
  8220. }
  8221. };
  8222. Layout.prototype.draw = function (ctx)
  8223. {
  8224. var layout_canvas;
  8225. var layout_ctx = ctx;
  8226. var ctx_changed = false;
  8227. var render_offscreen = !this.runtime.fullscreenScalingQuality;
  8228. if (render_offscreen)
  8229. {
  8230. if (!this.runtime.layout_canvas)
  8231. {
  8232. this.runtime.layout_canvas = document.createElement("canvas");
  8233. layout_canvas = this.runtime.layout_canvas;
  8234. layout_canvas.width = this.runtime.draw_width;
  8235. layout_canvas.height = this.runtime.draw_height;
  8236. this.runtime.layout_ctx = layout_canvas.getContext("2d");
  8237. ctx_changed = true;
  8238. }
  8239. layout_canvas = this.runtime.layout_canvas;
  8240. layout_ctx = this.runtime.layout_ctx;
  8241. if (layout_canvas.width !== this.runtime.draw_width)
  8242. {
  8243. layout_canvas.width = this.runtime.draw_width;
  8244. ctx_changed = true;
  8245. }
  8246. if (layout_canvas.height !== this.runtime.draw_height)
  8247. {
  8248. layout_canvas.height = this.runtime.draw_height;
  8249. ctx_changed = true;
  8250. }
  8251. if (ctx_changed)
  8252. {
  8253. this.runtime.setCtxImageSmoothingEnabled(layout_ctx, this.runtime.linearSampling);
  8254. }
  8255. }
  8256. layout_ctx.globalAlpha = 1;
  8257. layout_ctx.globalCompositeOperation = "source-over";
  8258. if (this.runtime.clearBackground && !this.hasOpaqueBottomLayer())
  8259. layout_ctx.clearRect(0, 0, this.runtime.draw_width, this.runtime.draw_height);
  8260. var i, len, l;
  8261. for (i = 0, len = this.layers.length; i < len; i++)
  8262. {
  8263. l = this.layers[i];
  8264. if (l.visible && l.opacity > 0 && l.blend_mode !== 11 && (l.instances.length || !l.transparent))
  8265. l.draw(layout_ctx);
  8266. else
  8267. l.updateViewport(null); // even if not drawing, keep viewport up to date
  8268. }
  8269. if (render_offscreen)
  8270. {
  8271. ctx.drawImage(layout_canvas, 0, 0, this.runtime.width, this.runtime.height);
  8272. }
  8273. };
  8274. Layout.prototype.drawGL_earlyZPass = function (glw)
  8275. {
  8276. glw.setEarlyZPass(true);
  8277. if (!this.runtime.layout_tex)
  8278. {
  8279. this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  8280. }
  8281. if (this.runtime.layout_tex.c2width !== this.runtime.draw_width || this.runtime.layout_tex.c2height !== this.runtime.draw_height)
  8282. {
  8283. glw.deleteTexture(this.runtime.layout_tex);
  8284. this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  8285. }
  8286. glw.setRenderingToTexture(this.runtime.layout_tex);
  8287. if (!this.runtime.fullscreenScalingQuality)
  8288. {
  8289. glw.setSize(this.runtime.draw_width, this.runtime.draw_height);
  8290. }
  8291. var i, l;
  8292. for (i = this.layers.length - 1; i >= 0; --i)
  8293. {
  8294. l = this.layers[i];
  8295. if (l.visible && l.opacity === 1 && l.shaders_preserve_opaqueness &&
  8296. l.blend_mode === 0 && (l.instances.length || !l.transparent))
  8297. {
  8298. l.drawGL_earlyZPass(glw);
  8299. }
  8300. else
  8301. {
  8302. l.updateViewport(null); // even if not drawing, keep viewport up to date
  8303. }
  8304. }
  8305. glw.setEarlyZPass(false);
  8306. };
  8307. Layout.prototype.drawGL = function (glw)
  8308. {
  8309. var render_to_texture = (this.active_effect_types.length > 0 ||
  8310. this.runtime.uses_background_blending ||
  8311. !this.runtime.fullscreenScalingQuality ||
  8312. this.runtime.enableFrontToBack);
  8313. if (render_to_texture)
  8314. {
  8315. if (!this.runtime.layout_tex)
  8316. {
  8317. this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  8318. }
  8319. if (this.runtime.layout_tex.c2width !== this.runtime.draw_width || this.runtime.layout_tex.c2height !== this.runtime.draw_height)
  8320. {
  8321. glw.deleteTexture(this.runtime.layout_tex);
  8322. this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  8323. }
  8324. glw.setRenderingToTexture(this.runtime.layout_tex);
  8325. if (!this.runtime.fullscreenScalingQuality)
  8326. {
  8327. glw.setSize(this.runtime.draw_width, this.runtime.draw_height);
  8328. }
  8329. }
  8330. else
  8331. {
  8332. if (this.runtime.layout_tex)
  8333. {
  8334. glw.setRenderingToTexture(null);
  8335. glw.deleteTexture(this.runtime.layout_tex);
  8336. this.runtime.layout_tex = null;
  8337. }
  8338. }
  8339. if (this.runtime.clearBackground && !this.hasOpaqueBottomLayer())
  8340. glw.clear(0, 0, 0, 0);
  8341. var i, len, l;
  8342. for (i = 0, len = this.layers.length; i < len; i++)
  8343. {
  8344. l = this.layers[i];
  8345. if (l.visible && l.opacity > 0 && (l.instances.length || !l.transparent))
  8346. l.drawGL(glw);
  8347. else
  8348. l.updateViewport(null); // even if not drawing, keep viewport up to date
  8349. }
  8350. if (render_to_texture)
  8351. {
  8352. if (this.active_effect_types.length === 0 ||
  8353. (this.active_effect_types.length === 1 && this.runtime.fullscreenScalingQuality))
  8354. {
  8355. if (this.active_effect_types.length === 1)
  8356. {
  8357. var etindex = this.active_effect_types[0].index;
  8358. glw.switchProgram(this.active_effect_types[0].shaderindex);
  8359. glw.setProgramParameters(null, // backTex
  8360. 1.0 / this.runtime.draw_width, // pixelWidth
  8361. 1.0 / this.runtime.draw_height, // pixelHeight
  8362. 0.0, 0.0, // destStart
  8363. 1.0, 1.0, // destEnd
  8364. this.scale, // layerScale
  8365. this.angle, // layerAngle
  8366. 0.0, 0.0, // viewOrigin
  8367. this.runtime.draw_width / 2, this.runtime.draw_height / 2, // scrollPos
  8368. this.runtime.kahanTime.sum, // seconds
  8369. this.effect_params[etindex]); // fx parameters
  8370. if (glw.programIsAnimated(this.active_effect_types[0].shaderindex))
  8371. this.runtime.redraw = true;
  8372. }
  8373. else
  8374. glw.switchProgram(0);
  8375. if (!this.runtime.fullscreenScalingQuality)
  8376. {
  8377. glw.setSize(this.runtime.width, this.runtime.height);
  8378. }
  8379. glw.setRenderingToTexture(null); // to backbuffer
  8380. glw.setDepthTestEnabled(false); // ignore depth buffer, copy full texture
  8381. glw.setOpacity(1);
  8382. glw.setTexture(this.runtime.layout_tex);
  8383. glw.setAlphaBlend();
  8384. glw.resetModelView();
  8385. glw.updateModelView();
  8386. var halfw = this.runtime.width / 2;
  8387. var halfh = this.runtime.height / 2;
  8388. glw.quad(-halfw, halfh, halfw, halfh, halfw, -halfh, -halfw, -halfh);
  8389. glw.setTexture(null);
  8390. glw.setDepthTestEnabled(true); // turn depth test back on
  8391. }
  8392. else
  8393. {
  8394. this.renderEffectChain(glw, null, null, null);
  8395. }
  8396. }
  8397. };
  8398. Layout.prototype.getRenderTarget = function()
  8399. {
  8400. if (this.active_effect_types.length > 0 ||
  8401. this.runtime.uses_background_blending ||
  8402. !this.runtime.fullscreenScalingQuality ||
  8403. this.runtime.enableFrontToBack)
  8404. {
  8405. return this.runtime.layout_tex;
  8406. }
  8407. else
  8408. {
  8409. return null;
  8410. }
  8411. };
  8412. Layout.prototype.getMinLayerScale = function ()
  8413. {
  8414. var m = this.layers[0].getScale();
  8415. var i, len, l;
  8416. for (i = 1, len = this.layers.length; i < len; i++)
  8417. {
  8418. l = this.layers[i];
  8419. if (l.parallaxX === 0 && l.parallaxY === 0)
  8420. continue;
  8421. if (l.getScale() < m)
  8422. m = l.getScale();
  8423. }
  8424. return m;
  8425. };
  8426. Layout.prototype.scrollToX = function (x)
  8427. {
  8428. if (!this.unbounded_scrolling)
  8429. {
  8430. var widthBoundary = (this.runtime.draw_width * (1 / this.getMinLayerScale()) / 2);
  8431. if (x > this.width - widthBoundary)
  8432. x = this.width - widthBoundary;
  8433. if (x < widthBoundary)
  8434. x = widthBoundary;
  8435. }
  8436. if (this.scrollX !== x)
  8437. {
  8438. this.scrollX = x;
  8439. this.runtime.redraw = true;
  8440. }
  8441. };
  8442. Layout.prototype.scrollToY = function (y)
  8443. {
  8444. if (!this.unbounded_scrolling)
  8445. {
  8446. var heightBoundary = (this.runtime.draw_height * (1 / this.getMinLayerScale()) / 2);
  8447. if (y > this.height - heightBoundary)
  8448. y = this.height - heightBoundary;
  8449. if (y < heightBoundary)
  8450. y = heightBoundary;
  8451. }
  8452. if (this.scrollY !== y)
  8453. {
  8454. this.scrollY = y;
  8455. this.runtime.redraw = true;
  8456. }
  8457. };
  8458. Layout.prototype.boundScrolling = function ()
  8459. {
  8460. this.scrollToX(this.scrollX);
  8461. this.scrollToY(this.scrollY);
  8462. };
  8463. Layout.prototype.renderEffectChain = function (glw, layer, inst, rendertarget)
  8464. {
  8465. var active_effect_types = inst ?
  8466. inst.active_effect_types :
  8467. layer ?
  8468. layer.active_effect_types :
  8469. this.active_effect_types;
  8470. var layerScale = 1, layerAngle = 0, viewOriginLeft = 0, viewOriginTop = 0, viewOriginRight = this.runtime.draw_width, viewOriginBottom = this.runtime.draw_height;
  8471. if (inst)
  8472. {
  8473. layerScale = inst.layer.getScale();
  8474. layerAngle = inst.layer.getAngle();
  8475. viewOriginLeft = inst.layer.viewLeft;
  8476. viewOriginTop = inst.layer.viewTop;
  8477. viewOriginRight = inst.layer.viewRight;
  8478. viewOriginBottom = inst.layer.viewBottom;
  8479. }
  8480. else if (layer)
  8481. {
  8482. layerScale = layer.getScale();
  8483. layerAngle = layer.getAngle();
  8484. viewOriginLeft = layer.viewLeft;
  8485. viewOriginTop = layer.viewTop;
  8486. viewOriginRight = layer.viewRight;
  8487. viewOriginBottom = layer.viewBottom;
  8488. }
  8489. var fx_tex = this.runtime.fx_tex;
  8490. var i, len, last, temp, fx_index = 0, other_fx_index = 1;
  8491. var y, h;
  8492. var windowWidth = this.runtime.draw_width;
  8493. var windowHeight = this.runtime.draw_height;
  8494. var halfw = windowWidth / 2;
  8495. var halfh = windowHeight / 2;
  8496. var rcTex = layer ? layer.rcTex : this.rcTex;
  8497. var rcTex2 = layer ? layer.rcTex2 : this.rcTex2;
  8498. var screenleft = 0, clearleft = 0;
  8499. var screentop = 0, cleartop = 0;
  8500. var screenright = windowWidth, clearright = windowWidth;
  8501. var screenbottom = windowHeight, clearbottom = windowHeight;
  8502. var boxExtendHorizontal = 0;
  8503. var boxExtendVertical = 0;
  8504. var inst_layer_angle = inst ? inst.layer.getAngle() : 0;
  8505. if (inst)
  8506. {
  8507. for (i = 0, len = active_effect_types.length; i < len; i++)
  8508. {
  8509. boxExtendHorizontal += glw.getProgramBoxExtendHorizontal(active_effect_types[i].shaderindex);
  8510. boxExtendVertical += glw.getProgramBoxExtendVertical(active_effect_types[i].shaderindex);
  8511. }
  8512. var bbox = inst.bbox;
  8513. screenleft = layer.layerToCanvas(bbox.left, bbox.top, true, true);
  8514. screentop = layer.layerToCanvas(bbox.left, bbox.top, false, true);
  8515. screenright = layer.layerToCanvas(bbox.right, bbox.bottom, true, true);
  8516. screenbottom = layer.layerToCanvas(bbox.right, bbox.bottom, false, true);
  8517. if (inst_layer_angle !== 0)
  8518. {
  8519. var screentrx = layer.layerToCanvas(bbox.right, bbox.top, true, true);
  8520. var screentry = layer.layerToCanvas(bbox.right, bbox.top, false, true);
  8521. var screenblx = layer.layerToCanvas(bbox.left, bbox.bottom, true, true);
  8522. var screenbly = layer.layerToCanvas(bbox.left, bbox.bottom, false, true);
  8523. temp = Math.min(screenleft, screenright, screentrx, screenblx);
  8524. screenright = Math.max(screenleft, screenright, screentrx, screenblx);
  8525. screenleft = temp;
  8526. temp = Math.min(screentop, screenbottom, screentry, screenbly);
  8527. screenbottom = Math.max(screentop, screenbottom, screentry, screenbly);
  8528. screentop = temp;
  8529. }
  8530. screenleft -= boxExtendHorizontal;
  8531. screentop -= boxExtendVertical;
  8532. screenright += boxExtendHorizontal;
  8533. screenbottom += boxExtendVertical;
  8534. rcTex2.left = screenleft / windowWidth;
  8535. rcTex2.top = 1 - screentop / windowHeight;
  8536. rcTex2.right = screenright / windowWidth;
  8537. rcTex2.bottom = 1 - screenbottom / windowHeight;
  8538. clearleft = screenleft = cr.floor(screenleft);
  8539. cleartop = screentop = cr.floor(screentop);
  8540. clearright = screenright = cr.ceil(screenright);
  8541. clearbottom = screenbottom = cr.ceil(screenbottom);
  8542. clearleft -= boxExtendHorizontal;
  8543. cleartop -= boxExtendVertical;
  8544. clearright += boxExtendHorizontal;
  8545. clearbottom += boxExtendVertical;
  8546. if (screenleft < 0) screenleft = 0;
  8547. if (screentop < 0) screentop = 0;
  8548. if (screenright > windowWidth) screenright = windowWidth;
  8549. if (screenbottom > windowHeight) screenbottom = windowHeight;
  8550. if (clearleft < 0) clearleft = 0;
  8551. if (cleartop < 0) cleartop = 0;
  8552. if (clearright > windowWidth) clearright = windowWidth;
  8553. if (clearbottom > windowHeight) clearbottom = windowHeight;
  8554. rcTex.left = screenleft / windowWidth;
  8555. rcTex.top = 1 - screentop / windowHeight;
  8556. rcTex.right = screenright / windowWidth;
  8557. rcTex.bottom = 1 - screenbottom / windowHeight;
  8558. }
  8559. else
  8560. {
  8561. rcTex.left = rcTex2.left = 0;
  8562. rcTex.top = rcTex2.top = 0;
  8563. rcTex.right = rcTex2.right = 1;
  8564. rcTex.bottom = rcTex2.bottom = 1;
  8565. }
  8566. var pre_draw = (inst && (glw.programUsesDest(active_effect_types[0].shaderindex) || boxExtendHorizontal !== 0 || boxExtendVertical !== 0 || inst.opacity !== 1 || inst.type.plugin.must_predraw)) || (layer && !inst && layer.opacity !== 1);
  8567. glw.setAlphaBlend();
  8568. if (pre_draw)
  8569. {
  8570. if (!fx_tex[fx_index])
  8571. {
  8572. fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling);
  8573. }
  8574. if (fx_tex[fx_index].c2width !== windowWidth || fx_tex[fx_index].c2height !== windowHeight)
  8575. {
  8576. glw.deleteTexture(fx_tex[fx_index]);
  8577. fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling);
  8578. }
  8579. glw.switchProgram(0);
  8580. glw.setRenderingToTexture(fx_tex[fx_index]);
  8581. h = clearbottom - cleartop;
  8582. y = (windowHeight - cleartop) - h;
  8583. glw.clearRect(clearleft, y, clearright - clearleft, h);
  8584. if (inst)
  8585. {
  8586. inst.drawGL(glw);
  8587. }
  8588. else
  8589. {
  8590. glw.setTexture(this.runtime.layer_tex);
  8591. glw.setOpacity(layer.opacity);
  8592. glw.resetModelView();
  8593. glw.translate(-halfw, -halfh);
  8594. glw.updateModelView();
  8595. glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex);
  8596. }
  8597. rcTex2.left = rcTex2.top = 0;
  8598. rcTex2.right = rcTex2.bottom = 1;
  8599. if (inst)
  8600. {
  8601. temp = rcTex.top;
  8602. rcTex.top = rcTex.bottom;
  8603. rcTex.bottom = temp;
  8604. }
  8605. fx_index = 1;
  8606. other_fx_index = 0;
  8607. }
  8608. glw.setOpacity(1);
  8609. var last = active_effect_types.length - 1;
  8610. var post_draw = glw.programUsesCrossSampling(active_effect_types[last].shaderindex) ||
  8611. (!layer && !inst && !this.runtime.fullscreenScalingQuality);
  8612. var etindex = 0;
  8613. for (i = 0, len = active_effect_types.length; i < len; i++)
  8614. {
  8615. if (!fx_tex[fx_index])
  8616. {
  8617. fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling);
  8618. }
  8619. if (fx_tex[fx_index].c2width !== windowWidth || fx_tex[fx_index].c2height !== windowHeight)
  8620. {
  8621. glw.deleteTexture(fx_tex[fx_index]);
  8622. fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling);
  8623. }
  8624. glw.switchProgram(active_effect_types[i].shaderindex);
  8625. etindex = active_effect_types[i].index;
  8626. if (glw.programIsAnimated(active_effect_types[i].shaderindex))
  8627. this.runtime.redraw = true;
  8628. if (i == 0 && !pre_draw)
  8629. {
  8630. glw.setRenderingToTexture(fx_tex[fx_index]);
  8631. h = clearbottom - cleartop;
  8632. y = (windowHeight - cleartop) - h;
  8633. glw.clearRect(clearleft, y, clearright - clearleft, h);
  8634. if (inst)
  8635. {
  8636. var pixelWidth;
  8637. var pixelHeight;
  8638. if (inst.curFrame && inst.curFrame.texture_img)
  8639. {
  8640. var img = inst.curFrame.texture_img;
  8641. pixelWidth = 1.0 / img.width;
  8642. pixelHeight = 1.0 / img.height;
  8643. }
  8644. else
  8645. {
  8646. pixelWidth = 1.0 / inst.width;
  8647. pixelHeight = 1.0 / inst.height;
  8648. }
  8649. glw.setProgramParameters(rendertarget, // backTex
  8650. pixelWidth,
  8651. pixelHeight,
  8652. rcTex2.left, rcTex2.top, // destStart
  8653. rcTex2.right, rcTex2.bottom, // destEnd
  8654. layerScale,
  8655. layerAngle,
  8656. viewOriginLeft, viewOriginTop,
  8657. (viewOriginLeft + viewOriginRight) / 2, (viewOriginTop + viewOriginBottom) / 2,
  8658. this.runtime.kahanTime.sum,
  8659. inst.effect_params[etindex]); // fx params
  8660. inst.drawGL(glw);
  8661. }
  8662. else
  8663. {
  8664. glw.setProgramParameters(rendertarget, // backTex
  8665. 1.0 / windowWidth, // pixelWidth
  8666. 1.0 / windowHeight, // pixelHeight
  8667. 0.0, 0.0, // destStart
  8668. 1.0, 1.0, // destEnd
  8669. layerScale,
  8670. layerAngle,
  8671. viewOriginLeft, viewOriginTop,
  8672. (viewOriginLeft + viewOriginRight) / 2, (viewOriginTop + viewOriginBottom) / 2,
  8673. this.runtime.kahanTime.sum,
  8674. layer ? // fx params
  8675. layer.effect_params[etindex] :
  8676. this.effect_params[etindex]);
  8677. glw.setTexture(layer ? this.runtime.layer_tex : this.runtime.layout_tex);
  8678. glw.resetModelView();
  8679. glw.translate(-halfw, -halfh);
  8680. glw.updateModelView();
  8681. glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex);
  8682. }
  8683. rcTex2.left = rcTex2.top = 0;
  8684. rcTex2.right = rcTex2.bottom = 1;
  8685. if (inst && !post_draw)
  8686. {
  8687. temp = screenbottom;
  8688. screenbottom = screentop;
  8689. screentop = temp;
  8690. }
  8691. }
  8692. else
  8693. {
  8694. glw.setProgramParameters(rendertarget, // backTex
  8695. 1.0 / windowWidth, // pixelWidth
  8696. 1.0 / windowHeight, // pixelHeight
  8697. rcTex2.left, rcTex2.top, // destStart
  8698. rcTex2.right, rcTex2.bottom, // destEnd
  8699. layerScale,
  8700. layerAngle,
  8701. viewOriginLeft, viewOriginTop,
  8702. (viewOriginLeft + viewOriginRight) / 2, (viewOriginTop + viewOriginBottom) / 2,
  8703. this.runtime.kahanTime.sum,
  8704. inst ? // fx params
  8705. inst.effect_params[etindex] :
  8706. layer ?
  8707. layer.effect_params[etindex] :
  8708. this.effect_params[etindex]);
  8709. glw.setTexture(null);
  8710. if (i === last && !post_draw)
  8711. {
  8712. if (inst)
  8713. glw.setBlend(inst.srcBlend, inst.destBlend);
  8714. else if (layer)
  8715. glw.setBlend(layer.srcBlend, layer.destBlend);
  8716. glw.setRenderingToTexture(rendertarget);
  8717. }
  8718. else
  8719. {
  8720. glw.setRenderingToTexture(fx_tex[fx_index]);
  8721. h = clearbottom - cleartop;
  8722. y = (windowHeight - cleartop) - h;
  8723. glw.clearRect(clearleft, y, clearright - clearleft, h);
  8724. }
  8725. glw.setTexture(fx_tex[other_fx_index]);
  8726. glw.resetModelView();
  8727. glw.translate(-halfw, -halfh);
  8728. glw.updateModelView();
  8729. glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex);
  8730. if (i === last && !post_draw)
  8731. glw.setTexture(null);
  8732. }
  8733. fx_index = (fx_index === 0 ? 1 : 0);
  8734. other_fx_index = (fx_index === 0 ? 1 : 0); // will be opposite to fx_index since it was just assigned
  8735. }
  8736. if (post_draw)
  8737. {
  8738. glw.switchProgram(0);
  8739. if (inst)
  8740. glw.setBlend(inst.srcBlend, inst.destBlend);
  8741. else if (layer)
  8742. glw.setBlend(layer.srcBlend, layer.destBlend);
  8743. else
  8744. {
  8745. if (!this.runtime.fullscreenScalingQuality)
  8746. {
  8747. glw.setSize(this.runtime.width, this.runtime.height);
  8748. halfw = this.runtime.width / 2;
  8749. halfh = this.runtime.height / 2;
  8750. screenleft = 0;
  8751. screentop = 0;
  8752. screenright = this.runtime.width;
  8753. screenbottom = this.runtime.height;
  8754. }
  8755. }
  8756. glw.setRenderingToTexture(rendertarget);
  8757. glw.setTexture(fx_tex[other_fx_index]);
  8758. glw.resetModelView();
  8759. glw.translate(-halfw, -halfh);
  8760. glw.updateModelView();
  8761. if (inst && active_effect_types.length === 1 && !pre_draw)
  8762. glw.quadTex(screenleft, screentop, screenright, screentop, screenright, screenbottom, screenleft, screenbottom, rcTex);
  8763. else
  8764. glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex);
  8765. glw.setTexture(null);
  8766. }
  8767. };
  8768. Layout.prototype.getLayerBySid = function (sid_)
  8769. {
  8770. var i, len;
  8771. for (i = 0, len = this.layers.length; i < len; i++)
  8772. {
  8773. if (this.layers[i].sid === sid_)
  8774. return this.layers[i];
  8775. }
  8776. return null;
  8777. };
  8778. Layout.prototype.saveToJSON = function ()
  8779. {
  8780. var i, len, layer, et;
  8781. var o = {
  8782. "sx": this.scrollX,
  8783. "sy": this.scrollY,
  8784. "s": this.scale,
  8785. "a": this.angle,
  8786. "w": this.width,
  8787. "h": this.height,
  8788. "fv": this.first_visit, // added r127
  8789. "persist": this.persist_data,
  8790. "fx": [],
  8791. "layers": {}
  8792. };
  8793. for (i = 0, len = this.effect_types.length; i < len; i++)
  8794. {
  8795. et = this.effect_types[i];
  8796. o["fx"].push({"name": et.name, "active": et.active, "params": this.effect_params[et.index] });
  8797. }
  8798. for (i = 0, len = this.layers.length; i < len; i++)
  8799. {
  8800. layer = this.layers[i];
  8801. o["layers"][layer.sid.toString()] = layer.saveToJSON();
  8802. }
  8803. return o;
  8804. };
  8805. Layout.prototype.loadFromJSON = function (o)
  8806. {
  8807. var i, j, len, fx, p, layer;
  8808. this.scrollX = o["sx"];
  8809. this.scrollY = o["sy"];
  8810. this.scale = o["s"];
  8811. this.angle = o["a"];
  8812. this.width = o["w"];
  8813. this.height = o["h"];
  8814. this.persist_data = o["persist"];
  8815. if (typeof o["fv"] !== "undefined")
  8816. this.first_visit = o["fv"];
  8817. var ofx = o["fx"];
  8818. for (i = 0, len = ofx.length; i < len; i++)
  8819. {
  8820. fx = this.getEffectByName(ofx[i]["name"]);
  8821. if (!fx)
  8822. continue; // must've gone missing
  8823. fx.active = ofx[i]["active"];
  8824. this.effect_params[fx.index] = ofx[i]["params"];
  8825. }
  8826. this.updateActiveEffects();
  8827. var olayers = o["layers"];
  8828. for (p in olayers)
  8829. {
  8830. if (olayers.hasOwnProperty(p))
  8831. {
  8832. layer = this.getLayerBySid(parseInt(p, 10));
  8833. if (!layer)
  8834. continue; // must've gone missing
  8835. layer.loadFromJSON(olayers[p]);
  8836. }
  8837. }
  8838. };
  8839. cr.layout = Layout;
  8840. function Layer(layout, m)
  8841. {
  8842. this.layout = layout;
  8843. this.runtime = layout.runtime;
  8844. this.instances = []; // running instances
  8845. this.scale = 1.0;
  8846. this.angle = 0;
  8847. this.disableAngle = false;
  8848. this.tmprect = new cr.rect(0, 0, 0, 0);
  8849. this.tmpquad = new cr.quad();
  8850. this.viewLeft = 0;
  8851. this.viewRight = 0;
  8852. this.viewTop = 0;
  8853. this.viewBottom = 0;
  8854. this.zindices_stale = false;
  8855. this.zindices_stale_from = -1; // first index that has changed, or -1 if no bound
  8856. this.clear_earlyz_index = 0;
  8857. this.name = m[0];
  8858. this.index = m[1];
  8859. this.sid = m[2];
  8860. this.visible = m[3]; // initially visible
  8861. this.background_color = m[4];
  8862. this.transparent = m[5];
  8863. this.parallaxX = m[6];
  8864. this.parallaxY = m[7];
  8865. this.opacity = m[8];
  8866. this.forceOwnTexture = m[9];
  8867. this.useRenderCells = m[10];
  8868. this.zoomRate = m[11];
  8869. this.blend_mode = m[12];
  8870. this.effect_fallback = m[13];
  8871. this.compositeOp = "source-over";
  8872. this.srcBlend = 0;
  8873. this.destBlend = 0;
  8874. this.render_grid = null;
  8875. this.last_render_list = alloc_arr();
  8876. this.render_list_stale = true;
  8877. this.last_render_cells = new cr.rect(0, 0, -1, -1);
  8878. this.cur_render_cells = new cr.rect(0, 0, -1, -1);
  8879. if (this.useRenderCells)
  8880. {
  8881. this.render_grid = new cr.RenderGrid(this.runtime.original_width, this.runtime.original_height);
  8882. }
  8883. this.render_offscreen = false;
  8884. var im = m[14];
  8885. var i, len;
  8886. this.startup_initial_instances = []; // for restoring initial_instances after load
  8887. this.initial_instances = [];
  8888. this.created_globals = []; // global object UIDs already created - for save/load to avoid recreating
  8889. for (i = 0, len = im.length; i < len; i++)
  8890. {
  8891. var inst = im[i];
  8892. var type = this.runtime.types_by_index[inst[1]];
  8893. ;
  8894. if (!type.default_instance)
  8895. {
  8896. type.default_instance = inst;
  8897. type.default_layerindex = this.index;
  8898. }
  8899. this.initial_instances.push(inst);
  8900. if (this.layout.initial_types.indexOf(type) === -1)
  8901. this.layout.initial_types.push(type);
  8902. }
  8903. cr.shallowAssignArray(this.startup_initial_instances, this.initial_instances);
  8904. this.effect_types = [];
  8905. this.active_effect_types = [];
  8906. this.shaders_preserve_opaqueness = true;
  8907. this.effect_params = [];
  8908. for (i = 0, len = m[15].length; i < len; i++)
  8909. {
  8910. this.effect_types.push({
  8911. id: m[15][i][0],
  8912. name: m[15][i][1],
  8913. shaderindex: -1,
  8914. preservesOpaqueness: false,
  8915. active: true,
  8916. index: i
  8917. });
  8918. this.effect_params.push(m[15][i][2].slice(0));
  8919. }
  8920. this.updateActiveEffects();
  8921. this.rcTex = new cr.rect(0, 0, 1, 1);
  8922. this.rcTex2 = new cr.rect(0, 0, 1, 1);
  8923. };
  8924. Layer.prototype.updateActiveEffects = function ()
  8925. {
  8926. cr.clearArray(this.active_effect_types);
  8927. this.shaders_preserve_opaqueness = true;
  8928. var i, len, et;
  8929. for (i = 0, len = this.effect_types.length; i < len; i++)
  8930. {
  8931. et = this.effect_types[i];
  8932. if (et.active)
  8933. {
  8934. this.active_effect_types.push(et);
  8935. if (!et.preservesOpaqueness)
  8936. this.shaders_preserve_opaqueness = false;
  8937. }
  8938. }
  8939. };
  8940. Layer.prototype.getEffectByName = function (name_)
  8941. {
  8942. var i, len, et;
  8943. for (i = 0, len = this.effect_types.length; i < len; i++)
  8944. {
  8945. et = this.effect_types[i];
  8946. if (et.name === name_)
  8947. return et;
  8948. }
  8949. return null;
  8950. };
  8951. Layer.prototype.createInitialInstances = function ()
  8952. {
  8953. var i, k, len, inst, initial_inst, type, keep, hasPersistBehavior;
  8954. for (i = 0, k = 0, len = this.initial_instances.length; i < len; i++)
  8955. {
  8956. initial_inst = this.initial_instances[i];
  8957. type = this.runtime.types_by_index[initial_inst[1]];
  8958. ;
  8959. hasPersistBehavior = this.runtime.typeHasPersistBehavior(type);
  8960. keep = true;
  8961. if (!hasPersistBehavior || this.layout.first_visit)
  8962. {
  8963. inst = this.runtime.createInstanceFromInit(initial_inst, this, true);
  8964. if (!inst)
  8965. continue; // may have skipped creation due to fallback effect "destroy"
  8966. created_instances.push(inst);
  8967. if (inst.type.global)
  8968. {
  8969. keep = false;
  8970. this.created_globals.push(inst.uid);
  8971. }
  8972. }
  8973. if (keep)
  8974. {
  8975. this.initial_instances[k] = this.initial_instances[i];
  8976. k++;
  8977. }
  8978. }
  8979. this.initial_instances.length = k;
  8980. this.runtime.ClearDeathRow(); // flushes creation row so IIDs will be correct
  8981. if (!this.runtime.glwrap && this.effect_types.length) // no WebGL renderer and shaders used
  8982. this.blend_mode = this.effect_fallback; // use fallback blend mode
  8983. this.compositeOp = cr.effectToCompositeOp(this.blend_mode);
  8984. if (this.runtime.gl)
  8985. cr.setGLBlend(this, this.blend_mode, this.runtime.gl);
  8986. this.render_list_stale = true;
  8987. };
  8988. Layer.prototype.recreateInitialObjects = function (only_type, rc)
  8989. {
  8990. var i, len, initial_inst, type, wm, x, y, inst, j, lenj, s;
  8991. var types_by_index = this.runtime.types_by_index;
  8992. var only_type_is_family = only_type.is_family;
  8993. var only_type_members = only_type.members;
  8994. for (i = 0, len = this.initial_instances.length; i < len; ++i)
  8995. {
  8996. initial_inst = this.initial_instances[i];
  8997. wm = initial_inst[0];
  8998. x = wm[0];
  8999. y = wm[1];
  9000. if (!rc.contains_pt(x, y))
  9001. continue; // not in the given area
  9002. type = types_by_index[initial_inst[1]];
  9003. if (type !== only_type)
  9004. {
  9005. if (only_type_is_family)
  9006. {
  9007. if (only_type_members.indexOf(type) < 0)
  9008. continue;
  9009. }
  9010. else
  9011. continue; // only_type is not a family, and the initial inst type does not match
  9012. }
  9013. inst = this.runtime.createInstanceFromInit(initial_inst, this, false);
  9014. this.runtime.isInOnDestroy++;
  9015. this.runtime.trigger(Object.getPrototypeOf(type.plugin).cnds.OnCreated, inst);
  9016. if (inst.is_contained)
  9017. {
  9018. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  9019. {
  9020. s = inst.siblings[i];
  9021. this.runtime.trigger(Object.getPrototypeOf(s.type.plugin).cnds.OnCreated, s);
  9022. }
  9023. }
  9024. this.runtime.isInOnDestroy--;
  9025. }
  9026. };
  9027. Layer.prototype.removeFromInstanceList = function (inst, remove_from_grid)
  9028. {
  9029. var index = cr.fastIndexOf(this.instances, inst);
  9030. if (index < 0)
  9031. return; // not found
  9032. if (remove_from_grid && this.useRenderCells && inst.rendercells && inst.rendercells.right >= inst.rendercells.left)
  9033. {
  9034. inst.update_bbox(); // make sure actually in its current rendercells
  9035. this.render_grid.update(inst, inst.rendercells, null); // no new range provided - remove only
  9036. inst.rendercells.set(0, 0, -1, -1); // set to invalid state to indicate not inserted
  9037. }
  9038. if (index === this.instances.length - 1)
  9039. this.instances.pop();
  9040. else
  9041. {
  9042. cr.arrayRemove(this.instances, index);
  9043. this.setZIndicesStaleFrom(index);
  9044. }
  9045. this.render_list_stale = true;
  9046. };
  9047. Layer.prototype.appendToInstanceList = function (inst, add_to_grid)
  9048. {
  9049. ;
  9050. inst.zindex = this.instances.length;
  9051. this.instances.push(inst);
  9052. if (add_to_grid && this.useRenderCells && inst.rendercells)
  9053. {
  9054. inst.set_bbox_changed(); // will cause immediate update and new insertion to grid
  9055. }
  9056. this.render_list_stale = true;
  9057. };
  9058. Layer.prototype.prependToInstanceList = function (inst, add_to_grid)
  9059. {
  9060. ;
  9061. this.instances.unshift(inst);
  9062. this.setZIndicesStaleFrom(0);
  9063. if (add_to_grid && this.useRenderCells && inst.rendercells)
  9064. {
  9065. inst.set_bbox_changed(); // will cause immediate update and new insertion to grid
  9066. }
  9067. };
  9068. Layer.prototype.moveInstanceAdjacent = function (inst, other, isafter)
  9069. {
  9070. ;
  9071. var myZ = inst.get_zindex();
  9072. var insertZ = other.get_zindex();
  9073. cr.arrayRemove(this.instances, myZ);
  9074. if (myZ < insertZ)
  9075. insertZ--;
  9076. if (isafter)
  9077. insertZ++;
  9078. if (insertZ === this.instances.length)
  9079. this.instances.push(inst);
  9080. else
  9081. this.instances.splice(insertZ, 0, inst);
  9082. this.setZIndicesStaleFrom(myZ < insertZ ? myZ : insertZ);
  9083. };
  9084. Layer.prototype.setZIndicesStaleFrom = function (index)
  9085. {
  9086. if (this.zindices_stale_from === -1) // not yet set
  9087. this.zindices_stale_from = index;
  9088. else if (index < this.zindices_stale_from) // determine minimum z index affected
  9089. this.zindices_stale_from = index;
  9090. this.zindices_stale = true;
  9091. this.render_list_stale = true;
  9092. };
  9093. Layer.prototype.updateZIndices = function ()
  9094. {
  9095. if (!this.zindices_stale)
  9096. return;
  9097. if (this.zindices_stale_from === -1)
  9098. this.zindices_stale_from = 0;
  9099. var i, len, inst;
  9100. if (this.useRenderCells)
  9101. {
  9102. for (i = this.zindices_stale_from, len = this.instances.length; i < len; ++i)
  9103. {
  9104. inst = this.instances[i];
  9105. inst.zindex = i;
  9106. this.render_grid.markRangeChanged(inst.rendercells);
  9107. }
  9108. }
  9109. else
  9110. {
  9111. for (i = this.zindices_stale_from, len = this.instances.length; i < len; ++i)
  9112. {
  9113. this.instances[i].zindex = i;
  9114. }
  9115. }
  9116. this.zindices_stale = false;
  9117. this.zindices_stale_from = -1;
  9118. };
  9119. Layer.prototype.getScale = function (include_aspect)
  9120. {
  9121. return this.getNormalScale() * (this.runtime.fullscreenScalingQuality || include_aspect ? this.runtime.aspect_scale : 1);
  9122. };
  9123. Layer.prototype.getNormalScale = function ()
  9124. {
  9125. return ((this.scale * this.layout.scale) - 1) * this.zoomRate + 1;
  9126. };
  9127. Layer.prototype.getAngle = function ()
  9128. {
  9129. if (this.disableAngle)
  9130. return 0;
  9131. return cr.clamp_angle(this.layout.angle + this.angle);
  9132. };
  9133. var arr_cache = [];
  9134. function alloc_arr()
  9135. {
  9136. if (arr_cache.length)
  9137. return arr_cache.pop();
  9138. else
  9139. return [];
  9140. }
  9141. function free_arr(a)
  9142. {
  9143. cr.clearArray(a);
  9144. arr_cache.push(a);
  9145. };
  9146. function mergeSortedZArrays(a, b, out)
  9147. {
  9148. var i = 0, j = 0, k = 0, lena = a.length, lenb = b.length, ai, bj;
  9149. out.length = lena + lenb;
  9150. for ( ; i < lena && j < lenb; ++k)
  9151. {
  9152. ai = a[i];
  9153. bj = b[j];
  9154. if (ai.zindex < bj.zindex)
  9155. {
  9156. out[k] = ai;
  9157. ++i;
  9158. }
  9159. else
  9160. {
  9161. out[k] = bj;
  9162. ++j;
  9163. }
  9164. }
  9165. for ( ; i < lena; ++i, ++k)
  9166. out[k] = a[i];
  9167. for ( ; j < lenb; ++j, ++k)
  9168. out[k] = b[j];
  9169. };
  9170. var next_arr = [];
  9171. function mergeAllSortedZArrays_pass(arr, first_pass)
  9172. {
  9173. var i, len, arr1, arr2, out;
  9174. for (i = 0, len = arr.length; i < len - 1; i += 2)
  9175. {
  9176. arr1 = arr[i];
  9177. arr2 = arr[i+1];
  9178. out = alloc_arr();
  9179. mergeSortedZArrays(arr1, arr2, out);
  9180. if (!first_pass)
  9181. {
  9182. free_arr(arr1);
  9183. free_arr(arr2);
  9184. }
  9185. next_arr.push(out);
  9186. }
  9187. if (len % 2 === 1)
  9188. {
  9189. if (first_pass)
  9190. {
  9191. arr1 = alloc_arr();
  9192. cr.shallowAssignArray(arr1, arr[len - 1]);
  9193. next_arr.push(arr1);
  9194. }
  9195. else
  9196. {
  9197. next_arr.push(arr[len - 1]);
  9198. }
  9199. }
  9200. cr.shallowAssignArray(arr, next_arr);
  9201. cr.clearArray(next_arr);
  9202. };
  9203. function mergeAllSortedZArrays(arr)
  9204. {
  9205. var first_pass = true;
  9206. while (arr.length > 1)
  9207. {
  9208. mergeAllSortedZArrays_pass(arr, first_pass);
  9209. first_pass = false;
  9210. }
  9211. return arr[0];
  9212. };
  9213. var render_arr = [];
  9214. Layer.prototype.getRenderCellInstancesToDraw = function ()
  9215. {
  9216. ;
  9217. this.updateZIndices();
  9218. this.render_grid.queryRange(this.viewLeft, this.viewTop, this.viewRight, this.viewBottom, render_arr);
  9219. if (!render_arr.length)
  9220. return alloc_arr();
  9221. if (render_arr.length === 1)
  9222. {
  9223. var a = alloc_arr();
  9224. cr.shallowAssignArray(a, render_arr[0]);
  9225. cr.clearArray(render_arr);
  9226. return a;
  9227. }
  9228. var draw_list = mergeAllSortedZArrays(render_arr);
  9229. cr.clearArray(render_arr);
  9230. return draw_list;
  9231. };
  9232. Layer.prototype.draw = function (ctx)
  9233. {
  9234. this.render_offscreen = (this.forceOwnTexture || this.opacity !== 1.0 || this.blend_mode !== 0);
  9235. var layer_canvas = this.runtime.canvas;
  9236. var layer_ctx = ctx;
  9237. var ctx_changed = false;
  9238. if (this.render_offscreen)
  9239. {
  9240. if (!this.runtime.layer_canvas)
  9241. {
  9242. this.runtime.layer_canvas = document.createElement("canvas");
  9243. ;
  9244. layer_canvas = this.runtime.layer_canvas;
  9245. layer_canvas.width = this.runtime.draw_width;
  9246. layer_canvas.height = this.runtime.draw_height;
  9247. this.runtime.layer_ctx = layer_canvas.getContext("2d");
  9248. ;
  9249. ctx_changed = true;
  9250. }
  9251. layer_canvas = this.runtime.layer_canvas;
  9252. layer_ctx = this.runtime.layer_ctx;
  9253. if (layer_canvas.width !== this.runtime.draw_width)
  9254. {
  9255. layer_canvas.width = this.runtime.draw_width;
  9256. ctx_changed = true;
  9257. }
  9258. if (layer_canvas.height !== this.runtime.draw_height)
  9259. {
  9260. layer_canvas.height = this.runtime.draw_height;
  9261. ctx_changed = true;
  9262. }
  9263. if (ctx_changed)
  9264. {
  9265. this.runtime.setCtxImageSmoothingEnabled(layer_ctx, this.runtime.linearSampling);
  9266. }
  9267. if (this.transparent)
  9268. layer_ctx.clearRect(0, 0, this.runtime.draw_width, this.runtime.draw_height);
  9269. }
  9270. layer_ctx.globalAlpha = 1;
  9271. layer_ctx.globalCompositeOperation = "source-over";
  9272. if (!this.transparent)
  9273. {
  9274. layer_ctx.fillStyle = "rgb(" + this.background_color[0] + "," + this.background_color[1] + "," + this.background_color[2] + ")";
  9275. layer_ctx.fillRect(0, 0, this.runtime.draw_width, this.runtime.draw_height);
  9276. }
  9277. layer_ctx.save();
  9278. this.disableAngle = true;
  9279. var px = this.canvasToLayer(0, 0, true, true);
  9280. var py = this.canvasToLayer(0, 0, false, true);
  9281. this.disableAngle = false;
  9282. if (this.runtime.pixel_rounding)
  9283. {
  9284. px = Math.round(px);
  9285. py = Math.round(py);
  9286. }
  9287. this.rotateViewport(px, py, layer_ctx);
  9288. var myscale = this.getScale();
  9289. layer_ctx.scale(myscale, myscale);
  9290. layer_ctx.translate(-px, -py);
  9291. var instances_to_draw;
  9292. if (this.useRenderCells)
  9293. {
  9294. this.cur_render_cells.left = this.render_grid.XToCell(this.viewLeft);
  9295. this.cur_render_cells.top = this.render_grid.YToCell(this.viewTop);
  9296. this.cur_render_cells.right = this.render_grid.XToCell(this.viewRight);
  9297. this.cur_render_cells.bottom = this.render_grid.YToCell(this.viewBottom);
  9298. if (this.render_list_stale || !this.cur_render_cells.equals(this.last_render_cells))
  9299. {
  9300. free_arr(this.last_render_list);
  9301. instances_to_draw = this.getRenderCellInstancesToDraw();
  9302. this.render_list_stale = false;
  9303. this.last_render_cells.copy(this.cur_render_cells);
  9304. }
  9305. else
  9306. instances_to_draw = this.last_render_list;
  9307. }
  9308. else
  9309. instances_to_draw = this.instances;
  9310. var i, len, inst, last_inst = null;
  9311. for (i = 0, len = instances_to_draw.length; i < len; ++i)
  9312. {
  9313. inst = instances_to_draw[i];
  9314. if (inst === last_inst)
  9315. continue;
  9316. this.drawInstance(inst, layer_ctx);
  9317. last_inst = inst;
  9318. }
  9319. if (this.useRenderCells)
  9320. this.last_render_list = instances_to_draw;
  9321. layer_ctx.restore();
  9322. if (this.render_offscreen)
  9323. {
  9324. ctx.globalCompositeOperation = this.compositeOp;
  9325. ctx.globalAlpha = this.opacity;
  9326. ctx.drawImage(layer_canvas, 0, 0);
  9327. }
  9328. };
  9329. Layer.prototype.drawInstance = function(inst, layer_ctx)
  9330. {
  9331. if (!inst.visible || inst.width === 0 || inst.height === 0)
  9332. return;
  9333. inst.update_bbox();
  9334. var bbox = inst.bbox;
  9335. if (bbox.right < this.viewLeft || bbox.bottom < this.viewTop || bbox.left > this.viewRight || bbox.top > this.viewBottom)
  9336. return;
  9337. layer_ctx.globalCompositeOperation = inst.compositeOp;
  9338. inst.draw(layer_ctx);
  9339. };
  9340. Layer.prototype.updateViewport = function (ctx)
  9341. {
  9342. this.disableAngle = true;
  9343. var px = this.canvasToLayer(0, 0, true, true);
  9344. var py = this.canvasToLayer(0, 0, false, true);
  9345. this.disableAngle = false;
  9346. if (this.runtime.pixel_rounding)
  9347. {
  9348. px = Math.round(px);
  9349. py = Math.round(py);
  9350. }
  9351. this.rotateViewport(px, py, ctx);
  9352. };
  9353. Layer.prototype.rotateViewport = function (px, py, ctx)
  9354. {
  9355. var myscale = this.getScale();
  9356. this.viewLeft = px;
  9357. this.viewTop = py;
  9358. this.viewRight = px + (this.runtime.draw_width * (1 / myscale));
  9359. this.viewBottom = py + (this.runtime.draw_height * (1 / myscale));
  9360. var temp;
  9361. if (this.viewLeft > this.viewRight)
  9362. {
  9363. temp = this.viewLeft;
  9364. this.viewLeft = this.viewRight;
  9365. this.viewRight = temp;
  9366. }
  9367. if (this.viewTop > this.viewBottom)
  9368. {
  9369. temp = this.viewTop;
  9370. this.viewTop = this.viewBottom;
  9371. this.viewBottom = temp;
  9372. }
  9373. var myAngle = this.getAngle();
  9374. if (myAngle !== 0)
  9375. {
  9376. if (ctx)
  9377. {
  9378. ctx.translate(this.runtime.draw_width / 2, this.runtime.draw_height / 2);
  9379. ctx.rotate(-myAngle);
  9380. ctx.translate(this.runtime.draw_width / -2, this.runtime.draw_height / -2);
  9381. }
  9382. this.tmprect.set(this.viewLeft, this.viewTop, this.viewRight, this.viewBottom);
  9383. this.tmprect.offset((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2);
  9384. this.tmpquad.set_from_rotated_rect(this.tmprect, myAngle);
  9385. this.tmpquad.bounding_box(this.tmprect);
  9386. this.tmprect.offset((this.viewLeft + this.viewRight) / 2, (this.viewTop + this.viewBottom) / 2);
  9387. this.viewLeft = this.tmprect.left;
  9388. this.viewTop = this.tmprect.top;
  9389. this.viewRight = this.tmprect.right;
  9390. this.viewBottom = this.tmprect.bottom;
  9391. }
  9392. }
  9393. Layer.prototype.drawGL_earlyZPass = function (glw)
  9394. {
  9395. var windowWidth = this.runtime.draw_width;
  9396. var windowHeight = this.runtime.draw_height;
  9397. var shaderindex = 0;
  9398. var etindex = 0;
  9399. this.render_offscreen = this.forceOwnTexture;
  9400. if (this.render_offscreen)
  9401. {
  9402. if (!this.runtime.layer_tex)
  9403. {
  9404. this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  9405. }
  9406. if (this.runtime.layer_tex.c2width !== this.runtime.draw_width || this.runtime.layer_tex.c2height !== this.runtime.draw_height)
  9407. {
  9408. glw.deleteTexture(this.runtime.layer_tex);
  9409. this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  9410. }
  9411. glw.setRenderingToTexture(this.runtime.layer_tex);
  9412. }
  9413. this.disableAngle = true;
  9414. var px = this.canvasToLayer(0, 0, true, true);
  9415. var py = this.canvasToLayer(0, 0, false, true);
  9416. this.disableAngle = false;
  9417. if (this.runtime.pixel_rounding)
  9418. {
  9419. px = Math.round(px);
  9420. py = Math.round(py);
  9421. }
  9422. this.rotateViewport(px, py, null);
  9423. var myscale = this.getScale();
  9424. glw.resetModelView();
  9425. glw.scale(myscale, myscale);
  9426. glw.rotateZ(-this.getAngle());
  9427. glw.translate((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2);
  9428. glw.updateModelView();
  9429. var instances_to_draw;
  9430. if (this.useRenderCells)
  9431. {
  9432. this.cur_render_cells.left = this.render_grid.XToCell(this.viewLeft);
  9433. this.cur_render_cells.top = this.render_grid.YToCell(this.viewTop);
  9434. this.cur_render_cells.right = this.render_grid.XToCell(this.viewRight);
  9435. this.cur_render_cells.bottom = this.render_grid.YToCell(this.viewBottom);
  9436. if (this.render_list_stale || !this.cur_render_cells.equals(this.last_render_cells))
  9437. {
  9438. free_arr(this.last_render_list);
  9439. instances_to_draw = this.getRenderCellInstancesToDraw();
  9440. this.render_list_stale = false;
  9441. this.last_render_cells.copy(this.cur_render_cells);
  9442. }
  9443. else
  9444. instances_to_draw = this.last_render_list;
  9445. }
  9446. else
  9447. instances_to_draw = this.instances;
  9448. var i, inst, last_inst = null;
  9449. for (i = instances_to_draw.length - 1; i >= 0; --i)
  9450. {
  9451. inst = instances_to_draw[i];
  9452. if (inst === last_inst)
  9453. continue;
  9454. this.drawInstanceGL_earlyZPass(instances_to_draw[i], glw);
  9455. last_inst = inst;
  9456. }
  9457. if (this.useRenderCells)
  9458. this.last_render_list = instances_to_draw;
  9459. if (!this.transparent)
  9460. {
  9461. this.clear_earlyz_index = this.runtime.earlyz_index++;
  9462. glw.setEarlyZIndex(this.clear_earlyz_index);
  9463. glw.setColorFillMode(1, 1, 1, 1);
  9464. glw.fullscreenQuad(); // fill remaining space in depth buffer with current Z value
  9465. glw.restoreEarlyZMode();
  9466. }
  9467. };
  9468. Layer.prototype.drawGL = function (glw)
  9469. {
  9470. var windowWidth = this.runtime.draw_width;
  9471. var windowHeight = this.runtime.draw_height;
  9472. var shaderindex = 0;
  9473. var etindex = 0;
  9474. this.render_offscreen = (this.forceOwnTexture || this.opacity !== 1.0 || this.active_effect_types.length > 0 || this.blend_mode !== 0);
  9475. if (this.render_offscreen)
  9476. {
  9477. if (!this.runtime.layer_tex)
  9478. {
  9479. this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  9480. }
  9481. if (this.runtime.layer_tex.c2width !== this.runtime.draw_width || this.runtime.layer_tex.c2height !== this.runtime.draw_height)
  9482. {
  9483. glw.deleteTexture(this.runtime.layer_tex);
  9484. this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling);
  9485. }
  9486. glw.setRenderingToTexture(this.runtime.layer_tex);
  9487. if (this.transparent)
  9488. glw.clear(0, 0, 0, 0);
  9489. }
  9490. if (!this.transparent)
  9491. {
  9492. if (this.runtime.enableFrontToBack)
  9493. {
  9494. glw.setEarlyZIndex(this.clear_earlyz_index);
  9495. glw.setColorFillMode(this.background_color[0] / 255, this.background_color[1] / 255, this.background_color[2] / 255, 1);
  9496. glw.fullscreenQuad();
  9497. glw.setTextureFillMode();
  9498. }
  9499. else
  9500. {
  9501. glw.clear(this.background_color[0] / 255, this.background_color[1] / 255, this.background_color[2] / 255, 1);
  9502. }
  9503. }
  9504. this.disableAngle = true;
  9505. var px = this.canvasToLayer(0, 0, true, true);
  9506. var py = this.canvasToLayer(0, 0, false, true);
  9507. this.disableAngle = false;
  9508. if (this.runtime.pixel_rounding)
  9509. {
  9510. px = Math.round(px);
  9511. py = Math.round(py);
  9512. }
  9513. this.rotateViewport(px, py, null);
  9514. var myscale = this.getScale();
  9515. glw.resetModelView();
  9516. glw.scale(myscale, myscale);
  9517. glw.rotateZ(-this.getAngle());
  9518. glw.translate((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2);
  9519. glw.updateModelView();
  9520. var instances_to_draw;
  9521. if (this.useRenderCells)
  9522. {
  9523. this.cur_render_cells.left = this.render_grid.XToCell(this.viewLeft);
  9524. this.cur_render_cells.top = this.render_grid.YToCell(this.viewTop);
  9525. this.cur_render_cells.right = this.render_grid.XToCell(this.viewRight);
  9526. this.cur_render_cells.bottom = this.render_grid.YToCell(this.viewBottom);
  9527. if (this.render_list_stale || !this.cur_render_cells.equals(this.last_render_cells))
  9528. {
  9529. free_arr(this.last_render_list);
  9530. instances_to_draw = this.getRenderCellInstancesToDraw();
  9531. this.render_list_stale = false;
  9532. this.last_render_cells.copy(this.cur_render_cells);
  9533. }
  9534. else
  9535. instances_to_draw = this.last_render_list;
  9536. }
  9537. else
  9538. instances_to_draw = this.instances;
  9539. var i, len, inst, last_inst = null;
  9540. for (i = 0, len = instances_to_draw.length; i < len; ++i)
  9541. {
  9542. inst = instances_to_draw[i];
  9543. if (inst === last_inst)
  9544. continue;
  9545. this.drawInstanceGL(instances_to_draw[i], glw);
  9546. last_inst = inst;
  9547. }
  9548. if (this.useRenderCells)
  9549. this.last_render_list = instances_to_draw;
  9550. if (this.render_offscreen)
  9551. {
  9552. shaderindex = this.active_effect_types.length ? this.active_effect_types[0].shaderindex : 0;
  9553. etindex = this.active_effect_types.length ? this.active_effect_types[0].index : 0;
  9554. if (this.active_effect_types.length === 0 || (this.active_effect_types.length === 1 &&
  9555. !glw.programUsesCrossSampling(shaderindex) && this.opacity === 1))
  9556. {
  9557. if (this.active_effect_types.length === 1)
  9558. {
  9559. glw.switchProgram(shaderindex);
  9560. glw.setProgramParameters(this.layout.getRenderTarget(), // backTex
  9561. 1.0 / this.runtime.draw_width, // pixelWidth
  9562. 1.0 / this.runtime.draw_height, // pixelHeight
  9563. 0.0, 0.0, // destStart
  9564. 1.0, 1.0, // destEnd
  9565. myscale, // layerScale
  9566. this.getAngle(),
  9567. this.viewLeft, this.viewTop,
  9568. (this.viewLeft + this.viewRight) / 2, (this.viewTop + this.viewBottom) / 2,
  9569. this.runtime.kahanTime.sum,
  9570. this.effect_params[etindex]); // fx parameters
  9571. if (glw.programIsAnimated(shaderindex))
  9572. this.runtime.redraw = true;
  9573. }
  9574. else
  9575. glw.switchProgram(0);
  9576. glw.setRenderingToTexture(this.layout.getRenderTarget());
  9577. glw.setOpacity(this.opacity);
  9578. glw.setTexture(this.runtime.layer_tex);
  9579. glw.setBlend(this.srcBlend, this.destBlend);
  9580. glw.resetModelView();
  9581. glw.updateModelView();
  9582. var halfw = this.runtime.draw_width / 2;
  9583. var halfh = this.runtime.draw_height / 2;
  9584. glw.quad(-halfw, halfh, halfw, halfh, halfw, -halfh, -halfw, -halfh);
  9585. glw.setTexture(null);
  9586. }
  9587. else
  9588. {
  9589. this.layout.renderEffectChain(glw, this, null, this.layout.getRenderTarget());
  9590. }
  9591. }
  9592. };
  9593. Layer.prototype.drawInstanceGL = function (inst, glw)
  9594. {
  9595. ;
  9596. if (!inst.visible || inst.width === 0 || inst.height === 0)
  9597. return;
  9598. inst.update_bbox();
  9599. var bbox = inst.bbox;
  9600. if (bbox.right < this.viewLeft || bbox.bottom < this.viewTop || bbox.left > this.viewRight || bbox.top > this.viewBottom)
  9601. return;
  9602. glw.setEarlyZIndex(inst.earlyz_index);
  9603. if (inst.uses_shaders)
  9604. {
  9605. this.drawInstanceWithShadersGL(inst, glw);
  9606. }
  9607. else
  9608. {
  9609. glw.switchProgram(0); // un-set any previously set shader
  9610. glw.setBlend(inst.srcBlend, inst.destBlend);
  9611. inst.drawGL(glw);
  9612. }
  9613. };
  9614. Layer.prototype.drawInstanceGL_earlyZPass = function (inst, glw)
  9615. {
  9616. ;
  9617. if (!inst.visible || inst.width === 0 || inst.height === 0)
  9618. return;
  9619. inst.update_bbox();
  9620. var bbox = inst.bbox;
  9621. if (bbox.right < this.viewLeft || bbox.bottom < this.viewTop || bbox.left > this.viewRight || bbox.top > this.viewBottom)
  9622. return;
  9623. inst.earlyz_index = this.runtime.earlyz_index++;
  9624. if (inst.blend_mode !== 0 || inst.opacity !== 1 || !inst.shaders_preserve_opaqueness || !inst.drawGL_earlyZPass)
  9625. return;
  9626. glw.setEarlyZIndex(inst.earlyz_index);
  9627. inst.drawGL_earlyZPass(glw);
  9628. };
  9629. Layer.prototype.drawInstanceWithShadersGL = function (inst, glw)
  9630. {
  9631. var shaderindex = inst.active_effect_types[0].shaderindex;
  9632. var etindex = inst.active_effect_types[0].index;
  9633. var myscale = this.getScale();
  9634. if (inst.active_effect_types.length === 1 && !glw.programUsesCrossSampling(shaderindex) &&
  9635. !glw.programExtendsBox(shaderindex) && ((!inst.angle && !inst.layer.getAngle()) || !glw.programUsesDest(shaderindex)) &&
  9636. inst.opacity === 1 && !inst.type.plugin.must_predraw)
  9637. {
  9638. glw.switchProgram(shaderindex);
  9639. glw.setBlend(inst.srcBlend, inst.destBlend);
  9640. if (glw.programIsAnimated(shaderindex))
  9641. this.runtime.redraw = true;
  9642. var destStartX = 0, destStartY = 0, destEndX = 0, destEndY = 0;
  9643. if (glw.programUsesDest(shaderindex))
  9644. {
  9645. var bbox = inst.bbox;
  9646. var screenleft = this.layerToCanvas(bbox.left, bbox.top, true, true);
  9647. var screentop = this.layerToCanvas(bbox.left, bbox.top, false, true);
  9648. var screenright = this.layerToCanvas(bbox.right, bbox.bottom, true, true);
  9649. var screenbottom = this.layerToCanvas(bbox.right, bbox.bottom, false, true);
  9650. destStartX = screenleft / windowWidth;
  9651. destStartY = 1 - screentop / windowHeight;
  9652. destEndX = screenright / windowWidth;
  9653. destEndY = 1 - screenbottom / windowHeight;
  9654. }
  9655. var pixelWidth;
  9656. var pixelHeight;
  9657. if (inst.curFrame && inst.curFrame.texture_img)
  9658. {
  9659. var img = inst.curFrame.texture_img;
  9660. pixelWidth = 1.0 / img.width;
  9661. pixelHeight = 1.0 / img.height;
  9662. }
  9663. else
  9664. {
  9665. pixelWidth = 1.0 / inst.width;
  9666. pixelHeight = 1.0 / inst.height;
  9667. }
  9668. glw.setProgramParameters(this.render_offscreen ? this.runtime.layer_tex : this.layout.getRenderTarget(), // backTex
  9669. pixelWidth,
  9670. pixelHeight,
  9671. destStartX, destStartY,
  9672. destEndX, destEndY,
  9673. myscale,
  9674. this.getAngle(),
  9675. this.viewLeft, this.viewTop,
  9676. (this.viewLeft + this.viewRight) / 2, (this.viewTop + this.viewBottom) / 2,
  9677. this.runtime.kahanTime.sum,
  9678. inst.effect_params[etindex]);
  9679. inst.drawGL(glw);
  9680. }
  9681. else
  9682. {
  9683. this.layout.renderEffectChain(glw, this, inst, this.render_offscreen ? this.runtime.layer_tex : this.layout.getRenderTarget());
  9684. glw.resetModelView();
  9685. glw.scale(myscale, myscale);
  9686. glw.rotateZ(-this.getAngle());
  9687. glw.translate((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2);
  9688. glw.updateModelView();
  9689. }
  9690. };
  9691. Layer.prototype.canvasToLayer = function (ptx, pty, getx, using_draw_area)
  9692. {
  9693. var multiplier = this.runtime.devicePixelRatio;
  9694. if (this.runtime.isRetina)
  9695. {
  9696. ptx *= multiplier;
  9697. pty *= multiplier;
  9698. }
  9699. var ox = this.runtime.parallax_x_origin;
  9700. var oy = this.runtime.parallax_y_origin;
  9701. var par_x = ((this.layout.scrollX - ox) * this.parallaxX) + ox;
  9702. var par_y = ((this.layout.scrollY - oy) * this.parallaxY) + oy;
  9703. var x = par_x;
  9704. var y = par_y;
  9705. var invScale = 1 / this.getScale(!using_draw_area);
  9706. if (using_draw_area)
  9707. {
  9708. x -= (this.runtime.draw_width * invScale) / 2;
  9709. y -= (this.runtime.draw_height * invScale) / 2;
  9710. }
  9711. else
  9712. {
  9713. x -= (this.runtime.width * invScale) / 2;
  9714. y -= (this.runtime.height * invScale) / 2;
  9715. }
  9716. x += ptx * invScale;
  9717. y += pty * invScale;
  9718. var a = this.getAngle();
  9719. if (a !== 0)
  9720. {
  9721. x -= par_x;
  9722. y -= par_y;
  9723. var cosa = Math.cos(a);
  9724. var sina = Math.sin(a);
  9725. var x_temp = (x * cosa) - (y * sina);
  9726. y = (y * cosa) + (x * sina);
  9727. x = x_temp;
  9728. x += par_x;
  9729. y += par_y;
  9730. }
  9731. return getx ? x : y;
  9732. };
  9733. Layer.prototype.layerToCanvas = function (ptx, pty, getx, using_draw_area)
  9734. {
  9735. var ox = this.runtime.parallax_x_origin;
  9736. var oy = this.runtime.parallax_y_origin;
  9737. var par_x = ((this.layout.scrollX - ox) * this.parallaxX) + ox;
  9738. var par_y = ((this.layout.scrollY - oy) * this.parallaxY) + oy;
  9739. var x = par_x;
  9740. var y = par_y;
  9741. var a = this.getAngle();
  9742. if (a !== 0)
  9743. {
  9744. ptx -= par_x;
  9745. pty -= par_y;
  9746. var cosa = Math.cos(-a);
  9747. var sina = Math.sin(-a);
  9748. var x_temp = (ptx * cosa) - (pty * sina);
  9749. pty = (pty * cosa) + (ptx * sina);
  9750. ptx = x_temp;
  9751. ptx += par_x;
  9752. pty += par_y;
  9753. }
  9754. var invScale = 1 / this.getScale(!using_draw_area);
  9755. if (using_draw_area)
  9756. {
  9757. x -= (this.runtime.draw_width * invScale) / 2;
  9758. y -= (this.runtime.draw_height * invScale) / 2;
  9759. }
  9760. else
  9761. {
  9762. x -= (this.runtime.width * invScale) / 2;
  9763. y -= (this.runtime.height * invScale) / 2;
  9764. }
  9765. x = (ptx - x) / invScale;
  9766. y = (pty - y) / invScale;
  9767. var multiplier = this.runtime.devicePixelRatio;
  9768. if (this.runtime.isRetina && !using_draw_area)
  9769. {
  9770. x /= multiplier;
  9771. y /= multiplier;
  9772. }
  9773. return getx ? x : y;
  9774. };
  9775. Layer.prototype.rotatePt = function (x_, y_, getx)
  9776. {
  9777. if (this.getAngle() === 0)
  9778. return getx ? x_ : y_;
  9779. var nx = this.layerToCanvas(x_, y_, true);
  9780. var ny = this.layerToCanvas(x_, y_, false);
  9781. this.disableAngle = true;
  9782. var px = this.canvasToLayer(nx, ny, true);
  9783. var py = this.canvasToLayer(nx, ny, true);
  9784. this.disableAngle = false;
  9785. return getx ? px : py;
  9786. };
  9787. Layer.prototype.saveToJSON = function ()
  9788. {
  9789. var i, len, et;
  9790. var o = {
  9791. "s": this.scale,
  9792. "a": this.angle,
  9793. "vl": this.viewLeft,
  9794. "vt": this.viewTop,
  9795. "vr": this.viewRight,
  9796. "vb": this.viewBottom,
  9797. "v": this.visible,
  9798. "bc": this.background_color,
  9799. "t": this.transparent,
  9800. "px": this.parallaxX,
  9801. "py": this.parallaxY,
  9802. "o": this.opacity,
  9803. "zr": this.zoomRate,
  9804. "fx": [],
  9805. "cg": this.created_globals, // added r197; list of global UIDs already created
  9806. "instances": []
  9807. };
  9808. for (i = 0, len = this.effect_types.length; i < len; i++)
  9809. {
  9810. et = this.effect_types[i];
  9811. o["fx"].push({"name": et.name, "active": et.active, "params": this.effect_params[et.index] });
  9812. }
  9813. return o;
  9814. };
  9815. Layer.prototype.loadFromJSON = function (o)
  9816. {
  9817. var i, j, len, p, inst, fx;
  9818. this.scale = o["s"];
  9819. this.angle = o["a"];
  9820. this.viewLeft = o["vl"];
  9821. this.viewTop = o["vt"];
  9822. this.viewRight = o["vr"];
  9823. this.viewBottom = o["vb"];
  9824. this.visible = o["v"];
  9825. this.background_color = o["bc"];
  9826. this.transparent = o["t"];
  9827. this.parallaxX = o["px"];
  9828. this.parallaxY = o["py"];
  9829. this.opacity = o["o"];
  9830. this.zoomRate = o["zr"];
  9831. this.created_globals = o["cg"] || []; // added r197
  9832. cr.shallowAssignArray(this.initial_instances, this.startup_initial_instances);
  9833. var temp_set = new cr.ObjectSet();
  9834. for (i = 0, len = this.created_globals.length; i < len; ++i)
  9835. temp_set.add(this.created_globals[i]);
  9836. for (i = 0, j = 0, len = this.initial_instances.length; i < len; ++i)
  9837. {
  9838. if (!temp_set.contains(this.initial_instances[i][2])) // UID in element 2
  9839. {
  9840. this.initial_instances[j] = this.initial_instances[i];
  9841. ++j;
  9842. }
  9843. }
  9844. cr.truncateArray(this.initial_instances, j);
  9845. var ofx = o["fx"];
  9846. for (i = 0, len = ofx.length; i < len; i++)
  9847. {
  9848. fx = this.getEffectByName(ofx[i]["name"]);
  9849. if (!fx)
  9850. continue; // must've gone missing
  9851. fx.active = ofx[i]["active"];
  9852. this.effect_params[fx.index] = ofx[i]["params"];
  9853. }
  9854. this.updateActiveEffects();
  9855. this.instances.sort(sort_by_zindex);
  9856. this.zindices_stale = true;
  9857. };
  9858. cr.layer = Layer;
  9859. }());
  9860. ;
  9861. (function()
  9862. {
  9863. var allUniqueSolModifiers = [];
  9864. function testSolsMatch(arr1, arr2)
  9865. {
  9866. var i, len = arr1.length;
  9867. switch (len) {
  9868. case 0:
  9869. return true;
  9870. case 1:
  9871. return arr1[0] === arr2[0];
  9872. case 2:
  9873. return arr1[0] === arr2[0] && arr1[1] === arr2[1];
  9874. default:
  9875. for (i = 0; i < len; i++)
  9876. {
  9877. if (arr1[i] !== arr2[i])
  9878. return false;
  9879. }
  9880. return true;
  9881. }
  9882. };
  9883. function solArraySorter(t1, t2)
  9884. {
  9885. return t1.index - t2.index;
  9886. };
  9887. function findMatchingSolModifier(arr)
  9888. {
  9889. var i, len, u, temp, subarr;
  9890. if (arr.length === 2)
  9891. {
  9892. if (arr[0].index > arr[1].index)
  9893. {
  9894. temp = arr[0];
  9895. arr[0] = arr[1];
  9896. arr[1] = temp;
  9897. }
  9898. }
  9899. else if (arr.length > 2)
  9900. arr.sort(solArraySorter); // so testSolsMatch compares in same order
  9901. if (arr.length >= allUniqueSolModifiers.length)
  9902. allUniqueSolModifiers.length = arr.length + 1;
  9903. if (!allUniqueSolModifiers[arr.length])
  9904. allUniqueSolModifiers[arr.length] = [];
  9905. subarr = allUniqueSolModifiers[arr.length];
  9906. for (i = 0, len = subarr.length; i < len; i++)
  9907. {
  9908. u = subarr[i];
  9909. if (testSolsMatch(arr, u))
  9910. return u;
  9911. }
  9912. subarr.push(arr);
  9913. return arr;
  9914. };
  9915. function EventSheet(runtime, m)
  9916. {
  9917. this.runtime = runtime;
  9918. this.triggers = {};
  9919. this.fasttriggers = {};
  9920. this.hasRun = false;
  9921. this.includes = new cr.ObjectSet(); // all event sheets included by this sheet, at first-level indirection only
  9922. this.deep_includes = []; // all includes from this sheet recursively, in trigger order
  9923. this.already_included_sheets = []; // used while building deep_includes
  9924. this.name = m[0];
  9925. var em = m[1]; // events model
  9926. this.events = []; // triggers won't make it to this array
  9927. var i, len;
  9928. for (i = 0, len = em.length; i < len; i++)
  9929. this.init_event(em[i], null, this.events);
  9930. };
  9931. EventSheet.prototype.toString = function ()
  9932. {
  9933. return this.name;
  9934. };
  9935. EventSheet.prototype.init_event = function (m, parent, nontriggers)
  9936. {
  9937. switch (m[0]) {
  9938. case 0: // event block
  9939. {
  9940. var block = new cr.eventblock(this, parent, m);
  9941. cr.seal(block);
  9942. if (block.orblock)
  9943. {
  9944. nontriggers.push(block);
  9945. var i, len;
  9946. for (i = 0, len = block.conditions.length; i < len; i++)
  9947. {
  9948. if (block.conditions[i].trigger)
  9949. this.init_trigger(block, i);
  9950. }
  9951. }
  9952. else
  9953. {
  9954. if (block.is_trigger())
  9955. this.init_trigger(block, 0);
  9956. else
  9957. nontriggers.push(block);
  9958. }
  9959. break;
  9960. }
  9961. case 1: // variable
  9962. {
  9963. var v = new cr.eventvariable(this, parent, m);
  9964. cr.seal(v);
  9965. nontriggers.push(v);
  9966. break;
  9967. }
  9968. case 2: // include
  9969. {
  9970. var inc = new cr.eventinclude(this, parent, m);
  9971. cr.seal(inc);
  9972. nontriggers.push(inc);
  9973. break;
  9974. }
  9975. default:
  9976. ;
  9977. }
  9978. };
  9979. EventSheet.prototype.postInit = function ()
  9980. {
  9981. var i, len;
  9982. for (i = 0, len = this.events.length; i < len; i++)
  9983. {
  9984. this.events[i].postInit(i < len - 1 && this.events[i + 1].is_else_block);
  9985. }
  9986. };
  9987. EventSheet.prototype.updateDeepIncludes = function ()
  9988. {
  9989. cr.clearArray(this.deep_includes);
  9990. cr.clearArray(this.already_included_sheets);
  9991. this.addDeepIncludes(this);
  9992. cr.clearArray(this.already_included_sheets);
  9993. };
  9994. EventSheet.prototype.addDeepIncludes = function (root_sheet)
  9995. {
  9996. var i, len, inc, sheet;
  9997. var deep_includes = root_sheet.deep_includes;
  9998. var already_included_sheets = root_sheet.already_included_sheets;
  9999. var arr = this.includes.valuesRef();
  10000. for (i = 0, len = arr.length; i < len; ++i)
  10001. {
  10002. inc = arr[i];
  10003. sheet = inc.include_sheet;
  10004. if (!inc.isActive() || root_sheet === sheet || already_included_sheets.indexOf(sheet) > -1)
  10005. continue;
  10006. already_included_sheets.push(sheet);
  10007. sheet.addDeepIncludes(root_sheet);
  10008. deep_includes.push(sheet);
  10009. }
  10010. };
  10011. EventSheet.prototype.run = function (from_include)
  10012. {
  10013. if (!this.runtime.resuming_breakpoint)
  10014. {
  10015. this.hasRun = true;
  10016. if (!from_include)
  10017. this.runtime.isRunningEvents = true;
  10018. }
  10019. var i, len;
  10020. for (i = 0, len = this.events.length; i < len; i++)
  10021. {
  10022. var ev = this.events[i];
  10023. ev.run();
  10024. this.runtime.clearSol(ev.solModifiers);
  10025. if (this.runtime.hasPendingInstances)
  10026. this.runtime.ClearDeathRow();
  10027. }
  10028. if (!from_include)
  10029. this.runtime.isRunningEvents = false;
  10030. };
  10031. function isPerformanceSensitiveTrigger(method)
  10032. {
  10033. if (cr.plugins_.Sprite && method === cr.plugins_.Sprite.prototype.cnds.OnFrameChanged)
  10034. {
  10035. return true;
  10036. }
  10037. return false;
  10038. };
  10039. EventSheet.prototype.init_trigger = function (trig, index)
  10040. {
  10041. if (!trig.orblock)
  10042. this.runtime.triggers_to_postinit.push(trig); // needs to be postInit'd later
  10043. var i, len;
  10044. var cnd = trig.conditions[index];
  10045. var type_name;
  10046. if (cnd.type)
  10047. type_name = cnd.type.name;
  10048. else
  10049. type_name = "system";
  10050. var fasttrigger = cnd.fasttrigger;
  10051. var triggers = (fasttrigger ? this.fasttriggers : this.triggers);
  10052. if (!triggers[type_name])
  10053. triggers[type_name] = [];
  10054. var obj_entry = triggers[type_name];
  10055. var method = cnd.func;
  10056. if (fasttrigger)
  10057. {
  10058. if (!cnd.parameters.length) // no parameters
  10059. return;
  10060. var firstparam = cnd.parameters[0];
  10061. if (firstparam.type !== 1 || // not a string param
  10062. firstparam.expression.type !== 2) // not a string literal node
  10063. {
  10064. return;
  10065. }
  10066. var fastevs;
  10067. var firstvalue = firstparam.expression.value.toLowerCase();
  10068. var i, len;
  10069. for (i = 0, len = obj_entry.length; i < len; i++)
  10070. {
  10071. if (obj_entry[i].method == method)
  10072. {
  10073. fastevs = obj_entry[i].evs;
  10074. if (!fastevs[firstvalue])
  10075. fastevs[firstvalue] = [[trig, index]];
  10076. else
  10077. fastevs[firstvalue].push([trig, index]);
  10078. return;
  10079. }
  10080. }
  10081. fastevs = {};
  10082. fastevs[firstvalue] = [[trig, index]];
  10083. obj_entry.push({ method: method, evs: fastevs });
  10084. }
  10085. else
  10086. {
  10087. for (i = 0, len = obj_entry.length; i < len; i++)
  10088. {
  10089. if (obj_entry[i].method == method)
  10090. {
  10091. obj_entry[i].evs.push([trig, index]);
  10092. return;
  10093. }
  10094. }
  10095. if (isPerformanceSensitiveTrigger(method))
  10096. obj_entry.unshift({ method: method, evs: [[trig, index]]});
  10097. else
  10098. obj_entry.push({ method: method, evs: [[trig, index]]});
  10099. }
  10100. };
  10101. cr.eventsheet = EventSheet;
  10102. function Selection(type)
  10103. {
  10104. this.type = type;
  10105. this.instances = []; // subset of picked instances
  10106. this.else_instances = []; // subset of unpicked instances
  10107. this.select_all = true;
  10108. };
  10109. Selection.prototype.hasObjects = function ()
  10110. {
  10111. if (this.select_all)
  10112. return this.type.instances.length;
  10113. else
  10114. return this.instances.length;
  10115. };
  10116. Selection.prototype.getObjects = function ()
  10117. {
  10118. if (this.select_all)
  10119. return this.type.instances;
  10120. else
  10121. return this.instances;
  10122. };
  10123. /*
  10124. Selection.prototype.ensure_picked = function (inst, skip_siblings)
  10125. {
  10126. var i, len;
  10127. var orblock = inst.runtime.getCurrentEventStack().current_event.orblock;
  10128. if (this.select_all)
  10129. {
  10130. this.select_all = false;
  10131. if (orblock)
  10132. {
  10133. cr.shallowAssignArray(this.else_instances, inst.type.instances);
  10134. cr.arrayFindRemove(this.else_instances, inst);
  10135. }
  10136. this.instances.length = 1;
  10137. this.instances[0] = inst;
  10138. }
  10139. else
  10140. {
  10141. if (orblock)
  10142. {
  10143. i = this.else_instances.indexOf(inst);
  10144. if (i !== -1)
  10145. {
  10146. this.instances.push(this.else_instances[i]);
  10147. this.else_instances.splice(i, 1);
  10148. }
  10149. }
  10150. else
  10151. {
  10152. if (this.instances.indexOf(inst) === -1)
  10153. this.instances.push(inst);
  10154. }
  10155. }
  10156. if (!skip_siblings)
  10157. {
  10158. }
  10159. };
  10160. */
  10161. Selection.prototype.pick_one = function (inst)
  10162. {
  10163. if (!inst)
  10164. return;
  10165. if (inst.runtime.getCurrentEventStack().current_event.orblock)
  10166. {
  10167. if (this.select_all)
  10168. {
  10169. cr.clearArray(this.instances);
  10170. cr.shallowAssignArray(this.else_instances, inst.type.instances);
  10171. this.select_all = false;
  10172. }
  10173. var i = this.else_instances.indexOf(inst);
  10174. if (i !== -1)
  10175. {
  10176. this.instances.push(this.else_instances[i]);
  10177. this.else_instances.splice(i, 1);
  10178. }
  10179. }
  10180. else
  10181. {
  10182. this.select_all = false;
  10183. cr.clearArray(this.instances);
  10184. this.instances[0] = inst;
  10185. }
  10186. };
  10187. cr.selection = Selection;
  10188. function EventBlock(sheet, parent, m)
  10189. {
  10190. this.sheet = sheet;
  10191. this.parent = parent;
  10192. this.runtime = sheet.runtime;
  10193. this.solModifiers = [];
  10194. this.solModifiersIncludingParents = [];
  10195. this.solWriterAfterCnds = false; // block does not change SOL after running its conditions
  10196. this.group = false; // is group of events
  10197. this.initially_activated = false; // if a group, is active on startup
  10198. this.toplevelevent = false; // is an event block parented only by a top-level group
  10199. this.toplevelgroup = false; // is parented only by other groups or is top-level (i.e. not in a subevent)
  10200. this.has_else_block = false; // is followed by else
  10201. ;
  10202. this.conditions = [];
  10203. this.actions = [];
  10204. this.subevents = [];
  10205. this.group_name = "";
  10206. this.group = false;
  10207. this.initially_activated = false;
  10208. this.group_active = false;
  10209. this.contained_includes = null;
  10210. if (m[1])
  10211. {
  10212. this.group_name = m[1][1].toLowerCase();
  10213. this.group = true;
  10214. this.initially_activated = !!m[1][0];
  10215. this.contained_includes = [];
  10216. this.group_active = this.initially_activated;
  10217. this.runtime.allGroups.push(this);
  10218. this.runtime.groups_by_name[this.group_name] = this;
  10219. }
  10220. this.orblock = m[2];
  10221. this.sid = m[4];
  10222. if (!this.group)
  10223. this.runtime.blocksBySid[this.sid.toString()] = this;
  10224. var i, len;
  10225. var cm = m[5];
  10226. for (i = 0, len = cm.length; i < len; i++)
  10227. {
  10228. var cnd = new cr.condition(this, cm[i]);
  10229. cnd.index = i;
  10230. cr.seal(cnd);
  10231. this.conditions.push(cnd);
  10232. /*
  10233. if (cnd.is_logical())
  10234. this.is_logical = true;
  10235. if (cnd.type && !cnd.type.plugin.singleglobal && this.cndReferences.indexOf(cnd.type) === -1)
  10236. this.cndReferences.push(cnd.type);
  10237. */
  10238. this.addSolModifier(cnd.type);
  10239. }
  10240. var am = m[6];
  10241. for (i = 0, len = am.length; i < len; i++)
  10242. {
  10243. var act = new cr.action(this, am[i]);
  10244. act.index = i;
  10245. cr.seal(act);
  10246. this.actions.push(act);
  10247. }
  10248. if (m.length === 8)
  10249. {
  10250. var em = m[7];
  10251. for (i = 0, len = em.length; i < len; i++)
  10252. this.sheet.init_event(em[i], this, this.subevents);
  10253. }
  10254. this.is_else_block = false;
  10255. if (this.conditions.length)
  10256. {
  10257. this.is_else_block = (this.conditions[0].type == null && this.conditions[0].func == cr.system_object.prototype.cnds.Else);
  10258. }
  10259. };
  10260. window["_c2hh_"] = "E8D4EF6B20D81CAD7C3B3932B134BCD4B42AB538";
  10261. EventBlock.prototype.postInit = function (hasElse/*, prevBlock_*/)
  10262. {
  10263. var i, len;
  10264. var p = this.parent;
  10265. if (this.group)
  10266. {
  10267. this.toplevelgroup = true;
  10268. while (p)
  10269. {
  10270. if (!p.group)
  10271. {
  10272. this.toplevelgroup = false;
  10273. break;
  10274. }
  10275. p = p.parent;
  10276. }
  10277. }
  10278. this.toplevelevent = !this.is_trigger() && (!this.parent || (this.parent.group && this.parent.toplevelgroup));
  10279. this.has_else_block = !!hasElse;
  10280. this.solModifiersIncludingParents = this.solModifiers.slice(0);
  10281. p = this.parent;
  10282. while (p)
  10283. {
  10284. for (i = 0, len = p.solModifiers.length; i < len; i++)
  10285. this.addParentSolModifier(p.solModifiers[i]);
  10286. p = p.parent;
  10287. }
  10288. this.solModifiers = findMatchingSolModifier(this.solModifiers);
  10289. this.solModifiersIncludingParents = findMatchingSolModifier(this.solModifiersIncludingParents);
  10290. var i, len/*, s*/;
  10291. for (i = 0, len = this.conditions.length; i < len; i++)
  10292. this.conditions[i].postInit();
  10293. for (i = 0, len = this.actions.length; i < len; i++)
  10294. this.actions[i].postInit();
  10295. for (i = 0, len = this.subevents.length; i < len; i++)
  10296. {
  10297. this.subevents[i].postInit(i < len - 1 && this.subevents[i + 1].is_else_block);
  10298. }
  10299. /*
  10300. if (this.is_else_block && this.prev_block)
  10301. {
  10302. for (i = 0, len = this.prev_block.solModifiers.length; i < len; i++)
  10303. {
  10304. s = this.prev_block.solModifiers[i];
  10305. if (this.solModifiers.indexOf(s) === -1)
  10306. this.solModifiers.push(s);
  10307. }
  10308. }
  10309. */
  10310. };
  10311. EventBlock.prototype.setGroupActive = function (a)
  10312. {
  10313. if (this.group_active === !!a)
  10314. return; // same state
  10315. this.group_active = !!a;
  10316. var i, len;
  10317. for (i = 0, len = this.contained_includes.length; i < len; ++i)
  10318. {
  10319. this.contained_includes[i].updateActive();
  10320. }
  10321. if (len > 0 && this.runtime.running_layout.event_sheet)
  10322. this.runtime.running_layout.event_sheet.updateDeepIncludes();
  10323. };
  10324. function addSolModifierToList(type, arr)
  10325. {
  10326. var i, len, t;
  10327. if (!type)
  10328. return;
  10329. if (arr.indexOf(type) === -1)
  10330. arr.push(type);
  10331. if (type.is_contained)
  10332. {
  10333. for (i = 0, len = type.container.length; i < len; i++)
  10334. {
  10335. t = type.container[i];
  10336. if (type === t)
  10337. continue; // already handled
  10338. if (arr.indexOf(t) === -1)
  10339. arr.push(t);
  10340. }
  10341. }
  10342. };
  10343. EventBlock.prototype.addSolModifier = function (type)
  10344. {
  10345. addSolModifierToList(type, this.solModifiers);
  10346. };
  10347. EventBlock.prototype.addParentSolModifier = function (type)
  10348. {
  10349. addSolModifierToList(type, this.solModifiersIncludingParents);
  10350. };
  10351. EventBlock.prototype.setSolWriterAfterCnds = function ()
  10352. {
  10353. this.solWriterAfterCnds = true;
  10354. if (this.parent)
  10355. this.parent.setSolWriterAfterCnds();
  10356. };
  10357. EventBlock.prototype.is_trigger = function ()
  10358. {
  10359. if (!this.conditions.length) // no conditions
  10360. return false;
  10361. else
  10362. return this.conditions[0].trigger;
  10363. };
  10364. EventBlock.prototype.run = function ()
  10365. {
  10366. var i, len, c, any_true = false, cnd_result;
  10367. var runtime = this.runtime;
  10368. var evinfo = this.runtime.getCurrentEventStack();
  10369. evinfo.current_event = this;
  10370. var conditions = this.conditions;
  10371. if (!this.is_else_block)
  10372. evinfo.else_branch_ran = false;
  10373. if (this.orblock)
  10374. {
  10375. if (conditions.length === 0)
  10376. any_true = true; // be sure to run if empty block
  10377. evinfo.cndindex = 0
  10378. for (len = conditions.length; evinfo.cndindex < len; evinfo.cndindex++)
  10379. {
  10380. c = conditions[evinfo.cndindex];
  10381. if (c.trigger) // skip triggers when running OR block
  10382. continue;
  10383. cnd_result = c.run();
  10384. if (cnd_result) // make sure all conditions run and run if any were true
  10385. any_true = true;
  10386. }
  10387. evinfo.last_event_true = any_true;
  10388. if (any_true)
  10389. this.run_actions_and_subevents();
  10390. }
  10391. else
  10392. {
  10393. evinfo.cndindex = 0
  10394. for (len = conditions.length; evinfo.cndindex < len; evinfo.cndindex++)
  10395. {
  10396. cnd_result = conditions[evinfo.cndindex].run();
  10397. if (!cnd_result) // condition failed
  10398. {
  10399. evinfo.last_event_true = false;
  10400. if (this.toplevelevent && runtime.hasPendingInstances)
  10401. runtime.ClearDeathRow();
  10402. return; // bail out now
  10403. }
  10404. }
  10405. evinfo.last_event_true = true;
  10406. this.run_actions_and_subevents();
  10407. }
  10408. this.end_run(evinfo);
  10409. };
  10410. EventBlock.prototype.end_run = function (evinfo)
  10411. {
  10412. if (evinfo.last_event_true && this.has_else_block)
  10413. evinfo.else_branch_ran = true;
  10414. if (this.toplevelevent && this.runtime.hasPendingInstances)
  10415. this.runtime.ClearDeathRow();
  10416. };
  10417. EventBlock.prototype.run_orblocktrigger = function (index)
  10418. {
  10419. var evinfo = this.runtime.getCurrentEventStack();
  10420. evinfo.current_event = this;
  10421. if (this.conditions[index].run())
  10422. {
  10423. this.run_actions_and_subevents();
  10424. this.runtime.getCurrentEventStack().last_event_true = true;
  10425. }
  10426. };
  10427. EventBlock.prototype.run_actions_and_subevents = function ()
  10428. {
  10429. var evinfo = this.runtime.getCurrentEventStack();
  10430. var len;
  10431. for (evinfo.actindex = 0, len = this.actions.length; evinfo.actindex < len; evinfo.actindex++)
  10432. {
  10433. if (this.actions[evinfo.actindex].run())
  10434. return;
  10435. }
  10436. this.run_subevents();
  10437. };
  10438. EventBlock.prototype.resume_actions_and_subevents = function ()
  10439. {
  10440. var evinfo = this.runtime.getCurrentEventStack();
  10441. var len;
  10442. for (len = this.actions.length; evinfo.actindex < len; evinfo.actindex++)
  10443. {
  10444. if (this.actions[evinfo.actindex].run())
  10445. return;
  10446. }
  10447. this.run_subevents();
  10448. };
  10449. EventBlock.prototype.run_subevents = function ()
  10450. {
  10451. if (!this.subevents.length)
  10452. return;
  10453. var i, len, subev, pushpop/*, skipped_pop = false, pop_modifiers = null*/;
  10454. var last = this.subevents.length - 1;
  10455. this.runtime.pushEventStack(this);
  10456. if (this.solWriterAfterCnds)
  10457. {
  10458. for (i = 0, len = this.subevents.length; i < len; i++)
  10459. {
  10460. subev = this.subevents[i];
  10461. pushpop = (!this.toplevelgroup || (!this.group && i < last));
  10462. if (pushpop)
  10463. this.runtime.pushCopySol(subev.solModifiers);
  10464. subev.run();
  10465. if (pushpop)
  10466. this.runtime.popSol(subev.solModifiers);
  10467. else
  10468. this.runtime.clearSol(subev.solModifiers);
  10469. }
  10470. }
  10471. else
  10472. {
  10473. for (i = 0, len = this.subevents.length; i < len; i++)
  10474. {
  10475. this.subevents[i].run();
  10476. }
  10477. }
  10478. this.runtime.popEventStack();
  10479. };
  10480. EventBlock.prototype.run_pretrigger = function ()
  10481. {
  10482. var evinfo = this.runtime.getCurrentEventStack();
  10483. evinfo.current_event = this;
  10484. var any_true = false;
  10485. var i, len;
  10486. for (evinfo.cndindex = 0, len = this.conditions.length; evinfo.cndindex < len; evinfo.cndindex++)
  10487. {
  10488. ;
  10489. if (this.conditions[evinfo.cndindex].run())
  10490. any_true = true;
  10491. else if (!this.orblock) // condition failed (let OR blocks run all conditions anyway)
  10492. return false; // bail out
  10493. }
  10494. return this.orblock ? any_true : true;
  10495. };
  10496. EventBlock.prototype.retrigger = function ()
  10497. {
  10498. this.runtime.execcount++;
  10499. var prevcndindex = this.runtime.getCurrentEventStack().cndindex;
  10500. var len;
  10501. var evinfo = this.runtime.pushEventStack(this);
  10502. if (!this.orblock)
  10503. {
  10504. for (evinfo.cndindex = prevcndindex + 1, len = this.conditions.length; evinfo.cndindex < len; evinfo.cndindex++)
  10505. {
  10506. if (!this.conditions[evinfo.cndindex].run()) // condition failed
  10507. {
  10508. this.runtime.popEventStack(); // moving up level of recursion
  10509. return false; // bail out
  10510. }
  10511. }
  10512. }
  10513. this.run_actions_and_subevents();
  10514. this.runtime.popEventStack();
  10515. return true; // ran an iteration
  10516. };
  10517. EventBlock.prototype.isFirstConditionOfType = function (cnd)
  10518. {
  10519. var cndindex = cnd.index;
  10520. if (cndindex === 0)
  10521. return true;
  10522. --cndindex;
  10523. for ( ; cndindex >= 0; --cndindex)
  10524. {
  10525. if (this.conditions[cndindex].type === cnd.type)
  10526. return false;
  10527. }
  10528. return true;
  10529. };
  10530. cr.eventblock = EventBlock;
  10531. function Condition(block, m)
  10532. {
  10533. this.block = block;
  10534. this.sheet = block.sheet;
  10535. this.runtime = block.runtime;
  10536. this.parameters = [];
  10537. this.results = [];
  10538. this.extra = {}; // for plugins to stow away some custom info
  10539. this.index = -1;
  10540. this.anyParamVariesPerInstance = false;
  10541. this.func = this.runtime.GetObjectReference(m[1]);
  10542. ;
  10543. this.trigger = (m[3] > 0);
  10544. this.fasttrigger = (m[3] === 2);
  10545. this.looping = m[4];
  10546. this.inverted = m[5];
  10547. this.isstatic = m[6];
  10548. this.sid = m[7];
  10549. this.runtime.cndsBySid[this.sid.toString()] = this;
  10550. if (m[0] === -1) // system object
  10551. {
  10552. this.type = null;
  10553. this.run = this.run_system;
  10554. this.behaviortype = null;
  10555. this.beh_index = -1;
  10556. }
  10557. else
  10558. {
  10559. this.type = this.runtime.types_by_index[m[0]];
  10560. ;
  10561. if (this.isstatic)
  10562. this.run = this.run_static;
  10563. else
  10564. this.run = this.run_object;
  10565. if (m[2])
  10566. {
  10567. this.behaviortype = this.type.getBehaviorByName(m[2]);
  10568. ;
  10569. this.beh_index = this.type.getBehaviorIndexByName(m[2]);
  10570. ;
  10571. }
  10572. else
  10573. {
  10574. this.behaviortype = null;
  10575. this.beh_index = -1;
  10576. }
  10577. if (this.block.parent)
  10578. this.block.parent.setSolWriterAfterCnds();
  10579. }
  10580. if (this.fasttrigger)
  10581. this.run = this.run_true;
  10582. if (m.length === 10)
  10583. {
  10584. var i, len;
  10585. var em = m[9];
  10586. for (i = 0, len = em.length; i < len; i++)
  10587. {
  10588. var param = new cr.parameter(this, em[i]);
  10589. cr.seal(param);
  10590. this.parameters.push(param);
  10591. }
  10592. this.results.length = em.length;
  10593. }
  10594. };
  10595. Condition.prototype.postInit = function ()
  10596. {
  10597. var i, len, p;
  10598. for (i = 0, len = this.parameters.length; i < len; i++)
  10599. {
  10600. p = this.parameters[i];
  10601. p.postInit();
  10602. if (p.variesPerInstance)
  10603. this.anyParamVariesPerInstance = true;
  10604. }
  10605. };
  10606. /*
  10607. Condition.prototype.is_logical = function ()
  10608. {
  10609. return !this.type || this.type.plugin.singleglobal;
  10610. };
  10611. */
  10612. Condition.prototype.run_true = function ()
  10613. {
  10614. return true;
  10615. };
  10616. Condition.prototype.run_system = function ()
  10617. {
  10618. var i, len;
  10619. for (i = 0, len = this.parameters.length; i < len; i++)
  10620. this.results[i] = this.parameters[i].get();
  10621. return cr.xor(this.func.apply(this.runtime.system, this.results), this.inverted);
  10622. };
  10623. Condition.prototype.run_static = function ()
  10624. {
  10625. var i, len;
  10626. for (i = 0, len = this.parameters.length; i < len; i++)
  10627. this.results[i] = this.parameters[i].get();
  10628. var ret = this.func.apply(this.behaviortype ? this.behaviortype : this.type, this.results);
  10629. this.type.applySolToContainer();
  10630. return ret;
  10631. };
  10632. Condition.prototype.run_object = function ()
  10633. {
  10634. var i, j, k, leni, lenj, p, ret, met, inst, s, sol2;
  10635. var type = this.type;
  10636. var sol = type.getCurrentSol();
  10637. var is_orblock = this.block.orblock && !this.trigger; // triggers in OR blocks need to work normally
  10638. var offset = 0;
  10639. var is_contained = type.is_contained;
  10640. var is_family = type.is_family;
  10641. var family_index = type.family_index;
  10642. var beh_index = this.beh_index;
  10643. var is_beh = (beh_index > -1);
  10644. var params_vary = this.anyParamVariesPerInstance;
  10645. var parameters = this.parameters;
  10646. var results = this.results;
  10647. var inverted = this.inverted;
  10648. var func = this.func;
  10649. var arr, container;
  10650. if (params_vary)
  10651. {
  10652. for (j = 0, lenj = parameters.length; j < lenj; ++j)
  10653. {
  10654. p = parameters[j];
  10655. if (!p.variesPerInstance)
  10656. results[j] = p.get(0);
  10657. }
  10658. }
  10659. else
  10660. {
  10661. for (j = 0, lenj = parameters.length; j < lenj; ++j)
  10662. results[j] = parameters[j].get(0);
  10663. }
  10664. if (sol.select_all) {
  10665. cr.clearArray(sol.instances); // clear contents
  10666. cr.clearArray(sol.else_instances);
  10667. arr = type.instances;
  10668. for (i = 0, leni = arr.length; i < leni; ++i)
  10669. {
  10670. inst = arr[i];
  10671. ;
  10672. if (params_vary)
  10673. {
  10674. for (j = 0, lenj = parameters.length; j < lenj; ++j)
  10675. {
  10676. p = parameters[j];
  10677. if (p.variesPerInstance)
  10678. results[j] = p.get(i); // default SOL index is current object
  10679. }
  10680. }
  10681. if (is_beh)
  10682. {
  10683. offset = 0;
  10684. if (is_family)
  10685. {
  10686. offset = inst.type.family_beh_map[family_index];
  10687. }
  10688. ret = func.apply(inst.behavior_insts[beh_index + offset], results);
  10689. }
  10690. else
  10691. ret = func.apply(inst, results);
  10692. met = cr.xor(ret, inverted);
  10693. if (met)
  10694. sol.instances.push(inst);
  10695. else if (is_orblock) // in OR blocks, keep the instances not meeting the condition for subsequent testing
  10696. sol.else_instances.push(inst);
  10697. }
  10698. if (type.finish)
  10699. type.finish(true);
  10700. sol.select_all = false;
  10701. type.applySolToContainer();
  10702. return sol.hasObjects();
  10703. }
  10704. else {
  10705. k = 0;
  10706. var using_else_instances = (is_orblock && !this.block.isFirstConditionOfType(this));
  10707. arr = (using_else_instances ? sol.else_instances : sol.instances);
  10708. var any_true = false;
  10709. for (i = 0, leni = arr.length; i < leni; ++i)
  10710. {
  10711. inst = arr[i];
  10712. ;
  10713. if (params_vary)
  10714. {
  10715. for (j = 0, lenj = parameters.length; j < lenj; ++j)
  10716. {
  10717. p = parameters[j];
  10718. if (p.variesPerInstance)
  10719. results[j] = p.get(i); // default SOL index is current object
  10720. }
  10721. }
  10722. if (is_beh)
  10723. {
  10724. offset = 0;
  10725. if (is_family)
  10726. {
  10727. offset = inst.type.family_beh_map[family_index];
  10728. }
  10729. ret = func.apply(inst.behavior_insts[beh_index + offset], results);
  10730. }
  10731. else
  10732. ret = func.apply(inst, results);
  10733. if (cr.xor(ret, inverted))
  10734. {
  10735. any_true = true;
  10736. if (using_else_instances)
  10737. {
  10738. sol.instances.push(inst);
  10739. if (is_contained)
  10740. {
  10741. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  10742. {
  10743. s = inst.siblings[j];
  10744. s.type.getCurrentSol().instances.push(s);
  10745. }
  10746. }
  10747. }
  10748. else
  10749. {
  10750. arr[k] = inst;
  10751. if (is_contained)
  10752. {
  10753. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  10754. {
  10755. s = inst.siblings[j];
  10756. s.type.getCurrentSol().instances[k] = s;
  10757. }
  10758. }
  10759. k++;
  10760. }
  10761. }
  10762. else
  10763. {
  10764. if (using_else_instances)
  10765. {
  10766. arr[k] = inst;
  10767. if (is_contained)
  10768. {
  10769. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  10770. {
  10771. s = inst.siblings[j];
  10772. s.type.getCurrentSol().else_instances[k] = s;
  10773. }
  10774. }
  10775. k++;
  10776. }
  10777. else if (is_orblock)
  10778. {
  10779. sol.else_instances.push(inst);
  10780. if (is_contained)
  10781. {
  10782. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  10783. {
  10784. s = inst.siblings[j];
  10785. s.type.getCurrentSol().else_instances.push(s);
  10786. }
  10787. }
  10788. }
  10789. }
  10790. }
  10791. cr.truncateArray(arr, k);
  10792. if (is_contained)
  10793. {
  10794. container = type.container;
  10795. for (i = 0, leni = container.length; i < leni; i++)
  10796. {
  10797. sol2 = container[i].getCurrentSol();
  10798. if (using_else_instances)
  10799. cr.truncateArray(sol2.else_instances, k);
  10800. else
  10801. cr.truncateArray(sol2.instances, k);
  10802. }
  10803. }
  10804. var pick_in_finish = any_true; // don't pick in finish() if we're only doing the logic test below
  10805. if (using_else_instances && !any_true)
  10806. {
  10807. for (i = 0, leni = sol.instances.length; i < leni; i++)
  10808. {
  10809. inst = sol.instances[i];
  10810. if (params_vary)
  10811. {
  10812. for (j = 0, lenj = parameters.length; j < lenj; j++)
  10813. {
  10814. p = parameters[j];
  10815. if (p.variesPerInstance)
  10816. results[j] = p.get(i);
  10817. }
  10818. }
  10819. if (is_beh)
  10820. ret = func.apply(inst.behavior_insts[beh_index], results);
  10821. else
  10822. ret = func.apply(inst, results);
  10823. if (cr.xor(ret, inverted))
  10824. {
  10825. any_true = true;
  10826. break; // got our flag, don't need to test any more
  10827. }
  10828. }
  10829. }
  10830. if (type.finish)
  10831. type.finish(pick_in_finish || is_orblock);
  10832. return is_orblock ? any_true : sol.hasObjects();
  10833. }
  10834. };
  10835. cr.condition = Condition;
  10836. function Action(block, m)
  10837. {
  10838. this.block = block;
  10839. this.sheet = block.sheet;
  10840. this.runtime = block.runtime;
  10841. this.parameters = [];
  10842. this.results = [];
  10843. this.extra = {}; // for plugins to stow away some custom info
  10844. this.index = -1;
  10845. this.anyParamVariesPerInstance = false;
  10846. this.func = this.runtime.GetObjectReference(m[1]);
  10847. ;
  10848. if (m[0] === -1) // system
  10849. {
  10850. this.type = null;
  10851. this.run = this.run_system;
  10852. this.behaviortype = null;
  10853. this.beh_index = -1;
  10854. }
  10855. else
  10856. {
  10857. this.type = this.runtime.types_by_index[m[0]];
  10858. ;
  10859. this.run = this.run_object;
  10860. if (m[2])
  10861. {
  10862. this.behaviortype = this.type.getBehaviorByName(m[2]);
  10863. ;
  10864. this.beh_index = this.type.getBehaviorIndexByName(m[2]);
  10865. ;
  10866. }
  10867. else
  10868. {
  10869. this.behaviortype = null;
  10870. this.beh_index = -1;
  10871. }
  10872. }
  10873. this.sid = m[3];
  10874. this.runtime.actsBySid[this.sid.toString()] = this;
  10875. if (m.length === 6)
  10876. {
  10877. var i, len;
  10878. var em = m[5];
  10879. for (i = 0, len = em.length; i < len; i++)
  10880. {
  10881. var param = new cr.parameter(this, em[i]);
  10882. cr.seal(param);
  10883. this.parameters.push(param);
  10884. }
  10885. this.results.length = em.length;
  10886. }
  10887. };
  10888. Action.prototype.postInit = function ()
  10889. {
  10890. var i, len, p;
  10891. for (i = 0, len = this.parameters.length; i < len; i++)
  10892. {
  10893. p = this.parameters[i];
  10894. p.postInit();
  10895. if (p.variesPerInstance)
  10896. this.anyParamVariesPerInstance = true;
  10897. }
  10898. };
  10899. Action.prototype.run_system = function ()
  10900. {
  10901. var runtime = this.runtime;
  10902. var i, len;
  10903. var parameters = this.parameters;
  10904. var results = this.results;
  10905. for (i = 0, len = parameters.length; i < len; ++i)
  10906. results[i] = parameters[i].get();
  10907. return this.func.apply(runtime.system, results);
  10908. };
  10909. Action.prototype.run_object = function ()
  10910. {
  10911. var type = this.type;
  10912. var beh_index = this.beh_index;
  10913. var family_index = type.family_index;
  10914. var params_vary = this.anyParamVariesPerInstance;
  10915. var parameters = this.parameters;
  10916. var results = this.results;
  10917. var func = this.func;
  10918. var instances = type.getCurrentSol().getObjects();
  10919. var is_family = type.is_family;
  10920. var is_beh = (beh_index > -1);
  10921. var i, j, leni, lenj, p, inst, offset;
  10922. if (params_vary)
  10923. {
  10924. for (j = 0, lenj = parameters.length; j < lenj; ++j)
  10925. {
  10926. p = parameters[j];
  10927. if (!p.variesPerInstance)
  10928. results[j] = p.get(0);
  10929. }
  10930. }
  10931. else
  10932. {
  10933. for (j = 0, lenj = parameters.length; j < lenj; ++j)
  10934. results[j] = parameters[j].get(0);
  10935. }
  10936. for (i = 0, leni = instances.length; i < leni; ++i)
  10937. {
  10938. inst = instances[i];
  10939. if (params_vary)
  10940. {
  10941. for (j = 0, lenj = parameters.length; j < lenj; ++j)
  10942. {
  10943. p = parameters[j];
  10944. if (p.variesPerInstance)
  10945. results[j] = p.get(i); // pass i to use as default SOL index
  10946. }
  10947. }
  10948. if (is_beh)
  10949. {
  10950. offset = 0;
  10951. if (is_family)
  10952. {
  10953. offset = inst.type.family_beh_map[family_index];
  10954. }
  10955. func.apply(inst.behavior_insts[beh_index + offset], results);
  10956. }
  10957. else
  10958. func.apply(inst, results);
  10959. }
  10960. return false;
  10961. };
  10962. cr.action = Action;
  10963. var tempValues = [];
  10964. var tempValuesPtr = -1;
  10965. function pushTempValue()
  10966. {
  10967. tempValuesPtr++;
  10968. if (tempValues.length === tempValuesPtr)
  10969. tempValues.push(new cr.expvalue());
  10970. return tempValues[tempValuesPtr];
  10971. };
  10972. function popTempValue()
  10973. {
  10974. tempValuesPtr--;
  10975. };
  10976. function Parameter(owner, m)
  10977. {
  10978. this.owner = owner;
  10979. this.block = owner.block;
  10980. this.sheet = owner.sheet;
  10981. this.runtime = owner.runtime;
  10982. this.type = m[0];
  10983. this.expression = null;
  10984. this.solindex = 0;
  10985. this.get = null;
  10986. this.combosel = 0;
  10987. this.layout = null;
  10988. this.key = 0;
  10989. this.object = null;
  10990. this.index = 0;
  10991. this.varname = null;
  10992. this.eventvar = null;
  10993. this.fileinfo = null;
  10994. this.subparams = null;
  10995. this.variadicret = null;
  10996. this.subparams = null;
  10997. this.variadicret = null;
  10998. this.variesPerInstance = false;
  10999. var i, len, param;
  11000. switch (m[0])
  11001. {
  11002. case 0: // number
  11003. case 7: // any
  11004. this.expression = new cr.expNode(this, m[1]);
  11005. this.solindex = 0;
  11006. this.get = this.get_exp;
  11007. break;
  11008. case 1: // string
  11009. this.expression = new cr.expNode(this, m[1]);
  11010. this.solindex = 0;
  11011. this.get = this.get_exp_str;
  11012. break;
  11013. case 5: // layer
  11014. this.expression = new cr.expNode(this, m[1]);
  11015. this.solindex = 0;
  11016. this.get = this.get_layer;
  11017. break;
  11018. case 3: // combo
  11019. case 8: // cmp
  11020. this.combosel = m[1];
  11021. this.get = this.get_combosel;
  11022. break;
  11023. case 6: // layout
  11024. this.layout = this.runtime.layouts[m[1]];
  11025. ;
  11026. this.get = this.get_layout;
  11027. break;
  11028. case 9: // keyb
  11029. this.key = m[1];
  11030. this.get = this.get_key;
  11031. break;
  11032. case 4: // object
  11033. this.object = this.runtime.types_by_index[m[1]];
  11034. ;
  11035. this.get = this.get_object;
  11036. this.block.addSolModifier(this.object);
  11037. if (this.owner instanceof cr.action)
  11038. this.block.setSolWriterAfterCnds();
  11039. else if (this.block.parent)
  11040. this.block.parent.setSolWriterAfterCnds();
  11041. break;
  11042. case 10: // instvar
  11043. this.index = m[1];
  11044. if (owner.type && owner.type.is_family)
  11045. {
  11046. this.get = this.get_familyvar;
  11047. this.variesPerInstance = true;
  11048. }
  11049. else
  11050. this.get = this.get_instvar;
  11051. break;
  11052. case 11: // eventvar
  11053. this.varname = m[1];
  11054. this.eventvar = null;
  11055. this.get = this.get_eventvar;
  11056. break;
  11057. case 2: // audiofile ["name", ismusic]
  11058. case 12: // fileinfo "name"
  11059. this.fileinfo = m[1];
  11060. this.get = this.get_audiofile;
  11061. break;
  11062. case 13: // variadic
  11063. this.get = this.get_variadic;
  11064. this.subparams = [];
  11065. this.variadicret = [];
  11066. for (i = 1, len = m.length; i < len; i++)
  11067. {
  11068. param = new cr.parameter(this.owner, m[i]);
  11069. cr.seal(param);
  11070. this.subparams.push(param);
  11071. this.variadicret.push(0);
  11072. }
  11073. break;
  11074. default:
  11075. ;
  11076. }
  11077. };
  11078. Parameter.prototype.postInit = function ()
  11079. {
  11080. var i, len;
  11081. if (this.type === 11) // eventvar
  11082. {
  11083. this.eventvar = this.runtime.getEventVariableByName(this.varname, this.block.parent);
  11084. ;
  11085. }
  11086. else if (this.type === 13) // variadic, postInit all sub-params
  11087. {
  11088. for (i = 0, len = this.subparams.length; i < len; i++)
  11089. this.subparams[i].postInit();
  11090. }
  11091. if (this.expression)
  11092. this.expression.postInit();
  11093. };
  11094. Parameter.prototype.maybeVaryForType = function (t)
  11095. {
  11096. if (this.variesPerInstance)
  11097. return; // already varies per instance, no need to check again
  11098. if (!t)
  11099. return; // never vary for system type
  11100. if (!t.plugin.singleglobal)
  11101. {
  11102. this.variesPerInstance = true;
  11103. return;
  11104. }
  11105. };
  11106. Parameter.prototype.setVaries = function ()
  11107. {
  11108. this.variesPerInstance = true;
  11109. };
  11110. Parameter.prototype.get_exp = function (solindex)
  11111. {
  11112. this.solindex = solindex || 0; // default SOL index to use
  11113. var temp = pushTempValue();
  11114. this.expression.get(temp);
  11115. popTempValue();
  11116. return temp.data; // return actual JS value, not expvalue
  11117. };
  11118. Parameter.prototype.get_exp_str = function (solindex)
  11119. {
  11120. this.solindex = solindex || 0; // default SOL index to use
  11121. var temp = pushTempValue();
  11122. this.expression.get(temp);
  11123. popTempValue();
  11124. if (cr.is_string(temp.data))
  11125. return temp.data;
  11126. else
  11127. return "";
  11128. };
  11129. Parameter.prototype.get_object = function ()
  11130. {
  11131. return this.object;
  11132. };
  11133. Parameter.prototype.get_combosel = function ()
  11134. {
  11135. return this.combosel;
  11136. };
  11137. Parameter.prototype.get_layer = function (solindex)
  11138. {
  11139. this.solindex = solindex || 0; // default SOL index to use
  11140. var temp = pushTempValue();
  11141. this.expression.get(temp);
  11142. popTempValue();
  11143. if (temp.is_number())
  11144. return this.runtime.getLayerByNumber(temp.data);
  11145. else
  11146. return this.runtime.getLayerByName(temp.data);
  11147. }
  11148. Parameter.prototype.get_layout = function ()
  11149. {
  11150. return this.layout;
  11151. };
  11152. Parameter.prototype.get_key = function ()
  11153. {
  11154. return this.key;
  11155. };
  11156. Parameter.prototype.get_instvar = function ()
  11157. {
  11158. return this.index;
  11159. };
  11160. Parameter.prototype.get_familyvar = function (solindex_)
  11161. {
  11162. var solindex = solindex_ || 0;
  11163. var familytype = this.owner.type;
  11164. var realtype = null;
  11165. var sol = familytype.getCurrentSol();
  11166. var objs = sol.getObjects();
  11167. if (objs.length)
  11168. realtype = objs[solindex % objs.length].type;
  11169. else if (sol.else_instances.length)
  11170. realtype = sol.else_instances[solindex % sol.else_instances.length].type;
  11171. else if (familytype.instances.length)
  11172. realtype = familytype.instances[solindex % familytype.instances.length].type;
  11173. else
  11174. return 0;
  11175. return this.index + realtype.family_var_map[familytype.family_index];
  11176. };
  11177. Parameter.prototype.get_eventvar = function ()
  11178. {
  11179. return this.eventvar;
  11180. };
  11181. Parameter.prototype.get_audiofile = function ()
  11182. {
  11183. return this.fileinfo;
  11184. };
  11185. Parameter.prototype.get_variadic = function ()
  11186. {
  11187. var i, len;
  11188. for (i = 0, len = this.subparams.length; i < len; i++)
  11189. {
  11190. this.variadicret[i] = this.subparams[i].get();
  11191. }
  11192. return this.variadicret;
  11193. };
  11194. cr.parameter = Parameter;
  11195. function EventVariable(sheet, parent, m)
  11196. {
  11197. this.sheet = sheet;
  11198. this.parent = parent;
  11199. this.runtime = sheet.runtime;
  11200. this.solModifiers = [];
  11201. this.name = m[1];
  11202. this.vartype = m[2];
  11203. this.initial = m[3];
  11204. this.is_static = !!m[4];
  11205. this.is_constant = !!m[5];
  11206. this.sid = m[6];
  11207. this.runtime.varsBySid[this.sid.toString()] = this;
  11208. this.data = this.initial; // note: also stored in event stack frame for local nonstatic nonconst vars
  11209. if (this.parent) // local var
  11210. {
  11211. if (this.is_static || this.is_constant)
  11212. this.localIndex = -1;
  11213. else
  11214. this.localIndex = this.runtime.stackLocalCount++;
  11215. this.runtime.all_local_vars.push(this);
  11216. }
  11217. else // global var
  11218. {
  11219. this.localIndex = -1;
  11220. this.runtime.all_global_vars.push(this);
  11221. }
  11222. };
  11223. EventVariable.prototype.postInit = function ()
  11224. {
  11225. this.solModifiers = findMatchingSolModifier(this.solModifiers);
  11226. };
  11227. EventVariable.prototype.setValue = function (x)
  11228. {
  11229. ;
  11230. var lvs = this.runtime.getCurrentLocalVarStack();
  11231. if (!this.parent || this.is_static || !lvs)
  11232. this.data = x;
  11233. else // local nonstatic variable: use event stack to keep value at this level of recursion
  11234. {
  11235. if (this.localIndex >= lvs.length)
  11236. lvs.length = this.localIndex + 1;
  11237. lvs[this.localIndex] = x;
  11238. }
  11239. };
  11240. EventVariable.prototype.getValue = function ()
  11241. {
  11242. var lvs = this.runtime.getCurrentLocalVarStack();
  11243. if (!this.parent || this.is_static || !lvs || this.is_constant)
  11244. return this.data;
  11245. else // local nonstatic variable
  11246. {
  11247. if (this.localIndex >= lvs.length)
  11248. {
  11249. return this.initial;
  11250. }
  11251. if (typeof lvs[this.localIndex] === "undefined")
  11252. {
  11253. return this.initial;
  11254. }
  11255. return lvs[this.localIndex];
  11256. }
  11257. };
  11258. EventVariable.prototype.run = function ()
  11259. {
  11260. if (this.parent && !this.is_static && !this.is_constant)
  11261. this.setValue(this.initial);
  11262. };
  11263. cr.eventvariable = EventVariable;
  11264. function EventInclude(sheet, parent, m)
  11265. {
  11266. this.sheet = sheet;
  11267. this.parent = parent;
  11268. this.runtime = sheet.runtime;
  11269. this.solModifiers = [];
  11270. this.include_sheet = null; // determined in postInit
  11271. this.include_sheet_name = m[1];
  11272. this.active = true;
  11273. };
  11274. EventInclude.prototype.toString = function ()
  11275. {
  11276. return "include:" + this.include_sheet.toString();
  11277. };
  11278. EventInclude.prototype.postInit = function ()
  11279. {
  11280. this.include_sheet = this.runtime.eventsheets[this.include_sheet_name];
  11281. ;
  11282. ;
  11283. this.sheet.includes.add(this);
  11284. this.solModifiers = findMatchingSolModifier(this.solModifiers);
  11285. var p = this.parent;
  11286. while (p)
  11287. {
  11288. if (p.group)
  11289. p.contained_includes.push(this);
  11290. p = p.parent;
  11291. }
  11292. this.updateActive();
  11293. };
  11294. EventInclude.prototype.run = function ()
  11295. {
  11296. if (this.parent)
  11297. this.runtime.pushCleanSol(this.runtime.types_by_index);
  11298. if (!this.include_sheet.hasRun)
  11299. this.include_sheet.run(true); // from include
  11300. if (this.parent)
  11301. this.runtime.popSol(this.runtime.types_by_index);
  11302. };
  11303. EventInclude.prototype.updateActive = function ()
  11304. {
  11305. var p = this.parent;
  11306. while (p)
  11307. {
  11308. if (p.group && !p.group_active)
  11309. {
  11310. this.active = false;
  11311. return;
  11312. }
  11313. p = p.parent;
  11314. }
  11315. this.active = true;
  11316. };
  11317. EventInclude.prototype.isActive = function ()
  11318. {
  11319. return this.active;
  11320. };
  11321. cr.eventinclude = EventInclude;
  11322. function EventStackFrame()
  11323. {
  11324. this.temp_parents_arr = [];
  11325. this.reset(null);
  11326. cr.seal(this);
  11327. };
  11328. EventStackFrame.prototype.reset = function (cur_event)
  11329. {
  11330. this.current_event = cur_event;
  11331. this.cndindex = 0;
  11332. this.actindex = 0;
  11333. cr.clearArray(this.temp_parents_arr);
  11334. this.last_event_true = false;
  11335. this.else_branch_ran = false;
  11336. this.any_true_state = false;
  11337. };
  11338. EventStackFrame.prototype.isModifierAfterCnds = function ()
  11339. {
  11340. if (this.current_event.solWriterAfterCnds)
  11341. return true;
  11342. if (this.cndindex < this.current_event.conditions.length - 1)
  11343. return !!this.current_event.solModifiers.length;
  11344. return false;
  11345. };
  11346. cr.eventStackFrame = EventStackFrame;
  11347. }());
  11348. (function()
  11349. {
  11350. function ExpNode(owner_, m)
  11351. {
  11352. this.owner = owner_;
  11353. this.runtime = owner_.runtime;
  11354. this.type = m[0];
  11355. ;
  11356. this.get = [this.eval_int,
  11357. this.eval_float,
  11358. this.eval_string,
  11359. this.eval_unaryminus,
  11360. this.eval_add,
  11361. this.eval_subtract,
  11362. this.eval_multiply,
  11363. this.eval_divide,
  11364. this.eval_mod,
  11365. this.eval_power,
  11366. this.eval_and,
  11367. this.eval_or,
  11368. this.eval_equal,
  11369. this.eval_notequal,
  11370. this.eval_less,
  11371. this.eval_lessequal,
  11372. this.eval_greater,
  11373. this.eval_greaterequal,
  11374. this.eval_conditional,
  11375. this.eval_system_exp,
  11376. this.eval_object_exp,
  11377. this.eval_instvar_exp,
  11378. this.eval_behavior_exp,
  11379. this.eval_eventvar_exp][this.type];
  11380. var paramsModel = null;
  11381. this.value = null;
  11382. this.first = null;
  11383. this.second = null;
  11384. this.third = null;
  11385. this.func = null;
  11386. this.results = null;
  11387. this.parameters = null;
  11388. this.object_type = null;
  11389. this.beh_index = -1;
  11390. this.instance_expr = null;
  11391. this.varindex = -1;
  11392. this.behavior_type = null;
  11393. this.varname = null;
  11394. this.eventvar = null;
  11395. this.return_string = false;
  11396. switch (this.type) {
  11397. case 0: // int
  11398. case 1: // float
  11399. case 2: // string
  11400. this.value = m[1];
  11401. break;
  11402. case 3: // unaryminus
  11403. this.first = new cr.expNode(owner_, m[1]);
  11404. break;
  11405. case 18: // conditional
  11406. this.first = new cr.expNode(owner_, m[1]);
  11407. this.second = new cr.expNode(owner_, m[2]);
  11408. this.third = new cr.expNode(owner_, m[3]);
  11409. break;
  11410. case 19: // system_exp
  11411. this.func = this.runtime.GetObjectReference(m[1]);
  11412. ;
  11413. if (this.func === cr.system_object.prototype.exps.random
  11414. || this.func === cr.system_object.prototype.exps.choose)
  11415. {
  11416. this.owner.setVaries();
  11417. }
  11418. this.results = [];
  11419. this.parameters = [];
  11420. if (m.length === 3)
  11421. {
  11422. paramsModel = m[2];
  11423. this.results.length = paramsModel.length + 1; // must also fit 'ret'
  11424. }
  11425. else
  11426. this.results.length = 1; // to fit 'ret'
  11427. break;
  11428. case 20: // object_exp
  11429. this.object_type = this.runtime.types_by_index[m[1]];
  11430. ;
  11431. this.beh_index = -1;
  11432. this.func = this.runtime.GetObjectReference(m[2]);
  11433. this.return_string = m[3];
  11434. if (cr.plugins_.Function && this.func === cr.plugins_.Function.prototype.exps.Call)
  11435. {
  11436. this.owner.setVaries();
  11437. }
  11438. if (m[4])
  11439. this.instance_expr = new cr.expNode(owner_, m[4]);
  11440. else
  11441. this.instance_expr = null;
  11442. this.results = [];
  11443. this.parameters = [];
  11444. if (m.length === 6)
  11445. {
  11446. paramsModel = m[5];
  11447. this.results.length = paramsModel.length + 1;
  11448. }
  11449. else
  11450. this.results.length = 1; // to fit 'ret'
  11451. break;
  11452. case 21: // instvar_exp
  11453. this.object_type = this.runtime.types_by_index[m[1]];
  11454. ;
  11455. this.return_string = m[2];
  11456. if (m[3])
  11457. this.instance_expr = new cr.expNode(owner_, m[3]);
  11458. else
  11459. this.instance_expr = null;
  11460. this.varindex = m[4];
  11461. break;
  11462. case 22: // behavior_exp
  11463. this.object_type = this.runtime.types_by_index[m[1]];
  11464. ;
  11465. this.behavior_type = this.object_type.getBehaviorByName(m[2]);
  11466. ;
  11467. this.beh_index = this.object_type.getBehaviorIndexByName(m[2]);
  11468. this.func = this.runtime.GetObjectReference(m[3]);
  11469. this.return_string = m[4];
  11470. if (m[5])
  11471. this.instance_expr = new cr.expNode(owner_, m[5]);
  11472. else
  11473. this.instance_expr = null;
  11474. this.results = [];
  11475. this.parameters = [];
  11476. if (m.length === 7)
  11477. {
  11478. paramsModel = m[6];
  11479. this.results.length = paramsModel.length + 1;
  11480. }
  11481. else
  11482. this.results.length = 1; // to fit 'ret'
  11483. break;
  11484. case 23: // eventvar_exp
  11485. this.varname = m[1];
  11486. this.eventvar = null; // assigned in postInit
  11487. break;
  11488. }
  11489. this.owner.maybeVaryForType(this.object_type);
  11490. if (this.type >= 4 && this.type <= 17)
  11491. {
  11492. this.first = new cr.expNode(owner_, m[1]);
  11493. this.second = new cr.expNode(owner_, m[2]);
  11494. }
  11495. if (paramsModel)
  11496. {
  11497. var i, len;
  11498. for (i = 0, len = paramsModel.length; i < len; i++)
  11499. this.parameters.push(new cr.expNode(owner_, paramsModel[i]));
  11500. }
  11501. cr.seal(this);
  11502. };
  11503. ExpNode.prototype.postInit = function ()
  11504. {
  11505. if (this.type === 23) // eventvar_exp
  11506. {
  11507. this.eventvar = this.owner.runtime.getEventVariableByName(this.varname, this.owner.block.parent);
  11508. ;
  11509. }
  11510. if (this.first)
  11511. this.first.postInit();
  11512. if (this.second)
  11513. this.second.postInit();
  11514. if (this.third)
  11515. this.third.postInit();
  11516. if (this.instance_expr)
  11517. this.instance_expr.postInit();
  11518. if (this.parameters)
  11519. {
  11520. var i, len;
  11521. for (i = 0, len = this.parameters.length; i < len; i++)
  11522. this.parameters[i].postInit();
  11523. }
  11524. };
  11525. var tempValues = [];
  11526. var tempValuesPtr = -1;
  11527. function pushTempValue()
  11528. {
  11529. ++tempValuesPtr;
  11530. if (tempValues.length === tempValuesPtr)
  11531. tempValues.push(new cr.expvalue());
  11532. return tempValues[tempValuesPtr];
  11533. };
  11534. function popTempValue()
  11535. {
  11536. --tempValuesPtr;
  11537. };
  11538. function eval_params(parameters, results, temp)
  11539. {
  11540. var i, len;
  11541. for (i = 0, len = parameters.length; i < len; ++i)
  11542. {
  11543. parameters[i].get(temp);
  11544. results[i + 1] = temp.data; // passing actual javascript value as argument instead of expvalue
  11545. }
  11546. }
  11547. ExpNode.prototype.eval_system_exp = function (ret)
  11548. {
  11549. var parameters = this.parameters;
  11550. var results = this.results;
  11551. results[0] = ret;
  11552. var temp = pushTempValue();
  11553. eval_params(parameters, results, temp);
  11554. popTempValue();
  11555. this.func.apply(this.runtime.system, results);
  11556. };
  11557. ExpNode.prototype.eval_object_exp = function (ret)
  11558. {
  11559. var object_type = this.object_type;
  11560. var results = this.results;
  11561. var parameters = this.parameters;
  11562. var instance_expr = this.instance_expr;
  11563. var func = this.func;
  11564. var index = this.owner.solindex; // default to parameter's intended SOL index
  11565. var sol = object_type.getCurrentSol();
  11566. var instances = sol.getObjects();
  11567. if (!instances.length)
  11568. {
  11569. if (sol.else_instances.length)
  11570. instances = sol.else_instances;
  11571. else
  11572. {
  11573. if (this.return_string)
  11574. ret.set_string("");
  11575. else
  11576. ret.set_int(0);
  11577. return;
  11578. }
  11579. }
  11580. results[0] = ret;
  11581. ret.object_class = object_type; // so expression can access family type if need be
  11582. var temp = pushTempValue();
  11583. eval_params(parameters, results, temp);
  11584. if (instance_expr) {
  11585. instance_expr.get(temp);
  11586. if (temp.is_number()) {
  11587. index = temp.data;
  11588. instances = object_type.instances; // pick from all instances, not SOL
  11589. }
  11590. }
  11591. popTempValue();
  11592. var len = instances.length;
  11593. if (index >= len || index <= -len)
  11594. index %= len; // wraparound
  11595. if (index < 0)
  11596. index += len;
  11597. var returned_val = func.apply(instances[index], results);
  11598. ;
  11599. };
  11600. ExpNode.prototype.eval_behavior_exp = function (ret)
  11601. {
  11602. var object_type = this.object_type;
  11603. var results = this.results;
  11604. var parameters = this.parameters;
  11605. var instance_expr = this.instance_expr;
  11606. var beh_index = this.beh_index;
  11607. var func = this.func;
  11608. var index = this.owner.solindex; // default to parameter's intended SOL index
  11609. var sol = object_type.getCurrentSol();
  11610. var instances = sol.getObjects();
  11611. if (!instances.length)
  11612. {
  11613. if (sol.else_instances.length)
  11614. instances = sol.else_instances;
  11615. else
  11616. {
  11617. if (this.return_string)
  11618. ret.set_string("");
  11619. else
  11620. ret.set_int(0);
  11621. return;
  11622. }
  11623. }
  11624. results[0] = ret;
  11625. ret.object_class = object_type; // so expression can access family type if need be
  11626. var temp = pushTempValue();
  11627. eval_params(parameters, results, temp);
  11628. if (instance_expr) {
  11629. instance_expr.get(temp);
  11630. if (temp.is_number()) {
  11631. index = temp.data;
  11632. instances = object_type.instances; // pick from all instances, not SOL
  11633. }
  11634. }
  11635. popTempValue();
  11636. var len = instances.length;
  11637. if (index >= len || index <= -len)
  11638. index %= len; // wraparound
  11639. if (index < 0)
  11640. index += len;
  11641. var inst = instances[index];
  11642. var offset = 0;
  11643. if (object_type.is_family)
  11644. {
  11645. offset = inst.type.family_beh_map[object_type.family_index];
  11646. }
  11647. var returned_val = func.apply(inst.behavior_insts[beh_index + offset], results);
  11648. ;
  11649. };
  11650. ExpNode.prototype.eval_instvar_exp = function (ret)
  11651. {
  11652. var instance_expr = this.instance_expr;
  11653. var object_type = this.object_type;
  11654. var varindex = this.varindex;
  11655. var index = this.owner.solindex; // default to parameter's intended SOL index
  11656. var sol = object_type.getCurrentSol();
  11657. var instances = sol.getObjects();
  11658. var inst;
  11659. if (!instances.length)
  11660. {
  11661. if (sol.else_instances.length)
  11662. instances = sol.else_instances;
  11663. else
  11664. {
  11665. if (this.return_string)
  11666. ret.set_string("");
  11667. else
  11668. ret.set_int(0);
  11669. return;
  11670. }
  11671. }
  11672. if (instance_expr)
  11673. {
  11674. var temp = pushTempValue();
  11675. instance_expr.get(temp);
  11676. if (temp.is_number())
  11677. {
  11678. index = temp.data;
  11679. var type_instances = object_type.instances;
  11680. if (type_instances.length !== 0) // avoid NaN result with %
  11681. {
  11682. index %= type_instances.length; // wraparound
  11683. if (index < 0) // offset
  11684. index += type_instances.length;
  11685. }
  11686. inst = object_type.getInstanceByIID(index);
  11687. var to_ret = inst.instance_vars[varindex];
  11688. if (cr.is_string(to_ret))
  11689. ret.set_string(to_ret);
  11690. else
  11691. ret.set_float(to_ret);
  11692. popTempValue();
  11693. return; // done
  11694. }
  11695. popTempValue();
  11696. }
  11697. var len = instances.length;
  11698. if (index >= len || index <= -len)
  11699. index %= len; // wraparound
  11700. if (index < 0)
  11701. index += len;
  11702. inst = instances[index];
  11703. var offset = 0;
  11704. if (object_type.is_family)
  11705. {
  11706. offset = inst.type.family_var_map[object_type.family_index];
  11707. }
  11708. var to_ret = inst.instance_vars[varindex + offset];
  11709. if (cr.is_string(to_ret))
  11710. ret.set_string(to_ret);
  11711. else
  11712. ret.set_float(to_ret);
  11713. };
  11714. ExpNode.prototype.eval_int = function (ret)
  11715. {
  11716. ret.type = cr.exptype.Integer;
  11717. ret.data = this.value;
  11718. };
  11719. ExpNode.prototype.eval_float = function (ret)
  11720. {
  11721. ret.type = cr.exptype.Float;
  11722. ret.data = this.value;
  11723. };
  11724. ExpNode.prototype.eval_string = function (ret)
  11725. {
  11726. ret.type = cr.exptype.String;
  11727. ret.data = this.value;
  11728. };
  11729. ExpNode.prototype.eval_unaryminus = function (ret)
  11730. {
  11731. this.first.get(ret); // retrieve operand
  11732. if (ret.is_number())
  11733. ret.data = -ret.data;
  11734. };
  11735. ExpNode.prototype.eval_add = function (ret)
  11736. {
  11737. this.first.get(ret); // left operand
  11738. var temp = pushTempValue();
  11739. this.second.get(temp); // right operand
  11740. if (ret.is_number() && temp.is_number())
  11741. {
  11742. ret.data += temp.data; // both operands numbers: add
  11743. if (temp.is_float())
  11744. ret.make_float();
  11745. }
  11746. popTempValue();
  11747. };
  11748. ExpNode.prototype.eval_subtract = function (ret)
  11749. {
  11750. this.first.get(ret); // left operand
  11751. var temp = pushTempValue();
  11752. this.second.get(temp); // right operand
  11753. if (ret.is_number() && temp.is_number())
  11754. {
  11755. ret.data -= temp.data; // both operands numbers: subtract
  11756. if (temp.is_float())
  11757. ret.make_float();
  11758. }
  11759. popTempValue();
  11760. };
  11761. ExpNode.prototype.eval_multiply = function (ret)
  11762. {
  11763. this.first.get(ret); // left operand
  11764. var temp = pushTempValue();
  11765. this.second.get(temp); // right operand
  11766. if (ret.is_number() && temp.is_number())
  11767. {
  11768. ret.data *= temp.data; // both operands numbers: multiply
  11769. if (temp.is_float())
  11770. ret.make_float();
  11771. }
  11772. popTempValue();
  11773. };
  11774. ExpNode.prototype.eval_divide = function (ret)
  11775. {
  11776. this.first.get(ret); // left operand
  11777. var temp = pushTempValue();
  11778. this.second.get(temp); // right operand
  11779. if (ret.is_number() && temp.is_number())
  11780. {
  11781. ret.data /= temp.data; // both operands numbers: divide
  11782. ret.make_float();
  11783. }
  11784. popTempValue();
  11785. };
  11786. ExpNode.prototype.eval_mod = function (ret)
  11787. {
  11788. this.first.get(ret); // left operand
  11789. var temp = pushTempValue();
  11790. this.second.get(temp); // right operand
  11791. if (ret.is_number() && temp.is_number())
  11792. {
  11793. ret.data %= temp.data; // both operands numbers: modulo
  11794. if (temp.is_float())
  11795. ret.make_float();
  11796. }
  11797. popTempValue();
  11798. };
  11799. ExpNode.prototype.eval_power = function (ret)
  11800. {
  11801. this.first.get(ret); // left operand
  11802. var temp = pushTempValue();
  11803. this.second.get(temp); // right operand
  11804. if (ret.is_number() && temp.is_number())
  11805. {
  11806. ret.data = Math.pow(ret.data, temp.data); // both operands numbers: raise to power
  11807. if (temp.is_float())
  11808. ret.make_float();
  11809. }
  11810. popTempValue();
  11811. };
  11812. ExpNode.prototype.eval_and = function (ret)
  11813. {
  11814. this.first.get(ret); // left operand
  11815. var temp = pushTempValue();
  11816. this.second.get(temp); // right operand
  11817. if (temp.is_string() || ret.is_string())
  11818. this.eval_and_stringconcat(ret, temp);
  11819. else
  11820. this.eval_and_logical(ret, temp);
  11821. popTempValue();
  11822. };
  11823. ExpNode.prototype.eval_and_stringconcat = function (ret, temp)
  11824. {
  11825. if (ret.is_string() && temp.is_string())
  11826. this.eval_and_stringconcat_str_str(ret, temp);
  11827. else
  11828. this.eval_and_stringconcat_num(ret, temp);
  11829. };
  11830. ExpNode.prototype.eval_and_stringconcat_str_str = function (ret, temp)
  11831. {
  11832. ret.data += temp.data;
  11833. };
  11834. ExpNode.prototype.eval_and_stringconcat_num = function (ret, temp)
  11835. {
  11836. if (ret.is_string())
  11837. {
  11838. ret.data += (Math.round(temp.data * 1e10) / 1e10).toString();
  11839. }
  11840. else
  11841. {
  11842. ret.set_string(ret.data.toString() + temp.data);
  11843. }
  11844. };
  11845. ExpNode.prototype.eval_and_logical = function (ret, temp)
  11846. {
  11847. ret.set_int(ret.data && temp.data ? 1 : 0);
  11848. };
  11849. ExpNode.prototype.eval_or = function (ret)
  11850. {
  11851. this.first.get(ret); // left operand
  11852. var temp = pushTempValue();
  11853. this.second.get(temp); // right operand
  11854. if (ret.is_number() && temp.is_number())
  11855. {
  11856. if (ret.data || temp.data)
  11857. ret.set_int(1);
  11858. else
  11859. ret.set_int(0);
  11860. }
  11861. popTempValue();
  11862. };
  11863. ExpNode.prototype.eval_conditional = function (ret)
  11864. {
  11865. this.first.get(ret); // condition operand
  11866. if (ret.data) // is true
  11867. this.second.get(ret); // evaluate second operand to ret
  11868. else
  11869. this.third.get(ret); // evaluate third operand to ret
  11870. };
  11871. ExpNode.prototype.eval_equal = function (ret)
  11872. {
  11873. this.first.get(ret); // left operand
  11874. var temp = pushTempValue();
  11875. this.second.get(temp); // right operand
  11876. ret.set_int(ret.data === temp.data ? 1 : 0);
  11877. popTempValue();
  11878. };
  11879. ExpNode.prototype.eval_notequal = function (ret)
  11880. {
  11881. this.first.get(ret); // left operand
  11882. var temp = pushTempValue();
  11883. this.second.get(temp); // right operand
  11884. ret.set_int(ret.data !== temp.data ? 1 : 0);
  11885. popTempValue();
  11886. };
  11887. ExpNode.prototype.eval_less = function (ret)
  11888. {
  11889. this.first.get(ret); // left operand
  11890. var temp = pushTempValue();
  11891. this.second.get(temp); // right operand
  11892. ret.set_int(ret.data < temp.data ? 1 : 0);
  11893. popTempValue();
  11894. };
  11895. ExpNode.prototype.eval_lessequal = function (ret)
  11896. {
  11897. this.first.get(ret); // left operand
  11898. var temp = pushTempValue();
  11899. this.second.get(temp); // right operand
  11900. ret.set_int(ret.data <= temp.data ? 1 : 0);
  11901. popTempValue();
  11902. };
  11903. ExpNode.prototype.eval_greater = function (ret)
  11904. {
  11905. this.first.get(ret); // left operand
  11906. var temp = pushTempValue();
  11907. this.second.get(temp); // right operand
  11908. ret.set_int(ret.data > temp.data ? 1 : 0);
  11909. popTempValue();
  11910. };
  11911. ExpNode.prototype.eval_greaterequal = function (ret)
  11912. {
  11913. this.first.get(ret); // left operand
  11914. var temp = pushTempValue();
  11915. this.second.get(temp); // right operand
  11916. ret.set_int(ret.data >= temp.data ? 1 : 0);
  11917. popTempValue();
  11918. };
  11919. ExpNode.prototype.eval_eventvar_exp = function (ret)
  11920. {
  11921. var val = this.eventvar.getValue();
  11922. if (cr.is_number(val))
  11923. ret.set_float(val);
  11924. else
  11925. ret.set_string(val);
  11926. };
  11927. cr.expNode = ExpNode;
  11928. function ExpValue(type, data)
  11929. {
  11930. this.type = type || cr.exptype.Integer;
  11931. this.data = data || 0;
  11932. this.object_class = null;
  11933. ;
  11934. ;
  11935. ;
  11936. if (this.type == cr.exptype.Integer)
  11937. this.data = Math.floor(this.data);
  11938. cr.seal(this);
  11939. };
  11940. ExpValue.prototype.is_int = function ()
  11941. {
  11942. return this.type === cr.exptype.Integer;
  11943. };
  11944. ExpValue.prototype.is_float = function ()
  11945. {
  11946. return this.type === cr.exptype.Float;
  11947. };
  11948. ExpValue.prototype.is_number = function ()
  11949. {
  11950. return this.type === cr.exptype.Integer || this.type === cr.exptype.Float;
  11951. };
  11952. ExpValue.prototype.is_string = function ()
  11953. {
  11954. return this.type === cr.exptype.String;
  11955. };
  11956. ExpValue.prototype.make_int = function ()
  11957. {
  11958. if (!this.is_int())
  11959. {
  11960. if (this.is_float())
  11961. this.data = Math.floor(this.data); // truncate float
  11962. else if (this.is_string())
  11963. this.data = parseInt(this.data, 10);
  11964. this.type = cr.exptype.Integer;
  11965. }
  11966. };
  11967. ExpValue.prototype.make_float = function ()
  11968. {
  11969. if (!this.is_float())
  11970. {
  11971. if (this.is_string())
  11972. this.data = parseFloat(this.data);
  11973. this.type = cr.exptype.Float;
  11974. }
  11975. };
  11976. ExpValue.prototype.make_string = function ()
  11977. {
  11978. if (!this.is_string())
  11979. {
  11980. this.data = this.data.toString();
  11981. this.type = cr.exptype.String;
  11982. }
  11983. };
  11984. ExpValue.prototype.set_int = function (val)
  11985. {
  11986. ;
  11987. this.type = cr.exptype.Integer;
  11988. this.data = Math.floor(val);
  11989. };
  11990. ExpValue.prototype.set_float = function (val)
  11991. {
  11992. ;
  11993. this.type = cr.exptype.Float;
  11994. this.data = val;
  11995. };
  11996. ExpValue.prototype.set_string = function (val)
  11997. {
  11998. ;
  11999. this.type = cr.exptype.String;
  12000. this.data = val;
  12001. };
  12002. ExpValue.prototype.set_any = function (val)
  12003. {
  12004. if (cr.is_number(val))
  12005. {
  12006. this.type = cr.exptype.Float;
  12007. this.data = val;
  12008. }
  12009. else if (cr.is_string(val))
  12010. {
  12011. this.type = cr.exptype.String;
  12012. this.data = val.toString();
  12013. }
  12014. else
  12015. {
  12016. this.type = cr.exptype.Integer;
  12017. this.data = 0;
  12018. }
  12019. };
  12020. cr.expvalue = ExpValue;
  12021. cr.exptype = {
  12022. Integer: 0, // emulated; no native integer support in javascript
  12023. Float: 1,
  12024. String: 2
  12025. };
  12026. }());
  12027. ;
  12028. cr.system_object = function (runtime)
  12029. {
  12030. this.runtime = runtime;
  12031. this.waits = [];
  12032. };
  12033. cr.system_object.prototype.saveToJSON = function ()
  12034. {
  12035. var o = {};
  12036. var i, len, j, lenj, p, w, t, sobj;
  12037. o["waits"] = [];
  12038. var owaits = o["waits"];
  12039. var waitobj;
  12040. for (i = 0, len = this.waits.length; i < len; i++)
  12041. {
  12042. w = this.waits[i];
  12043. waitobj = {
  12044. "t": w.time,
  12045. "st": w.signaltag,
  12046. "s": w.signalled,
  12047. "ev": w.ev.sid,
  12048. "sm": [],
  12049. "sols": {}
  12050. };
  12051. if (w.ev.actions[w.actindex])
  12052. waitobj["act"] = w.ev.actions[w.actindex].sid;
  12053. for (j = 0, lenj = w.solModifiers.length; j < lenj; j++)
  12054. waitobj["sm"].push(w.solModifiers[j].sid);
  12055. for (p in w.sols)
  12056. {
  12057. if (w.sols.hasOwnProperty(p))
  12058. {
  12059. t = this.runtime.types_by_index[parseInt(p, 10)];
  12060. ;
  12061. sobj = {
  12062. "sa": w.sols[p].sa,
  12063. "insts": []
  12064. };
  12065. for (j = 0, lenj = w.sols[p].insts.length; j < lenj; j++)
  12066. sobj["insts"].push(w.sols[p].insts[j].uid);
  12067. waitobj["sols"][t.sid.toString()] = sobj;
  12068. }
  12069. }
  12070. owaits.push(waitobj);
  12071. }
  12072. return o;
  12073. };
  12074. cr.system_object.prototype.loadFromJSON = function (o)
  12075. {
  12076. var owaits = o["waits"];
  12077. var i, len, j, lenj, p, w, addWait, e, aindex, t, savedsol, nusol, inst;
  12078. cr.clearArray(this.waits);
  12079. for (i = 0, len = owaits.length; i < len; i++)
  12080. {
  12081. w = owaits[i];
  12082. e = this.runtime.blocksBySid[w["ev"].toString()];
  12083. if (!e)
  12084. continue; // event must've gone missing
  12085. aindex = -1;
  12086. for (j = 0, lenj = e.actions.length; j < lenj; j++)
  12087. {
  12088. if (e.actions[j].sid === w["act"])
  12089. {
  12090. aindex = j;
  12091. break;
  12092. }
  12093. }
  12094. if (aindex === -1)
  12095. continue; // action must've gone missing
  12096. addWait = {};
  12097. addWait.sols = {};
  12098. addWait.solModifiers = [];
  12099. addWait.deleteme = false;
  12100. addWait.time = w["t"];
  12101. addWait.signaltag = w["st"] || "";
  12102. addWait.signalled = !!w["s"];
  12103. addWait.ev = e;
  12104. addWait.actindex = aindex;
  12105. for (j = 0, lenj = w["sm"].length; j < lenj; j++)
  12106. {
  12107. t = this.runtime.getObjectTypeBySid(w["sm"][j]);
  12108. if (t)
  12109. addWait.solModifiers.push(t);
  12110. }
  12111. for (p in w["sols"])
  12112. {
  12113. if (w["sols"].hasOwnProperty(p))
  12114. {
  12115. t = this.runtime.getObjectTypeBySid(parseInt(p, 10));
  12116. if (!t)
  12117. continue; // type must've been deleted
  12118. savedsol = w["sols"][p];
  12119. nusol = {
  12120. sa: savedsol["sa"],
  12121. insts: []
  12122. };
  12123. for (j = 0, lenj = savedsol["insts"].length; j < lenj; j++)
  12124. {
  12125. inst = this.runtime.getObjectByUID(savedsol["insts"][j]);
  12126. if (inst)
  12127. nusol.insts.push(inst);
  12128. }
  12129. addWait.sols[t.index.toString()] = nusol;
  12130. }
  12131. }
  12132. this.waits.push(addWait);
  12133. }
  12134. };
  12135. (function ()
  12136. {
  12137. var sysProto = cr.system_object.prototype;
  12138. function SysCnds() {};
  12139. SysCnds.prototype.EveryTick = function()
  12140. {
  12141. return true;
  12142. };
  12143. SysCnds.prototype.OnLayoutStart = function()
  12144. {
  12145. return true;
  12146. };
  12147. SysCnds.prototype.OnLayoutEnd = function()
  12148. {
  12149. return true;
  12150. };
  12151. SysCnds.prototype.Compare = function(x, cmp, y)
  12152. {
  12153. return cr.do_cmp(x, cmp, y);
  12154. };
  12155. SysCnds.prototype.CompareTime = function (cmp, t)
  12156. {
  12157. var elapsed = this.runtime.kahanTime.sum;
  12158. if (cmp === 0)
  12159. {
  12160. var cnd = this.runtime.getCurrentCondition();
  12161. if (!cnd.extra["CompareTime_executed"])
  12162. {
  12163. if (elapsed >= t)
  12164. {
  12165. cnd.extra["CompareTime_executed"] = true;
  12166. return true;
  12167. }
  12168. }
  12169. return false;
  12170. }
  12171. return cr.do_cmp(elapsed, cmp, t);
  12172. };
  12173. SysCnds.prototype.LayerVisible = function (layer)
  12174. {
  12175. if (!layer)
  12176. return false;
  12177. else
  12178. return layer.visible;
  12179. };
  12180. SysCnds.prototype.LayerEmpty = function (layer)
  12181. {
  12182. if (!layer)
  12183. return false;
  12184. else
  12185. return !layer.instances.length;
  12186. };
  12187. SysCnds.prototype.LayerCmpOpacity = function (layer, cmp, opacity_)
  12188. {
  12189. if (!layer)
  12190. return false;
  12191. return cr.do_cmp(layer.opacity * 100, cmp, opacity_);
  12192. };
  12193. SysCnds.prototype.Repeat = function (count)
  12194. {
  12195. var current_frame = this.runtime.getCurrentEventStack();
  12196. var current_event = current_frame.current_event;
  12197. var solModifierAfterCnds = current_frame.isModifierAfterCnds();
  12198. var current_loop = this.runtime.pushLoopStack();
  12199. var i;
  12200. if (solModifierAfterCnds)
  12201. {
  12202. for (i = 0; i < count && !current_loop.stopped; i++)
  12203. {
  12204. this.runtime.pushCopySol(current_event.solModifiers);
  12205. current_loop.index = i;
  12206. current_event.retrigger();
  12207. this.runtime.popSol(current_event.solModifiers);
  12208. }
  12209. }
  12210. else
  12211. {
  12212. for (i = 0; i < count && !current_loop.stopped; i++)
  12213. {
  12214. current_loop.index = i;
  12215. current_event.retrigger();
  12216. }
  12217. }
  12218. this.runtime.popLoopStack();
  12219. return false;
  12220. };
  12221. SysCnds.prototype.While = function (count)
  12222. {
  12223. var current_frame = this.runtime.getCurrentEventStack();
  12224. var current_event = current_frame.current_event;
  12225. var solModifierAfterCnds = current_frame.isModifierAfterCnds();
  12226. var current_loop = this.runtime.pushLoopStack();
  12227. var i;
  12228. if (solModifierAfterCnds)
  12229. {
  12230. for (i = 0; !current_loop.stopped; i++)
  12231. {
  12232. this.runtime.pushCopySol(current_event.solModifiers);
  12233. current_loop.index = i;
  12234. if (!current_event.retrigger()) // one of the other conditions returned false
  12235. current_loop.stopped = true; // break
  12236. this.runtime.popSol(current_event.solModifiers);
  12237. }
  12238. }
  12239. else
  12240. {
  12241. for (i = 0; !current_loop.stopped; i++)
  12242. {
  12243. current_loop.index = i;
  12244. if (!current_event.retrigger())
  12245. current_loop.stopped = true;
  12246. }
  12247. }
  12248. this.runtime.popLoopStack();
  12249. return false;
  12250. };
  12251. SysCnds.prototype.For = function (name, start, end)
  12252. {
  12253. var current_frame = this.runtime.getCurrentEventStack();
  12254. var current_event = current_frame.current_event;
  12255. var solModifierAfterCnds = current_frame.isModifierAfterCnds();
  12256. var current_loop = this.runtime.pushLoopStack(name);
  12257. var i;
  12258. if (end < start)
  12259. {
  12260. if (solModifierAfterCnds)
  12261. {
  12262. for (i = start; i >= end && !current_loop.stopped; --i) // inclusive to end
  12263. {
  12264. this.runtime.pushCopySol(current_event.solModifiers);
  12265. current_loop.index = i;
  12266. current_event.retrigger();
  12267. this.runtime.popSol(current_event.solModifiers);
  12268. }
  12269. }
  12270. else
  12271. {
  12272. for (i = start; i >= end && !current_loop.stopped; --i) // inclusive to end
  12273. {
  12274. current_loop.index = i;
  12275. current_event.retrigger();
  12276. }
  12277. }
  12278. }
  12279. else
  12280. {
  12281. if (solModifierAfterCnds)
  12282. {
  12283. for (i = start; i <= end && !current_loop.stopped; ++i) // inclusive to end
  12284. {
  12285. this.runtime.pushCopySol(current_event.solModifiers);
  12286. current_loop.index = i;
  12287. current_event.retrigger();
  12288. this.runtime.popSol(current_event.solModifiers);
  12289. }
  12290. }
  12291. else
  12292. {
  12293. for (i = start; i <= end && !current_loop.stopped; ++i) // inclusive to end
  12294. {
  12295. current_loop.index = i;
  12296. current_event.retrigger();
  12297. }
  12298. }
  12299. }
  12300. this.runtime.popLoopStack();
  12301. return false;
  12302. };
  12303. var foreach_instancestack = [];
  12304. var foreach_instanceptr = -1;
  12305. SysCnds.prototype.ForEach = function (obj)
  12306. {
  12307. var sol = obj.getCurrentSol();
  12308. foreach_instanceptr++;
  12309. if (foreach_instancestack.length === foreach_instanceptr)
  12310. foreach_instancestack.push([]);
  12311. var instances = foreach_instancestack[foreach_instanceptr];
  12312. cr.shallowAssignArray(instances, sol.getObjects());
  12313. var current_frame = this.runtime.getCurrentEventStack();
  12314. var current_event = current_frame.current_event;
  12315. var solModifierAfterCnds = current_frame.isModifierAfterCnds();
  12316. var current_loop = this.runtime.pushLoopStack();
  12317. var i, len, j, lenj, inst, s, sol2;
  12318. var is_contained = obj.is_contained;
  12319. if (solModifierAfterCnds)
  12320. {
  12321. for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++)
  12322. {
  12323. this.runtime.pushCopySol(current_event.solModifiers);
  12324. inst = instances[i];
  12325. sol = obj.getCurrentSol();
  12326. sol.select_all = false;
  12327. cr.clearArray(sol.instances);
  12328. sol.instances[0] = inst;
  12329. if (is_contained)
  12330. {
  12331. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  12332. {
  12333. s = inst.siblings[j];
  12334. sol2 = s.type.getCurrentSol();
  12335. sol2.select_all = false;
  12336. cr.clearArray(sol2.instances);
  12337. sol2.instances[0] = s;
  12338. }
  12339. }
  12340. current_loop.index = i;
  12341. current_event.retrigger();
  12342. this.runtime.popSol(current_event.solModifiers);
  12343. }
  12344. }
  12345. else
  12346. {
  12347. sol.select_all = false;
  12348. cr.clearArray(sol.instances);
  12349. for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++)
  12350. {
  12351. inst = instances[i];
  12352. sol.instances[0] = inst;
  12353. if (is_contained)
  12354. {
  12355. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  12356. {
  12357. s = inst.siblings[j];
  12358. sol2 = s.type.getCurrentSol();
  12359. sol2.select_all = false;
  12360. cr.clearArray(sol2.instances);
  12361. sol2.instances[0] = s;
  12362. }
  12363. }
  12364. current_loop.index = i;
  12365. current_event.retrigger();
  12366. }
  12367. }
  12368. cr.clearArray(instances);
  12369. this.runtime.popLoopStack();
  12370. foreach_instanceptr--;
  12371. return false;
  12372. };
  12373. function foreach_sortinstances(a, b)
  12374. {
  12375. var va = a.extra["c2_feo_val"];
  12376. var vb = b.extra["c2_feo_val"];
  12377. if (cr.is_number(va) && cr.is_number(vb))
  12378. return va - vb;
  12379. else
  12380. {
  12381. va = "" + va;
  12382. vb = "" + vb;
  12383. if (va < vb)
  12384. return -1;
  12385. else if (va > vb)
  12386. return 1;
  12387. else
  12388. return 0;
  12389. }
  12390. };
  12391. SysCnds.prototype.ForEachOrdered = function (obj, exp, order)
  12392. {
  12393. var sol = obj.getCurrentSol();
  12394. foreach_instanceptr++;
  12395. if (foreach_instancestack.length === foreach_instanceptr)
  12396. foreach_instancestack.push([]);
  12397. var instances = foreach_instancestack[foreach_instanceptr];
  12398. cr.shallowAssignArray(instances, sol.getObjects());
  12399. var current_frame = this.runtime.getCurrentEventStack();
  12400. var current_event = current_frame.current_event;
  12401. var current_condition = this.runtime.getCurrentCondition();
  12402. var solModifierAfterCnds = current_frame.isModifierAfterCnds();
  12403. var current_loop = this.runtime.pushLoopStack();
  12404. var i, len, j, lenj, inst, s, sol2;
  12405. for (i = 0, len = instances.length; i < len; i++)
  12406. {
  12407. instances[i].extra["c2_feo_val"] = current_condition.parameters[1].get(i);
  12408. }
  12409. instances.sort(foreach_sortinstances);
  12410. if (order === 1)
  12411. instances.reverse();
  12412. var is_contained = obj.is_contained;
  12413. if (solModifierAfterCnds)
  12414. {
  12415. for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++)
  12416. {
  12417. this.runtime.pushCopySol(current_event.solModifiers);
  12418. inst = instances[i];
  12419. sol = obj.getCurrentSol();
  12420. sol.select_all = false;
  12421. cr.clearArray(sol.instances);
  12422. sol.instances[0] = inst;
  12423. if (is_contained)
  12424. {
  12425. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  12426. {
  12427. s = inst.siblings[j];
  12428. sol2 = s.type.getCurrentSol();
  12429. sol2.select_all = false;
  12430. cr.clearArray(sol2.instances);
  12431. sol2.instances[0] = s;
  12432. }
  12433. }
  12434. current_loop.index = i;
  12435. current_event.retrigger();
  12436. this.runtime.popSol(current_event.solModifiers);
  12437. }
  12438. }
  12439. else
  12440. {
  12441. sol.select_all = false;
  12442. cr.clearArray(sol.instances);
  12443. for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++)
  12444. {
  12445. inst = instances[i];
  12446. sol.instances[0] = inst;
  12447. if (is_contained)
  12448. {
  12449. for (j = 0, lenj = inst.siblings.length; j < lenj; j++)
  12450. {
  12451. s = inst.siblings[j];
  12452. sol2 = s.type.getCurrentSol();
  12453. sol2.select_all = false;
  12454. cr.clearArray(sol2.instances);
  12455. sol2.instances[0] = s;
  12456. }
  12457. }
  12458. current_loop.index = i;
  12459. current_event.retrigger();
  12460. }
  12461. }
  12462. cr.clearArray(instances);
  12463. this.runtime.popLoopStack();
  12464. foreach_instanceptr--;
  12465. return false;
  12466. };
  12467. SysCnds.prototype.PickByComparison = function (obj_, exp_, cmp_, val_)
  12468. {
  12469. var i, len, k, inst;
  12470. if (!obj_)
  12471. return;
  12472. foreach_instanceptr++;
  12473. if (foreach_instancestack.length === foreach_instanceptr)
  12474. foreach_instancestack.push([]);
  12475. var tmp_instances = foreach_instancestack[foreach_instanceptr];
  12476. var sol = obj_.getCurrentSol();
  12477. cr.shallowAssignArray(tmp_instances, sol.getObjects());
  12478. if (sol.select_all)
  12479. cr.clearArray(sol.else_instances);
  12480. var current_condition = this.runtime.getCurrentCondition();
  12481. for (i = 0, k = 0, len = tmp_instances.length; i < len; i++)
  12482. {
  12483. inst = tmp_instances[i];
  12484. tmp_instances[k] = inst;
  12485. exp_ = current_condition.parameters[1].get(i);
  12486. val_ = current_condition.parameters[3].get(i);
  12487. if (cr.do_cmp(exp_, cmp_, val_))
  12488. {
  12489. k++;
  12490. }
  12491. else
  12492. {
  12493. sol.else_instances.push(inst);
  12494. }
  12495. }
  12496. cr.truncateArray(tmp_instances, k);
  12497. sol.select_all = false;
  12498. cr.shallowAssignArray(sol.instances, tmp_instances);
  12499. cr.clearArray(tmp_instances);
  12500. foreach_instanceptr--;
  12501. obj_.applySolToContainer();
  12502. return !!sol.instances.length;
  12503. };
  12504. SysCnds.prototype.PickByEvaluate = function (obj_, exp_)
  12505. {
  12506. var i, len, k, inst;
  12507. if (!obj_)
  12508. return;
  12509. foreach_instanceptr++;
  12510. if (foreach_instancestack.length === foreach_instanceptr)
  12511. foreach_instancestack.push([]);
  12512. var tmp_instances = foreach_instancestack[foreach_instanceptr];
  12513. var sol = obj_.getCurrentSol();
  12514. cr.shallowAssignArray(tmp_instances, sol.getObjects());
  12515. if (sol.select_all)
  12516. cr.clearArray(sol.else_instances);
  12517. var current_condition = this.runtime.getCurrentCondition();
  12518. for (i = 0, k = 0, len = tmp_instances.length; i < len; i++)
  12519. {
  12520. inst = tmp_instances[i];
  12521. tmp_instances[k] = inst;
  12522. exp_ = current_condition.parameters[1].get(i);
  12523. if (exp_)
  12524. {
  12525. k++;
  12526. }
  12527. else
  12528. {
  12529. sol.else_instances.push(inst);
  12530. }
  12531. }
  12532. cr.truncateArray(tmp_instances, k);
  12533. sol.select_all = false;
  12534. cr.shallowAssignArray(sol.instances, tmp_instances);
  12535. cr.clearArray(tmp_instances);
  12536. foreach_instanceptr--;
  12537. obj_.applySolToContainer();
  12538. return !!sol.instances.length;
  12539. };
  12540. SysCnds.prototype.TriggerOnce = function ()
  12541. {
  12542. var cndextra = this.runtime.getCurrentCondition().extra;
  12543. if (typeof cndextra["TriggerOnce_lastTick"] === "undefined")
  12544. cndextra["TriggerOnce_lastTick"] = -1;
  12545. var last_tick = cndextra["TriggerOnce_lastTick"];
  12546. var cur_tick = this.runtime.tickcount;
  12547. cndextra["TriggerOnce_lastTick"] = cur_tick;
  12548. return this.runtime.layout_first_tick || last_tick !== cur_tick - 1;
  12549. };
  12550. SysCnds.prototype.Every = function (seconds)
  12551. {
  12552. var cnd = this.runtime.getCurrentCondition();
  12553. var last_time = cnd.extra["Every_lastTime"] || 0;
  12554. var cur_time = this.runtime.kahanTime.sum;
  12555. if (typeof cnd.extra["Every_seconds"] === "undefined")
  12556. cnd.extra["Every_seconds"] = seconds;
  12557. var this_seconds = cnd.extra["Every_seconds"];
  12558. if (cur_time >= last_time + this_seconds)
  12559. {
  12560. cnd.extra["Every_lastTime"] = last_time + this_seconds;
  12561. if (cur_time >= cnd.extra["Every_lastTime"] + 0.04)
  12562. {
  12563. cnd.extra["Every_lastTime"] = cur_time;
  12564. }
  12565. cnd.extra["Every_seconds"] = seconds;
  12566. return true;
  12567. }
  12568. else if (cur_time < last_time - 0.1)
  12569. {
  12570. cnd.extra["Every_lastTime"] = cur_time;
  12571. }
  12572. return false;
  12573. };
  12574. SysCnds.prototype.PickNth = function (obj, index)
  12575. {
  12576. if (!obj)
  12577. return false;
  12578. var sol = obj.getCurrentSol();
  12579. var instances = sol.getObjects();
  12580. index = cr.floor(index);
  12581. if (index < 0 || index >= instances.length)
  12582. return false;
  12583. var inst = instances[index];
  12584. sol.pick_one(inst);
  12585. obj.applySolToContainer();
  12586. return true;
  12587. };
  12588. SysCnds.prototype.PickRandom = function (obj)
  12589. {
  12590. if (!obj)
  12591. return false;
  12592. var sol = obj.getCurrentSol();
  12593. var instances = sol.getObjects();
  12594. var index = cr.floor(Math.random() * instances.length);
  12595. if (index >= instances.length)
  12596. return false;
  12597. var inst = instances[index];
  12598. sol.pick_one(inst);
  12599. obj.applySolToContainer();
  12600. return true;
  12601. };
  12602. SysCnds.prototype.CompareVar = function (v, cmp, val)
  12603. {
  12604. return cr.do_cmp(v.getValue(), cmp, val);
  12605. };
  12606. SysCnds.prototype.IsGroupActive = function (group)
  12607. {
  12608. var g = this.runtime.groups_by_name[group.toLowerCase()];
  12609. return g && g.group_active;
  12610. };
  12611. SysCnds.prototype.IsPreview = function ()
  12612. {
  12613. return typeof cr_is_preview !== "undefined";
  12614. };
  12615. SysCnds.prototype.PickAll = function (obj)
  12616. {
  12617. if (!obj)
  12618. return false;
  12619. if (!obj.instances.length)
  12620. return false;
  12621. var sol = obj.getCurrentSol();
  12622. sol.select_all = true;
  12623. obj.applySolToContainer();
  12624. return true;
  12625. };
  12626. SysCnds.prototype.IsMobile = function ()
  12627. {
  12628. return this.runtime.isMobile;
  12629. };
  12630. SysCnds.prototype.CompareBetween = function (x, a, b)
  12631. {
  12632. return x >= a && x <= b;
  12633. };
  12634. SysCnds.prototype.Else = function ()
  12635. {
  12636. var current_frame = this.runtime.getCurrentEventStack();
  12637. if (current_frame.else_branch_ran)
  12638. return false; // another event in this else-if chain has run
  12639. else
  12640. return !current_frame.last_event_true;
  12641. /*
  12642. var current_frame = this.runtime.getCurrentEventStack();
  12643. var current_event = current_frame.current_event;
  12644. var prev_event = current_event.prev_block;
  12645. if (!prev_event)
  12646. return false;
  12647. if (prev_event.is_logical)
  12648. return !this.runtime.last_event_true;
  12649. var i, len, j, lenj, s, sol, temp, inst, any_picked = false;
  12650. for (i = 0, len = prev_event.cndReferences.length; i < len; i++)
  12651. {
  12652. s = prev_event.cndReferences[i];
  12653. sol = s.getCurrentSol();
  12654. if (sol.select_all || sol.instances.length === s.instances.length)
  12655. {
  12656. sol.select_all = false;
  12657. sol.instances.length = 0;
  12658. }
  12659. else
  12660. {
  12661. if (sol.instances.length === 1 && sol.else_instances.length === 0 && s.instances.length >= 2)
  12662. {
  12663. inst = sol.instances[0];
  12664. sol.instances.length = 0;
  12665. for (j = 0, lenj = s.instances.length; j < lenj; j++)
  12666. {
  12667. if (s.instances[j] != inst)
  12668. sol.instances.push(s.instances[j]);
  12669. }
  12670. any_picked = true;
  12671. }
  12672. else
  12673. {
  12674. temp = sol.instances;
  12675. sol.instances = sol.else_instances;
  12676. sol.else_instances = temp;
  12677. any_picked = true;
  12678. }
  12679. }
  12680. }
  12681. return any_picked;
  12682. */
  12683. };
  12684. SysCnds.prototype.OnLoadFinished = function ()
  12685. {
  12686. return true;
  12687. };
  12688. SysCnds.prototype.OnCanvasSnapshot = function ()
  12689. {
  12690. return true;
  12691. };
  12692. SysCnds.prototype.EffectsSupported = function ()
  12693. {
  12694. return !!this.runtime.glwrap;
  12695. };
  12696. SysCnds.prototype.OnSaveComplete = function ()
  12697. {
  12698. return true;
  12699. };
  12700. SysCnds.prototype.OnSaveFailed = function ()
  12701. {
  12702. return true;
  12703. };
  12704. SysCnds.prototype.OnLoadComplete = function ()
  12705. {
  12706. return true;
  12707. };
  12708. SysCnds.prototype.OnLoadFailed = function ()
  12709. {
  12710. return true;
  12711. };
  12712. SysCnds.prototype.ObjectUIDExists = function (u)
  12713. {
  12714. return !!this.runtime.getObjectByUID(u);
  12715. };
  12716. SysCnds.prototype.IsOnPlatform = function (p)
  12717. {
  12718. var rt = this.runtime;
  12719. switch (p) {
  12720. case 0: // HTML5 website
  12721. return !rt.isDomFree && !rt.isNodeWebkit && !rt.isCordova && !rt.isWinJS && !rt.isWindowsPhone8 && !rt.isBlackberry10 && !rt.isAmazonWebApp;
  12722. case 1: // iOS
  12723. return rt.isiOS;
  12724. case 2: // Android
  12725. return rt.isAndroid;
  12726. case 3: // Windows 8
  12727. return rt.isWindows8App;
  12728. case 4: // Windows Phone 8
  12729. return rt.isWindowsPhone8;
  12730. case 5: // Blackberry 10
  12731. return rt.isBlackberry10;
  12732. case 6: // Tizen
  12733. return rt.isTizen;
  12734. case 7: // CocoonJS
  12735. return rt.isCocoonJs;
  12736. case 8: // Cordova
  12737. return rt.isCordova;
  12738. case 9: // Scirra Arcade
  12739. return rt.isArcade;
  12740. case 10: // node-webkit
  12741. return rt.isNodeWebkit;
  12742. case 11: // crosswalk
  12743. return rt.isCrosswalk;
  12744. case 12: // amazon webapp
  12745. return rt.isAmazonWebApp;
  12746. case 13: // windows 10 app
  12747. return rt.isWindows10;
  12748. default: // should not be possible
  12749. return false;
  12750. }
  12751. };
  12752. var cacheRegex = null;
  12753. var lastRegex = "";
  12754. var lastFlags = "";
  12755. function getRegex(regex_, flags_)
  12756. {
  12757. if (!cacheRegex || regex_ !== lastRegex || flags_ !== lastFlags)
  12758. {
  12759. cacheRegex = new RegExp(regex_, flags_);
  12760. lastRegex = regex_;
  12761. lastFlags = flags_;
  12762. }
  12763. cacheRegex.lastIndex = 0; // reset
  12764. return cacheRegex;
  12765. };
  12766. SysCnds.prototype.RegexTest = function (str_, regex_, flags_)
  12767. {
  12768. var regex = getRegex(regex_, flags_);
  12769. return regex.test(str_);
  12770. };
  12771. var tmp_arr = [];
  12772. SysCnds.prototype.PickOverlappingPoint = function (obj_, x_, y_)
  12773. {
  12774. if (!obj_)
  12775. return false;
  12776. var sol = obj_.getCurrentSol();
  12777. var instances = sol.getObjects();
  12778. var current_event = this.runtime.getCurrentEventStack().current_event;
  12779. var orblock = current_event.orblock;
  12780. var cnd = this.runtime.getCurrentCondition();
  12781. var i, len, inst, pick;
  12782. if (sol.select_all)
  12783. {
  12784. cr.shallowAssignArray(tmp_arr, instances);
  12785. cr.clearArray(sol.else_instances);
  12786. sol.select_all = false;
  12787. cr.clearArray(sol.instances);
  12788. }
  12789. else
  12790. {
  12791. if (orblock)
  12792. {
  12793. cr.shallowAssignArray(tmp_arr, sol.else_instances);
  12794. cr.clearArray(sol.else_instances);
  12795. }
  12796. else
  12797. {
  12798. cr.shallowAssignArray(tmp_arr, instances);
  12799. cr.clearArray(sol.instances);
  12800. }
  12801. }
  12802. for (i = 0, len = tmp_arr.length; i < len; ++i)
  12803. {
  12804. inst = tmp_arr[i];
  12805. inst.update_bbox();
  12806. pick = cr.xor(inst.contains_pt(x_, y_), cnd.inverted);
  12807. if (pick)
  12808. sol.instances.push(inst);
  12809. else
  12810. sol.else_instances.push(inst);
  12811. }
  12812. obj_.applySolToContainer();
  12813. return cr.xor(!!sol.instances.length, cnd.inverted);
  12814. };
  12815. SysCnds.prototype.IsNaN = function (n)
  12816. {
  12817. return !!isNaN(n);
  12818. };
  12819. SysCnds.prototype.AngleWithin = function (a1, within, a2)
  12820. {
  12821. return cr.angleDiff(cr.to_radians(a1), cr.to_radians(a2)) <= cr.to_radians(within);
  12822. };
  12823. SysCnds.prototype.IsClockwiseFrom = function (a1, a2)
  12824. {
  12825. return cr.angleClockwise(cr.to_radians(a1), cr.to_radians(a2));
  12826. };
  12827. SysCnds.prototype.IsBetweenAngles = function (a, la, ua)
  12828. {
  12829. var angle = cr.to_clamped_radians(a);
  12830. var lower = cr.to_clamped_radians(la);
  12831. var upper = cr.to_clamped_radians(ua);
  12832. var obtuse = (!cr.angleClockwise(upper, lower));
  12833. if (obtuse)
  12834. return !(!cr.angleClockwise(angle, lower) && cr.angleClockwise(angle, upper));
  12835. else
  12836. return cr.angleClockwise(angle, lower) && !cr.angleClockwise(angle, upper);
  12837. };
  12838. SysCnds.prototype.IsValueType = function (x, t)
  12839. {
  12840. if (typeof x === "number")
  12841. return t === 0;
  12842. else // string
  12843. return t === 1;
  12844. };
  12845. sysProto.cnds = new SysCnds();
  12846. function SysActs() {};
  12847. SysActs.prototype.GoToLayout = function (to)
  12848. {
  12849. if (this.runtime.isloading)
  12850. return; // cannot change layout while loading on loader layout
  12851. if (this.runtime.changelayout)
  12852. return; // already changing to a different layout
  12853. ;
  12854. this.runtime.changelayout = to;
  12855. };
  12856. SysActs.prototype.NextPrevLayout = function (prev)
  12857. {
  12858. if (this.runtime.isloading)
  12859. return; // cannot change layout while loading on loader layout
  12860. if (this.runtime.changelayout)
  12861. return; // already changing to a different layout
  12862. var index = this.runtime.layouts_by_index.indexOf(this.runtime.running_layout);
  12863. if (prev && index === 0)
  12864. return; // cannot go to previous layout from first layout
  12865. if (!prev && index === this.runtime.layouts_by_index.length - 1)
  12866. return; // cannot go to next layout from last layout
  12867. var to = this.runtime.layouts_by_index[index + (prev ? -1 : 1)];
  12868. ;
  12869. this.runtime.changelayout = to;
  12870. };
  12871. SysActs.prototype.CreateObject = function (obj, layer, x, y)
  12872. {
  12873. if (!layer || !obj)
  12874. return;
  12875. var inst = this.runtime.createInstance(obj, layer, x, y);
  12876. if (!inst)
  12877. return;
  12878. this.runtime.isInOnDestroy++;
  12879. var i, len, s;
  12880. this.runtime.trigger(Object.getPrototypeOf(obj.plugin).cnds.OnCreated, inst);
  12881. if (inst.is_contained)
  12882. {
  12883. for (i = 0, len = inst.siblings.length; i < len; i++)
  12884. {
  12885. s = inst.siblings[i];
  12886. this.runtime.trigger(Object.getPrototypeOf(s.type.plugin).cnds.OnCreated, s);
  12887. }
  12888. }
  12889. this.runtime.isInOnDestroy--;
  12890. var sol = obj.getCurrentSol();
  12891. sol.select_all = false;
  12892. cr.clearArray(sol.instances);
  12893. sol.instances[0] = inst;
  12894. if (inst.is_contained)
  12895. {
  12896. for (i = 0, len = inst.siblings.length; i < len; i++)
  12897. {
  12898. s = inst.siblings[i];
  12899. sol = s.type.getCurrentSol();
  12900. sol.select_all = false;
  12901. cr.clearArray(sol.instances);
  12902. sol.instances[0] = s;
  12903. }
  12904. }
  12905. };
  12906. SysActs.prototype.SetLayerVisible = function (layer, visible_)
  12907. {
  12908. if (!layer)
  12909. return;
  12910. if (layer.visible !== visible_)
  12911. {
  12912. layer.visible = visible_;
  12913. this.runtime.redraw = true;
  12914. }
  12915. };
  12916. SysActs.prototype.SetLayerOpacity = function (layer, opacity_)
  12917. {
  12918. if (!layer)
  12919. return;
  12920. opacity_ = cr.clamp(opacity_ / 100, 0, 1);
  12921. if (layer.opacity !== opacity_)
  12922. {
  12923. layer.opacity = opacity_;
  12924. this.runtime.redraw = true;
  12925. }
  12926. };
  12927. SysActs.prototype.SetLayerScaleRate = function (layer, sr)
  12928. {
  12929. if (!layer)
  12930. return;
  12931. if (layer.zoomRate !== sr)
  12932. {
  12933. layer.zoomRate = sr;
  12934. this.runtime.redraw = true;
  12935. }
  12936. };
  12937. SysActs.prototype.SetLayerForceOwnTexture = function (layer, f)
  12938. {
  12939. if (!layer)
  12940. return;
  12941. f = !!f;
  12942. if (layer.forceOwnTexture !== f)
  12943. {
  12944. layer.forceOwnTexture = f;
  12945. this.runtime.redraw = true;
  12946. }
  12947. };
  12948. SysActs.prototype.SetLayoutScale = function (s)
  12949. {
  12950. if (!this.runtime.running_layout)
  12951. return;
  12952. if (this.runtime.running_layout.scale !== s)
  12953. {
  12954. this.runtime.running_layout.scale = s;
  12955. this.runtime.running_layout.boundScrolling();
  12956. this.runtime.redraw = true;
  12957. }
  12958. };
  12959. SysActs.prototype.ScrollX = function(x)
  12960. {
  12961. this.runtime.running_layout.scrollToX(x);
  12962. };
  12963. SysActs.prototype.ScrollY = function(y)
  12964. {
  12965. this.runtime.running_layout.scrollToY(y);
  12966. };
  12967. SysActs.prototype.Scroll = function(x, y)
  12968. {
  12969. this.runtime.running_layout.scrollToX(x);
  12970. this.runtime.running_layout.scrollToY(y);
  12971. };
  12972. SysActs.prototype.ScrollToObject = function(obj)
  12973. {
  12974. var inst = obj.getFirstPicked();
  12975. if (inst)
  12976. {
  12977. this.runtime.running_layout.scrollToX(inst.x);
  12978. this.runtime.running_layout.scrollToY(inst.y);
  12979. }
  12980. };
  12981. SysActs.prototype.SetVar = function(v, x)
  12982. {
  12983. ;
  12984. if (v.vartype === 0)
  12985. {
  12986. if (cr.is_number(x))
  12987. v.setValue(x);
  12988. else
  12989. v.setValue(parseFloat(x));
  12990. }
  12991. else if (v.vartype === 1)
  12992. v.setValue(x.toString());
  12993. };
  12994. SysActs.prototype.AddVar = function(v, x)
  12995. {
  12996. ;
  12997. if (v.vartype === 0)
  12998. {
  12999. if (cr.is_number(x))
  13000. v.setValue(v.getValue() + x);
  13001. else
  13002. v.setValue(v.getValue() + parseFloat(x));
  13003. }
  13004. else if (v.vartype === 1)
  13005. v.setValue(v.getValue() + x.toString());
  13006. };
  13007. SysActs.prototype.SubVar = function(v, x)
  13008. {
  13009. ;
  13010. if (v.vartype === 0)
  13011. {
  13012. if (cr.is_number(x))
  13013. v.setValue(v.getValue() - x);
  13014. else
  13015. v.setValue(v.getValue() - parseFloat(x));
  13016. }
  13017. };
  13018. SysActs.prototype.SetGroupActive = function (group, active)
  13019. {
  13020. var g = this.runtime.groups_by_name[group.toLowerCase()];
  13021. if (!g)
  13022. return;
  13023. switch (active) {
  13024. case 0:
  13025. g.setGroupActive(false);
  13026. break;
  13027. case 1:
  13028. g.setGroupActive(true);
  13029. break;
  13030. case 2:
  13031. g.setGroupActive(!g.group_active);
  13032. break;
  13033. }
  13034. };
  13035. SysActs.prototype.SetTimescale = function (ts_)
  13036. {
  13037. var ts = ts_;
  13038. if (ts < 0)
  13039. ts = 0;
  13040. this.runtime.timescale = ts;
  13041. };
  13042. SysActs.prototype.SetObjectTimescale = function (obj, ts_)
  13043. {
  13044. var ts = ts_;
  13045. if (ts < 0)
  13046. ts = 0;
  13047. if (!obj)
  13048. return;
  13049. var sol = obj.getCurrentSol();
  13050. var instances = sol.getObjects();
  13051. var i, len;
  13052. for (i = 0, len = instances.length; i < len; i++)
  13053. {
  13054. instances[i].my_timescale = ts;
  13055. }
  13056. };
  13057. SysActs.prototype.RestoreObjectTimescale = function (obj)
  13058. {
  13059. if (!obj)
  13060. return false;
  13061. var sol = obj.getCurrentSol();
  13062. var instances = sol.getObjects();
  13063. var i, len;
  13064. for (i = 0, len = instances.length; i < len; i++)
  13065. {
  13066. instances[i].my_timescale = -1.0;
  13067. }
  13068. };
  13069. var waitobjrecycle = [];
  13070. function allocWaitObject()
  13071. {
  13072. var w;
  13073. if (waitobjrecycle.length)
  13074. w = waitobjrecycle.pop();
  13075. else
  13076. {
  13077. w = {};
  13078. w.sols = {};
  13079. w.solModifiers = [];
  13080. }
  13081. w.deleteme = false;
  13082. return w;
  13083. };
  13084. function freeWaitObject(w)
  13085. {
  13086. cr.wipe(w.sols);
  13087. cr.clearArray(w.solModifiers);
  13088. waitobjrecycle.push(w);
  13089. };
  13090. var solstateobjects = [];
  13091. function allocSolStateObject()
  13092. {
  13093. var s;
  13094. if (solstateobjects.length)
  13095. s = solstateobjects.pop();
  13096. else
  13097. {
  13098. s = {};
  13099. s.insts = [];
  13100. }
  13101. s.sa = false;
  13102. return s;
  13103. };
  13104. function freeSolStateObject(s)
  13105. {
  13106. cr.clearArray(s.insts);
  13107. solstateobjects.push(s);
  13108. };
  13109. SysActs.prototype.Wait = function (seconds)
  13110. {
  13111. if (seconds < 0)
  13112. return;
  13113. var i, len, s, t, ss;
  13114. var evinfo = this.runtime.getCurrentEventStack();
  13115. var waitobj = allocWaitObject();
  13116. waitobj.time = this.runtime.kahanTime.sum + seconds;
  13117. waitobj.signaltag = "";
  13118. waitobj.signalled = false;
  13119. waitobj.ev = evinfo.current_event;
  13120. waitobj.actindex = evinfo.actindex + 1; // pointing at next action
  13121. for (i = 0, len = this.runtime.types_by_index.length; i < len; i++)
  13122. {
  13123. t = this.runtime.types_by_index[i];
  13124. s = t.getCurrentSol();
  13125. if (s.select_all && evinfo.current_event.solModifiers.indexOf(t) === -1)
  13126. continue;
  13127. waitobj.solModifiers.push(t);
  13128. ss = allocSolStateObject();
  13129. ss.sa = s.select_all;
  13130. cr.shallowAssignArray(ss.insts, s.instances);
  13131. waitobj.sols[i.toString()] = ss;
  13132. }
  13133. this.waits.push(waitobj);
  13134. return true;
  13135. };
  13136. SysActs.prototype.WaitForSignal = function (tag)
  13137. {
  13138. var i, len, s, t, ss;
  13139. var evinfo = this.runtime.getCurrentEventStack();
  13140. var waitobj = allocWaitObject();
  13141. waitobj.time = -1;
  13142. waitobj.signaltag = tag.toLowerCase();
  13143. waitobj.signalled = false;
  13144. waitobj.ev = evinfo.current_event;
  13145. waitobj.actindex = evinfo.actindex + 1; // pointing at next action
  13146. for (i = 0, len = this.runtime.types_by_index.length; i < len; i++)
  13147. {
  13148. t = this.runtime.types_by_index[i];
  13149. s = t.getCurrentSol();
  13150. if (s.select_all && evinfo.current_event.solModifiers.indexOf(t) === -1)
  13151. continue;
  13152. waitobj.solModifiers.push(t);
  13153. ss = allocSolStateObject();
  13154. ss.sa = s.select_all;
  13155. cr.shallowAssignArray(ss.insts, s.instances);
  13156. waitobj.sols[i.toString()] = ss;
  13157. }
  13158. this.waits.push(waitobj);
  13159. return true;
  13160. };
  13161. SysActs.prototype.Signal = function (tag)
  13162. {
  13163. var lowertag = tag.toLowerCase();
  13164. var i, len, w;
  13165. for (i = 0, len = this.waits.length; i < len; ++i)
  13166. {
  13167. w = this.waits[i];
  13168. if (w.time !== -1)
  13169. continue; // timer wait, ignore
  13170. if (w.signaltag === lowertag) // waiting for this signal
  13171. w.signalled = true; // will run on next check
  13172. }
  13173. };
  13174. SysActs.prototype.SetLayerScale = function (layer, scale)
  13175. {
  13176. if (!layer)
  13177. return;
  13178. if (layer.scale === scale)
  13179. return;
  13180. layer.scale = scale;
  13181. this.runtime.redraw = true;
  13182. };
  13183. SysActs.prototype.ResetGlobals = function ()
  13184. {
  13185. var i, len, g;
  13186. for (i = 0, len = this.runtime.all_global_vars.length; i < len; i++)
  13187. {
  13188. g = this.runtime.all_global_vars[i];
  13189. g.data = g.initial;
  13190. }
  13191. };
  13192. SysActs.prototype.SetLayoutAngle = function (a)
  13193. {
  13194. a = cr.to_radians(a);
  13195. a = cr.clamp_angle(a);
  13196. if (this.runtime.running_layout)
  13197. {
  13198. if (this.runtime.running_layout.angle !== a)
  13199. {
  13200. this.runtime.running_layout.angle = a;
  13201. this.runtime.redraw = true;
  13202. }
  13203. }
  13204. };
  13205. SysActs.prototype.SetLayerAngle = function (layer, a)
  13206. {
  13207. if (!layer)
  13208. return;
  13209. a = cr.to_radians(a);
  13210. a = cr.clamp_angle(a);
  13211. if (layer.angle === a)
  13212. return;
  13213. layer.angle = a;
  13214. this.runtime.redraw = true;
  13215. };
  13216. SysActs.prototype.SetLayerParallax = function (layer, px, py)
  13217. {
  13218. if (!layer)
  13219. return;
  13220. if (layer.parallaxX === px / 100 && layer.parallaxY === py / 100)
  13221. return;
  13222. layer.parallaxX = px / 100;
  13223. layer.parallaxY = py / 100;
  13224. if (layer.parallaxX !== 1 || layer.parallaxY !== 1)
  13225. {
  13226. var i, len, instances = layer.instances;
  13227. for (i = 0, len = instances.length; i < len; ++i)
  13228. {
  13229. instances[i].type.any_instance_parallaxed = true;
  13230. }
  13231. }
  13232. this.runtime.redraw = true;
  13233. };
  13234. SysActs.prototype.SetLayerBackground = function (layer, c)
  13235. {
  13236. if (!layer)
  13237. return;
  13238. var r = cr.GetRValue(c);
  13239. var g = cr.GetGValue(c);
  13240. var b = cr.GetBValue(c);
  13241. if (layer.background_color[0] === r && layer.background_color[1] === g && layer.background_color[2] === b)
  13242. return;
  13243. layer.background_color[0] = r;
  13244. layer.background_color[1] = g;
  13245. layer.background_color[2] = b;
  13246. this.runtime.redraw = true;
  13247. };
  13248. SysActs.prototype.SetLayerTransparent = function (layer, t)
  13249. {
  13250. if (!layer)
  13251. return;
  13252. if (!!t === !!layer.transparent)
  13253. return;
  13254. layer.transparent = !!t;
  13255. this.runtime.redraw = true;
  13256. };
  13257. SysActs.prototype.SetLayerBlendMode = function (layer, bm)
  13258. {
  13259. if (!layer)
  13260. return;
  13261. if (layer.blend_mode === bm)
  13262. return;
  13263. layer.blend_mode = bm;
  13264. layer.compositeOp = cr.effectToCompositeOp(layer.blend_mode);
  13265. if (this.runtime.gl)
  13266. cr.setGLBlend(layer, layer.blend_mode, this.runtime.gl);
  13267. this.runtime.redraw = true;
  13268. };
  13269. SysActs.prototype.StopLoop = function ()
  13270. {
  13271. if (this.runtime.loop_stack_index < 0)
  13272. return; // no loop currently running
  13273. this.runtime.getCurrentLoop().stopped = true;
  13274. };
  13275. SysActs.prototype.GoToLayoutByName = function (layoutname)
  13276. {
  13277. if (this.runtime.isloading)
  13278. return; // cannot change layout while loading on loader layout
  13279. if (this.runtime.changelayout)
  13280. return; // already changing to different layout
  13281. ;
  13282. var l;
  13283. for (l in this.runtime.layouts)
  13284. {
  13285. if (this.runtime.layouts.hasOwnProperty(l) && cr.equals_nocase(l, layoutname))
  13286. {
  13287. this.runtime.changelayout = this.runtime.layouts[l];
  13288. return;
  13289. }
  13290. }
  13291. };
  13292. SysActs.prototype.RestartLayout = function (layoutname)
  13293. {
  13294. if (this.runtime.isloading)
  13295. return; // cannot restart loader layouts
  13296. if (this.runtime.changelayout)
  13297. return; // already changing to a different layout
  13298. ;
  13299. if (!this.runtime.running_layout)
  13300. return;
  13301. this.runtime.changelayout = this.runtime.running_layout;
  13302. var i, len, g;
  13303. for (i = 0, len = this.runtime.allGroups.length; i < len; i++)
  13304. {
  13305. g = this.runtime.allGroups[i];
  13306. g.setGroupActive(g.initially_activated);
  13307. }
  13308. };
  13309. SysActs.prototype.SnapshotCanvas = function (format_, quality_)
  13310. {
  13311. this.runtime.doCanvasSnapshot(format_ === 0 ? "image/png" : "image/jpeg", quality_ / 100);
  13312. };
  13313. SysActs.prototype.SetCanvasSize = function (w, h)
  13314. {
  13315. if (w <= 0 || h <= 0)
  13316. return;
  13317. var mode = this.runtime.fullscreen_mode;
  13318. var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || !!document["msFullscreenElement"] || document["fullScreen"] || this.runtime.isNodeFullscreen);
  13319. if (isfullscreen && this.runtime.fullscreen_scaling > 0)
  13320. mode = this.runtime.fullscreen_scaling;
  13321. if (mode === 0)
  13322. {
  13323. this.runtime["setSize"](w, h, true);
  13324. }
  13325. else
  13326. {
  13327. this.runtime.original_width = w;
  13328. this.runtime.original_height = h;
  13329. this.runtime["setSize"](this.runtime.lastWindowWidth, this.runtime.lastWindowHeight, true);
  13330. }
  13331. };
  13332. SysActs.prototype.SetLayoutEffectEnabled = function (enable_, effectname_)
  13333. {
  13334. if (!this.runtime.running_layout || !this.runtime.glwrap)
  13335. return;
  13336. var et = this.runtime.running_layout.getEffectByName(effectname_);
  13337. if (!et)
  13338. return; // effect name not found
  13339. var enable = (enable_ === 1);
  13340. if (et.active == enable)
  13341. return; // no change
  13342. et.active = enable;
  13343. this.runtime.running_layout.updateActiveEffects();
  13344. this.runtime.redraw = true;
  13345. };
  13346. SysActs.prototype.SetLayerEffectEnabled = function (layer, enable_, effectname_)
  13347. {
  13348. if (!layer || !this.runtime.glwrap)
  13349. return;
  13350. var et = layer.getEffectByName(effectname_);
  13351. if (!et)
  13352. return; // effect name not found
  13353. var enable = (enable_ === 1);
  13354. if (et.active == enable)
  13355. return; // no change
  13356. et.active = enable;
  13357. layer.updateActiveEffects();
  13358. this.runtime.redraw = true;
  13359. };
  13360. SysActs.prototype.SetLayoutEffectParam = function (effectname_, index_, value_)
  13361. {
  13362. if (!this.runtime.running_layout || !this.runtime.glwrap)
  13363. return;
  13364. var et = this.runtime.running_layout.getEffectByName(effectname_);
  13365. if (!et)
  13366. return; // effect name not found
  13367. var params = this.runtime.running_layout.effect_params[et.index];
  13368. index_ = Math.floor(index_);
  13369. if (index_ < 0 || index_ >= params.length)
  13370. return; // effect index out of bounds
  13371. if (this.runtime.glwrap.getProgramParameterType(et.shaderindex, index_) === 1)
  13372. value_ /= 100.0;
  13373. if (params[index_] === value_)
  13374. return; // no change
  13375. params[index_] = value_;
  13376. if (et.active)
  13377. this.runtime.redraw = true;
  13378. };
  13379. SysActs.prototype.SetLayerEffectParam = function (layer, effectname_, index_, value_)
  13380. {
  13381. if (!layer || !this.runtime.glwrap)
  13382. return;
  13383. var et = layer.getEffectByName(effectname_);
  13384. if (!et)
  13385. return; // effect name not found
  13386. var params = layer.effect_params[et.index];
  13387. index_ = Math.floor(index_);
  13388. if (index_ < 0 || index_ >= params.length)
  13389. return; // effect index out of bounds
  13390. if (this.runtime.glwrap.getProgramParameterType(et.shaderindex, index_) === 1)
  13391. value_ /= 100.0;
  13392. if (params[index_] === value_)
  13393. return; // no change
  13394. params[index_] = value_;
  13395. if (et.active)
  13396. this.runtime.redraw = true;
  13397. };
  13398. SysActs.prototype.SaveState = function (slot_)
  13399. {
  13400. this.runtime.saveToSlot = slot_;
  13401. };
  13402. SysActs.prototype.LoadState = function (slot_)
  13403. {
  13404. this.runtime.loadFromSlot = slot_;
  13405. };
  13406. SysActs.prototype.LoadStateJSON = function (jsonstr_)
  13407. {
  13408. this.runtime.loadFromJson = jsonstr_;
  13409. };
  13410. SysActs.prototype.SetHalfFramerateMode = function (set_)
  13411. {
  13412. this.runtime.halfFramerateMode = (set_ !== 0);
  13413. };
  13414. SysActs.prototype.SetFullscreenQuality = function (q)
  13415. {
  13416. var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || !!document["msFullscreenElement"] || document["fullScreen"] || this.isNodeFullscreen);
  13417. if (!isfullscreen && this.runtime.fullscreen_mode === 0)
  13418. return;
  13419. this.runtime.wantFullscreenScalingQuality = (q !== 0);
  13420. this.runtime["setSize"](this.runtime.lastWindowWidth, this.runtime.lastWindowHeight, true);
  13421. };
  13422. SysActs.prototype.ResetPersisted = function ()
  13423. {
  13424. var i, len;
  13425. for (i = 0, len = this.runtime.layouts_by_index.length; i < len; ++i)
  13426. {
  13427. this.runtime.layouts_by_index[i].persist_data = {};
  13428. this.runtime.layouts_by_index[i].first_visit = true;
  13429. }
  13430. };
  13431. SysActs.prototype.RecreateInitialObjects = function (obj, x1, y1, x2, y2)
  13432. {
  13433. if (!obj)
  13434. return;
  13435. this.runtime.running_layout.recreateInitialObjects(obj, x1, y1, x2, y2);
  13436. };
  13437. SysActs.prototype.SetPixelRounding = function (m)
  13438. {
  13439. this.runtime.pixel_rounding = (m !== 0);
  13440. this.runtime.redraw = true;
  13441. };
  13442. SysActs.prototype.SetMinimumFramerate = function (f)
  13443. {
  13444. if (f < 1)
  13445. f = 1;
  13446. if (f > 120)
  13447. f = 120;
  13448. this.runtime.minimumFramerate = f;
  13449. };
  13450. function SortZOrderList(a, b)
  13451. {
  13452. var layerA = a[0];
  13453. var layerB = b[0];
  13454. var diff = layerA - layerB;
  13455. if (diff !== 0)
  13456. return diff;
  13457. var indexA = a[1];
  13458. var indexB = b[1];
  13459. return indexA - indexB;
  13460. };
  13461. function SortInstancesByValue(a, b)
  13462. {
  13463. return a[1] - b[1];
  13464. };
  13465. SysActs.prototype.SortZOrderByInstVar = function (obj, iv)
  13466. {
  13467. if (!obj)
  13468. return;
  13469. var i, len, inst, value, r, layer, toZ;
  13470. var sol = obj.getCurrentSol();
  13471. var pickedInstances = sol.getObjects();
  13472. var zOrderList = [];
  13473. var instValues = [];
  13474. var layout = this.runtime.running_layout;
  13475. var isFamily = obj.is_family;
  13476. var familyIndex = obj.family_index;
  13477. for (i = 0, len = pickedInstances.length; i < len; ++i)
  13478. {
  13479. inst = pickedInstances[i];
  13480. if (!inst.layer)
  13481. continue; // not a world instance
  13482. if (isFamily)
  13483. value = inst.instance_vars[iv + inst.type.family_var_map[familyIndex]];
  13484. else
  13485. value = inst.instance_vars[iv];
  13486. zOrderList.push([
  13487. inst.layer.index,
  13488. inst.get_zindex()
  13489. ]);
  13490. instValues.push([
  13491. inst,
  13492. value
  13493. ]);
  13494. }
  13495. if (!zOrderList.length)
  13496. return; // no instances were world instances
  13497. zOrderList.sort(SortZOrderList);
  13498. instValues.sort(SortInstancesByValue);
  13499. for (i = 0, len = zOrderList.length; i < len; ++i)
  13500. {
  13501. inst = instValues[i][0]; // instance in the order we want
  13502. layer = layout.layers[zOrderList[i][0]]; // layer to put it on
  13503. toZ = zOrderList[i][1]; // Z index on that layer to put it
  13504. if (layer.instances[toZ] !== inst) // not already got this instance there
  13505. {
  13506. layer.instances[toZ] = inst; // update instance
  13507. inst.layer = layer; // update instance's layer reference (could have changed)
  13508. layer.setZIndicesStaleFrom(toZ); // mark Z indices stale from this point since they have changed
  13509. }
  13510. }
  13511. };
  13512. sysProto.acts = new SysActs();
  13513. function SysExps() {};
  13514. SysExps.prototype["int"] = function(ret, x)
  13515. {
  13516. if (cr.is_string(x))
  13517. {
  13518. ret.set_int(parseInt(x, 10));
  13519. if (isNaN(ret.data))
  13520. ret.data = 0;
  13521. }
  13522. else
  13523. ret.set_int(x);
  13524. };
  13525. SysExps.prototype["float"] = function(ret, x)
  13526. {
  13527. if (cr.is_string(x))
  13528. {
  13529. ret.set_float(parseFloat(x));
  13530. if (isNaN(ret.data))
  13531. ret.data = 0;
  13532. }
  13533. else
  13534. ret.set_float(x);
  13535. };
  13536. SysExps.prototype.str = function(ret, x)
  13537. {
  13538. if (cr.is_string(x))
  13539. ret.set_string(x);
  13540. else
  13541. ret.set_string(x.toString());
  13542. };
  13543. SysExps.prototype.len = function(ret, x)
  13544. {
  13545. ret.set_int(x.length || 0);
  13546. };
  13547. SysExps.prototype.random = function (ret, a, b)
  13548. {
  13549. if (b === undefined)
  13550. {
  13551. ret.set_float(Math.random() * a);
  13552. }
  13553. else
  13554. {
  13555. ret.set_float(Math.random() * (b - a) + a);
  13556. }
  13557. };
  13558. SysExps.prototype.sqrt = function(ret, x)
  13559. {
  13560. ret.set_float(Math.sqrt(x));
  13561. };
  13562. SysExps.prototype.abs = function(ret, x)
  13563. {
  13564. ret.set_float(Math.abs(x));
  13565. };
  13566. SysExps.prototype.round = function(ret, x)
  13567. {
  13568. ret.set_int(Math.round(x));
  13569. };
  13570. SysExps.prototype.floor = function(ret, x)
  13571. {
  13572. ret.set_int(Math.floor(x));
  13573. };
  13574. SysExps.prototype.ceil = function(ret, x)
  13575. {
  13576. ret.set_int(Math.ceil(x));
  13577. };
  13578. SysExps.prototype.sin = function(ret, x)
  13579. {
  13580. ret.set_float(Math.sin(cr.to_radians(x)));
  13581. };
  13582. SysExps.prototype.cos = function(ret, x)
  13583. {
  13584. ret.set_float(Math.cos(cr.to_radians(x)));
  13585. };
  13586. SysExps.prototype.tan = function(ret, x)
  13587. {
  13588. ret.set_float(Math.tan(cr.to_radians(x)));
  13589. };
  13590. SysExps.prototype.asin = function(ret, x)
  13591. {
  13592. ret.set_float(cr.to_degrees(Math.asin(x)));
  13593. };
  13594. SysExps.prototype.acos = function(ret, x)
  13595. {
  13596. ret.set_float(cr.to_degrees(Math.acos(x)));
  13597. };
  13598. SysExps.prototype.atan = function(ret, x)
  13599. {
  13600. ret.set_float(cr.to_degrees(Math.atan(x)));
  13601. };
  13602. SysExps.prototype.exp = function(ret, x)
  13603. {
  13604. ret.set_float(Math.exp(x));
  13605. };
  13606. SysExps.prototype.ln = function(ret, x)
  13607. {
  13608. ret.set_float(Math.log(x));
  13609. };
  13610. SysExps.prototype.log10 = function(ret, x)
  13611. {
  13612. ret.set_float(Math.log(x) / Math.LN10);
  13613. };
  13614. SysExps.prototype.max = function(ret)
  13615. {
  13616. var max_ = arguments[1];
  13617. if (typeof max_ !== "number")
  13618. max_ = 0;
  13619. var i, len, a;
  13620. for (i = 2, len = arguments.length; i < len; i++)
  13621. {
  13622. a = arguments[i];
  13623. if (typeof a !== "number")
  13624. continue; // ignore non-numeric types
  13625. if (max_ < a)
  13626. max_ = a;
  13627. }
  13628. ret.set_float(max_);
  13629. };
  13630. SysExps.prototype.min = function(ret)
  13631. {
  13632. var min_ = arguments[1];
  13633. if (typeof min_ !== "number")
  13634. min_ = 0;
  13635. var i, len, a;
  13636. for (i = 2, len = arguments.length; i < len; i++)
  13637. {
  13638. a = arguments[i];
  13639. if (typeof a !== "number")
  13640. continue; // ignore non-numeric types
  13641. if (min_ > a)
  13642. min_ = a;
  13643. }
  13644. ret.set_float(min_);
  13645. };
  13646. SysExps.prototype.dt = function(ret)
  13647. {
  13648. ret.set_float(this.runtime.dt);
  13649. };
  13650. SysExps.prototype.timescale = function(ret)
  13651. {
  13652. ret.set_float(this.runtime.timescale);
  13653. };
  13654. SysExps.prototype.wallclocktime = function(ret)
  13655. {
  13656. ret.set_float((Date.now() - this.runtime.start_time) / 1000.0);
  13657. };
  13658. SysExps.prototype.time = function(ret)
  13659. {
  13660. ret.set_float(this.runtime.kahanTime.sum);
  13661. };
  13662. SysExps.prototype.tickcount = function(ret)
  13663. {
  13664. ret.set_int(this.runtime.tickcount);
  13665. };
  13666. SysExps.prototype.objectcount = function(ret)
  13667. {
  13668. ret.set_int(this.runtime.objectcount);
  13669. };
  13670. SysExps.prototype.fps = function(ret)
  13671. {
  13672. ret.set_int(this.runtime.fps);
  13673. };
  13674. SysExps.prototype.loopindex = function(ret, name_)
  13675. {
  13676. var loop, i, len;
  13677. if (!this.runtime.loop_stack.length)
  13678. {
  13679. ret.set_int(0);
  13680. return;
  13681. }
  13682. if (name_)
  13683. {
  13684. for (i = this.runtime.loop_stack_index; i >= 0; --i)
  13685. {
  13686. loop = this.runtime.loop_stack[i];
  13687. if (loop.name === name_)
  13688. {
  13689. ret.set_int(loop.index);
  13690. return;
  13691. }
  13692. }
  13693. ret.set_int(0);
  13694. }
  13695. else
  13696. {
  13697. loop = this.runtime.getCurrentLoop();
  13698. ret.set_int(loop ? loop.index : -1);
  13699. }
  13700. };
  13701. SysExps.prototype.distance = function(ret, x1, y1, x2, y2)
  13702. {
  13703. ret.set_float(cr.distanceTo(x1, y1, x2, y2));
  13704. };
  13705. SysExps.prototype.angle = function(ret, x1, y1, x2, y2)
  13706. {
  13707. ret.set_float(cr.to_degrees(cr.angleTo(x1, y1, x2, y2)));
  13708. };
  13709. SysExps.prototype.scrollx = function(ret)
  13710. {
  13711. ret.set_float(this.runtime.running_layout.scrollX);
  13712. };
  13713. SysExps.prototype.scrolly = function(ret)
  13714. {
  13715. ret.set_float(this.runtime.running_layout.scrollY);
  13716. };
  13717. SysExps.prototype.newline = function(ret)
  13718. {
  13719. ret.set_string("\n");
  13720. };
  13721. SysExps.prototype.lerp = function(ret, a, b, x)
  13722. {
  13723. ret.set_float(cr.lerp(a, b, x));
  13724. };
  13725. SysExps.prototype.qarp = function(ret, a, b, c, x)
  13726. {
  13727. ret.set_float(cr.qarp(a, b, c, x));
  13728. };
  13729. SysExps.prototype.cubic = function(ret, a, b, c, d, x)
  13730. {
  13731. ret.set_float(cr.cubic(a, b, c, d, x));
  13732. };
  13733. SysExps.prototype.cosp = function(ret, a, b, x)
  13734. {
  13735. ret.set_float(cr.cosp(a, b, x));
  13736. };
  13737. SysExps.prototype.windowwidth = function(ret)
  13738. {
  13739. ret.set_int(this.runtime.width);
  13740. };
  13741. SysExps.prototype.windowheight = function(ret)
  13742. {
  13743. ret.set_int(this.runtime.height);
  13744. };
  13745. SysExps.prototype.uppercase = function(ret, str)
  13746. {
  13747. ret.set_string(cr.is_string(str) ? str.toUpperCase() : "");
  13748. };
  13749. SysExps.prototype.lowercase = function(ret, str)
  13750. {
  13751. ret.set_string(cr.is_string(str) ? str.toLowerCase() : "");
  13752. };
  13753. SysExps.prototype.clamp = function(ret, x, l, u)
  13754. {
  13755. if (x < l)
  13756. ret.set_float(l);
  13757. else if (x > u)
  13758. ret.set_float(u);
  13759. else
  13760. ret.set_float(x);
  13761. };
  13762. SysExps.prototype.layerscale = function (ret, layerparam)
  13763. {
  13764. var layer = this.runtime.getLayer(layerparam);
  13765. if (!layer)
  13766. ret.set_float(0);
  13767. else
  13768. ret.set_float(layer.scale);
  13769. };
  13770. SysExps.prototype.layeropacity = function (ret, layerparam)
  13771. {
  13772. var layer = this.runtime.getLayer(layerparam);
  13773. if (!layer)
  13774. ret.set_float(0);
  13775. else
  13776. ret.set_float(layer.opacity * 100);
  13777. };
  13778. SysExps.prototype.layerscalerate = function (ret, layerparam)
  13779. {
  13780. var layer = this.runtime.getLayer(layerparam);
  13781. if (!layer)
  13782. ret.set_float(0);
  13783. else
  13784. ret.set_float(layer.zoomRate);
  13785. };
  13786. SysExps.prototype.layerparallaxx = function (ret, layerparam)
  13787. {
  13788. var layer = this.runtime.getLayer(layerparam);
  13789. if (!layer)
  13790. ret.set_float(0);
  13791. else
  13792. ret.set_float(layer.parallaxX * 100);
  13793. };
  13794. SysExps.prototype.layerparallaxy = function (ret, layerparam)
  13795. {
  13796. var layer = this.runtime.getLayer(layerparam);
  13797. if (!layer)
  13798. ret.set_float(0);
  13799. else
  13800. ret.set_float(layer.parallaxY * 100);
  13801. };
  13802. SysExps.prototype.layerindex = function (ret, layerparam)
  13803. {
  13804. var layer = this.runtime.getLayer(layerparam);
  13805. if (!layer)
  13806. ret.set_int(-1);
  13807. else
  13808. ret.set_int(layer.index);
  13809. };
  13810. SysExps.prototype.layoutscale = function (ret)
  13811. {
  13812. if (this.runtime.running_layout)
  13813. ret.set_float(this.runtime.running_layout.scale);
  13814. else
  13815. ret.set_float(0);
  13816. };
  13817. SysExps.prototype.layoutangle = function (ret)
  13818. {
  13819. ret.set_float(cr.to_degrees(this.runtime.running_layout.angle));
  13820. };
  13821. SysExps.prototype.layerangle = function (ret, layerparam)
  13822. {
  13823. var layer = this.runtime.getLayer(layerparam);
  13824. if (!layer)
  13825. ret.set_float(0);
  13826. else
  13827. ret.set_float(cr.to_degrees(layer.angle));
  13828. };
  13829. SysExps.prototype.layoutwidth = function (ret)
  13830. {
  13831. ret.set_int(this.runtime.running_layout.width);
  13832. };
  13833. SysExps.prototype.layoutheight = function (ret)
  13834. {
  13835. ret.set_int(this.runtime.running_layout.height);
  13836. };
  13837. SysExps.prototype.find = function (ret, text, searchstr)
  13838. {
  13839. if (cr.is_string(text) && cr.is_string(searchstr))
  13840. ret.set_int(text.search(new RegExp(cr.regexp_escape(searchstr), "i")));
  13841. else
  13842. ret.set_int(-1);
  13843. };
  13844. SysExps.prototype.findcase = function (ret, text, searchstr)
  13845. {
  13846. if (cr.is_string(text) && cr.is_string(searchstr))
  13847. ret.set_int(text.search(new RegExp(cr.regexp_escape(searchstr), "")));
  13848. else
  13849. ret.set_int(-1);
  13850. };
  13851. SysExps.prototype.left = function (ret, text, n)
  13852. {
  13853. ret.set_string(cr.is_string(text) ? text.substr(0, n) : "");
  13854. };
  13855. SysExps.prototype.right = function (ret, text, n)
  13856. {
  13857. ret.set_string(cr.is_string(text) ? text.substr(text.length - n) : "");
  13858. };
  13859. SysExps.prototype.mid = function (ret, text, index_, length_)
  13860. {
  13861. ret.set_string(cr.is_string(text) ? text.substr(index_, length_) : "");
  13862. };
  13863. SysExps.prototype.tokenat = function (ret, text, index_, sep)
  13864. {
  13865. if (cr.is_string(text) && cr.is_string(sep))
  13866. {
  13867. var arr = text.split(sep);
  13868. var i = cr.floor(index_);
  13869. if (i < 0 || i >= arr.length)
  13870. ret.set_string("");
  13871. else
  13872. ret.set_string(arr[i]);
  13873. }
  13874. else
  13875. ret.set_string("");
  13876. };
  13877. SysExps.prototype.tokencount = function (ret, text, sep)
  13878. {
  13879. if (cr.is_string(text) && text.length)
  13880. ret.set_int(text.split(sep).length);
  13881. else
  13882. ret.set_int(0);
  13883. };
  13884. SysExps.prototype.replace = function (ret, text, find_, replace_)
  13885. {
  13886. if (cr.is_string(text) && cr.is_string(find_) && cr.is_string(replace_))
  13887. ret.set_string(text.replace(new RegExp(cr.regexp_escape(find_), "gi"), replace_));
  13888. else
  13889. ret.set_string(cr.is_string(text) ? text : "");
  13890. };
  13891. SysExps.prototype.trim = function (ret, text)
  13892. {
  13893. ret.set_string(cr.is_string(text) ? text.trim() : "");
  13894. };
  13895. SysExps.prototype.pi = function (ret)
  13896. {
  13897. ret.set_float(cr.PI);
  13898. };
  13899. SysExps.prototype.layoutname = function (ret)
  13900. {
  13901. if (this.runtime.running_layout)
  13902. ret.set_string(this.runtime.running_layout.name);
  13903. else
  13904. ret.set_string("");
  13905. };
  13906. SysExps.prototype.renderer = function (ret)
  13907. {
  13908. ret.set_string(this.runtime.gl ? "webgl" : "canvas2d");
  13909. };
  13910. SysExps.prototype.rendererdetail = function (ret)
  13911. {
  13912. ret.set_string(this.runtime.glUnmaskedRenderer);
  13913. };
  13914. SysExps.prototype.anglediff = function (ret, a, b)
  13915. {
  13916. ret.set_float(cr.to_degrees(cr.angleDiff(cr.to_radians(a), cr.to_radians(b))));
  13917. };
  13918. SysExps.prototype.choose = function (ret)
  13919. {
  13920. var index = cr.floor(Math.random() * (arguments.length - 1));
  13921. ret.set_any(arguments[index + 1]);
  13922. };
  13923. SysExps.prototype.rgb = function (ret, r, g, b)
  13924. {
  13925. ret.set_int(cr.RGB(r, g, b));
  13926. };
  13927. SysExps.prototype.projectversion = function (ret)
  13928. {
  13929. ret.set_string(this.runtime.versionstr);
  13930. };
  13931. SysExps.prototype.projectname = function (ret)
  13932. {
  13933. ret.set_string(this.runtime.projectName);
  13934. };
  13935. SysExps.prototype.anglelerp = function (ret, a, b, x)
  13936. {
  13937. a = cr.to_radians(a);
  13938. b = cr.to_radians(b);
  13939. var diff = cr.angleDiff(a, b);
  13940. if (cr.angleClockwise(b, a))
  13941. {
  13942. ret.set_float(cr.to_clamped_degrees(a + diff * x));
  13943. }
  13944. else
  13945. {
  13946. ret.set_float(cr.to_clamped_degrees(a - diff * x));
  13947. }
  13948. };
  13949. SysExps.prototype.anglerotate = function (ret, a, b, c)
  13950. {
  13951. a = cr.to_radians(a);
  13952. b = cr.to_radians(b);
  13953. c = cr.to_radians(c);
  13954. ret.set_float(cr.to_clamped_degrees(cr.angleRotate(a, b, c)));
  13955. };
  13956. SysExps.prototype.zeropad = function (ret, n, d)
  13957. {
  13958. var s = (n < 0 ? "-" : "");
  13959. if (n < 0) n = -n;
  13960. var zeroes = d - n.toString().length;
  13961. for (var i = 0; i < zeroes; i++)
  13962. s += "0";
  13963. ret.set_string(s + n.toString());
  13964. };
  13965. SysExps.prototype.cpuutilisation = function (ret)
  13966. {
  13967. ret.set_float(this.runtime.cpuutilisation / 1000);
  13968. };
  13969. SysExps.prototype.viewportleft = function (ret, layerparam)
  13970. {
  13971. var layer = this.runtime.getLayer(layerparam);
  13972. ret.set_float(layer ? layer.viewLeft : 0);
  13973. };
  13974. SysExps.prototype.viewporttop = function (ret, layerparam)
  13975. {
  13976. var layer = this.runtime.getLayer(layerparam);
  13977. ret.set_float(layer ? layer.viewTop : 0);
  13978. };
  13979. SysExps.prototype.viewportright = function (ret, layerparam)
  13980. {
  13981. var layer = this.runtime.getLayer(layerparam);
  13982. ret.set_float(layer ? layer.viewRight : 0);
  13983. };
  13984. SysExps.prototype.viewportbottom = function (ret, layerparam)
  13985. {
  13986. var layer = this.runtime.getLayer(layerparam);
  13987. ret.set_float(layer ? layer.viewBottom : 0);
  13988. };
  13989. SysExps.prototype.loadingprogress = function (ret)
  13990. {
  13991. ret.set_float(this.runtime.loadingprogress);
  13992. };
  13993. SysExps.prototype.unlerp = function(ret, a, b, y)
  13994. {
  13995. ret.set_float(cr.unlerp(a, b, y));
  13996. };
  13997. SysExps.prototype.canvassnapshot = function (ret)
  13998. {
  13999. ret.set_string(this.runtime.snapshotData);
  14000. };
  14001. SysExps.prototype.urlencode = function (ret, s)
  14002. {
  14003. ret.set_string(encodeURIComponent(s));
  14004. };
  14005. SysExps.prototype.urldecode = function (ret, s)
  14006. {
  14007. ret.set_string(decodeURIComponent(s));
  14008. };
  14009. SysExps.prototype.canvastolayerx = function (ret, layerparam, x, y)
  14010. {
  14011. var layer = this.runtime.getLayer(layerparam);
  14012. ret.set_float(layer ? layer.canvasToLayer(x, y, true) : 0);
  14013. };
  14014. SysExps.prototype.canvastolayery = function (ret, layerparam, x, y)
  14015. {
  14016. var layer = this.runtime.getLayer(layerparam);
  14017. ret.set_float(layer ? layer.canvasToLayer(x, y, false) : 0);
  14018. };
  14019. SysExps.prototype.layertocanvasx = function (ret, layerparam, x, y)
  14020. {
  14021. var layer = this.runtime.getLayer(layerparam);
  14022. ret.set_float(layer ? layer.layerToCanvas(x, y, true) : 0);
  14023. };
  14024. SysExps.prototype.layertocanvasy = function (ret, layerparam, x, y)
  14025. {
  14026. var layer = this.runtime.getLayer(layerparam);
  14027. ret.set_float(layer ? layer.layerToCanvas(x, y, false) : 0);
  14028. };
  14029. SysExps.prototype.savestatejson = function (ret)
  14030. {
  14031. ret.set_string(this.runtime.lastSaveJson);
  14032. };
  14033. SysExps.prototype.imagememoryusage = function (ret)
  14034. {
  14035. if (this.runtime.glwrap)
  14036. ret.set_float(Math.round(100 * this.runtime.glwrap.estimateVRAM() / (1024 * 1024)) / 100);
  14037. else
  14038. ret.set_float(0);
  14039. };
  14040. SysExps.prototype.regexsearch = function (ret, str_, regex_, flags_)
  14041. {
  14042. var regex = getRegex(regex_, flags_);
  14043. ret.set_int(str_ ? str_.search(regex) : -1);
  14044. };
  14045. SysExps.prototype.regexreplace = function (ret, str_, regex_, flags_, replace_)
  14046. {
  14047. var regex = getRegex(regex_, flags_);
  14048. ret.set_string(str_ ? str_.replace(regex, replace_) : "");
  14049. };
  14050. var regexMatches = [];
  14051. var lastMatchesStr = "";
  14052. var lastMatchesRegex = "";
  14053. var lastMatchesFlags = "";
  14054. function updateRegexMatches(str_, regex_, flags_)
  14055. {
  14056. if (str_ === lastMatchesStr && regex_ === lastMatchesRegex && flags_ === lastMatchesFlags)
  14057. return;
  14058. var regex = getRegex(regex_, flags_);
  14059. regexMatches = str_.match(regex);
  14060. lastMatchesStr = str_;
  14061. lastMatchesRegex = regex_;
  14062. lastMatchesFlags = flags_;
  14063. };
  14064. SysExps.prototype.regexmatchcount = function (ret, str_, regex_, flags_)
  14065. {
  14066. var regex = getRegex(regex_, flags_);
  14067. updateRegexMatches(str_.toString(), regex_, flags_);
  14068. ret.set_int(regexMatches ? regexMatches.length : 0);
  14069. };
  14070. SysExps.prototype.regexmatchat = function (ret, str_, regex_, flags_, index_)
  14071. {
  14072. index_ = Math.floor(index_);
  14073. var regex = getRegex(regex_, flags_);
  14074. updateRegexMatches(str_.toString(), regex_, flags_);
  14075. if (!regexMatches || index_ < 0 || index_ >= regexMatches.length)
  14076. ret.set_string("");
  14077. else
  14078. ret.set_string(regexMatches[index_]);
  14079. };
  14080. SysExps.prototype.infinity = function (ret)
  14081. {
  14082. ret.set_float(Infinity);
  14083. };
  14084. SysExps.prototype.setbit = function (ret, n, b, v)
  14085. {
  14086. n = n | 0;
  14087. b = b | 0;
  14088. v = (v !== 0 ? 1 : 0);
  14089. ret.set_int((n & ~(1 << b)) | (v << b));
  14090. };
  14091. SysExps.prototype.togglebit = function (ret, n, b)
  14092. {
  14093. n = n | 0;
  14094. b = b | 0;
  14095. ret.set_int(n ^ (1 << b));
  14096. };
  14097. SysExps.prototype.getbit = function (ret, n, b)
  14098. {
  14099. n = n | 0;
  14100. b = b | 0;
  14101. ret.set_int((n & (1 << b)) ? 1 : 0);
  14102. };
  14103. SysExps.prototype.originalwindowwidth = function (ret)
  14104. {
  14105. ret.set_int(this.runtime.original_width);
  14106. };
  14107. SysExps.prototype.originalwindowheight = function (ret)
  14108. {
  14109. ret.set_int(this.runtime.original_height);
  14110. };
  14111. sysProto.exps = new SysExps();
  14112. sysProto.runWaits = function ()
  14113. {
  14114. var i, j, len, w, k, s, ss;
  14115. var evinfo = this.runtime.getCurrentEventStack();
  14116. for (i = 0, len = this.waits.length; i < len; i++)
  14117. {
  14118. w = this.waits[i];
  14119. if (w.time === -1) // signalled wait
  14120. {
  14121. if (!w.signalled)
  14122. continue; // not yet signalled
  14123. }
  14124. else // timer wait
  14125. {
  14126. if (w.time > this.runtime.kahanTime.sum)
  14127. continue; // timer not yet expired
  14128. }
  14129. evinfo.current_event = w.ev;
  14130. evinfo.actindex = w.actindex;
  14131. evinfo.cndindex = 0;
  14132. for (k in w.sols)
  14133. {
  14134. if (w.sols.hasOwnProperty(k))
  14135. {
  14136. s = this.runtime.types_by_index[parseInt(k, 10)].getCurrentSol();
  14137. ss = w.sols[k];
  14138. s.select_all = ss.sa;
  14139. cr.shallowAssignArray(s.instances, ss.insts);
  14140. freeSolStateObject(ss);
  14141. }
  14142. }
  14143. w.ev.resume_actions_and_subevents();
  14144. this.runtime.clearSol(w.solModifiers);
  14145. w.deleteme = true;
  14146. }
  14147. for (i = 0, j = 0, len = this.waits.length; i < len; i++)
  14148. {
  14149. w = this.waits[i];
  14150. this.waits[j] = w;
  14151. if (w.deleteme)
  14152. freeWaitObject(w);
  14153. else
  14154. j++;
  14155. }
  14156. cr.truncateArray(this.waits, j);
  14157. };
  14158. }());
  14159. ;
  14160. (function () {
  14161. cr.add_common_aces = function (m, pluginProto)
  14162. {
  14163. var singleglobal_ = m[1];
  14164. var position_aces = m[3];
  14165. var size_aces = m[4];
  14166. var angle_aces = m[5];
  14167. var appearance_aces = m[6];
  14168. var zorder_aces = m[7];
  14169. var effects_aces = m[8];
  14170. if (!pluginProto.cnds)
  14171. pluginProto.cnds = {};
  14172. if (!pluginProto.acts)
  14173. pluginProto.acts = {};
  14174. if (!pluginProto.exps)
  14175. pluginProto.exps = {};
  14176. var cnds = pluginProto.cnds;
  14177. var acts = pluginProto.acts;
  14178. var exps = pluginProto.exps;
  14179. if (position_aces)
  14180. {
  14181. cnds.CompareX = function (cmp, x)
  14182. {
  14183. return cr.do_cmp(this.x, cmp, x);
  14184. };
  14185. cnds.CompareY = function (cmp, y)
  14186. {
  14187. return cr.do_cmp(this.y, cmp, y);
  14188. };
  14189. cnds.IsOnScreen = function ()
  14190. {
  14191. var layer = this.layer;
  14192. this.update_bbox();
  14193. var bbox = this.bbox;
  14194. return !(bbox.right < layer.viewLeft || bbox.bottom < layer.viewTop || bbox.left > layer.viewRight || bbox.top > layer.viewBottom);
  14195. };
  14196. cnds.IsOutsideLayout = function ()
  14197. {
  14198. this.update_bbox();
  14199. var bbox = this.bbox;
  14200. var layout = this.runtime.running_layout;
  14201. return (bbox.right < 0 || bbox.bottom < 0 || bbox.left > layout.width || bbox.top > layout.height);
  14202. };
  14203. cnds.PickDistance = function (which, x, y)
  14204. {
  14205. var sol = this.getCurrentSol();
  14206. var instances = sol.getObjects();
  14207. if (!instances.length)
  14208. return false;
  14209. var inst = instances[0];
  14210. var pickme = inst;
  14211. var dist = cr.distanceTo(inst.x, inst.y, x, y);
  14212. var i, len, d;
  14213. for (i = 1, len = instances.length; i < len; i++)
  14214. {
  14215. inst = instances[i];
  14216. d = cr.distanceTo(inst.x, inst.y, x, y);
  14217. if ((which === 0 && d < dist) || (which === 1 && d > dist))
  14218. {
  14219. dist = d;
  14220. pickme = inst;
  14221. }
  14222. }
  14223. sol.pick_one(pickme);
  14224. return true;
  14225. };
  14226. acts.SetX = function (x)
  14227. {
  14228. if (this.x !== x)
  14229. {
  14230. this.x = x;
  14231. this.set_bbox_changed();
  14232. }
  14233. };
  14234. acts.SetY = function (y)
  14235. {
  14236. if (this.y !== y)
  14237. {
  14238. this.y = y;
  14239. this.set_bbox_changed();
  14240. }
  14241. };
  14242. acts.SetPos = function (x, y)
  14243. {
  14244. if (this.x !== x || this.y !== y)
  14245. {
  14246. this.x = x;
  14247. this.y = y;
  14248. this.set_bbox_changed();
  14249. }
  14250. };
  14251. acts.SetPosToObject = function (obj, imgpt)
  14252. {
  14253. var inst = obj.getPairedInstance(this);
  14254. if (!inst)
  14255. return;
  14256. var newx, newy;
  14257. if (inst.getImagePoint)
  14258. {
  14259. newx = inst.getImagePoint(imgpt, true);
  14260. newy = inst.getImagePoint(imgpt, false);
  14261. }
  14262. else
  14263. {
  14264. newx = inst.x;
  14265. newy = inst.y;
  14266. }
  14267. if (this.x !== newx || this.y !== newy)
  14268. {
  14269. this.x = newx;
  14270. this.y = newy;
  14271. this.set_bbox_changed();
  14272. }
  14273. };
  14274. acts.MoveForward = function (dist)
  14275. {
  14276. if (dist !== 0)
  14277. {
  14278. this.x += Math.cos(this.angle) * dist;
  14279. this.y += Math.sin(this.angle) * dist;
  14280. this.set_bbox_changed();
  14281. }
  14282. };
  14283. acts.MoveAtAngle = function (a, dist)
  14284. {
  14285. if (dist !== 0)
  14286. {
  14287. this.x += Math.cos(cr.to_radians(a)) * dist;
  14288. this.y += Math.sin(cr.to_radians(a)) * dist;
  14289. this.set_bbox_changed();
  14290. }
  14291. };
  14292. exps.X = function (ret)
  14293. {
  14294. ret.set_float(this.x);
  14295. };
  14296. exps.Y = function (ret)
  14297. {
  14298. ret.set_float(this.y);
  14299. };
  14300. exps.dt = function (ret)
  14301. {
  14302. ret.set_float(this.runtime.getDt(this));
  14303. };
  14304. }
  14305. if (size_aces)
  14306. {
  14307. cnds.CompareWidth = function (cmp, w)
  14308. {
  14309. return cr.do_cmp(this.width, cmp, w);
  14310. };
  14311. cnds.CompareHeight = function (cmp, h)
  14312. {
  14313. return cr.do_cmp(this.height, cmp, h);
  14314. };
  14315. acts.SetWidth = function (w)
  14316. {
  14317. if (this.width !== w)
  14318. {
  14319. this.width = w;
  14320. this.set_bbox_changed();
  14321. }
  14322. };
  14323. acts.SetHeight = function (h)
  14324. {
  14325. if (this.height !== h)
  14326. {
  14327. this.height = h;
  14328. this.set_bbox_changed();
  14329. }
  14330. };
  14331. acts.SetSize = function (w, h)
  14332. {
  14333. if (this.width !== w || this.height !== h)
  14334. {
  14335. this.width = w;
  14336. this.height = h;
  14337. this.set_bbox_changed();
  14338. }
  14339. };
  14340. exps.Width = function (ret)
  14341. {
  14342. ret.set_float(this.width);
  14343. };
  14344. exps.Height = function (ret)
  14345. {
  14346. ret.set_float(this.height);
  14347. };
  14348. exps.BBoxLeft = function (ret)
  14349. {
  14350. this.update_bbox();
  14351. ret.set_float(this.bbox.left);
  14352. };
  14353. exps.BBoxTop = function (ret)
  14354. {
  14355. this.update_bbox();
  14356. ret.set_float(this.bbox.top);
  14357. };
  14358. exps.BBoxRight = function (ret)
  14359. {
  14360. this.update_bbox();
  14361. ret.set_float(this.bbox.right);
  14362. };
  14363. exps.BBoxBottom = function (ret)
  14364. {
  14365. this.update_bbox();
  14366. ret.set_float(this.bbox.bottom);
  14367. };
  14368. }
  14369. if (angle_aces)
  14370. {
  14371. cnds.AngleWithin = function (within, a)
  14372. {
  14373. return cr.angleDiff(this.angle, cr.to_radians(a)) <= cr.to_radians(within);
  14374. };
  14375. cnds.IsClockwiseFrom = function (a)
  14376. {
  14377. return cr.angleClockwise(this.angle, cr.to_radians(a));
  14378. };
  14379. cnds.IsBetweenAngles = function (a, b)
  14380. {
  14381. var lower = cr.to_clamped_radians(a);
  14382. var upper = cr.to_clamped_radians(b);
  14383. var angle = cr.clamp_angle(this.angle);
  14384. var obtuse = (!cr.angleClockwise(upper, lower));
  14385. if (obtuse)
  14386. return !(!cr.angleClockwise(angle, lower) && cr.angleClockwise(angle, upper));
  14387. else
  14388. return cr.angleClockwise(angle, lower) && !cr.angleClockwise(angle, upper);
  14389. };
  14390. acts.SetAngle = function (a)
  14391. {
  14392. var newangle = cr.to_radians(cr.clamp_angle_degrees(a));
  14393. if (isNaN(newangle))
  14394. return;
  14395. if (this.angle !== newangle)
  14396. {
  14397. this.angle = newangle;
  14398. this.set_bbox_changed();
  14399. }
  14400. };
  14401. acts.RotateClockwise = function (a)
  14402. {
  14403. if (a !== 0 && !isNaN(a))
  14404. {
  14405. this.angle += cr.to_radians(a);
  14406. this.angle = cr.clamp_angle(this.angle);
  14407. this.set_bbox_changed();
  14408. }
  14409. };
  14410. acts.RotateCounterclockwise = function (a)
  14411. {
  14412. if (a !== 0 && !isNaN(a))
  14413. {
  14414. this.angle -= cr.to_radians(a);
  14415. this.angle = cr.clamp_angle(this.angle);
  14416. this.set_bbox_changed();
  14417. }
  14418. };
  14419. acts.RotateTowardAngle = function (amt, target)
  14420. {
  14421. var newangle = cr.angleRotate(this.angle, cr.to_radians(target), cr.to_radians(amt));
  14422. if (isNaN(newangle))
  14423. return;
  14424. if (this.angle !== newangle)
  14425. {
  14426. this.angle = newangle;
  14427. this.set_bbox_changed();
  14428. }
  14429. };
  14430. acts.RotateTowardPosition = function (amt, x, y)
  14431. {
  14432. var dx = x - this.x;
  14433. var dy = y - this.y;
  14434. var target = Math.atan2(dy, dx);
  14435. var newangle = cr.angleRotate(this.angle, target, cr.to_radians(amt));
  14436. if (isNaN(newangle))
  14437. return;
  14438. if (this.angle !== newangle)
  14439. {
  14440. this.angle = newangle;
  14441. this.set_bbox_changed();
  14442. }
  14443. };
  14444. acts.SetTowardPosition = function (x, y)
  14445. {
  14446. var dx = x - this.x;
  14447. var dy = y - this.y;
  14448. var newangle = Math.atan2(dy, dx);
  14449. if (isNaN(newangle))
  14450. return;
  14451. if (this.angle !== newangle)
  14452. {
  14453. this.angle = newangle;
  14454. this.set_bbox_changed();
  14455. }
  14456. };
  14457. exps.Angle = function (ret)
  14458. {
  14459. ret.set_float(cr.to_clamped_degrees(this.angle));
  14460. };
  14461. }
  14462. if (!singleglobal_)
  14463. {
  14464. cnds.CompareInstanceVar = function (iv, cmp, val)
  14465. {
  14466. return cr.do_cmp(this.instance_vars[iv], cmp, val);
  14467. };
  14468. cnds.IsBoolInstanceVarSet = function (iv)
  14469. {
  14470. return this.instance_vars[iv];
  14471. };
  14472. cnds.PickInstVarHiLow = function (which, iv)
  14473. {
  14474. var sol = this.getCurrentSol();
  14475. var instances = sol.getObjects();
  14476. if (!instances.length)
  14477. return false;
  14478. var inst = instances[0];
  14479. var pickme = inst;
  14480. var val = inst.instance_vars[iv];
  14481. var i, len, v;
  14482. for (i = 1, len = instances.length; i < len; i++)
  14483. {
  14484. inst = instances[i];
  14485. v = inst.instance_vars[iv];
  14486. if ((which === 0 && v < val) || (which === 1 && v > val))
  14487. {
  14488. val = v;
  14489. pickme = inst;
  14490. }
  14491. }
  14492. sol.pick_one(pickme);
  14493. return true;
  14494. };
  14495. cnds.PickByUID = function (u)
  14496. {
  14497. var i, len, j, inst, families, instances, sol;
  14498. var cnd = this.runtime.getCurrentCondition();
  14499. if (cnd.inverted)
  14500. {
  14501. sol = this.getCurrentSol();
  14502. if (sol.select_all)
  14503. {
  14504. sol.select_all = false;
  14505. cr.clearArray(sol.instances);
  14506. cr.clearArray(sol.else_instances);
  14507. instances = this.instances;
  14508. for (i = 0, len = instances.length; i < len; i++)
  14509. {
  14510. inst = instances[i];
  14511. if (inst.uid === u)
  14512. sol.else_instances.push(inst);
  14513. else
  14514. sol.instances.push(inst);
  14515. }
  14516. this.applySolToContainer();
  14517. return !!sol.instances.length;
  14518. }
  14519. else
  14520. {
  14521. for (i = 0, j = 0, len = sol.instances.length; i < len; i++)
  14522. {
  14523. inst = sol.instances[i];
  14524. sol.instances[j] = inst;
  14525. if (inst.uid === u)
  14526. {
  14527. sol.else_instances.push(inst);
  14528. }
  14529. else
  14530. j++;
  14531. }
  14532. cr.truncateArray(sol.instances, j);
  14533. this.applySolToContainer();
  14534. return !!sol.instances.length;
  14535. }
  14536. }
  14537. else
  14538. {
  14539. inst = this.runtime.getObjectByUID(u);
  14540. if (!inst)
  14541. return false;
  14542. sol = this.getCurrentSol();
  14543. if (!sol.select_all && sol.instances.indexOf(inst) === -1)
  14544. return false; // not picked
  14545. if (this.is_family)
  14546. {
  14547. families = inst.type.families;
  14548. for (i = 0, len = families.length; i < len; i++)
  14549. {
  14550. if (families[i] === this)
  14551. {
  14552. sol.pick_one(inst);
  14553. this.applySolToContainer();
  14554. return true;
  14555. }
  14556. }
  14557. }
  14558. else if (inst.type === this)
  14559. {
  14560. sol.pick_one(inst);
  14561. this.applySolToContainer();
  14562. return true;
  14563. }
  14564. return false;
  14565. }
  14566. };
  14567. cnds.OnCreated = function ()
  14568. {
  14569. return true;
  14570. };
  14571. cnds.OnDestroyed = function ()
  14572. {
  14573. return true;
  14574. };
  14575. acts.SetInstanceVar = function (iv, val)
  14576. {
  14577. var myinstvars = this.instance_vars;
  14578. if (cr.is_number(myinstvars[iv]))
  14579. {
  14580. if (cr.is_number(val))
  14581. myinstvars[iv] = val;
  14582. else
  14583. myinstvars[iv] = parseFloat(val);
  14584. }
  14585. else if (cr.is_string(myinstvars[iv]))
  14586. {
  14587. if (cr.is_string(val))
  14588. myinstvars[iv] = val;
  14589. else
  14590. myinstvars[iv] = val.toString();
  14591. }
  14592. else
  14593. ;
  14594. };
  14595. acts.AddInstanceVar = function (iv, val)
  14596. {
  14597. var myinstvars = this.instance_vars;
  14598. if (cr.is_number(myinstvars[iv]))
  14599. {
  14600. if (cr.is_number(val))
  14601. myinstvars[iv] += val;
  14602. else
  14603. myinstvars[iv] += parseFloat(val);
  14604. }
  14605. else if (cr.is_string(myinstvars[iv]))
  14606. {
  14607. if (cr.is_string(val))
  14608. myinstvars[iv] += val;
  14609. else
  14610. myinstvars[iv] += val.toString();
  14611. }
  14612. else
  14613. ;
  14614. };
  14615. acts.SubInstanceVar = function (iv, val)
  14616. {
  14617. var myinstvars = this.instance_vars;
  14618. if (cr.is_number(myinstvars[iv]))
  14619. {
  14620. if (cr.is_number(val))
  14621. myinstvars[iv] -= val;
  14622. else
  14623. myinstvars[iv] -= parseFloat(val);
  14624. }
  14625. else
  14626. ;
  14627. };
  14628. acts.SetBoolInstanceVar = function (iv, val)
  14629. {
  14630. this.instance_vars[iv] = val ? 1 : 0;
  14631. };
  14632. acts.ToggleBoolInstanceVar = function (iv)
  14633. {
  14634. this.instance_vars[iv] = 1 - this.instance_vars[iv];
  14635. };
  14636. acts.Destroy = function ()
  14637. {
  14638. this.runtime.DestroyInstance(this);
  14639. };
  14640. if (!acts.LoadFromJsonString)
  14641. {
  14642. acts.LoadFromJsonString = function (str_)
  14643. {
  14644. var o, i, len, binst;
  14645. try {
  14646. o = JSON.parse(str_);
  14647. }
  14648. catch (e) {
  14649. return;
  14650. }
  14651. this.runtime.loadInstanceFromJSON(this, o, true);
  14652. if (this.afterLoad)
  14653. this.afterLoad();
  14654. if (this.behavior_insts)
  14655. {
  14656. for (i = 0, len = this.behavior_insts.length; i < len; ++i)
  14657. {
  14658. binst = this.behavior_insts[i];
  14659. if (binst.afterLoad)
  14660. binst.afterLoad();
  14661. }
  14662. }
  14663. };
  14664. }
  14665. exps.Count = function (ret)
  14666. {
  14667. var count = ret.object_class.instances.length;
  14668. var i, len, inst;
  14669. for (i = 0, len = this.runtime.createRow.length; i < len; i++)
  14670. {
  14671. inst = this.runtime.createRow[i];
  14672. if (ret.object_class.is_family)
  14673. {
  14674. if (inst.type.families.indexOf(ret.object_class) >= 0)
  14675. count++;
  14676. }
  14677. else
  14678. {
  14679. if (inst.type === ret.object_class)
  14680. count++;
  14681. }
  14682. }
  14683. ret.set_int(count);
  14684. };
  14685. exps.PickedCount = function (ret)
  14686. {
  14687. ret.set_int(ret.object_class.getCurrentSol().getObjects().length);
  14688. };
  14689. exps.UID = function (ret)
  14690. {
  14691. ret.set_int(this.uid);
  14692. };
  14693. exps.IID = function (ret)
  14694. {
  14695. ret.set_int(this.get_iid());
  14696. };
  14697. if (!exps.AsJSON)
  14698. {
  14699. exps.AsJSON = function (ret)
  14700. {
  14701. ret.set_string(JSON.stringify(this.runtime.saveInstanceToJSON(this, true)));
  14702. };
  14703. }
  14704. }
  14705. if (appearance_aces)
  14706. {
  14707. cnds.IsVisible = function ()
  14708. {
  14709. return this.visible;
  14710. };
  14711. acts.SetVisible = function (v)
  14712. {
  14713. if (!v !== !this.visible)
  14714. {
  14715. this.visible = !!v;
  14716. this.runtime.redraw = true;
  14717. }
  14718. };
  14719. cnds.CompareOpacity = function (cmp, x)
  14720. {
  14721. return cr.do_cmp(cr.round6dp(this.opacity * 100), cmp, x);
  14722. };
  14723. acts.SetOpacity = function (x)
  14724. {
  14725. var new_opacity = x / 100.0;
  14726. if (new_opacity < 0)
  14727. new_opacity = 0;
  14728. else if (new_opacity > 1)
  14729. new_opacity = 1;
  14730. if (new_opacity !== this.opacity)
  14731. {
  14732. this.opacity = new_opacity;
  14733. this.runtime.redraw = true;
  14734. }
  14735. };
  14736. exps.Opacity = function (ret)
  14737. {
  14738. ret.set_float(cr.round6dp(this.opacity * 100.0));
  14739. };
  14740. }
  14741. if (zorder_aces)
  14742. {
  14743. cnds.IsOnLayer = function (layer_)
  14744. {
  14745. if (!layer_)
  14746. return false;
  14747. return this.layer === layer_;
  14748. };
  14749. cnds.PickTopBottom = function (which_)
  14750. {
  14751. var sol = this.getCurrentSol();
  14752. var instances = sol.getObjects();
  14753. if (!instances.length)
  14754. return false;
  14755. var inst = instances[0];
  14756. var pickme = inst;
  14757. var i, len;
  14758. for (i = 1, len = instances.length; i < len; i++)
  14759. {
  14760. inst = instances[i];
  14761. if (which_ === 0)
  14762. {
  14763. if (inst.layer.index > pickme.layer.index || (inst.layer.index === pickme.layer.index && inst.get_zindex() > pickme.get_zindex()))
  14764. {
  14765. pickme = inst;
  14766. }
  14767. }
  14768. else
  14769. {
  14770. if (inst.layer.index < pickme.layer.index || (inst.layer.index === pickme.layer.index && inst.get_zindex() < pickme.get_zindex()))
  14771. {
  14772. pickme = inst;
  14773. }
  14774. }
  14775. }
  14776. sol.pick_one(pickme);
  14777. return true;
  14778. };
  14779. acts.MoveToTop = function ()
  14780. {
  14781. var layer = this.layer;
  14782. var layer_instances = layer.instances;
  14783. if (layer_instances.length && layer_instances[layer_instances.length - 1] === this)
  14784. return; // is already at top
  14785. layer.removeFromInstanceList(this, false);
  14786. layer.appendToInstanceList(this, false);
  14787. this.runtime.redraw = true;
  14788. };
  14789. acts.MoveToBottom = function ()
  14790. {
  14791. var layer = this.layer;
  14792. var layer_instances = layer.instances;
  14793. if (layer_instances.length && layer_instances[0] === this)
  14794. return; // is already at bottom
  14795. layer.removeFromInstanceList(this, false);
  14796. layer.prependToInstanceList(this, false);
  14797. this.runtime.redraw = true;
  14798. };
  14799. acts.MoveToLayer = function (layerMove)
  14800. {
  14801. if (!layerMove || layerMove == this.layer)
  14802. return;
  14803. this.layer.removeFromInstanceList(this, true);
  14804. this.layer = layerMove;
  14805. layerMove.appendToInstanceList(this, true);
  14806. this.runtime.redraw = true;
  14807. };
  14808. acts.ZMoveToObject = function (where_, obj_)
  14809. {
  14810. var isafter = (where_ === 0);
  14811. if (!obj_)
  14812. return;
  14813. var other = obj_.getFirstPicked(this);
  14814. if (!other || other.uid === this.uid)
  14815. return;
  14816. if (this.layer.index !== other.layer.index)
  14817. {
  14818. this.layer.removeFromInstanceList(this, true);
  14819. this.layer = other.layer;
  14820. other.layer.appendToInstanceList(this, true);
  14821. }
  14822. this.layer.moveInstanceAdjacent(this, other, isafter);
  14823. this.runtime.redraw = true;
  14824. };
  14825. exps.LayerNumber = function (ret)
  14826. {
  14827. ret.set_int(this.layer.number);
  14828. };
  14829. exps.LayerName = function (ret)
  14830. {
  14831. ret.set_string(this.layer.name);
  14832. };
  14833. exps.ZIndex = function (ret)
  14834. {
  14835. ret.set_int(this.get_zindex());
  14836. };
  14837. }
  14838. if (effects_aces)
  14839. {
  14840. acts.SetEffectEnabled = function (enable_, effectname_)
  14841. {
  14842. if (!this.runtime.glwrap)
  14843. return;
  14844. var i = this.type.getEffectIndexByName(effectname_);
  14845. if (i < 0)
  14846. return; // effect name not found
  14847. var enable = (enable_ === 1);
  14848. if (this.active_effect_flags[i] === enable)
  14849. return; // no change
  14850. this.active_effect_flags[i] = enable;
  14851. this.updateActiveEffects();
  14852. this.runtime.redraw = true;
  14853. };
  14854. acts.SetEffectParam = function (effectname_, index_, value_)
  14855. {
  14856. if (!this.runtime.glwrap)
  14857. return;
  14858. var i = this.type.getEffectIndexByName(effectname_);
  14859. if (i < 0)
  14860. return; // effect name not found
  14861. var et = this.type.effect_types[i];
  14862. var params = this.effect_params[i];
  14863. index_ = Math.floor(index_);
  14864. if (index_ < 0 || index_ >= params.length)
  14865. return; // effect index out of bounds
  14866. if (this.runtime.glwrap.getProgramParameterType(et.shaderindex, index_) === 1)
  14867. value_ /= 100.0;
  14868. if (params[index_] === value_)
  14869. return; // no change
  14870. params[index_] = value_;
  14871. if (et.active)
  14872. this.runtime.redraw = true;
  14873. };
  14874. }
  14875. };
  14876. cr.set_bbox_changed = function ()
  14877. {
  14878. this.bbox_changed = true; // will recreate next time box requested
  14879. this.cell_changed = true;
  14880. this.type.any_cell_changed = true; // avoid unnecessary updateAllBBox() calls
  14881. this.runtime.redraw = true; // assume runtime needs to redraw
  14882. var i, len, callbacks = this.bbox_changed_callbacks;
  14883. for (i = 0, len = callbacks.length; i < len; ++i)
  14884. {
  14885. callbacks[i](this);
  14886. }
  14887. if (this.layer.useRenderCells)
  14888. this.update_bbox();
  14889. };
  14890. cr.add_bbox_changed_callback = function (f)
  14891. {
  14892. if (f)
  14893. {
  14894. this.bbox_changed_callbacks.push(f);
  14895. }
  14896. };
  14897. cr.update_bbox = function ()
  14898. {
  14899. if (!this.bbox_changed)
  14900. return; // bounding box not changed
  14901. var bbox = this.bbox;
  14902. var bquad = this.bquad;
  14903. bbox.set(this.x, this.y, this.x + this.width, this.y + this.height);
  14904. bbox.offset(-this.hotspotX * this.width, -this.hotspotY * this.height);
  14905. if (!this.angle)
  14906. {
  14907. bquad.set_from_rect(bbox); // make bounding quad from box
  14908. }
  14909. else
  14910. {
  14911. bbox.offset(-this.x, -this.y); // translate to origin
  14912. bquad.set_from_rotated_rect(bbox, this.angle); // rotate around origin
  14913. bquad.offset(this.x, this.y); // translate back to original position
  14914. bquad.bounding_box(bbox);
  14915. }
  14916. bbox.normalize();
  14917. this.bbox_changed = false; // bounding box up to date
  14918. this.update_render_cell();
  14919. };
  14920. var tmprc = new cr.rect(0, 0, 0, 0);
  14921. cr.update_render_cell = function ()
  14922. {
  14923. if (!this.layer.useRenderCells)
  14924. return;
  14925. var mygrid = this.layer.render_grid;
  14926. var bbox = this.bbox;
  14927. tmprc.set(mygrid.XToCell(bbox.left), mygrid.YToCell(bbox.top), mygrid.XToCell(bbox.right), mygrid.YToCell(bbox.bottom));
  14928. if (this.rendercells.equals(tmprc))
  14929. return;
  14930. if (this.rendercells.right < this.rendercells.left)
  14931. mygrid.update(this, null, tmprc); // first insertion with invalid rect: don't provide old range
  14932. else
  14933. mygrid.update(this, this.rendercells, tmprc);
  14934. this.rendercells.copy(tmprc);
  14935. this.layer.render_list_stale = true;
  14936. };
  14937. cr.update_collision_cell = function ()
  14938. {
  14939. if (!this.cell_changed || !this.collisionsEnabled)
  14940. return;
  14941. this.update_bbox();
  14942. var mygrid = this.type.collision_grid;
  14943. var bbox = this.bbox;
  14944. tmprc.set(mygrid.XToCell(bbox.left), mygrid.YToCell(bbox.top), mygrid.XToCell(bbox.right), mygrid.YToCell(bbox.bottom));
  14945. if (this.collcells.equals(tmprc))
  14946. return;
  14947. if (this.collcells.right < this.collcells.left)
  14948. mygrid.update(this, null, tmprc); // first insertion with invalid rect: don't provide old range
  14949. else
  14950. mygrid.update(this, this.collcells, tmprc);
  14951. this.collcells.copy(tmprc);
  14952. this.cell_changed = false;
  14953. };
  14954. cr.inst_contains_pt = function (x, y)
  14955. {
  14956. if (!this.bbox.contains_pt(x, y))
  14957. return false;
  14958. if (!this.bquad.contains_pt(x, y))
  14959. return false;
  14960. if (this.tilemap_exists)
  14961. return this.testPointOverlapTile(x, y);
  14962. if (this.collision_poly && !this.collision_poly.is_empty())
  14963. {
  14964. this.collision_poly.cache_poly(this.width, this.height, this.angle);
  14965. return this.collision_poly.contains_pt(x - this.x, y - this.y);
  14966. }
  14967. else
  14968. return true;
  14969. };
  14970. cr.inst_get_iid = function ()
  14971. {
  14972. this.type.updateIIDs();
  14973. return this.iid;
  14974. };
  14975. cr.inst_get_zindex = function ()
  14976. {
  14977. this.layer.updateZIndices();
  14978. return this.zindex;
  14979. };
  14980. cr.inst_updateActiveEffects = function ()
  14981. {
  14982. cr.clearArray(this.active_effect_types);
  14983. var i, len, et;
  14984. var preserves_opaqueness = true;
  14985. for (i = 0, len = this.active_effect_flags.length; i < len; i++)
  14986. {
  14987. if (this.active_effect_flags[i])
  14988. {
  14989. et = this.type.effect_types[i];
  14990. this.active_effect_types.push(et);
  14991. if (!et.preservesOpaqueness)
  14992. preserves_opaqueness = false;
  14993. }
  14994. }
  14995. this.uses_shaders = !!this.active_effect_types.length;
  14996. this.shaders_preserve_opaqueness = preserves_opaqueness;
  14997. };
  14998. cr.inst_toString = function ()
  14999. {
  15000. return "Inst" + this.puid;
  15001. };
  15002. cr.type_getFirstPicked = function (frominst)
  15003. {
  15004. if (frominst && frominst.is_contained && frominst.type != this)
  15005. {
  15006. var i, len, s;
  15007. for (i = 0, len = frominst.siblings.length; i < len; i++)
  15008. {
  15009. s = frominst.siblings[i];
  15010. if (s.type == this)
  15011. return s;
  15012. }
  15013. }
  15014. var instances = this.getCurrentSol().getObjects();
  15015. if (instances.length)
  15016. return instances[0];
  15017. else
  15018. return null;
  15019. };
  15020. cr.type_getPairedInstance = function (inst)
  15021. {
  15022. var instances = this.getCurrentSol().getObjects();
  15023. if (instances.length)
  15024. return instances[inst.get_iid() % instances.length];
  15025. else
  15026. return null;
  15027. };
  15028. cr.type_updateIIDs = function ()
  15029. {
  15030. if (!this.stale_iids || this.is_family)
  15031. return; // up to date or is family - don't want family to overwrite IIDs
  15032. var i, len;
  15033. for (i = 0, len = this.instances.length; i < len; i++)
  15034. this.instances[i].iid = i;
  15035. var next_iid = i;
  15036. var createRow = this.runtime.createRow;
  15037. for (i = 0, len = createRow.length; i < len; ++i)
  15038. {
  15039. if (createRow[i].type === this)
  15040. createRow[i].iid = next_iid++;
  15041. }
  15042. this.stale_iids = false;
  15043. };
  15044. cr.type_getInstanceByIID = function (i)
  15045. {
  15046. if (i < this.instances.length)
  15047. return this.instances[i];
  15048. i -= this.instances.length;
  15049. var createRow = this.runtime.createRow;
  15050. var j, lenj;
  15051. for (j = 0, lenj = createRow.length; j < lenj; ++j)
  15052. {
  15053. if (createRow[j].type === this)
  15054. {
  15055. if (i === 0)
  15056. return createRow[j];
  15057. --i;
  15058. }
  15059. }
  15060. ;
  15061. return null;
  15062. };
  15063. cr.type_getCurrentSol = function ()
  15064. {
  15065. return this.solstack[this.cur_sol];
  15066. };
  15067. cr.type_pushCleanSol = function ()
  15068. {
  15069. this.cur_sol++;
  15070. if (this.cur_sol === this.solstack.length)
  15071. {
  15072. this.solstack.push(new cr.selection(this));
  15073. }
  15074. else
  15075. {
  15076. this.solstack[this.cur_sol].select_all = true; // else clear next SOL
  15077. cr.clearArray(this.solstack[this.cur_sol].else_instances);
  15078. }
  15079. };
  15080. cr.type_pushCopySol = function ()
  15081. {
  15082. this.cur_sol++;
  15083. if (this.cur_sol === this.solstack.length)
  15084. this.solstack.push(new cr.selection(this));
  15085. var clonesol = this.solstack[this.cur_sol];
  15086. var prevsol = this.solstack[this.cur_sol - 1];
  15087. if (prevsol.select_all)
  15088. {
  15089. clonesol.select_all = true;
  15090. }
  15091. else
  15092. {
  15093. clonesol.select_all = false;
  15094. cr.shallowAssignArray(clonesol.instances, prevsol.instances);
  15095. }
  15096. cr.clearArray(clonesol.else_instances);
  15097. };
  15098. cr.type_popSol = function ()
  15099. {
  15100. ;
  15101. this.cur_sol--;
  15102. };
  15103. cr.type_getBehaviorByName = function (behname)
  15104. {
  15105. var i, len, j, lenj, f, index = 0;
  15106. if (!this.is_family)
  15107. {
  15108. for (i = 0, len = this.families.length; i < len; i++)
  15109. {
  15110. f = this.families[i];
  15111. for (j = 0, lenj = f.behaviors.length; j < lenj; j++)
  15112. {
  15113. if (behname === f.behaviors[j].name)
  15114. {
  15115. this.extra["lastBehIndex"] = index;
  15116. return f.behaviors[j];
  15117. }
  15118. index++;
  15119. }
  15120. }
  15121. }
  15122. for (i = 0, len = this.behaviors.length; i < len; i++) {
  15123. if (behname === this.behaviors[i].name)
  15124. {
  15125. this.extra["lastBehIndex"] = index;
  15126. return this.behaviors[i];
  15127. }
  15128. index++;
  15129. }
  15130. return null;
  15131. };
  15132. cr.type_getBehaviorIndexByName = function (behname)
  15133. {
  15134. var b = this.getBehaviorByName(behname);
  15135. if (b)
  15136. return this.extra["lastBehIndex"];
  15137. else
  15138. return -1;
  15139. };
  15140. cr.type_getEffectIndexByName = function (name_)
  15141. {
  15142. var i, len;
  15143. for (i = 0, len = this.effect_types.length; i < len; i++)
  15144. {
  15145. if (this.effect_types[i].name === name_)
  15146. return i;
  15147. }
  15148. return -1;
  15149. };
  15150. cr.type_applySolToContainer = function ()
  15151. {
  15152. if (!this.is_contained || this.is_family)
  15153. return;
  15154. var i, len, j, lenj, t, sol, sol2;
  15155. this.updateIIDs();
  15156. sol = this.getCurrentSol();
  15157. var select_all = sol.select_all;
  15158. var es = this.runtime.getCurrentEventStack();
  15159. var orblock = es && es.current_event && es.current_event.orblock;
  15160. for (i = 0, len = this.container.length; i < len; i++)
  15161. {
  15162. t = this.container[i];
  15163. if (t === this)
  15164. continue;
  15165. t.updateIIDs();
  15166. sol2 = t.getCurrentSol();
  15167. sol2.select_all = select_all;
  15168. if (!select_all)
  15169. {
  15170. cr.clearArray(sol2.instances);
  15171. for (j = 0, lenj = sol.instances.length; j < lenj; ++j)
  15172. sol2.instances[j] = t.getInstanceByIID(sol.instances[j].iid);
  15173. if (orblock)
  15174. {
  15175. cr.clearArray(sol2.else_instances);
  15176. for (j = 0, lenj = sol.else_instances.length; j < lenj; ++j)
  15177. sol2.else_instances[j] = t.getInstanceByIID(sol.else_instances[j].iid);
  15178. }
  15179. }
  15180. }
  15181. };
  15182. cr.type_toString = function ()
  15183. {
  15184. return "Type" + this.sid;
  15185. };
  15186. cr.do_cmp = function (x, cmp, y)
  15187. {
  15188. if (typeof x === "undefined" || typeof y === "undefined")
  15189. return false;
  15190. switch (cmp)
  15191. {
  15192. case 0: // equal
  15193. return x === y;
  15194. case 1: // not equal
  15195. return x !== y;
  15196. case 2: // less
  15197. return x < y;
  15198. case 3: // less/equal
  15199. return x <= y;
  15200. case 4: // greater
  15201. return x > y;
  15202. case 5: // greater/equal
  15203. return x >= y;
  15204. default:
  15205. ;
  15206. return false;
  15207. }
  15208. };
  15209. })();
  15210. cr.shaders = {};
  15211. ;
  15212. ;
  15213. cr.plugins_.Button = function(runtime)
  15214. {
  15215. this.runtime = runtime;
  15216. };
  15217. (function ()
  15218. {
  15219. var pluginProto = cr.plugins_.Button.prototype;
  15220. pluginProto.Type = function(plugin)
  15221. {
  15222. this.plugin = plugin;
  15223. this.runtime = plugin.runtime;
  15224. };
  15225. var typeProto = pluginProto.Type.prototype;
  15226. typeProto.onCreate = function()
  15227. {
  15228. };
  15229. pluginProto.Instance = function(type)
  15230. {
  15231. this.type = type;
  15232. this.runtime = type.runtime;
  15233. };
  15234. var instanceProto = pluginProto.Instance.prototype;
  15235. instanceProto.onCreate = function()
  15236. {
  15237. if (this.runtime.isDomFree)
  15238. {
  15239. cr.logexport("[Construct 2] Button plugin not supported on this platform - the object will not be created");
  15240. return;
  15241. }
  15242. this.isCheckbox = (this.properties[0] === 1);
  15243. this.inputElem = document.createElement("input");
  15244. if (this.isCheckbox)
  15245. this.elem = document.createElement("label");
  15246. else
  15247. this.elem = this.inputElem;
  15248. this.labelText = null;
  15249. this.inputElem.type = (this.isCheckbox ? "checkbox" : "button");
  15250. this.inputElem.id = this.properties[6];
  15251. jQuery(this.elem).appendTo(this.runtime.canvasdiv ? this.runtime.canvasdiv : "body");
  15252. if (this.isCheckbox)
  15253. {
  15254. jQuery(this.inputElem).appendTo(this.elem);
  15255. this.labelText = document.createTextNode(this.properties[1]);
  15256. jQuery(this.elem).append(this.labelText);
  15257. this.inputElem.checked = (this.properties[7] !== 0);
  15258. jQuery(this.elem).css("font-family", "sans-serif");
  15259. jQuery(this.elem).css("display", "inline-block");
  15260. jQuery(this.elem).css("color", "black");
  15261. }
  15262. else
  15263. this.inputElem.value = this.properties[1];
  15264. this.elem.title = this.properties[2];
  15265. this.inputElem.disabled = (this.properties[4] === 0);
  15266. this.autoFontSize = (this.properties[5] !== 0);
  15267. this.element_hidden = false;
  15268. if (this.properties[3] === 0)
  15269. {
  15270. jQuery(this.elem).hide();
  15271. this.visible = false;
  15272. this.element_hidden = true;
  15273. }
  15274. this.inputElem.onclick = (function (self) {
  15275. return function(e) {
  15276. e.stopPropagation();
  15277. self.runtime.isInUserInputEvent = true;
  15278. self.runtime.trigger(cr.plugins_.Button.prototype.cnds.OnClicked, self);
  15279. self.runtime.isInUserInputEvent = false;
  15280. };
  15281. })(this);
  15282. this.elem.addEventListener("touchstart", function (e) {
  15283. e.stopPropagation();
  15284. }, false);
  15285. this.elem.addEventListener("touchmove", function (e) {
  15286. e.stopPropagation();
  15287. }, false);
  15288. this.elem.addEventListener("touchend", function (e) {
  15289. e.stopPropagation();
  15290. }, false);
  15291. jQuery(this.elem).mousedown(function (e) {
  15292. e.stopPropagation();
  15293. });
  15294. jQuery(this.elem).mouseup(function (e) {
  15295. e.stopPropagation();
  15296. });
  15297. jQuery(this.elem).keydown(function (e) {
  15298. e.stopPropagation();
  15299. });
  15300. jQuery(this.elem).keyup(function (e) {
  15301. e.stopPropagation();
  15302. });
  15303. this.lastLeft = 0;
  15304. this.lastTop = 0;
  15305. this.lastRight = 0;
  15306. this.lastBottom = 0;
  15307. this.lastWinWidth = 0;
  15308. this.lastWinHeight = 0;
  15309. this.updatePosition(true);
  15310. this.runtime.tickMe(this);
  15311. };
  15312. instanceProto.saveToJSON = function ()
  15313. {
  15314. var o = {
  15315. "tooltip": this.elem.title,
  15316. "disabled": !!this.inputElem.disabled
  15317. };
  15318. if (this.isCheckbox)
  15319. {
  15320. o["checked"] = !!this.inputElem.checked;
  15321. o["text"] = this.labelText.nodeValue;
  15322. }
  15323. else
  15324. {
  15325. o["text"] = this.elem.value;
  15326. }
  15327. return o;
  15328. };
  15329. instanceProto.loadFromJSON = function (o)
  15330. {
  15331. this.elem.title = o["tooltip"];
  15332. this.inputElem.disabled = o["disabled"];
  15333. if (this.isCheckbox)
  15334. {
  15335. this.inputElem.checked = o["checked"];
  15336. this.labelText.nodeValue = o["text"];
  15337. }
  15338. else
  15339. {
  15340. this.elem.value = o["text"];
  15341. }
  15342. };
  15343. instanceProto.onDestroy = function ()
  15344. {
  15345. if (this.runtime.isDomFree)
  15346. return;
  15347. jQuery(this.elem).remove();
  15348. this.elem = null;
  15349. };
  15350. instanceProto.tick = function ()
  15351. {
  15352. this.updatePosition();
  15353. };
  15354. var last_canvas_offset = null;
  15355. var last_checked_tick = -1;
  15356. instanceProto.updatePosition = function (first)
  15357. {
  15358. if (this.runtime.isDomFree)
  15359. return;
  15360. var left = this.layer.layerToCanvas(this.x, this.y, true);
  15361. var top = this.layer.layerToCanvas(this.x, this.y, false);
  15362. var right = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, true);
  15363. var bottom = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, false);
  15364. var rightEdge = this.runtime.width / this.runtime.devicePixelRatio;
  15365. var bottomEdge = this.runtime.height / this.runtime.devicePixelRatio;
  15366. if (!this.visible || !this.layer.visible || right <= 0 || bottom <= 0 || left >= rightEdge || top >= bottomEdge)
  15367. {
  15368. if (!this.element_hidden)
  15369. jQuery(this.elem).hide();
  15370. this.element_hidden = true;
  15371. return;
  15372. }
  15373. if (left < 1)
  15374. left = 1;
  15375. if (top < 1)
  15376. top = 1;
  15377. if (right >= rightEdge)
  15378. right = rightEdge - 1;
  15379. if (bottom >= bottomEdge)
  15380. bottom = bottomEdge - 1;
  15381. var curWinWidth = window.innerWidth;
  15382. var curWinHeight = window.innerHeight;
  15383. if (!first && this.lastLeft === left && this.lastTop === top && this.lastRight === right && this.lastBottom === bottom && this.lastWinWidth === curWinWidth && this.lastWinHeight === curWinHeight)
  15384. {
  15385. if (this.element_hidden)
  15386. {
  15387. jQuery(this.elem).show();
  15388. this.element_hidden = false;
  15389. }
  15390. return;
  15391. }
  15392. this.lastLeft = left;
  15393. this.lastTop = top;
  15394. this.lastRight = right;
  15395. this.lastBottom = bottom;
  15396. this.lastWinWidth = curWinWidth;
  15397. this.lastWinHeight = curWinHeight;
  15398. if (this.element_hidden)
  15399. {
  15400. jQuery(this.elem).show();
  15401. this.element_hidden = false;
  15402. }
  15403. var offx = Math.round(left) + jQuery(this.runtime.canvas).offset().left;
  15404. var offy = Math.round(top) + jQuery(this.runtime.canvas).offset().top;
  15405. jQuery(this.elem).css("position", "absolute");
  15406. jQuery(this.elem).offset({left: offx, top: offy});
  15407. jQuery(this.elem).width(Math.round(right - left));
  15408. jQuery(this.elem).height(Math.round(bottom - top));
  15409. if (this.autoFontSize)
  15410. jQuery(this.elem).css("font-size", ((this.layer.getScale(true) / this.runtime.devicePixelRatio) - 0.2) + "em");
  15411. };
  15412. instanceProto.draw = function(ctx)
  15413. {
  15414. };
  15415. instanceProto.drawGL = function(glw)
  15416. {
  15417. };
  15418. function Cnds() {};
  15419. Cnds.prototype.OnClicked = function ()
  15420. {
  15421. return true;
  15422. };
  15423. Cnds.prototype.IsChecked = function ()
  15424. {
  15425. return this.isCheckbox && this.inputElem.checked;
  15426. };
  15427. pluginProto.cnds = new Cnds();
  15428. function Acts() {};
  15429. Acts.prototype.SetText = function (text)
  15430. {
  15431. if (this.runtime.isDomFree)
  15432. return;
  15433. if (this.isCheckbox)
  15434. this.labelText.nodeValue = text;
  15435. else
  15436. this.elem.value = text;
  15437. };
  15438. Acts.prototype.SetTooltip = function (text)
  15439. {
  15440. if (this.runtime.isDomFree)
  15441. return;
  15442. this.elem.title = text;
  15443. };
  15444. Acts.prototype.SetVisible = function (vis)
  15445. {
  15446. if (this.runtime.isDomFree)
  15447. return;
  15448. this.visible = (vis !== 0);
  15449. };
  15450. Acts.prototype.SetEnabled = function (en)
  15451. {
  15452. if (this.runtime.isDomFree)
  15453. return;
  15454. this.inputElem.disabled = (en === 0);
  15455. };
  15456. Acts.prototype.SetFocus = function ()
  15457. {
  15458. if (this.runtime.isDomFree)
  15459. return;
  15460. this.inputElem.focus();
  15461. };
  15462. Acts.prototype.SetBlur = function ()
  15463. {
  15464. if (this.runtime.isDomFree)
  15465. return;
  15466. this.inputElem.blur();
  15467. };
  15468. Acts.prototype.SetCSSStyle = function (p, v)
  15469. {
  15470. if (this.runtime.isDomFree)
  15471. return;
  15472. jQuery(this.elem).css(p, v);
  15473. };
  15474. Acts.prototype.SetChecked = function (c)
  15475. {
  15476. if (this.runtime.isDomFree || !this.isCheckbox)
  15477. return;
  15478. this.inputElem.checked = (c === 1);
  15479. };
  15480. Acts.prototype.ToggleChecked = function ()
  15481. {
  15482. if (this.runtime.isDomFree || !this.isCheckbox)
  15483. return;
  15484. this.inputElem.checked = !this.inputElem.checked;
  15485. };
  15486. pluginProto.acts = new Acts();
  15487. function Exps() {};
  15488. pluginProto.exps = new Exps();
  15489. }());
  15490. ;
  15491. ;
  15492. cr.plugins_.Function = function(runtime)
  15493. {
  15494. this.runtime = runtime;
  15495. };
  15496. (function ()
  15497. {
  15498. var pluginProto = cr.plugins_.Function.prototype;
  15499. pluginProto.Type = function(plugin)
  15500. {
  15501. this.plugin = plugin;
  15502. this.runtime = plugin.runtime;
  15503. };
  15504. var typeProto = pluginProto.Type.prototype;
  15505. typeProto.onCreate = function()
  15506. {
  15507. };
  15508. pluginProto.Instance = function(type)
  15509. {
  15510. this.type = type;
  15511. this.runtime = type.runtime;
  15512. };
  15513. var instanceProto = pluginProto.Instance.prototype;
  15514. var funcStack = [];
  15515. var funcStackPtr = -1;
  15516. var isInPreview = false; // set in onCreate
  15517. function FuncStackEntry()
  15518. {
  15519. this.name = "";
  15520. this.retVal = 0;
  15521. this.params = [];
  15522. };
  15523. function pushFuncStack()
  15524. {
  15525. funcStackPtr++;
  15526. if (funcStackPtr === funcStack.length)
  15527. funcStack.push(new FuncStackEntry());
  15528. return funcStack[funcStackPtr];
  15529. };
  15530. function getCurrentFuncStack()
  15531. {
  15532. if (funcStackPtr < 0)
  15533. return null;
  15534. return funcStack[funcStackPtr];
  15535. };
  15536. function getOneAboveFuncStack()
  15537. {
  15538. if (!funcStack.length)
  15539. return null;
  15540. var i = funcStackPtr + 1;
  15541. if (i >= funcStack.length)
  15542. i = funcStack.length - 1;
  15543. return funcStack[i];
  15544. };
  15545. function popFuncStack()
  15546. {
  15547. ;
  15548. funcStackPtr--;
  15549. };
  15550. instanceProto.onCreate = function()
  15551. {
  15552. isInPreview = (typeof cr_is_preview !== "undefined");
  15553. var self = this;
  15554. window["c2_callFunction"] = function (name_, params_)
  15555. {
  15556. var i, len, v;
  15557. var fs = pushFuncStack();
  15558. fs.name = name_.toLowerCase();
  15559. fs.retVal = 0;
  15560. if (params_)
  15561. {
  15562. fs.params.length = params_.length;
  15563. for (i = 0, len = params_.length; i < len; ++i)
  15564. {
  15565. v = params_[i];
  15566. if (typeof v === "number" || typeof v === "string")
  15567. fs.params[i] = v;
  15568. else if (typeof v === "boolean")
  15569. fs.params[i] = (v ? 1 : 0);
  15570. else
  15571. fs.params[i] = 0;
  15572. }
  15573. }
  15574. else
  15575. {
  15576. cr.clearArray(fs.params);
  15577. }
  15578. self.runtime.trigger(cr.plugins_.Function.prototype.cnds.OnFunction, self, fs.name);
  15579. popFuncStack();
  15580. return fs.retVal;
  15581. };
  15582. };
  15583. function Cnds() {};
  15584. Cnds.prototype.OnFunction = function (name_)
  15585. {
  15586. var fs = getCurrentFuncStack();
  15587. if (!fs)
  15588. return false;
  15589. return cr.equals_nocase(name_, fs.name);
  15590. };
  15591. Cnds.prototype.CompareParam = function (index_, cmp_, value_)
  15592. {
  15593. var fs = getCurrentFuncStack();
  15594. if (!fs)
  15595. return false;
  15596. index_ = cr.floor(index_);
  15597. if (index_ < 0 || index_ >= fs.params.length)
  15598. return false;
  15599. return cr.do_cmp(fs.params[index_], cmp_, value_);
  15600. };
  15601. pluginProto.cnds = new Cnds();
  15602. function Acts() {};
  15603. Acts.prototype.CallFunction = function (name_, params_)
  15604. {
  15605. var fs = pushFuncStack();
  15606. fs.name = name_.toLowerCase();
  15607. fs.retVal = 0;
  15608. cr.shallowAssignArray(fs.params, params_);
  15609. var ran = this.runtime.trigger(cr.plugins_.Function.prototype.cnds.OnFunction, this, fs.name);
  15610. if (isInPreview && !ran)
  15611. {
  15612. ;
  15613. }
  15614. popFuncStack();
  15615. };
  15616. Acts.prototype.SetReturnValue = function (value_)
  15617. {
  15618. var fs = getCurrentFuncStack();
  15619. if (fs)
  15620. fs.retVal = value_;
  15621. else
  15622. ;
  15623. };
  15624. Acts.prototype.CallExpression = function (unused)
  15625. {
  15626. };
  15627. pluginProto.acts = new Acts();
  15628. function Exps() {};
  15629. Exps.prototype.ReturnValue = function (ret)
  15630. {
  15631. var fs = getOneAboveFuncStack();
  15632. if (fs)
  15633. ret.set_any(fs.retVal);
  15634. else
  15635. ret.set_int(0);
  15636. };
  15637. Exps.prototype.ParamCount = function (ret)
  15638. {
  15639. var fs = getCurrentFuncStack();
  15640. if (fs)
  15641. ret.set_int(fs.params.length);
  15642. else
  15643. {
  15644. ;
  15645. ret.set_int(0);
  15646. }
  15647. };
  15648. Exps.prototype.Param = function (ret, index_)
  15649. {
  15650. index_ = cr.floor(index_);
  15651. var fs = getCurrentFuncStack();
  15652. if (fs)
  15653. {
  15654. if (index_ >= 0 && index_ < fs.params.length)
  15655. {
  15656. ret.set_any(fs.params[index_]);
  15657. }
  15658. else
  15659. {
  15660. ;
  15661. ret.set_int(0);
  15662. }
  15663. }
  15664. else
  15665. {
  15666. ;
  15667. ret.set_int(0);
  15668. }
  15669. };
  15670. Exps.prototype.Call = function (ret, name_)
  15671. {
  15672. var fs = pushFuncStack();
  15673. fs.name = name_.toLowerCase();
  15674. fs.retVal = 0;
  15675. cr.clearArray(fs.params);
  15676. var i, len;
  15677. for (i = 2, len = arguments.length; i < len; i++)
  15678. fs.params.push(arguments[i]);
  15679. var ran = this.runtime.trigger(cr.plugins_.Function.prototype.cnds.OnFunction, this, fs.name);
  15680. if (isInPreview && !ran)
  15681. {
  15682. ;
  15683. }
  15684. popFuncStack();
  15685. ret.set_any(fs.retVal);
  15686. };
  15687. pluginProto.exps = new Exps();
  15688. }());
  15689. ;
  15690. ;
  15691. cr.plugins_.Text = function(runtime)
  15692. {
  15693. this.runtime = runtime;
  15694. };
  15695. (function ()
  15696. {
  15697. var pluginProto = cr.plugins_.Text.prototype;
  15698. pluginProto.onCreate = function ()
  15699. {
  15700. pluginProto.acts.SetWidth = function (w)
  15701. {
  15702. if (this.width !== w)
  15703. {
  15704. this.width = w;
  15705. this.text_changed = true; // also recalculate text wrapping
  15706. this.set_bbox_changed();
  15707. }
  15708. };
  15709. };
  15710. pluginProto.Type = function(plugin)
  15711. {
  15712. this.plugin = plugin;
  15713. this.runtime = plugin.runtime;
  15714. };
  15715. var typeProto = pluginProto.Type.prototype;
  15716. typeProto.onCreate = function()
  15717. {
  15718. };
  15719. typeProto.onLostWebGLContext = function ()
  15720. {
  15721. if (this.is_family)
  15722. return;
  15723. var i, len, inst;
  15724. for (i = 0, len = this.instances.length; i < len; i++)
  15725. {
  15726. inst = this.instances[i];
  15727. inst.mycanvas = null;
  15728. inst.myctx = null;
  15729. inst.mytex = null;
  15730. }
  15731. };
  15732. pluginProto.Instance = function(type)
  15733. {
  15734. this.type = type;
  15735. this.runtime = type.runtime;
  15736. if (this.recycled)
  15737. cr.clearArray(this.lines);
  15738. else
  15739. this.lines = []; // for word wrapping
  15740. this.text_changed = true;
  15741. };
  15742. var instanceProto = pluginProto.Instance.prototype;
  15743. var requestedWebFonts = {}; // already requested web fonts have an entry here
  15744. instanceProto.onCreate = function()
  15745. {
  15746. this.text = this.properties[0];
  15747. this.visible = (this.properties[1] === 0); // 0=visible, 1=invisible
  15748. this.font = this.properties[2];
  15749. this.color = this.properties[3];
  15750. this.halign = this.properties[4]; // 0=left, 1=center, 2=right
  15751. this.valign = this.properties[5]; // 0=top, 1=center, 2=bottom
  15752. this.wrapbyword = (this.properties[7] === 0); // 0=word, 1=character
  15753. this.lastwidth = this.width;
  15754. this.lastwrapwidth = this.width;
  15755. this.lastheight = this.height;
  15756. this.line_height_offset = this.properties[8];
  15757. this.facename = "";
  15758. this.fontstyle = "";
  15759. this.ptSize = 0;
  15760. this.textWidth = 0;
  15761. this.textHeight = 0;
  15762. this.parseFont();
  15763. this.mycanvas = null;
  15764. this.myctx = null;
  15765. this.mytex = null;
  15766. this.need_text_redraw = false;
  15767. this.last_render_tick = this.runtime.tickcount;
  15768. if (this.recycled)
  15769. this.rcTex.set(0, 0, 1, 1);
  15770. else
  15771. this.rcTex = new cr.rect(0, 0, 1, 1);
  15772. if (this.runtime.glwrap)
  15773. this.runtime.tickMe(this);
  15774. ;
  15775. };
  15776. instanceProto.parseFont = function ()
  15777. {
  15778. var arr = this.font.split(" ");
  15779. var i;
  15780. for (i = 0; i < arr.length; i++)
  15781. {
  15782. if (arr[i].substr(arr[i].length - 2, 2) === "pt")
  15783. {
  15784. this.ptSize = parseInt(arr[i].substr(0, arr[i].length - 2));
  15785. this.pxHeight = Math.ceil((this.ptSize / 72.0) * 96.0) + 4; // assume 96dpi...
  15786. if (i > 0)
  15787. this.fontstyle = arr[i - 1];
  15788. this.facename = arr[i + 1];
  15789. for (i = i + 2; i < arr.length; i++)
  15790. this.facename += " " + arr[i];
  15791. break;
  15792. }
  15793. }
  15794. };
  15795. instanceProto.saveToJSON = function ()
  15796. {
  15797. return {
  15798. "t": this.text,
  15799. "f": this.font,
  15800. "c": this.color,
  15801. "ha": this.halign,
  15802. "va": this.valign,
  15803. "wr": this.wrapbyword,
  15804. "lho": this.line_height_offset,
  15805. "fn": this.facename,
  15806. "fs": this.fontstyle,
  15807. "ps": this.ptSize,
  15808. "pxh": this.pxHeight,
  15809. "tw": this.textWidth,
  15810. "th": this.textHeight,
  15811. "lrt": this.last_render_tick
  15812. };
  15813. };
  15814. instanceProto.loadFromJSON = function (o)
  15815. {
  15816. this.text = o["t"];
  15817. this.font = o["f"];
  15818. this.color = o["c"];
  15819. this.halign = o["ha"];
  15820. this.valign = o["va"];
  15821. this.wrapbyword = o["wr"];
  15822. this.line_height_offset = o["lho"];
  15823. this.facename = o["fn"];
  15824. this.fontstyle = o["fs"];
  15825. this.ptSize = o["ps"];
  15826. this.pxHeight = o["pxh"];
  15827. this.textWidth = o["tw"];
  15828. this.textHeight = o["th"];
  15829. this.last_render_tick = o["lrt"];
  15830. this.text_changed = true;
  15831. this.lastwidth = this.width;
  15832. this.lastwrapwidth = this.width;
  15833. this.lastheight = this.height;
  15834. };
  15835. instanceProto.tick = function ()
  15836. {
  15837. if (this.runtime.glwrap && this.mytex && (this.runtime.tickcount - this.last_render_tick >= 300))
  15838. {
  15839. var layer = this.layer;
  15840. this.update_bbox();
  15841. var bbox = this.bbox;
  15842. if (bbox.right < layer.viewLeft || bbox.bottom < layer.viewTop || bbox.left > layer.viewRight || bbox.top > layer.viewBottom)
  15843. {
  15844. this.runtime.glwrap.deleteTexture(this.mytex);
  15845. this.mytex = null;
  15846. this.myctx = null;
  15847. this.mycanvas = null;
  15848. }
  15849. }
  15850. };
  15851. instanceProto.onDestroy = function ()
  15852. {
  15853. this.myctx = null;
  15854. this.mycanvas = null;
  15855. if (this.runtime.glwrap && this.mytex)
  15856. this.runtime.glwrap.deleteTexture(this.mytex);
  15857. this.mytex = null;
  15858. };
  15859. instanceProto.updateFont = function ()
  15860. {
  15861. this.font = this.fontstyle + " " + this.ptSize.toString() + "pt " + this.facename;
  15862. this.text_changed = true;
  15863. this.runtime.redraw = true;
  15864. };
  15865. instanceProto.draw = function(ctx, glmode)
  15866. {
  15867. ctx.font = this.font;
  15868. ctx.textBaseline = "top";
  15869. ctx.fillStyle = this.color;
  15870. ctx.globalAlpha = glmode ? 1 : this.opacity;
  15871. var myscale = 1;
  15872. if (glmode)
  15873. {
  15874. myscale = Math.abs(this.layer.getScale());
  15875. ctx.save();
  15876. ctx.scale(myscale, myscale);
  15877. }
  15878. if (this.text_changed || this.width !== this.lastwrapwidth)
  15879. {
  15880. this.type.plugin.WordWrap(this.text, this.lines, ctx, this.width, this.wrapbyword);
  15881. this.text_changed = false;
  15882. this.lastwrapwidth = this.width;
  15883. }
  15884. this.update_bbox();
  15885. var penX = glmode ? 0 : this.bquad.tlx;
  15886. var penY = glmode ? 0 : this.bquad.tly;
  15887. if (this.runtime.pixel_rounding)
  15888. {
  15889. penX = (penX + 0.5) | 0;
  15890. penY = (penY + 0.5) | 0;
  15891. }
  15892. if (this.angle !== 0 && !glmode)
  15893. {
  15894. ctx.save();
  15895. ctx.translate(penX, penY);
  15896. ctx.rotate(this.angle);
  15897. penX = 0;
  15898. penY = 0;
  15899. }
  15900. var endY = penY + this.height;
  15901. var line_height = this.pxHeight;
  15902. line_height += this.line_height_offset;
  15903. var drawX;
  15904. var i;
  15905. if (this.valign === 1) // center
  15906. penY += Math.max(this.height / 2 - (this.lines.length * line_height) / 2, 0);
  15907. else if (this.valign === 2) // bottom
  15908. penY += Math.max(this.height - (this.lines.length * line_height) - 2, 0);
  15909. for (i = 0; i < this.lines.length; i++)
  15910. {
  15911. drawX = penX;
  15912. if (this.halign === 1) // center
  15913. drawX = penX + (this.width - this.lines[i].width) / 2;
  15914. else if (this.halign === 2) // right
  15915. drawX = penX + (this.width - this.lines[i].width);
  15916. ctx.fillText(this.lines[i].text, drawX, penY);
  15917. penY += line_height;
  15918. if (penY >= endY - line_height)
  15919. break;
  15920. }
  15921. if (this.angle !== 0 || glmode)
  15922. ctx.restore();
  15923. this.last_render_tick = this.runtime.tickcount;
  15924. };
  15925. instanceProto.drawGL = function(glw)
  15926. {
  15927. if (this.width < 1 || this.height < 1)
  15928. return;
  15929. var need_redraw = this.text_changed || this.need_text_redraw;
  15930. this.need_text_redraw = false;
  15931. var layer_scale = this.layer.getScale();
  15932. var layer_angle = this.layer.getAngle();
  15933. var rcTex = this.rcTex;
  15934. var floatscaledwidth = layer_scale * this.width;
  15935. var floatscaledheight = layer_scale * this.height;
  15936. var scaledwidth = Math.ceil(floatscaledwidth);
  15937. var scaledheight = Math.ceil(floatscaledheight);
  15938. var absscaledwidth = Math.abs(scaledwidth);
  15939. var absscaledheight = Math.abs(scaledheight);
  15940. var halfw = this.runtime.draw_width / 2;
  15941. var halfh = this.runtime.draw_height / 2;
  15942. if (!this.myctx)
  15943. {
  15944. this.mycanvas = document.createElement("canvas");
  15945. this.mycanvas.width = absscaledwidth;
  15946. this.mycanvas.height = absscaledheight;
  15947. this.lastwidth = absscaledwidth;
  15948. this.lastheight = absscaledheight;
  15949. need_redraw = true;
  15950. this.myctx = this.mycanvas.getContext("2d");
  15951. }
  15952. if (absscaledwidth !== this.lastwidth || absscaledheight !== this.lastheight)
  15953. {
  15954. this.mycanvas.width = absscaledwidth;
  15955. this.mycanvas.height = absscaledheight;
  15956. if (this.mytex)
  15957. {
  15958. glw.deleteTexture(this.mytex);
  15959. this.mytex = null;
  15960. }
  15961. need_redraw = true;
  15962. }
  15963. if (need_redraw)
  15964. {
  15965. this.myctx.clearRect(0, 0, absscaledwidth, absscaledheight);
  15966. this.draw(this.myctx, true);
  15967. if (!this.mytex)
  15968. this.mytex = glw.createEmptyTexture(absscaledwidth, absscaledheight, this.runtime.linearSampling, this.runtime.isMobile);
  15969. glw.videoToTexture(this.mycanvas, this.mytex, this.runtime.isMobile);
  15970. }
  15971. this.lastwidth = absscaledwidth;
  15972. this.lastheight = absscaledheight;
  15973. glw.setTexture(this.mytex);
  15974. glw.setOpacity(this.opacity);
  15975. glw.resetModelView();
  15976. glw.translate(-halfw, -halfh);
  15977. glw.updateModelView();
  15978. var q = this.bquad;
  15979. var tlx = this.layer.layerToCanvas(q.tlx, q.tly, true, true);
  15980. var tly = this.layer.layerToCanvas(q.tlx, q.tly, false, true);
  15981. var trx = this.layer.layerToCanvas(q.trx, q.try_, true, true);
  15982. var try_ = this.layer.layerToCanvas(q.trx, q.try_, false, true);
  15983. var brx = this.layer.layerToCanvas(q.brx, q.bry, true, true);
  15984. var bry = this.layer.layerToCanvas(q.brx, q.bry, false, true);
  15985. var blx = this.layer.layerToCanvas(q.blx, q.bly, true, true);
  15986. var bly = this.layer.layerToCanvas(q.blx, q.bly, false, true);
  15987. if (this.runtime.pixel_rounding || (this.angle === 0 && layer_angle === 0))
  15988. {
  15989. var ox = ((tlx + 0.5) | 0) - tlx;
  15990. var oy = ((tly + 0.5) | 0) - tly
  15991. tlx += ox;
  15992. tly += oy;
  15993. trx += ox;
  15994. try_ += oy;
  15995. brx += ox;
  15996. bry += oy;
  15997. blx += ox;
  15998. bly += oy;
  15999. }
  16000. if (this.angle === 0 && layer_angle === 0)
  16001. {
  16002. trx = tlx + scaledwidth;
  16003. try_ = tly;
  16004. brx = trx;
  16005. bry = tly + scaledheight;
  16006. blx = tlx;
  16007. bly = bry;
  16008. rcTex.right = 1;
  16009. rcTex.bottom = 1;
  16010. }
  16011. else
  16012. {
  16013. rcTex.right = floatscaledwidth / scaledwidth;
  16014. rcTex.bottom = floatscaledheight / scaledheight;
  16015. }
  16016. glw.quadTex(tlx, tly, trx, try_, brx, bry, blx, bly, rcTex);
  16017. glw.resetModelView();
  16018. glw.scale(layer_scale, layer_scale);
  16019. glw.rotateZ(-this.layer.getAngle());
  16020. glw.translate((this.layer.viewLeft + this.layer.viewRight) / -2, (this.layer.viewTop + this.layer.viewBottom) / -2);
  16021. glw.updateModelView();
  16022. this.last_render_tick = this.runtime.tickcount;
  16023. };
  16024. var wordsCache = [];
  16025. pluginProto.TokeniseWords = function (text)
  16026. {
  16027. cr.clearArray(wordsCache);
  16028. var cur_word = "";
  16029. var ch;
  16030. var i = 0;
  16031. while (i < text.length)
  16032. {
  16033. ch = text.charAt(i);
  16034. if (ch === "\n")
  16035. {
  16036. if (cur_word.length)
  16037. {
  16038. wordsCache.push(cur_word);
  16039. cur_word = "";
  16040. }
  16041. wordsCache.push("\n");
  16042. ++i;
  16043. }
  16044. else if (ch === " " || ch === "\t" || ch === "-")
  16045. {
  16046. do {
  16047. cur_word += text.charAt(i);
  16048. i++;
  16049. }
  16050. while (i < text.length && (text.charAt(i) === " " || text.charAt(i) === "\t"));
  16051. wordsCache.push(cur_word);
  16052. cur_word = "";
  16053. }
  16054. else if (i < text.length)
  16055. {
  16056. cur_word += ch;
  16057. i++;
  16058. }
  16059. }
  16060. if (cur_word.length)
  16061. wordsCache.push(cur_word);
  16062. };
  16063. var linesCache = [];
  16064. function allocLine()
  16065. {
  16066. if (linesCache.length)
  16067. return linesCache.pop();
  16068. else
  16069. return {};
  16070. };
  16071. function freeLine(l)
  16072. {
  16073. linesCache.push(l);
  16074. };
  16075. function freeAllLines(arr)
  16076. {
  16077. var i, len;
  16078. for (i = 0, len = arr.length; i < len; i++)
  16079. {
  16080. freeLine(arr[i]);
  16081. }
  16082. cr.clearArray(arr);
  16083. };
  16084. pluginProto.WordWrap = function (text, lines, ctx, width, wrapbyword)
  16085. {
  16086. if (!text || !text.length)
  16087. {
  16088. freeAllLines(lines);
  16089. return;
  16090. }
  16091. if (width <= 2.0)
  16092. {
  16093. freeAllLines(lines);
  16094. return;
  16095. }
  16096. if (text.length <= 100 && text.indexOf("\n") === -1)
  16097. {
  16098. var all_width = ctx.measureText(text).width;
  16099. if (all_width <= width)
  16100. {
  16101. freeAllLines(lines);
  16102. lines.push(allocLine());
  16103. lines[0].text = text;
  16104. lines[0].width = all_width;
  16105. return;
  16106. }
  16107. }
  16108. this.WrapText(text, lines, ctx, width, wrapbyword);
  16109. };
  16110. function trimSingleSpaceRight(str)
  16111. {
  16112. if (!str.length || str.charAt(str.length - 1) !== " ")
  16113. return str;
  16114. return str.substring(0, str.length - 1);
  16115. };
  16116. pluginProto.WrapText = function (text, lines, ctx, width, wrapbyword)
  16117. {
  16118. var wordArray;
  16119. if (wrapbyword)
  16120. {
  16121. this.TokeniseWords(text); // writes to wordsCache
  16122. wordArray = wordsCache;
  16123. }
  16124. else
  16125. wordArray = text;
  16126. var cur_line = "";
  16127. var prev_line;
  16128. var line_width;
  16129. var i;
  16130. var lineIndex = 0;
  16131. var line;
  16132. for (i = 0; i < wordArray.length; i++)
  16133. {
  16134. if (wordArray[i] === "\n")
  16135. {
  16136. if (lineIndex >= lines.length)
  16137. lines.push(allocLine());
  16138. cur_line = trimSingleSpaceRight(cur_line); // for correct center/right alignment
  16139. line = lines[lineIndex];
  16140. line.text = cur_line;
  16141. line.width = ctx.measureText(cur_line).width;
  16142. lineIndex++;
  16143. cur_line = "";
  16144. continue;
  16145. }
  16146. prev_line = cur_line;
  16147. cur_line += wordArray[i];
  16148. line_width = ctx.measureText(cur_line).width;
  16149. if (line_width >= width)
  16150. {
  16151. if (lineIndex >= lines.length)
  16152. lines.push(allocLine());
  16153. prev_line = trimSingleSpaceRight(prev_line);
  16154. line = lines[lineIndex];
  16155. line.text = prev_line;
  16156. line.width = ctx.measureText(prev_line).width;
  16157. lineIndex++;
  16158. cur_line = wordArray[i];
  16159. if (!wrapbyword && cur_line === " ")
  16160. cur_line = "";
  16161. }
  16162. }
  16163. if (cur_line.length)
  16164. {
  16165. if (lineIndex >= lines.length)
  16166. lines.push(allocLine());
  16167. cur_line = trimSingleSpaceRight(cur_line);
  16168. line = lines[lineIndex];
  16169. line.text = cur_line;
  16170. line.width = ctx.measureText(cur_line).width;
  16171. lineIndex++;
  16172. }
  16173. for (i = lineIndex; i < lines.length; i++)
  16174. freeLine(lines[i]);
  16175. lines.length = lineIndex;
  16176. };
  16177. function Cnds() {};
  16178. Cnds.prototype.CompareText = function(text_to_compare, case_sensitive)
  16179. {
  16180. if (case_sensitive)
  16181. return this.text == text_to_compare;
  16182. else
  16183. return cr.equals_nocase(this.text, text_to_compare);
  16184. };
  16185. pluginProto.cnds = new Cnds();
  16186. function Acts() {};
  16187. Acts.prototype.SetText = function(param)
  16188. {
  16189. if (cr.is_number(param) && param < 1e9)
  16190. param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors
  16191. var text_to_set = param.toString();
  16192. if (this.text !== text_to_set)
  16193. {
  16194. this.text = text_to_set;
  16195. this.text_changed = true;
  16196. this.runtime.redraw = true;
  16197. }
  16198. };
  16199. Acts.prototype.AppendText = function(param)
  16200. {
  16201. if (cr.is_number(param))
  16202. param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors
  16203. var text_to_append = param.toString();
  16204. if (text_to_append) // not empty
  16205. {
  16206. this.text += text_to_append;
  16207. this.text_changed = true;
  16208. this.runtime.redraw = true;
  16209. }
  16210. };
  16211. Acts.prototype.SetFontFace = function (face_, style_)
  16212. {
  16213. var newstyle = "";
  16214. switch (style_) {
  16215. case 1: newstyle = "bold"; break;
  16216. case 2: newstyle = "italic"; break;
  16217. case 3: newstyle = "bold italic"; break;
  16218. }
  16219. if (face_ === this.facename && newstyle === this.fontstyle)
  16220. return; // no change
  16221. this.facename = face_;
  16222. this.fontstyle = newstyle;
  16223. this.updateFont();
  16224. };
  16225. Acts.prototype.SetFontSize = function (size_)
  16226. {
  16227. if (this.ptSize === size_)
  16228. return;
  16229. this.ptSize = size_;
  16230. this.pxHeight = Math.ceil((this.ptSize / 72.0) * 96.0) + 4; // assume 96dpi...
  16231. this.updateFont();
  16232. };
  16233. Acts.prototype.SetFontColor = function (rgb)
  16234. {
  16235. var newcolor = "rgb(" + cr.GetRValue(rgb).toString() + "," + cr.GetGValue(rgb).toString() + "," + cr.GetBValue(rgb).toString() + ")";
  16236. if (newcolor === this.color)
  16237. return;
  16238. this.color = newcolor;
  16239. this.need_text_redraw = true;
  16240. this.runtime.redraw = true;
  16241. };
  16242. Acts.prototype.SetWebFont = function (familyname_, cssurl_)
  16243. {
  16244. if (this.runtime.isDomFree)
  16245. {
  16246. cr.logexport("[Construct 2] Text plugin: 'Set web font' not supported on this platform - the action has been ignored");
  16247. return; // DC todo
  16248. }
  16249. var self = this;
  16250. var refreshFunc = (function () {
  16251. self.runtime.redraw = true;
  16252. self.text_changed = true;
  16253. });
  16254. if (requestedWebFonts.hasOwnProperty(cssurl_))
  16255. {
  16256. var newfacename = "'" + familyname_ + "'";
  16257. if (this.facename === newfacename)
  16258. return; // no change
  16259. this.facename = newfacename;
  16260. this.updateFont();
  16261. for (var i = 1; i < 10; i++)
  16262. {
  16263. setTimeout(refreshFunc, i * 100);
  16264. setTimeout(refreshFunc, i * 1000);
  16265. }
  16266. return;
  16267. }
  16268. var wf = document.createElement("link");
  16269. wf.href = cssurl_;
  16270. wf.rel = "stylesheet";
  16271. wf.type = "text/css";
  16272. wf.onload = refreshFunc;
  16273. document.getElementsByTagName('head')[0].appendChild(wf);
  16274. requestedWebFonts[cssurl_] = true;
  16275. this.facename = "'" + familyname_ + "'";
  16276. this.updateFont();
  16277. for (var i = 1; i < 10; i++)
  16278. {
  16279. setTimeout(refreshFunc, i * 100);
  16280. setTimeout(refreshFunc, i * 1000);
  16281. }
  16282. ;
  16283. };
  16284. Acts.prototype.SetEffect = function (effect)
  16285. {
  16286. this.blend_mode = effect;
  16287. this.compositeOp = cr.effectToCompositeOp(effect);
  16288. cr.setGLBlend(this, effect, this.runtime.gl);
  16289. this.runtime.redraw = true;
  16290. };
  16291. pluginProto.acts = new Acts();
  16292. function Exps() {};
  16293. Exps.prototype.Text = function(ret)
  16294. {
  16295. ret.set_string(this.text);
  16296. };
  16297. Exps.prototype.FaceName = function (ret)
  16298. {
  16299. ret.set_string(this.facename);
  16300. };
  16301. Exps.prototype.FaceSize = function (ret)
  16302. {
  16303. ret.set_int(this.ptSize);
  16304. };
  16305. Exps.prototype.TextWidth = function (ret)
  16306. {
  16307. var w = 0;
  16308. var i, len, x;
  16309. for (i = 0, len = this.lines.length; i < len; i++)
  16310. {
  16311. x = this.lines[i].width;
  16312. if (w < x)
  16313. w = x;
  16314. }
  16315. ret.set_int(w);
  16316. };
  16317. Exps.prototype.TextHeight = function (ret)
  16318. {
  16319. ret.set_int(this.lines.length * (this.pxHeight + this.line_height_offset) - this.line_height_offset);
  16320. };
  16321. pluginProto.exps = new Exps();
  16322. }());
  16323. ;
  16324. ;
  16325. cr.plugins_.TextBox = function(runtime)
  16326. {
  16327. this.runtime = runtime;
  16328. };
  16329. (function ()
  16330. {
  16331. var pluginProto = cr.plugins_.TextBox.prototype;
  16332. pluginProto.Type = function(plugin)
  16333. {
  16334. this.plugin = plugin;
  16335. this.runtime = plugin.runtime;
  16336. };
  16337. var typeProto = pluginProto.Type.prototype;
  16338. typeProto.onCreate = function()
  16339. {
  16340. };
  16341. pluginProto.Instance = function(type)
  16342. {
  16343. this.type = type;
  16344. this.runtime = type.runtime;
  16345. };
  16346. var instanceProto = pluginProto.Instance.prototype;
  16347. var elemTypes = ["text", "password", "email", "number", "tel", "url"];
  16348. if (navigator.userAgent.indexOf("MSIE 9") > -1)
  16349. {
  16350. elemTypes[2] = "text";
  16351. elemTypes[3] = "text";
  16352. elemTypes[4] = "text";
  16353. elemTypes[5] = "text";
  16354. }
  16355. instanceProto.onCreate = function()
  16356. {
  16357. if (this.runtime.isDomFree)
  16358. {
  16359. cr.logexport("[Construct 2] Textbox plugin not supported on this platform - the object will not be created");
  16360. return;
  16361. }
  16362. if (this.properties[7] === 6) // textarea
  16363. {
  16364. this.elem = document.createElement("textarea");
  16365. jQuery(this.elem).css("resize", "none");
  16366. }
  16367. else
  16368. {
  16369. this.elem = document.createElement("input");
  16370. this.elem.type = elemTypes[this.properties[7]];
  16371. }
  16372. this.elem.id = this.properties[9];
  16373. jQuery(this.elem).appendTo(this.runtime.canvasdiv ? this.runtime.canvasdiv : "body");
  16374. this.elem["autocomplete"] = "off";
  16375. this.elem.value = this.properties[0];
  16376. this.elem["placeholder"] = this.properties[1];
  16377. this.elem.title = this.properties[2];
  16378. this.elem.disabled = (this.properties[4] === 0);
  16379. this.elem["readOnly"] = (this.properties[5] === 1);
  16380. this.elem["spellcheck"] = (this.properties[6] === 1);
  16381. this.autoFontSize = (this.properties[8] !== 0);
  16382. this.element_hidden = false;
  16383. if (this.properties[3] === 0)
  16384. {
  16385. jQuery(this.elem).hide();
  16386. this.visible = false;
  16387. this.element_hidden = true;
  16388. }
  16389. var onchangetrigger = (function (self) {
  16390. return function() {
  16391. self.runtime.trigger(cr.plugins_.TextBox.prototype.cnds.OnTextChanged, self);
  16392. };
  16393. })(this);
  16394. this.elem["oninput"] = onchangetrigger;
  16395. if (navigator.userAgent.indexOf("MSIE") !== -1)
  16396. this.elem["oncut"] = onchangetrigger;
  16397. this.elem.onclick = (function (self) {
  16398. return function(e) {
  16399. e.stopPropagation();
  16400. self.runtime.isInUserInputEvent = true;
  16401. self.runtime.trigger(cr.plugins_.TextBox.prototype.cnds.OnClicked, self);
  16402. self.runtime.isInUserInputEvent = false;
  16403. };
  16404. })(this);
  16405. this.elem.ondblclick = (function (self) {
  16406. return function(e) {
  16407. e.stopPropagation();
  16408. self.runtime.isInUserInputEvent = true;
  16409. self.runtime.trigger(cr.plugins_.TextBox.prototype.cnds.OnDoubleClicked, self);
  16410. self.runtime.isInUserInputEvent = false;
  16411. };
  16412. })(this);
  16413. this.elem.addEventListener("touchstart", function (e) {
  16414. e.stopPropagation();
  16415. }, false);
  16416. this.elem.addEventListener("touchmove", function (e) {
  16417. e.stopPropagation();
  16418. }, false);
  16419. this.elem.addEventListener("touchend", function (e) {
  16420. e.stopPropagation();
  16421. }, false);
  16422. jQuery(this.elem).mousedown(function (e) {
  16423. e.stopPropagation();
  16424. });
  16425. jQuery(this.elem).mouseup(function (e) {
  16426. e.stopPropagation();
  16427. });
  16428. jQuery(this.elem).keydown(function (e) {
  16429. if (e.which !== 13 && e.which != 27) // allow enter and escape
  16430. e.stopPropagation();
  16431. });
  16432. jQuery(this.elem).keyup(function (e) {
  16433. if (e.which !== 13 && e.which != 27) // allow enter and escape
  16434. e.stopPropagation();
  16435. });
  16436. this.lastLeft = 0;
  16437. this.lastTop = 0;
  16438. this.lastRight = 0;
  16439. this.lastBottom = 0;
  16440. this.lastWinWidth = 0;
  16441. this.lastWinHeight = 0;
  16442. this.updatePosition(true);
  16443. this.runtime.tickMe(this);
  16444. };
  16445. instanceProto.saveToJSON = function ()
  16446. {
  16447. return {
  16448. "text": this.elem.value,
  16449. "placeholder": this.elem.placeholder,
  16450. "tooltip": this.elem.title,
  16451. "disabled": !!this.elem.disabled,
  16452. "readonly": !!this.elem.readOnly,
  16453. "spellcheck": !!this.elem["spellcheck"]
  16454. };
  16455. };
  16456. instanceProto.loadFromJSON = function (o)
  16457. {
  16458. this.elem.value = o["text"];
  16459. this.elem.placeholder = o["placeholder"];
  16460. this.elem.title = o["tooltip"];
  16461. this.elem.disabled = o["disabled"];
  16462. this.elem.readOnly = o["readonly"];
  16463. this.elem["spellcheck"] = o["spellcheck"];
  16464. };
  16465. instanceProto.onDestroy = function ()
  16466. {
  16467. if (this.runtime.isDomFree)
  16468. return;
  16469. jQuery(this.elem).remove();
  16470. this.elem = null;
  16471. };
  16472. instanceProto.tick = function ()
  16473. {
  16474. this.updatePosition();
  16475. };
  16476. instanceProto.updatePosition = function (first)
  16477. {
  16478. if (this.runtime.isDomFree)
  16479. return;
  16480. var left = this.layer.layerToCanvas(this.x, this.y, true);
  16481. var top = this.layer.layerToCanvas(this.x, this.y, false);
  16482. var right = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, true);
  16483. var bottom = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, false);
  16484. var rightEdge = this.runtime.width / this.runtime.devicePixelRatio;
  16485. var bottomEdge = this.runtime.height / this.runtime.devicePixelRatio;
  16486. if (!this.visible || !this.layer.visible || right <= 0 || bottom <= 0 || left >= rightEdge || top >= bottomEdge)
  16487. {
  16488. if (!this.element_hidden)
  16489. jQuery(this.elem).hide();
  16490. this.element_hidden = true;
  16491. return;
  16492. }
  16493. if (left < 1)
  16494. left = 1;
  16495. if (top < 1)
  16496. top = 1;
  16497. if (right >= rightEdge)
  16498. right = rightEdge - 1;
  16499. if (bottom >= bottomEdge)
  16500. bottom = bottomEdge - 1;
  16501. var curWinWidth = window.innerWidth;
  16502. var curWinHeight = window.innerHeight;
  16503. if (!first && this.lastLeft === left && this.lastTop === top && this.lastRight === right && this.lastBottom === bottom && this.lastWinWidth === curWinWidth && this.lastWinHeight === curWinHeight)
  16504. {
  16505. if (this.element_hidden)
  16506. {
  16507. jQuery(this.elem).show();
  16508. this.element_hidden = false;
  16509. }
  16510. return;
  16511. }
  16512. this.lastLeft = left;
  16513. this.lastTop = top;
  16514. this.lastRight = right;
  16515. this.lastBottom = bottom;
  16516. this.lastWinWidth = curWinWidth;
  16517. this.lastWinHeight = curWinHeight;
  16518. if (this.element_hidden)
  16519. {
  16520. jQuery(this.elem).show();
  16521. this.element_hidden = false;
  16522. }
  16523. var offx = Math.round(left) + jQuery(this.runtime.canvas).offset().left;
  16524. var offy = Math.round(top) + jQuery(this.runtime.canvas).offset().top;
  16525. jQuery(this.elem).css("position", "absolute");
  16526. jQuery(this.elem).offset({left: offx, top: offy});
  16527. jQuery(this.elem).width(Math.round(right - left));
  16528. jQuery(this.elem).height(Math.round(bottom - top));
  16529. if (this.autoFontSize)
  16530. jQuery(this.elem).css("font-size", ((this.layer.getScale(true) / this.runtime.devicePixelRatio) - 0.2) + "em");
  16531. };
  16532. instanceProto.draw = function(ctx)
  16533. {
  16534. };
  16535. instanceProto.drawGL = function(glw)
  16536. {
  16537. };
  16538. function Cnds() {};
  16539. Cnds.prototype.CompareText = function (text, case_)
  16540. {
  16541. if (this.runtime.isDomFree)
  16542. return false;
  16543. if (case_ === 0) // insensitive
  16544. return cr.equals_nocase(this.elem.value, text);
  16545. else
  16546. return this.elem.value === text;
  16547. };
  16548. Cnds.prototype.OnTextChanged = function ()
  16549. {
  16550. return true;
  16551. };
  16552. Cnds.prototype.OnClicked = function ()
  16553. {
  16554. return true;
  16555. };
  16556. Cnds.prototype.OnDoubleClicked = function ()
  16557. {
  16558. return true;
  16559. };
  16560. pluginProto.cnds = new Cnds();
  16561. function Acts() {};
  16562. Acts.prototype.SetText = function (text)
  16563. {
  16564. if (this.runtime.isDomFree)
  16565. return;
  16566. this.elem.value = text;
  16567. };
  16568. Acts.prototype.SetPlaceholder = function (text)
  16569. {
  16570. if (this.runtime.isDomFree)
  16571. return;
  16572. this.elem.placeholder = text;
  16573. };
  16574. Acts.prototype.SetTooltip = function (text)
  16575. {
  16576. if (this.runtime.isDomFree)
  16577. return;
  16578. this.elem.title = text;
  16579. };
  16580. Acts.prototype.SetVisible = function (vis)
  16581. {
  16582. if (this.runtime.isDomFree)
  16583. return;
  16584. this.visible = (vis !== 0);
  16585. };
  16586. Acts.prototype.SetEnabled = function (en)
  16587. {
  16588. if (this.runtime.isDomFree)
  16589. return;
  16590. this.elem.disabled = (en === 0);
  16591. };
  16592. Acts.prototype.SetReadOnly = function (ro)
  16593. {
  16594. if (this.runtime.isDomFree)
  16595. return;
  16596. this.elem.readOnly = (ro === 0);
  16597. };
  16598. Acts.prototype.SetFocus = function ()
  16599. {
  16600. if (this.runtime.isDomFree)
  16601. return;
  16602. this.elem.focus();
  16603. };
  16604. Acts.prototype.SetBlur = function ()
  16605. {
  16606. if (this.runtime.isDomFree)
  16607. return;
  16608. this.elem.blur();
  16609. };
  16610. Acts.prototype.SetCSSStyle = function (p, v)
  16611. {
  16612. if (this.runtime.isDomFree)
  16613. return;
  16614. jQuery(this.elem).css(p, v);
  16615. };
  16616. Acts.prototype.ScrollToBottom = function ()
  16617. {
  16618. if (this.runtime.isDomFree)
  16619. return;
  16620. this.elem.scrollTop = this.elem.scrollHeight;
  16621. };
  16622. pluginProto.acts = new Acts();
  16623. function Exps() {};
  16624. Exps.prototype.Text = function (ret)
  16625. {
  16626. if (this.runtime.isDomFree)
  16627. {
  16628. ret.set_string("");
  16629. return;
  16630. }
  16631. ret.set_string(this.elem.value);
  16632. };
  16633. pluginProto.exps = new Exps();
  16634. }());
  16635. ;
  16636. ;
  16637. cr.plugins_.TiledBg = function(runtime)
  16638. {
  16639. this.runtime = runtime;
  16640. };
  16641. (function ()
  16642. {
  16643. var pluginProto = cr.plugins_.TiledBg.prototype;
  16644. pluginProto.Type = function(plugin)
  16645. {
  16646. this.plugin = plugin;
  16647. this.runtime = plugin.runtime;
  16648. };
  16649. var typeProto = pluginProto.Type.prototype;
  16650. typeProto.onCreate = function()
  16651. {
  16652. if (this.is_family)
  16653. return;
  16654. this.texture_img = new Image();
  16655. this.texture_img.cr_filesize = this.texture_filesize;
  16656. this.runtime.waitForImageLoad(this.texture_img, this.texture_file);
  16657. this.pattern = null;
  16658. this.webGL_texture = null;
  16659. };
  16660. typeProto.onLostWebGLContext = function ()
  16661. {
  16662. if (this.is_family)
  16663. return;
  16664. this.webGL_texture = null;
  16665. };
  16666. typeProto.onRestoreWebGLContext = function ()
  16667. {
  16668. if (this.is_family || !this.instances.length)
  16669. return;
  16670. if (!this.webGL_texture)
  16671. {
  16672. this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, true, this.runtime.linearSampling, this.texture_pixelformat);
  16673. }
  16674. var i, len;
  16675. for (i = 0, len = this.instances.length; i < len; i++)
  16676. this.instances[i].webGL_texture = this.webGL_texture;
  16677. };
  16678. typeProto.loadTextures = function ()
  16679. {
  16680. if (this.is_family || this.webGL_texture || !this.runtime.glwrap)
  16681. return;
  16682. this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, true, this.runtime.linearSampling, this.texture_pixelformat);
  16683. };
  16684. typeProto.unloadTextures = function ()
  16685. {
  16686. if (this.is_family || this.instances.length || !this.webGL_texture)
  16687. return;
  16688. this.runtime.glwrap.deleteTexture(this.webGL_texture);
  16689. this.webGL_texture = null;
  16690. };
  16691. typeProto.preloadCanvas2D = function (ctx)
  16692. {
  16693. ctx.drawImage(this.texture_img, 0, 0);
  16694. };
  16695. pluginProto.Instance = function(type)
  16696. {
  16697. this.type = type;
  16698. this.runtime = type.runtime;
  16699. };
  16700. var instanceProto = pluginProto.Instance.prototype;
  16701. instanceProto.onCreate = function()
  16702. {
  16703. this.visible = (this.properties[0] === 0); // 0=visible, 1=invisible
  16704. this.rcTex = new cr.rect(0, 0, 0, 0);
  16705. this.has_own_texture = false; // true if a texture loaded in from URL
  16706. this.texture_img = this.type.texture_img;
  16707. if (this.runtime.glwrap)
  16708. {
  16709. this.type.loadTextures();
  16710. this.webGL_texture = this.type.webGL_texture;
  16711. }
  16712. else
  16713. {
  16714. if (!this.type.pattern)
  16715. this.type.pattern = this.runtime.ctx.createPattern(this.type.texture_img, "repeat");
  16716. this.pattern = this.type.pattern;
  16717. }
  16718. };
  16719. instanceProto.afterLoad = function ()
  16720. {
  16721. this.has_own_texture = false;
  16722. this.texture_img = this.type.texture_img;
  16723. };
  16724. instanceProto.onDestroy = function ()
  16725. {
  16726. if (this.runtime.glwrap && this.has_own_texture && this.webGL_texture)
  16727. {
  16728. this.runtime.glwrap.deleteTexture(this.webGL_texture);
  16729. this.webGL_texture = null;
  16730. }
  16731. };
  16732. instanceProto.draw = function(ctx)
  16733. {
  16734. ctx.globalAlpha = this.opacity;
  16735. ctx.save();
  16736. ctx.fillStyle = this.pattern;
  16737. var myx = this.x;
  16738. var myy = this.y;
  16739. if (this.runtime.pixel_rounding)
  16740. {
  16741. myx = Math.round(myx);
  16742. myy = Math.round(myy);
  16743. }
  16744. var drawX = -(this.hotspotX * this.width);
  16745. var drawY = -(this.hotspotY * this.height);
  16746. var offX = drawX % this.texture_img.width;
  16747. var offY = drawY % this.texture_img.height;
  16748. if (offX < 0)
  16749. offX += this.texture_img.width;
  16750. if (offY < 0)
  16751. offY += this.texture_img.height;
  16752. ctx.translate(myx, myy);
  16753. ctx.rotate(this.angle);
  16754. ctx.translate(offX, offY);
  16755. ctx.fillRect(drawX - offX,
  16756. drawY - offY,
  16757. this.width,
  16758. this.height);
  16759. ctx.restore();
  16760. };
  16761. instanceProto.drawGL_earlyZPass = function(glw)
  16762. {
  16763. this.drawGL(glw);
  16764. };
  16765. instanceProto.drawGL = function(glw)
  16766. {
  16767. glw.setTexture(this.webGL_texture);
  16768. glw.setOpacity(this.opacity);
  16769. var rcTex = this.rcTex;
  16770. rcTex.right = this.width / this.texture_img.width;
  16771. rcTex.bottom = this.height / this.texture_img.height;
  16772. var q = this.bquad;
  16773. if (this.runtime.pixel_rounding)
  16774. {
  16775. var ox = Math.round(this.x) - this.x;
  16776. var oy = Math.round(this.y) - this.y;
  16777. glw.quadTex(q.tlx + ox, q.tly + oy, q.trx + ox, q.try_ + oy, q.brx + ox, q.bry + oy, q.blx + ox, q.bly + oy, rcTex);
  16778. }
  16779. else
  16780. glw.quadTex(q.tlx, q.tly, q.trx, q.try_, q.brx, q.bry, q.blx, q.bly, rcTex);
  16781. };
  16782. function Cnds() {};
  16783. Cnds.prototype.OnURLLoaded = function ()
  16784. {
  16785. return true;
  16786. };
  16787. pluginProto.cnds = new Cnds();
  16788. function Acts() {};
  16789. Acts.prototype.SetEffect = function (effect)
  16790. {
  16791. this.blend_mode = effect;
  16792. this.compositeOp = cr.effectToCompositeOp(effect);
  16793. cr.setGLBlend(this, effect, this.runtime.gl);
  16794. this.runtime.redraw = true;
  16795. };
  16796. Acts.prototype.LoadURL = function (url_, crossOrigin_)
  16797. {
  16798. var img = new Image();
  16799. var self = this;
  16800. img.onload = function ()
  16801. {
  16802. self.texture_img = img;
  16803. if (self.runtime.glwrap)
  16804. {
  16805. if (self.has_own_texture && self.webGL_texture)
  16806. self.runtime.glwrap.deleteTexture(self.webGL_texture);
  16807. self.webGL_texture = self.runtime.glwrap.loadTexture(img, true, self.runtime.linearSampling);
  16808. }
  16809. else
  16810. {
  16811. self.pattern = self.runtime.ctx.createPattern(img, "repeat");
  16812. }
  16813. self.has_own_texture = true;
  16814. self.runtime.redraw = true;
  16815. self.runtime.trigger(cr.plugins_.TiledBg.prototype.cnds.OnURLLoaded, self);
  16816. };
  16817. if (url_.substr(0, 5) !== "data:" && crossOrigin_ === 0)
  16818. img.crossOrigin = "anonymous";
  16819. this.runtime.setImageSrc(img, url_);
  16820. };
  16821. pluginProto.acts = new Acts();
  16822. function Exps() {};
  16823. Exps.prototype.ImageWidth = function (ret)
  16824. {
  16825. ret.set_float(this.texture_img.width);
  16826. };
  16827. Exps.prototype.ImageHeight = function (ret)
  16828. {
  16829. ret.set_float(this.texture_img.height);
  16830. };
  16831. pluginProto.exps = new Exps();
  16832. }());
  16833. ;
  16834. ;
  16835. cr.plugins_.sirg_wickeyappstore = function (runtime) {
  16836. this.runtime = runtime;
  16837. };
  16838. (function () {
  16839. var pluginProto = cr.plugins_.sirg_wickeyappstore.prototype;
  16840. pluginProto.Type = function (plugin) {
  16841. this.plugin = plugin;
  16842. this.runtime = plugin.runtime;
  16843. };
  16844. var typeProto = pluginProto.Type.prototype;
  16845. typeProto.onCreate = function () {};
  16846. pluginProto.Instance = function (type) {
  16847. this.type = type;
  16848. this.runtime = type.runtime;
  16849. };
  16850. var instanceProto = pluginProto.Instance.prototype;
  16851. instanceProto.onCreate = function () {
  16852. var el = "wickey-appstore";
  16853. var was = "WAS";
  16854. var userService = "userService";
  16855. var dataService = "dataService";
  16856. this.wickeyappstore = document.querySelector(el);
  16857. this.userService = window[was][userService];
  16858. this.dataService = window[was][dataService];
  16859. this.isOpened = false;
  16860. this.isLogged = false;
  16861. this.error = "";
  16862. this.leaderboard = [];
  16863. this.rank = 0;
  16864. this.openPayId = 0;
  16865. this.openPayStatus = false;
  16866. this.checkIfPurchasedId = 0;
  16867. this.checkIfPurchasedStatus = false;
  16868. var self = this;
  16869. this.wickeyappstore.addEventListener("open", function (event) {
  16870. self.isOpened = true;
  16871. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onOpen, self);
  16872. });
  16873. this.dataService["data"].subscribe(function (mydata) {
  16874. self.localData = mydata;
  16875. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onDataUpdate, self);
  16876. });
  16877. function onSaveConflict(localSave, cloudSave) {
  16878. var keepSave = localSave;
  16879. if (localSave && cloudSave) {
  16880. if (cloudSave.highScore > localSave.highScore) {
  16881. keepSave = cloudSave;
  16882. }
  16883. }
  16884. return keepSave;
  16885. }
  16886. this.dataService["restore"](onSaveConflict).subscribe(function (mydata) {
  16887. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onDataRestored, self);
  16888. });
  16889. this.userService["loginChange"].subscribe(function (_isLogged) {
  16890. self.isLogged = _isLogged;
  16891. self.runtime.trigger(
  16892. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onLoginChange,
  16893. self
  16894. );
  16895. });
  16896. this.userService["user"].subscribe(function (usr) {
  16897. self.userData = usr;
  16898. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onUserUpdate, self);
  16899. });
  16900. };
  16901. instanceProto.getLeaderboard = function () {
  16902. var self = this;
  16903. this.userService["getLeaderboard"](this.userData["username"]).subscribe(function (res) {
  16904. self.leaderboard = res["leaderboard"];
  16905. self.rank = res["rank"];
  16906. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onLeaderboardGet,self);
  16907. });
  16908. };
  16909. instanceProto.onSetUserNameError = function (error) {
  16910. this.error = error;
  16911. this.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onError,this);
  16912. };
  16913. instanceProto.onDestroy = function () {};
  16914. instanceProto.saveToJSON = function () {return {};};
  16915. instanceProto.loadFromJSON = function (o) {};
  16916. instanceProto.draw = function (ctx) {};
  16917. instanceProto.drawGL = function (glw) {};
  16918. instanceProto.drawGL = function (glw) {};
  16919. function Cnds() {}
  16920. Cnds.prototype.onOpen = function () {return true;};
  16921. Cnds.prototype.onDataUpdate = function () {return true;};
  16922. Cnds.prototype.onDataRestored = function () {return true;};
  16923. Cnds.prototype.onLoginChange = function () {return true;};
  16924. Cnds.prototype.onUserUpdate = function () {return true;};
  16925. Cnds.prototype.onLeaderboardGet = function () {return true;};
  16926. Cnds.prototype.onError = function () {return true;};
  16927. Cnds.prototype.onPayWindowTrigger = function (id) {
  16928. id = parseInt(id);
  16929. return cr.equals_nocase(id, this.openPayId);
  16930. };
  16931. Cnds.prototype.onCheckIfPurchased = function (id) {
  16932. id = parseInt(id);
  16933. return cr.equals_nocase(id, this.checkIfPurchasedId);
  16934. };
  16935. pluginProto.cnds = new Cnds();
  16936. function Acts() {}
  16937. /* */
  16938. Acts.prototype.leaveReview = function () {
  16939. this.userService["leavereviewjs"]();
  16940. };
  16941. Acts.prototype.persist = function () {
  16942. this.dataService["persist"]();
  16943. };
  16944. Acts.prototype.dataSave = function (_key, _val) {
  16945. this.dataService["save"](_key, _val);
  16946. };
  16947. Acts.prototype.setUserName = function (_val) {
  16948. if (_val === "") {
  16949. return;
  16950. }
  16951. var self = this;
  16952. this.userService["updateUsername"](_val).subscribe(function (usr) {
  16953. }, function (error) {
  16954. self.onSetUserNameError(error);
  16955. /*
  16956. if (error === 'Username already taken') {
  16957. }
  16958. */
  16959. });
  16960. };
  16961. Acts.prototype.setHighscore = function (_val) {
  16962. _val = parseInt(_val);
  16963. this.userService["setHighscore"](_val);
  16964. };
  16965. Acts.prototype.getLeaderboard = function () {
  16966. this.getLeaderboard();
  16967. };
  16968. Acts.prototype.showLeaderboard = function () {
  16969. this.userService["showLeaderboardjs"]();
  16970. };
  16971. Acts.prototype.addLeaderboardHighscore = function (_val) {
  16972. _val = parseInt(_val);
  16973. this.userService["addToLeaderboardjs"](_val);
  16974. };
  16975. Acts.prototype.onPayWindowTrigger = function (id) {
  16976. var self = this;
  16977. id = parseInt(id);
  16978. var _inapp = this.userService["getInapp"](id);
  16979. this.userService["openpayjs"](_inapp).subscribe(function (isSuccessful) {
  16980. self.openPayId = id;
  16981. self.openPayStatus = isSuccessful;
  16982. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onPayWindowTrigger, self);
  16983. });
  16984. };
  16985. Acts.prototype.onCheckIfPurchased = function (id) {
  16986. var self = this;
  16987. id = parseInt(id);
  16988. this.userService["checkIfPurchased"](id).subscribe(function (isSuccessful) {
  16989. if (isSuccessful) {
  16990. self.checkIfPurchasedId = id;
  16991. self.checkIfPurchasedStatus = (isSuccessful === true);
  16992. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onCheckIfPurchased, self);
  16993. } else {
  16994. self.checkIfPurchasedId = id;
  16995. self.checkIfPurchasedStatus = false;
  16996. self.runtime.trigger(cr.plugins_.sirg_wickeyappstore.prototype.cnds.onCheckIfPurchased, self);
  16997. }
  16998. });
  16999. };
  17000. pluginProto.acts = new Acts();
  17001. function Exps() {}
  17002. Exps.prototype.isOpened = function (ret) {
  17003. ret.set_int(Number(this.isOpened));
  17004. };
  17005. Exps.prototype.isLogged = function (ret) {
  17006. ret.set_int(Number(this.isLogged));
  17007. };
  17008. Exps.prototype.getData = function (ret, _key) {
  17009. ret.set_any(this.dataService["get"](_key));
  17010. };
  17011. Exps.prototype.coins = function (ret) {
  17012. ret.set_int(this.userData["coins"]);
  17013. };
  17014. Exps.prototype.rated = function (ret) {
  17015. ret.set_int(Number(this.userData["rated_app"]));
  17016. };
  17017. Exps.prototype.userid = function (ret) {
  17018. ret.set_string(this.userData["user_id"]);
  17019. };
  17020. Exps.prototype.username = function (ret) {
  17021. ret.set_string(this.userData["username"]);
  17022. };
  17023. Exps.prototype.freebie = function (ret) {
  17024. ret.set_int(Number(this.userData["freebie_used"]));
  17025. };
  17026. Exps.prototype.verified = function (ret) {
  17027. ret.set_int(Number(this.userData["account_verified"]));
  17028. };
  17029. Exps.prototype.leaderboard = function (ret) {
  17030. ret.set_any(JSON.stringify(this.leaderboard));
  17031. };
  17032. Exps.prototype.rank = function (ret) {
  17033. ret.set_int(this.rank);
  17034. };
  17035. Exps.prototype.openPayId = function (ret) {
  17036. ret.set_int(this.openPayId);
  17037. };
  17038. Exps.prototype.openPayStatus = function (ret) {
  17039. ret.set_int(Number(this.openPayStatus));
  17040. };
  17041. Exps.prototype.checkIfPurchasedId = function (ret) {
  17042. ret.set_int(this.checkIfPurchasedId);
  17043. };
  17044. Exps.prototype.checkIfPurchasedStatus = function (ret) {
  17045. ret.set_int(Number(this.checkIfPurchasedStatus));
  17046. };
  17047. Exps.prototype.getError = function (ret) {
  17048. ret.set_string(this.error);
  17049. };
  17050. pluginProto.exps = new Exps();
  17051. })();
  17052. cr.getObjectRefTable = function () { return [
  17053. cr.plugins_.Button,
  17054. cr.plugins_.Function,
  17055. cr.plugins_.sirg_wickeyappstore,
  17056. cr.plugins_.Text,
  17057. cr.plugins_.TextBox,
  17058. cr.plugins_.TiledBg,
  17059. cr.plugins_.Function.prototype.cnds.OnFunction,
  17060. cr.plugins_.TextBox.prototype.acts.SetText,
  17061. cr.plugins_.TextBox.prototype.exps.Text,
  17062. cr.system_object.prototype.exps.newline,
  17063. cr.plugins_.Function.prototype.exps.Param,
  17064. cr.plugins_.TextBox.prototype.acts.ScrollToBottom,
  17065. cr.plugins_.Button.prototype.cnds.OnClicked,
  17066. cr.plugins_.Function.prototype.acts.CallFunction,
  17067. cr.plugins_.sirg_wickeyappstore.prototype.acts.dataSave,
  17068. cr.plugins_.sirg_wickeyappstore.prototype.exps.getData,
  17069. cr.plugins_.sirg_wickeyappstore.prototype.acts.leaveReview,
  17070. cr.plugins_.sirg_wickeyappstore.prototype.acts.persist,
  17071. cr.plugins_.sirg_wickeyappstore.prototype.acts.setHighscore,
  17072. cr.plugins_.sirg_wickeyappstore.prototype.acts.setUserName,
  17073. cr.plugins_.sirg_wickeyappstore.prototype.acts.getLeaderboard,
  17074. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onError,
  17075. cr.plugins_.sirg_wickeyappstore.prototype.exps.getError,
  17076. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onLoginChange,
  17077. cr.plugins_.sirg_wickeyappstore.prototype.exps.isLogged,
  17078. cr.plugins_.Text.prototype.acts.SetText,
  17079. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onOpen,
  17080. cr.plugins_.sirg_wickeyappstore.prototype.exps.isOpened,
  17081. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onDataUpdate,
  17082. cr.plugins_.sirg_wickeyappstore.prototype.exps.coins,
  17083. cr.plugins_.sirg_wickeyappstore.prototype.exps.rated,
  17084. cr.plugins_.sirg_wickeyappstore.prototype.exps.userid,
  17085. cr.plugins_.sirg_wickeyappstore.prototype.exps.username,
  17086. cr.plugins_.sirg_wickeyappstore.prototype.exps.verified,
  17087. cr.plugins_.sirg_wickeyappstore.prototype.exps.freebie,
  17088. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onUserUpdate,
  17089. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onLeaderboardGet,
  17090. cr.system_object.prototype.exps.str,
  17091. cr.plugins_.sirg_wickeyappstore.prototype.exps.rank,
  17092. cr.plugins_.sirg_wickeyappstore.prototype.exps.leaderboard,
  17093. cr.plugins_.TextBox.prototype.cnds.CompareText,
  17094. cr.plugins_.sirg_wickeyappstore.prototype.acts.onPayWindowTrigger,
  17095. cr.plugins_.sirg_wickeyappstore.prototype.acts.onCheckIfPurchased,
  17096. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onPayWindowTrigger,
  17097. cr.plugins_.sirg_wickeyappstore.prototype.exps.openPayStatus,
  17098. cr.plugins_.sirg_wickeyappstore.prototype.cnds.onCheckIfPurchased,
  17099. cr.plugins_.sirg_wickeyappstore.prototype.exps.checkIfPurchasedStatus
  17100. ];};
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement