// Generated by Construct 2, the HTML5 game and app creator :: https://www.construct.net var cr = {}; cr.plugins_ = {}; cr.behaviors = {}; if (typeof Object.getPrototypeOf !== "function") { if (typeof "test".__proto__ === "object") { Object.getPrototypeOf = function(object) { return object.__proto__; }; } else { Object.getPrototypeOf = function(object) { return object.constructor.prototype; }; } } (function(){ cr.logexport = function (msg) { if (window.console && window.console.log) window.console.log(msg); }; cr.logerror = function (msg) { if (window.console && window.console.error) window.console.error(msg); }; cr.seal = function(x) { return x; }; cr.freeze = function(x) { return x; }; cr.is_undefined = function (x) { return typeof x === "undefined"; }; cr.is_number = function (x) { return typeof x === "number"; }; cr.is_string = function (x) { return typeof x === "string"; }; cr.isPOT = function (x) { return x > 0 && ((x - 1) & x) === 0; }; cr.nextHighestPowerOfTwo = function(x) { --x; for (var i = 1; i < 32; i <<= 1) { x = x | x >> i; } return x + 1; } cr.abs = function (x) { return (x < 0 ? -x : x); }; cr.max = function (a, b) { return (a > b ? a : b); }; cr.min = function (a, b) { return (a < b ? a : b); }; cr.PI = Math.PI; cr.round = function (x) { return (x + 0.5) | 0; }; cr.floor = function (x) { if (x >= 0) return x | 0; else return (x | 0) - 1; // correctly round down when negative }; cr.ceil = function (x) { var f = x | 0; return (f === x ? f : f + 1); }; function Vector2(x, y) { this.x = x; this.y = y; cr.seal(this); }; Vector2.prototype.offset = function (px, py) { this.x += px; this.y += py; return this; }; Vector2.prototype.mul = function (px, py) { this.x *= px; this.y *= py; return this; }; cr.vector2 = Vector2; cr.segments_intersect = function(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y) { var max_ax, min_ax, max_ay, min_ay, max_bx, min_bx, max_by, min_by; if (a1x < a2x) { min_ax = a1x; max_ax = a2x; } else { min_ax = a2x; max_ax = a1x; } if (b1x < b2x) { min_bx = b1x; max_bx = b2x; } else { min_bx = b2x; max_bx = b1x; } if (max_ax < min_bx || min_ax > max_bx) return false; if (a1y < a2y) { min_ay = a1y; max_ay = a2y; } else { min_ay = a2y; max_ay = a1y; } if (b1y < b2y) { min_by = b1y; max_by = b2y; } else { min_by = b2y; max_by = b1y; } if (max_ay < min_by || min_ay > max_by) return false; var dpx = b1x - a1x + b2x - a2x; var dpy = b1y - a1y + b2y - a2y; var qax = a2x - a1x; var qay = a2y - a1y; var qbx = b2x - b1x; var qby = b2y - b1y; var d = cr.abs(qay * qbx - qby * qax); var la = qbx * dpy - qby * dpx; if (cr.abs(la) > d) return false; var lb = qax * dpy - qay * dpx; return cr.abs(lb) <= d; }; function Rect(left, top, right, bottom) { this.set(left, top, right, bottom); cr.seal(this); }; Rect.prototype.set = function (left, top, right, bottom) { this.left = left; this.top = top; this.right = right; this.bottom = bottom; }; Rect.prototype.copy = function (r) { this.left = r.left; this.top = r.top; this.right = r.right; this.bottom = r.bottom; }; Rect.prototype.width = function () { return this.right - this.left; }; Rect.prototype.height = function () { return this.bottom - this.top; }; Rect.prototype.offset = function (px, py) { this.left += px; this.top += py; this.right += px; this.bottom += py; return this; }; Rect.prototype.normalize = function () { var temp = 0; if (this.left > this.right) { temp = this.left; this.left = this.right; this.right = temp; } if (this.top > this.bottom) { temp = this.top; this.top = this.bottom; this.bottom = temp; } }; Rect.prototype.intersects_rect = function (rc) { return !(rc.right < this.left || rc.bottom < this.top || rc.left > this.right || rc.top > this.bottom); }; Rect.prototype.intersects_rect_off = function (rc, ox, oy) { return !(rc.right + ox < this.left || rc.bottom + oy < this.top || rc.left + ox > this.right || rc.top + oy > this.bottom); }; Rect.prototype.contains_pt = function (x, y) { return (x >= this.left && x <= this.right) && (y >= this.top && y <= this.bottom); }; Rect.prototype.equals = function (r) { return this.left === r.left && this.top === r.top && this.right === r.right && this.bottom === r.bottom; }; cr.rect = Rect; function Quad() { this.tlx = 0; this.tly = 0; this.trx = 0; this.try_ = 0; // is a keyword otherwise! this.brx = 0; this.bry = 0; this.blx = 0; this.bly = 0; cr.seal(this); }; Quad.prototype.set_from_rect = function (rc) { this.tlx = rc.left; this.tly = rc.top; this.trx = rc.right; this.try_ = rc.top; this.brx = rc.right; this.bry = rc.bottom; this.blx = rc.left; this.bly = rc.bottom; }; Quad.prototype.set_from_rotated_rect = function (rc, a) { if (a === 0) { this.set_from_rect(rc); } else { var sin_a = Math.sin(a); var cos_a = Math.cos(a); var left_sin_a = rc.left * sin_a; var top_sin_a = rc.top * sin_a; var right_sin_a = rc.right * sin_a; var bottom_sin_a = rc.bottom * sin_a; var left_cos_a = rc.left * cos_a; var top_cos_a = rc.top * cos_a; var right_cos_a = rc.right * cos_a; var bottom_cos_a = rc.bottom * cos_a; this.tlx = left_cos_a - top_sin_a; this.tly = top_cos_a + left_sin_a; this.trx = right_cos_a - top_sin_a; this.try_ = top_cos_a + right_sin_a; this.brx = right_cos_a - bottom_sin_a; this.bry = bottom_cos_a + right_sin_a; this.blx = left_cos_a - bottom_sin_a; this.bly = bottom_cos_a + left_sin_a; } }; Quad.prototype.offset = function (px, py) { this.tlx += px; this.tly += py; this.trx += px; this.try_ += py; this.brx += px; this.bry += py; this.blx += px; this.bly += py; return this; }; var minresult = 0; var maxresult = 0; function minmax4(a, b, c, d) { if (a < b) { if (c < d) { if (a < c) minresult = a; else minresult = c; if (b > d) maxresult = b; else maxresult = d; } else { if (a < d) minresult = a; else minresult = d; if (b > c) maxresult = b; else maxresult = c; } } else { if (c < d) { if (b < c) minresult = b; else minresult = c; if (a > d) maxresult = a; else maxresult = d; } else { if (b < d) minresult = b; else minresult = d; if (a > c) maxresult = a; else maxresult = c; } } }; Quad.prototype.bounding_box = function (rc) { minmax4(this.tlx, this.trx, this.brx, this.blx); rc.left = minresult; rc.right = maxresult; minmax4(this.tly, this.try_, this.bry, this.bly); rc.top = minresult; rc.bottom = maxresult; }; Quad.prototype.contains_pt = function (x, y) { var tlx = this.tlx; var tly = this.tly; var v0x = this.trx - tlx; var v0y = this.try_ - tly; var v1x = this.brx - tlx; var v1y = this.bry - tly; var v2x = x - tlx; var v2y = y - tly; var dot00 = v0x * v0x + v0y * v0y var dot01 = v0x * v1x + v0y * v1y var dot02 = v0x * v2x + v0y * v2y var dot11 = v1x * v1x + v1y * v1y var dot12 = v1x * v2x + v1y * v2y var invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01); var u = (dot11 * dot02 - dot01 * dot12) * invDenom; var v = (dot00 * dot12 - dot01 * dot02) * invDenom; if ((u >= 0.0) && (v > 0.0) && (u + v < 1)) return true; v0x = this.blx - tlx; v0y = this.bly - tly; var dot00 = v0x * v0x + v0y * v0y var dot01 = v0x * v1x + v0y * v1y var dot02 = v0x * v2x + v0y * v2y invDenom = 1.0 / (dot00 * dot11 - dot01 * dot01); u = (dot11 * dot02 - dot01 * dot12) * invDenom; v = (dot00 * dot12 - dot01 * dot02) * invDenom; return (u >= 0.0) && (v > 0.0) && (u + v < 1); }; Quad.prototype.at = function (i, xory) { if (xory) { switch (i) { case 0: return this.tlx; case 1: return this.trx; case 2: return this.brx; case 3: return this.blx; case 4: return this.tlx; default: return this.tlx; } } else { switch (i) { case 0: return this.tly; case 1: return this.try_; case 2: return this.bry; case 3: return this.bly; case 4: return this.tly; default: return this.tly; } } }; Quad.prototype.midX = function () { return (this.tlx + this.trx + this.brx + this.blx) / 4; }; Quad.prototype.midY = function () { return (this.tly + this.try_ + this.bry + this.bly) / 4; }; Quad.prototype.intersects_segment = function (x1, y1, x2, y2) { if (this.contains_pt(x1, y1) || this.contains_pt(x2, y2)) return true; var a1x, a1y, a2x, a2y; var i; for (i = 0; i < 4; i++) { a1x = this.at(i, true); a1y = this.at(i, false); a2x = this.at(i + 1, true); a2y = this.at(i + 1, false); if (cr.segments_intersect(x1, y1, x2, y2, a1x, a1y, a2x, a2y)) return true; } return false; }; Quad.prototype.intersects_quad = function (rhs) { var midx = rhs.midX(); var midy = rhs.midY(); if (this.contains_pt(midx, midy)) return true; midx = this.midX(); midy = this.midY(); if (rhs.contains_pt(midx, midy)) return true; var a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y; var i, j; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { a1x = this.at(i, true); a1y = this.at(i, false); a2x = this.at(i + 1, true); a2y = this.at(i + 1, false); b1x = rhs.at(j, true); b1y = rhs.at(j, false); b2x = rhs.at(j + 1, true); b2y = rhs.at(j + 1, false); if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) return true; } } return false; }; cr.quad = Quad; cr.RGB = function (red, green, blue) { return Math.max(Math.min(red, 255), 0) | (Math.max(Math.min(green, 255), 0) << 8) | (Math.max(Math.min(blue, 255), 0) << 16); }; cr.GetRValue = function (rgb) { return rgb & 0xFF; }; cr.GetGValue = function (rgb) { return (rgb & 0xFF00) >> 8; }; cr.GetBValue = function (rgb) { return (rgb & 0xFF0000) >> 16; }; cr.shallowCopy = function (a, b, allowOverwrite) { var attr; for (attr in b) { if (b.hasOwnProperty(attr)) { ; a[attr] = b[attr]; } } return a; }; cr.arrayRemove = function (arr, index) { var i, len; index = cr.floor(index); if (index < 0 || index >= arr.length) return; // index out of bounds for (i = index, len = arr.length - 1; i < len; i++) arr[i] = arr[i + 1]; cr.truncateArray(arr, len); }; cr.truncateArray = function (arr, index) { arr.length = index; }; cr.clearArray = function (arr) { cr.truncateArray(arr, 0); }; cr.shallowAssignArray = function (dest, src) { cr.clearArray(dest); var i, len; for (i = 0, len = src.length; i < len; ++i) dest[i] = src[i]; }; cr.appendArray = function (a, b) { a.push.apply(a, b); }; cr.fastIndexOf = function (arr, item) { var i, len; for (i = 0, len = arr.length; i < len; ++i) { if (arr[i] === item) return i; } return -1; }; cr.arrayFindRemove = function (arr, item) { var index = cr.fastIndexOf(arr, item); if (index !== -1) cr.arrayRemove(arr, index); }; cr.clamp = function(x, a, b) { if (x < a) return a; else if (x > b) return b; else return x; }; cr.to_radians = function(x) { return x / (180.0 / cr.PI); }; cr.to_degrees = function(x) { return x * (180.0 / cr.PI); }; cr.clamp_angle_degrees = function (a) { a %= 360; // now in (-360, 360) range if (a < 0) a += 360; // now in [0, 360) range return a; }; cr.clamp_angle = function (a) { a %= 2 * cr.PI; // now in (-2pi, 2pi) range if (a < 0) a += 2 * cr.PI; // now in [0, 2pi) range return a; }; cr.to_clamped_degrees = function (x) { return cr.clamp_angle_degrees(cr.to_degrees(x)); }; cr.to_clamped_radians = function (x) { return cr.clamp_angle(cr.to_radians(x)); }; cr.angleTo = function(x1, y1, x2, y2) { var dx = x2 - x1; var dy = y2 - y1; return Math.atan2(dy, dx); }; cr.angleDiff = function (a1, a2) { if (a1 === a2) return 0; var s1 = Math.sin(a1); var c1 = Math.cos(a1); var s2 = Math.sin(a2); var c2 = Math.cos(a2); var n = s1 * s2 + c1 * c2; if (n >= 1) return 0; if (n <= -1) return cr.PI; return Math.acos(n); }; cr.angleRotate = function (start, end, step) { var ss = Math.sin(start); var cs = Math.cos(start); var se = Math.sin(end); var ce = Math.cos(end); if (Math.acos(ss * se + cs * ce) > step) { if (cs * se - ss * ce > 0) return cr.clamp_angle(start + step); else return cr.clamp_angle(start - step); } else return cr.clamp_angle(end); }; cr.angleClockwise = function (a1, a2) { var s1 = Math.sin(a1); var c1 = Math.cos(a1); var s2 = Math.sin(a2); var c2 = Math.cos(a2); return c1 * s2 - s1 * c2 <= 0; }; cr.rotatePtAround = function (px, py, a, ox, oy, getx) { if (a === 0) return getx ? px : py; var sin_a = Math.sin(a); var cos_a = Math.cos(a); px -= ox; py -= oy; var left_sin_a = px * sin_a; var top_sin_a = py * sin_a; var left_cos_a = px * cos_a; var top_cos_a = py * cos_a; px = left_cos_a - top_sin_a; py = top_cos_a + left_sin_a; px += ox; py += oy; return getx ? px : py; } cr.distanceTo = function(x1, y1, x2, y2) { var dx = x2 - x1; var dy = y2 - y1; return Math.sqrt(dx*dx + dy*dy); }; cr.xor = function (x, y) { return !x !== !y; }; cr.lerp = function (a, b, x) { return a + (b - a) * x; }; cr.unlerp = function (a, b, c) { if (a === b) return 0; // avoid divide by 0 return (c - a) / (b - a); }; cr.anglelerp = function (a, b, x) { var diff = cr.angleDiff(a, b); if (cr.angleClockwise(b, a)) { return a + diff * x; } else { return a - diff * x; } }; cr.qarp = function (a, b, c, x) { return cr.lerp(cr.lerp(a, b, x), cr.lerp(b, c, x), x); }; cr.cubic = function (a, b, c, d, x) { return cr.lerp(cr.qarp(a, b, c, x), cr.qarp(b, c, d, x), x); }; cr.cosp = function (a, b, x) { return (a + b + (a - b) * Math.cos(x * Math.PI)) / 2; }; cr.hasAnyOwnProperty = function (o) { var p; for (p in o) { if (o.hasOwnProperty(p)) return true; } return false; }; cr.wipe = function (obj) { var p; for (p in obj) { if (obj.hasOwnProperty(p)) delete obj[p]; } }; var startup_time = +(new Date()); cr.performance_now = function() { if (typeof window["performance"] !== "undefined") { var winperf = window["performance"]; if (typeof winperf.now !== "undefined") return winperf.now(); else if (typeof winperf["webkitNow"] !== "undefined") return winperf["webkitNow"](); else if (typeof winperf["mozNow"] !== "undefined") return winperf["mozNow"](); else if (typeof winperf["msNow"] !== "undefined") return winperf["msNow"](); } return Date.now() - startup_time; }; var isChrome = false; var isSafari = false; var isiOS = false; var isEjecta = false; if (typeof window !== "undefined") // not c2 editor { isChrome = /chrome/i.test(navigator.userAgent) || /chromium/i.test(navigator.userAgent); isSafari = !isChrome && /safari/i.test(navigator.userAgent); isiOS = /(iphone|ipod|ipad)/i.test(navigator.userAgent); isEjecta = window["c2ejecta"]; } var supports_set = ((!isSafari && !isEjecta && !isiOS) && (typeof Set !== "undefined" && typeof Set.prototype["forEach"] !== "undefined")); function ObjectSet_() { this.s = null; this.items = null; // lazy allocated (hopefully results in better GC performance) this.item_count = 0; if (supports_set) { this.s = new Set(); } this.values_cache = []; this.cache_valid = true; cr.seal(this); }; ObjectSet_.prototype.contains = function (x) { if (this.isEmpty()) return false; if (supports_set) return this.s["has"](x); else return (this.items && this.items.hasOwnProperty(x)); }; ObjectSet_.prototype.add = function (x) { if (supports_set) { if (!this.s["has"](x)) { this.s["add"](x); this.cache_valid = false; } } else { var str = x.toString(); var items = this.items; if (!items) { this.items = {}; this.items[str] = x; this.item_count = 1; this.cache_valid = false; } else if (!items.hasOwnProperty(str)) { items[str] = x; this.item_count++; this.cache_valid = false; } } }; ObjectSet_.prototype.remove = function (x) { if (this.isEmpty()) return; if (supports_set) { if (this.s["has"](x)) { this.s["delete"](x); this.cache_valid = false; } } else if (this.items) { var str = x.toString(); var items = this.items; if (items.hasOwnProperty(str)) { delete items[str]; this.item_count--; this.cache_valid = false; } } }; ObjectSet_.prototype.clear = function (/*wipe_*/) { if (this.isEmpty()) return; if (supports_set) { this.s["clear"](); // best! } else { this.items = null; // creates garbage; will lazy allocate on next add() this.item_count = 0; } cr.clearArray(this.values_cache); this.cache_valid = true; }; ObjectSet_.prototype.isEmpty = function () { return this.count() === 0; }; ObjectSet_.prototype.count = function () { if (supports_set) return this.s["size"]; else return this.item_count; }; var current_arr = null; var current_index = 0; function set_append_to_arr(x) { current_arr[current_index++] = x; }; ObjectSet_.prototype.update_cache = function () { if (this.cache_valid) return; if (supports_set) { cr.clearArray(this.values_cache); current_arr = this.values_cache; current_index = 0; this.s["forEach"](set_append_to_arr); ; current_arr = null; current_index = 0; } else { var values_cache = this.values_cache; cr.clearArray(values_cache); var p, n = 0, items = this.items; if (items) { for (p in items) { if (items.hasOwnProperty(p)) values_cache[n++] = items[p]; } } ; } this.cache_valid = true; }; ObjectSet_.prototype.valuesRef = function () { this.update_cache(); return this.values_cache; }; cr.ObjectSet = ObjectSet_; var tmpSet = new cr.ObjectSet(); cr.removeArrayDuplicates = function (arr) { var i, len; for (i = 0, len = arr.length; i < len; ++i) { tmpSet.add(arr[i]); } cr.shallowAssignArray(arr, tmpSet.valuesRef()); tmpSet.clear(); }; cr.arrayRemoveAllFromObjectSet = function (arr, remset) { if (supports_set) cr.arrayRemoveAll_set(arr, remset.s); else cr.arrayRemoveAll_arr(arr, remset.valuesRef()); }; cr.arrayRemoveAll_set = function (arr, s) { var i, j, len, item; for (i = 0, j = 0, len = arr.length; i < len; ++i) { item = arr[i]; if (!s["has"](item)) // not an item to remove arr[j++] = item; // keep it } cr.truncateArray(arr, j); }; cr.arrayRemoveAll_arr = function (arr, rem) { var i, j, len, item; for (i = 0, j = 0, len = arr.length; i < len; ++i) { item = arr[i]; if (cr.fastIndexOf(rem, item) === -1) // not an item to remove arr[j++] = item; // keep it } cr.truncateArray(arr, j); }; function KahanAdder_() { this.c = 0; this.y = 0; this.t = 0; this.sum = 0; cr.seal(this); }; KahanAdder_.prototype.add = function (v) { this.y = v - this.c; this.t = this.sum + this.y; this.c = (this.t - this.sum) - this.y; this.sum = this.t; }; KahanAdder_.prototype.reset = function () { this.c = 0; this.y = 0; this.t = 0; this.sum = 0; }; cr.KahanAdder = KahanAdder_; cr.regexp_escape = function(text) { return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); }; function CollisionPoly_(pts_array_) { this.pts_cache = []; this.bboxLeft = 0; this.bboxTop = 0; this.bboxRight = 0; this.bboxBottom = 0; this.convexpolys = null; // for physics behavior to cache separated polys this.set_pts(pts_array_); cr.seal(this); }; CollisionPoly_.prototype.set_pts = function(pts_array_) { this.pts_array = pts_array_; this.pts_count = pts_array_.length / 2; // x, y, x, y... in array this.pts_cache.length = pts_array_.length; this.cache_width = -1; this.cache_height = -1; this.cache_angle = 0; }; CollisionPoly_.prototype.is_empty = function() { return !this.pts_array.length; }; CollisionPoly_.prototype.update_bbox = function () { var myptscache = this.pts_cache; var bboxLeft_ = myptscache[0]; var bboxRight_ = bboxLeft_; var bboxTop_ = myptscache[1]; var bboxBottom_ = bboxTop_; var x, y, i = 1, i2, len = this.pts_count; for ( ; i < len; ++i) { i2 = i*2; x = myptscache[i2]; y = myptscache[i2+1]; if (x < bboxLeft_) bboxLeft_ = x; if (x > bboxRight_) bboxRight_ = x; if (y < bboxTop_) bboxTop_ = y; if (y > bboxBottom_) bboxBottom_ = y; } this.bboxLeft = bboxLeft_; this.bboxRight = bboxRight_; this.bboxTop = bboxTop_; this.bboxBottom = bboxBottom_; }; CollisionPoly_.prototype.set_from_rect = function(rc, offx, offy) { this.pts_cache.length = 8; this.pts_count = 4; var myptscache = this.pts_cache; myptscache[0] = rc.left - offx; myptscache[1] = rc.top - offy; myptscache[2] = rc.right - offx; myptscache[3] = rc.top - offy; myptscache[4] = rc.right - offx; myptscache[5] = rc.bottom - offy; myptscache[6] = rc.left - offx; myptscache[7] = rc.bottom - offy; this.cache_width = rc.right - rc.left; this.cache_height = rc.bottom - rc.top; this.update_bbox(); }; CollisionPoly_.prototype.set_from_quad = function(q, offx, offy, w, h) { this.pts_cache.length = 8; this.pts_count = 4; var myptscache = this.pts_cache; myptscache[0] = q.tlx - offx; myptscache[1] = q.tly - offy; myptscache[2] = q.trx - offx; myptscache[3] = q.try_ - offy; myptscache[4] = q.brx - offx; myptscache[5] = q.bry - offy; myptscache[6] = q.blx - offx; myptscache[7] = q.bly - offy; this.cache_width = w; this.cache_height = h; this.update_bbox(); }; CollisionPoly_.prototype.set_from_poly = function (r) { this.pts_count = r.pts_count; cr.shallowAssignArray(this.pts_cache, r.pts_cache); this.bboxLeft = r.bboxLeft; this.bboxTop - r.bboxTop; this.bboxRight = r.bboxRight; this.bboxBottom = r.bboxBottom; }; CollisionPoly_.prototype.cache_poly = function(w, h, a) { if (this.cache_width === w && this.cache_height === h && this.cache_angle === a) return; // cache up-to-date this.cache_width = w; this.cache_height = h; this.cache_angle = a; var i, i2, i21, len, x, y; var sina = 0; var cosa = 1; var myptsarray = this.pts_array; var myptscache = this.pts_cache; if (a !== 0) { sina = Math.sin(a); cosa = Math.cos(a); } for (i = 0, len = this.pts_count; i < len; i++) { i2 = i*2; i21 = i2+1; x = myptsarray[i2] * w; y = myptsarray[i21] * h; myptscache[i2] = (x * cosa) - (y * sina); myptscache[i21] = (y * cosa) + (x * sina); } this.update_bbox(); }; CollisionPoly_.prototype.contains_pt = function (a2x, a2y) { var myptscache = this.pts_cache; if (a2x === myptscache[0] && a2y === myptscache[1]) return true; var i, i2, imod, len = this.pts_count; var a1x = this.bboxLeft - 110; var a1y = this.bboxTop - 101; var a3x = this.bboxRight + 131 var a3y = this.bboxBottom + 120; var b1x, b1y, b2x, b2y; var count1 = 0, count2 = 0; for (i = 0; i < len; i++) { i2 = i*2; imod = ((i+1)%len)*2; b1x = myptscache[i2]; b1y = myptscache[i2+1]; b2x = myptscache[imod]; b2y = myptscache[imod+1]; if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) count1++; if (cr.segments_intersect(a3x, a3y, a2x, a2y, b1x, b1y, b2x, b2y)) count2++; } return (count1 % 2 === 1) || (count2 % 2 === 1); }; CollisionPoly_.prototype.intersects_poly = function (rhs, offx, offy) { var rhspts = rhs.pts_cache; var mypts = this.pts_cache; if (this.contains_pt(rhspts[0] + offx, rhspts[1] + offy)) return true; if (rhs.contains_pt(mypts[0] - offx, mypts[1] - offy)) return true; var i, i2, imod, leni, j, j2, jmod, lenj; var a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y; for (i = 0, leni = this.pts_count; i < leni; i++) { i2 = i*2; imod = ((i+1)%leni)*2; a1x = mypts[i2]; a1y = mypts[i2+1]; a2x = mypts[imod]; a2y = mypts[imod+1]; for (j = 0, lenj = rhs.pts_count; j < lenj; j++) { j2 = j*2; jmod = ((j+1)%lenj)*2; b1x = rhspts[j2] + offx; b1y = rhspts[j2+1] + offy; b2x = rhspts[jmod] + offx; b2y = rhspts[jmod+1] + offy; if (cr.segments_intersect(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)) return true; } } return false; }; CollisionPoly_.prototype.intersects_segment = function (offx, offy, x1, y1, x2, y2) { var mypts = this.pts_cache; if (this.contains_pt(x1 - offx, y1 - offy)) return true; var i, leni, i2, imod; var a1x, a1y, a2x, a2y; for (i = 0, leni = this.pts_count; i < leni; i++) { i2 = i*2; imod = ((i+1)%leni)*2; a1x = mypts[i2] + offx; a1y = mypts[i2+1] + offy; a2x = mypts[imod] + offx; a2y = mypts[imod+1] + offy; if (cr.segments_intersect(x1, y1, x2, y2, a1x, a1y, a2x, a2y)) return true; } return false; }; CollisionPoly_.prototype.mirror = function (px) { var i, leni, i2; for (i = 0, leni = this.pts_count; i < leni; ++i) { i2 = i*2; this.pts_cache[i2] = px * 2 - this.pts_cache[i2]; } }; CollisionPoly_.prototype.flip = function (py) { var i, leni, i21; for (i = 0, leni = this.pts_count; i < leni; ++i) { i21 = i*2+1; this.pts_cache[i21] = py * 2 - this.pts_cache[i21]; } }; CollisionPoly_.prototype.diag = function () { var i, leni, i2, i21, temp; for (i = 0, leni = this.pts_count; i < leni; ++i) { i2 = i*2; i21 = i2+1; temp = this.pts_cache[i2]; this.pts_cache[i2] = this.pts_cache[i21]; this.pts_cache[i21] = temp; } }; cr.CollisionPoly = CollisionPoly_; function SparseGrid_(cellwidth_, cellheight_) { this.cellwidth = cellwidth_; this.cellheight = cellheight_; this.cells = {}; }; SparseGrid_.prototype.totalCellCount = 0; SparseGrid_.prototype.getCell = function (x_, y_, create_if_missing) { var ret; var col = this.cells[x_]; if (!col) { if (create_if_missing) { ret = allocGridCell(this, x_, y_); this.cells[x_] = {}; this.cells[x_][y_] = ret; return ret; } else return null; } ret = col[y_]; if (ret) return ret; else if (create_if_missing) { ret = allocGridCell(this, x_, y_); this.cells[x_][y_] = ret; return ret; } else return null; }; SparseGrid_.prototype.XToCell = function (x_) { return cr.floor(x_ / this.cellwidth); }; SparseGrid_.prototype.YToCell = function (y_) { return cr.floor(y_ / this.cellheight); }; SparseGrid_.prototype.update = function (inst, oldrange, newrange) { var x, lenx, y, leny, cell; if (oldrange) { for (x = oldrange.left, lenx = oldrange.right; x <= lenx; ++x) { for (y = oldrange.top, leny = oldrange.bottom; y <= leny; ++y) { if (newrange && newrange.contains_pt(x, y)) continue; // is still in this cell cell = this.getCell(x, y, false); // don't create if missing if (!cell) continue; // cell does not exist yet cell.remove(inst); if (cell.isEmpty()) { freeGridCell(cell); this.cells[x][y] = null; } } } } if (newrange) { for (x = newrange.left, lenx = newrange.right; x <= lenx; ++x) { for (y = newrange.top, leny = newrange.bottom; y <= leny; ++y) { if (oldrange && oldrange.contains_pt(x, y)) continue; // is still in this cell this.getCell(x, y, true).insert(inst); } } } }; SparseGrid_.prototype.queryRange = function (rc, result) { var x, lenx, ystart, y, leny, cell; x = this.XToCell(rc.left); ystart = this.YToCell(rc.top); lenx = this.XToCell(rc.right); leny = this.YToCell(rc.bottom); for ( ; x <= lenx; ++x) { for (y = ystart; y <= leny; ++y) { cell = this.getCell(x, y, false); if (!cell) continue; cell.dump(result); } } }; cr.SparseGrid = SparseGrid_; function RenderGrid_(cellwidth_, cellheight_) { this.cellwidth = cellwidth_; this.cellheight = cellheight_; this.cells = {}; }; RenderGrid_.prototype.totalCellCount = 0; RenderGrid_.prototype.getCell = function (x_, y_, create_if_missing) { var ret; var col = this.cells[x_]; if (!col) { if (create_if_missing) { ret = allocRenderCell(this, x_, y_); this.cells[x_] = {}; this.cells[x_][y_] = ret; return ret; } else return null; } ret = col[y_]; if (ret) return ret; else if (create_if_missing) { ret = allocRenderCell(this, x_, y_); this.cells[x_][y_] = ret; return ret; } else return null; }; RenderGrid_.prototype.XToCell = function (x_) { return cr.floor(x_ / this.cellwidth); }; RenderGrid_.prototype.YToCell = function (y_) { return cr.floor(y_ / this.cellheight); }; RenderGrid_.prototype.update = function (inst, oldrange, newrange) { var x, lenx, y, leny, cell; if (oldrange) { for (x = oldrange.left, lenx = oldrange.right; x <= lenx; ++x) { for (y = oldrange.top, leny = oldrange.bottom; y <= leny; ++y) { if (newrange && newrange.contains_pt(x, y)) continue; // is still in this cell cell = this.getCell(x, y, false); // don't create if missing if (!cell) continue; // cell does not exist yet cell.remove(inst); if (cell.isEmpty()) { freeRenderCell(cell); this.cells[x][y] = null; } } } } if (newrange) { for (x = newrange.left, lenx = newrange.right; x <= lenx; ++x) { for (y = newrange.top, leny = newrange.bottom; y <= leny; ++y) { if (oldrange && oldrange.contains_pt(x, y)) continue; // is still in this cell this.getCell(x, y, true).insert(inst); } } } }; RenderGrid_.prototype.queryRange = function (left, top, right, bottom, result) { var x, lenx, ystart, y, leny, cell; x = this.XToCell(left); ystart = this.YToCell(top); lenx = this.XToCell(right); leny = this.YToCell(bottom); for ( ; x <= lenx; ++x) { for (y = ystart; y <= leny; ++y) { cell = this.getCell(x, y, false); if (!cell) continue; cell.dump(result); } } }; RenderGrid_.prototype.markRangeChanged = function (rc) { var x, lenx, ystart, y, leny, cell; x = rc.left; ystart = rc.top; lenx = rc.right; leny = rc.bottom; for ( ; x <= lenx; ++x) { for (y = ystart; y <= leny; ++y) { cell = this.getCell(x, y, false); if (!cell) continue; cell.is_sorted = false; } } }; cr.RenderGrid = RenderGrid_; var gridcellcache = []; function allocGridCell(grid_, x_, y_) { var ret; SparseGrid_.prototype.totalCellCount++; if (gridcellcache.length) { ret = gridcellcache.pop(); ret.grid = grid_; ret.x = x_; ret.y = y_; return ret; } else return new cr.GridCell(grid_, x_, y_); }; function freeGridCell(c) { SparseGrid_.prototype.totalCellCount--; c.objects.clear(); if (gridcellcache.length < 1000) gridcellcache.push(c); }; function GridCell_(grid_, x_, y_) { this.grid = grid_; this.x = x_; this.y = y_; this.objects = new cr.ObjectSet(); }; GridCell_.prototype.isEmpty = function () { return this.objects.isEmpty(); }; GridCell_.prototype.insert = function (inst) { this.objects.add(inst); }; GridCell_.prototype.remove = function (inst) { this.objects.remove(inst); }; GridCell_.prototype.dump = function (result) { cr.appendArray(result, this.objects.valuesRef()); }; cr.GridCell = GridCell_; var rendercellcache = []; function allocRenderCell(grid_, x_, y_) { var ret; RenderGrid_.prototype.totalCellCount++; if (rendercellcache.length) { ret = rendercellcache.pop(); ret.grid = grid_; ret.x = x_; ret.y = y_; return ret; } else return new cr.RenderCell(grid_, x_, y_); }; function freeRenderCell(c) { RenderGrid_.prototype.totalCellCount--; c.reset(); if (rendercellcache.length < 1000) rendercellcache.push(c); }; function RenderCell_(grid_, x_, y_) { this.grid = grid_; this.x = x_; this.y = y_; this.objects = []; // array which needs to be sorted by Z order this.is_sorted = true; // whether array is in correct sort order or not this.pending_removal = new cr.ObjectSet(); this.any_pending_removal = false; }; RenderCell_.prototype.isEmpty = function () { if (!this.objects.length) { ; ; return true; } if (this.objects.length > this.pending_removal.count()) return false; ; this.flush_pending(); // takes fast path and just resets state return true; }; RenderCell_.prototype.insert = function (inst) { if (this.pending_removal.contains(inst)) { this.pending_removal.remove(inst); if (this.pending_removal.isEmpty()) this.any_pending_removal = false; return; } if (this.objects.length) { var top = this.objects[this.objects.length - 1]; if (top.get_zindex() > inst.get_zindex()) this.is_sorted = false; // 'inst' should be somewhere beneath 'top' this.objects.push(inst); } else { this.objects.push(inst); this.is_sorted = true; } ; }; RenderCell_.prototype.remove = function (inst) { this.pending_removal.add(inst); this.any_pending_removal = true; if (this.pending_removal.count() >= 30) this.flush_pending(); }; RenderCell_.prototype.flush_pending = function () { ; if (!this.any_pending_removal) return; // not changed if (this.pending_removal.count() === this.objects.length) { this.reset(); return; } cr.arrayRemoveAllFromObjectSet(this.objects, this.pending_removal); this.pending_removal.clear(); this.any_pending_removal = false; }; function sortByInstanceZIndex(a, b) { return a.zindex - b.zindex; }; RenderCell_.prototype.ensure_sorted = function () { if (this.is_sorted) return; // already sorted this.objects.sort(sortByInstanceZIndex); this.is_sorted = true; }; RenderCell_.prototype.reset = function () { cr.clearArray(this.objects); this.is_sorted = true; this.pending_removal.clear(); this.any_pending_removal = false; }; RenderCell_.prototype.dump = function (result) { this.flush_pending(); this.ensure_sorted(); if (this.objects.length) result.push(this.objects); }; cr.RenderCell = RenderCell_; var fxNames = [ "lighter", "xor", "copy", "destination-over", "source-in", "destination-in", "source-out", "destination-out", "source-atop", "destination-atop"]; cr.effectToCompositeOp = function(effect) { if (effect <= 0 || effect >= 11) return "source-over"; return fxNames[effect - 1]; // not including "none" so offset by 1 }; cr.setGLBlend = function(this_, effect, gl) { if (!gl) return; this_.srcBlend = gl.ONE; this_.destBlend = gl.ONE_MINUS_SRC_ALPHA; switch (effect) { case 1: // lighter (additive) this_.srcBlend = gl.ONE; this_.destBlend = gl.ONE; break; case 2: // xor break; // todo case 3: // copy this_.srcBlend = gl.ONE; this_.destBlend = gl.ZERO; break; case 4: // destination-over this_.srcBlend = gl.ONE_MINUS_DST_ALPHA; this_.destBlend = gl.ONE; break; case 5: // source-in this_.srcBlend = gl.DST_ALPHA; this_.destBlend = gl.ZERO; break; case 6: // destination-in this_.srcBlend = gl.ZERO; this_.destBlend = gl.SRC_ALPHA; break; case 7: // source-out this_.srcBlend = gl.ONE_MINUS_DST_ALPHA; this_.destBlend = gl.ZERO; break; case 8: // destination-out this_.srcBlend = gl.ZERO; this_.destBlend = gl.ONE_MINUS_SRC_ALPHA; break; case 9: // source-atop this_.srcBlend = gl.DST_ALPHA; this_.destBlend = gl.ONE_MINUS_SRC_ALPHA; break; case 10: // destination-atop this_.srcBlend = gl.ONE_MINUS_DST_ALPHA; this_.destBlend = gl.SRC_ALPHA; break; } }; cr.round6dp = function (x) { return Math.round(x * 1000000) / 1000000; }; /* var localeCompare_options = { "usage": "search", "sensitivity": "accent" }; var has_localeCompare = !!"a".localeCompare; var localeCompare_works1 = (has_localeCompare && "a".localeCompare("A", undefined, localeCompare_options) === 0); var localeCompare_works2 = (has_localeCompare && "a".localeCompare("รก", undefined, localeCompare_options) !== 0); var supports_localeCompare = (has_localeCompare && localeCompare_works1 && localeCompare_works2); */ cr.equals_nocase = function (a, b) { if (typeof a !== "string" || typeof b !== "string") return false; if (a.length !== b.length) return false; if (a === b) return true; /* if (supports_localeCompare) { return (a.localeCompare(b, undefined, localeCompare_options) === 0); } else { */ return a.toLowerCase() === b.toLowerCase(); }; cr.isCanvasInputEvent = function (e) { var target = e.target; if (!target) return true; if (target === document || target === window) return true; if (document && document.body && target === document.body) return true; if (cr.equals_nocase(target.tagName, "canvas")) return true; return false; }; }()); 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}; 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}; 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]}; 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]+"]"}; 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}; 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}; 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}; 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}; 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}; 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}; 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; 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}; 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}; 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* 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}; 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}; 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]; 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}; 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* 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}; 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}; 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}; 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)}; 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}; 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]= 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}; 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}; 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)}; 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}; 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}; 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}; 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}; quat4.str=function(a){return"["+a[0]+", "+a[1]+", "+a[2]+", "+a[3]+"]"}; (function() { var MAX_VERTICES = 8000; // equates to 2500 objects being drawn var MAX_INDICES = (MAX_VERTICES / 2) * 3; // 6 indices for every 4 vertices var MAX_POINTS = 8000; var MULTI_BUFFERS = 4; // cycle 4 buffers to try and avoid blocking var BATCH_NULL = 0; var BATCH_QUAD = 1; var BATCH_SETTEXTURE = 2; var BATCH_SETOPACITY = 3; var BATCH_SETBLEND = 4; var BATCH_UPDATEMODELVIEW = 5; var BATCH_RENDERTOTEXTURE = 6; var BATCH_CLEAR = 7; var BATCH_POINTS = 8; var BATCH_SETPROGRAM = 9; var BATCH_SETPROGRAMPARAMETERS = 10; var BATCH_SETTEXTURE1 = 11; var BATCH_SETCOLOR = 12; var BATCH_SETDEPTHTEST = 13; var BATCH_SETEARLYZMODE = 14; /* var lose_ext = null; window.lose_context = function () { if (!lose_ext) { console.log("WEBGL_lose_context not supported"); return; } lose_ext.loseContext(); }; window.restore_context = function () { if (!lose_ext) { console.log("WEBGL_lose_context not supported"); return; } lose_ext.restoreContext(); }; */ var tempMat4 = mat4.create(); function GLWrap_(gl, isMobile, enableFrontToBack) { this.isIE = /msie/i.test(navigator.userAgent) || /trident/i.test(navigator.userAgent); this.width = 0; // not yet known, wait for call to setSize() this.height = 0; this.enableFrontToBack = !!enableFrontToBack; this.isEarlyZPass = false; this.isBatchInEarlyZPass = false; this.currentZ = 0; this.zNear = 1; this.zFar = 1000; this.zIncrement = ((this.zFar - this.zNear) / 32768); this.zA = this.zFar / (this.zFar - this.zNear); this.zB = this.zFar * this.zNear / (this.zNear - this.zFar); this.kzA = 65536 * this.zA; this.kzB = 65536 * this.zB; this.cam = vec3.create([0, 0, 100]); // camera position this.look = vec3.create([0, 0, 0]); // lookat position this.up = vec3.create([0, 1, 0]); // up vector this.worldScale = vec3.create([1, 1, 1]); // world scaling factor this.enable_mipmaps = true; this.matP = mat4.create(); // perspective matrix this.matMV = mat4.create(); // model view matrix this.lastMV = mat4.create(); this.currentMV = mat4.create(); this.gl = gl; this.version = (this.gl.getParameter(this.gl.VERSION).indexOf("WebGL 2") === 0 ? 2 : 1); this.initState(); }; GLWrap_.prototype.initState = function () { var gl = this.gl; var i, len; this.lastOpacity = 1; this.lastTexture0 = null; // last bound to TEXTURE0 this.lastTexture1 = null; // last bound to TEXTURE1 this.currentOpacity = 1; gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.enable(gl.BLEND); gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA); gl.disable(gl.CULL_FACE); gl.disable(gl.STENCIL_TEST); gl.disable(gl.DITHER); if (this.enableFrontToBack) { gl.enable(gl.DEPTH_TEST); gl.depthFunc(gl.LEQUAL); } else { gl.disable(gl.DEPTH_TEST); } this.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE); this.lastSrcBlend = gl.ONE; this.lastDestBlend = gl.ONE_MINUS_SRC_ALPHA; this.vertexData = new Float32Array(MAX_VERTICES * (this.enableFrontToBack ? 3 : 2)); this.texcoordData = new Float32Array(MAX_VERTICES * 2); this.pointData = new Float32Array(MAX_POINTS * 4); this.pointBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer); gl.bufferData(gl.ARRAY_BUFFER, this.pointData.byteLength, gl.DYNAMIC_DRAW); this.vertexBuffers = new Array(MULTI_BUFFERS); this.texcoordBuffers = new Array(MULTI_BUFFERS); for (i = 0; i < MULTI_BUFFERS; i++) { this.vertexBuffers[i] = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffers[i]); gl.bufferData(gl.ARRAY_BUFFER, this.vertexData.byteLength, gl.DYNAMIC_DRAW); this.texcoordBuffers[i] = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffers[i]); gl.bufferData(gl.ARRAY_BUFFER, this.texcoordData.byteLength, gl.DYNAMIC_DRAW); } this.curBuffer = 0; this.indexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indexBuffer); var indexData = new Uint16Array(MAX_INDICES); i = 0, len = MAX_INDICES; var fv = 0; while (i < len) { indexData[i++] = fv; // top left indexData[i++] = fv + 1; // top right indexData[i++] = fv + 2; // bottom right (first tri) indexData[i++] = fv; // top left indexData[i++] = fv + 2; // bottom right indexData[i++] = fv + 3; // bottom left fv += 4; } gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, indexData, gl.STATIC_DRAW); this.vertexPtr = 0; this.texPtr = 0; this.pointPtr = 0; var fsSource, vsSource; this.shaderPrograms = []; fsSource = [ "varying mediump vec2 vTex;", "uniform lowp float opacity;", "uniform lowp sampler2D samplerFront;", "void main(void) {", " gl_FragColor = texture2D(samplerFront, vTex);", " gl_FragColor *= opacity;", "}" ].join("\n"); if (this.enableFrontToBack) { vsSource = [ "attribute highp vec3 aPos;", "attribute mediump vec2 aTex;", "varying mediump vec2 vTex;", "uniform highp mat4 matP;", "uniform highp mat4 matMV;", "void main(void) {", " gl_Position = matP * matMV * vec4(aPos.x, aPos.y, aPos.z, 1.0);", " vTex = aTex;", "}" ].join("\n"); } else { vsSource = [ "attribute highp vec2 aPos;", "attribute mediump vec2 aTex;", "varying mediump vec2 vTex;", "uniform highp mat4 matP;", "uniform highp mat4 matMV;", "void main(void) {", " gl_Position = matP * matMV * vec4(aPos.x, aPos.y, 0.0, 1.0);", " vTex = aTex;", "}" ].join("\n"); } var shaderProg = this.createShaderProgram({src: fsSource}, vsSource, ""); ; this.shaderPrograms.push(shaderProg); // Default shader is always shader 0 fsSource = [ "uniform mediump sampler2D samplerFront;", "varying lowp float opacity;", "void main(void) {", " gl_FragColor = texture2D(samplerFront, gl_PointCoord);", " gl_FragColor *= opacity;", "}" ].join("\n"); var pointVsSource = [ "attribute vec4 aPos;", "varying float opacity;", "uniform mat4 matP;", "uniform mat4 matMV;", "void main(void) {", " gl_Position = matP * matMV * vec4(aPos.x, aPos.y, 0.0, 1.0);", " gl_PointSize = aPos.z;", " opacity = aPos.w;", "}" ].join("\n"); shaderProg = this.createShaderProgram({src: fsSource}, pointVsSource, ""); ; this.shaderPrograms.push(shaderProg); // Point shader is always shader 1 fsSource = [ "varying mediump vec2 vTex;", "uniform lowp sampler2D samplerFront;", "void main(void) {", " if (texture2D(samplerFront, vTex).a < 1.0)", " discard;", // discarding non-opaque fragments "}" ].join("\n"); var shaderProg = this.createShaderProgram({src: fsSource}, vsSource, ""); ; this.shaderPrograms.push(shaderProg); // Early-Z shader is always shader 2 fsSource = [ "uniform lowp vec4 colorFill;", "void main(void) {", " gl_FragColor = colorFill;", "}" ].join("\n"); var shaderProg = this.createShaderProgram({src: fsSource}, vsSource, ""); ; this.shaderPrograms.push(shaderProg); // Fill-color shader is always shader 3 for (var shader_name in cr.shaders) { if (cr.shaders.hasOwnProperty(shader_name)) this.shaderPrograms.push(this.createShaderProgram(cr.shaders[shader_name], vsSource, shader_name)); } gl.activeTexture(gl.TEXTURE0); gl.bindTexture(gl.TEXTURE_2D, null); this.batch = []; this.batchPtr = 0; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; this.lastProgram = -1; // start -1 so first switchProgram can do work this.currentProgram = -1; // current program during batch execution this.currentShader = null; this.fbo = gl.createFramebuffer(); this.renderToTex = null; this.depthBuffer = null; this.attachedDepthBuffer = false; // wait until first size call to attach, otherwise it has no storage if (this.enableFrontToBack) { this.depthBuffer = gl.createRenderbuffer(); } this.tmpVec3 = vec3.create([0, 0, 0]); ; var pointsizes = gl.getParameter(gl.ALIASED_POINT_SIZE_RANGE); this.minPointSize = pointsizes[0]; this.maxPointSize = pointsizes[1]; if (this.maxPointSize > 2048) this.maxPointSize = 2048; ; this.switchProgram(0); cr.seal(this); }; function GLShaderProgram(gl, shaderProgram, name) { this.gl = gl; this.shaderProgram = shaderProgram; this.name = name; this.locAPos = gl.getAttribLocation(shaderProgram, "aPos"); this.locATex = gl.getAttribLocation(shaderProgram, "aTex"); this.locMatP = gl.getUniformLocation(shaderProgram, "matP"); this.locMatMV = gl.getUniformLocation(shaderProgram, "matMV"); this.locOpacity = gl.getUniformLocation(shaderProgram, "opacity"); this.locColorFill = gl.getUniformLocation(shaderProgram, "colorFill"); this.locSamplerFront = gl.getUniformLocation(shaderProgram, "samplerFront"); this.locSamplerBack = gl.getUniformLocation(shaderProgram, "samplerBack"); this.locDestStart = gl.getUniformLocation(shaderProgram, "destStart"); this.locDestEnd = gl.getUniformLocation(shaderProgram, "destEnd"); this.locSeconds = gl.getUniformLocation(shaderProgram, "seconds"); this.locPixelWidth = gl.getUniformLocation(shaderProgram, "pixelWidth"); this.locPixelHeight = gl.getUniformLocation(shaderProgram, "pixelHeight"); this.locLayerScale = gl.getUniformLocation(shaderProgram, "layerScale"); this.locLayerAngle = gl.getUniformLocation(shaderProgram, "layerAngle"); this.locViewOrigin = gl.getUniformLocation(shaderProgram, "viewOrigin"); this.locScrollPos = gl.getUniformLocation(shaderProgram, "scrollPos"); this.hasAnyOptionalUniforms = !!(this.locPixelWidth || this.locPixelHeight || this.locSeconds || this.locSamplerBack || this.locDestStart || this.locDestEnd || this.locLayerScale || this.locLayerAngle || this.locViewOrigin || this.locScrollPos); this.lpPixelWidth = -999; // set to something unlikely so never counts as cached on first set this.lpPixelHeight = -999; this.lpOpacity = 1; this.lpDestStartX = 0.0; this.lpDestStartY = 0.0; this.lpDestEndX = 1.0; this.lpDestEndY = 1.0; this.lpLayerScale = 1.0; this.lpLayerAngle = 0.0; this.lpViewOriginX = 0.0; this.lpViewOriginY = 0.0; this.lpScrollPosX = 0.0; this.lpScrollPosY = 0.0; this.lpSeconds = 0.0; this.lastCustomParams = []; this.lpMatMV = mat4.create(); if (this.locOpacity) gl.uniform1f(this.locOpacity, 1); if (this.locColorFill) gl.uniform4f(this.locColorFill, 1.0, 1.0, 1.0, 1.0); if (this.locSamplerFront) gl.uniform1i(this.locSamplerFront, 0); if (this.locSamplerBack) gl.uniform1i(this.locSamplerBack, 1); if (this.locDestStart) gl.uniform2f(this.locDestStart, 0.0, 0.0); if (this.locDestEnd) gl.uniform2f(this.locDestEnd, 1.0, 1.0); if (this.locLayerScale) gl.uniform1f(this.locLayerScale, 1.0); if (this.locLayerAngle) gl.uniform1f(this.locLayerAngle, 0.0); if (this.locViewOrigin) gl.uniform2f(this.locViewOrigin, 0.0, 0.0); if (this.locScrollPos) gl.uniform2f(this.locScrollPos, 0.0, 0.0); if (this.locSeconds) gl.uniform1f(this.locSeconds, 0.0); this.hasCurrentMatMV = false; // matMV needs updating }; function areMat4sEqual(a, b) { return a[0]===b[0]&&a[1]===b[1]&&a[2]===b[2]&&a[3]===b[3]&& a[4]===b[4]&&a[5]===b[5]&&a[6]===b[6]&&a[7]===b[7]&& a[8]===b[8]&&a[9]===b[9]&&a[10]===b[10]&&a[11]===b[11]&& a[12]===b[12]&&a[13]===b[13]&&a[14]===b[14]&&a[15]===b[15]; }; GLShaderProgram.prototype.updateMatMV = function (mv) { if (areMat4sEqual(this.lpMatMV, mv)) return; // no change, save the expensive GL call mat4.set(mv, this.lpMatMV); this.gl.uniformMatrix4fv(this.locMatMV, false, mv); }; GLWrap_.prototype.createShaderProgram = function(shaderEntry, vsSource, name) { var gl = this.gl; var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, shaderEntry.src); gl.compileShader(fragmentShader); if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { var compilationlog = gl.getShaderInfoLog(fragmentShader); gl.deleteShader(fragmentShader); throw new Error("error compiling fragment shader: " + compilationlog); } var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, vsSource); gl.compileShader(vertexShader); if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { var compilationlog = gl.getShaderInfoLog(vertexShader); gl.deleteShader(fragmentShader); gl.deleteShader(vertexShader); throw new Error("error compiling vertex shader: " + compilationlog); } var shaderProgram = gl.createProgram(); gl.attachShader(shaderProgram, fragmentShader); gl.attachShader(shaderProgram, vertexShader); gl.linkProgram(shaderProgram); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { var compilationlog = gl.getProgramInfoLog(shaderProgram); gl.deleteShader(fragmentShader); gl.deleteShader(vertexShader); gl.deleteProgram(shaderProgram); throw new Error("error linking shader program: " + compilationlog); } gl.useProgram(shaderProgram); gl.deleteShader(fragmentShader); gl.deleteShader(vertexShader); var ret = new GLShaderProgram(gl, shaderProgram, name); ret.extendBoxHorizontal = shaderEntry.extendBoxHorizontal || 0; ret.extendBoxVertical = shaderEntry.extendBoxVertical || 0; ret.crossSampling = !!shaderEntry.crossSampling; ret.preservesOpaqueness = !!shaderEntry.preservesOpaqueness; ret.animated = !!shaderEntry.animated; ret.parameters = shaderEntry.parameters || []; var i, len; for (i = 0, len = ret.parameters.length; i < len; i++) { ret.parameters[i][1] = gl.getUniformLocation(shaderProgram, ret.parameters[i][0]); ret.lastCustomParams.push(0); gl.uniform1f(ret.parameters[i][1], 0); } cr.seal(ret); return ret; }; GLWrap_.prototype.getShaderIndex = function(name_) { var i, len; for (i = 0, len = this.shaderPrograms.length; i < len; i++) { if (this.shaderPrograms[i].name === name_) return i; } return -1; }; GLWrap_.prototype.project = function (x, y, out) { var mv = this.matMV; var proj = this.matP; var fTempo = [0, 0, 0, 0, 0, 0, 0, 0]; fTempo[0] = mv[0]*x+mv[4]*y+mv[12]; fTempo[1] = mv[1]*x+mv[5]*y+mv[13]; fTempo[2] = mv[2]*x+mv[6]*y+mv[14]; fTempo[3] = mv[3]*x+mv[7]*y+mv[15]; fTempo[4] = proj[0]*fTempo[0]+proj[4]*fTempo[1]+proj[8]*fTempo[2]+proj[12]*fTempo[3]; fTempo[5] = proj[1]*fTempo[0]+proj[5]*fTempo[1]+proj[9]*fTempo[2]+proj[13]*fTempo[3]; fTempo[6] = proj[2]*fTempo[0]+proj[6]*fTempo[1]+proj[10]*fTempo[2]+proj[14]*fTempo[3]; fTempo[7] = -fTempo[2]; if(fTempo[7]===0.0) //The w value return; fTempo[7]=1.0/fTempo[7]; fTempo[4]*=fTempo[7]; fTempo[5]*=fTempo[7]; fTempo[6]*=fTempo[7]; out[0]=(fTempo[4]*0.5+0.5)*this.width; out[1]=(fTempo[5]*0.5+0.5)*this.height; }; GLWrap_.prototype.setSize = function(w, h, force) { if (this.width === w && this.height === h && !force) return; this.endBatch(); var gl = this.gl; this.width = w; this.height = h; gl.viewport(0, 0, w, h); mat4.lookAt(this.cam, this.look, this.up, this.matMV); if (this.enableFrontToBack) { mat4.ortho(-w/2, w/2, h/2, -h/2, this.zNear, this.zFar, this.matP); this.worldScale[0] = 1; this.worldScale[1] = 1; } else { mat4.perspective(45, w / h, this.zNear, this.zFar, this.matP); var tl = [0, 0]; var br = [0, 0]; this.project(0, 0, tl); this.project(1, 1, br); this.worldScale[0] = 1 / (br[0] - tl[0]); this.worldScale[1] = -1 / (br[1] - tl[1]); } var i, len, s; for (i = 0, len = this.shaderPrograms.length; i < len; i++) { s = this.shaderPrograms[i]; s.hasCurrentMatMV = false; if (s.locMatP) { gl.useProgram(s.shaderProgram); gl.uniformMatrix4fv(s.locMatP, false, this.matP); } } gl.useProgram(this.shaderPrograms[this.lastProgram].shaderProgram); gl.bindTexture(gl.TEXTURE_2D, null); gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, null); gl.activeTexture(gl.TEXTURE0); this.lastTexture0 = null; this.lastTexture1 = null; if (this.depthBuffer) { gl.bindFramebuffer(gl.FRAMEBUFFER, this.fbo); gl.bindRenderbuffer(gl.RENDERBUFFER, this.depthBuffer); gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, this.width, this.height); if (!this.attachedDepthBuffer) { gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, this.depthBuffer); this.attachedDepthBuffer = true; } gl.bindRenderbuffer(gl.RENDERBUFFER, null); gl.bindFramebuffer(gl.FRAMEBUFFER, null); this.renderToTex = null; } }; GLWrap_.prototype.resetModelView = function () { mat4.lookAt(this.cam, this.look, this.up, this.matMV); mat4.scale(this.matMV, this.worldScale); }; GLWrap_.prototype.translate = function (x, y) { if (x === 0 && y === 0) return; this.tmpVec3[0] = x;// * this.worldScale[0]; this.tmpVec3[1] = y;// * this.worldScale[1]; this.tmpVec3[2] = 0; mat4.translate(this.matMV, this.tmpVec3); }; GLWrap_.prototype.scale = function (x, y) { if (x === 1 && y === 1) return; this.tmpVec3[0] = x; this.tmpVec3[1] = y; this.tmpVec3[2] = 1; mat4.scale(this.matMV, this.tmpVec3); }; GLWrap_.prototype.rotateZ = function (a) { if (a === 0) return; mat4.rotateZ(this.matMV, a); }; GLWrap_.prototype.updateModelView = function() { if (areMat4sEqual(this.lastMV, this.matMV)) return; var b = this.pushBatch(); b.type = BATCH_UPDATEMODELVIEW; if (b.mat4param) mat4.set(this.matMV, b.mat4param); else b.mat4param = mat4.create(this.matMV); mat4.set(this.matMV, this.lastMV); this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; /* var debugBatch = false; jQuery(document).mousedown( function(info) { if (info.which === 2) debugBatch = true; } ); */ GLWrap_.prototype.setEarlyZIndex = function (i) { if (!this.enableFrontToBack) return; if (i > 32760) i = 32760; this.currentZ = this.cam[2] - this.zNear - i * this.zIncrement; }; function GLBatchJob(type_, glwrap_) { this.type = type_; this.glwrap = glwrap_; this.gl = glwrap_.gl; this.opacityParam = 0; // for setOpacity() this.startIndex = 0; // for quad() this.indexCount = 0; // " this.texParam = null; // for setTexture() this.mat4param = null; // for updateModelView() this.shaderParams = []; // for user parameters cr.seal(this); }; GLBatchJob.prototype.doSetEarlyZPass = function () { var gl = this.gl; var glwrap = this.glwrap; if (this.startIndex !== 0) // enable { gl.depthMask(true); // enable depth writes gl.colorMask(false, false, false, false); // disable color writes gl.disable(gl.BLEND); // no color writes so disable blend gl.bindFramebuffer(gl.FRAMEBUFFER, glwrap.fbo); gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); gl.clear(gl.DEPTH_BUFFER_BIT); // auto-clear depth buffer gl.bindFramebuffer(gl.FRAMEBUFFER, null); glwrap.isBatchInEarlyZPass = true; } else { gl.depthMask(false); // disable depth writes, only test existing depth values gl.colorMask(true, true, true, true); // enable color writes gl.enable(gl.BLEND); // turn blending back on glwrap.isBatchInEarlyZPass = false; } }; GLBatchJob.prototype.doSetTexture = function () { this.gl.bindTexture(this.gl.TEXTURE_2D, this.texParam); }; GLBatchJob.prototype.doSetTexture1 = function () { var gl = this.gl; gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, this.texParam); gl.activeTexture(gl.TEXTURE0); }; GLBatchJob.prototype.doSetOpacity = function () { var o = this.opacityParam; var glwrap = this.glwrap; glwrap.currentOpacity = o; var curProg = glwrap.currentShader; if (curProg.locOpacity && curProg.lpOpacity !== o) { curProg.lpOpacity = o; this.gl.uniform1f(curProg.locOpacity, o); } }; GLBatchJob.prototype.doQuad = function () { this.gl.drawElements(this.gl.TRIANGLES, this.indexCount, this.gl.UNSIGNED_SHORT, this.startIndex); }; GLBatchJob.prototype.doSetBlend = function () { this.gl.blendFunc(this.startIndex, this.indexCount); }; GLBatchJob.prototype.doUpdateModelView = function () { var i, len, s, shaderPrograms = this.glwrap.shaderPrograms, currentProgram = this.glwrap.currentProgram; for (i = 0, len = shaderPrograms.length; i < len; i++) { s = shaderPrograms[i]; if (i === currentProgram && s.locMatMV) { s.updateMatMV(this.mat4param); s.hasCurrentMatMV = true; } else s.hasCurrentMatMV = false; } mat4.set(this.mat4param, this.glwrap.currentMV); }; GLBatchJob.prototype.doRenderToTexture = function () { var gl = this.gl; var glwrap = this.glwrap; if (this.texParam) { if (glwrap.lastTexture1 === this.texParam) { gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, null); glwrap.lastTexture1 = null; gl.activeTexture(gl.TEXTURE0); } gl.bindFramebuffer(gl.FRAMEBUFFER, glwrap.fbo); if (!glwrap.isBatchInEarlyZPass) { gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.texParam, 0); } } else { if (!glwrap.enableFrontToBack) { gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0); } gl.bindFramebuffer(gl.FRAMEBUFFER, null); } }; GLBatchJob.prototype.doClear = function () { var gl = this.gl; var mode = this.startIndex; if (mode === 0) // clear whole surface { gl.clearColor(this.mat4param[0], this.mat4param[1], this.mat4param[2], this.mat4param[3]); gl.clear(gl.COLOR_BUFFER_BIT); } else if (mode === 1) // clear rectangle { gl.enable(gl.SCISSOR_TEST); gl.scissor(this.mat4param[0], this.mat4param[1], this.mat4param[2], this.mat4param[3]); gl.clearColor(0, 0, 0, 0); gl.clear(gl.COLOR_BUFFER_BIT); gl.disable(gl.SCISSOR_TEST); } else // clear depth { gl.clear(gl.DEPTH_BUFFER_BIT); } }; GLBatchJob.prototype.doSetDepthTestEnabled = function () { var gl = this.gl; var enable = this.startIndex; if (enable !== 0) { gl.enable(gl.DEPTH_TEST); } else { gl.disable(gl.DEPTH_TEST); } }; GLBatchJob.prototype.doPoints = function () { var gl = this.gl; var glwrap = this.glwrap; if (glwrap.enableFrontToBack) gl.disable(gl.DEPTH_TEST); var s = glwrap.shaderPrograms[1]; gl.useProgram(s.shaderProgram); if (!s.hasCurrentMatMV && s.locMatMV) { s.updateMatMV(glwrap.currentMV); s.hasCurrentMatMV = true; } gl.enableVertexAttribArray(s.locAPos); gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.pointBuffer); gl.vertexAttribPointer(s.locAPos, 4, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.POINTS, this.startIndex / 4, this.indexCount); s = glwrap.currentShader; gl.useProgram(s.shaderProgram); if (s.locAPos >= 0) { gl.enableVertexAttribArray(s.locAPos); gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.vertexBuffers[glwrap.curBuffer]); gl.vertexAttribPointer(s.locAPos, glwrap.enableFrontToBack ? 3 : 2, gl.FLOAT, false, 0, 0); } if (s.locATex >= 0) { gl.enableVertexAttribArray(s.locATex); gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.texcoordBuffers[glwrap.curBuffer]); gl.vertexAttribPointer(s.locATex, 2, gl.FLOAT, false, 0, 0); } if (glwrap.enableFrontToBack) gl.enable(gl.DEPTH_TEST); }; GLBatchJob.prototype.doSetProgram = function () { var gl = this.gl; var glwrap = this.glwrap; var s = glwrap.shaderPrograms[this.startIndex]; // recycled param to save memory glwrap.currentProgram = this.startIndex; // current batch program glwrap.currentShader = s; gl.useProgram(s.shaderProgram); // switch to if (!s.hasCurrentMatMV && s.locMatMV) { s.updateMatMV(glwrap.currentMV); s.hasCurrentMatMV = true; } if (s.locOpacity && s.lpOpacity !== glwrap.currentOpacity) { s.lpOpacity = glwrap.currentOpacity; gl.uniform1f(s.locOpacity, glwrap.currentOpacity); } if (s.locAPos >= 0) { gl.enableVertexAttribArray(s.locAPos); gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.vertexBuffers[glwrap.curBuffer]); gl.vertexAttribPointer(s.locAPos, glwrap.enableFrontToBack ? 3 : 2, gl.FLOAT, false, 0, 0); } if (s.locATex >= 0) { gl.enableVertexAttribArray(s.locATex); gl.bindBuffer(gl.ARRAY_BUFFER, glwrap.texcoordBuffers[glwrap.curBuffer]); gl.vertexAttribPointer(s.locATex, 2, gl.FLOAT, false, 0, 0); } } GLBatchJob.prototype.doSetColor = function () { var s = this.glwrap.currentShader; var mat4param = this.mat4param; this.gl.uniform4f(s.locColorFill, mat4param[0], mat4param[1], mat4param[2], mat4param[3]); }; GLBatchJob.prototype.doSetProgramParameters = function () { var i, len, s = this.glwrap.currentShader; var gl = this.gl; var mat4param = this.mat4param; if (s.locSamplerBack && this.glwrap.lastTexture1 !== this.texParam) { gl.activeTexture(gl.TEXTURE1); gl.bindTexture(gl.TEXTURE_2D, this.texParam); this.glwrap.lastTexture1 = this.texParam; gl.activeTexture(gl.TEXTURE0); } var v = mat4param[0]; var v2; if (s.locPixelWidth && v !== s.lpPixelWidth) { s.lpPixelWidth = v; gl.uniform1f(s.locPixelWidth, v); } v = mat4param[1]; if (s.locPixelHeight && v !== s.lpPixelHeight) { s.lpPixelHeight = v; gl.uniform1f(s.locPixelHeight, v); } v = mat4param[2]; v2 = mat4param[3]; if (s.locDestStart && (v !== s.lpDestStartX || v2 !== s.lpDestStartY)) { s.lpDestStartX = v; s.lpDestStartY = v2; gl.uniform2f(s.locDestStart, v, v2); } v = mat4param[4]; v2 = mat4param[5]; if (s.locDestEnd && (v !== s.lpDestEndX || v2 !== s.lpDestEndY)) { s.lpDestEndX = v; s.lpDestEndY = v2; gl.uniform2f(s.locDestEnd, v, v2); } v = mat4param[6]; if (s.locLayerScale && v !== s.lpLayerScale) { s.lpLayerScale = v; gl.uniform1f(s.locLayerScale, v); } v = mat4param[7]; if (s.locLayerAngle && v !== s.lpLayerAngle) { s.lpLayerAngle = v; gl.uniform1f(s.locLayerAngle, v); } v = mat4param[8]; v2 = mat4param[9]; if (s.locViewOrigin && (v !== s.lpViewOriginX || v2 !== s.lpViewOriginY)) { s.lpViewOriginX = v; s.lpViewOriginY = v2; gl.uniform2f(s.locViewOrigin, v, v2); } v = mat4param[10]; v2 = mat4param[11]; if (s.locScrollPos && (v !== s.lpScrollPosX || v2 !== s.lpScrollPosY)) { s.lpScrollPosX = v; s.lpScrollPosY = v2; gl.uniform2f(s.locScrollPos, v, v2); } v = mat4param[12]; if (s.locSeconds && v !== s.lpSeconds) { s.lpSeconds = v; gl.uniform1f(s.locSeconds, v); } if (s.parameters.length) { for (i = 0, len = s.parameters.length; i < len; i++) { v = this.shaderParams[i]; if (v !== s.lastCustomParams[i]) { s.lastCustomParams[i] = v; gl.uniform1f(s.parameters[i][1], v); } } } }; GLWrap_.prototype.pushBatch = function () { if (this.batchPtr === this.batch.length) this.batch.push(new GLBatchJob(BATCH_NULL, this)); return this.batch[this.batchPtr++]; }; GLWrap_.prototype.endBatch = function () { if (this.batchPtr === 0) return; if (this.gl.isContextLost()) return; var gl = this.gl; if (this.pointPtr > 0) { gl.bindBuffer(gl.ARRAY_BUFFER, this.pointBuffer); gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.pointData.subarray(0, this.pointPtr)); if (s && s.locAPos >= 0 && s.name === "") gl.vertexAttribPointer(s.locAPos, 4, gl.FLOAT, false, 0, 0); } if (this.vertexPtr > 0) { var s = this.currentShader; gl.bindBuffer(gl.ARRAY_BUFFER, this.vertexBuffers[this.curBuffer]); gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.vertexData.subarray(0, this.vertexPtr)); if (s && s.locAPos >= 0 && s.name !== "") gl.vertexAttribPointer(s.locAPos, this.enableFrontToBack ? 3 : 2, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, this.texcoordBuffers[this.curBuffer]); gl.bufferSubData(gl.ARRAY_BUFFER, 0, this.texcoordData.subarray(0, this.texPtr)); if (s && s.locATex >= 0 && s.name !== "") gl.vertexAttribPointer(s.locATex, 2, gl.FLOAT, false, 0, 0); } var i, len, b; for (i = 0, len = this.batchPtr; i < len; i++) { b = this.batch[i]; switch (b.type) { case 1: b.doQuad(); break; case 2: b.doSetTexture(); break; case 3: b.doSetOpacity(); break; case 4: b.doSetBlend(); break; case 5: b.doUpdateModelView(); break; case 6: b.doRenderToTexture(); break; case 7: b.doClear(); break; case 8: b.doPoints(); break; case 9: b.doSetProgram(); break; case 10: b.doSetProgramParameters(); break; case 11: b.doSetTexture1(); break; case 12: b.doSetColor(); break; case 13: b.doSetDepthTestEnabled(); break; case 14: b.doSetEarlyZPass(); break; } } this.batchPtr = 0; this.vertexPtr = 0; this.texPtr = 0; this.pointPtr = 0; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; this.isBatchInEarlyZPass = false; this.curBuffer++; if (this.curBuffer >= MULTI_BUFFERS) this.curBuffer = 0; }; GLWrap_.prototype.setOpacity = function (op) { if (op === this.lastOpacity) return; if (this.isEarlyZPass) return; // ignore var b = this.pushBatch(); b.type = BATCH_SETOPACITY; b.opacityParam = op; this.lastOpacity = op; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.setTexture = function (tex) { if (tex === this.lastTexture0) return; ; var b = this.pushBatch(); b.type = BATCH_SETTEXTURE; b.texParam = tex; this.lastTexture0 = tex; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.setBlend = function (s, d) { if (s === this.lastSrcBlend && d === this.lastDestBlend) return; if (this.isEarlyZPass) return; // ignore var b = this.pushBatch(); b.type = BATCH_SETBLEND; b.startIndex = s; // recycle params to save memory b.indexCount = d; this.lastSrcBlend = s; this.lastDestBlend = d; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.isPremultipliedAlphaBlend = function () { return (this.lastSrcBlend === this.gl.ONE && this.lastDestBlend === this.gl.ONE_MINUS_SRC_ALPHA); }; GLWrap_.prototype.setAlphaBlend = function () { this.setBlend(this.gl.ONE, this.gl.ONE_MINUS_SRC_ALPHA); }; GLWrap_.prototype.setNoPremultiplyAlphaBlend = function () { this.setBlend(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA); }; var LAST_VERTEX = MAX_VERTICES * 2 - 8; GLWrap_.prototype.quad = function(tlx, tly, trx, try_, brx, bry, blx, bly) { if (this.vertexPtr >= LAST_VERTEX) this.endBatch(); var v = this.vertexPtr; // vertex cursor var t = this.texPtr; var vd = this.vertexData; // vertex data array var td = this.texcoordData; // texture coord data array var currentZ = this.currentZ; if (this.hasQuadBatchTop) { this.batch[this.batchPtr - 1].indexCount += 6; } else { var b = this.pushBatch(); b.type = BATCH_QUAD; b.startIndex = this.enableFrontToBack ? v : (v / 2) * 3; b.indexCount = 6; this.hasQuadBatchTop = true; this.hasPointBatchTop = false; } if (this.enableFrontToBack) { vd[v++] = tlx; vd[v++] = tly; vd[v++] = currentZ; vd[v++] = trx; vd[v++] = try_; vd[v++] = currentZ; vd[v++] = brx; vd[v++] = bry; vd[v++] = currentZ; vd[v++] = blx; vd[v++] = bly; vd[v++] = currentZ; } else { vd[v++] = tlx; vd[v++] = tly; vd[v++] = trx; vd[v++] = try_; vd[v++] = brx; vd[v++] = bry; vd[v++] = blx; vd[v++] = bly; } td[t++] = 0; td[t++] = 0; td[t++] = 1; td[t++] = 0; td[t++] = 1; td[t++] = 1; td[t++] = 0; td[t++] = 1; this.vertexPtr = v; this.texPtr = t; }; GLWrap_.prototype.quadTex = function(tlx, tly, trx, try_, brx, bry, blx, bly, rcTex) { if (this.vertexPtr >= LAST_VERTEX) this.endBatch(); var v = this.vertexPtr; // vertex cursor var t = this.texPtr; var vd = this.vertexData; // vertex data array var td = this.texcoordData; // texture coord data array var currentZ = this.currentZ; if (this.hasQuadBatchTop) { this.batch[this.batchPtr - 1].indexCount += 6; } else { var b = this.pushBatch(); b.type = BATCH_QUAD; b.startIndex = this.enableFrontToBack ? v : (v / 2) * 3; b.indexCount = 6; this.hasQuadBatchTop = true; this.hasPointBatchTop = false; } var rc_left = rcTex.left; var rc_top = rcTex.top; var rc_right = rcTex.right; var rc_bottom = rcTex.bottom; if (this.enableFrontToBack) { vd[v++] = tlx; vd[v++] = tly; vd[v++] = currentZ; vd[v++] = trx; vd[v++] = try_; vd[v++] = currentZ; vd[v++] = brx; vd[v++] = bry; vd[v++] = currentZ; vd[v++] = blx; vd[v++] = bly; vd[v++] = currentZ; } else { vd[v++] = tlx; vd[v++] = tly; vd[v++] = trx; vd[v++] = try_; vd[v++] = brx; vd[v++] = bry; vd[v++] = blx; vd[v++] = bly; } td[t++] = rc_left; td[t++] = rc_top; td[t++] = rc_right; td[t++] = rc_top; td[t++] = rc_right; td[t++] = rc_bottom; td[t++] = rc_left; td[t++] = rc_bottom; this.vertexPtr = v; this.texPtr = t; }; GLWrap_.prototype.quadTexUV = function(tlx, tly, trx, try_, brx, bry, blx, bly, tlu, tlv, tru, trv, bru, brv, blu, blv) { if (this.vertexPtr >= LAST_VERTEX) this.endBatch(); var v = this.vertexPtr; // vertex cursor var t = this.texPtr; var vd = this.vertexData; // vertex data array var td = this.texcoordData; // texture coord data array var currentZ = this.currentZ; if (this.hasQuadBatchTop) { this.batch[this.batchPtr - 1].indexCount += 6; } else { var b = this.pushBatch(); b.type = BATCH_QUAD; b.startIndex = this.enableFrontToBack ? v : (v / 2) * 3; b.indexCount = 6; this.hasQuadBatchTop = true; this.hasPointBatchTop = false; } if (this.enableFrontToBack) { vd[v++] = tlx; vd[v++] = tly; vd[v++] = currentZ; vd[v++] = trx; vd[v++] = try_; vd[v++] = currentZ; vd[v++] = brx; vd[v++] = bry; vd[v++] = currentZ; vd[v++] = blx; vd[v++] = bly; vd[v++] = currentZ; } else { vd[v++] = tlx; vd[v++] = tly; vd[v++] = trx; vd[v++] = try_; vd[v++] = brx; vd[v++] = bry; vd[v++] = blx; vd[v++] = bly; } td[t++] = tlu; td[t++] = tlv; td[t++] = tru; td[t++] = trv; td[t++] = bru; td[t++] = brv; td[t++] = blu; td[t++] = blv; this.vertexPtr = v; this.texPtr = t; }; GLWrap_.prototype.convexPoly = function(pts) { var pts_count = pts.length / 2; ; var tris = pts_count - 2; // 3 points = 1 tri, 4 points = 2 tris, 5 points = 3 tris etc. var last_tri = tris - 1; var p0x = pts[0]; var p0y = pts[1]; var i, i2, p1x, p1y, p2x, p2y, p3x, p3y; for (i = 0; i < tris; i += 2) // draw 2 triangles at a time { i2 = i * 2; p1x = pts[i2 + 2]; p1y = pts[i2 + 3]; p2x = pts[i2 + 4]; p2y = pts[i2 + 5]; if (i === last_tri) { this.quad(p0x, p0y, p1x, p1y, p2x, p2y, p2x, p2y); } else { p3x = pts[i2 + 6]; p3y = pts[i2 + 7]; this.quad(p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y); } } }; var LAST_POINT = MAX_POINTS - 4; GLWrap_.prototype.point = function(x_, y_, size_, opacity_) { if (this.pointPtr >= LAST_POINT) this.endBatch(); var p = this.pointPtr; // point cursor var pd = this.pointData; // point data array if (this.hasPointBatchTop) { this.batch[this.batchPtr - 1].indexCount++; } else { var b = this.pushBatch(); b.type = BATCH_POINTS; b.startIndex = p; b.indexCount = 1; this.hasPointBatchTop = true; this.hasQuadBatchTop = false; } pd[p++] = x_; pd[p++] = y_; pd[p++] = size_; pd[p++] = opacity_; this.pointPtr = p; }; GLWrap_.prototype.switchProgram = function (progIndex) { if (this.lastProgram === progIndex) return; // no change var shaderProg = this.shaderPrograms[progIndex]; if (!shaderProg) { if (this.lastProgram === 0) return; // already on default shader progIndex = 0; shaderProg = this.shaderPrograms[0]; } var b = this.pushBatch(); b.type = BATCH_SETPROGRAM; b.startIndex = progIndex; this.lastProgram = progIndex; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.programUsesDest = function (progIndex) { var s = this.shaderPrograms[progIndex]; return !!(s.locDestStart || s.locDestEnd); }; GLWrap_.prototype.programUsesCrossSampling = function (progIndex) { var s = this.shaderPrograms[progIndex]; return !!(s.locDestStart || s.locDestEnd || s.crossSampling); }; GLWrap_.prototype.programPreservesOpaqueness = function (progIndex) { return this.shaderPrograms[progIndex].preservesOpaqueness; }; GLWrap_.prototype.programExtendsBox = function (progIndex) { var s = this.shaderPrograms[progIndex]; return s.extendBoxHorizontal !== 0 || s.extendBoxVertical !== 0; }; GLWrap_.prototype.getProgramBoxExtendHorizontal = function (progIndex) { return this.shaderPrograms[progIndex].extendBoxHorizontal; }; GLWrap_.prototype.getProgramBoxExtendVertical = function (progIndex) { return this.shaderPrograms[progIndex].extendBoxVertical; }; GLWrap_.prototype.getProgramParameterType = function (progIndex, paramIndex) { return this.shaderPrograms[progIndex].parameters[paramIndex][2]; }; GLWrap_.prototype.programIsAnimated = function (progIndex) { return this.shaderPrograms[progIndex].animated; }; GLWrap_.prototype.setProgramParameters = function (backTex, pixelWidth, pixelHeight, destStartX, destStartY, destEndX, destEndY, layerScale, layerAngle, viewOriginLeft, viewOriginTop, scrollPosX, scrollPosY, seconds, params) { var i, len; var s = this.shaderPrograms[this.lastProgram]; var b, mat4param, shaderParams; if (s.hasAnyOptionalUniforms || params.length) { b = this.pushBatch(); b.type = BATCH_SETPROGRAMPARAMETERS; if (b.mat4param) mat4.set(this.matMV, b.mat4param); else b.mat4param = mat4.create(); mat4param = b.mat4param; mat4param[0] = pixelWidth; mat4param[1] = pixelHeight; mat4param[2] = destStartX; mat4param[3] = destStartY; mat4param[4] = destEndX; mat4param[5] = destEndY; mat4param[6] = layerScale; mat4param[7] = layerAngle; mat4param[8] = viewOriginLeft; mat4param[9] = viewOriginTop; mat4param[10] = scrollPosX; mat4param[11] = scrollPosY; mat4param[12] = seconds; if (s.locSamplerBack) { ; b.texParam = backTex; } else b.texParam = null; if (params.length) { shaderParams = b.shaderParams; shaderParams.length = params.length; for (i = 0, len = params.length; i < len; i++) shaderParams[i] = params[i]; } this.hasQuadBatchTop = false; this.hasPointBatchTop = false; } }; GLWrap_.prototype.clear = function (r, g, b_, a) { var b = this.pushBatch(); b.type = BATCH_CLEAR; b.startIndex = 0; // clear all mode if (!b.mat4param) b.mat4param = mat4.create(); b.mat4param[0] = r; b.mat4param[1] = g; b.mat4param[2] = b_; b.mat4param[3] = a; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.clearRect = function (x, y, w, h) { if (w < 0 || h < 0) return; // invalid clear area var b = this.pushBatch(); b.type = BATCH_CLEAR; b.startIndex = 1; // clear rect mode if (!b.mat4param) b.mat4param = mat4.create(); b.mat4param[0] = x; b.mat4param[1] = y; b.mat4param[2] = w; b.mat4param[3] = h; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.clearDepth = function () { var b = this.pushBatch(); b.type = BATCH_CLEAR; b.startIndex = 2; // clear depth mode this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.setEarlyZPass = function (e) { if (!this.enableFrontToBack) return; // no depth buffer in use e = !!e; if (this.isEarlyZPass === e) return; // no change var b = this.pushBatch(); b.type = BATCH_SETEARLYZMODE; b.startIndex = (e ? 1 : 0); this.hasQuadBatchTop = false; this.hasPointBatchTop = false; this.isEarlyZPass = e; this.renderToTex = null; if (this.isEarlyZPass) { this.switchProgram(2); // early Z program } else { this.switchProgram(0); // normal rendering } }; GLWrap_.prototype.setDepthTestEnabled = function (e) { if (!this.enableFrontToBack) return; // no depth buffer in use var b = this.pushBatch(); b.type = BATCH_SETDEPTHTEST; b.startIndex = (e ? 1 : 0); this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.fullscreenQuad = function () { mat4.set(this.lastMV, tempMat4); this.resetModelView(); this.updateModelView(); var halfw = this.width / 2; var halfh = this.height / 2; this.quad(-halfw, halfh, halfw, halfh, halfw, -halfh, -halfw, -halfh); mat4.set(tempMat4, this.matMV); this.updateModelView(); }; GLWrap_.prototype.setColorFillMode = function (r_, g_, b_, a_) { this.switchProgram(3); var b = this.pushBatch(); b.type = BATCH_SETCOLOR; if (!b.mat4param) b.mat4param = mat4.create(); b.mat4param[0] = r_; b.mat4param[1] = g_; b.mat4param[2] = b_; b.mat4param[3] = a_; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; GLWrap_.prototype.setTextureFillMode = function () { ; this.switchProgram(0); }; GLWrap_.prototype.restoreEarlyZMode = function () { ; this.switchProgram(2); }; GLWrap_.prototype.present = function () { this.endBatch(); this.gl.flush(); /* if (debugBatch) { ; debugBatch = false; } */ }; function nextHighestPowerOfTwo(x) { --x; for (var i = 1; i < 32; i <<= 1) { x = x | x >> i; } return x + 1; } var all_textures = []; var textures_by_src = {}; GLWrap_.prototype.contextLost = function () { cr.clearArray(all_textures); textures_by_src = {}; }; var BF_RGBA8 = 0; var BF_RGB8 = 1; var BF_RGBA4 = 2; var BF_RGB5_A1 = 3; var BF_RGB565 = 4; GLWrap_.prototype.loadTexture = function (img, tiling, linearsampling, pixelformat, tiletype, nomip) { tiling = !!tiling; linearsampling = !!linearsampling; var tex_key = img.src + "," + tiling + "," + linearsampling + (tiling ? ("," + tiletype) : ""); var webGL_texture = null; if (typeof img.src !== "undefined" && textures_by_src.hasOwnProperty(tex_key)) { webGL_texture = textures_by_src[tex_key]; webGL_texture.c2refcount++; return webGL_texture; } this.endBatch(); ; var gl = this.gl; var isPOT = (cr.isPOT(img.width) && cr.isPOT(img.height)); webGL_texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, webGL_texture); gl.pixelStorei(gl["UNPACK_PREMULTIPLY_ALPHA_WEBGL"], true); var internalformat = gl.RGBA; var format = gl.RGBA; var type = gl.UNSIGNED_BYTE; if (pixelformat && !this.isIE) { switch (pixelformat) { case BF_RGB8: internalformat = gl.RGB; format = gl.RGB; break; case BF_RGBA4: type = gl.UNSIGNED_SHORT_4_4_4_4; break; case BF_RGB5_A1: type = gl.UNSIGNED_SHORT_5_5_5_1; break; case BF_RGB565: internalformat = gl.RGB; format = gl.RGB; type = gl.UNSIGNED_SHORT_5_6_5; break; } } if (this.version === 1 && !isPOT && tiling) { var canvas = document.createElement("canvas"); canvas.width = cr.nextHighestPowerOfTwo(img.width); canvas.height = cr.nextHighestPowerOfTwo(img.height); var ctx = canvas.getContext("2d"); if (typeof ctx["imageSmoothingEnabled"] !== "undefined") { ctx["imageSmoothingEnabled"] = linearsampling; } else { ctx["webkitImageSmoothingEnabled"] = linearsampling; ctx["mozImageSmoothingEnabled"] = linearsampling; ctx["msImageSmoothingEnabled"] = linearsampling; } ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height); gl.texImage2D(gl.TEXTURE_2D, 0, internalformat, format, type, canvas); } else gl.texImage2D(gl.TEXTURE_2D, 0, internalformat, format, type, img); if (tiling) { if (tiletype === "repeat-x") { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); } else if (tiletype === "repeat-y") { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); } else { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); } } else { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); } if (linearsampling) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR); if ((isPOT || this.version >= 2) && this.enable_mipmaps && !nomip) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR); gl.generateMipmap(gl.TEXTURE_2D); } else gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); } else { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); } gl.bindTexture(gl.TEXTURE_2D, null); this.lastTexture0 = null; webGL_texture.c2width = img.width; webGL_texture.c2height = img.height; webGL_texture.c2refcount = 1; webGL_texture.c2texkey = tex_key; all_textures.push(webGL_texture); textures_by_src[tex_key] = webGL_texture; return webGL_texture; }; GLWrap_.prototype.createEmptyTexture = function (w, h, linearsampling, _16bit, tiling) { this.endBatch(); var gl = this.gl; if (this.isIE) _16bit = false; var webGL_texture = gl.createTexture(); gl.bindTexture(gl.TEXTURE_2D, webGL_texture); 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); if (tiling) { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT); } else { gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE); } gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, linearsampling ? gl.LINEAR : gl.NEAREST); gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, linearsampling ? gl.LINEAR : gl.NEAREST); gl.bindTexture(gl.TEXTURE_2D, null); this.lastTexture0 = null; webGL_texture.c2width = w; webGL_texture.c2height = h; all_textures.push(webGL_texture); return webGL_texture; }; GLWrap_.prototype.videoToTexture = function (video_, texture_, _16bit) { this.endBatch(); var gl = this.gl; if (this.isIE) _16bit = false; gl.bindTexture(gl.TEXTURE_2D, texture_); gl.pixelStorei(gl["UNPACK_PREMULTIPLY_ALPHA_WEBGL"], true); try { gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, _16bit ? gl.UNSIGNED_SHORT_4_4_4_4 : gl.UNSIGNED_BYTE, video_); } catch (e) { if (console && console.error) console.error("Error updating WebGL texture: ", e); } gl.bindTexture(gl.TEXTURE_2D, null); this.lastTexture0 = null; }; GLWrap_.prototype.deleteTexture = function (tex) { if (!tex) return; if (typeof tex.c2refcount !== "undefined" && tex.c2refcount > 1) { tex.c2refcount--; return; } this.endBatch(); if (tex === this.lastTexture0) { this.gl.bindTexture(this.gl.TEXTURE_2D, null); this.lastTexture0 = null; } if (tex === this.lastTexture1) { this.gl.activeTexture(this.gl.TEXTURE1); this.gl.bindTexture(this.gl.TEXTURE_2D, null); this.gl.activeTexture(this.gl.TEXTURE0); this.lastTexture1 = null; } cr.arrayFindRemove(all_textures, tex); if (typeof tex.c2texkey !== "undefined") delete textures_by_src[tex.c2texkey]; this.gl.deleteTexture(tex); }; GLWrap_.prototype.estimateVRAM = function () { var total = this.width * this.height * 4 * 2; var i, len, t; for (i = 0, len = all_textures.length; i < len; i++) { t = all_textures[i]; total += (t.c2width * t.c2height * 4); } return total; }; GLWrap_.prototype.textureCount = function () { return all_textures.length; }; GLWrap_.prototype.setRenderingToTexture = function (tex) { if (tex === this.renderToTex) return; ; var b = this.pushBatch(); b.type = BATCH_RENDERTOTEXTURE; b.texParam = tex; this.renderToTex = tex; this.hasQuadBatchTop = false; this.hasPointBatchTop = false; }; cr.GLWrap = GLWrap_; }()); ; (function() { var raf = window["requestAnimationFrame"] || window["mozRequestAnimationFrame"] || window["webkitRequestAnimationFrame"] || window["msRequestAnimationFrame"] || window["oRequestAnimationFrame"]; function Runtime(canvas) { if (!canvas || (!canvas.getContext && !canvas["dc"])) return; if (canvas["c2runtime"]) return; else canvas["c2runtime"] = this; var self = this; this.isCrosswalk = /crosswalk/i.test(navigator.userAgent) || /xwalk/i.test(navigator.userAgent) || !!(typeof window["c2isCrosswalk"] !== "undefined" && window["c2isCrosswalk"]); this.isCordova = this.isCrosswalk || (typeof window["device"] !== "undefined" && (typeof window["device"]["cordova"] !== "undefined" || typeof window["device"]["phonegap"] !== "undefined")) || (typeof window["c2iscordova"] !== "undefined" && window["c2iscordova"]); this.isPhoneGap = this.isCordova; this.isDirectCanvas = !!canvas["dc"]; this.isAppMobi = (typeof window["AppMobi"] !== "undefined" || this.isDirectCanvas); this.isCocoonJs = !!window["c2cocoonjs"]; this.isEjecta = !!window["c2ejecta"]; if (this.isCocoonJs) { CocoonJS["App"]["onSuspended"].addEventListener(function() { self["setSuspended"](true); }); CocoonJS["App"]["onActivated"].addEventListener(function () { self["setSuspended"](false); }); } if (this.isEjecta) { document.addEventListener("pagehide", function() { self["setSuspended"](true); }); document.addEventListener("pageshow", function() { self["setSuspended"](false); }); document.addEventListener("resize", function () { self["setSize"](window.innerWidth, window.innerHeight); }); } this.isDomFree = (this.isDirectCanvas || this.isCocoonJs || this.isEjecta); this.isMicrosoftEdge = /edge\//i.test(navigator.userAgent); this.isIE = (/msie/i.test(navigator.userAgent) || /trident/i.test(navigator.userAgent) || /iemobile/i.test(navigator.userAgent)) && !this.isMicrosoftEdge; this.isTizen = /tizen/i.test(navigator.userAgent); this.isAndroid = /android/i.test(navigator.userAgent) && !this.isTizen && !this.isIE && !this.isMicrosoftEdge; // IE mobile and Tizen masquerade as Android 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 this.isiPad = /ipad/i.test(navigator.userAgent); this.isiPadMacitosh = /macintosh/i.test(navigator.userAgent) && this.isCordova; this.isiOS = this.isiPhone || this.isiPad || this.isEjecta || this.isiPadMacitosh; this.isiPhoneiOS6 = (this.isiPhone && /os\s6/i.test(navigator.userAgent)); 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 this.isAmazonWebApp = /amazonwebappplatform/i.test(navigator.userAgent); this.isFirefox = /firefox/i.test(navigator.userAgent); this.isSafari = /safari/i.test(navigator.userAgent) && !this.isChrome && !this.isIE && !this.isMicrosoftEdge; // Chrome and IE Mobile masquerade as Safari this.isWindows = /windows/i.test(navigator.userAgent); this.isNWjs = (typeof window["c2nodewebkit"] !== "undefined" || typeof window["c2nwjs"] !== "undefined" || /nodewebkit/i.test(navigator.userAgent) || /nwjs/i.test(navigator.userAgent)); this.isNodeWebkit = this.isNWjs; // old name for backwards compat this.isArcade = (typeof window["is_scirra_arcade"] !== "undefined"); this.isWindows8App = !!(typeof window["c2isWindows8"] !== "undefined" && window["c2isWindows8"]); this.isWindows8Capable = !!(typeof window["c2isWindows8Capable"] !== "undefined" && window["c2isWindows8Capable"]); this.isWindowsPhone8 = !!(typeof window["c2isWindowsPhone8"] !== "undefined" && window["c2isWindowsPhone8"]); this.isWindowsPhone81 = !!(typeof window["c2isWindowsPhone81"] !== "undefined" && window["c2isWindowsPhone81"]); this.isWindows10 = !!window["cr_windows10"]; this.isWinJS = (this.isWindows8App || this.isWindows8Capable || this.isWindowsPhone81 || this.isWindows10); // note not WP8.0 this.isBlackberry10 = !!(typeof window["c2isBlackberry10"] !== "undefined" && window["c2isBlackberry10"]); this.isAndroidStockBrowser = (this.isAndroid && !this.isChrome && !this.isCrosswalk && !this.isFirefox && !this.isAmazonWebApp && !this.isDomFree); this.devicePixelRatio = 1; this.isMobile = (this.isCordova || this.isCrosswalk || this.isAppMobi || this.isCocoonJs || this.isAndroid || this.isiOS || this.isWindowsPhone8 || this.isWindowsPhone81 || this.isBlackberry10 || this.isTizen || this.isEjecta); if (!this.isMobile) { this.isMobile = /(blackberry|bb10|playbook|palm|symbian|nokia|windows\s+ce|phone|mobile|tablet|kindle|silk)/i.test(navigator.userAgent); } this.isWKWebView = !!(this.isiOS && this.isCordova && window["webkit"]); if (typeof cr_is_preview !== "undefined" && !this.isNWjs && (window.location.search === "?nw" || /nodewebkit/i.test(navigator.userAgent) || /nwjs/i.test(navigator.userAgent))) { this.isNWjs = true; } this.isDebug = (typeof cr_is_preview !== "undefined" && window.location.search.indexOf("debug") > -1); this.canvas = canvas; this.canvasdiv = document.getElementById("c2canvasdiv"); this.gl = null; this.glwrap = null; this.glUnmaskedRenderer = "(unavailable)"; this.enableFrontToBack = false; this.earlyz_index = 0; this.ctx = null; this.firstInFullscreen = false; this.oldWidth = 0; // for restoring non-fullscreen canvas after fullscreen this.oldHeight = 0; this.canvas.oncontextmenu = function (e) { if (e.preventDefault) e.preventDefault(); return false; }; this.canvas.onselectstart = function (e) { if (e.preventDefault) e.preventDefault(); return false; }; this.canvas.ontouchstart = function (e) { if(e.preventDefault) e.preventDefault(); return false; }; if (this.isDirectCanvas) window["c2runtime"] = this; if (this.isNWjs) { window["ondragover"] = function(e) { e.preventDefault(); return false; }; window["ondrop"] = function(e) { e.preventDefault(); return false; }; if (window["nwgui"] && window["nwgui"]["App"]["clearCache"]) window["nwgui"]["App"]["clearCache"](); } if (this.isAndroidStockBrowser && typeof jQuery !== "undefined") { jQuery("canvas").parents("*").css("overflow", "visible"); } this.width = canvas.width; this.height = canvas.height; this.draw_width = this.width; this.draw_height = this.height; this.cssWidth = this.width; this.cssHeight = this.height; this.lastWindowWidth = window.innerWidth; this.lastWindowHeight = window.innerHeight; this.forceCanvasAlpha = false; // note: now unused, left for backwards compat since plugins could modify it this.redraw = true; this.isSuspended = false; if (!Date.now) { Date.now = function now() { return +new Date(); }; } this.plugins = []; this.types = {}; this.types_by_index = []; this.behaviors = []; this.layouts = {}; this.layouts_by_index = []; this.eventsheets = {}; this.eventsheets_by_index = []; this.wait_for_textures = []; // for blocking until textures loaded this.triggers_to_postinit = []; this.all_global_vars = []; this.all_local_vars = []; this.solidBehavior = null; this.jumpthruBehavior = null; this.shadowcasterBehavior = null; this.deathRow = {}; this.hasPendingInstances = false; // true if anything exists in create row or death row this.isInClearDeathRow = false; this.isInOnDestroy = 0; // needs to support recursion so increments and decrements and is true if > 0 this.isRunningEvents = false; this.isEndingLayout = false; this.createRow = []; this.isLoadingState = false; this.saveToSlot = ""; this.loadFromSlot = ""; this.loadFromJson = null; // set to string when there is something to try to load this.lastSaveJson = ""; this.signalledContinuousPreview = false; this.suspendDrawing = false; // for hiding display until continuous preview loads this.fireOnCreateAfterLoad = []; // for delaying "On create" triggers until loading complete this.dt = 0; this.dt1 = 0; this.minimumFramerate = 30; this.logictime = 0; // used to calculate CPUUtilisation this.cpuutilisation = 0; this.timescale = 1.0; this.kahanTime = new cr.KahanAdder(); this.wallTime = new cr.KahanAdder(); this.last_tick_time = 0; this.fps = 0; this.last_fps_time = 0; this.tickcount = 0; this.tickcount_nosave = 0; // same as tickcount but never saved/loaded this.execcount = 0; this.framecount = 0; // for fps this.objectcount = 0; this.changelayout = null; this.destroycallbacks = []; this.event_stack = []; this.event_stack_index = -1; this.localvar_stack = [[]]; this.localvar_stack_index = 0; this.trigger_depth = 0; // recursion depth for triggers this.pushEventStack(null); this.loop_stack = []; this.loop_stack_index = -1; this.next_uid = 0; this.next_puid = 0; // permanent unique ids this.layout_first_tick = true; this.family_count = 0; this.suspend_events = []; this.raf_id = -1; this.timeout_id = -1; this.isloading = true; this.loadingprogress = 0; this.isNodeFullscreen = false; this.stackLocalCount = 0; // number of stack-based local vars for recursion this.audioInstance = null; this.had_a_click = false; this.isInUserInputEvent = false; this.objects_to_pretick = new cr.ObjectSet(); this.objects_to_tick = new cr.ObjectSet(); this.objects_to_tick2 = new cr.ObjectSet(); this.registered_collisions = []; this.temp_poly = new cr.CollisionPoly([]); this.temp_poly2 = new cr.CollisionPoly([]); this.allGroups = []; // array of all event groups this.groups_by_name = {}; this.cndsBySid = {}; this.actsBySid = {}; this.varsBySid = {}; this.blocksBySid = {}; this.running_layout = null; // currently running layout this.layer_canvas = null; // for layers "render-to-texture" this.layer_ctx = null; this.layer_tex = null; this.layout_tex = null; this.layout_canvas = null; this.layout_ctx = null; this.is_WebGL_context_lost = false; this.uses_background_blending = false; // if any shader uses background blending, so entire layout renders to texture this.fx_tex = [null, null]; this.fullscreen_scaling = 0; this.files_subfolder = ""; // path with project files this.objectsByUid = {}; // maps every in-use UID (as a string) to its instance this.loaderlogos = null; this.snapshotCanvas = null; this.snapshotData = ""; this.objectRefTable = []; this.requestProjectData(); }; Runtime.prototype.requestProjectData = function () { var self = this; if (this.isWKWebView) { this.fetchLocalFileViaCordovaAsText("data.js", function (str) { self.loadProject(JSON.parse(str)); }, function (err) { alert("Error fetching data.js"); }); return; } var xhr; if (this.isWindowsPhone8) xhr = new ActiveXObject("Microsoft.XMLHTTP"); else xhr = new XMLHttpRequest(); var datajs_filename = "data.js"; if (typeof window['NSG_G_VER'] !== 'undefined') { datajs_filename += '?' + window['NSG_G_VER']; } if (this.isWindows8App || this.isWindowsPhone8 || this.isWindowsPhone81 || this.isWindows10) datajs_filename = "data.json"; xhr.open("GET", datajs_filename, true); var supportsJsonResponse = false; if (!this.isDomFree && ("response" in xhr) && ("responseType" in xhr)) { try { xhr["responseType"] = "json"; supportsJsonResponse = (xhr["responseType"] === "json"); } catch (e) { supportsJsonResponse = false; } } if (!supportsJsonResponse && ("responseType" in xhr)) { try { xhr["responseType"] = "text"; } catch (e) {} } if ("overrideMimeType" in xhr) { try { xhr["overrideMimeType"]("application/json; charset=utf-8"); } catch (e) {} } if (this.isWindowsPhone8) { xhr.onreadystatechange = function () { if (xhr.readyState !== 4) return; self.loadProject(JSON.parse(xhr["responseText"])); }; } else { xhr.onload = function () { if (supportsJsonResponse) { self.loadProject(xhr["response"]); // already parsed by browser } else { if (self.isEjecta) { var str = xhr["responseText"]; str = str.substr(str.indexOf("{")); // trim any BOM self.loadProject(JSON.parse(str)); } else { self.loadProject(JSON.parse(xhr["responseText"])); // forced to sync parse JSON } } }; xhr.onerror = function (e) { cr.logerror("Error requesting " + datajs_filename + ":"); cr.logerror(e); }; } xhr.send(); }; Runtime.prototype.initRendererAndLoader = function () { var self = this; var i, len, j, lenj, k, lenk, t, s, l, y; this.isRetina = ((!this.isDomFree || this.isEjecta || this.isCordova) && this.useHighDpi && !this.isAndroidStockBrowser); if (this.fullscreen_mode === 0 && this.isiOS) this.isRetina = false; this.devicePixelRatio = (this.isRetina ? (window["devicePixelRatio"] || window["webkitDevicePixelRatio"] || window["mozDevicePixelRatio"] || window["msDevicePixelRatio"] || 1) : 1); if (typeof window["StatusBar"] === "object") window["StatusBar"]["hide"](); this.ClearDeathRow(); var attribs; if (this.fullscreen_mode > 0) this["setSize"](window.innerWidth, window.innerHeight, true); this.canvas.addEventListener("webglcontextlost", function (ev) { ev.preventDefault(); self.onContextLost(); cr.logexport("[Construct 2] WebGL context lost"); window["cr_setSuspended"](true); // stop rendering }, false); this.canvas.addEventListener("webglcontextrestored", function (ev) { self.glwrap.initState(); self.glwrap.setSize(self.glwrap.width, self.glwrap.height, true); self.layer_tex = null; self.layout_tex = null; self.fx_tex[0] = null; self.fx_tex[1] = null; self.onContextRestored(); self.redraw = true; cr.logexport("[Construct 2] WebGL context restored"); window["cr_setSuspended"](false); // resume rendering }, false); try { if (this.enableWebGL && (this.isCocoonJs || this.isEjecta || !this.isDomFree)) { attribs = { "alpha": true, "depth": false, "antialias": false, "powerPreference": "high-performance", "failIfMajorPerformanceCaveat": true }; if (!this.isAndroid) this.gl = this.canvas.getContext("webgl2", attribs); if (!this.gl) { this.gl = (this.canvas.getContext("webgl", attribs) || this.canvas.getContext("experimental-webgl", attribs)); } } } catch (e) { } if (this.gl) { var isWebGL2 = (this.gl.getParameter(this.gl.VERSION).indexOf("WebGL 2") === 0); var debug_ext = this.gl.getExtension("WEBGL_debug_renderer_info"); if (debug_ext) { var unmasked_vendor = this.gl.getParameter(debug_ext.UNMASKED_VENDOR_WEBGL); var unmasked_renderer = this.gl.getParameter(debug_ext.UNMASKED_RENDERER_WEBGL); this.glUnmaskedRenderer = unmasked_renderer + " [" + unmasked_vendor + "]"; } if (this.enableFrontToBack) this.glUnmaskedRenderer += " [front-to-back enabled]"; ; if (!this.isDomFree) { this.overlay_canvas = document.createElement("canvas"); jQuery(this.overlay_canvas).appendTo(this.canvas.parentNode); this.overlay_canvas.oncontextmenu = function (e) { return false; }; this.overlay_canvas.onselectstart = function (e) { return false; }; this.overlay_canvas.width = Math.round(this.cssWidth * this.devicePixelRatio); this.overlay_canvas.height = Math.round(this.cssHeight * this.devicePixelRatio); jQuery(this.overlay_canvas).css({"width": this.cssWidth + "px", "height": this.cssHeight + "px"}); this.positionOverlayCanvas(); this.overlay_ctx = this.overlay_canvas.getContext("2d"); } this.glwrap = new cr.GLWrap(this.gl, this.isMobile, this.enableFrontToBack); this.glwrap.setSize(this.canvas.width, this.canvas.height); this.glwrap.enable_mipmaps = (this.downscalingQuality !== 0); this.ctx = null; for (i = 0, len = this.types_by_index.length; i < len; i++) { t = this.types_by_index[i]; for (j = 0, lenj = t.effect_types.length; j < lenj; j++) { s = t.effect_types[j]; s.shaderindex = this.glwrap.getShaderIndex(s.id); s.preservesOpaqueness = this.glwrap.programPreservesOpaqueness(s.shaderindex); this.uses_background_blending = this.uses_background_blending || this.glwrap.programUsesDest(s.shaderindex); } } for (i = 0, len = this.layouts_by_index.length; i < len; i++) { l = this.layouts_by_index[i]; for (j = 0, lenj = l.effect_types.length; j < lenj; j++) { s = l.effect_types[j]; s.shaderindex = this.glwrap.getShaderIndex(s.id); s.preservesOpaqueness = this.glwrap.programPreservesOpaqueness(s.shaderindex); } l.updateActiveEffects(); // update preserves opaqueness flag for (j = 0, lenj = l.layers.length; j < lenj; j++) { y = l.layers[j]; for (k = 0, lenk = y.effect_types.length; k < lenk; k++) { s = y.effect_types[k]; s.shaderindex = this.glwrap.getShaderIndex(s.id); s.preservesOpaqueness = this.glwrap.programPreservesOpaqueness(s.shaderindex); this.uses_background_blending = this.uses_background_blending || this.glwrap.programUsesDest(s.shaderindex); } y.updateActiveEffects(); // update preserves opaqueness flag } } } else { if (this.fullscreen_mode > 0 && this.isDirectCanvas) { ; this.canvas = null; document.oncontextmenu = function (e) { return false; }; document.onselectstart = function (e) { return false; }; this.ctx = AppMobi["canvas"]["getContext"]("2d"); try { this.ctx["samplingMode"] = this.linearSampling ? "smooth" : "sharp"; this.ctx["globalScale"] = 1; this.ctx["HTML5CompatibilityMode"] = true; this.ctx["imageSmoothingEnabled"] = this.linearSampling; } catch(e){} if (this.width !== 0 && this.height !== 0) { this.ctx.width = this.width; this.ctx.height = this.height; } } if (!this.ctx) { ; if (this.isCocoonJs) { attribs = { "antialias": !!this.linearSampling, "alpha": true }; this.ctx = this.canvas.getContext("2d", attribs); } else { attribs = { "alpha": true }; this.ctx = this.canvas.getContext("2d", attribs); } this.setCtxImageSmoothingEnabled(this.ctx, this.linearSampling); } this.overlay_canvas = null; this.overlay_ctx = null; } this.tickFunc = function (timestamp) { self.tick(false, timestamp); }; if (window != window.top && !this.isDomFree && !this.isWinJS && !this.isWindowsPhone8) { document.addEventListener("mousedown", function () { window.focus(); }, true); document.addEventListener("touchstart", function () { window.focus(); }, true); } if (typeof cr_is_preview !== "undefined") { if (this.isCocoonJs) console.log("[Construct 2] In preview-over-wifi via CocoonJS mode"); if (window.location.search.indexOf("continuous") > -1) { cr.logexport("Reloading for continuous preview"); this.loadFromSlot = "__c2_continuouspreview"; this.suspendDrawing = true; } if (this.pauseOnBlur && !this.isMobile) { jQuery(window).focus(function () { self["setSuspended"](false); }); jQuery(window).blur(function () { var parent = window.parent; if (!parent || !parent.document.hasFocus()) self["setSuspended"](true); }); } } window.addEventListener("blur", function () { self.onWindowBlur(); }); if (!this.isDomFree) { var unfocusFormControlFunc = function (e) { if (cr.isCanvasInputEvent(e) && document["activeElement"] && document["activeElement"] !== document.getElementsByTagName("body")[0] && document["activeElement"].blur) { try { document["activeElement"].blur(); } catch (e) {} } } if (typeof PointerEvent !== "undefined") { document.addEventListener("pointerdown", unfocusFormControlFunc); } else if (window.navigator["msPointerEnabled"]) { document.addEventListener("MSPointerDown", unfocusFormControlFunc); } else { document.addEventListener("touchstart", unfocusFormControlFunc); } document.addEventListener("mousedown", unfocusFormControlFunc); } if (this.fullscreen_mode === 0 && this.isRetina && this.devicePixelRatio > 1) { this["setSize"](this.original_width, this.original_height, true); } this.tryLockOrientation(); this.getready(); // determine things to preload this.go(); // run loading screen this.extra = {}; cr.seal(this); }; var webkitRepaintFlag = false; Runtime.prototype["setSize"] = function (w, h, force) { var offx = 0, offy = 0; var neww = 0, newh = 0, intscale = 0; if (this.lastWindowWidth === w && this.lastWindowHeight === h && !force) return; this.lastWindowWidth = w; this.lastWindowHeight = h; var mode = this.fullscreen_mode; var orig_aspect, cur_aspect; var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || !!document["msFullscreenElement"] || document["fullScreen"] || this.isNodeFullscreen) && !this.isCordova; if (!isfullscreen && this.fullscreen_mode === 0 && !force) return; // ignore size events when not fullscreen and not using a fullscreen-in-browser mode if (isfullscreen) mode = this.fullscreen_scaling; var dpr = this.devicePixelRatio; if (mode >= 4) { if (mode === 5 && dpr !== 1) // integer scaling { w += 1; h += 1; } orig_aspect = this.original_width / this.original_height; cur_aspect = w / h; if (cur_aspect > orig_aspect) { neww = h * orig_aspect; if (mode === 5) // integer scaling { intscale = (neww * dpr) / this.original_width; if (intscale > 1) intscale = Math.floor(intscale); else if (intscale < 1) intscale = 1 / Math.ceil(1 / intscale); neww = this.original_width * intscale / dpr; newh = this.original_height * intscale / dpr; offx = (w - neww) / 2; offy = (h - newh) / 2; w = neww; h = newh; } else { offx = (w - neww) / 2; w = neww; } } else { newh = w / orig_aspect; if (mode === 5) // integer scaling { intscale = (newh * dpr) / this.original_height; if (intscale > 1) intscale = Math.floor(intscale); else if (intscale < 1) intscale = 1 / Math.ceil(1 / intscale); neww = this.original_width * intscale / dpr; newh = this.original_height * intscale / dpr; offx = (w - neww) / 2; offy = (h - newh) / 2; w = neww; h = newh; } else { offy = (h - newh) / 2; h = newh; } } } else if (isfullscreen && mode === 0) { offx = Math.floor((w - this.original_width) / 2); offy = Math.floor((h - this.original_height) / 2); w = this.original_width; h = this.original_height; } if (mode < 2) this.aspect_scale = dpr; this.cssWidth = Math.round(w); this.cssHeight = Math.round(h); this.width = Math.round(w * dpr); this.height = Math.round(h * dpr); this.redraw = true; if (this.wantFullscreenScalingQuality) { this.draw_width = this.width; this.draw_height = this.height; this.fullscreenScalingQuality = true; } else { if ((this.width < this.original_width && this.height < this.original_height) || mode === 1) { this.draw_width = this.width; this.draw_height = this.height; this.fullscreenScalingQuality = true; } else { this.draw_width = this.original_width; this.draw_height = this.original_height; this.fullscreenScalingQuality = false; /*var orig_aspect = this.original_width / this.original_height; var cur_aspect = this.width / this.height; if ((this.fullscreen_mode !== 2 && cur_aspect > orig_aspect) || (this.fullscreen_mode === 2 && cur_aspect < orig_aspect)) this.aspect_scale = this.height / this.original_height; else this.aspect_scale = this.width / this.original_width;*/ if (mode === 2) // scale inner { orig_aspect = this.original_width / this.original_height; cur_aspect = this.lastWindowWidth / this.lastWindowHeight; if (cur_aspect < orig_aspect) this.draw_width = this.draw_height * cur_aspect; else if (cur_aspect > orig_aspect) this.draw_height = this.draw_width / cur_aspect; } else if (mode === 3) { orig_aspect = this.original_width / this.original_height; cur_aspect = this.lastWindowWidth / this.lastWindowHeight; if (cur_aspect > orig_aspect) this.draw_width = this.draw_height * cur_aspect; else if (cur_aspect < orig_aspect) this.draw_height = this.draw_width / cur_aspect; } } } if (this.canvasdiv && !this.isDomFree) { jQuery(this.canvasdiv).css({"width": Math.round(w) + "px", "height": Math.round(h) + "px", "margin-left": Math.floor(offx) + "px", "margin-top": Math.floor(offy) + "px"}); if (typeof cr_is_preview !== "undefined") { jQuery("#borderwrap").css({"width": Math.round(w) + "px", "height": Math.round(h) + "px"}); } } if (this.canvas) { this.canvas.width = Math.round(w * dpr); this.canvas.height = Math.round(h * dpr); if (this.isEjecta) { this.canvas.style.left = Math.floor(offx) + "px"; this.canvas.style.top = Math.floor(offy) + "px"; this.canvas.style.width = Math.round(w) + "px"; this.canvas.style.height = Math.round(h) + "px"; } else if (this.isRetina && !this.isDomFree) { this.canvas.style.width = Math.round(w) + "px"; this.canvas.style.height = Math.round(h) + "px"; } } if (this.overlay_canvas) { this.overlay_canvas.width = Math.round(w * dpr); this.overlay_canvas.height = Math.round(h * dpr); this.overlay_canvas.style.width = this.cssWidth + "px"; this.overlay_canvas.style.height = this.cssHeight + "px"; } if (this.glwrap) { this.glwrap.setSize(Math.round(w * dpr), Math.round(h * dpr)); } if (this.isDirectCanvas && this.ctx) { this.ctx.width = Math.round(w); this.ctx.height = Math.round(h); } if (this.ctx) { this.setCtxImageSmoothingEnabled(this.ctx, this.linearSampling); } this.tryLockOrientation(); if (this.isiPhone && !this.isCordova) { window.scrollTo(0, 0); } }; Runtime.prototype.tryLockOrientation = function () { if (!this.autoLockOrientation || this.orientations === 0) return; var orientation = "portrait"; if (this.orientations === 2) orientation = "landscape"; try { if (screen["orientation"] && screen["orientation"]["lock"]) screen["orientation"]["lock"](orientation).catch(function(){}); else if (screen["lockOrientation"]) screen["lockOrientation"](orientation); else if (screen["webkitLockOrientation"]) screen["webkitLockOrientation"](orientation); else if (screen["mozLockOrientation"]) screen["mozLockOrientation"](orientation); else if (screen["msLockOrientation"]) screen["msLockOrientation"](orientation); } catch (e) { if (console && console.warn) console.warn("Failed to lock orientation: ", e); } }; Runtime.prototype.onContextLost = function () { this.glwrap.contextLost(); this.is_WebGL_context_lost = true; var i, len, t; for (i = 0, len = this.types_by_index.length; i < len; i++) { t = this.types_by_index[i]; if (t.onLostWebGLContext) t.onLostWebGLContext(); } }; Runtime.prototype.onContextRestored = function () { this.is_WebGL_context_lost = false; var i, len, t; for (i = 0, len = this.types_by_index.length; i < len; i++) { t = this.types_by_index[i]; if (t.onRestoreWebGLContext) t.onRestoreWebGLContext(); } }; Runtime.prototype.positionOverlayCanvas = function() { if (this.isDomFree) return; var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || document["fullScreen"] || !!document["msFullscreenElement"] || this.isNodeFullscreen) && !this.isCordova; var overlay_position = isfullscreen ? jQuery(this.canvas).offset() : jQuery(this.canvas).position(); overlay_position.position = "absolute"; jQuery(this.overlay_canvas).css(overlay_position); }; var caf = window["cancelAnimationFrame"] || window["mozCancelAnimationFrame"] || window["webkitCancelAnimationFrame"] || window["msCancelAnimationFrame"] || window["oCancelAnimationFrame"]; Runtime.prototype["setSuspended"] = function (s) { var i, len; var self = this; if (s && !this.isSuspended) { cr.logexport("[Construct 2] Suspending"); this.isSuspended = true; // next tick will be last if (this.raf_id !== -1 && caf) // note: CocoonJS does not implement cancelAnimationFrame caf(this.raf_id); if (this.timeout_id !== -1) clearTimeout(this.timeout_id); for (i = 0, len = this.suspend_events.length; i < len; i++) this.suspend_events[i](true); } else if (!s && this.isSuspended) { cr.logexport("[Construct 2] Resuming"); this.isSuspended = false; this.last_tick_time = cr.performance_now(); // ensure first tick is a zero-dt one this.last_fps_time = cr.performance_now(); // reset FPS counter this.framecount = 0; this.logictime = 0; for (i = 0, len = this.suspend_events.length; i < len; i++) this.suspend_events[i](false); this.tick(false); // kick off runtime again } }; Runtime.prototype.addSuspendCallback = function (f) { this.suspend_events.push(f); }; Runtime.prototype.GetObjectReference = function (i) { ; return this.objectRefTable[i]; }; Runtime.prototype.loadProject = function (data_response) { ; if (!data_response || !data_response["project"]) cr.logerror("Project model unavailable"); var pm = data_response["project"]; this.name = pm[0]; this.first_layout = pm[1]; this.fullscreen_mode = pm[12]; // 0 = off, 1 = crop, 2 = scale inner, 3 = scale outer, 4 = letterbox scale, 5 = integer letterbox scale this.fullscreen_mode_set = pm[12]; this.original_width = pm[10]; this.original_height = pm[11]; this.parallax_x_origin = this.original_width / 2; this.parallax_y_origin = this.original_height / 2; if (this.isDomFree && !this.isEjecta && (pm[12] >= 4 || pm[12] === 0)) { cr.logexport("[Construct 2] Letterbox scale fullscreen modes are not supported on this platform - falling back to 'Scale outer'"); this.fullscreen_mode = 3; this.fullscreen_mode_set = 3; } this.uses_loader_layout = pm[18]; this.loaderstyle = pm[19]; if (this.loaderstyle === 0) { var loaderImage = new Image(); loaderImage.crossOrigin = "anonymous"; this.setImageSrc(loaderImage, "loading-logo.png"); this.loaderlogos = { logo: loaderImage }; } else if (this.loaderstyle === 4) // c2 splash { var loaderC2logo_1024 = new Image(); loaderC2logo_1024.src = ""; var loaderC2logo_512 = new Image(); loaderC2logo_512.src = ""; var loaderC2logo_256 = new Image(); loaderC2logo_256.src = ""; var loaderC2logo_128 = new Image(); loaderC2logo_128.src = ""; var loaderPowered_1024 = new Image(); loaderPowered_1024.src = ""; var loaderPowered_512 = new Image(); loaderPowered_512.src = ""; var loaderPowered_256 = new Image(); loaderPowered_256.src = ""; var loaderPowered_128 = new Image(); loaderPowered_128.src = ""; var loaderWebsite_1024 = new Image(); loaderWebsite_1024.src = ""; var loaderWebsite_512 = new Image(); loaderWebsite_512.src = ""; var loaderWebsite_256 = new Image(); loaderWebsite_256.src = ""; var loaderWebsite_128 = new Image(); loaderWebsite_128.src = ""; this.loaderlogos = { logo: [loaderC2logo_1024, loaderC2logo_512, loaderC2logo_256, loaderC2logo_128], powered: [loaderPowered_1024, loaderPowered_512, loaderPowered_256, loaderPowered_128], website: [loaderWebsite_1024, loaderWebsite_512, loaderWebsite_256, loaderWebsite_128] }; } this.next_uid = pm[21]; this.objectRefTable = cr.getObjectRefTable(); this.system = new cr.system_object(this); var i, len, j, lenj, k, lenk, idstr, m, b, t, f, p; var plugin, plugin_ctor; for (i = 0, len = pm[2].length; i < len; i++) { m = pm[2][i]; p = this.GetObjectReference(m[0]); ; cr.add_common_aces(m, p.prototype); plugin = new p(this); plugin.singleglobal = m[1]; plugin.is_world = m[2]; plugin.is_rotatable = m[5]; plugin.must_predraw = m[9]; if (plugin.onCreate) plugin.onCreate(); // opportunity to override default ACEs cr.seal(plugin); this.plugins.push(plugin); } this.objectRefTable = cr.getObjectRefTable(); for (i = 0, len = pm[3].length; i < len; i++) { m = pm[3][i]; plugin_ctor = this.GetObjectReference(m[1]); ; plugin = null; for (j = 0, lenj = this.plugins.length; j < lenj; j++) { if (this.plugins[j] instanceof plugin_ctor) { plugin = this.plugins[j]; break; } } ; ; var type_inst = new plugin.Type(plugin); ; type_inst.name = m[0]; type_inst.is_family = m[2]; type_inst.instvar_sids = m[3].slice(0); type_inst.vars_count = m[3].length; type_inst.behs_count = m[4]; type_inst.fx_count = m[5]; type_inst.sid = m[11]; if (type_inst.is_family) { type_inst.members = []; // types in this family type_inst.family_index = this.family_count++; type_inst.families = null; } else { type_inst.members = null; type_inst.family_index = -1; type_inst.families = []; // families this type belongs to } type_inst.family_var_map = null; type_inst.family_beh_map = null; type_inst.family_fx_map = null; type_inst.is_contained = false; type_inst.container = null; if (m[6]) { type_inst.texture_file = m[6][0]; type_inst.texture_filesize = m[6][1]; type_inst.texture_pixelformat = m[6][2]; } else { type_inst.texture_file = null; type_inst.texture_filesize = 0; type_inst.texture_pixelformat = 0; // rgba8 } if (m[7]) { type_inst.animations = m[7]; } else { type_inst.animations = null; } type_inst.index = i; // save index in to types array in type type_inst.instances = []; // all instances of this type type_inst.deadCache = []; // destroyed instances to recycle next create type_inst.solstack = [new cr.selection(type_inst)]; // initialise SOL stack with one empty SOL type_inst.cur_sol = 0; type_inst.default_instance = null; type_inst.default_layerindex = 0; type_inst.stale_iids = true; type_inst.updateIIDs = cr.type_updateIIDs; type_inst.getFirstPicked = cr.type_getFirstPicked; type_inst.getPairedInstance = cr.type_getPairedInstance; type_inst.getCurrentSol = cr.type_getCurrentSol; type_inst.pushCleanSol = cr.type_pushCleanSol; type_inst.pushCopySol = cr.type_pushCopySol; type_inst.popSol = cr.type_popSol; type_inst.getBehaviorByName = cr.type_getBehaviorByName; type_inst.getBehaviorIndexByName = cr.type_getBehaviorIndexByName; type_inst.getEffectIndexByName = cr.type_getEffectIndexByName; type_inst.applySolToContainer = cr.type_applySolToContainer; type_inst.getInstanceByIID = cr.type_getInstanceByIID; type_inst.collision_grid = new cr.SparseGrid(this.original_width, this.original_height); type_inst.any_cell_changed = true; type_inst.any_instance_parallaxed = false; type_inst.extra = {}; type_inst.toString = cr.type_toString; type_inst.behaviors = []; for (j = 0, lenj = m[8].length; j < lenj; j++) { b = m[8][j]; var behavior_ctor = this.GetObjectReference(b[1]); var behavior_plugin = null; for (k = 0, lenk = this.behaviors.length; k < lenk; k++) { if (this.behaviors[k] instanceof behavior_ctor) { behavior_plugin = this.behaviors[k]; break; } } if (!behavior_plugin) { behavior_plugin = new behavior_ctor(this); behavior_plugin.my_types = []; // types using this behavior behavior_plugin.my_instances = new cr.ObjectSet(); // instances of this behavior if (behavior_plugin.onCreate) behavior_plugin.onCreate(); cr.seal(behavior_plugin); this.behaviors.push(behavior_plugin); if (cr.behaviors.solid && behavior_plugin instanceof cr.behaviors.solid) this.solidBehavior = behavior_plugin; if (cr.behaviors.jumpthru && behavior_plugin instanceof cr.behaviors.jumpthru) this.jumpthruBehavior = behavior_plugin; if (cr.behaviors.shadowcaster && behavior_plugin instanceof cr.behaviors.shadowcaster) this.shadowcasterBehavior = behavior_plugin; } if (behavior_plugin.my_types.indexOf(type_inst) === -1) behavior_plugin.my_types.push(type_inst); var behavior_type = new behavior_plugin.Type(behavior_plugin, type_inst); behavior_type.name = b[0]; behavior_type.sid = b[2]; behavior_type.onCreate(); cr.seal(behavior_type); type_inst.behaviors.push(behavior_type); } type_inst.global = m[9]; type_inst.isOnLoaderLayout = m[10]; type_inst.effect_types = []; for (j = 0, lenj = m[12].length; j < lenj; j++) { type_inst.effect_types.push({ id: m[12][j][0], name: m[12][j][1], shaderindex: -1, preservesOpaqueness: false, active: true, index: j }); } type_inst.tile_poly_data = m[13]; if (!this.uses_loader_layout || type_inst.is_family || type_inst.isOnLoaderLayout || !plugin.is_world) { type_inst.onCreate(); cr.seal(type_inst); } if (type_inst.name) this.types[type_inst.name] = type_inst; this.types_by_index.push(type_inst); if (plugin.singleglobal) { var instance = new plugin.Instance(type_inst); instance.uid = this.next_uid++; instance.puid = this.next_puid++; instance.iid = 0; instance.get_iid = cr.inst_get_iid; instance.toString = cr.inst_toString; instance.properties = m[14]; instance.onCreate(); cr.seal(instance); type_inst.instances.push(instance); this.objectsByUid[instance.uid.toString()] = instance; } } for (i = 0, len = pm[4].length; i < len; i++) { var familydata = pm[4][i]; var familytype = this.types_by_index[familydata[0]]; var familymember; for (j = 1, lenj = familydata.length; j < lenj; j++) { familymember = this.types_by_index[familydata[j]]; familymember.families.push(familytype); familytype.members.push(familymember); } } for (i = 0, len = pm[28].length; i < len; i++) { var containerdata = pm[28][i]; var containertypes = []; for (j = 0, lenj = containerdata.length; j < lenj; j++) containertypes.push(this.types_by_index[containerdata[j]]); for (j = 0, lenj = containertypes.length; j < lenj; j++) { containertypes[j].is_contained = true; containertypes[j].container = containertypes; } } if (this.family_count > 0) { for (i = 0, len = this.types_by_index.length; i < len; i++) { t = this.types_by_index[i]; if (t.is_family || !t.families.length) continue; t.family_var_map = new Array(this.family_count); t.family_beh_map = new Array(this.family_count); t.family_fx_map = new Array(this.family_count); var all_fx = []; var varsum = 0; var behsum = 0; var fxsum = 0; for (j = 0, lenj = t.families.length; j < lenj; j++) { f = t.families[j]; t.family_var_map[f.family_index] = varsum; varsum += f.vars_count; t.family_beh_map[f.family_index] = behsum; behsum += f.behs_count; t.family_fx_map[f.family_index] = fxsum; fxsum += f.fx_count; for (k = 0, lenk = f.effect_types.length; k < lenk; k++) all_fx.push(cr.shallowCopy({}, f.effect_types[k])); } t.effect_types = all_fx.concat(t.effect_types); for (j = 0, lenj = t.effect_types.length; j < lenj; j++) t.effect_types[j].index = j; } } for (i = 0, len = pm[5].length; i < len; i++) { m = pm[5][i]; var layout = new cr.layout(this, m); cr.seal(layout); this.layouts[layout.name] = layout; this.layouts_by_index.push(layout); } for (i = 0, len = pm[6].length; i < len; i++) { m = pm[6][i]; var sheet = new cr.eventsheet(this, m); cr.seal(sheet); this.eventsheets[sheet.name] = sheet; this.eventsheets_by_index.push(sheet); } for (i = 0, len = this.eventsheets_by_index.length; i < len; i++) this.eventsheets_by_index[i].postInit(); for (i = 0, len = this.eventsheets_by_index.length; i < len; i++) this.eventsheets_by_index[i].updateDeepIncludes(); for (i = 0, len = this.triggers_to_postinit.length; i < len; i++) this.triggers_to_postinit[i].postInit(); cr.clearArray(this.triggers_to_postinit) this.audio_to_preload = pm[7]; this.files_subfolder = pm[8]; this.pixel_rounding = pm[9]; this.aspect_scale = 1.0; this.enableWebGL = pm[13]; this.linearSampling = pm[14]; this.clearBackground = pm[15]; this.versionstr = pm[16]; this.useHighDpi = pm[17]; this.orientations = pm[20]; // 0 = any, 1 = portrait, 2 = landscape this.autoLockOrientation = (this.orientations > 0); this.pauseOnBlur = pm[22]; this.wantFullscreenScalingQuality = pm[23]; // false = low quality, true = high quality this.fullscreenScalingQuality = this.wantFullscreenScalingQuality; this.downscalingQuality = pm[24]; // 0 = low (mips off), 1 = medium (mips on, dense spritesheet), 2 = high (mips on, sparse spritesheet) this.preloadSounds = pm[25]; // 0 = no, 1 = yes this.projectName = pm[26]; this.enableFrontToBack = pm[27] && !this.isIE; // front-to-back renderer disabled in IE (but not Edge) this.start_time = Date.now(); cr.clearArray(this.objectRefTable); this.initRendererAndLoader(); }; var anyImageHadError = false; var MAX_PARALLEL_IMAGE_LOADS = 100; var currentlyActiveImageLoads = 0; var imageLoadQueue = []; // array of [img, srcToSet] Runtime.prototype.queueImageLoad = function (img_, src_) { var self = this; var doneFunc = function () { currentlyActiveImageLoads--; self.maybeLoadNextImages(); }; img_.addEventListener("load", doneFunc); img_.addEventListener("error", doneFunc); if (typeof window['NSG_G_VER'] !== 'undefined') { src_ += '?' + window['NSG_G_VER']; } imageLoadQueue.push([img_, src_]); this.maybeLoadNextImages(); }; Runtime.prototype.maybeLoadNextImages = function () { var next; while (imageLoadQueue.length && currentlyActiveImageLoads < MAX_PARALLEL_IMAGE_LOADS) { currentlyActiveImageLoads++; next = imageLoadQueue.shift(); this.setImageSrc(next[0], next[1]); } }; Runtime.prototype.waitForImageLoad = function (img_, src_) { img_["cocoonLazyLoad"] = true; img_.onerror = function (e) { img_.c2error = true; anyImageHadError = true; if (console && console.error) console.error("Error loading image '" + img_.src + "': ", e); }; if (this.isEjecta) { img_.src = src_; } else if (!img_.src) { if (typeof XAPKReader !== "undefined") { XAPKReader.get(src_, function (expanded_url) { img_.src = expanded_url; }, function (e) { img_.c2error = true; anyImageHadError = true; if (console && console.error) console.error("Error extracting image '" + src_ + "' from expansion file: ", e); }); } else { img_.crossOrigin = "anonymous"; // required for Arcade sandbox compatibility this.queueImageLoad(img_, src_); // use a queue to avoid requesting all images simultaneously } } this.wait_for_textures.push(img_); }; Runtime.prototype.findWaitingTexture = function (src_) { var i, len; for (i = 0, len = this.wait_for_textures.length; i < len; i++) { if (this.wait_for_textures[i].cr_src === src_) return this.wait_for_textures[i]; } return null; }; var audio_preload_totalsize = 0; var audio_preload_started = false; Runtime.prototype.getready = function () { if (!this.audioInstance) return; audio_preload_totalsize = this.audioInstance.setPreloadList(this.audio_to_preload); }; Runtime.prototype.areAllTexturesAndSoundsLoaded = function () { var totalsize = audio_preload_totalsize; var completedsize = 0; var audiocompletedsize = 0; var ret = true; var i, len, img; for (i = 0, len = this.wait_for_textures.length; i < len; i++) { img = this.wait_for_textures[i]; var filesize = img.cr_filesize; if (!filesize || filesize <= 0) filesize = 50000; totalsize += filesize; if (!!img.src && (img.complete || img["loaded"]) && !img.c2error) completedsize += filesize; else ret = false; // not all textures loaded } if (ret && this.preloadSounds && this.audioInstance) { if (!audio_preload_started) { this.audioInstance.startPreloads(); audio_preload_started = true; } audiocompletedsize = this.audioInstance.getPreloadedSize(); completedsize += audiocompletedsize; if (audiocompletedsize < audio_preload_totalsize) ret = false; // not done yet } if (totalsize == 0) this.progress = 1; // indicate to C2 splash loader that it can finish now else this.progress = (completedsize / totalsize); return ret; }; var isC2SplashDone = false; Runtime.prototype.go = function () { if (!this.ctx && !this.glwrap) return; var ctx = this.ctx || this.overlay_ctx; if (this.overlay_canvas) this.positionOverlayCanvas(); var curwidth = window.innerWidth; var curheight = window.innerHeight; if (this.lastWindowWidth !== curwidth || this.lastWindowHeight !== curheight) { this["setSize"](curwidth, curheight); } this.progress = 0; this.last_progress = -1; var self = this; if (this.areAllTexturesAndSoundsLoaded() && (this.loaderstyle !== 4 || isC2SplashDone)) { this.go_loading_finished(); } else { var ms_elapsed = Date.now() - this.start_time; if (ctx) { var overlay_width = this.width; var overlay_height = this.height; var dpr = this.devicePixelRatio; if (this.loaderstyle < 3 && (this.isCocoonJs || (ms_elapsed >= 500 && this.last_progress != this.progress))) { ctx.clearRect(0, 0, overlay_width, overlay_height); var mx = overlay_width / 2; var my = overlay_height / 2; var haslogo = (this.loaderstyle === 0 && this.loaderlogos.logo.complete); var hlw = 40 * dpr; var hlh = 0; var logowidth = 80 * dpr; var logoheight; if (haslogo) { var loaderLogoImage = this.loaderlogos.logo; logowidth = loaderLogoImage.width * dpr; logoheight = loaderLogoImage.height * dpr; hlw = logowidth / 2; hlh = logoheight / 2; ctx.drawImage(loaderLogoImage, cr.floor(mx - hlw), cr.floor(my - hlh), logowidth, logoheight); } if (this.loaderstyle <= 1) { my += hlh + (haslogo ? 12 * dpr : 0); mx -= hlw; mx = cr.floor(mx) + 0.5; my = cr.floor(my) + 0.5; ctx.fillStyle = anyImageHadError ? "red" : "DodgerBlue"; ctx.fillRect(mx, my, Math.floor(logowidth * this.progress), 6 * dpr); ctx.strokeStyle = "black"; ctx.strokeRect(mx, my, logowidth, 6 * dpr); ctx.strokeStyle = "white"; ctx.strokeRect(mx - 1 * dpr, my - 1 * dpr, logowidth + 2 * dpr, 8 * dpr); } else if (this.loaderstyle === 2) { ctx.font = (this.isEjecta ? "12pt ArialMT" : "12pt Arial"); ctx.fillStyle = anyImageHadError ? "#f00" : "#999"; ctx.textBaseLine = "middle"; var percent_text = Math.round(this.progress * 100) + "%"; var text_dim = ctx.measureText ? ctx.measureText(percent_text) : null; var text_width = text_dim ? text_dim.width : 0; ctx.fillText(percent_text, mx - (text_width / 2), my); } this.last_progress = this.progress; } else if (this.loaderstyle === 4) { this.draw_c2_splash_loader(ctx); if (raf) raf(function() { self.go(); }); else setTimeout(function() { self.go(); }, 16); return; } } setTimeout(function() { self.go(); }, (this.isCocoonJs ? 10 : 100)); } }; var splashStartTime = -1; var splashFadeInDuration = 300; var splashFadeOutDuration = 300; var splashAfterFadeOutWait = (typeof cr_is_preview === "undefined" ? 200 : 0); var splashIsFadeIn = true; var splashIsFadeOut = false; var splashFadeInFinish = 0; var splashFadeOutStart = 0; var splashMinDisplayTime = (typeof cr_is_preview === "undefined" ? 3000 : 0); var renderViaCanvas = null; var renderViaCtx = null; var splashFrameNumber = 0; function maybeCreateRenderViaCanvas(w, h) { if (!renderViaCanvas || renderViaCanvas.width !== w || renderViaCanvas.height !== h) { renderViaCanvas = document.createElement("canvas"); renderViaCanvas.width = w; renderViaCanvas.height = h; renderViaCtx = renderViaCanvas.getContext("2d"); } }; function mipImage(arr, size) { if (size <= 128) return arr[3]; else if (size <= 256) return arr[2]; else if (size <= 512) return arr[1]; else return arr[0]; }; Runtime.prototype.draw_c2_splash_loader = function(ctx) { if (isC2SplashDone) return; var w = Math.ceil(this.width); var h = Math.ceil(this.height); var dpr = this.devicePixelRatio; var logoimages = this.loaderlogos.logo; var poweredimages = this.loaderlogos.powered; var websiteimages = this.loaderlogos.website; for (var i = 0; i < 4; ++i) { if (!logoimages[i].complete || !poweredimages[i].complete || !websiteimages[i].complete) return; } if (splashFrameNumber === 0) splashStartTime = Date.now(); var nowTime = Date.now(); var isRenderingVia = false; var renderToCtx = ctx; var drawW, drawH; if (splashIsFadeIn || splashIsFadeOut) { ctx.clearRect(0, 0, w, h); maybeCreateRenderViaCanvas(w, h); renderToCtx = renderViaCtx; isRenderingVia = true; if (splashIsFadeIn && splashFrameNumber === 1) splashStartTime = Date.now(); } else { ctx.globalAlpha = 1; } renderToCtx.fillStyle = "#333333"; renderToCtx.fillRect(0, 0, w, h); if (this.cssHeight > 256) { drawW = cr.clamp(h * 0.22, 105, w * 0.6); drawH = drawW * 0.25; renderToCtx.drawImage(mipImage(poweredimages, drawW), w * 0.5 - drawW/2, h * 0.2 - drawH/2, drawW, drawH); drawW = Math.min(h * 0.395, w * 0.95); drawH = drawW; renderToCtx.drawImage(mipImage(logoimages, drawW), w * 0.5 - drawW/2, h * 0.485 - drawH/2, drawW, drawH); drawW = cr.clamp(h * 0.22, 105, w * 0.6); drawH = drawW * 0.25; renderToCtx.drawImage(mipImage(websiteimages, drawW), w * 0.5 - drawW/2, h * 0.868 - drawH/2, drawW, drawH); renderToCtx.fillStyle = "#3C3C3C"; drawW = w; drawH = Math.max(h * 0.005, 2); renderToCtx.fillRect(0, h * 0.8 - drawH/2, drawW, drawH); renderToCtx.fillStyle = anyImageHadError ? "red" : "#E0FF65"; drawW = w * this.progress; renderToCtx.fillRect(w * 0.5 - drawW/2, h * 0.8 - drawH/2, drawW, drawH); } else { drawW = h * 0.55; drawH = drawW; renderToCtx.drawImage(mipImage(logoimages, drawW), w * 0.5 - drawW/2, h * 0.45 - drawH/2, drawW, drawH); renderToCtx.fillStyle = "#3C3C3C"; drawW = w; drawH = Math.max(h * 0.005, 2); renderToCtx.fillRect(0, h * 0.85 - drawH/2, drawW, drawH); renderToCtx.fillStyle = anyImageHadError ? "red" : "#E0FF65"; drawW = w * this.progress; renderToCtx.fillRect(w * 0.5 - drawW/2, h * 0.85 - drawH/2, drawW, drawH); } if (isRenderingVia) { if (splashIsFadeIn) { if (splashFrameNumber === 0) ctx.globalAlpha = 0; else ctx.globalAlpha = Math.min((nowTime - splashStartTime) / splashFadeInDuration, 1); } else if (splashIsFadeOut) { ctx.globalAlpha = Math.max(1 - (nowTime - splashFadeOutStart) / splashFadeOutDuration, 0); } ctx.drawImage(renderViaCanvas, 0, 0, w, h); } if (splashIsFadeIn && nowTime - splashStartTime >= splashFadeInDuration && splashFrameNumber >= 2) { splashIsFadeIn = false; splashFadeInFinish = nowTime; } if (!splashIsFadeIn && nowTime - splashFadeInFinish >= splashMinDisplayTime && !splashIsFadeOut && this.progress >= 1) { splashIsFadeOut = true; splashFadeOutStart = nowTime; } if ((splashIsFadeOut && nowTime - splashFadeOutStart >= splashFadeOutDuration + splashAfterFadeOutWait) || (typeof cr_is_preview !== "undefined" && this.progress >= 1 && Date.now() - splashStartTime < 500)) { isC2SplashDone = true; splashIsFadeIn = false; splashIsFadeOut = false; renderViaCanvas = null; renderViaCtx = null; this.loaderlogos = null; } ++splashFrameNumber; }; Runtime.prototype.go_loading_finished = function () { if (this.overlay_canvas) { this.canvas.parentNode.removeChild(this.overlay_canvas); this.overlay_ctx = null; this.overlay_canvas = null; } this.start_time = Date.now(); this.last_fps_time = cr.performance_now(); // for counting framerate var i, len, t; if (this.uses_loader_layout) { for (i = 0, len = this.types_by_index.length; i < len; i++) { t = this.types_by_index[i]; if (!t.is_family && !t.isOnLoaderLayout && t.plugin.is_world) { t.onCreate(); cr.seal(t); } } } else this.isloading = false; for (i = 0, len = this.layouts_by_index.length; i < len; i++) { this.layouts_by_index[i].createGlobalNonWorlds(); } if (this.fullscreen_mode >= 2) { var orig_aspect = this.original_width / this.original_height; var cur_aspect = this.width / this.height; if ((this.fullscreen_mode !== 2 && cur_aspect > orig_aspect) || (this.fullscreen_mode === 2 && cur_aspect < orig_aspect)) this.aspect_scale = this.height / this.original_height; else this.aspect_scale = this.width / this.original_width; } if (this.first_layout) this.layouts[this.first_layout].startRunning(); else this.layouts_by_index[0].startRunning(); ; if (!this.uses_loader_layout) { this.loadingprogress = 1; this.trigger(cr.system_object.prototype.cnds.OnLoadFinished, null); if (window["C2_RegisterSW"]) // note not all platforms use SW window["C2_RegisterSW"](); } if (navigator["splashscreen"] && navigator["splashscreen"]["hide"]) navigator["splashscreen"]["hide"](); for (i = 0, len = this.types_by_index.length; i < len; i++) { t = this.types_by_index[i]; if (t.onAppBegin) t.onAppBegin(); } if (document["hidden"] || document["webkitHidden"] || document["mozHidden"] || document["msHidden"]) { window["cr_setSuspended"](true); // stop rendering } else { this.tick(false); } if (this.isDirectCanvas) AppMobi["webview"]["execute"]("onGameReady();"); }; Runtime.prototype.tick = function (background_wake, timestamp, debug_step) { if (!this.running_layout) return; var nowtime = cr.performance_now(); var logic_start = nowtime; if (!debug_step && this.isSuspended && !background_wake) return; if (!background_wake) { if (raf) this.raf_id = raf(this.tickFunc); else { this.timeout_id = setTimeout(this.tickFunc, this.isMobile ? 1 : 16); } } var raf_time = timestamp || nowtime; var fsmode = this.fullscreen_mode; var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || document["fullScreen"] || !!document["msFullscreenElement"]) && !this.isCordova; if ((isfullscreen || this.isNodeFullscreen) && this.fullscreen_scaling > 0) fsmode = this.fullscreen_scaling; if (fsmode > 0) // r222: experimentally enabling this workaround for all platforms { var curwidth = window.innerWidth; var curheight = window.innerHeight; if (this.lastWindowWidth !== curwidth || this.lastWindowHeight !== curheight) { this["setSize"](curwidth, curheight); } } if (!this.isDomFree) { if (isfullscreen) { if (!this.firstInFullscreen) this.firstInFullscreen = true; } else { if (this.firstInFullscreen) { this.firstInFullscreen = false; if (this.fullscreen_mode === 0) { this["setSize"](Math.round(this.oldWidth / this.devicePixelRatio), Math.round(this.oldHeight / this.devicePixelRatio), true); } } else { this.oldWidth = this.width; this.oldHeight = this.height; } } } if (this.isloading) { var done = this.areAllTexturesAndSoundsLoaded(); // updates this.progress this.loadingprogress = this.progress; if (done) { this.isloading = false; this.progress = 1; this.trigger(cr.system_object.prototype.cnds.OnLoadFinished, null); if (window["C2_RegisterSW"]) window["C2_RegisterSW"](); } } this.logic(raf_time); if ((this.redraw || this.isCocoonJs) && !this.is_WebGL_context_lost && !this.suspendDrawing && !background_wake) { this.redraw = false; if (this.glwrap) this.drawGL(); else this.draw(); if (this.snapshotCanvas) { if (this.canvas && this.canvas.toDataURL) { this.snapshotData = this.canvas.toDataURL(this.snapshotCanvas[0], this.snapshotCanvas[1]); if (window["cr_onSnapshot"]) window["cr_onSnapshot"](this.snapshotData); this.trigger(cr.system_object.prototype.cnds.OnCanvasSnapshot, null); } this.snapshotCanvas = null; } } if (!this.hit_breakpoint) { this.tickcount++; this.tickcount_nosave++; this.execcount++; this.framecount++; } this.logictime += cr.performance_now() - logic_start; }; Runtime.prototype.logic = function (cur_time) { var i, leni, j, lenj, k, lenk, type, inst, binst; if (cur_time - this.last_fps_time >= 1000) // every 1 second { this.last_fps_time += 1000; if (cur_time - this.last_fps_time >= 1000) this.last_fps_time = cur_time; this.fps = this.framecount; this.framecount = 0; this.cpuutilisation = this.logictime; this.logictime = 0; } var wallDt = 0; if (this.last_tick_time !== 0) { var ms_diff = cur_time - this.last_tick_time; if (ms_diff < 0) ms_diff = 0; wallDt = ms_diff / 1000.0; // dt measured in seconds this.dt1 = wallDt; if (this.dt1 > 0.5) this.dt1 = 0; else if (this.dt1 > 1 / this.minimumFramerate) this.dt1 = 1 / this.minimumFramerate; } this.last_tick_time = cur_time; this.dt = this.dt1 * this.timescale; this.kahanTime.add(this.dt); this.wallTime.add(wallDt); // prevent min/max framerate affecting wall clock var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || document["fullScreen"] || !!document["msFullscreenElement"] || this.isNodeFullscreen) && !this.isCordova; if (this.fullscreen_mode >= 2 /* scale */ || (isfullscreen && this.fullscreen_scaling > 0)) { var orig_aspect = this.original_width / this.original_height; var cur_aspect = this.width / this.height; var mode = this.fullscreen_mode; if (isfullscreen && this.fullscreen_scaling > 0) mode = this.fullscreen_scaling; if ((mode !== 2 && cur_aspect > orig_aspect) || (mode === 2 && cur_aspect < orig_aspect)) { this.aspect_scale = this.height / this.original_height; } else { this.aspect_scale = this.width / this.original_width; } if (this.running_layout) { this.running_layout.scrollToX(this.running_layout.scrollX); this.running_layout.scrollToY(this.running_layout.scrollY); } } else this.aspect_scale = (this.isRetina ? this.devicePixelRatio : 1); this.ClearDeathRow(); this.isInOnDestroy++; this.system.runWaits(); // prevent instance list changing this.isInOnDestroy--; this.ClearDeathRow(); // allow instance list changing this.isInOnDestroy++; var tickarr = this.objects_to_pretick.valuesRef(); for (i = 0, leni = tickarr.length; i < leni; i++) tickarr[i].pretick(); for (i = 0, leni = this.types_by_index.length; i < leni; i++) { type = this.types_by_index[i]; if (type.is_family || (!type.behaviors.length && !type.families.length)) continue; for (j = 0, lenj = type.instances.length; j < lenj; j++) { inst = type.instances[j]; for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++) { inst.behavior_insts[k].tick(); } } } for (i = 0, leni = this.types_by_index.length; i < leni; i++) { type = this.types_by_index[i]; if (type.is_family || (!type.behaviors.length && !type.families.length)) continue; // type doesn't have any behaviors for (j = 0, lenj = type.instances.length; j < lenj; j++) { inst = type.instances[j]; for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++) { binst = inst.behavior_insts[k]; if (binst.posttick) { binst.posttick(); } } } } tickarr = this.objects_to_tick.valuesRef(); for (i = 0, leni = tickarr.length; i < leni; i++) tickarr[i].tick(); this.isInOnDestroy--; // end preventing instance lists from being changed this.handleSaveLoad(); // save/load now if queued i = 0; while (this.changelayout && i++ < 10) { this.doChangeLayout(this.changelayout); } for (i = 0, leni = this.eventsheets_by_index.length; i < leni; i++) this.eventsheets_by_index[i].hasRun = false; if (this.running_layout.event_sheet) this.running_layout.event_sheet.run(); cr.clearArray(this.registered_collisions); this.layout_first_tick = false; this.isInOnDestroy++; // prevent instance lists from being changed for (i = 0, leni = this.types_by_index.length; i < leni; i++) { type = this.types_by_index[i]; if (type.is_family || (!type.behaviors.length && !type.families.length)) continue; // type doesn't have any behaviors for (j = 0, lenj = type.instances.length; j < lenj; j++) { var inst = type.instances[j]; for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++) { binst = inst.behavior_insts[k]; if (binst.tick2) { binst.tick2(); } } } } tickarr = this.objects_to_tick2.valuesRef(); for (i = 0, leni = tickarr.length; i < leni; i++) tickarr[i].tick2(); this.isInOnDestroy--; // end preventing instance lists from being changed }; Runtime.prototype.onWindowBlur = function () { var i, leni, j, lenj, k, lenk, type, inst, binst; for (i = 0, leni = this.types_by_index.length; i < leni; i++) { type = this.types_by_index[i]; if (type.is_family) continue; for (j = 0, lenj = type.instances.length; j < lenj; j++) { inst = type.instances[j]; if (inst.onWindowBlur) inst.onWindowBlur(); if (!inst.behavior_insts) continue; // single-globals don't have behavior_insts for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++) { binst = inst.behavior_insts[k]; if (binst.onWindowBlur) binst.onWindowBlur(); } } } }; Runtime.prototype.doChangeLayout = function (changeToLayout) { var prev_layout = this.running_layout; this.running_layout.stopRunning(); var i, len, j, lenj, k, lenk, type, inst, binst; if (this.glwrap) { for (i = 0, len = this.types_by_index.length; i < len; i++) { type = this.types_by_index[i]; if (type.is_family) continue; if (type.unloadTextures && (!type.global || type.instances.length === 0) && changeToLayout.initial_types.indexOf(type) === -1) { type.unloadTextures(); } } } if (prev_layout == changeToLayout) cr.clearArray(this.system.waits); cr.clearArray(this.registered_collisions); this.runLayoutChangeMethods(true); changeToLayout.startRunning(); this.runLayoutChangeMethods(false); this.redraw = true; this.layout_first_tick = true; this.ClearDeathRow(); }; Runtime.prototype.runLayoutChangeMethods = function (isBeforeChange) { var i, len, beh, type, j, lenj, inst, k, lenk, binst; for (i = 0, len = this.behaviors.length; i < len; i++) { beh = this.behaviors[i]; if (isBeforeChange) { if (beh.onBeforeLayoutChange) beh.onBeforeLayoutChange(); } else { if (beh.onLayoutChange) beh.onLayoutChange(); } } for (i = 0, len = this.types_by_index.length; i < len; i++) { type = this.types_by_index[i]; if (!type.global && !type.plugin.singleglobal) continue; for (j = 0, lenj = type.instances.length; j < lenj; j++) { inst = type.instances[j]; if (isBeforeChange) { if (inst.onBeforeLayoutChange) inst.onBeforeLayoutChange(); } else { if (inst.onLayoutChange) inst.onLayoutChange(); } if (inst.behavior_insts) { for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++) { binst = inst.behavior_insts[k]; if (isBeforeChange) { if (binst.onBeforeLayoutChange) binst.onBeforeLayoutChange(); } else { if (binst.onLayoutChange) binst.onLayoutChange(); } } } } } }; Runtime.prototype.pretickMe = function (inst) { this.objects_to_pretick.add(inst); }; Runtime.prototype.unpretickMe = function (inst) { this.objects_to_pretick.remove(inst); }; Runtime.prototype.tickMe = function (inst) { this.objects_to_tick.add(inst); }; Runtime.prototype.untickMe = function (inst) { this.objects_to_tick.remove(inst); }; Runtime.prototype.tick2Me = function (inst) { this.objects_to_tick2.add(inst); }; Runtime.prototype.untick2Me = function (inst) { this.objects_to_tick2.remove(inst); }; Runtime.prototype.getDt = function (inst) { if (!inst || inst.my_timescale === -1.0) return this.dt; return this.dt1 * inst.my_timescale; }; Runtime.prototype.draw = function () { this.running_layout.draw(this.ctx); if (this.isDirectCanvas) this.ctx["present"](); }; Runtime.prototype.drawGL = function () { if (this.enableFrontToBack) { this.earlyz_index = 1; // start from front, 1-based to avoid exactly equalling near plane Z value this.running_layout.drawGL_earlyZPass(this.glwrap); } this.running_layout.drawGL(this.glwrap); this.glwrap.present(); }; Runtime.prototype.addDestroyCallback = function (f) { if (f) this.destroycallbacks.push(f); }; Runtime.prototype.removeDestroyCallback = function (f) { cr.arrayFindRemove(this.destroycallbacks, f); }; Runtime.prototype.getObjectByUID = function (uid_) { ; var uidstr = uid_.toString(); if (this.objectsByUid.hasOwnProperty(uidstr)) return this.objectsByUid[uidstr]; else return null; }; var objectset_cache = []; function alloc_objectset() { if (objectset_cache.length) return objectset_cache.pop(); else return new cr.ObjectSet(); }; function free_objectset(s) { s.clear(); objectset_cache.push(s); }; Runtime.prototype.DestroyInstance = function (inst) { var i, len; var type = inst.type; var typename = type.name; var has_typename = this.deathRow.hasOwnProperty(typename); var obj_set = null; if (has_typename) { obj_set = this.deathRow[typename]; if (obj_set.contains(inst)) return; // already had DestroyInstance called } else { obj_set = alloc_objectset(); this.deathRow[typename] = obj_set; } obj_set.add(inst); this.hasPendingInstances = true; if (inst.is_contained) { for (i = 0, len = inst.siblings.length; i < len; i++) { this.DestroyInstance(inst.siblings[i]); } } if (this.isInClearDeathRow) obj_set.values_cache.push(inst); if (!this.isEndingLayout) { this.isInOnDestroy++; // support recursion this.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnDestroyed, inst); this.isInOnDestroy--; } }; Runtime.prototype.ClearDeathRow = function () { if (!this.hasPendingInstances) return; var inst, type, instances; var i, j, leni, lenj, obj_set; this.isInClearDeathRow = true; for (i = 0, leni = this.createRow.length; i < leni; ++i) { inst = this.createRow[i]; type = inst.type; type.instances.push(inst); for (j = 0, lenj = type.families.length; j < lenj; ++j) { type.families[j].instances.push(inst); type.families[j].stale_iids = true; } } cr.clearArray(this.createRow); this.IterateDeathRow(); // moved to separate function so for-in performance doesn't hobble entire function cr.wipe(this.deathRow); // all objectsets have already been recycled this.isInClearDeathRow = false; this.hasPendingInstances = false; }; Runtime.prototype.IterateDeathRow = function () { for (var p in this.deathRow) { if (this.deathRow.hasOwnProperty(p)) { this.ClearDeathRowForType(this.deathRow[p]); } } }; Runtime.prototype.ClearDeathRowForType = function (obj_set) { var arr = obj_set.valuesRef(); // get array of items from set ; var type = arr[0].type; ; ; var i, len, j, lenj, w, f, layer_instances, inst; cr.arrayRemoveAllFromObjectSet(type.instances, obj_set); type.stale_iids = true; if (type.instances.length === 0) type.any_instance_parallaxed = false; for (i = 0, len = type.families.length; i < len; ++i) { f = type.families[i]; cr.arrayRemoveAllFromObjectSet(f.instances, obj_set); f.stale_iids = true; } for (i = 0, len = this.system.waits.length; i < len; ++i) { w = this.system.waits[i]; if (w.sols.hasOwnProperty(type.index)) cr.arrayRemoveAllFromObjectSet(w.sols[type.index].insts, obj_set); if (!type.is_family) { for (j = 0, lenj = type.families.length; j < lenj; ++j) { f = type.families[j]; if (w.sols.hasOwnProperty(f.index)) cr.arrayRemoveAllFromObjectSet(w.sols[f.index].insts, obj_set); } } } var first_layer = arr[0].layer; if (first_layer) { if (first_layer.useRenderCells) { layer_instances = first_layer.instances; for (i = 0, len = layer_instances.length; i < len; ++i) { inst = layer_instances[i]; if (!obj_set.contains(inst)) continue; // not destroying this instance inst.update_bbox(); first_layer.render_grid.update(inst, inst.rendercells, null); inst.rendercells.set(0, 0, -1, -1); } } cr.arrayRemoveAllFromObjectSet(first_layer.instances, obj_set); first_layer.setZIndicesStaleFrom(0); } for (i = 0; i < arr.length; ++i) // check array length every time in case it changes { this.ClearDeathRowForSingleInstance(arr[i], type); } free_objectset(obj_set); this.redraw = true; }; Runtime.prototype.ClearDeathRowForSingleInstance = function (inst, type) { var i, len, binst; for (i = 0, len = this.destroycallbacks.length; i < len; ++i) this.destroycallbacks[i](inst); if (inst.collcells) { type.collision_grid.update(inst, inst.collcells, null); } var layer = inst.layer; if (layer) { layer.removeFromInstanceList(inst, true); // remove from both instance list and render grid } if (inst.behavior_insts) { for (i = 0, len = inst.behavior_insts.length; i < len; ++i) { binst = inst.behavior_insts[i]; if (binst.onDestroy) binst.onDestroy(); binst.behavior.my_instances.remove(inst); } } this.objects_to_pretick.remove(inst); this.objects_to_tick.remove(inst); this.objects_to_tick2.remove(inst); if (inst.onDestroy) inst.onDestroy(); if (this.objectsByUid.hasOwnProperty(inst.uid.toString())) delete this.objectsByUid[inst.uid.toString()]; this.objectcount--; if (type.deadCache.length < 100) type.deadCache.push(inst); }; Runtime.prototype.createInstance = function (type, layer, sx, sy) { if (type.is_family) { var i = cr.floor(Math.random() * type.members.length); return this.createInstance(type.members[i], layer, sx, sy); } if (!type.default_instance) { return null; } return this.createInstanceFromInit(type.default_instance, layer, false, sx, sy, false); }; var all_behaviors = []; Runtime.prototype.createInstanceFromInit = function (initial_inst, layer, is_startup_instance, sx, sy, skip_siblings) { var i, len, j, lenj, p, effect_fallback, x, y; if (!initial_inst) return null; var type = this.types_by_index[initial_inst[1]]; ; ; var is_world = type.plugin.is_world; ; if (this.isloading && is_world && !type.isOnLoaderLayout) return null; if (is_world && !this.glwrap && initial_inst[0][11] === 11) return null; var original_layer = layer; if (!is_world) layer = null; var inst; if (type.deadCache.length) { inst = type.deadCache.pop(); inst.recycled = true; type.plugin.Instance.call(inst, type); } else { inst = new type.plugin.Instance(type); inst.recycled = false; } if (is_startup_instance && !skip_siblings && !this.objectsByUid.hasOwnProperty(initial_inst[2].toString())) inst.uid = initial_inst[2]; else inst.uid = this.next_uid++; this.objectsByUid[inst.uid.toString()] = inst; inst.puid = this.next_puid++; inst.iid = type.instances.length; for (i = 0, len = this.createRow.length; i < len; ++i) { if (this.createRow[i].type === type) inst.iid++; } inst.get_iid = cr.inst_get_iid; inst.toString = cr.inst_toString; var initial_vars = initial_inst[3]; if (inst.recycled) { cr.wipe(inst.extra); } else { inst.extra = {}; if (typeof cr_is_preview !== "undefined") { inst.instance_var_names = []; inst.instance_var_names.length = initial_vars.length; for (i = 0, len = initial_vars.length; i < len; i++) inst.instance_var_names[i] = initial_vars[i][1]; } inst.instance_vars = []; inst.instance_vars.length = initial_vars.length; } for (i = 0, len = initial_vars.length; i < len; i++) inst.instance_vars[i] = initial_vars[i][0]; if (is_world) { var wm = initial_inst[0]; ; inst.x = cr.is_undefined(sx) ? wm[0] : sx; inst.y = cr.is_undefined(sy) ? wm[1] : sy; inst.z = wm[2]; inst.width = wm[3]; inst.height = wm[4]; inst.depth = wm[5]; inst.angle = wm[6]; inst.opacity = wm[7]; inst.hotspotX = wm[8]; inst.hotspotY = wm[9]; inst.blend_mode = wm[10]; effect_fallback = wm[11]; if (!this.glwrap && type.effect_types.length) // no WebGL renderer and shaders used inst.blend_mode = effect_fallback; // use fallback blend mode - destroy mode was handled above inst.compositeOp = cr.effectToCompositeOp(inst.blend_mode); if (this.gl) cr.setGLBlend(inst, inst.blend_mode, this.gl); if (inst.recycled) { for (i = 0, len = wm[12].length; i < len; i++) { for (j = 0, lenj = wm[12][i].length; j < lenj; j++) inst.effect_params[i][j] = wm[12][i][j]; } inst.bbox.set(0, 0, 0, 0); inst.collcells.set(0, 0, -1, -1); inst.rendercells.set(0, 0, -1, -1); inst.bquad.set_from_rect(inst.bbox); cr.clearArray(inst.bbox_changed_callbacks); } else { inst.effect_params = wm[12].slice(0); for (i = 0, len = inst.effect_params.length; i < len; i++) inst.effect_params[i] = wm[12][i].slice(0); inst.active_effect_types = []; inst.active_effect_flags = []; inst.active_effect_flags.length = type.effect_types.length; inst.bbox = new cr.rect(0, 0, 0, 0); inst.collcells = new cr.rect(0, 0, -1, -1); inst.rendercells = new cr.rect(0, 0, -1, -1); inst.bquad = new cr.quad(); inst.bbox_changed_callbacks = []; inst.set_bbox_changed = cr.set_bbox_changed; inst.add_bbox_changed_callback = cr.add_bbox_changed_callback; inst.contains_pt = cr.inst_contains_pt; inst.update_bbox = cr.update_bbox; inst.update_render_cell = cr.update_render_cell; inst.update_collision_cell = cr.update_collision_cell; inst.get_zindex = cr.inst_get_zindex; } inst.tilemap_exists = false; inst.tilemap_width = 0; inst.tilemap_height = 0; inst.tilemap_data = null; if (wm.length === 14) { inst.tilemap_exists = true; inst.tilemap_width = wm[13][0]; inst.tilemap_height = wm[13][1]; inst.tilemap_data = wm[13][2]; } for (i = 0, len = type.effect_types.length; i < len; i++) inst.active_effect_flags[i] = true; inst.shaders_preserve_opaqueness = true; inst.updateActiveEffects = cr.inst_updateActiveEffects; inst.updateActiveEffects(); inst.uses_shaders = !!inst.active_effect_types.length; inst.bbox_changed = true; inst.cell_changed = true; type.any_cell_changed = true; inst.visible = true; inst.my_timescale = -1.0; inst.layer = layer; inst.zindex = layer.instances.length; // will be placed at top of current layer inst.earlyz_index = 0; if (typeof inst.collision_poly === "undefined") inst.collision_poly = null; inst.collisionsEnabled = true; this.redraw = true; } var initial_props, binst; cr.clearArray(all_behaviors); for (i = 0, len = type.families.length; i < len; i++) { all_behaviors.push.apply(all_behaviors, type.families[i].behaviors); } all_behaviors.push.apply(all_behaviors, type.behaviors); if (inst.recycled) { for (i = 0, len = all_behaviors.length; i < len; i++) { var btype = all_behaviors[i]; binst = inst.behavior_insts[i]; binst.recycled = true; btype.behavior.Instance.call(binst, btype, inst); initial_props = initial_inst[4][i]; for (j = 0, lenj = initial_props.length; j < lenj; j++) binst.properties[j] = initial_props[j]; binst.onCreate(); btype.behavior.my_instances.add(inst); } } else { inst.behavior_insts = []; for (i = 0, len = all_behaviors.length; i < len; i++) { var btype = all_behaviors[i]; var binst = new btype.behavior.Instance(btype, inst); binst.recycled = false; binst.properties = initial_inst[4][i].slice(0); binst.onCreate(); cr.seal(binst); inst.behavior_insts.push(binst); btype.behavior.my_instances.add(inst); } } initial_props = initial_inst[5]; if (inst.recycled) { for (i = 0, len = initial_props.length; i < len; i++) inst.properties[i] = initial_props[i]; } else inst.properties = initial_props.slice(0); this.createRow.push(inst); this.hasPendingInstances = true; if (layer) { ; layer.appendToInstanceList(inst, true); if (layer.parallaxX !== 1 || layer.parallaxY !== 1) type.any_instance_parallaxed = true; } this.objectcount++; if (type.is_contained) { inst.is_contained = true; if (inst.recycled) cr.clearArray(inst.siblings); else inst.siblings = []; // note: should not include self in siblings if (!is_startup_instance && !skip_siblings) // layout links initial instances { for (i = 0, len = type.container.length; i < len; i++) { if (type.container[i] === type) continue; if (!type.container[i].default_instance) { return null; } inst.siblings.push(this.createInstanceFromInit(type.container[i].default_instance, original_layer, false, is_world ? inst.x : sx, is_world ? inst.y : sy, true)); } for (i = 0, len = inst.siblings.length; i < len; i++) { inst.siblings[i].siblings.push(inst); for (j = 0; j < len; j++) { if (i !== j) inst.siblings[i].siblings.push(inst.siblings[j]); } } } } else { inst.is_contained = false; inst.siblings = null; } inst.onCreate(); if (!inst.recycled) cr.seal(inst); for (i = 0, len = inst.behavior_insts.length; i < len; i++) { if (inst.behavior_insts[i].postCreate) inst.behavior_insts[i].postCreate(); } return inst; }; Runtime.prototype.getLayerByName = function (layer_name) { var i, len; for (i = 0, len = this.running_layout.layers.length; i < len; i++) { var layer = this.running_layout.layers[i]; if (cr.equals_nocase(layer.name, layer_name)) return layer; } return null; }; Runtime.prototype.getLayerByNumber = function (index) { index = cr.floor(index); if (index < 0) index = 0; if (index >= this.running_layout.layers.length) index = this.running_layout.layers.length - 1; return this.running_layout.layers[index]; }; Runtime.prototype.getLayer = function (l) { if (cr.is_number(l)) return this.getLayerByNumber(l); else return this.getLayerByName(l.toString()); }; Runtime.prototype.clearSol = function (solModifiers) { var i, len; for (i = 0, len = solModifiers.length; i < len; i++) { solModifiers[i].getCurrentSol().select_all = true; } }; Runtime.prototype.pushCleanSol = function (solModifiers) { var i, len; for (i = 0, len = solModifiers.length; i < len; i++) { solModifiers[i].pushCleanSol(); } }; Runtime.prototype.pushCopySol = function (solModifiers) { var i, len; for (i = 0, len = solModifiers.length; i < len; i++) { solModifiers[i].pushCopySol(); } }; Runtime.prototype.popSol = function (solModifiers) { var i, len; for (i = 0, len = solModifiers.length; i < len; i++) { solModifiers[i].popSol(); } }; Runtime.prototype.updateAllCells = function (type) { if (!type.any_cell_changed) return; // all instances must already be up-to-date var i, len, instances = type.instances; for (i = 0, len = instances.length; i < len; ++i) { instances[i].update_collision_cell(); } var createRow = this.createRow; for (i = 0, len = createRow.length; i < len; ++i) { if (createRow[i].type === type) createRow[i].update_collision_cell(); } type.any_cell_changed = false; }; Runtime.prototype.getCollisionCandidates = function (layer, rtype, bbox, candidates) { var i, len, t; var is_parallaxed = (layer ? (layer.parallaxX !== 1 || layer.parallaxY !== 1) : false); if (rtype.is_family) { for (i = 0, len = rtype.members.length; i < len; ++i) { t = rtype.members[i]; if (is_parallaxed || t.any_instance_parallaxed) { cr.appendArray(candidates, t.instances); } else { this.updateAllCells(t); t.collision_grid.queryRange(bbox, candidates); } } } else { if (is_parallaxed || rtype.any_instance_parallaxed) { cr.appendArray(candidates, rtype.instances); } else { this.updateAllCells(rtype); rtype.collision_grid.queryRange(bbox, candidates); } } }; Runtime.prototype.getTypesCollisionCandidates = function (layer, types, bbox, candidates) { var i, len; for (i = 0, len = types.length; i < len; ++i) { this.getCollisionCandidates(layer, types[i], bbox, candidates); } }; Runtime.prototype.getSolidCollisionCandidates = function (layer, bbox, candidates) { var solid = this.getSolidBehavior(); if (!solid) return null; this.getTypesCollisionCandidates(layer, solid.my_types, bbox, candidates); }; Runtime.prototype.getJumpthruCollisionCandidates = function (layer, bbox, candidates) { var jumpthru = this.getJumpthruBehavior(); if (!jumpthru) return null; this.getTypesCollisionCandidates(layer, jumpthru.my_types, bbox, candidates); }; Runtime.prototype.testAndSelectCanvasPointOverlap = function (type, ptx, pty, inverted) { var sol = type.getCurrentSol(); var i, j, inst, len; var orblock = this.getCurrentEventStack().current_event.orblock; var lx, ly, arr; if (sol.select_all) { if (!inverted) { sol.select_all = false; cr.clearArray(sol.instances); // clear contents } for (i = 0, len = type.instances.length; i < len; i++) { inst = type.instances[i]; inst.update_bbox(); lx = inst.layer.canvasToLayer(ptx, pty, true); ly = inst.layer.canvasToLayer(ptx, pty, false); if (inst.contains_pt(lx, ly)) { if (inverted) return false; else sol.instances.push(inst); } else if (orblock) sol.else_instances.push(inst); } } else { j = 0; arr = (orblock ? sol.else_instances : sol.instances); for (i = 0, len = arr.length; i < len; i++) { inst = arr[i]; inst.update_bbox(); lx = inst.layer.canvasToLayer(ptx, pty, true); ly = inst.layer.canvasToLayer(ptx, pty, false); if (inst.contains_pt(lx, ly)) { if (inverted) return false; else if (orblock) sol.instances.push(inst); else { sol.instances[j] = sol.instances[i]; j++; } } } if (!inverted) arr.length = j; } type.applySolToContainer(); if (inverted) return true; // did not find anything overlapping else return sol.hasObjects(); }; Runtime.prototype.testOverlap = function (a, b) { if (!a || !b || a === b || !a.collisionsEnabled || !b.collisionsEnabled) return false; a.update_bbox(); b.update_bbox(); var layera = a.layer; var layerb = b.layer; 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)); var i, len, i2, i21, x, y, haspolya, haspolyb, polya, polyb; if (!different_layers) // same layers: easy check { if (!a.bbox.intersects_rect(b.bbox)) return false; if (!a.bquad.intersects_quad(b.bquad)) return false; if (a.tilemap_exists && b.tilemap_exists) return false; if (a.tilemap_exists) return this.testTilemapOverlap(a, b); if (b.tilemap_exists) return this.testTilemapOverlap(b, a); haspolya = (a.collision_poly && !a.collision_poly.is_empty()); haspolyb = (b.collision_poly && !b.collision_poly.is_empty()); if (!haspolya && !haspolyb) return true; if (haspolya) { a.collision_poly.cache_poly(a.width, a.height, a.angle); polya = a.collision_poly; } else { this.temp_poly.set_from_quad(a.bquad, a.x, a.y, a.width, a.height); polya = this.temp_poly; } if (haspolyb) { b.collision_poly.cache_poly(b.width, b.height, b.angle); polyb = b.collision_poly; } else { this.temp_poly.set_from_quad(b.bquad, b.x, b.y, b.width, b.height); polyb = this.temp_poly; } return polya.intersects_poly(polyb, b.x - a.x, b.y - a.y); } else // different layers: need to do full translated check { haspolya = (a.collision_poly && !a.collision_poly.is_empty()); haspolyb = (b.collision_poly && !b.collision_poly.is_empty()); if (haspolya) { a.collision_poly.cache_poly(a.width, a.height, a.angle); this.temp_poly.set_from_poly(a.collision_poly); } else { this.temp_poly.set_from_quad(a.bquad, a.x, a.y, a.width, a.height); } polya = this.temp_poly; if (haspolyb) { b.collision_poly.cache_poly(b.width, b.height, b.angle); this.temp_poly2.set_from_poly(b.collision_poly); } else { this.temp_poly2.set_from_quad(b.bquad, b.x, b.y, b.width, b.height); } polyb = this.temp_poly2; for (i = 0, len = polya.pts_count; i < len; i++) { i2 = i * 2; i21 = i2 + 1; x = polya.pts_cache[i2]; y = polya.pts_cache[i21]; polya.pts_cache[i2] = layera.layerToCanvas(x + a.x, y + a.y, true); polya.pts_cache[i21] = layera.layerToCanvas(x + a.x, y + a.y, false); } polya.update_bbox(); for (i = 0, len = polyb.pts_count; i < len; i++) { i2 = i * 2; i21 = i2 + 1; x = polyb.pts_cache[i2]; y = polyb.pts_cache[i21]; polyb.pts_cache[i2] = layerb.layerToCanvas(x + b.x, y + b.y, true); polyb.pts_cache[i21] = layerb.layerToCanvas(x + b.x, y + b.y, false); } polyb.update_bbox(); return polya.intersects_poly(polyb, 0, 0); } }; var tmpQuad = new cr.quad(); var tmpRect = new cr.rect(0, 0, 0, 0); var collrect_candidates = []; Runtime.prototype.testTilemapOverlap = function (tm, a) { var i, len, c, rc; var bbox = a.bbox; var tmx = tm.x; var tmy = tm.y; tm.getCollisionRectCandidates(bbox, collrect_candidates); var collrects = collrect_candidates; var haspolya = (a.collision_poly && !a.collision_poly.is_empty()); for (i = 0, len = collrects.length; i < len; ++i) { c = collrects[i]; rc = c.rc; if (bbox.intersects_rect_off(rc, tmx, tmy)) { tmpQuad.set_from_rect(rc); tmpQuad.offset(tmx, tmy); if (tmpQuad.intersects_quad(a.bquad)) { if (haspolya) { a.collision_poly.cache_poly(a.width, a.height, a.angle); if (c.poly) { if (c.poly.intersects_poly(a.collision_poly, a.x - (tmx + rc.left), a.y - (tmy + rc.top))) { cr.clearArray(collrect_candidates); return true; } } else { this.temp_poly.set_from_quad(tmpQuad, 0, 0, rc.right - rc.left, rc.bottom - rc.top); if (this.temp_poly.intersects_poly(a.collision_poly, a.x, a.y)) { cr.clearArray(collrect_candidates); return true; } } } else { if (c.poly) { this.temp_poly.set_from_quad(a.bquad, 0, 0, a.width, a.height); if (c.poly.intersects_poly(this.temp_poly, -(tmx + rc.left), -(tmy + rc.top))) { cr.clearArray(collrect_candidates); return true; } } else { cr.clearArray(collrect_candidates); return true; } } } } } cr.clearArray(collrect_candidates); return false; }; Runtime.prototype.testRectOverlap = function (r, b) { if (!b || !b.collisionsEnabled) return false; b.update_bbox(); var layerb = b.layer; var haspolyb, polyb; if (!b.bbox.intersects_rect(r)) return false; if (b.tilemap_exists) { b.getCollisionRectCandidates(r, collrect_candidates); var collrects = collrect_candidates; var i, len, c, tilerc; var tmx = b.x; var tmy = b.y; for (i = 0, len = collrects.length; i < len; ++i) { c = collrects[i]; tilerc = c.rc; if (r.intersects_rect_off(tilerc, tmx, tmy)) { if (c.poly) { this.temp_poly.set_from_rect(r, 0, 0); if (c.poly.intersects_poly(this.temp_poly, -(tmx + tilerc.left), -(tmy + tilerc.top))) { cr.clearArray(collrect_candidates); return true; } } else { cr.clearArray(collrect_candidates); return true; } } } cr.clearArray(collrect_candidates); return false; } else { tmpQuad.set_from_rect(r); if (!b.bquad.intersects_quad(tmpQuad)) return false; haspolyb = (b.collision_poly && !b.collision_poly.is_empty()); if (!haspolyb) return true; b.collision_poly.cache_poly(b.width, b.height, b.angle); tmpQuad.offset(-r.left, -r.top); this.temp_poly.set_from_quad(tmpQuad, 0, 0, 1, 1); return b.collision_poly.intersects_poly(this.temp_poly, r.left - b.x, r.top - b.y); } }; Runtime.prototype.testSegmentOverlap = function (x1, y1, x2, y2, b) { if (!b || !b.collisionsEnabled) return false; b.update_bbox(); var layerb = b.layer; var haspolyb, polyb; tmpRect.set(cr.min(x1, x2), cr.min(y1, y2), cr.max(x1, x2), cr.max(y1, y2)); if (!b.bbox.intersects_rect(tmpRect)) return false; if (b.tilemap_exists) { b.getCollisionRectCandidates(tmpRect, collrect_candidates); var collrects = collrect_candidates; var i, len, c, tilerc; var tmx = b.x; var tmy = b.y; for (i = 0, len = collrects.length; i < len; ++i) { c = collrects[i]; tilerc = c.rc; if (tmpRect.intersects_rect_off(tilerc, tmx, tmy)) { tmpQuad.set_from_rect(tilerc); tmpQuad.offset(tmx, tmy); if (tmpQuad.intersects_segment(x1, y1, x2, y2)) { if (c.poly) { if (c.poly.intersects_segment(tmx + tilerc.left, tmy + tilerc.top, x1, y1, x2, y2)) { cr.clearArray(collrect_candidates); return true; } } else { cr.clearArray(collrect_candidates); return true; } } } } cr.clearArray(collrect_candidates); return false; } else { if (!b.bquad.intersects_segment(x1, y1, x2, y2)) return false; haspolyb = (b.collision_poly && !b.collision_poly.is_empty()); if (!haspolyb) return true; b.collision_poly.cache_poly(b.width, b.height, b.angle); return b.collision_poly.intersects_segment(b.x, b.y, x1, y1, x2, y2); } }; Runtime.prototype.typeHasBehavior = function (t, b) { if (!b) return false; var i, len, j, lenj, f; for (i = 0, len = t.behaviors.length; i < len; i++) { if (t.behaviors[i].behavior instanceof b) return true; } if (!t.is_family) { for (i = 0, len = t.families.length; i < len; i++) { f = t.families[i]; for (j = 0, lenj = f.behaviors.length; j < lenj; j++) { if (f.behaviors[j].behavior instanceof b) return true; } } } return false; }; Runtime.prototype.typeHasNoSaveBehavior = function (t) { return this.typeHasBehavior(t, cr.behaviors.NoSave); }; Runtime.prototype.typeHasPersistBehavior = function (t) { return this.typeHasBehavior(t, cr.behaviors.Persist); }; Runtime.prototype.getSolidBehavior = function () { return this.solidBehavior; }; Runtime.prototype.getJumpthruBehavior = function () { return this.jumpthruBehavior; }; var candidates = []; Runtime.prototype.testOverlapSolid = function (inst) { var i, len, s; inst.update_bbox(); this.getSolidCollisionCandidates(inst.layer, inst.bbox, candidates); for (i = 0, len = candidates.length; i < len; ++i) { s = candidates[i]; if (!s.extra["solidEnabled"]) continue; if (this.testOverlap(inst, s)) { cr.clearArray(candidates); return s; } } cr.clearArray(candidates); return null; }; Runtime.prototype.testRectOverlapSolid = function (r) { var i, len, s; this.getSolidCollisionCandidates(null, r, candidates); for (i = 0, len = candidates.length; i < len; ++i) { s = candidates[i]; if (!s.extra["solidEnabled"]) continue; if (this.testRectOverlap(r, s)) { cr.clearArray(candidates); return s; } } cr.clearArray(candidates); return null; }; var jumpthru_array_ret = []; Runtime.prototype.testOverlapJumpThru = function (inst, all) { var ret = null; if (all) { ret = jumpthru_array_ret; cr.clearArray(ret); } inst.update_bbox(); this.getJumpthruCollisionCandidates(inst.layer, inst.bbox, candidates); var i, len, j; for (i = 0, len = candidates.length; i < len; ++i) { j = candidates[i]; if (!j.extra["jumpthruEnabled"]) continue; if (this.testOverlap(inst, j)) { if (all) ret.push(j); else { cr.clearArray(candidates); return j; } } } cr.clearArray(candidates); return ret; }; Runtime.prototype.pushOutSolid = function (inst, xdir, ydir, dist, include_jumpthrus, specific_jumpthru) { var push_dist = dist || 50; var oldx = inst.x var oldy = inst.y; var i; var last_overlapped = null, secondlast_overlapped = null; for (i = 0; i < push_dist; i++) { inst.x = (oldx + (xdir * i)); inst.y = (oldy + (ydir * i)); inst.set_bbox_changed(); if (!this.testOverlap(inst, last_overlapped)) { last_overlapped = this.testOverlapSolid(inst); if (last_overlapped) secondlast_overlapped = last_overlapped; if (!last_overlapped) { if (include_jumpthrus) { if (specific_jumpthru) last_overlapped = (this.testOverlap(inst, specific_jumpthru) ? specific_jumpthru : null); else last_overlapped = this.testOverlapJumpThru(inst); if (last_overlapped) secondlast_overlapped = last_overlapped; } if (!last_overlapped) { if (secondlast_overlapped) this.pushInFractional(inst, xdir, ydir, secondlast_overlapped, 16); return true; } } } } inst.x = oldx; inst.y = oldy; inst.set_bbox_changed(); return false; }; Runtime.prototype.pushOutSolidAxis = function(inst, xdir, ydir, dist) { dist = dist || 50; var oldX = inst.x; var oldY = inst.y; var lastOverlapped = null; var secondLastOverlapped = null; var i, which, sign; for (i = 0; i < dist; ++i) { for (which = 0; which < 2; ++which) { sign = which * 2 - 1; // -1 or 1 inst.x = oldX + (xdir * i * sign); inst.y = oldY + (ydir * i * sign); inst.set_bbox_changed(); if (!this.testOverlap(inst, lastOverlapped)) { lastOverlapped = this.testOverlapSolid(inst); if (lastOverlapped) { secondLastOverlapped = lastOverlapped; } else { if (secondLastOverlapped) this.pushInFractional(inst, xdir * sign, ydir * sign, secondLastOverlapped, 16); return true; } } } } inst.x = oldX; inst.y = oldY; inst.set_bbox_changed(); return false; }; Runtime.prototype.pushOut = function (inst, xdir, ydir, dist, otherinst) { var push_dist = dist || 50; var oldx = inst.x var oldy = inst.y; var i; for (i = 0; i < push_dist; i++) { inst.x = (oldx + (xdir * i)); inst.y = (oldy + (ydir * i)); inst.set_bbox_changed(); if (!this.testOverlap(inst, otherinst)) return true; } inst.x = oldx; inst.y = oldy; inst.set_bbox_changed(); return false; }; Runtime.prototype.pushInFractional = function (inst, xdir, ydir, obj, limit) { var divisor = 2; var frac; var forward = false; var overlapping = false; var bestx = inst.x; var besty = inst.y; while (divisor <= limit) { frac = 1 / divisor; divisor *= 2; inst.x += xdir * frac * (forward ? 1 : -1); inst.y += ydir * frac * (forward ? 1 : -1); inst.set_bbox_changed(); if (this.testOverlap(inst, obj)) { forward = true; overlapping = true; } else { forward = false; overlapping = false; bestx = inst.x; besty = inst.y; } } if (overlapping) { inst.x = bestx; inst.y = besty; inst.set_bbox_changed(); } }; Runtime.prototype.pushOutSolidNearest = function (inst, max_dist_) { var max_dist = (cr.is_undefined(max_dist_) ? 100 : max_dist_); var dist = 0; var oldx = inst.x var oldy = inst.y; var dir = 0; var dx = 0, dy = 0; var last_overlapped = this.testOverlapSolid(inst); if (!last_overlapped) return true; // already clear of solids while (dist <= max_dist) { switch (dir) { case 0: dx = 0; dy = -1; dist++; break; case 1: dx = 1; dy = -1; break; case 2: dx = 1; dy = 0; break; case 3: dx = 1; dy = 1; break; case 4: dx = 0; dy = 1; break; case 5: dx = -1; dy = 1; break; case 6: dx = -1; dy = 0; break; case 7: dx = -1; dy = -1; break; } dir = (dir + 1) % 8; inst.x = cr.floor(oldx + (dx * dist)); inst.y = cr.floor(oldy + (dy * dist)); inst.set_bbox_changed(); if (!this.testOverlap(inst, last_overlapped)) { last_overlapped = this.testOverlapSolid(inst); if (!last_overlapped) return true; } } inst.x = oldx; inst.y = oldy; inst.set_bbox_changed(); return false; }; Runtime.prototype.registerCollision = function (a, b) { if (!a.collisionsEnabled || !b.collisionsEnabled) return; this.registered_collisions.push([a, b]); }; Runtime.prototype.addRegisteredCollisionCandidates = function (inst, otherType, arr) { var i, len, r, otherInst; for (i = 0, len = this.registered_collisions.length; i < len; ++i) { r = this.registered_collisions[i]; if (r[0] === inst) otherInst = r[1]; else if (r[1] === inst) otherInst = r[0]; else continue; if (otherType.is_family) { if (otherType.members.indexOf(otherType) === -1) continue; } else { if (otherInst.type !== otherType) continue; } if (arr.indexOf(otherInst) === -1) arr.push(otherInst); } }; Runtime.prototype.checkRegisteredCollision = function (a, b) { var i, len, x; for (i = 0, len = this.registered_collisions.length; i < len; i++) { x = this.registered_collisions[i]; if ((x[0] === a && x[1] === b) || (x[0] === b && x[1] === a)) return true; } return false; }; Runtime.prototype.calculateSolidBounceAngle = function(inst, startx, starty, obj) { var objx = inst.x; var objy = inst.y; var radius = cr.max(10, cr.distanceTo(startx, starty, objx, objy)); var startangle = cr.angleTo(startx, starty, objx, objy); var firstsolid = obj || this.testOverlapSolid(inst); if (!firstsolid) return cr.clamp_angle(startangle + cr.PI); var cursolid = firstsolid; var i, curangle, anticlockwise_free_angle, clockwise_free_angle; var increment = cr.to_radians(5); // 5 degree increments for (i = 1; i < 36; i++) { curangle = startangle - i * increment; inst.x = startx + Math.cos(curangle) * radius; inst.y = starty + Math.sin(curangle) * radius; inst.set_bbox_changed(); if (!this.testOverlap(inst, cursolid)) { cursolid = obj ? null : this.testOverlapSolid(inst); if (!cursolid) { anticlockwise_free_angle = curangle; break; } } } if (i === 36) anticlockwise_free_angle = cr.clamp_angle(startangle + cr.PI); var cursolid = firstsolid; for (i = 1; i < 36; i++) { curangle = startangle + i * increment; inst.x = startx + Math.cos(curangle) * radius; inst.y = starty + Math.sin(curangle) * radius; inst.set_bbox_changed(); if (!this.testOverlap(inst, cursolid)) { cursolid = obj ? null : this.testOverlapSolid(inst); if (!cursolid) { clockwise_free_angle = curangle; break; } } } if (i === 36) clockwise_free_angle = cr.clamp_angle(startangle + cr.PI); inst.x = objx; inst.y = objy; inst.set_bbox_changed(); if (clockwise_free_angle === anticlockwise_free_angle) return clockwise_free_angle; var half_diff = cr.angleDiff(clockwise_free_angle, anticlockwise_free_angle) / 2; var normal; if (cr.angleClockwise(clockwise_free_angle, anticlockwise_free_angle)) { normal = cr.clamp_angle(anticlockwise_free_angle + half_diff + cr.PI); } else { normal = cr.clamp_angle(clockwise_free_angle + half_diff); } ; var vx = Math.cos(startangle); var vy = Math.sin(startangle); var nx = Math.cos(normal); var ny = Math.sin(normal); var v_dot_n = vx * nx + vy * ny; var rx = vx - 2 * v_dot_n * nx; var ry = vy - 2 * v_dot_n * ny; return cr.angleTo(0, 0, rx, ry); }; var triggerSheetIndex = -1; Runtime.prototype.trigger = function (method, inst, value /* for fast triggers */) { ; if (!this.running_layout) return false; var sheet = this.running_layout.event_sheet; if (!sheet) return false; // no event sheet active; nothing to trigger var ret = false; var r, i, len; triggerSheetIndex++; var deep_includes = sheet.deep_includes; for (i = 0, len = deep_includes.length; i < len; ++i) { r = this.triggerOnSheet(method, inst, deep_includes[i], value); ret = ret || r; } r = this.triggerOnSheet(method, inst, sheet, value); ret = ret || r; triggerSheetIndex--; return ret; }; Runtime.prototype.triggerOnSheet = function (method, inst, sheet, value) { var ret = false; var i, leni, r, families; if (!inst) { r = this.triggerOnSheetForTypeName(method, inst, "system", sheet, value); ret = ret || r; } else { r = this.triggerOnSheetForTypeName(method, inst, inst.type.name, sheet, value); ret = ret || r; families = inst.type.families; for (i = 0, leni = families.length; i < leni; ++i) { r = this.triggerOnSheetForTypeName(method, inst, families[i].name, sheet, value); ret = ret || r; } } return ret; // true if anything got triggered }; Runtime.prototype.triggerOnSheetForTypeName = function (method, inst, type_name, sheet, value) { var i, leni; var ret = false, ret2 = false; var trig, index; var fasttrigger = (typeof value !== "undefined"); var triggers = (fasttrigger ? sheet.fasttriggers : sheet.triggers); var obj_entry = triggers[type_name]; if (!obj_entry) return ret; var triggers_list = null; for (i = 0, leni = obj_entry.length; i < leni; ++i) { if (obj_entry[i].method == method) { triggers_list = obj_entry[i].evs; break; } } if (!triggers_list) return ret; var triggers_to_fire; if (fasttrigger) { triggers_to_fire = triggers_list[value]; } else { triggers_to_fire = triggers_list; } if (!triggers_to_fire) return null; for (i = 0, leni = triggers_to_fire.length; i < leni; i++) { trig = triggers_to_fire[i][0]; index = triggers_to_fire[i][1]; ret2 = this.executeSingleTrigger(inst, type_name, trig, index); ret = ret || ret2; } return ret; }; Runtime.prototype.executeSingleTrigger = function (inst, type_name, trig, index) { var i, leni; var ret = false; this.trigger_depth++; var current_event = this.getCurrentEventStack().current_event; if (current_event) this.pushCleanSol(current_event.solModifiersIncludingParents); var isrecursive = (this.trigger_depth > 1); // calling trigger from inside another trigger this.pushCleanSol(trig.solModifiersIncludingParents); if (isrecursive) this.pushLocalVarStack(); var event_stack = this.pushEventStack(trig); event_stack.current_event = trig; if (inst) { var sol = this.types[type_name].getCurrentSol(); sol.select_all = false; cr.clearArray(sol.instances); sol.instances[0] = inst; this.types[type_name].applySolToContainer(); } var ok_to_run = true; if (trig.parent) { var temp_parents_arr = event_stack.temp_parents_arr; var cur_parent = trig.parent; while (cur_parent) { temp_parents_arr.push(cur_parent); cur_parent = cur_parent.parent; } temp_parents_arr.reverse(); for (i = 0, leni = temp_parents_arr.length; i < leni; i++) { if (!temp_parents_arr[i].run_pretrigger()) // parent event failed { ok_to_run = false; break; } } } if (ok_to_run) { this.execcount++; if (trig.orblock) trig.run_orblocktrigger(index); else trig.run(); ret = ret || event_stack.last_event_true; } this.popEventStack(); if (isrecursive) this.popLocalVarStack(); this.popSol(trig.solModifiersIncludingParents); if (current_event) this.popSol(current_event.solModifiersIncludingParents); if (this.hasPendingInstances && this.isInOnDestroy === 0 && triggerSheetIndex === 0 && !this.isRunningEvents) { this.ClearDeathRow(); } this.trigger_depth--; return ret; }; Runtime.prototype.getCurrentCondition = function () { var evinfo = this.getCurrentEventStack(); return evinfo.current_event.conditions[evinfo.cndindex]; }; Runtime.prototype.getCurrentConditionObjectType = function () { var cnd = this.getCurrentCondition(); return cnd.type; }; Runtime.prototype.isCurrentConditionFirst = function () { var evinfo = this.getCurrentEventStack(); return evinfo.cndindex === 0; }; Runtime.prototype.getCurrentAction = function () { var evinfo = this.getCurrentEventStack(); return evinfo.current_event.actions[evinfo.actindex]; }; Runtime.prototype.pushLocalVarStack = function () { this.localvar_stack_index++; if (this.localvar_stack_index >= this.localvar_stack.length) this.localvar_stack.push([]); }; Runtime.prototype.popLocalVarStack = function () { ; this.localvar_stack_index--; }; Runtime.prototype.getCurrentLocalVarStack = function () { return this.localvar_stack[this.localvar_stack_index]; }; Runtime.prototype.pushEventStack = function (cur_event) { this.event_stack_index++; if (this.event_stack_index >= this.event_stack.length) this.event_stack.push(new cr.eventStackFrame()); var ret = this.getCurrentEventStack(); ret.reset(cur_event); return ret; }; Runtime.prototype.popEventStack = function () { ; this.event_stack_index--; }; Runtime.prototype.getCurrentEventStack = function () { return this.event_stack[this.event_stack_index]; }; Runtime.prototype.pushLoopStack = function (name_) { this.loop_stack_index++; if (this.loop_stack_index >= this.loop_stack.length) { this.loop_stack.push(cr.seal({ name: name_, index: 0, stopped: false })); } var ret = this.getCurrentLoop(); ret.name = name_; ret.index = 0; ret.stopped = false; return ret; }; Runtime.prototype.popLoopStack = function () { ; this.loop_stack_index--; }; Runtime.prototype.getCurrentLoop = function () { return this.loop_stack[this.loop_stack_index]; }; Runtime.prototype.getEventVariableByName = function (name, scope) { var i, leni, j, lenj, sheet, e; while (scope) { for (i = 0, leni = scope.subevents.length; i < leni; i++) { e = scope.subevents[i]; if (e instanceof cr.eventvariable && cr.equals_nocase(name, e.name)) return e; } scope = scope.parent; } for (i = 0, leni = this.eventsheets_by_index.length; i < leni; i++) { sheet = this.eventsheets_by_index[i]; for (j = 0, lenj = sheet.events.length; j < lenj; j++) { e = sheet.events[j]; if (e instanceof cr.eventvariable && cr.equals_nocase(name, e.name)) return e; } } return null; }; Runtime.prototype.getLayoutBySid = function (sid_) { var i, len; for (i = 0, len = this.layouts_by_index.length; i < len; i++) { if (this.layouts_by_index[i].sid === sid_) return this.layouts_by_index[i]; } return null; }; Runtime.prototype.getObjectTypeBySid = function (sid_) { var i, len; for (i = 0, len = this.types_by_index.length; i < len; i++) { if (this.types_by_index[i].sid === sid_) return this.types_by_index[i]; } return null; }; Runtime.prototype.getGroupBySid = function (sid_) { var i, len; for (i = 0, len = this.allGroups.length; i < len; i++) { if (this.allGroups[i].sid === sid_) return this.allGroups[i]; } return null; }; Runtime.prototype.doCanvasSnapshot = function (format_, quality_) { this.snapshotCanvas = [format_, quality_]; this.redraw = true; // force redraw so snapshot is always taken }; function IsIndexedDBAvailable() { try { return !!window.indexedDB; } catch (e) { return false; } }; function makeSaveDb(e) { var db = e.target.result; db.createObjectStore("saves", { keyPath: "slot" }); }; function IndexedDB_WriteSlot(slot_, data_, oncomplete_, onerror_) { try { var request = indexedDB.open("_C2SaveStates"); request.onupgradeneeded = makeSaveDb; request.onerror = onerror_; request.onsuccess = function (e) { var db = e.target.result; db.onerror = onerror_; var transaction = db.transaction(["saves"], "readwrite"); var objectStore = transaction.objectStore("saves"); var putReq = objectStore.put({"slot": slot_, "data": data_ }); putReq.onsuccess = oncomplete_; }; } catch (err) { onerror_(err); } }; function IndexedDB_ReadSlot(slot_, oncomplete_, onerror_) { try { var request = indexedDB.open("_C2SaveStates"); request.onupgradeneeded = makeSaveDb; request.onerror = onerror_; request.onsuccess = function (e) { var db = e.target.result; db.onerror = onerror_; var transaction = db.transaction(["saves"]); var objectStore = transaction.objectStore("saves"); var readReq = objectStore.get(slot_); readReq.onsuccess = function (e) { if (readReq.result) oncomplete_(readReq.result["data"]); else oncomplete_(null); }; }; } catch (err) { onerror_(err); } }; Runtime.prototype.signalContinuousPreview = function () { this.signalledContinuousPreview = true; }; function doContinuousPreviewReload() { cr.logexport("Reloading for continuous preview"); if (!!window["c2cocoonjs"]) { CocoonJS["App"]["reload"](); } else { if (window.location.search.indexOf("continuous") > -1) window.location.reload(true); else window.location = window.location + "?continuous"; } }; Runtime.prototype.handleSaveLoad = function () { var self = this; var savingToSlot = this.saveToSlot; var savingJson = this.lastSaveJson; var loadingFromSlot = this.loadFromSlot; var continuous = false; if (this.signalledContinuousPreview) { continuous = true; savingToSlot = "__c2_continuouspreview"; this.signalledContinuousPreview = false; } if (savingToSlot.length) { this.ClearDeathRow(); savingJson = this.saveToJSONString(); if (IsIndexedDBAvailable() && !this.isCocoonJs) { IndexedDB_WriteSlot(savingToSlot, savingJson, function () { cr.logexport("Saved state to IndexedDB storage (" + savingJson.length + " bytes)"); self.lastSaveJson = savingJson; self.trigger(cr.system_object.prototype.cnds.OnSaveComplete, null); self.lastSaveJson = ""; savingJson = ""; if (continuous) doContinuousPreviewReload(); }, function (e) { try { localStorage.setItem("__c2save_" + savingToSlot, savingJson); cr.logexport("Saved state to WebStorage (" + savingJson.length + " bytes)"); self.lastSaveJson = savingJson; self.trigger(cr.system_object.prototype.cnds.OnSaveComplete, null); self.lastSaveJson = ""; savingJson = ""; if (continuous) doContinuousPreviewReload(); } catch (f) { cr.logexport("Failed to save game state: " + e + "; " + f); self.trigger(cr.system_object.prototype.cnds.OnSaveFailed, null); } }); } else { try { localStorage.setItem("__c2save_" + savingToSlot, savingJson); cr.logexport("Saved state to WebStorage (" + savingJson.length + " bytes)"); self.lastSaveJson = savingJson; this.trigger(cr.system_object.prototype.cnds.OnSaveComplete, null); self.lastSaveJson = ""; savingJson = ""; if (continuous) doContinuousPreviewReload(); } catch (e) { cr.logexport("Error saving to WebStorage: " + e); self.trigger(cr.system_object.prototype.cnds.OnSaveFailed, null); } } this.saveToSlot = ""; this.loadFromSlot = ""; this.loadFromJson = null; } if (loadingFromSlot.length) { if (IsIndexedDBAvailable() && !this.isCocoonJs) { IndexedDB_ReadSlot(loadingFromSlot, function (result_) { if (result_) { self.loadFromJson = result_; cr.logexport("Loaded state from IndexedDB storage (" + self.loadFromJson.length + " bytes)"); } else { self.loadFromJson = localStorage.getItem("__c2save_" + loadingFromSlot) || ""; cr.logexport("Loaded state from WebStorage (" + self.loadFromJson.length + " bytes)"); } self.suspendDrawing = false; if (!self.loadFromJson) { self.loadFromJson = null; self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null); } }, function (e) { self.loadFromJson = localStorage.getItem("__c2save_" + loadingFromSlot) || ""; cr.logexport("Loaded state from WebStorage (" + self.loadFromJson.length + " bytes)"); self.suspendDrawing = false; if (!self.loadFromJson) { self.loadFromJson = null; self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null); } }); } else { try { this.loadFromJson = localStorage.getItem("__c2save_" + loadingFromSlot) || ""; cr.logexport("Loaded state from WebStorage (" + this.loadFromJson.length + " bytes)"); } catch (e) { this.loadFromJson = null; } this.suspendDrawing = false; if (!self.loadFromJson) { self.loadFromJson = null; self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null); } } this.loadFromSlot = ""; this.saveToSlot = ""; } if (this.loadFromJson !== null) { this.ClearDeathRow(); var ok = this.loadFromJSONString(this.loadFromJson); if (ok) { this.lastSaveJson = this.loadFromJson; this.trigger(cr.system_object.prototype.cnds.OnLoadComplete, null); this.lastSaveJson = ""; } else { self.trigger(cr.system_object.prototype.cnds.OnLoadFailed, null); } this.loadFromJson = null; } }; function CopyExtraObject(extra) { var p, ret = {}; for (p in extra) { if (extra.hasOwnProperty(p)) { if (extra[p] instanceof cr.ObjectSet) continue; if (extra[p] && typeof extra[p].c2userdata !== "undefined") continue; if (p === "spriteCreatedDestroyCallback") continue; ret[p] = extra[p]; } } return ret; }; Runtime.prototype.saveToJSONString = function() { var i, len, j, lenj, type, layout, typeobj, g, c, a, v, p; var o = { "c2save": true, "version": 1, "rt": { "time": this.kahanTime.sum, "walltime": this.wallTime.sum, "timescale": this.timescale, "tickcount": this.tickcount, "execcount": this.execcount, "next_uid": this.next_uid, "running_layout": this.running_layout.sid, "start_time_offset": (Date.now() - this.start_time) }, "types": {}, "layouts": {}, "events": { "groups": {}, "cnds": {}, "acts": {}, "vars": {} } }; for (i = 0, len = this.types_by_index.length; i < len; i++) { type = this.types_by_index[i]; if (type.is_family || this.typeHasNoSaveBehavior(type)) continue; typeobj = { "instances": [] }; if (cr.hasAnyOwnProperty(type.extra)) typeobj["ex"] = CopyExtraObject(type.extra); for (j = 0, lenj = type.instances.length; j < lenj; j++) { typeobj["instances"].push(this.saveInstanceToJSON(type.instances[j])); } o["types"][type.sid.toString()] = typeobj; } for (i = 0, len = this.layouts_by_index.length; i < len; i++) { layout = this.layouts_by_index[i]; o["layouts"][layout.sid.toString()] = layout.saveToJSON(); } var ogroups = o["events"]["groups"]; for (i = 0, len = this.allGroups.length; i < len; i++) { g = this.allGroups[i]; ogroups[g.sid.toString()] = this.groups_by_name[g.group_name].group_active; } var ocnds = o["events"]["cnds"]; for (p in this.cndsBySid) { if (this.cndsBySid.hasOwnProperty(p)) { c = this.cndsBySid[p]; if (cr.hasAnyOwnProperty(c.extra)) ocnds[p] = { "ex": CopyExtraObject(c.extra) }; } } var oacts = o["events"]["acts"]; for (p in this.actsBySid) { if (this.actsBySid.hasOwnProperty(p)) { a = this.actsBySid[p]; if (cr.hasAnyOwnProperty(a.extra)) oacts[p] = { "ex": CopyExtraObject(a.extra) }; } } var ovars = o["events"]["vars"]; for (p in this.varsBySid) { if (this.varsBySid.hasOwnProperty(p)) { v = this.varsBySid[p]; if (!v.is_constant && (!v.parent || v.is_static)) ovars[p] = v.data; } } o["system"] = this.system.saveToJSON(); return JSON.stringify(o); }; Runtime.prototype.refreshUidMap = function () { var i, len, type, j, lenj, inst; this.objectsByUid = {}; for (i = 0, len = this.types_by_index.length; i < len; i++) { type = this.types_by_index[i]; if (type.is_family) continue; for (j = 0, lenj = type.instances.length; j < lenj; j++) { inst = type.instances[j]; this.objectsByUid[inst.uid.toString()] = inst; } } }; Runtime.prototype.loadFromJSONString = function (str) { var o; try { o = JSON.parse(str); } catch (e) { return false; } if (!o["c2save"]) return false; // probably not a c2 save state if (o["version"] > 1) return false; // from future version of c2; assume not compatible this.isLoadingState = true; var rt = o["rt"]; this.kahanTime.reset(); this.kahanTime.sum = rt["time"]; this.wallTime.reset(); this.wallTime.sum = rt["walltime"] || 0; this.timescale = rt["timescale"]; this.tickcount = rt["tickcount"]; this.execcount = rt["execcount"]; this.start_time = Date.now() - rt["start_time_offset"]; var layout_sid = rt["running_layout"]; if (layout_sid !== this.running_layout.sid) { var changeToLayout = this.getLayoutBySid(layout_sid); if (changeToLayout) this.doChangeLayout(changeToLayout); else return; // layout that was saved on has gone missing (deleted?) } var i, len, j, lenj, k, lenk, p, type, existing_insts, load_insts, inst, binst, layout, layer, g, iid, t; var otypes = o["types"]; for (p in otypes) { if (otypes.hasOwnProperty(p)) { type = this.getObjectTypeBySid(parseInt(p, 10)); if (!type || type.is_family || this.typeHasNoSaveBehavior(type)) continue; if (otypes[p]["ex"]) type.extra = otypes[p]["ex"]; else cr.wipe(type.extra); existing_insts = type.instances; load_insts = otypes[p]["instances"]; for (i = 0, len = cr.min(existing_insts.length, load_insts.length); i < len; i++) { this.loadInstanceFromJSON(existing_insts[i], load_insts[i]); } for (i = load_insts.length, len = existing_insts.length; i < len; i++) this.DestroyInstance(existing_insts[i]); for (i = existing_insts.length, len = load_insts.length; i < len; i++) { layer = null; if (type.plugin.is_world) { layer = this.running_layout.getLayerBySid(load_insts[i]["w"]["l"]); if (!layer) continue; } inst = this.createInstanceFromInit(type.default_instance, layer, false, 0, 0, true); this.loadInstanceFromJSON(inst, load_insts[i]); } type.stale_iids = true; } } this.ClearDeathRow(); this.refreshUidMap(); var olayouts = o["layouts"]; for (p in olayouts) { if (olayouts.hasOwnProperty(p)) { layout = this.getLayoutBySid(parseInt(p, 10)); if (!layout) continue; // must've gone missing layout.loadFromJSON(olayouts[p]); } } var ogroups = o["events"]["groups"]; for (p in ogroups) { if (ogroups.hasOwnProperty(p)) { g = this.getGroupBySid(parseInt(p, 10)); if (g && this.groups_by_name[g.group_name]) this.groups_by_name[g.group_name].setGroupActive(ogroups[p]); } } var ocnds = o["events"]["cnds"]; for (p in this.cndsBySid) { if (this.cndsBySid.hasOwnProperty(p)) { if (ocnds.hasOwnProperty(p)) { this.cndsBySid[p].extra = ocnds[p]["ex"]; } else { this.cndsBySid[p].extra = {}; } } } var oacts = o["events"]["acts"]; for (p in this.actsBySid) { if (this.actsBySid.hasOwnProperty(p)) { if (oacts.hasOwnProperty(p)) { this.actsBySid[p].extra = oacts[p]["ex"]; } else { this.actsBySid[p].extra = {}; } } } var ovars = o["events"]["vars"]; for (p in ovars) { if (ovars.hasOwnProperty(p) && this.varsBySid.hasOwnProperty(p)) { this.varsBySid[p].data = ovars[p]; } } this.next_uid = rt["next_uid"]; this.isLoadingState = false; for (i = 0, len = this.fireOnCreateAfterLoad.length; i < len; ++i) { inst = this.fireOnCreateAfterLoad[i]; this.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnCreated, inst); } cr.clearArray(this.fireOnCreateAfterLoad); this.system.loadFromJSON(o["system"]); for (i = 0, len = this.types_by_index.length; i < len; i++) { type = this.types_by_index[i]; if (type.is_family || this.typeHasNoSaveBehavior(type)) continue; for (j = 0, lenj = type.instances.length; j < lenj; j++) { inst = type.instances[j]; if (type.is_contained) { iid = inst.get_iid(); cr.clearArray(inst.siblings); for (k = 0, lenk = type.container.length; k < lenk; k++) { t = type.container[k]; if (type === t) continue; ; inst.siblings.push(t.instances[iid]); } } if (inst.afterLoad) inst.afterLoad(); if (inst.behavior_insts) { for (k = 0, lenk = inst.behavior_insts.length; k < lenk; k++) { binst = inst.behavior_insts[k]; if (binst.afterLoad) binst.afterLoad(); } } } } this.redraw = true; return true; }; Runtime.prototype.saveInstanceToJSON = function(inst, state_only) { var i, len, world, behinst, et; var type = inst.type; var plugin = type.plugin; var o = {}; if (state_only) o["c2"] = true; // mark as known json data from Construct 2 else o["uid"] = inst.uid; if (cr.hasAnyOwnProperty(inst.extra)) o["ex"] = CopyExtraObject(inst.extra); if (inst.instance_vars && inst.instance_vars.length) { o["ivs"] = {}; for (i = 0, len = inst.instance_vars.length; i < len; i++) { o["ivs"][inst.type.instvar_sids[i].toString()] = inst.instance_vars[i]; } } if (plugin.is_world) { world = { "x": inst.x, "y": inst.y, "w": inst.width, "h": inst.height, "l": inst.layer.sid, "zi": inst.get_zindex() }; if (inst.angle !== 0) world["a"] = inst.angle; if (inst.opacity !== 1) world["o"] = inst.opacity; if (inst.hotspotX !== 0.5) world["hX"] = inst.hotspotX; if (inst.hotspotY !== 0.5) world["hY"] = inst.hotspotY; if (inst.blend_mode !== 0) world["bm"] = inst.blend_mode; if (!inst.visible) world["v"] = inst.visible; if (!inst.collisionsEnabled) world["ce"] = inst.collisionsEnabled; if (inst.my_timescale !== -1) world["mts"] = inst.my_timescale; if (type.effect_types.length) { world["fx"] = []; for (i = 0, len = type.effect_types.length; i < len; i++) { et = type.effect_types[i]; world["fx"].push({"name": et.name, "active": inst.active_effect_flags[et.index], "params": inst.effect_params[et.index] }); } } o["w"] = world; } if (inst.behavior_insts && inst.behavior_insts.length) { o["behs"] = {}; for (i = 0, len = inst.behavior_insts.length; i < len; i++) { behinst = inst.behavior_insts[i]; if (behinst.saveToJSON) o["behs"][behinst.type.sid.toString()] = behinst.saveToJSON(); } } if (inst.saveToJSON) o["data"] = inst.saveToJSON(); return o; }; Runtime.prototype.getInstanceVarIndexBySid = function (type, sid_) { var i, len; for (i = 0, len = type.instvar_sids.length; i < len; i++) { if (type.instvar_sids[i] === sid_) return i; } return -1; }; Runtime.prototype.getBehaviorIndexBySid = function (inst, sid_) { var i, len; for (i = 0, len = inst.behavior_insts.length; i < len; i++) { if (inst.behavior_insts[i].type.sid === sid_) return i; } return -1; }; Runtime.prototype.loadInstanceFromJSON = function(inst, o, state_only) { var p, i, len, iv, oivs, world, fxindex, obehs, behindex, value; var oldlayer; var type = inst.type; var plugin = type.plugin; if (state_only) { if (!o["c2"]) return; } else inst.uid = o["uid"]; if (o["ex"]) inst.extra = o["ex"]; else cr.wipe(inst.extra); oivs = o["ivs"]; if (oivs) { for (p in oivs) { if (oivs.hasOwnProperty(p)) { iv = this.getInstanceVarIndexBySid(type, parseInt(p, 10)); if (iv < 0 || iv >= inst.instance_vars.length) continue; // must've gone missing value = oivs[p]; if (value === null) value = NaN; inst.instance_vars[iv] = value; } } } if (plugin.is_world) { world = o["w"]; if (inst.layer.sid !== world["l"]) { oldlayer = inst.layer; inst.layer = this.running_layout.getLayerBySid(world["l"]); if (inst.layer) { oldlayer.removeFromInstanceList(inst, true); inst.layer.appendToInstanceList(inst, true); inst.set_bbox_changed(); inst.layer.setZIndicesStaleFrom(0); } else { inst.layer = oldlayer; if (!state_only) this.DestroyInstance(inst); } } inst.x = world["x"]; inst.y = world["y"]; inst.width = world["w"]; inst.height = world["h"]; inst.zindex = world["zi"]; inst.angle = world.hasOwnProperty("a") ? world["a"] : 0; inst.opacity = world.hasOwnProperty("o") ? world["o"] : 1; inst.hotspotX = world.hasOwnProperty("hX") ? world["hX"] : 0.5; inst.hotspotY = world.hasOwnProperty("hY") ? world["hY"] : 0.5; inst.visible = world.hasOwnProperty("v") ? world["v"] : true; inst.collisionsEnabled = world.hasOwnProperty("ce") ? world["ce"] : true; inst.my_timescale = world.hasOwnProperty("mts") ? world["mts"] : -1; inst.blend_mode = world.hasOwnProperty("bm") ? world["bm"] : 0;; inst.compositeOp = cr.effectToCompositeOp(inst.blend_mode); if (this.gl) cr.setGLBlend(inst, inst.blend_mode, this.gl); inst.set_bbox_changed(); if (world.hasOwnProperty("fx")) { for (i = 0, len = world["fx"].length; i < len; i++) { fxindex = type.getEffectIndexByName(world["fx"][i]["name"]); if (fxindex < 0) continue; // must've gone missing inst.active_effect_flags[fxindex] = world["fx"][i]["active"]; inst.effect_params[fxindex] = world["fx"][i]["params"]; } } inst.updateActiveEffects(); } obehs = o["behs"]; if (obehs) { for (p in obehs) { if (obehs.hasOwnProperty(p)) { behindex = this.getBehaviorIndexBySid(inst, parseInt(p, 10)); if (behindex < 0) continue; // must've gone missing inst.behavior_insts[behindex].loadFromJSON(obehs[p]); } } } if (o["data"]) inst.loadFromJSON(o["data"]); }; Runtime.prototype.fetchLocalFileViaCordova = function (filename, successCallback, errorCallback) { var path = cordova["file"]["applicationDirectory"] + "www/" + filename; window["resolveLocalFileSystemURL"](path, function (entry) { entry.file(successCallback, errorCallback); }, errorCallback); }; Runtime.prototype.fetchLocalFileViaCordovaAsText = function (filename, successCallback, errorCallback) { this.fetchLocalFileViaCordova(filename, function (file) { var reader = new FileReader(); reader.onload = function (e) { successCallback(e.target.result); }; reader.onerror = errorCallback; reader.readAsText(file); }, errorCallback); }; var queuedArrayBufferReads = []; var activeArrayBufferReads = 0; var MAX_ARRAYBUFFER_READS = 8; Runtime.prototype.maybeStartNextArrayBufferRead = function() { if (!queuedArrayBufferReads.length) return; // none left if (activeArrayBufferReads >= MAX_ARRAYBUFFER_READS) return; // already got maximum number in-flight activeArrayBufferReads++; var job = queuedArrayBufferReads.shift(); this.doFetchLocalFileViaCordovaAsArrayBuffer(job.filename, job.successCallback, job.errorCallback); }; Runtime.prototype.fetchLocalFileViaCordovaAsArrayBuffer = function (filename, successCallback_, errorCallback_) { var self = this; queuedArrayBufferReads.push({ filename: filename, successCallback: function (result) { activeArrayBufferReads--; self.maybeStartNextArrayBufferRead(); successCallback_(result); }, errorCallback: function (err) { activeArrayBufferReads--; self.maybeStartNextArrayBufferRead(); errorCallback_(err); } }); this.maybeStartNextArrayBufferRead(); }; Runtime.prototype.doFetchLocalFileViaCordovaAsArrayBuffer = function (filename, successCallback, errorCallback) { this.fetchLocalFileViaCordova(filename, function (file) { var reader = new FileReader(); reader.onload = function (e) { successCallback(e.target.result); }; reader.readAsArrayBuffer(file); }, errorCallback); }; Runtime.prototype.fetchLocalFileViaCordovaAsURL = function (filename, successCallback, errorCallback) { var blobType = ""; var lowername = filename.toLowerCase(); var ext3 = lowername.substr(lowername.length - 4); var ext4 = lowername.substr(lowername.length - 5); if (ext3 === ".mp4") blobType = "video/mp4"; else if (ext4 === ".webm") blobType = "video/webm"; // use video type but hopefully works with audio too else if (ext3 === ".m4a") blobType = "audio/mp4"; else if (ext3 === ".mp3") blobType = "audio/mpeg"; this.fetchLocalFileViaCordovaAsArrayBuffer(filename, function (arrayBuffer) { var blob = new Blob([arrayBuffer], { type: blobType }); var url = URL.createObjectURL(blob); successCallback(url); }, errorCallback); }; Runtime.prototype.isAbsoluteUrl = function (url) { return /^(?:[a-z]+:)?\/\//.test(url) || url.substr(0, 5) === "data:" || url.substr(0, 5) === "blob:"; }; Runtime.prototype.setImageSrc = function (img, src) { if (this.isWKWebView && !this.isAbsoluteUrl(src)) { this.fetchLocalFileViaCordovaAsURL(src, function (url) { img.src = url; }, function (err) { alert("Failed to load image: " + err); }); } else { img.src = src; } }; Runtime.prototype.setCtxImageSmoothingEnabled = function (ctx, e) { if (typeof ctx["imageSmoothingEnabled"] !== "undefined") { ctx["imageSmoothingEnabled"] = e; } else { ctx["webkitImageSmoothingEnabled"] = e; ctx["mozImageSmoothingEnabled"] = e; ctx["msImageSmoothingEnabled"] = e; } }; cr.runtime = Runtime; cr.createRuntime = function (canvasid) { return new Runtime(document.getElementById(canvasid)); }; cr.createDCRuntime = function (w, h) { return new Runtime({ "dc": true, "width": w, "height": h }); }; window["cr_createRuntime"] = cr.createRuntime; window["cr_createDCRuntime"] = cr.createDCRuntime; window["createCocoonJSRuntime"] = function () { window["c2cocoonjs"] = true; var canvas = document.createElement("screencanvas") || document.createElement("canvas"); canvas.screencanvas = true; document.body.appendChild(canvas); var rt = new Runtime(canvas); window["c2runtime"] = rt; window.addEventListener("orientationchange", function () { window["c2runtime"]["setSize"](window.innerWidth, window.innerHeight); }); window["c2runtime"]["setSize"](window.innerWidth, window.innerHeight); return rt; }; window["createEjectaRuntime"] = function () { var canvas = document.getElementById("canvas"); var rt = new Runtime(canvas); window["c2runtime"] = rt; window["c2runtime"]["setSize"](window.innerWidth, window.innerHeight); return rt; }; }()); window["cr_getC2Runtime"] = function() { var canvas = document.getElementById("c2canvas"); if (canvas) return canvas["c2runtime"]; else if (window["c2runtime"]) return window["c2runtime"]; else return null; } window["cr_getSnapshot"] = function (format_, quality_) { var runtime = window["cr_getC2Runtime"](); if (runtime) runtime.doCanvasSnapshot(format_, quality_); } window["cr_sizeCanvas"] = function(w, h) { if (w === 0 || h === 0) return; var runtime = window["cr_getC2Runtime"](); if (runtime) runtime["setSize"](w, h); } window["cr_setSuspended"] = function(s) { var runtime = window["cr_getC2Runtime"](); if (runtime) runtime["setSuspended"](s); } ; (function() { function Layout(runtime, m) { this.runtime = runtime; this.event_sheet = null; this.scrollX = (this.runtime.original_width / 2); this.scrollY = (this.runtime.original_height / 2); this.scale = 1.0; this.angle = 0; this.first_visit = true; this.name = m[0]; this.originalWidth = m[1]; this.originalHeight = m[2]; this.width = m[1]; this.height = m[2]; this.unbounded_scrolling = m[3]; this.sheetname = m[4]; this.sid = m[5]; var lm = m[6]; var i, len; this.layers = []; this.initial_types = []; for (i = 0, len = lm.length; i < len; i++) { var layer = new cr.layer(this, lm[i]); layer.number = i; cr.seal(layer); this.layers.push(layer); } var im = m[7]; this.initial_nonworld = []; for (i = 0, len = im.length; i < len; i++) { var inst = im[i]; var type = this.runtime.types_by_index[inst[1]]; ; if (!type.default_instance) type.default_instance = inst; this.initial_nonworld.push(inst); if (this.initial_types.indexOf(type) === -1) this.initial_types.push(type); } this.effect_types = []; this.active_effect_types = []; this.shaders_preserve_opaqueness = true; this.effect_params = []; for (i = 0, len = m[8].length; i < len; i++) { this.effect_types.push({ id: m[8][i][0], name: m[8][i][1], shaderindex: -1, preservesOpaqueness: false, active: true, index: i }); this.effect_params.push(m[8][i][2].slice(0)); } this.updateActiveEffects(); this.rcTex = new cr.rect(0, 0, 1, 1); this.rcTex2 = new cr.rect(0, 0, 1, 1); this.persist_data = {}; }; Layout.prototype.saveObjectToPersist = function (inst) { var sidStr = inst.type.sid.toString(); if (!this.persist_data.hasOwnProperty(sidStr)) this.persist_data[sidStr] = []; var type_persist = this.persist_data[sidStr]; type_persist.push(this.runtime.saveInstanceToJSON(inst)); }; Layout.prototype.hasOpaqueBottomLayer = function () { var layer = this.layers[0]; return !layer.transparent && layer.opacity === 1.0 && !layer.forceOwnTexture && layer.visible; }; Layout.prototype.updateActiveEffects = function () { cr.clearArray(this.active_effect_types); this.shaders_preserve_opaqueness = true; var i, len, et; for (i = 0, len = this.effect_types.length; i < len; i++) { et = this.effect_types[i]; if (et.active) { this.active_effect_types.push(et); if (!et.preservesOpaqueness) this.shaders_preserve_opaqueness = false; } } }; Layout.prototype.getEffectByName = function (name_) { var i, len, et; for (i = 0, len = this.effect_types.length; i < len; i++) { et = this.effect_types[i]; if (et.name === name_) return et; } return null; }; var created_instances = []; function sort_by_zindex(a, b) { return a.zindex - b.zindex; }; var first_layout = true; Layout.prototype.startRunning = function () { if (this.sheetname) { this.event_sheet = this.runtime.eventsheets[this.sheetname]; ; this.event_sheet.updateDeepIncludes(); } this.runtime.running_layout = this; this.width = this.originalWidth; this.height = this.originalHeight; this.scrollX = (this.runtime.original_width / 2); this.scrollY = (this.runtime.original_height / 2); var i, k, len, lenk, type, type_instances, initial_inst, inst, iid, t, s, p, q, type_data, layer; for (i = 0, len = this.runtime.types_by_index.length; i < len; i++) { type = this.runtime.types_by_index[i]; if (type.is_family) continue; // instances are only transferred for their real type type_instances = type.instances; for (k = 0, lenk = type_instances.length; k < lenk; k++) { inst = type_instances[k]; if (inst.layer) { var num = inst.layer.number; if (num >= this.layers.length) num = this.layers.length - 1; inst.layer = this.layers[num]; if (inst.layer.instances.indexOf(inst) === -1) inst.layer.instances.push(inst); inst.layer.zindices_stale = true; } } } if (!first_layout) { for (i = 0, len = this.layers.length; i < len; ++i) { this.layers[i].instances.sort(sort_by_zindex); } } var layer; cr.clearArray(created_instances); this.boundScrolling(); for (i = 0, len = this.layers.length; i < len; i++) { layer = this.layers[i]; layer.createInitialInstances(); // fills created_instances layer.updateViewport(null); } var uids_changed = false; if (!this.first_visit) { for (p in this.persist_data) { if (this.persist_data.hasOwnProperty(p)) { type = this.runtime.getObjectTypeBySid(parseInt(p, 10)); if (!type || type.is_family || !this.runtime.typeHasPersistBehavior(type)) continue; type_data = this.persist_data[p]; for (i = 0, len = type_data.length; i < len; i++) { layer = null; if (type.plugin.is_world) { layer = this.getLayerBySid(type_data[i]["w"]["l"]); if (!layer) continue; } inst = this.runtime.createInstanceFromInit(type.default_instance, layer, false, 0, 0, true); this.runtime.loadInstanceFromJSON(inst, type_data[i]); uids_changed = true; created_instances.push(inst); } cr.clearArray(type_data); } } for (i = 0, len = this.layers.length; i < len; i++) { this.layers[i].instances.sort(sort_by_zindex); this.layers[i].zindices_stale = true; // in case of duplicates/holes } } if (uids_changed) { this.runtime.ClearDeathRow(); this.runtime.refreshUidMap(); } for (i = 0; i < created_instances.length; i++) { inst = created_instances[i]; if (!inst.type.is_contained) continue; iid = inst.get_iid(); for (k = 0, lenk = inst.type.container.length; k < lenk; k++) { t = inst.type.container[k]; if (inst.type === t) continue; if (t.instances.length > iid) inst.siblings.push(t.instances[iid]); else { if (!t.default_instance) { } else { s = this.runtime.createInstanceFromInit(t.default_instance, inst.layer, true, inst.x, inst.y, true); this.runtime.ClearDeathRow(); t.updateIIDs(); inst.siblings.push(s); created_instances.push(s); // come back around and link up its own instances too } } } } for (i = 0, len = this.initial_nonworld.length; i < len; i++) { initial_inst = this.initial_nonworld[i]; type = this.runtime.types_by_index[initial_inst[1]]; if (!type.is_contained) { inst = this.runtime.createInstanceFromInit(this.initial_nonworld[i], null, true); } ; } this.runtime.changelayout = null; this.runtime.ClearDeathRow(); if (this.runtime.ctx && !this.runtime.isDomFree) { for (i = 0, len = this.runtime.types_by_index.length; i < len; i++) { t = this.runtime.types_by_index[i]; if (t.is_family || !t.instances.length || !t.preloadCanvas2D) continue; t.preloadCanvas2D(this.runtime.ctx); } } /* if (this.runtime.glwrap) { console.log("Estimated VRAM at layout start: " + this.runtime.glwrap.textureCount() + " textures, approx. " + Math.round(this.runtime.glwrap.estimateVRAM() / 1024) + " kb"); } */ if (this.runtime.isLoadingState) { cr.shallowAssignArray(this.runtime.fireOnCreateAfterLoad, created_instances); } else { for (i = 0, len = created_instances.length; i < len; i++) { inst = created_instances[i]; this.runtime.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnCreated, inst); } } cr.clearArray(created_instances); if (!this.runtime.isLoadingState) { this.runtime.trigger(cr.system_object.prototype.cnds.OnLayoutStart, null); } this.first_visit = false; }; Layout.prototype.createGlobalNonWorlds = function () { var i, k, len, initial_inst, inst, type; for (i = 0, k = 0, len = this.initial_nonworld.length; i < len; i++) { initial_inst = this.initial_nonworld[i]; type = this.runtime.types_by_index[initial_inst[1]]; if (type.global) { if (!type.is_contained) { inst = this.runtime.createInstanceFromInit(initial_inst, null, true); } } else { this.initial_nonworld[k] = initial_inst; k++; } } cr.truncateArray(this.initial_nonworld, k); }; Layout.prototype.stopRunning = function () { ; /* if (this.runtime.glwrap) { console.log("Estimated VRAM at layout end: " + this.runtime.glwrap.textureCount() + " textures, approx. " + Math.round(this.runtime.glwrap.estimateVRAM() / 1024) + " kb"); } */ if (!this.runtime.isLoadingState) { this.runtime.trigger(cr.system_object.prototype.cnds.OnLayoutEnd, null); } this.runtime.isEndingLayout = true; cr.clearArray(this.runtime.system.waits); var i, leni, j, lenj; var layer_instances, inst, type; if (!this.first_visit) { for (i = 0, leni = this.layers.length; i < leni; i++) { this.layers[i].updateZIndices(); layer_instances = this.layers[i].instances; for (j = 0, lenj = layer_instances.length; j < lenj; j++) { inst = layer_instances[j]; if (!inst.type.global) { if (this.runtime.typeHasPersistBehavior(inst.type)) this.saveObjectToPersist(inst); } } } } for (i = 0, leni = this.layers.length; i < leni; i++) { layer_instances = this.layers[i].instances; for (j = 0, lenj = layer_instances.length; j < lenj; j++) { inst = layer_instances[j]; if (!inst.type.global) { this.runtime.DestroyInstance(inst); } } this.runtime.ClearDeathRow(); cr.clearArray(layer_instances); this.layers[i].zindices_stale = true; } for (i = 0, leni = this.runtime.types_by_index.length; i < leni; i++) { type = this.runtime.types_by_index[i]; if (type.global || type.plugin.is_world || type.plugin.singleglobal || type.is_family) continue; for (j = 0, lenj = type.instances.length; j < lenj; j++) this.runtime.DestroyInstance(type.instances[j]); this.runtime.ClearDeathRow(); } first_layout = false; this.runtime.isEndingLayout = false; }; var temp_rect = new cr.rect(0, 0, 0, 0); Layout.prototype.recreateInitialObjects = function (type, x1, y1, x2, y2) { temp_rect.set(x1, y1, x2, y2); var i, len; for (i = 0, len = this.layers.length; i < len; i++) { this.layers[i].recreateInitialObjects(type, temp_rect); } }; Layout.prototype.draw = function (ctx) { var layout_canvas; var layout_ctx = ctx; var ctx_changed = false; var render_offscreen = !this.runtime.fullscreenScalingQuality; if (render_offscreen) { if (!this.runtime.layout_canvas) { this.runtime.layout_canvas = document.createElement("canvas"); layout_canvas = this.runtime.layout_canvas; layout_canvas.width = this.runtime.draw_width; layout_canvas.height = this.runtime.draw_height; this.runtime.layout_ctx = layout_canvas.getContext("2d"); ctx_changed = true; } layout_canvas = this.runtime.layout_canvas; layout_ctx = this.runtime.layout_ctx; if (layout_canvas.width !== this.runtime.draw_width) { layout_canvas.width = this.runtime.draw_width; ctx_changed = true; } if (layout_canvas.height !== this.runtime.draw_height) { layout_canvas.height = this.runtime.draw_height; ctx_changed = true; } if (ctx_changed) { this.runtime.setCtxImageSmoothingEnabled(layout_ctx, this.runtime.linearSampling); } } layout_ctx.globalAlpha = 1; layout_ctx.globalCompositeOperation = "source-over"; if (this.runtime.clearBackground && !this.hasOpaqueBottomLayer()) layout_ctx.clearRect(0, 0, this.runtime.draw_width, this.runtime.draw_height); var i, len, l; for (i = 0, len = this.layers.length; i < len; i++) { l = this.layers[i]; if (l.visible && l.opacity > 0 && l.blend_mode !== 11 && (l.instances.length || !l.transparent)) l.draw(layout_ctx); else l.updateViewport(null); // even if not drawing, keep viewport up to date } if (render_offscreen) { ctx.drawImage(layout_canvas, 0, 0, this.runtime.width, this.runtime.height); } }; Layout.prototype.drawGL_earlyZPass = function (glw) { glw.setEarlyZPass(true); if (!this.runtime.layout_tex) { this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } if (this.runtime.layout_tex.c2width !== this.runtime.draw_width || this.runtime.layout_tex.c2height !== this.runtime.draw_height) { glw.deleteTexture(this.runtime.layout_tex); this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } glw.setRenderingToTexture(this.runtime.layout_tex); if (!this.runtime.fullscreenScalingQuality) { glw.setSize(this.runtime.draw_width, this.runtime.draw_height); } var i, l; for (i = this.layers.length - 1; i >= 0; --i) { l = this.layers[i]; if (l.visible && l.opacity === 1 && l.shaders_preserve_opaqueness && l.blend_mode === 0 && (l.instances.length || !l.transparent)) { l.drawGL_earlyZPass(glw); } else { l.updateViewport(null); // even if not drawing, keep viewport up to date } } glw.setEarlyZPass(false); }; Layout.prototype.drawGL = function (glw) { var render_to_texture = (this.active_effect_types.length > 0 || this.runtime.uses_background_blending || !this.runtime.fullscreenScalingQuality || this.runtime.enableFrontToBack); if (render_to_texture) { if (!this.runtime.layout_tex) { this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } if (this.runtime.layout_tex.c2width !== this.runtime.draw_width || this.runtime.layout_tex.c2height !== this.runtime.draw_height) { glw.deleteTexture(this.runtime.layout_tex); this.runtime.layout_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } glw.setRenderingToTexture(this.runtime.layout_tex); if (!this.runtime.fullscreenScalingQuality) { glw.setSize(this.runtime.draw_width, this.runtime.draw_height); } } else { if (this.runtime.layout_tex) { glw.setRenderingToTexture(null); glw.deleteTexture(this.runtime.layout_tex); this.runtime.layout_tex = null; } } if (this.runtime.clearBackground && !this.hasOpaqueBottomLayer()) glw.clear(0, 0, 0, 0); var i, len, l; for (i = 0, len = this.layers.length; i < len; i++) { l = this.layers[i]; if (l.visible && l.opacity > 0 && (l.instances.length || !l.transparent)) l.drawGL(glw); else l.updateViewport(null); // even if not drawing, keep viewport up to date } if (render_to_texture) { if (this.active_effect_types.length === 0 || (this.active_effect_types.length === 1 && this.runtime.fullscreenScalingQuality)) { if (this.active_effect_types.length === 1) { var etindex = this.active_effect_types[0].index; glw.switchProgram(this.active_effect_types[0].shaderindex); glw.setProgramParameters(null, // backTex 1.0 / this.runtime.draw_width, // pixelWidth 1.0 / this.runtime.draw_height, // pixelHeight 0.0, 0.0, // destStart 1.0, 1.0, // destEnd this.scale, // layerScale this.angle, // layerAngle 0.0, 0.0, // viewOrigin this.runtime.draw_width / 2, this.runtime.draw_height / 2, // scrollPos this.runtime.kahanTime.sum, // seconds this.effect_params[etindex]); // fx parameters if (glw.programIsAnimated(this.active_effect_types[0].shaderindex)) this.runtime.redraw = true; } else glw.switchProgram(0); if (!this.runtime.fullscreenScalingQuality) { glw.setSize(this.runtime.width, this.runtime.height); } glw.setRenderingToTexture(null); // to backbuffer glw.setDepthTestEnabled(false); // ignore depth buffer, copy full texture glw.setOpacity(1); glw.setTexture(this.runtime.layout_tex); glw.setAlphaBlend(); glw.resetModelView(); glw.updateModelView(); var halfw = this.runtime.width / 2; var halfh = this.runtime.height / 2; glw.quad(-halfw, halfh, halfw, halfh, halfw, -halfh, -halfw, -halfh); glw.setTexture(null); glw.setDepthTestEnabled(true); // turn depth test back on } else { this.renderEffectChain(glw, null, null, null); } } }; Layout.prototype.getRenderTarget = function() { if (this.active_effect_types.length > 0 || this.runtime.uses_background_blending || !this.runtime.fullscreenScalingQuality || this.runtime.enableFrontToBack) { return this.runtime.layout_tex; } else { return null; } }; Layout.prototype.getMinLayerScale = function () { var m = this.layers[0].getScale(); var i, len, l; for (i = 1, len = this.layers.length; i < len; i++) { l = this.layers[i]; if (l.parallaxX === 0 && l.parallaxY === 0) continue; if (l.getScale() < m) m = l.getScale(); } return m; }; Layout.prototype.scrollToX = function (x) { if (!this.unbounded_scrolling) { var widthBoundary = (this.runtime.draw_width * (1 / this.getMinLayerScale()) / 2); if (x > this.width - widthBoundary) x = this.width - widthBoundary; if (x < widthBoundary) x = widthBoundary; } if (this.scrollX !== x) { this.scrollX = x; this.runtime.redraw = true; } }; Layout.prototype.scrollToY = function (y) { if (!this.unbounded_scrolling) { var heightBoundary = (this.runtime.draw_height * (1 / this.getMinLayerScale()) / 2); if (y > this.height - heightBoundary) y = this.height - heightBoundary; if (y < heightBoundary) y = heightBoundary; } if (this.scrollY !== y) { this.scrollY = y; this.runtime.redraw = true; } }; Layout.prototype.boundScrolling = function () { this.scrollToX(this.scrollX); this.scrollToY(this.scrollY); }; Layout.prototype.renderEffectChain = function (glw, layer, inst, rendertarget) { var active_effect_types = inst ? inst.active_effect_types : layer ? layer.active_effect_types : this.active_effect_types; var layerScale = 1, layerAngle = 0, viewOriginLeft = 0, viewOriginTop = 0, viewOriginRight = this.runtime.draw_width, viewOriginBottom = this.runtime.draw_height; if (inst) { layerScale = inst.layer.getScale(); layerAngle = inst.layer.getAngle(); viewOriginLeft = inst.layer.viewLeft; viewOriginTop = inst.layer.viewTop; viewOriginRight = inst.layer.viewRight; viewOriginBottom = inst.layer.viewBottom; } else if (layer) { layerScale = layer.getScale(); layerAngle = layer.getAngle(); viewOriginLeft = layer.viewLeft; viewOriginTop = layer.viewTop; viewOriginRight = layer.viewRight; viewOriginBottom = layer.viewBottom; } var fx_tex = this.runtime.fx_tex; var i, len, last, temp, fx_index = 0, other_fx_index = 1; var y, h; var windowWidth = this.runtime.draw_width; var windowHeight = this.runtime.draw_height; var halfw = windowWidth / 2; var halfh = windowHeight / 2; var rcTex = layer ? layer.rcTex : this.rcTex; var rcTex2 = layer ? layer.rcTex2 : this.rcTex2; var screenleft = 0, clearleft = 0; var screentop = 0, cleartop = 0; var screenright = windowWidth, clearright = windowWidth; var screenbottom = windowHeight, clearbottom = windowHeight; var boxExtendHorizontal = 0; var boxExtendVertical = 0; var inst_layer_angle = inst ? inst.layer.getAngle() : 0; if (inst) { for (i = 0, len = active_effect_types.length; i < len; i++) { boxExtendHorizontal += glw.getProgramBoxExtendHorizontal(active_effect_types[i].shaderindex); boxExtendVertical += glw.getProgramBoxExtendVertical(active_effect_types[i].shaderindex); } var bbox = inst.bbox; screenleft = layer.layerToCanvas(bbox.left, bbox.top, true, true); screentop = layer.layerToCanvas(bbox.left, bbox.top, false, true); screenright = layer.layerToCanvas(bbox.right, bbox.bottom, true, true); screenbottom = layer.layerToCanvas(bbox.right, bbox.bottom, false, true); if (inst_layer_angle !== 0) { var screentrx = layer.layerToCanvas(bbox.right, bbox.top, true, true); var screentry = layer.layerToCanvas(bbox.right, bbox.top, false, true); var screenblx = layer.layerToCanvas(bbox.left, bbox.bottom, true, true); var screenbly = layer.layerToCanvas(bbox.left, bbox.bottom, false, true); temp = Math.min(screenleft, screenright, screentrx, screenblx); screenright = Math.max(screenleft, screenright, screentrx, screenblx); screenleft = temp; temp = Math.min(screentop, screenbottom, screentry, screenbly); screenbottom = Math.max(screentop, screenbottom, screentry, screenbly); screentop = temp; } screenleft -= boxExtendHorizontal; screentop -= boxExtendVertical; screenright += boxExtendHorizontal; screenbottom += boxExtendVertical; rcTex2.left = screenleft / windowWidth; rcTex2.top = 1 - screentop / windowHeight; rcTex2.right = screenright / windowWidth; rcTex2.bottom = 1 - screenbottom / windowHeight; clearleft = screenleft = cr.floor(screenleft); cleartop = screentop = cr.floor(screentop); clearright = screenright = cr.ceil(screenright); clearbottom = screenbottom = cr.ceil(screenbottom); clearleft -= boxExtendHorizontal; cleartop -= boxExtendVertical; clearright += boxExtendHorizontal; clearbottom += boxExtendVertical; if (screenleft < 0) screenleft = 0; if (screentop < 0) screentop = 0; if (screenright > windowWidth) screenright = windowWidth; if (screenbottom > windowHeight) screenbottom = windowHeight; if (clearleft < 0) clearleft = 0; if (cleartop < 0) cleartop = 0; if (clearright > windowWidth) clearright = windowWidth; if (clearbottom > windowHeight) clearbottom = windowHeight; rcTex.left = screenleft / windowWidth; rcTex.top = 1 - screentop / windowHeight; rcTex.right = screenright / windowWidth; rcTex.bottom = 1 - screenbottom / windowHeight; } else { rcTex.left = rcTex2.left = 0; rcTex.top = rcTex2.top = 0; rcTex.right = rcTex2.right = 1; rcTex.bottom = rcTex2.bottom = 1; } 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); glw.setAlphaBlend(); if (pre_draw) { if (!fx_tex[fx_index]) { fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling); } if (fx_tex[fx_index].c2width !== windowWidth || fx_tex[fx_index].c2height !== windowHeight) { glw.deleteTexture(fx_tex[fx_index]); fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling); } glw.switchProgram(0); glw.setRenderingToTexture(fx_tex[fx_index]); h = clearbottom - cleartop; y = (windowHeight - cleartop) - h; glw.clearRect(clearleft, y, clearright - clearleft, h); if (inst) { inst.drawGL(glw); } else { glw.setTexture(this.runtime.layer_tex); glw.setOpacity(layer.opacity); glw.resetModelView(); glw.translate(-halfw, -halfh); glw.updateModelView(); glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex); } rcTex2.left = rcTex2.top = 0; rcTex2.right = rcTex2.bottom = 1; if (inst) { temp = rcTex.top; rcTex.top = rcTex.bottom; rcTex.bottom = temp; } fx_index = 1; other_fx_index = 0; } glw.setOpacity(1); var last = active_effect_types.length - 1; var post_draw = glw.programUsesCrossSampling(active_effect_types[last].shaderindex) || (!layer && !inst && !this.runtime.fullscreenScalingQuality); var etindex = 0; for (i = 0, len = active_effect_types.length; i < len; i++) { if (!fx_tex[fx_index]) { fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling); } if (fx_tex[fx_index].c2width !== windowWidth || fx_tex[fx_index].c2height !== windowHeight) { glw.deleteTexture(fx_tex[fx_index]); fx_tex[fx_index] = glw.createEmptyTexture(windowWidth, windowHeight, this.runtime.linearSampling); } glw.switchProgram(active_effect_types[i].shaderindex); etindex = active_effect_types[i].index; if (glw.programIsAnimated(active_effect_types[i].shaderindex)) this.runtime.redraw = true; if (i == 0 && !pre_draw) { glw.setRenderingToTexture(fx_tex[fx_index]); h = clearbottom - cleartop; y = (windowHeight - cleartop) - h; glw.clearRect(clearleft, y, clearright - clearleft, h); if (inst) { var pixelWidth; var pixelHeight; if (inst.curFrame && inst.curFrame.texture_img) { var img = inst.curFrame.texture_img; pixelWidth = 1.0 / img.width; pixelHeight = 1.0 / img.height; } else { pixelWidth = 1.0 / inst.width; pixelHeight = 1.0 / inst.height; } glw.setProgramParameters(rendertarget, // backTex pixelWidth, pixelHeight, rcTex2.left, rcTex2.top, // destStart rcTex2.right, rcTex2.bottom, // destEnd layerScale, layerAngle, viewOriginLeft, viewOriginTop, (viewOriginLeft + viewOriginRight) / 2, (viewOriginTop + viewOriginBottom) / 2, this.runtime.kahanTime.sum, inst.effect_params[etindex]); // fx params inst.drawGL(glw); } else { glw.setProgramParameters(rendertarget, // backTex 1.0 / windowWidth, // pixelWidth 1.0 / windowHeight, // pixelHeight 0.0, 0.0, // destStart 1.0, 1.0, // destEnd layerScale, layerAngle, viewOriginLeft, viewOriginTop, (viewOriginLeft + viewOriginRight) / 2, (viewOriginTop + viewOriginBottom) / 2, this.runtime.kahanTime.sum, layer ? // fx params layer.effect_params[etindex] : this.effect_params[etindex]); glw.setTexture(layer ? this.runtime.layer_tex : this.runtime.layout_tex); glw.resetModelView(); glw.translate(-halfw, -halfh); glw.updateModelView(); glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex); } rcTex2.left = rcTex2.top = 0; rcTex2.right = rcTex2.bottom = 1; if (inst && !post_draw) { temp = screenbottom; screenbottom = screentop; screentop = temp; } } else { glw.setProgramParameters(rendertarget, // backTex 1.0 / windowWidth, // pixelWidth 1.0 / windowHeight, // pixelHeight rcTex2.left, rcTex2.top, // destStart rcTex2.right, rcTex2.bottom, // destEnd layerScale, layerAngle, viewOriginLeft, viewOriginTop, (viewOriginLeft + viewOriginRight) / 2, (viewOriginTop + viewOriginBottom) / 2, this.runtime.kahanTime.sum, inst ? // fx params inst.effect_params[etindex] : layer ? layer.effect_params[etindex] : this.effect_params[etindex]); glw.setTexture(null); if (i === last && !post_draw) { if (inst) glw.setBlend(inst.srcBlend, inst.destBlend); else if (layer) glw.setBlend(layer.srcBlend, layer.destBlend); glw.setRenderingToTexture(rendertarget); } else { glw.setRenderingToTexture(fx_tex[fx_index]); h = clearbottom - cleartop; y = (windowHeight - cleartop) - h; glw.clearRect(clearleft, y, clearright - clearleft, h); } glw.setTexture(fx_tex[other_fx_index]); glw.resetModelView(); glw.translate(-halfw, -halfh); glw.updateModelView(); glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex); if (i === last && !post_draw) glw.setTexture(null); } fx_index = (fx_index === 0 ? 1 : 0); other_fx_index = (fx_index === 0 ? 1 : 0); // will be opposite to fx_index since it was just assigned } if (post_draw) { glw.switchProgram(0); if (inst) glw.setBlend(inst.srcBlend, inst.destBlend); else if (layer) glw.setBlend(layer.srcBlend, layer.destBlend); else { if (!this.runtime.fullscreenScalingQuality) { glw.setSize(this.runtime.width, this.runtime.height); halfw = this.runtime.width / 2; halfh = this.runtime.height / 2; screenleft = 0; screentop = 0; screenright = this.runtime.width; screenbottom = this.runtime.height; } } glw.setRenderingToTexture(rendertarget); glw.setTexture(fx_tex[other_fx_index]); glw.resetModelView(); glw.translate(-halfw, -halfh); glw.updateModelView(); if (inst && active_effect_types.length === 1 && !pre_draw) glw.quadTex(screenleft, screentop, screenright, screentop, screenright, screenbottom, screenleft, screenbottom, rcTex); else glw.quadTex(screenleft, screenbottom, screenright, screenbottom, screenright, screentop, screenleft, screentop, rcTex); glw.setTexture(null); } }; Layout.prototype.getLayerBySid = function (sid_) { var i, len; for (i = 0, len = this.layers.length; i < len; i++) { if (this.layers[i].sid === sid_) return this.layers[i]; } return null; }; Layout.prototype.saveToJSON = function () { var i, len, layer, et; var o = { "sx": this.scrollX, "sy": this.scrollY, "s": this.scale, "a": this.angle, "w": this.width, "h": this.height, "fv": this.first_visit, // added r127 "persist": this.persist_data, "fx": [], "layers": {} }; for (i = 0, len = this.effect_types.length; i < len; i++) { et = this.effect_types[i]; o["fx"].push({"name": et.name, "active": et.active, "params": this.effect_params[et.index] }); } for (i = 0, len = this.layers.length; i < len; i++) { layer = this.layers[i]; o["layers"][layer.sid.toString()] = layer.saveToJSON(); } return o; }; Layout.prototype.loadFromJSON = function (o) { var i, j, len, fx, p, layer; this.scrollX = o["sx"]; this.scrollY = o["sy"]; this.scale = o["s"]; this.angle = o["a"]; this.width = o["w"]; this.height = o["h"]; this.persist_data = o["persist"]; if (typeof o["fv"] !== "undefined") this.first_visit = o["fv"]; var ofx = o["fx"]; for (i = 0, len = ofx.length; i < len; i++) { fx = this.getEffectByName(ofx[i]["name"]); if (!fx) continue; // must've gone missing fx.active = ofx[i]["active"]; this.effect_params[fx.index] = ofx[i]["params"]; } this.updateActiveEffects(); var olayers = o["layers"]; for (p in olayers) { if (olayers.hasOwnProperty(p)) { layer = this.getLayerBySid(parseInt(p, 10)); if (!layer) continue; // must've gone missing layer.loadFromJSON(olayers[p]); } } }; cr.layout = Layout; function Layer(layout, m) { this.layout = layout; this.runtime = layout.runtime; this.instances = []; // running instances this.scale = 1.0; this.angle = 0; this.disableAngle = false; this.tmprect = new cr.rect(0, 0, 0, 0); this.tmpquad = new cr.quad(); this.viewLeft = 0; this.viewRight = 0; this.viewTop = 0; this.viewBottom = 0; this.zindices_stale = false; this.zindices_stale_from = -1; // first index that has changed, or -1 if no bound this.clear_earlyz_index = 0; this.name = m[0]; this.index = m[1]; this.sid = m[2]; this.visible = m[3]; // initially visible this.background_color = m[4]; this.transparent = m[5]; this.parallaxX = m[6]; this.parallaxY = m[7]; this.opacity = m[8]; this.forceOwnTexture = m[9]; this.useRenderCells = m[10]; this.zoomRate = m[11]; this.blend_mode = m[12]; this.effect_fallback = m[13]; this.compositeOp = "source-over"; this.srcBlend = 0; this.destBlend = 0; this.render_grid = null; this.last_render_list = alloc_arr(); this.render_list_stale = true; this.last_render_cells = new cr.rect(0, 0, -1, -1); this.cur_render_cells = new cr.rect(0, 0, -1, -1); if (this.useRenderCells) { this.render_grid = new cr.RenderGrid(this.runtime.original_width, this.runtime.original_height); } this.render_offscreen = false; var im = m[14]; var i, len; this.startup_initial_instances = []; // for restoring initial_instances after load this.initial_instances = []; this.created_globals = []; // global object UIDs already created - for save/load to avoid recreating for (i = 0, len = im.length; i < len; i++) { var inst = im[i]; var type = this.runtime.types_by_index[inst[1]]; ; if (!type.default_instance) { type.default_instance = inst; type.default_layerindex = this.index; } this.initial_instances.push(inst); if (this.layout.initial_types.indexOf(type) === -1) this.layout.initial_types.push(type); } cr.shallowAssignArray(this.startup_initial_instances, this.initial_instances); this.effect_types = []; this.active_effect_types = []; this.shaders_preserve_opaqueness = true; this.effect_params = []; for (i = 0, len = m[15].length; i < len; i++) { this.effect_types.push({ id: m[15][i][0], name: m[15][i][1], shaderindex: -1, preservesOpaqueness: false, active: true, index: i }); this.effect_params.push(m[15][i][2].slice(0)); } this.updateActiveEffects(); this.rcTex = new cr.rect(0, 0, 1, 1); this.rcTex2 = new cr.rect(0, 0, 1, 1); }; Layer.prototype.updateActiveEffects = function () { cr.clearArray(this.active_effect_types); this.shaders_preserve_opaqueness = true; var i, len, et; for (i = 0, len = this.effect_types.length; i < len; i++) { et = this.effect_types[i]; if (et.active) { this.active_effect_types.push(et); if (!et.preservesOpaqueness) this.shaders_preserve_opaqueness = false; } } }; Layer.prototype.getEffectByName = function (name_) { var i, len, et; for (i = 0, len = this.effect_types.length; i < len; i++) { et = this.effect_types[i]; if (et.name === name_) return et; } return null; }; Layer.prototype.createInitialInstances = function () { var i, k, len, inst, initial_inst, type, keep, hasPersistBehavior; for (i = 0, k = 0, len = this.initial_instances.length; i < len; i++) { initial_inst = this.initial_instances[i]; type = this.runtime.types_by_index[initial_inst[1]]; ; hasPersistBehavior = this.runtime.typeHasPersistBehavior(type); keep = true; if (!hasPersistBehavior || this.layout.first_visit) { inst = this.runtime.createInstanceFromInit(initial_inst, this, true); if (!inst) continue; // may have skipped creation due to fallback effect "destroy" created_instances.push(inst); if (inst.type.global) { keep = false; this.created_globals.push(inst.uid); } } if (keep) { this.initial_instances[k] = this.initial_instances[i]; k++; } } this.initial_instances.length = k; this.runtime.ClearDeathRow(); // flushes creation row so IIDs will be correct if (!this.runtime.glwrap && this.effect_types.length) // no WebGL renderer and shaders used this.blend_mode = this.effect_fallback; // use fallback blend mode this.compositeOp = cr.effectToCompositeOp(this.blend_mode); if (this.runtime.gl) cr.setGLBlend(this, this.blend_mode, this.runtime.gl); this.render_list_stale = true; }; Layer.prototype.recreateInitialObjects = function (only_type, rc) { var i, len, initial_inst, type, wm, x, y, inst, j, lenj, s; var types_by_index = this.runtime.types_by_index; var only_type_is_family = only_type.is_family; var only_type_members = only_type.members; for (i = 0, len = this.initial_instances.length; i < len; ++i) { initial_inst = this.initial_instances[i]; wm = initial_inst[0]; x = wm[0]; y = wm[1]; if (!rc.contains_pt(x, y)) continue; // not in the given area type = types_by_index[initial_inst[1]]; if (type !== only_type) { if (only_type_is_family) { if (only_type_members.indexOf(type) < 0) continue; } else continue; // only_type is not a family, and the initial inst type does not match } inst = this.runtime.createInstanceFromInit(initial_inst, this, false); this.runtime.isInOnDestroy++; this.runtime.trigger(Object.getPrototypeOf(type.plugin).cnds.OnCreated, inst); if (inst.is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[i]; this.runtime.trigger(Object.getPrototypeOf(s.type.plugin).cnds.OnCreated, s); } } this.runtime.isInOnDestroy--; } }; Layer.prototype.removeFromInstanceList = function (inst, remove_from_grid) { var index = cr.fastIndexOf(this.instances, inst); if (index < 0) return; // not found if (remove_from_grid && this.useRenderCells && inst.rendercells && inst.rendercells.right >= inst.rendercells.left) { inst.update_bbox(); // make sure actually in its current rendercells this.render_grid.update(inst, inst.rendercells, null); // no new range provided - remove only inst.rendercells.set(0, 0, -1, -1); // set to invalid state to indicate not inserted } if (index === this.instances.length - 1) this.instances.pop(); else { cr.arrayRemove(this.instances, index); this.setZIndicesStaleFrom(index); } this.render_list_stale = true; }; Layer.prototype.appendToInstanceList = function (inst, add_to_grid) { ; inst.zindex = this.instances.length; this.instances.push(inst); if (add_to_grid && this.useRenderCells && inst.rendercells) { inst.set_bbox_changed(); // will cause immediate update and new insertion to grid } this.render_list_stale = true; }; Layer.prototype.prependToInstanceList = function (inst, add_to_grid) { ; this.instances.unshift(inst); this.setZIndicesStaleFrom(0); if (add_to_grid && this.useRenderCells && inst.rendercells) { inst.set_bbox_changed(); // will cause immediate update and new insertion to grid } }; Layer.prototype.moveInstanceAdjacent = function (inst, other, isafter) { ; var myZ = inst.get_zindex(); var insertZ = other.get_zindex(); cr.arrayRemove(this.instances, myZ); if (myZ < insertZ) insertZ--; if (isafter) insertZ++; if (insertZ === this.instances.length) this.instances.push(inst); else this.instances.splice(insertZ, 0, inst); this.setZIndicesStaleFrom(myZ < insertZ ? myZ : insertZ); }; Layer.prototype.setZIndicesStaleFrom = function (index) { if (this.zindices_stale_from === -1) // not yet set this.zindices_stale_from = index; else if (index < this.zindices_stale_from) // determine minimum z index affected this.zindices_stale_from = index; this.zindices_stale = true; this.render_list_stale = true; }; Layer.prototype.updateZIndices = function () { if (!this.zindices_stale) return; if (this.zindices_stale_from === -1) this.zindices_stale_from = 0; var i, len, inst; if (this.useRenderCells) { for (i = this.zindices_stale_from, len = this.instances.length; i < len; ++i) { inst = this.instances[i]; inst.zindex = i; this.render_grid.markRangeChanged(inst.rendercells); } } else { for (i = this.zindices_stale_from, len = this.instances.length; i < len; ++i) { this.instances[i].zindex = i; } } this.zindices_stale = false; this.zindices_stale_from = -1; }; Layer.prototype.getScale = function (include_aspect) { return this.getNormalScale() * (this.runtime.fullscreenScalingQuality || include_aspect ? this.runtime.aspect_scale : 1); }; Layer.prototype.getNormalScale = function () { return ((this.scale * this.layout.scale) - 1) * this.zoomRate + 1; }; Layer.prototype.getAngle = function () { if (this.disableAngle) return 0; return cr.clamp_angle(this.layout.angle + this.angle); }; var arr_cache = []; function alloc_arr() { if (arr_cache.length) return arr_cache.pop(); else return []; } function free_arr(a) { cr.clearArray(a); arr_cache.push(a); }; function mergeSortedZArrays(a, b, out) { var i = 0, j = 0, k = 0, lena = a.length, lenb = b.length, ai, bj; out.length = lena + lenb; for ( ; i < lena && j < lenb; ++k) { ai = a[i]; bj = b[j]; if (ai.zindex < bj.zindex) { out[k] = ai; ++i; } else { out[k] = bj; ++j; } } for ( ; i < lena; ++i, ++k) out[k] = a[i]; for ( ; j < lenb; ++j, ++k) out[k] = b[j]; }; var next_arr = []; function mergeAllSortedZArrays_pass(arr, first_pass) { var i, len, arr1, arr2, out; for (i = 0, len = arr.length; i < len - 1; i += 2) { arr1 = arr[i]; arr2 = arr[i+1]; out = alloc_arr(); mergeSortedZArrays(arr1, arr2, out); if (!first_pass) { free_arr(arr1); free_arr(arr2); } next_arr.push(out); } if (len % 2 === 1) { if (first_pass) { arr1 = alloc_arr(); cr.shallowAssignArray(arr1, arr[len - 1]); next_arr.push(arr1); } else { next_arr.push(arr[len - 1]); } } cr.shallowAssignArray(arr, next_arr); cr.clearArray(next_arr); }; function mergeAllSortedZArrays(arr) { var first_pass = true; while (arr.length > 1) { mergeAllSortedZArrays_pass(arr, first_pass); first_pass = false; } return arr[0]; }; var render_arr = []; Layer.prototype.getRenderCellInstancesToDraw = function () { ; this.updateZIndices(); this.render_grid.queryRange(this.viewLeft, this.viewTop, this.viewRight, this.viewBottom, render_arr); if (!render_arr.length) return alloc_arr(); if (render_arr.length === 1) { var a = alloc_arr(); cr.shallowAssignArray(a, render_arr[0]); cr.clearArray(render_arr); return a; } var draw_list = mergeAllSortedZArrays(render_arr); cr.clearArray(render_arr); return draw_list; }; Layer.prototype.draw = function (ctx) { this.render_offscreen = (this.forceOwnTexture || this.opacity !== 1.0 || this.blend_mode !== 0); var layer_canvas = this.runtime.canvas; var layer_ctx = ctx; var ctx_changed = false; if (this.render_offscreen) { if (!this.runtime.layer_canvas) { this.runtime.layer_canvas = document.createElement("canvas"); ; layer_canvas = this.runtime.layer_canvas; layer_canvas.width = this.runtime.draw_width; layer_canvas.height = this.runtime.draw_height; this.runtime.layer_ctx = layer_canvas.getContext("2d"); ; ctx_changed = true; } layer_canvas = this.runtime.layer_canvas; layer_ctx = this.runtime.layer_ctx; if (layer_canvas.width !== this.runtime.draw_width) { layer_canvas.width = this.runtime.draw_width; ctx_changed = true; } if (layer_canvas.height !== this.runtime.draw_height) { layer_canvas.height = this.runtime.draw_height; ctx_changed = true; } if (ctx_changed) { this.runtime.setCtxImageSmoothingEnabled(layer_ctx, this.runtime.linearSampling); } if (this.transparent) layer_ctx.clearRect(0, 0, this.runtime.draw_width, this.runtime.draw_height); } layer_ctx.globalAlpha = 1; layer_ctx.globalCompositeOperation = "source-over"; if (!this.transparent) { layer_ctx.fillStyle = "rgb(" + this.background_color[0] + "," + this.background_color[1] + "," + this.background_color[2] + ")"; layer_ctx.fillRect(0, 0, this.runtime.draw_width, this.runtime.draw_height); } layer_ctx.save(); this.disableAngle = true; var px = this.canvasToLayer(0, 0, true, true); var py = this.canvasToLayer(0, 0, false, true); this.disableAngle = false; if (this.runtime.pixel_rounding) { px = Math.round(px); py = Math.round(py); } this.rotateViewport(px, py, layer_ctx); var myscale = this.getScale(); layer_ctx.scale(myscale, myscale); layer_ctx.translate(-px, -py); var instances_to_draw; if (this.useRenderCells) { this.cur_render_cells.left = this.render_grid.XToCell(this.viewLeft); this.cur_render_cells.top = this.render_grid.YToCell(this.viewTop); this.cur_render_cells.right = this.render_grid.XToCell(this.viewRight); this.cur_render_cells.bottom = this.render_grid.YToCell(this.viewBottom); if (this.render_list_stale || !this.cur_render_cells.equals(this.last_render_cells)) { free_arr(this.last_render_list); instances_to_draw = this.getRenderCellInstancesToDraw(); this.render_list_stale = false; this.last_render_cells.copy(this.cur_render_cells); } else instances_to_draw = this.last_render_list; } else instances_to_draw = this.instances; var i, len, inst, last_inst = null; for (i = 0, len = instances_to_draw.length; i < len; ++i) { inst = instances_to_draw[i]; if (inst === last_inst) continue; this.drawInstance(inst, layer_ctx); last_inst = inst; } if (this.useRenderCells) this.last_render_list = instances_to_draw; layer_ctx.restore(); if (this.render_offscreen) { ctx.globalCompositeOperation = this.compositeOp; ctx.globalAlpha = this.opacity; ctx.drawImage(layer_canvas, 0, 0); } }; Layer.prototype.drawInstance = function(inst, layer_ctx) { if (!inst.visible || inst.width === 0 || inst.height === 0) return; inst.update_bbox(); var bbox = inst.bbox; if (bbox.right < this.viewLeft || bbox.bottom < this.viewTop || bbox.left > this.viewRight || bbox.top > this.viewBottom) return; layer_ctx.globalCompositeOperation = inst.compositeOp; inst.draw(layer_ctx); }; Layer.prototype.updateViewport = function (ctx) { this.disableAngle = true; var px = this.canvasToLayer(0, 0, true, true); var py = this.canvasToLayer(0, 0, false, true); this.disableAngle = false; if (this.runtime.pixel_rounding) { px = Math.round(px); py = Math.round(py); } this.rotateViewport(px, py, ctx); }; Layer.prototype.rotateViewport = function (px, py, ctx) { var myscale = this.getScale(); this.viewLeft = px; this.viewTop = py; this.viewRight = px + (this.runtime.draw_width * (1 / myscale)); this.viewBottom = py + (this.runtime.draw_height * (1 / myscale)); var temp; if (this.viewLeft > this.viewRight) { temp = this.viewLeft; this.viewLeft = this.viewRight; this.viewRight = temp; } if (this.viewTop > this.viewBottom) { temp = this.viewTop; this.viewTop = this.viewBottom; this.viewBottom = temp; } var myAngle = this.getAngle(); if (myAngle !== 0) { if (ctx) { ctx.translate(this.runtime.draw_width / 2, this.runtime.draw_height / 2); ctx.rotate(-myAngle); ctx.translate(this.runtime.draw_width / -2, this.runtime.draw_height / -2); } this.tmprect.set(this.viewLeft, this.viewTop, this.viewRight, this.viewBottom); this.tmprect.offset((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2); this.tmpquad.set_from_rotated_rect(this.tmprect, myAngle); this.tmpquad.bounding_box(this.tmprect); this.tmprect.offset((this.viewLeft + this.viewRight) / 2, (this.viewTop + this.viewBottom) / 2); this.viewLeft = this.tmprect.left; this.viewTop = this.tmprect.top; this.viewRight = this.tmprect.right; this.viewBottom = this.tmprect.bottom; } } Layer.prototype.drawGL_earlyZPass = function (glw) { var windowWidth = this.runtime.draw_width; var windowHeight = this.runtime.draw_height; var shaderindex = 0; var etindex = 0; this.render_offscreen = this.forceOwnTexture; if (this.render_offscreen) { if (!this.runtime.layer_tex) { this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } if (this.runtime.layer_tex.c2width !== this.runtime.draw_width || this.runtime.layer_tex.c2height !== this.runtime.draw_height) { glw.deleteTexture(this.runtime.layer_tex); this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } glw.setRenderingToTexture(this.runtime.layer_tex); } this.disableAngle = true; var px = this.canvasToLayer(0, 0, true, true); var py = this.canvasToLayer(0, 0, false, true); this.disableAngle = false; if (this.runtime.pixel_rounding) { px = Math.round(px); py = Math.round(py); } this.rotateViewport(px, py, null); var myscale = this.getScale(); glw.resetModelView(); glw.scale(myscale, myscale); glw.rotateZ(-this.getAngle()); glw.translate((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2); glw.updateModelView(); var instances_to_draw; if (this.useRenderCells) { this.cur_render_cells.left = this.render_grid.XToCell(this.viewLeft); this.cur_render_cells.top = this.render_grid.YToCell(this.viewTop); this.cur_render_cells.right = this.render_grid.XToCell(this.viewRight); this.cur_render_cells.bottom = this.render_grid.YToCell(this.viewBottom); if (this.render_list_stale || !this.cur_render_cells.equals(this.last_render_cells)) { free_arr(this.last_render_list); instances_to_draw = this.getRenderCellInstancesToDraw(); this.render_list_stale = false; this.last_render_cells.copy(this.cur_render_cells); } else instances_to_draw = this.last_render_list; } else instances_to_draw = this.instances; var i, inst, last_inst = null; for (i = instances_to_draw.length - 1; i >= 0; --i) { inst = instances_to_draw[i]; if (inst === last_inst) continue; this.drawInstanceGL_earlyZPass(instances_to_draw[i], glw); last_inst = inst; } if (this.useRenderCells) this.last_render_list = instances_to_draw; if (!this.transparent) { this.clear_earlyz_index = this.runtime.earlyz_index++; glw.setEarlyZIndex(this.clear_earlyz_index); glw.setColorFillMode(1, 1, 1, 1); glw.fullscreenQuad(); // fill remaining space in depth buffer with current Z value glw.restoreEarlyZMode(); } }; Layer.prototype.drawGL = function (glw) { var windowWidth = this.runtime.draw_width; var windowHeight = this.runtime.draw_height; var shaderindex = 0; var etindex = 0; this.render_offscreen = (this.forceOwnTexture || this.opacity !== 1.0 || this.active_effect_types.length > 0 || this.blend_mode !== 0); if (this.render_offscreen) { if (!this.runtime.layer_tex) { this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } if (this.runtime.layer_tex.c2width !== this.runtime.draw_width || this.runtime.layer_tex.c2height !== this.runtime.draw_height) { glw.deleteTexture(this.runtime.layer_tex); this.runtime.layer_tex = glw.createEmptyTexture(this.runtime.draw_width, this.runtime.draw_height, this.runtime.linearSampling); } glw.setRenderingToTexture(this.runtime.layer_tex); if (this.transparent) glw.clear(0, 0, 0, 0); } if (!this.transparent) { if (this.runtime.enableFrontToBack) { glw.setEarlyZIndex(this.clear_earlyz_index); glw.setColorFillMode(this.background_color[0] / 255, this.background_color[1] / 255, this.background_color[2] / 255, 1); glw.fullscreenQuad(); glw.setTextureFillMode(); } else { glw.clear(this.background_color[0] / 255, this.background_color[1] / 255, this.background_color[2] / 255, 1); } } this.disableAngle = true; var px = this.canvasToLayer(0, 0, true, true); var py = this.canvasToLayer(0, 0, false, true); this.disableAngle = false; if (this.runtime.pixel_rounding) { px = Math.round(px); py = Math.round(py); } this.rotateViewport(px, py, null); var myscale = this.getScale(); glw.resetModelView(); glw.scale(myscale, myscale); glw.rotateZ(-this.getAngle()); glw.translate((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2); glw.updateModelView(); var instances_to_draw; if (this.useRenderCells) { this.cur_render_cells.left = this.render_grid.XToCell(this.viewLeft); this.cur_render_cells.top = this.render_grid.YToCell(this.viewTop); this.cur_render_cells.right = this.render_grid.XToCell(this.viewRight); this.cur_render_cells.bottom = this.render_grid.YToCell(this.viewBottom); if (this.render_list_stale || !this.cur_render_cells.equals(this.last_render_cells)) { free_arr(this.last_render_list); instances_to_draw = this.getRenderCellInstancesToDraw(); this.render_list_stale = false; this.last_render_cells.copy(this.cur_render_cells); } else instances_to_draw = this.last_render_list; } else instances_to_draw = this.instances; var i, len, inst, last_inst = null; for (i = 0, len = instances_to_draw.length; i < len; ++i) { inst = instances_to_draw[i]; if (inst === last_inst) continue; this.drawInstanceGL(instances_to_draw[i], glw); last_inst = inst; } if (this.useRenderCells) this.last_render_list = instances_to_draw; if (this.render_offscreen) { shaderindex = this.active_effect_types.length ? this.active_effect_types[0].shaderindex : 0; etindex = this.active_effect_types.length ? this.active_effect_types[0].index : 0; if (this.active_effect_types.length === 0 || (this.active_effect_types.length === 1 && !glw.programUsesCrossSampling(shaderindex) && this.opacity === 1)) { if (this.active_effect_types.length === 1) { glw.switchProgram(shaderindex); glw.setProgramParameters(this.layout.getRenderTarget(), // backTex 1.0 / this.runtime.draw_width, // pixelWidth 1.0 / this.runtime.draw_height, // pixelHeight 0.0, 0.0, // destStart 1.0, 1.0, // destEnd myscale, // layerScale this.getAngle(), this.viewLeft, this.viewTop, (this.viewLeft + this.viewRight) / 2, (this.viewTop + this.viewBottom) / 2, this.runtime.kahanTime.sum, this.effect_params[etindex]); // fx parameters if (glw.programIsAnimated(shaderindex)) this.runtime.redraw = true; } else glw.switchProgram(0); glw.setRenderingToTexture(this.layout.getRenderTarget()); glw.setOpacity(this.opacity); glw.setTexture(this.runtime.layer_tex); glw.setBlend(this.srcBlend, this.destBlend); glw.resetModelView(); glw.updateModelView(); var halfw = this.runtime.draw_width / 2; var halfh = this.runtime.draw_height / 2; glw.quad(-halfw, halfh, halfw, halfh, halfw, -halfh, -halfw, -halfh); glw.setTexture(null); } else { this.layout.renderEffectChain(glw, this, null, this.layout.getRenderTarget()); } } }; Layer.prototype.drawInstanceGL = function (inst, glw) { ; if (!inst.visible || inst.width === 0 || inst.height === 0) return; inst.update_bbox(); var bbox = inst.bbox; if (bbox.right < this.viewLeft || bbox.bottom < this.viewTop || bbox.left > this.viewRight || bbox.top > this.viewBottom) return; glw.setEarlyZIndex(inst.earlyz_index); if (inst.uses_shaders) { this.drawInstanceWithShadersGL(inst, glw); } else { glw.switchProgram(0); // un-set any previously set shader glw.setBlend(inst.srcBlend, inst.destBlend); inst.drawGL(glw); } }; Layer.prototype.drawInstanceGL_earlyZPass = function (inst, glw) { ; if (!inst.visible || inst.width === 0 || inst.height === 0) return; inst.update_bbox(); var bbox = inst.bbox; if (bbox.right < this.viewLeft || bbox.bottom < this.viewTop || bbox.left > this.viewRight || bbox.top > this.viewBottom) return; inst.earlyz_index = this.runtime.earlyz_index++; if (inst.blend_mode !== 0 || inst.opacity !== 1 || !inst.shaders_preserve_opaqueness || !inst.drawGL_earlyZPass) return; glw.setEarlyZIndex(inst.earlyz_index); inst.drawGL_earlyZPass(glw); }; Layer.prototype.drawInstanceWithShadersGL = function (inst, glw) { var shaderindex = inst.active_effect_types[0].shaderindex; var etindex = inst.active_effect_types[0].index; var myscale = this.getScale(); if (inst.active_effect_types.length === 1 && !glw.programUsesCrossSampling(shaderindex) && !glw.programExtendsBox(shaderindex) && ((!inst.angle && !inst.layer.getAngle()) || !glw.programUsesDest(shaderindex)) && inst.opacity === 1 && !inst.type.plugin.must_predraw) { glw.switchProgram(shaderindex); glw.setBlend(inst.srcBlend, inst.destBlend); if (glw.programIsAnimated(shaderindex)) this.runtime.redraw = true; var destStartX = 0, destStartY = 0, destEndX = 0, destEndY = 0; if (glw.programUsesDest(shaderindex)) { var bbox = inst.bbox; var screenleft = this.layerToCanvas(bbox.left, bbox.top, true, true); var screentop = this.layerToCanvas(bbox.left, bbox.top, false, true); var screenright = this.layerToCanvas(bbox.right, bbox.bottom, true, true); var screenbottom = this.layerToCanvas(bbox.right, bbox.bottom, false, true); destStartX = screenleft / windowWidth; destStartY = 1 - screentop / windowHeight; destEndX = screenright / windowWidth; destEndY = 1 - screenbottom / windowHeight; } var pixelWidth; var pixelHeight; if (inst.curFrame && inst.curFrame.texture_img) { var img = inst.curFrame.texture_img; pixelWidth = 1.0 / img.width; pixelHeight = 1.0 / img.height; } else { pixelWidth = 1.0 / inst.width; pixelHeight = 1.0 / inst.height; } glw.setProgramParameters(this.render_offscreen ? this.runtime.layer_tex : this.layout.getRenderTarget(), // backTex pixelWidth, pixelHeight, destStartX, destStartY, destEndX, destEndY, myscale, this.getAngle(), this.viewLeft, this.viewTop, (this.viewLeft + this.viewRight) / 2, (this.viewTop + this.viewBottom) / 2, this.runtime.kahanTime.sum, inst.effect_params[etindex]); inst.drawGL(glw); } else { this.layout.renderEffectChain(glw, this, inst, this.render_offscreen ? this.runtime.layer_tex : this.layout.getRenderTarget()); glw.resetModelView(); glw.scale(myscale, myscale); glw.rotateZ(-this.getAngle()); glw.translate((this.viewLeft + this.viewRight) / -2, (this.viewTop + this.viewBottom) / -2); glw.updateModelView(); } }; Layer.prototype.canvasToLayer = function (ptx, pty, getx, using_draw_area) { var multiplier = this.runtime.devicePixelRatio; if (this.runtime.isRetina) { ptx *= multiplier; pty *= multiplier; } var ox = this.runtime.parallax_x_origin; var oy = this.runtime.parallax_y_origin; var par_x = ((this.layout.scrollX - ox) * this.parallaxX) + ox; var par_y = ((this.layout.scrollY - oy) * this.parallaxY) + oy; var x = par_x; var y = par_y; var invScale = 1 / this.getScale(!using_draw_area); if (using_draw_area) { x -= (this.runtime.draw_width * invScale) / 2; y -= (this.runtime.draw_height * invScale) / 2; } else { x -= (this.runtime.width * invScale) / 2; y -= (this.runtime.height * invScale) / 2; } x += ptx * invScale; y += pty * invScale; var a = this.getAngle(); if (a !== 0) { x -= par_x; y -= par_y; var cosa = Math.cos(a); var sina = Math.sin(a); var x_temp = (x * cosa) - (y * sina); y = (y * cosa) + (x * sina); x = x_temp; x += par_x; y += par_y; } return getx ? x : y; }; Layer.prototype.layerToCanvas = function (ptx, pty, getx, using_draw_area) { var ox = this.runtime.parallax_x_origin; var oy = this.runtime.parallax_y_origin; var par_x = ((this.layout.scrollX - ox) * this.parallaxX) + ox; var par_y = ((this.layout.scrollY - oy) * this.parallaxY) + oy; var x = par_x; var y = par_y; var a = this.getAngle(); if (a !== 0) { ptx -= par_x; pty -= par_y; var cosa = Math.cos(-a); var sina = Math.sin(-a); var x_temp = (ptx * cosa) - (pty * sina); pty = (pty * cosa) + (ptx * sina); ptx = x_temp; ptx += par_x; pty += par_y; } var invScale = 1 / this.getScale(!using_draw_area); if (using_draw_area) { x -= (this.runtime.draw_width * invScale) / 2; y -= (this.runtime.draw_height * invScale) / 2; } else { x -= (this.runtime.width * invScale) / 2; y -= (this.runtime.height * invScale) / 2; } x = (ptx - x) / invScale; y = (pty - y) / invScale; var multiplier = this.runtime.devicePixelRatio; if (this.runtime.isRetina && !using_draw_area) { x /= multiplier; y /= multiplier; } return getx ? x : y; }; Layer.prototype.rotatePt = function (x_, y_, getx) { if (this.getAngle() === 0) return getx ? x_ : y_; var nx = this.layerToCanvas(x_, y_, true); var ny = this.layerToCanvas(x_, y_, false); this.disableAngle = true; var px = this.canvasToLayer(nx, ny, true); var py = this.canvasToLayer(nx, ny, true); this.disableAngle = false; return getx ? px : py; }; Layer.prototype.saveToJSON = function () { var i, len, et; var o = { "s": this.scale, "a": this.angle, "vl": this.viewLeft, "vt": this.viewTop, "vr": this.viewRight, "vb": this.viewBottom, "v": this.visible, "bc": this.background_color, "t": this.transparent, "px": this.parallaxX, "py": this.parallaxY, "o": this.opacity, "zr": this.zoomRate, "fx": [], "cg": this.created_globals, // added r197; list of global UIDs already created "instances": [] }; for (i = 0, len = this.effect_types.length; i < len; i++) { et = this.effect_types[i]; o["fx"].push({"name": et.name, "active": et.active, "params": this.effect_params[et.index] }); } return o; }; Layer.prototype.loadFromJSON = function (o) { var i, j, len, p, inst, fx; this.scale = o["s"]; this.angle = o["a"]; this.viewLeft = o["vl"]; this.viewTop = o["vt"]; this.viewRight = o["vr"]; this.viewBottom = o["vb"]; this.visible = o["v"]; this.background_color = o["bc"]; this.transparent = o["t"]; this.parallaxX = o["px"]; this.parallaxY = o["py"]; this.opacity = o["o"]; this.zoomRate = o["zr"]; this.created_globals = o["cg"] || []; // added r197 cr.shallowAssignArray(this.initial_instances, this.startup_initial_instances); var temp_set = new cr.ObjectSet(); for (i = 0, len = this.created_globals.length; i < len; ++i) temp_set.add(this.created_globals[i]); for (i = 0, j = 0, len = this.initial_instances.length; i < len; ++i) { if (!temp_set.contains(this.initial_instances[i][2])) // UID in element 2 { this.initial_instances[j] = this.initial_instances[i]; ++j; } } cr.truncateArray(this.initial_instances, j); var ofx = o["fx"]; for (i = 0, len = ofx.length; i < len; i++) { fx = this.getEffectByName(ofx[i]["name"]); if (!fx) continue; // must've gone missing fx.active = ofx[i]["active"]; this.effect_params[fx.index] = ofx[i]["params"]; } this.updateActiveEffects(); this.instances.sort(sort_by_zindex); this.zindices_stale = true; }; cr.layer = Layer; }()); ; (function() { var allUniqueSolModifiers = []; function testSolsMatch(arr1, arr2) { var i, len = arr1.length; switch (len) { case 0: return true; case 1: return arr1[0] === arr2[0]; case 2: return arr1[0] === arr2[0] && arr1[1] === arr2[1]; default: for (i = 0; i < len; i++) { if (arr1[i] !== arr2[i]) return false; } return true; } }; function solArraySorter(t1, t2) { return t1.index - t2.index; }; function findMatchingSolModifier(arr) { var i, len, u, temp, subarr; if (arr.length === 2) { if (arr[0].index > arr[1].index) { temp = arr[0]; arr[0] = arr[1]; arr[1] = temp; } } else if (arr.length > 2) arr.sort(solArraySorter); // so testSolsMatch compares in same order if (arr.length >= allUniqueSolModifiers.length) allUniqueSolModifiers.length = arr.length + 1; if (!allUniqueSolModifiers[arr.length]) allUniqueSolModifiers[arr.length] = []; subarr = allUniqueSolModifiers[arr.length]; for (i = 0, len = subarr.length; i < len; i++) { u = subarr[i]; if (testSolsMatch(arr, u)) return u; } subarr.push(arr); return arr; }; function EventSheet(runtime, m) { this.runtime = runtime; this.triggers = {}; this.fasttriggers = {}; this.hasRun = false; this.includes = new cr.ObjectSet(); // all event sheets included by this sheet, at first-level indirection only this.deep_includes = []; // all includes from this sheet recursively, in trigger order this.already_included_sheets = []; // used while building deep_includes this.name = m[0]; var em = m[1]; // events model this.events = []; // triggers won't make it to this array var i, len; for (i = 0, len = em.length; i < len; i++) this.init_event(em[i], null, this.events); }; EventSheet.prototype.toString = function () { return this.name; }; EventSheet.prototype.init_event = function (m, parent, nontriggers) { switch (m[0]) { case 0: // event block { var block = new cr.eventblock(this, parent, m); cr.seal(block); if (block.orblock) { nontriggers.push(block); var i, len; for (i = 0, len = block.conditions.length; i < len; i++) { if (block.conditions[i].trigger) this.init_trigger(block, i); } } else { if (block.is_trigger()) this.init_trigger(block, 0); else nontriggers.push(block); } break; } case 1: // variable { var v = new cr.eventvariable(this, parent, m); cr.seal(v); nontriggers.push(v); break; } case 2: // include { var inc = new cr.eventinclude(this, parent, m); cr.seal(inc); nontriggers.push(inc); break; } default: ; } }; EventSheet.prototype.postInit = function () { var i, len; for (i = 0, len = this.events.length; i < len; i++) { this.events[i].postInit(i < len - 1 && this.events[i + 1].is_else_block); } }; EventSheet.prototype.updateDeepIncludes = function () { cr.clearArray(this.deep_includes); cr.clearArray(this.already_included_sheets); this.addDeepIncludes(this); cr.clearArray(this.already_included_sheets); }; EventSheet.prototype.addDeepIncludes = function (root_sheet) { var i, len, inc, sheet; var deep_includes = root_sheet.deep_includes; var already_included_sheets = root_sheet.already_included_sheets; var arr = this.includes.valuesRef(); for (i = 0, len = arr.length; i < len; ++i) { inc = arr[i]; sheet = inc.include_sheet; if (!inc.isActive() || root_sheet === sheet || already_included_sheets.indexOf(sheet) > -1) continue; already_included_sheets.push(sheet); sheet.addDeepIncludes(root_sheet); deep_includes.push(sheet); } }; EventSheet.prototype.run = function (from_include) { if (!this.runtime.resuming_breakpoint) { this.hasRun = true; if (!from_include) this.runtime.isRunningEvents = true; } var i, len; for (i = 0, len = this.events.length; i < len; i++) { var ev = this.events[i]; ev.run(); this.runtime.clearSol(ev.solModifiers); if (this.runtime.hasPendingInstances) this.runtime.ClearDeathRow(); } if (!from_include) this.runtime.isRunningEvents = false; }; function isPerformanceSensitiveTrigger(method) { if (cr.plugins_.Sprite && method === cr.plugins_.Sprite.prototype.cnds.OnFrameChanged) { return true; } return false; }; EventSheet.prototype.init_trigger = function (trig, index) { if (!trig.orblock) this.runtime.triggers_to_postinit.push(trig); // needs to be postInit'd later var i, len; var cnd = trig.conditions[index]; var type_name; if (cnd.type) type_name = cnd.type.name; else type_name = "system"; var fasttrigger = cnd.fasttrigger; var triggers = (fasttrigger ? this.fasttriggers : this.triggers); if (!triggers[type_name]) triggers[type_name] = []; var obj_entry = triggers[type_name]; var method = cnd.func; if (fasttrigger) { if (!cnd.parameters.length) // no parameters return; var firstparam = cnd.parameters[0]; if (firstparam.type !== 1 || // not a string param firstparam.expression.type !== 2) // not a string literal node { return; } var fastevs; var firstvalue = firstparam.expression.value.toLowerCase(); var i, len; for (i = 0, len = obj_entry.length; i < len; i++) { if (obj_entry[i].method == method) { fastevs = obj_entry[i].evs; if (!fastevs[firstvalue]) fastevs[firstvalue] = [[trig, index]]; else fastevs[firstvalue].push([trig, index]); return; } } fastevs = {}; fastevs[firstvalue] = [[trig, index]]; obj_entry.push({ method: method, evs: fastevs }); } else { for (i = 0, len = obj_entry.length; i < len; i++) { if (obj_entry[i].method == method) { obj_entry[i].evs.push([trig, index]); return; } } if (isPerformanceSensitiveTrigger(method)) obj_entry.unshift({ method: method, evs: [[trig, index]]}); else obj_entry.push({ method: method, evs: [[trig, index]]}); } }; cr.eventsheet = EventSheet; function Selection(type) { this.type = type; this.instances = []; // subset of picked instances this.else_instances = []; // subset of unpicked instances this.select_all = true; }; Selection.prototype.hasObjects = function () { if (this.select_all) return this.type.instances.length; else return this.instances.length; }; Selection.prototype.getObjects = function () { if (this.select_all) return this.type.instances; else return this.instances; }; /* Selection.prototype.ensure_picked = function (inst, skip_siblings) { var i, len; var orblock = inst.runtime.getCurrentEventStack().current_event.orblock; if (this.select_all) { this.select_all = false; if (orblock) { cr.shallowAssignArray(this.else_instances, inst.type.instances); cr.arrayFindRemove(this.else_instances, inst); } this.instances.length = 1; this.instances[0] = inst; } else { if (orblock) { i = this.else_instances.indexOf(inst); if (i !== -1) { this.instances.push(this.else_instances[i]); this.else_instances.splice(i, 1); } } else { if (this.instances.indexOf(inst) === -1) this.instances.push(inst); } } if (!skip_siblings) { } }; */ Selection.prototype.pick_one = function (inst) { if (!inst) return; if (inst.runtime.getCurrentEventStack().current_event.orblock) { if (this.select_all) { cr.clearArray(this.instances); cr.shallowAssignArray(this.else_instances, inst.type.instances); this.select_all = false; } var i = this.else_instances.indexOf(inst); if (i !== -1) { this.instances.push(this.else_instances[i]); this.else_instances.splice(i, 1); } } else { this.select_all = false; cr.clearArray(this.instances); this.instances[0] = inst; } }; cr.selection = Selection; function EventBlock(sheet, parent, m) { this.sheet = sheet; this.parent = parent; this.runtime = sheet.runtime; this.solModifiers = []; this.solModifiersIncludingParents = []; this.solWriterAfterCnds = false; // block does not change SOL after running its conditions this.group = false; // is group of events this.initially_activated = false; // if a group, is active on startup this.toplevelevent = false; // is an event block parented only by a top-level group this.toplevelgroup = false; // is parented only by other groups or is top-level (i.e. not in a subevent) this.has_else_block = false; // is followed by else ; this.conditions = []; this.actions = []; this.subevents = []; this.group_name = ""; this.group = false; this.initially_activated = false; this.group_active = false; this.contained_includes = null; if (m[1]) { this.group_name = m[1][1].toLowerCase(); this.group = true; this.initially_activated = !!m[1][0]; this.contained_includes = []; this.group_active = this.initially_activated; this.runtime.allGroups.push(this); this.runtime.groups_by_name[this.group_name] = this; } this.orblock = m[2]; this.sid = m[4]; if (!this.group) this.runtime.blocksBySid[this.sid.toString()] = this; var i, len; var cm = m[5]; for (i = 0, len = cm.length; i < len; i++) { var cnd = new cr.condition(this, cm[i]); cnd.index = i; cr.seal(cnd); this.conditions.push(cnd); /* if (cnd.is_logical()) this.is_logical = true; if (cnd.type && !cnd.type.plugin.singleglobal && this.cndReferences.indexOf(cnd.type) === -1) this.cndReferences.push(cnd.type); */ this.addSolModifier(cnd.type); } var am = m[6]; for (i = 0, len = am.length; i < len; i++) { var act = new cr.action(this, am[i]); act.index = i; cr.seal(act); this.actions.push(act); } if (m.length === 8) { var em = m[7]; for (i = 0, len = em.length; i < len; i++) this.sheet.init_event(em[i], this, this.subevents); } this.is_else_block = false; if (this.conditions.length) { this.is_else_block = (this.conditions[0].type == null && this.conditions[0].func == cr.system_object.prototype.cnds.Else); } }; window["_c2hh_"] = "3D2B739A1CCDEED5BB9AD9934803BF00AAC05827"; EventBlock.prototype.postInit = function (hasElse/*, prevBlock_*/) { var i, len; var p = this.parent; if (this.group) { this.toplevelgroup = true; while (p) { if (!p.group) { this.toplevelgroup = false; break; } p = p.parent; } } this.toplevelevent = !this.is_trigger() && (!this.parent || (this.parent.group && this.parent.toplevelgroup)); this.has_else_block = !!hasElse; this.solModifiersIncludingParents = this.solModifiers.slice(0); p = this.parent; while (p) { for (i = 0, len = p.solModifiers.length; i < len; i++) this.addParentSolModifier(p.solModifiers[i]); p = p.parent; } this.solModifiers = findMatchingSolModifier(this.solModifiers); this.solModifiersIncludingParents = findMatchingSolModifier(this.solModifiersIncludingParents); var i, len/*, s*/; for (i = 0, len = this.conditions.length; i < len; i++) this.conditions[i].postInit(); for (i = 0, len = this.actions.length; i < len; i++) this.actions[i].postInit(); for (i = 0, len = this.subevents.length; i < len; i++) { this.subevents[i].postInit(i < len - 1 && this.subevents[i + 1].is_else_block); } /* if (this.is_else_block && this.prev_block) { for (i = 0, len = this.prev_block.solModifiers.length; i < len; i++) { s = this.prev_block.solModifiers[i]; if (this.solModifiers.indexOf(s) === -1) this.solModifiers.push(s); } } */ }; EventBlock.prototype.setGroupActive = function (a) { if (this.group_active === !!a) return; // same state this.group_active = !!a; var i, len; for (i = 0, len = this.contained_includes.length; i < len; ++i) { this.contained_includes[i].updateActive(); } if (len > 0 && this.runtime.running_layout.event_sheet) this.runtime.running_layout.event_sheet.updateDeepIncludes(); }; function addSolModifierToList(type, arr) { var i, len, t; if (!type) return; if (arr.indexOf(type) === -1) arr.push(type); if (type.is_contained) { for (i = 0, len = type.container.length; i < len; i++) { t = type.container[i]; if (type === t) continue; // already handled if (arr.indexOf(t) === -1) arr.push(t); } } }; EventBlock.prototype.addSolModifier = function (type) { addSolModifierToList(type, this.solModifiers); }; EventBlock.prototype.addParentSolModifier = function (type) { addSolModifierToList(type, this.solModifiersIncludingParents); }; EventBlock.prototype.setSolWriterAfterCnds = function () { this.solWriterAfterCnds = true; if (this.parent) this.parent.setSolWriterAfterCnds(); }; EventBlock.prototype.is_trigger = function () { if (!this.conditions.length) // no conditions return false; else return this.conditions[0].trigger; }; EventBlock.prototype.run = function () { var i, len, c, any_true = false, cnd_result; var runtime = this.runtime; var evinfo = this.runtime.getCurrentEventStack(); evinfo.current_event = this; var conditions = this.conditions; if (!this.is_else_block) evinfo.else_branch_ran = false; if (this.orblock) { if (conditions.length === 0) any_true = true; // be sure to run if empty block evinfo.cndindex = 0 for (len = conditions.length; evinfo.cndindex < len; evinfo.cndindex++) { c = conditions[evinfo.cndindex]; if (c.trigger) // skip triggers when running OR block continue; cnd_result = c.run(); if (cnd_result) // make sure all conditions run and run if any were true any_true = true; } evinfo.last_event_true = any_true; if (any_true) this.run_actions_and_subevents(); } else { evinfo.cndindex = 0 for (len = conditions.length; evinfo.cndindex < len; evinfo.cndindex++) { cnd_result = conditions[evinfo.cndindex].run(); if (!cnd_result) // condition failed { evinfo.last_event_true = false; if (this.toplevelevent && runtime.hasPendingInstances) runtime.ClearDeathRow(); return; // bail out now } } evinfo.last_event_true = true; this.run_actions_and_subevents(); } this.end_run(evinfo); }; EventBlock.prototype.end_run = function (evinfo) { if (evinfo.last_event_true && this.has_else_block) evinfo.else_branch_ran = true; if (this.toplevelevent && this.runtime.hasPendingInstances) this.runtime.ClearDeathRow(); }; EventBlock.prototype.run_orblocktrigger = function (index) { var evinfo = this.runtime.getCurrentEventStack(); evinfo.current_event = this; if (this.conditions[index].run()) { this.run_actions_and_subevents(); this.runtime.getCurrentEventStack().last_event_true = true; } }; EventBlock.prototype.run_actions_and_subevents = function () { var evinfo = this.runtime.getCurrentEventStack(); var len; for (evinfo.actindex = 0, len = this.actions.length; evinfo.actindex < len; evinfo.actindex++) { if (this.actions[evinfo.actindex].run()) return; } this.run_subevents(); }; EventBlock.prototype.resume_actions_and_subevents = function () { var evinfo = this.runtime.getCurrentEventStack(); var len; for (len = this.actions.length; evinfo.actindex < len; evinfo.actindex++) { if (this.actions[evinfo.actindex].run()) return; } this.run_subevents(); }; EventBlock.prototype.run_subevents = function () { if (!this.subevents.length) return; var i, len, subev, pushpop/*, skipped_pop = false, pop_modifiers = null*/; var last = this.subevents.length - 1; this.runtime.pushEventStack(this); if (this.solWriterAfterCnds) { for (i = 0, len = this.subevents.length; i < len; i++) { subev = this.subevents[i]; pushpop = (!this.toplevelgroup || (!this.group && i < last)); if (pushpop) this.runtime.pushCopySol(subev.solModifiers); subev.run(); if (pushpop) this.runtime.popSol(subev.solModifiers); else this.runtime.clearSol(subev.solModifiers); } } else { for (i = 0, len = this.subevents.length; i < len; i++) { this.subevents[i].run(); } } this.runtime.popEventStack(); }; EventBlock.prototype.run_pretrigger = function () { var evinfo = this.runtime.getCurrentEventStack(); evinfo.current_event = this; var any_true = false; var i, len; for (evinfo.cndindex = 0, len = this.conditions.length; evinfo.cndindex < len; evinfo.cndindex++) { ; if (this.conditions[evinfo.cndindex].run()) any_true = true; else if (!this.orblock) // condition failed (let OR blocks run all conditions anyway) return false; // bail out } return this.orblock ? any_true : true; }; EventBlock.prototype.retrigger = function () { this.runtime.execcount++; var prevcndindex = this.runtime.getCurrentEventStack().cndindex; var len; var evinfo = this.runtime.pushEventStack(this); if (!this.orblock) { for (evinfo.cndindex = prevcndindex + 1, len = this.conditions.length; evinfo.cndindex < len; evinfo.cndindex++) { if (!this.conditions[evinfo.cndindex].run()) // condition failed { this.runtime.popEventStack(); // moving up level of recursion return false; // bail out } } } this.run_actions_and_subevents(); this.runtime.popEventStack(); return true; // ran an iteration }; EventBlock.prototype.isFirstConditionOfType = function (cnd) { var cndindex = cnd.index; if (cndindex === 0) return true; --cndindex; for ( ; cndindex >= 0; --cndindex) { if (this.conditions[cndindex].type === cnd.type) return false; } return true; }; cr.eventblock = EventBlock; function Condition(block, m) { this.block = block; this.sheet = block.sheet; this.runtime = block.runtime; this.parameters = []; this.results = []; this.extra = {}; // for plugins to stow away some custom info this.index = -1; this.anyParamVariesPerInstance = false; this.func = this.runtime.GetObjectReference(m[1]); ; this.trigger = (m[3] > 0); this.fasttrigger = (m[3] === 2); this.looping = m[4]; this.inverted = m[5]; this.isstatic = m[6]; this.sid = m[7]; this.runtime.cndsBySid[this.sid.toString()] = this; if (m[0] === -1) // system object { this.type = null; this.run = this.run_system; this.behaviortype = null; this.beh_index = -1; } else { this.type = this.runtime.types_by_index[m[0]]; ; if (this.isstatic) this.run = this.run_static; else this.run = this.run_object; if (m[2]) { this.behaviortype = this.type.getBehaviorByName(m[2]); ; this.beh_index = this.type.getBehaviorIndexByName(m[2]); ; } else { this.behaviortype = null; this.beh_index = -1; } if (this.block.parent) this.block.parent.setSolWriterAfterCnds(); } if (this.fasttrigger) this.run = this.run_true; if (m.length === 10) { var i, len; var em = m[9]; for (i = 0, len = em.length; i < len; i++) { var param = new cr.parameter(this, em[i]); cr.seal(param); this.parameters.push(param); } this.results.length = em.length; } }; Condition.prototype.postInit = function () { var i, len, p; for (i = 0, len = this.parameters.length; i < len; i++) { p = this.parameters[i]; p.postInit(); if (p.variesPerInstance) this.anyParamVariesPerInstance = true; } }; /* Condition.prototype.is_logical = function () { return !this.type || this.type.plugin.singleglobal; }; */ Condition.prototype.run_true = function () { return true; }; Condition.prototype.run_system = function () { var i, len; for (i = 0, len = this.parameters.length; i < len; i++) this.results[i] = this.parameters[i].get(); return cr.xor(this.func.apply(this.runtime.system, this.results), this.inverted); }; Condition.prototype.run_static = function () { var i, len; for (i = 0, len = this.parameters.length; i < len; i++) this.results[i] = this.parameters[i].get(); var ret = this.func.apply(this.behaviortype ? this.behaviortype : this.type, this.results); this.type.applySolToContainer(); return ret; }; Condition.prototype.run_object = function () { var i, j, k, leni, lenj, p, ret, met, inst, s, sol2; var type = this.type; var sol = type.getCurrentSol(); var is_orblock = this.block.orblock && !this.trigger; // triggers in OR blocks need to work normally var offset = 0; var is_contained = type.is_contained; var is_family = type.is_family; var family_index = type.family_index; var beh_index = this.beh_index; var is_beh = (beh_index > -1); var params_vary = this.anyParamVariesPerInstance; var parameters = this.parameters; var results = this.results; var inverted = this.inverted; var func = this.func; var arr, container; if (params_vary) { for (j = 0, lenj = parameters.length; j < lenj; ++j) { p = parameters[j]; if (!p.variesPerInstance) results[j] = p.get(0); } } else { for (j = 0, lenj = parameters.length; j < lenj; ++j) results[j] = parameters[j].get(0); } if (sol.select_all) { cr.clearArray(sol.instances); // clear contents cr.clearArray(sol.else_instances); arr = type.instances; for (i = 0, leni = arr.length; i < leni; ++i) { inst = arr[i]; ; if (params_vary) { for (j = 0, lenj = parameters.length; j < lenj; ++j) { p = parameters[j]; if (p.variesPerInstance) results[j] = p.get(i); // default SOL index is current object } } if (is_beh) { offset = 0; if (is_family) { offset = inst.type.family_beh_map[family_index]; } ret = func.apply(inst.behavior_insts[beh_index + offset], results); } else ret = func.apply(inst, results); met = cr.xor(ret, inverted); if (met) sol.instances.push(inst); else if (is_orblock) // in OR blocks, keep the instances not meeting the condition for subsequent testing sol.else_instances.push(inst); } if (type.finish) type.finish(true); sol.select_all = false; type.applySolToContainer(); return sol.hasObjects(); } else { k = 0; var using_else_instances = (is_orblock && !this.block.isFirstConditionOfType(this)); arr = (using_else_instances ? sol.else_instances : sol.instances); var any_true = false; for (i = 0, leni = arr.length; i < leni; ++i) { inst = arr[i]; ; if (params_vary) { for (j = 0, lenj = parameters.length; j < lenj; ++j) { p = parameters[j]; if (p.variesPerInstance) results[j] = p.get(i); // default SOL index is current object } } if (is_beh) { offset = 0; if (is_family) { offset = inst.type.family_beh_map[family_index]; } ret = func.apply(inst.behavior_insts[beh_index + offset], results); } else ret = func.apply(inst, results); if (cr.xor(ret, inverted)) { any_true = true; if (using_else_instances) { sol.instances.push(inst); if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; s.type.getCurrentSol().instances.push(s); } } } else { arr[k] = inst; if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; s.type.getCurrentSol().instances[k] = s; } } k++; } } else { if (using_else_instances) { arr[k] = inst; if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; s.type.getCurrentSol().else_instances[k] = s; } } k++; } else if (is_orblock) { sol.else_instances.push(inst); if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; s.type.getCurrentSol().else_instances.push(s); } } } } } cr.truncateArray(arr, k); if (is_contained) { container = type.container; for (i = 0, leni = container.length; i < leni; i++) { sol2 = container[i].getCurrentSol(); if (using_else_instances) cr.truncateArray(sol2.else_instances, k); else cr.truncateArray(sol2.instances, k); } } var pick_in_finish = any_true; // don't pick in finish() if we're only doing the logic test below if (using_else_instances && !any_true) { for (i = 0, leni = sol.instances.length; i < leni; i++) { inst = sol.instances[i]; if (params_vary) { for (j = 0, lenj = parameters.length; j < lenj; j++) { p = parameters[j]; if (p.variesPerInstance) results[j] = p.get(i); } } if (is_beh) ret = func.apply(inst.behavior_insts[beh_index], results); else ret = func.apply(inst, results); if (cr.xor(ret, inverted)) { any_true = true; break; // got our flag, don't need to test any more } } } if (type.finish) type.finish(pick_in_finish || is_orblock); return is_orblock ? any_true : sol.hasObjects(); } }; cr.condition = Condition; function Action(block, m) { this.block = block; this.sheet = block.sheet; this.runtime = block.runtime; this.parameters = []; this.results = []; this.extra = {}; // for plugins to stow away some custom info this.index = -1; this.anyParamVariesPerInstance = false; this.func = this.runtime.GetObjectReference(m[1]); ; if (m[0] === -1) // system { this.type = null; this.run = this.run_system; this.behaviortype = null; this.beh_index = -1; } else { this.type = this.runtime.types_by_index[m[0]]; ; this.run = this.run_object; if (m[2]) { this.behaviortype = this.type.getBehaviorByName(m[2]); ; this.beh_index = this.type.getBehaviorIndexByName(m[2]); ; } else { this.behaviortype = null; this.beh_index = -1; } } this.sid = m[3]; this.runtime.actsBySid[this.sid.toString()] = this; if (m.length === 6) { var i, len; var em = m[5]; for (i = 0, len = em.length; i < len; i++) { var param = new cr.parameter(this, em[i]); cr.seal(param); this.parameters.push(param); } this.results.length = em.length; } }; Action.prototype.postInit = function () { var i, len, p; for (i = 0, len = this.parameters.length; i < len; i++) { p = this.parameters[i]; p.postInit(); if (p.variesPerInstance) this.anyParamVariesPerInstance = true; } }; Action.prototype.run_system = function () { var runtime = this.runtime; var i, len; var parameters = this.parameters; var results = this.results; for (i = 0, len = parameters.length; i < len; ++i) results[i] = parameters[i].get(); return this.func.apply(runtime.system, results); }; Action.prototype.run_object = function () { var type = this.type; var beh_index = this.beh_index; var family_index = type.family_index; var params_vary = this.anyParamVariesPerInstance; var parameters = this.parameters; var results = this.results; var func = this.func; var instances = type.getCurrentSol().getObjects(); var is_family = type.is_family; var is_beh = (beh_index > -1); var i, j, leni, lenj, p, inst, offset; if (params_vary) { for (j = 0, lenj = parameters.length; j < lenj; ++j) { p = parameters[j]; if (!p.variesPerInstance) results[j] = p.get(0); } } else { for (j = 0, lenj = parameters.length; j < lenj; ++j) results[j] = parameters[j].get(0); } for (i = 0, leni = instances.length; i < leni; ++i) { inst = instances[i]; if (params_vary) { for (j = 0, lenj = parameters.length; j < lenj; ++j) { p = parameters[j]; if (p.variesPerInstance) results[j] = p.get(i); // pass i to use as default SOL index } } if (is_beh) { offset = 0; if (is_family) { offset = inst.type.family_beh_map[family_index]; } func.apply(inst.behavior_insts[beh_index + offset], results); } else func.apply(inst, results); } return false; }; cr.action = Action; var tempValues = []; var tempValuesPtr = -1; function pushTempValue() { tempValuesPtr++; if (tempValues.length === tempValuesPtr) tempValues.push(new cr.expvalue()); return tempValues[tempValuesPtr]; }; function popTempValue() { tempValuesPtr--; }; function Parameter(owner, m) { this.owner = owner; this.block = owner.block; this.sheet = owner.sheet; this.runtime = owner.runtime; this.type = m[0]; this.expression = null; this.solindex = 0; this.get = null; this.combosel = 0; this.layout = null; this.key = 0; this.object = null; this.index = 0; this.varname = null; this.eventvar = null; this.fileinfo = null; this.subparams = null; this.variadicret = null; this.subparams = null; this.variadicret = null; this.variesPerInstance = false; var i, len, param; switch (m[0]) { case 0: // number case 7: // any this.expression = new cr.expNode(this, m[1]); this.solindex = 0; this.get = this.get_exp; break; case 1: // string this.expression = new cr.expNode(this, m[1]); this.solindex = 0; this.get = this.get_exp_str; break; case 5: // layer this.expression = new cr.expNode(this, m[1]); this.solindex = 0; this.get = this.get_layer; break; case 3: // combo case 8: // cmp this.combosel = m[1]; this.get = this.get_combosel; break; case 6: // layout this.layout = this.runtime.layouts[m[1]]; ; this.get = this.get_layout; break; case 9: // keyb this.key = m[1]; this.get = this.get_key; break; case 4: // object this.object = this.runtime.types_by_index[m[1]]; ; this.get = this.get_object; this.block.addSolModifier(this.object); if (this.owner instanceof cr.action) this.block.setSolWriterAfterCnds(); else if (this.block.parent) this.block.parent.setSolWriterAfterCnds(); break; case 10: // instvar this.index = m[1]; if (owner.type && owner.type.is_family) { this.get = this.get_familyvar; this.variesPerInstance = true; } else this.get = this.get_instvar; break; case 11: // eventvar this.varname = m[1]; this.eventvar = null; this.get = this.get_eventvar; break; case 2: // audiofile ["name", ismusic] case 12: // fileinfo "name" this.fileinfo = m[1]; this.get = this.get_audiofile; break; case 13: // variadic this.get = this.get_variadic; this.subparams = []; this.variadicret = []; for (i = 1, len = m.length; i < len; i++) { param = new cr.parameter(this.owner, m[i]); cr.seal(param); this.subparams.push(param); this.variadicret.push(0); } break; default: ; } }; Parameter.prototype.postInit = function () { var i, len; if (this.type === 11) // eventvar { this.eventvar = this.runtime.getEventVariableByName(this.varname, this.block.parent); ; } else if (this.type === 13) // variadic, postInit all sub-params { for (i = 0, len = this.subparams.length; i < len; i++) this.subparams[i].postInit(); } if (this.expression) this.expression.postInit(); }; Parameter.prototype.maybeVaryForType = function (t) { if (this.variesPerInstance) return; // already varies per instance, no need to check again if (!t) return; // never vary for system type if (!t.plugin.singleglobal) { this.variesPerInstance = true; return; } }; Parameter.prototype.setVaries = function () { this.variesPerInstance = true; }; Parameter.prototype.get_exp = function (solindex) { this.solindex = solindex || 0; // default SOL index to use var temp = pushTempValue(); this.expression.get(temp); popTempValue(); return temp.data; // return actual JS value, not expvalue }; Parameter.prototype.get_exp_str = function (solindex) { this.solindex = solindex || 0; // default SOL index to use var temp = pushTempValue(); this.expression.get(temp); popTempValue(); if (cr.is_string(temp.data)) return temp.data; else return ""; }; Parameter.prototype.get_object = function () { return this.object; }; Parameter.prototype.get_combosel = function () { return this.combosel; }; Parameter.prototype.get_layer = function (solindex) { this.solindex = solindex || 0; // default SOL index to use var temp = pushTempValue(); this.expression.get(temp); popTempValue(); if (temp.is_number()) return this.runtime.getLayerByNumber(temp.data); else return this.runtime.getLayerByName(temp.data); } Parameter.prototype.get_layout = function () { return this.layout; }; Parameter.prototype.get_key = function () { return this.key; }; Parameter.prototype.get_instvar = function () { return this.index; }; Parameter.prototype.get_familyvar = function (solindex_) { var solindex = solindex_ || 0; var familytype = this.owner.type; var realtype = null; var sol = familytype.getCurrentSol(); var objs = sol.getObjects(); if (objs.length) realtype = objs[solindex % objs.length].type; else if (sol.else_instances.length) realtype = sol.else_instances[solindex % sol.else_instances.length].type; else if (familytype.instances.length) realtype = familytype.instances[solindex % familytype.instances.length].type; else return 0; return this.index + realtype.family_var_map[familytype.family_index]; }; Parameter.prototype.get_eventvar = function () { return this.eventvar; }; Parameter.prototype.get_audiofile = function () { return this.fileinfo; }; Parameter.prototype.get_variadic = function () { var i, len; for (i = 0, len = this.subparams.length; i < len; i++) { this.variadicret[i] = this.subparams[i].get(); } return this.variadicret; }; cr.parameter = Parameter; function EventVariable(sheet, parent, m) { this.sheet = sheet; this.parent = parent; this.runtime = sheet.runtime; this.solModifiers = []; this.name = m[1]; this.vartype = m[2]; this.initial = m[3]; this.is_static = !!m[4]; this.is_constant = !!m[5]; this.sid = m[6]; this.runtime.varsBySid[this.sid.toString()] = this; this.data = this.initial; // note: also stored in event stack frame for local nonstatic nonconst vars if (this.parent) // local var { if (this.is_static || this.is_constant) this.localIndex = -1; else this.localIndex = this.runtime.stackLocalCount++; this.runtime.all_local_vars.push(this); } else // global var { this.localIndex = -1; this.runtime.all_global_vars.push(this); } }; EventVariable.prototype.postInit = function () { this.solModifiers = findMatchingSolModifier(this.solModifiers); }; EventVariable.prototype.setValue = function (x) { ; var lvs = this.runtime.getCurrentLocalVarStack(); if (!this.parent || this.is_static || !lvs) this.data = x; else // local nonstatic variable: use event stack to keep value at this level of recursion { if (this.localIndex >= lvs.length) lvs.length = this.localIndex + 1; lvs[this.localIndex] = x; } }; EventVariable.prototype.getValue = function () { var lvs = this.runtime.getCurrentLocalVarStack(); if (!this.parent || this.is_static || !lvs || this.is_constant) return this.data; else // local nonstatic variable { if (this.localIndex >= lvs.length) { return this.initial; } if (typeof lvs[this.localIndex] === "undefined") { return this.initial; } return lvs[this.localIndex]; } }; EventVariable.prototype.run = function () { if (this.parent && !this.is_static && !this.is_constant) this.setValue(this.initial); }; cr.eventvariable = EventVariable; function EventInclude(sheet, parent, m) { this.sheet = sheet; this.parent = parent; this.runtime = sheet.runtime; this.solModifiers = []; this.include_sheet = null; // determined in postInit this.include_sheet_name = m[1]; this.active = true; }; EventInclude.prototype.toString = function () { return "include:" + this.include_sheet.toString(); }; EventInclude.prototype.postInit = function () { this.include_sheet = this.runtime.eventsheets[this.include_sheet_name]; ; ; this.sheet.includes.add(this); this.solModifiers = findMatchingSolModifier(this.solModifiers); var p = this.parent; while (p) { if (p.group) p.contained_includes.push(this); p = p.parent; } this.updateActive(); }; EventInclude.prototype.run = function () { if (this.parent) this.runtime.pushCleanSol(this.runtime.types_by_index); if (!this.include_sheet.hasRun) this.include_sheet.run(true); // from include if (this.parent) this.runtime.popSol(this.runtime.types_by_index); }; EventInclude.prototype.updateActive = function () { var p = this.parent; while (p) { if (p.group && !p.group_active) { this.active = false; return; } p = p.parent; } this.active = true; }; EventInclude.prototype.isActive = function () { return this.active; }; cr.eventinclude = EventInclude; function EventStackFrame() { this.temp_parents_arr = []; this.reset(null); cr.seal(this); }; EventStackFrame.prototype.reset = function (cur_event) { this.current_event = cur_event; this.cndindex = 0; this.actindex = 0; cr.clearArray(this.temp_parents_arr); this.last_event_true = false; this.else_branch_ran = false; this.any_true_state = false; }; EventStackFrame.prototype.isModifierAfterCnds = function () { if (this.current_event.solWriterAfterCnds) return true; if (this.cndindex < this.current_event.conditions.length - 1) return !!this.current_event.solModifiers.length; return false; }; cr.eventStackFrame = EventStackFrame; }()); (function() { function ExpNode(owner_, m) { this.owner = owner_; this.runtime = owner_.runtime; this.type = m[0]; ; this.get = [this.eval_int, this.eval_float, this.eval_string, this.eval_unaryminus, this.eval_add, this.eval_subtract, this.eval_multiply, this.eval_divide, this.eval_mod, this.eval_power, this.eval_and, this.eval_or, this.eval_equal, this.eval_notequal, this.eval_less, this.eval_lessequal, this.eval_greater, this.eval_greaterequal, this.eval_conditional, this.eval_system_exp, this.eval_object_exp, this.eval_instvar_exp, this.eval_behavior_exp, this.eval_eventvar_exp][this.type]; var paramsModel = null; this.value = null; this.first = null; this.second = null; this.third = null; this.func = null; this.results = null; this.parameters = null; this.object_type = null; this.beh_index = -1; this.instance_expr = null; this.varindex = -1; this.behavior_type = null; this.varname = null; this.eventvar = null; this.return_string = false; switch (this.type) { case 0: // int case 1: // float case 2: // string this.value = m[1]; break; case 3: // unaryminus this.first = new cr.expNode(owner_, m[1]); break; case 18: // conditional this.first = new cr.expNode(owner_, m[1]); this.second = new cr.expNode(owner_, m[2]); this.third = new cr.expNode(owner_, m[3]); break; case 19: // system_exp this.func = this.runtime.GetObjectReference(m[1]); ; if (this.func === cr.system_object.prototype.exps.random || this.func === cr.system_object.prototype.exps.choose) { this.owner.setVaries(); } this.results = []; this.parameters = []; if (m.length === 3) { paramsModel = m[2]; this.results.length = paramsModel.length + 1; // must also fit 'ret' } else this.results.length = 1; // to fit 'ret' break; case 20: // object_exp this.object_type = this.runtime.types_by_index[m[1]]; ; this.beh_index = -1; this.func = this.runtime.GetObjectReference(m[2]); this.return_string = m[3]; if (cr.plugins_.Function && this.func === cr.plugins_.Function.prototype.exps.Call) { this.owner.setVaries(); } if (m[4]) this.instance_expr = new cr.expNode(owner_, m[4]); else this.instance_expr = null; this.results = []; this.parameters = []; if (m.length === 6) { paramsModel = m[5]; this.results.length = paramsModel.length + 1; } else this.results.length = 1; // to fit 'ret' break; case 21: // instvar_exp this.object_type = this.runtime.types_by_index[m[1]]; ; this.return_string = m[2]; if (m[3]) this.instance_expr = new cr.expNode(owner_, m[3]); else this.instance_expr = null; this.varindex = m[4]; break; case 22: // behavior_exp this.object_type = this.runtime.types_by_index[m[1]]; ; this.behavior_type = this.object_type.getBehaviorByName(m[2]); ; this.beh_index = this.object_type.getBehaviorIndexByName(m[2]); this.func = this.runtime.GetObjectReference(m[3]); this.return_string = m[4]; if (m[5]) this.instance_expr = new cr.expNode(owner_, m[5]); else this.instance_expr = null; this.results = []; this.parameters = []; if (m.length === 7) { paramsModel = m[6]; this.results.length = paramsModel.length + 1; } else this.results.length = 1; // to fit 'ret' break; case 23: // eventvar_exp this.varname = m[1]; this.eventvar = null; // assigned in postInit break; } this.owner.maybeVaryForType(this.object_type); if (this.type >= 4 && this.type <= 17) { this.first = new cr.expNode(owner_, m[1]); this.second = new cr.expNode(owner_, m[2]); } if (paramsModel) { var i, len; for (i = 0, len = paramsModel.length; i < len; i++) this.parameters.push(new cr.expNode(owner_, paramsModel[i])); } cr.seal(this); }; ExpNode.prototype.postInit = function () { if (this.type === 23) // eventvar_exp { this.eventvar = this.owner.runtime.getEventVariableByName(this.varname, this.owner.block.parent); ; } if (this.first) this.first.postInit(); if (this.second) this.second.postInit(); if (this.third) this.third.postInit(); if (this.instance_expr) this.instance_expr.postInit(); if (this.parameters) { var i, len; for (i = 0, len = this.parameters.length; i < len; i++) this.parameters[i].postInit(); } }; var tempValues = []; var tempValuesPtr = -1; function pushTempValue() { ++tempValuesPtr; if (tempValues.length === tempValuesPtr) tempValues.push(new cr.expvalue()); return tempValues[tempValuesPtr]; }; function popTempValue() { --tempValuesPtr; }; function eval_params(parameters, results, temp) { var i, len; for (i = 0, len = parameters.length; i < len; ++i) { parameters[i].get(temp); results[i + 1] = temp.data; // passing actual javascript value as argument instead of expvalue } } ExpNode.prototype.eval_system_exp = function (ret) { var parameters = this.parameters; var results = this.results; results[0] = ret; var temp = pushTempValue(); eval_params(parameters, results, temp); popTempValue(); this.func.apply(this.runtime.system, results); }; ExpNode.prototype.eval_object_exp = function (ret) { var object_type = this.object_type; var results = this.results; var parameters = this.parameters; var instance_expr = this.instance_expr; var func = this.func; var index = this.owner.solindex; // default to parameter's intended SOL index var sol = object_type.getCurrentSol(); var instances = sol.getObjects(); if (!instances.length) { if (sol.else_instances.length) instances = sol.else_instances; else { if (this.return_string) ret.set_string(""); else ret.set_int(0); return; } } results[0] = ret; ret.object_class = object_type; // so expression can access family type if need be var temp = pushTempValue(); eval_params(parameters, results, temp); if (instance_expr) { instance_expr.get(temp); if (temp.is_number()) { index = temp.data; instances = object_type.instances; // pick from all instances, not SOL } } popTempValue(); var len = instances.length; if (index >= len || index <= -len) index %= len; // wraparound if (index < 0) index += len; var returned_val = func.apply(instances[index], results); ; }; ExpNode.prototype.eval_behavior_exp = function (ret) { var object_type = this.object_type; var results = this.results; var parameters = this.parameters; var instance_expr = this.instance_expr; var beh_index = this.beh_index; var func = this.func; var index = this.owner.solindex; // default to parameter's intended SOL index var sol = object_type.getCurrentSol(); var instances = sol.getObjects(); if (!instances.length) { if (sol.else_instances.length) instances = sol.else_instances; else { if (this.return_string) ret.set_string(""); else ret.set_int(0); return; } } results[0] = ret; ret.object_class = object_type; // so expression can access family type if need be var temp = pushTempValue(); eval_params(parameters, results, temp); if (instance_expr) { instance_expr.get(temp); if (temp.is_number()) { index = temp.data; instances = object_type.instances; // pick from all instances, not SOL } } popTempValue(); var len = instances.length; if (index >= len || index <= -len) index %= len; // wraparound if (index < 0) index += len; var inst = instances[index]; var offset = 0; if (object_type.is_family) { offset = inst.type.family_beh_map[object_type.family_index]; } var returned_val = func.apply(inst.behavior_insts[beh_index + offset], results); ; }; ExpNode.prototype.eval_instvar_exp = function (ret) { var instance_expr = this.instance_expr; var object_type = this.object_type; var varindex = this.varindex; var index = this.owner.solindex; // default to parameter's intended SOL index var sol = object_type.getCurrentSol(); var instances = sol.getObjects(); var inst; if (!instances.length) { if (sol.else_instances.length) instances = sol.else_instances; else { if (this.return_string) ret.set_string(""); else ret.set_int(0); return; } } if (instance_expr) { var temp = pushTempValue(); instance_expr.get(temp); if (temp.is_number()) { index = temp.data; var type_instances = object_type.instances; if (type_instances.length !== 0) // avoid NaN result with % { index %= type_instances.length; // wraparound if (index < 0) // offset index += type_instances.length; } inst = object_type.getInstanceByIID(index); var to_ret = inst.instance_vars[varindex]; if (cr.is_string(to_ret)) ret.set_string(to_ret); else ret.set_float(to_ret); popTempValue(); return; // done } popTempValue(); } var len = instances.length; if (index >= len || index <= -len) index %= len; // wraparound if (index < 0) index += len; inst = instances[index]; var offset = 0; if (object_type.is_family) { offset = inst.type.family_var_map[object_type.family_index]; } var to_ret = inst.instance_vars[varindex + offset]; if (cr.is_string(to_ret)) ret.set_string(to_ret); else ret.set_float(to_ret); }; ExpNode.prototype.eval_int = function (ret) { ret.type = cr.exptype.Integer; ret.data = this.value; }; ExpNode.prototype.eval_float = function (ret) { ret.type = cr.exptype.Float; ret.data = this.value; }; ExpNode.prototype.eval_string = function (ret) { ret.type = cr.exptype.String; ret.data = this.value; }; ExpNode.prototype.eval_unaryminus = function (ret) { this.first.get(ret); // retrieve operand if (ret.is_number()) ret.data = -ret.data; }; ExpNode.prototype.eval_add = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (ret.is_number() && temp.is_number()) { ret.data += temp.data; // both operands numbers: add if (temp.is_float()) ret.make_float(); } popTempValue(); }; ExpNode.prototype.eval_subtract = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (ret.is_number() && temp.is_number()) { ret.data -= temp.data; // both operands numbers: subtract if (temp.is_float()) ret.make_float(); } popTempValue(); }; ExpNode.prototype.eval_multiply = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (ret.is_number() && temp.is_number()) { ret.data *= temp.data; // both operands numbers: multiply if (temp.is_float()) ret.make_float(); } popTempValue(); }; ExpNode.prototype.eval_divide = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (ret.is_number() && temp.is_number()) { ret.data /= temp.data; // both operands numbers: divide ret.make_float(); } popTempValue(); }; ExpNode.prototype.eval_mod = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (ret.is_number() && temp.is_number()) { ret.data %= temp.data; // both operands numbers: modulo if (temp.is_float()) ret.make_float(); } popTempValue(); }; ExpNode.prototype.eval_power = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (ret.is_number() && temp.is_number()) { ret.data = Math.pow(ret.data, temp.data); // both operands numbers: raise to power if (temp.is_float()) ret.make_float(); } popTempValue(); }; ExpNode.prototype.eval_and = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (temp.is_string() || ret.is_string()) this.eval_and_stringconcat(ret, temp); else this.eval_and_logical(ret, temp); popTempValue(); }; ExpNode.prototype.eval_and_stringconcat = function (ret, temp) { if (ret.is_string() && temp.is_string()) this.eval_and_stringconcat_str_str(ret, temp); else this.eval_and_stringconcat_num(ret, temp); }; ExpNode.prototype.eval_and_stringconcat_str_str = function (ret, temp) { ret.data += temp.data; }; ExpNode.prototype.eval_and_stringconcat_num = function (ret, temp) { if (ret.is_string()) { ret.data += (Math.round(temp.data * 1e10) / 1e10).toString(); } else { ret.set_string(ret.data.toString() + temp.data); } }; ExpNode.prototype.eval_and_logical = function (ret, temp) { ret.set_int(ret.data && temp.data ? 1 : 0); }; ExpNode.prototype.eval_or = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand if (ret.is_number() && temp.is_number()) { if (ret.data || temp.data) ret.set_int(1); else ret.set_int(0); } popTempValue(); }; ExpNode.prototype.eval_conditional = function (ret) { this.first.get(ret); // condition operand if (ret.data) // is true this.second.get(ret); // evaluate second operand to ret else this.third.get(ret); // evaluate third operand to ret }; ExpNode.prototype.eval_equal = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand ret.set_int(ret.data === temp.data ? 1 : 0); popTempValue(); }; ExpNode.prototype.eval_notequal = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand ret.set_int(ret.data !== temp.data ? 1 : 0); popTempValue(); }; ExpNode.prototype.eval_less = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand ret.set_int(ret.data < temp.data ? 1 : 0); popTempValue(); }; ExpNode.prototype.eval_lessequal = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand ret.set_int(ret.data <= temp.data ? 1 : 0); popTempValue(); }; ExpNode.prototype.eval_greater = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand ret.set_int(ret.data > temp.data ? 1 : 0); popTempValue(); }; ExpNode.prototype.eval_greaterequal = function (ret) { this.first.get(ret); // left operand var temp = pushTempValue(); this.second.get(temp); // right operand ret.set_int(ret.data >= temp.data ? 1 : 0); popTempValue(); }; ExpNode.prototype.eval_eventvar_exp = function (ret) { var val = this.eventvar.getValue(); if (cr.is_number(val)) ret.set_float(val); else ret.set_string(val); }; cr.expNode = ExpNode; function ExpValue(type, data) { this.type = type || cr.exptype.Integer; this.data = data || 0; this.object_class = null; ; ; ; if (this.type == cr.exptype.Integer) this.data = Math.floor(this.data); cr.seal(this); }; ExpValue.prototype.is_int = function () { return this.type === cr.exptype.Integer; }; ExpValue.prototype.is_float = function () { return this.type === cr.exptype.Float; }; ExpValue.prototype.is_number = function () { return this.type === cr.exptype.Integer || this.type === cr.exptype.Float; }; ExpValue.prototype.is_string = function () { return this.type === cr.exptype.String; }; ExpValue.prototype.make_int = function () { if (!this.is_int()) { if (this.is_float()) this.data = Math.floor(this.data); // truncate float else if (this.is_string()) this.data = parseInt(this.data, 10); this.type = cr.exptype.Integer; } }; ExpValue.prototype.make_float = function () { if (!this.is_float()) { if (this.is_string()) this.data = parseFloat(this.data); this.type = cr.exptype.Float; } }; ExpValue.prototype.make_string = function () { if (!this.is_string()) { this.data = this.data.toString(); this.type = cr.exptype.String; } }; ExpValue.prototype.set_int = function (val) { ; this.type = cr.exptype.Integer; this.data = Math.floor(val); }; ExpValue.prototype.set_float = function (val) { ; this.type = cr.exptype.Float; this.data = val; }; ExpValue.prototype.set_string = function (val) { ; this.type = cr.exptype.String; this.data = val; }; ExpValue.prototype.set_any = function (val) { if (cr.is_number(val)) { this.type = cr.exptype.Float; this.data = val; } else if (cr.is_string(val)) { this.type = cr.exptype.String; this.data = val.toString(); } else { this.type = cr.exptype.Integer; this.data = 0; } }; cr.expvalue = ExpValue; cr.exptype = { Integer: 0, // emulated; no native integer support in javascript Float: 1, String: 2 }; }()); ; cr.system_object = function (runtime) { this.runtime = runtime; this.waits = []; }; cr.system_object.prototype.saveToJSON = function () { var o = {}; var i, len, j, lenj, p, w, t, sobj; o["waits"] = []; var owaits = o["waits"]; var waitobj; for (i = 0, len = this.waits.length; i < len; i++) { w = this.waits[i]; waitobj = { "t": w.time, "st": w.signaltag, "s": w.signalled, "ev": w.ev.sid, "sm": [], "sols": {} }; if (w.ev.actions[w.actindex]) waitobj["act"] = w.ev.actions[w.actindex].sid; for (j = 0, lenj = w.solModifiers.length; j < lenj; j++) waitobj["sm"].push(w.solModifiers[j].sid); for (p in w.sols) { if (w.sols.hasOwnProperty(p)) { t = this.runtime.types_by_index[parseInt(p, 10)]; ; sobj = { "sa": w.sols[p].sa, "insts": [] }; for (j = 0, lenj = w.sols[p].insts.length; j < lenj; j++) sobj["insts"].push(w.sols[p].insts[j].uid); waitobj["sols"][t.sid.toString()] = sobj; } } owaits.push(waitobj); } return o; }; cr.system_object.prototype.loadFromJSON = function (o) { var owaits = o["waits"]; var i, len, j, lenj, p, w, addWait, e, aindex, t, savedsol, nusol, inst; cr.clearArray(this.waits); for (i = 0, len = owaits.length; i < len; i++) { w = owaits[i]; e = this.runtime.blocksBySid[w["ev"].toString()]; if (!e) continue; // event must've gone missing aindex = -1; for (j = 0, lenj = e.actions.length; j < lenj; j++) { if (e.actions[j].sid === w["act"]) { aindex = j; break; } } if (aindex === -1) continue; // action must've gone missing addWait = {}; addWait.sols = {}; addWait.solModifiers = []; addWait.deleteme = false; addWait.time = w["t"]; addWait.signaltag = w["st"] || ""; addWait.signalled = !!w["s"]; addWait.ev = e; addWait.actindex = aindex; for (j = 0, lenj = w["sm"].length; j < lenj; j++) { t = this.runtime.getObjectTypeBySid(w["sm"][j]); if (t) addWait.solModifiers.push(t); } for (p in w["sols"]) { if (w["sols"].hasOwnProperty(p)) { t = this.runtime.getObjectTypeBySid(parseInt(p, 10)); if (!t) continue; // type must've been deleted savedsol = w["sols"][p]; nusol = { sa: savedsol["sa"], insts: [] }; for (j = 0, lenj = savedsol["insts"].length; j < lenj; j++) { inst = this.runtime.getObjectByUID(savedsol["insts"][j]); if (inst) nusol.insts.push(inst); } addWait.sols[t.index.toString()] = nusol; } } this.waits.push(addWait); } }; (function () { var sysProto = cr.system_object.prototype; function SysCnds() {}; SysCnds.prototype.EveryTick = function() { return true; }; SysCnds.prototype.OnLayoutStart = function() { return true; }; SysCnds.prototype.OnLayoutEnd = function() { return true; }; SysCnds.prototype.Compare = function(x, cmp, y) { return cr.do_cmp(x, cmp, y); }; SysCnds.prototype.CompareTime = function (cmp, t) { var elapsed = this.runtime.kahanTime.sum; if (cmp === 0) { var cnd = this.runtime.getCurrentCondition(); if (!cnd.extra["CompareTime_executed"]) { if (elapsed >= t) { cnd.extra["CompareTime_executed"] = true; return true; } } return false; } return cr.do_cmp(elapsed, cmp, t); }; SysCnds.prototype.LayerVisible = function (layer) { if (!layer) return false; else return layer.visible; }; SysCnds.prototype.LayerEmpty = function (layer) { if (!layer) return false; else return !layer.instances.length; }; SysCnds.prototype.LayerCmpOpacity = function (layer, cmp, opacity_) { if (!layer) return false; return cr.do_cmp(layer.opacity * 100, cmp, opacity_); }; SysCnds.prototype.Repeat = function (count) { var current_frame = this.runtime.getCurrentEventStack(); var current_event = current_frame.current_event; var solModifierAfterCnds = current_frame.isModifierAfterCnds(); var current_loop = this.runtime.pushLoopStack(); var i; if (solModifierAfterCnds) { for (i = 0; i < count && !current_loop.stopped; i++) { this.runtime.pushCopySol(current_event.solModifiers); current_loop.index = i; current_event.retrigger(); this.runtime.popSol(current_event.solModifiers); } } else { for (i = 0; i < count && !current_loop.stopped; i++) { current_loop.index = i; current_event.retrigger(); } } this.runtime.popLoopStack(); return false; }; SysCnds.prototype.While = function (count) { var current_frame = this.runtime.getCurrentEventStack(); var current_event = current_frame.current_event; var solModifierAfterCnds = current_frame.isModifierAfterCnds(); var current_loop = this.runtime.pushLoopStack(); var i; if (solModifierAfterCnds) { for (i = 0; !current_loop.stopped; i++) { this.runtime.pushCopySol(current_event.solModifiers); current_loop.index = i; if (!current_event.retrigger()) // one of the other conditions returned false current_loop.stopped = true; // break this.runtime.popSol(current_event.solModifiers); } } else { for (i = 0; !current_loop.stopped; i++) { current_loop.index = i; if (!current_event.retrigger()) current_loop.stopped = true; } } this.runtime.popLoopStack(); return false; }; SysCnds.prototype.For = function (name, start, end) { var current_frame = this.runtime.getCurrentEventStack(); var current_event = current_frame.current_event; var solModifierAfterCnds = current_frame.isModifierAfterCnds(); var current_loop = this.runtime.pushLoopStack(name); var i; if (end < start) { if (solModifierAfterCnds) { for (i = start; i >= end && !current_loop.stopped; --i) // inclusive to end { this.runtime.pushCopySol(current_event.solModifiers); current_loop.index = i; current_event.retrigger(); this.runtime.popSol(current_event.solModifiers); } } else { for (i = start; i >= end && !current_loop.stopped; --i) // inclusive to end { current_loop.index = i; current_event.retrigger(); } } } else { if (solModifierAfterCnds) { for (i = start; i <= end && !current_loop.stopped; ++i) // inclusive to end { this.runtime.pushCopySol(current_event.solModifiers); current_loop.index = i; current_event.retrigger(); this.runtime.popSol(current_event.solModifiers); } } else { for (i = start; i <= end && !current_loop.stopped; ++i) // inclusive to end { current_loop.index = i; current_event.retrigger(); } } } this.runtime.popLoopStack(); return false; }; var foreach_instancestack = []; var foreach_instanceptr = -1; SysCnds.prototype.ForEach = function (obj) { var sol = obj.getCurrentSol(); foreach_instanceptr++; if (foreach_instancestack.length === foreach_instanceptr) foreach_instancestack.push([]); var instances = foreach_instancestack[foreach_instanceptr]; cr.shallowAssignArray(instances, sol.getObjects()); var current_frame = this.runtime.getCurrentEventStack(); var current_event = current_frame.current_event; var solModifierAfterCnds = current_frame.isModifierAfterCnds(); var current_loop = this.runtime.pushLoopStack(); var i, len, j, lenj, inst, s, sol2; var is_contained = obj.is_contained; if (solModifierAfterCnds) { for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++) { this.runtime.pushCopySol(current_event.solModifiers); inst = instances[i]; sol = obj.getCurrentSol(); sol.select_all = false; cr.clearArray(sol.instances); sol.instances[0] = inst; if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; sol2 = s.type.getCurrentSol(); sol2.select_all = false; cr.clearArray(sol2.instances); sol2.instances[0] = s; } } current_loop.index = i; current_event.retrigger(); this.runtime.popSol(current_event.solModifiers); } } else { sol.select_all = false; cr.clearArray(sol.instances); for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++) { inst = instances[i]; sol.instances[0] = inst; if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; sol2 = s.type.getCurrentSol(); sol2.select_all = false; cr.clearArray(sol2.instances); sol2.instances[0] = s; } } current_loop.index = i; current_event.retrigger(); } } cr.clearArray(instances); this.runtime.popLoopStack(); foreach_instanceptr--; return false; }; function foreach_sortinstances(a, b) { var va = a.extra["c2_feo_val"]; var vb = b.extra["c2_feo_val"]; if (cr.is_number(va) && cr.is_number(vb)) return va - vb; else { va = "" + va; vb = "" + vb; if (va < vb) return -1; else if (va > vb) return 1; else return 0; } }; SysCnds.prototype.ForEachOrdered = function (obj, exp, order) { var sol = obj.getCurrentSol(); foreach_instanceptr++; if (foreach_instancestack.length === foreach_instanceptr) foreach_instancestack.push([]); var instances = foreach_instancestack[foreach_instanceptr]; cr.shallowAssignArray(instances, sol.getObjects()); var current_frame = this.runtime.getCurrentEventStack(); var current_event = current_frame.current_event; var current_condition = this.runtime.getCurrentCondition(); var solModifierAfterCnds = current_frame.isModifierAfterCnds(); var current_loop = this.runtime.pushLoopStack(); var i, len, j, lenj, inst, s, sol2; for (i = 0, len = instances.length; i < len; i++) { instances[i].extra["c2_feo_val"] = current_condition.parameters[1].get(i); } instances.sort(foreach_sortinstances); if (order === 1) instances.reverse(); var is_contained = obj.is_contained; if (solModifierAfterCnds) { for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++) { this.runtime.pushCopySol(current_event.solModifiers); inst = instances[i]; sol = obj.getCurrentSol(); sol.select_all = false; cr.clearArray(sol.instances); sol.instances[0] = inst; if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; sol2 = s.type.getCurrentSol(); sol2.select_all = false; cr.clearArray(sol2.instances); sol2.instances[0] = s; } } current_loop.index = i; current_event.retrigger(); this.runtime.popSol(current_event.solModifiers); } } else { sol.select_all = false; cr.clearArray(sol.instances); for (i = 0, len = instances.length; i < len && !current_loop.stopped; i++) { inst = instances[i]; sol.instances[0] = inst; if (is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; sol2 = s.type.getCurrentSol(); sol2.select_all = false; cr.clearArray(sol2.instances); sol2.instances[0] = s; } } current_loop.index = i; current_event.retrigger(); } } cr.clearArray(instances); this.runtime.popLoopStack(); foreach_instanceptr--; return false; }; SysCnds.prototype.PickByComparison = function (obj_, exp_, cmp_, val_) { var i, len, k, inst; if (!obj_) return; foreach_instanceptr++; if (foreach_instancestack.length === foreach_instanceptr) foreach_instancestack.push([]); var tmp_instances = foreach_instancestack[foreach_instanceptr]; var sol = obj_.getCurrentSol(); cr.shallowAssignArray(tmp_instances, sol.getObjects()); if (sol.select_all) cr.clearArray(sol.else_instances); var current_condition = this.runtime.getCurrentCondition(); for (i = 0, k = 0, len = tmp_instances.length; i < len; i++) { inst = tmp_instances[i]; tmp_instances[k] = inst; exp_ = current_condition.parameters[1].get(i); val_ = current_condition.parameters[3].get(i); if (cr.do_cmp(exp_, cmp_, val_)) { k++; } else { sol.else_instances.push(inst); } } cr.truncateArray(tmp_instances, k); sol.select_all = false; cr.shallowAssignArray(sol.instances, tmp_instances); cr.clearArray(tmp_instances); foreach_instanceptr--; obj_.applySolToContainer(); return !!sol.instances.length; }; SysCnds.prototype.PickByEvaluate = function (obj_, exp_) { var i, len, k, inst; if (!obj_) return; foreach_instanceptr++; if (foreach_instancestack.length === foreach_instanceptr) foreach_instancestack.push([]); var tmp_instances = foreach_instancestack[foreach_instanceptr]; var sol = obj_.getCurrentSol(); cr.shallowAssignArray(tmp_instances, sol.getObjects()); if (sol.select_all) cr.clearArray(sol.else_instances); var current_condition = this.runtime.getCurrentCondition(); for (i = 0, k = 0, len = tmp_instances.length; i < len; i++) { inst = tmp_instances[i]; tmp_instances[k] = inst; exp_ = current_condition.parameters[1].get(i); if (exp_) { k++; } else { sol.else_instances.push(inst); } } cr.truncateArray(tmp_instances, k); sol.select_all = false; cr.shallowAssignArray(sol.instances, tmp_instances); cr.clearArray(tmp_instances); foreach_instanceptr--; obj_.applySolToContainer(); return !!sol.instances.length; }; SysCnds.prototype.TriggerOnce = function () { var cndextra = this.runtime.getCurrentCondition().extra; if (typeof cndextra["TriggerOnce_lastTick"] === "undefined") cndextra["TriggerOnce_lastTick"] = -1; var last_tick = cndextra["TriggerOnce_lastTick"]; var cur_tick = this.runtime.tickcount; cndextra["TriggerOnce_lastTick"] = cur_tick; return this.runtime.layout_first_tick || last_tick !== cur_tick - 1; }; SysCnds.prototype.Every = function (seconds) { var cnd = this.runtime.getCurrentCondition(); var last_time = cnd.extra["Every_lastTime"] || 0; var cur_time = this.runtime.kahanTime.sum; if (typeof cnd.extra["Every_seconds"] === "undefined") cnd.extra["Every_seconds"] = seconds; var this_seconds = cnd.extra["Every_seconds"]; if (cur_time >= last_time + this_seconds) { cnd.extra["Every_lastTime"] = last_time + this_seconds; if (cur_time >= cnd.extra["Every_lastTime"] + 0.04) { cnd.extra["Every_lastTime"] = cur_time; } cnd.extra["Every_seconds"] = seconds; return true; } else if (cur_time < last_time - 0.1) { cnd.extra["Every_lastTime"] = cur_time; } return false; }; SysCnds.prototype.PickNth = function (obj, index) { if (!obj) return false; var sol = obj.getCurrentSol(); var instances = sol.getObjects(); index = cr.floor(index); if (index < 0 || index >= instances.length) return false; var inst = instances[index]; sol.pick_one(inst); obj.applySolToContainer(); return true; }; SysCnds.prototype.PickRandom = function (obj) { if (!obj) return false; var sol = obj.getCurrentSol(); var instances = sol.getObjects(); var index = cr.floor(Math.random() * instances.length); if (index >= instances.length) return false; var inst = instances[index]; sol.pick_one(inst); obj.applySolToContainer(); return true; }; SysCnds.prototype.CompareVar = function (v, cmp, val) { return cr.do_cmp(v.getValue(), cmp, val); }; SysCnds.prototype.IsGroupActive = function (group) { var g = this.runtime.groups_by_name[group.toLowerCase()]; return g && g.group_active; }; SysCnds.prototype.IsPreview = function () { return typeof cr_is_preview !== "undefined"; }; SysCnds.prototype.PickAll = function (obj) { if (!obj) return false; if (!obj.instances.length) return false; var sol = obj.getCurrentSol(); sol.select_all = true; obj.applySolToContainer(); return true; }; SysCnds.prototype.IsMobile = function () { return this.runtime.isMobile; }; SysCnds.prototype.CompareBetween = function (x, a, b) { return x >= a && x <= b; }; SysCnds.prototype.Else = function () { var current_frame = this.runtime.getCurrentEventStack(); if (current_frame.else_branch_ran) return false; // another event in this else-if chain has run else return !current_frame.last_event_true; /* var current_frame = this.runtime.getCurrentEventStack(); var current_event = current_frame.current_event; var prev_event = current_event.prev_block; if (!prev_event) return false; if (prev_event.is_logical) return !this.runtime.last_event_true; var i, len, j, lenj, s, sol, temp, inst, any_picked = false; for (i = 0, len = prev_event.cndReferences.length; i < len; i++) { s = prev_event.cndReferences[i]; sol = s.getCurrentSol(); if (sol.select_all || sol.instances.length === s.instances.length) { sol.select_all = false; sol.instances.length = 0; } else { if (sol.instances.length === 1 && sol.else_instances.length === 0 && s.instances.length >= 2) { inst = sol.instances[0]; sol.instances.length = 0; for (j = 0, lenj = s.instances.length; j < lenj; j++) { if (s.instances[j] != inst) sol.instances.push(s.instances[j]); } any_picked = true; } else { temp = sol.instances; sol.instances = sol.else_instances; sol.else_instances = temp; any_picked = true; } } } return any_picked; */ }; SysCnds.prototype.OnLoadFinished = function () { return true; }; SysCnds.prototype.OnCanvasSnapshot = function () { return true; }; SysCnds.prototype.EffectsSupported = function () { return !!this.runtime.glwrap; }; SysCnds.prototype.OnSaveComplete = function () { return true; }; SysCnds.prototype.OnSaveFailed = function () { return true; }; SysCnds.prototype.OnLoadComplete = function () { return true; }; SysCnds.prototype.OnLoadFailed = function () { return true; }; SysCnds.prototype.ObjectUIDExists = function (u) { return !!this.runtime.getObjectByUID(u); }; SysCnds.prototype.IsOnPlatform = function (p) { var rt = this.runtime; switch (p) { case 0: // HTML5 website return !rt.isDomFree && !rt.isNodeWebkit && !rt.isCordova && !rt.isWinJS && !rt.isWindowsPhone8 && !rt.isBlackberry10 && !rt.isAmazonWebApp; case 1: // iOS return rt.isiOS; case 2: // Android return rt.isAndroid; case 3: // Windows 8 return rt.isWindows8App; case 4: // Windows Phone 8 return rt.isWindowsPhone8; case 5: // Blackberry 10 return rt.isBlackberry10; case 6: // Tizen return rt.isTizen; case 7: // CocoonJS return rt.isCocoonJs; case 8: // Cordova return rt.isCordova; case 9: // Scirra Arcade return rt.isArcade; case 10: // node-webkit return rt.isNodeWebkit; case 11: // crosswalk return rt.isCrosswalk; case 12: // amazon webapp return rt.isAmazonWebApp; case 13: // windows 10 app return rt.isWindows10; default: // should not be possible return false; } }; var cacheRegex = null; var lastRegex = ""; var lastFlags = ""; function getRegex(regex_, flags_) { if (!cacheRegex || regex_ !== lastRegex || flags_ !== lastFlags) { cacheRegex = new RegExp(regex_, flags_); lastRegex = regex_; lastFlags = flags_; } cacheRegex.lastIndex = 0; // reset return cacheRegex; }; SysCnds.prototype.RegexTest = function (str_, regex_, flags_) { var regex = getRegex(regex_, flags_); return regex.test(str_); }; var tmp_arr = []; SysCnds.prototype.PickOverlappingPoint = function (obj_, x_, y_) { if (!obj_) return false; var sol = obj_.getCurrentSol(); var instances = sol.getObjects(); var current_event = this.runtime.getCurrentEventStack().current_event; var orblock = current_event.orblock; var cnd = this.runtime.getCurrentCondition(); var i, len, inst, pick; if (sol.select_all) { cr.shallowAssignArray(tmp_arr, instances); cr.clearArray(sol.else_instances); sol.select_all = false; cr.clearArray(sol.instances); } else { if (orblock) { cr.shallowAssignArray(tmp_arr, sol.else_instances); cr.clearArray(sol.else_instances); } else { cr.shallowAssignArray(tmp_arr, instances); cr.clearArray(sol.instances); } } for (i = 0, len = tmp_arr.length; i < len; ++i) { inst = tmp_arr[i]; inst.update_bbox(); pick = cr.xor(inst.contains_pt(x_, y_), cnd.inverted); if (pick) sol.instances.push(inst); else sol.else_instances.push(inst); } obj_.applySolToContainer(); return cr.xor(!!sol.instances.length, cnd.inverted); }; SysCnds.prototype.IsNaN = function (n) { return !!isNaN(n); }; SysCnds.prototype.AngleWithin = function (a1, within, a2) { return cr.angleDiff(cr.to_radians(a1), cr.to_radians(a2)) <= cr.to_radians(within); }; SysCnds.prototype.IsClockwiseFrom = function (a1, a2) { return cr.angleClockwise(cr.to_radians(a1), cr.to_radians(a2)); }; SysCnds.prototype.IsBetweenAngles = function (a, la, ua) { var angle = cr.to_clamped_radians(a); var lower = cr.to_clamped_radians(la); var upper = cr.to_clamped_radians(ua); var obtuse = (!cr.angleClockwise(upper, lower)); if (obtuse) return !(!cr.angleClockwise(angle, lower) && cr.angleClockwise(angle, upper)); else return cr.angleClockwise(angle, lower) && !cr.angleClockwise(angle, upper); }; SysCnds.prototype.IsValueType = function (x, t) { if (typeof x === "number") return t === 0; else // string return t === 1; }; sysProto.cnds = new SysCnds(); function SysActs() {}; SysActs.prototype.GoToLayout = function (to) { if (this.runtime.isloading) return; // cannot change layout while loading on loader layout if (this.runtime.changelayout) return; // already changing to a different layout ; this.runtime.changelayout = to; }; SysActs.prototype.NextPrevLayout = function (prev) { if (this.runtime.isloading) return; // cannot change layout while loading on loader layout if (this.runtime.changelayout) return; // already changing to a different layout var index = this.runtime.layouts_by_index.indexOf(this.runtime.running_layout); if (prev && index === 0) return; // cannot go to previous layout from first layout if (!prev && index === this.runtime.layouts_by_index.length - 1) return; // cannot go to next layout from last layout var to = this.runtime.layouts_by_index[index + (prev ? -1 : 1)]; ; this.runtime.changelayout = to; }; SysActs.prototype.CreateObject = function (obj, layer, x, y) { if (!layer || !obj) return; var inst = this.runtime.createInstance(obj, layer, x, y); if (!inst) return; this.runtime.isInOnDestroy++; var i, len, s; this.runtime.trigger(Object.getPrototypeOf(obj.plugin).cnds.OnCreated, inst); if (inst.is_contained) { for (i = 0, len = inst.siblings.length; i < len; i++) { s = inst.siblings[i]; this.runtime.trigger(Object.getPrototypeOf(s.type.plugin).cnds.OnCreated, s); } } this.runtime.isInOnDestroy--; var sol = obj.getCurrentSol(); sol.select_all = false; cr.clearArray(sol.instances); sol.instances[0] = inst; if (inst.is_contained) { for (i = 0, len = inst.siblings.length; i < len; i++) { s = inst.siblings[i]; sol = s.type.getCurrentSol(); sol.select_all = false; cr.clearArray(sol.instances); sol.instances[0] = s; } } }; SysActs.prototype.SetLayerVisible = function (layer, visible_) { if (!layer) return; if (layer.visible !== visible_) { layer.visible = visible_; this.runtime.redraw = true; } }; SysActs.prototype.SetLayerOpacity = function (layer, opacity_) { if (!layer) return; opacity_ = cr.clamp(opacity_ / 100, 0, 1); if (layer.opacity !== opacity_) { layer.opacity = opacity_; this.runtime.redraw = true; } }; SysActs.prototype.SetLayerScaleRate = function (layer, sr) { if (!layer) return; if (layer.zoomRate !== sr) { layer.zoomRate = sr; this.runtime.redraw = true; } }; SysActs.prototype.SetLayerForceOwnTexture = function (layer, f) { if (!layer) return; f = !!f; if (layer.forceOwnTexture !== f) { layer.forceOwnTexture = f; this.runtime.redraw = true; } }; SysActs.prototype.SetLayoutScale = function (s) { if (!this.runtime.running_layout) return; if (this.runtime.running_layout.scale !== s) { this.runtime.running_layout.scale = s; this.runtime.running_layout.boundScrolling(); this.runtime.redraw = true; } }; SysActs.prototype.ScrollX = function(x) { this.runtime.running_layout.scrollToX(x); }; SysActs.prototype.ScrollY = function(y) { this.runtime.running_layout.scrollToY(y); }; SysActs.prototype.Scroll = function(x, y) { this.runtime.running_layout.scrollToX(x); this.runtime.running_layout.scrollToY(y); }; SysActs.prototype.ScrollToObject = function(obj) { var inst = obj.getFirstPicked(); if (inst) { this.runtime.running_layout.scrollToX(inst.x); this.runtime.running_layout.scrollToY(inst.y); } }; SysActs.prototype.SetVar = function(v, x) { ; if (v.vartype === 0) { if (cr.is_number(x)) v.setValue(x); else v.setValue(parseFloat(x)); } else if (v.vartype === 1) v.setValue(x.toString()); }; SysActs.prototype.AddVar = function(v, x) { ; if (v.vartype === 0) { if (cr.is_number(x)) v.setValue(v.getValue() + x); else v.setValue(v.getValue() + parseFloat(x)); } else if (v.vartype === 1) v.setValue(v.getValue() + x.toString()); }; SysActs.prototype.SubVar = function(v, x) { ; if (v.vartype === 0) { if (cr.is_number(x)) v.setValue(v.getValue() - x); else v.setValue(v.getValue() - parseFloat(x)); } }; SysActs.prototype.SetGroupActive = function (group, active) { var g = this.runtime.groups_by_name[group.toLowerCase()]; if (!g) return; switch (active) { case 0: g.setGroupActive(false); break; case 1: g.setGroupActive(true); break; case 2: g.setGroupActive(!g.group_active); break; } }; SysActs.prototype.SetTimescale = function (ts_) { var ts = ts_; if (ts < 0) ts = 0; this.runtime.timescale = ts; }; SysActs.prototype.SetObjectTimescale = function (obj, ts_) { var ts = ts_; if (ts < 0) ts = 0; if (!obj) return; var sol = obj.getCurrentSol(); var instances = sol.getObjects(); var i, len; for (i = 0, len = instances.length; i < len; i++) { instances[i].my_timescale = ts; } }; SysActs.prototype.RestoreObjectTimescale = function (obj) { if (!obj) return false; var sol = obj.getCurrentSol(); var instances = sol.getObjects(); var i, len; for (i = 0, len = instances.length; i < len; i++) { instances[i].my_timescale = -1.0; } }; var waitobjrecycle = []; function allocWaitObject() { var w; if (waitobjrecycle.length) w = waitobjrecycle.pop(); else { w = {}; w.sols = {}; w.solModifiers = []; } w.deleteme = false; return w; }; function freeWaitObject(w) { cr.wipe(w.sols); cr.clearArray(w.solModifiers); waitobjrecycle.push(w); }; var solstateobjects = []; function allocSolStateObject() { var s; if (solstateobjects.length) s = solstateobjects.pop(); else { s = {}; s.insts = []; } s.sa = false; return s; }; function freeSolStateObject(s) { cr.clearArray(s.insts); solstateobjects.push(s); }; SysActs.prototype.Wait = function (seconds) { if (seconds < 0) return; var i, len, s, t, ss; var evinfo = this.runtime.getCurrentEventStack(); var waitobj = allocWaitObject(); waitobj.time = this.runtime.kahanTime.sum + seconds; waitobj.signaltag = ""; waitobj.signalled = false; waitobj.ev = evinfo.current_event; waitobj.actindex = evinfo.actindex + 1; // pointing at next action for (i = 0, len = this.runtime.types_by_index.length; i < len; i++) { t = this.runtime.types_by_index[i]; s = t.getCurrentSol(); if (s.select_all && evinfo.current_event.solModifiers.indexOf(t) === -1) continue; waitobj.solModifiers.push(t); ss = allocSolStateObject(); ss.sa = s.select_all; cr.shallowAssignArray(ss.insts, s.instances); waitobj.sols[i.toString()] = ss; } this.waits.push(waitobj); return true; }; SysActs.prototype.WaitForSignal = function (tag) { var i, len, s, t, ss; var evinfo = this.runtime.getCurrentEventStack(); var waitobj = allocWaitObject(); waitobj.time = -1; waitobj.signaltag = tag.toLowerCase(); waitobj.signalled = false; waitobj.ev = evinfo.current_event; waitobj.actindex = evinfo.actindex + 1; // pointing at next action for (i = 0, len = this.runtime.types_by_index.length; i < len; i++) { t = this.runtime.types_by_index[i]; s = t.getCurrentSol(); if (s.select_all && evinfo.current_event.solModifiers.indexOf(t) === -1) continue; waitobj.solModifiers.push(t); ss = allocSolStateObject(); ss.sa = s.select_all; cr.shallowAssignArray(ss.insts, s.instances); waitobj.sols[i.toString()] = ss; } this.waits.push(waitobj); return true; }; SysActs.prototype.Signal = function (tag) { var lowertag = tag.toLowerCase(); var i, len, w; for (i = 0, len = this.waits.length; i < len; ++i) { w = this.waits[i]; if (w.time !== -1) continue; // timer wait, ignore if (w.signaltag === lowertag) // waiting for this signal w.signalled = true; // will run on next check } }; SysActs.prototype.SetLayerScale = function (layer, scale) { if (!layer) return; if (layer.scale === scale) return; layer.scale = scale; this.runtime.redraw = true; }; SysActs.prototype.ResetGlobals = function () { var i, len, g; for (i = 0, len = this.runtime.all_global_vars.length; i < len; i++) { g = this.runtime.all_global_vars[i]; g.data = g.initial; } }; SysActs.prototype.SetLayoutAngle = function (a) { a = cr.to_radians(a); a = cr.clamp_angle(a); if (this.runtime.running_layout) { if (this.runtime.running_layout.angle !== a) { this.runtime.running_layout.angle = a; this.runtime.redraw = true; } } }; SysActs.prototype.SetLayerAngle = function (layer, a) { if (!layer) return; a = cr.to_radians(a); a = cr.clamp_angle(a); if (layer.angle === a) return; layer.angle = a; this.runtime.redraw = true; }; SysActs.prototype.SetLayerParallax = function (layer, px, py) { if (!layer) return; if (layer.parallaxX === px / 100 && layer.parallaxY === py / 100) return; layer.parallaxX = px / 100; layer.parallaxY = py / 100; if (layer.parallaxX !== 1 || layer.parallaxY !== 1) { var i, len, instances = layer.instances; for (i = 0, len = instances.length; i < len; ++i) { instances[i].type.any_instance_parallaxed = true; } } this.runtime.redraw = true; }; SysActs.prototype.SetLayerBackground = function (layer, c) { if (!layer) return; var r = cr.GetRValue(c); var g = cr.GetGValue(c); var b = cr.GetBValue(c); if (layer.background_color[0] === r && layer.background_color[1] === g && layer.background_color[2] === b) return; layer.background_color[0] = r; layer.background_color[1] = g; layer.background_color[2] = b; this.runtime.redraw = true; }; SysActs.prototype.SetLayerTransparent = function (layer, t) { if (!layer) return; if (!!t === !!layer.transparent) return; layer.transparent = !!t; this.runtime.redraw = true; }; SysActs.prototype.SetLayerBlendMode = function (layer, bm) { if (!layer) return; if (layer.blend_mode === bm) return; layer.blend_mode = bm; layer.compositeOp = cr.effectToCompositeOp(layer.blend_mode); if (this.runtime.gl) cr.setGLBlend(layer, layer.blend_mode, this.runtime.gl); this.runtime.redraw = true; }; SysActs.prototype.StopLoop = function () { if (this.runtime.loop_stack_index < 0) return; // no loop currently running this.runtime.getCurrentLoop().stopped = true; }; SysActs.prototype.GoToLayoutByName = function (layoutname) { if (this.runtime.isloading) return; // cannot change layout while loading on loader layout if (this.runtime.changelayout) return; // already changing to different layout ; var l; for (l in this.runtime.layouts) { if (this.runtime.layouts.hasOwnProperty(l) && cr.equals_nocase(l, layoutname)) { this.runtime.changelayout = this.runtime.layouts[l]; return; } } }; SysActs.prototype.RestartLayout = function (layoutname) { if (this.runtime.isloading) return; // cannot restart loader layouts if (this.runtime.changelayout) return; // already changing to a different layout ; if (!this.runtime.running_layout) return; this.runtime.changelayout = this.runtime.running_layout; var i, len, g; for (i = 0, len = this.runtime.allGroups.length; i < len; i++) { g = this.runtime.allGroups[i]; g.setGroupActive(g.initially_activated); } }; SysActs.prototype.SnapshotCanvas = function (format_, quality_) { this.runtime.doCanvasSnapshot(format_ === 0 ? "image/png" : "image/jpeg", quality_ / 100); }; SysActs.prototype.SetCanvasSize = function (w, h) { if (w <= 0 || h <= 0) return; var mode = this.runtime.fullscreen_mode; var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || !!document["msFullscreenElement"] || document["fullScreen"] || this.runtime.isNodeFullscreen); if (isfullscreen && this.runtime.fullscreen_scaling > 0) mode = this.runtime.fullscreen_scaling; if (mode === 0) { this.runtime["setSize"](w, h, true); } else { this.runtime.original_width = w; this.runtime.original_height = h; this.runtime["setSize"](this.runtime.lastWindowWidth, this.runtime.lastWindowHeight, true); } }; SysActs.prototype.SetLayoutEffectEnabled = function (enable_, effectname_) { if (!this.runtime.running_layout || !this.runtime.glwrap) return; var et = this.runtime.running_layout.getEffectByName(effectname_); if (!et) return; // effect name not found var enable = (enable_ === 1); if (et.active == enable) return; // no change et.active = enable; this.runtime.running_layout.updateActiveEffects(); this.runtime.redraw = true; }; SysActs.prototype.SetLayerEffectEnabled = function (layer, enable_, effectname_) { if (!layer || !this.runtime.glwrap) return; var et = layer.getEffectByName(effectname_); if (!et) return; // effect name not found var enable = (enable_ === 1); if (et.active == enable) return; // no change et.active = enable; layer.updateActiveEffects(); this.runtime.redraw = true; }; SysActs.prototype.SetLayoutEffectParam = function (effectname_, index_, value_) { if (!this.runtime.running_layout || !this.runtime.glwrap) return; var et = this.runtime.running_layout.getEffectByName(effectname_); if (!et) return; // effect name not found var params = this.runtime.running_layout.effect_params[et.index]; index_ = Math.floor(index_); if (index_ < 0 || index_ >= params.length) return; // effect index out of bounds if (this.runtime.glwrap.getProgramParameterType(et.shaderindex, index_) === 1) value_ /= 100.0; if (params[index_] === value_) return; // no change params[index_] = value_; if (et.active) this.runtime.redraw = true; }; SysActs.prototype.SetLayerEffectParam = function (layer, effectname_, index_, value_) { if (!layer || !this.runtime.glwrap) return; var et = layer.getEffectByName(effectname_); if (!et) return; // effect name not found var params = layer.effect_params[et.index]; index_ = Math.floor(index_); if (index_ < 0 || index_ >= params.length) return; // effect index out of bounds if (this.runtime.glwrap.getProgramParameterType(et.shaderindex, index_) === 1) value_ /= 100.0; if (params[index_] === value_) return; // no change params[index_] = value_; if (et.active) this.runtime.redraw = true; }; SysActs.prototype.SaveState = function (slot_) { this.runtime.saveToSlot = slot_; }; SysActs.prototype.LoadState = function (slot_) { this.runtime.loadFromSlot = slot_; }; SysActs.prototype.LoadStateJSON = function (jsonstr_) { this.runtime.loadFromJson = jsonstr_; }; SysActs.prototype.SetHalfFramerateMode = function (set_) { this.runtime.halfFramerateMode = (set_ !== 0); }; SysActs.prototype.SetFullscreenQuality = function (q) { var isfullscreen = (document["mozFullScreen"] || document["webkitIsFullScreen"] || !!document["msFullscreenElement"] || document["fullScreen"] || this.isNodeFullscreen); if (!isfullscreen && this.runtime.fullscreen_mode === 0) return; this.runtime.wantFullscreenScalingQuality = (q !== 0); this.runtime["setSize"](this.runtime.lastWindowWidth, this.runtime.lastWindowHeight, true); }; SysActs.prototype.ResetPersisted = function () { var i, len; for (i = 0, len = this.runtime.layouts_by_index.length; i < len; ++i) { this.runtime.layouts_by_index[i].persist_data = {}; this.runtime.layouts_by_index[i].first_visit = true; } }; SysActs.prototype.RecreateInitialObjects = function (obj, x1, y1, x2, y2) { if (!obj) return; this.runtime.running_layout.recreateInitialObjects(obj, x1, y1, x2, y2); }; SysActs.prototype.SetPixelRounding = function (m) { this.runtime.pixel_rounding = (m !== 0); this.runtime.redraw = true; }; SysActs.prototype.SetMinimumFramerate = function (f) { if (f < 1) f = 1; if (f > 120) f = 120; this.runtime.minimumFramerate = f; }; function SortZOrderList(a, b) { var layerA = a[0]; var layerB = b[0]; var diff = layerA - layerB; if (diff !== 0) return diff; var indexA = a[1]; var indexB = b[1]; return indexA - indexB; }; function SortInstancesByValue(a, b) { return a[1] - b[1]; }; SysActs.prototype.SortZOrderByInstVar = function (obj, iv) { if (!obj) return; var i, len, inst, value, r, layer, toZ; var sol = obj.getCurrentSol(); var pickedInstances = sol.getObjects(); var zOrderList = []; var instValues = []; var layout = this.runtime.running_layout; var isFamily = obj.is_family; var familyIndex = obj.family_index; for (i = 0, len = pickedInstances.length; i < len; ++i) { inst = pickedInstances[i]; if (!inst.layer) continue; // not a world instance if (isFamily) value = inst.instance_vars[iv + inst.type.family_var_map[familyIndex]]; else value = inst.instance_vars[iv]; zOrderList.push([ inst.layer.index, inst.get_zindex() ]); instValues.push([ inst, value ]); } if (!zOrderList.length) return; // no instances were world instances zOrderList.sort(SortZOrderList); instValues.sort(SortInstancesByValue); for (i = 0, len = zOrderList.length; i < len; ++i) { inst = instValues[i][0]; // instance in the order we want layer = layout.layers[zOrderList[i][0]]; // layer to put it on toZ = zOrderList[i][1]; // Z index on that layer to put it if (layer.instances[toZ] !== inst) // not already got this instance there { layer.instances[toZ] = inst; // update instance inst.layer = layer; // update instance's layer reference (could have changed) layer.setZIndicesStaleFrom(toZ); // mark Z indices stale from this point since they have changed } } }; sysProto.acts = new SysActs(); function SysExps() {}; SysExps.prototype["int"] = function(ret, x) { if (cr.is_string(x)) { ret.set_int(parseInt(x, 10)); if (isNaN(ret.data)) ret.data = 0; } else ret.set_int(x); }; SysExps.prototype["float"] = function(ret, x) { if (cr.is_string(x)) { ret.set_float(parseFloat(x)); if (isNaN(ret.data)) ret.data = 0; } else ret.set_float(x); }; SysExps.prototype.str = function(ret, x) { if (cr.is_string(x)) ret.set_string(x); else ret.set_string(x.toString()); }; SysExps.prototype.len = function(ret, x) { ret.set_int(x.length || 0); }; SysExps.prototype.random = function (ret, a, b) { if (b === undefined) { ret.set_float(Math.random() * a); } else { ret.set_float(Math.random() * (b - a) + a); } }; SysExps.prototype.sqrt = function(ret, x) { ret.set_float(Math.sqrt(x)); }; SysExps.prototype.abs = function(ret, x) { ret.set_float(Math.abs(x)); }; SysExps.prototype.round = function(ret, x) { ret.set_int(Math.round(x)); }; SysExps.prototype.floor = function(ret, x) { ret.set_int(Math.floor(x)); }; SysExps.prototype.ceil = function(ret, x) { ret.set_int(Math.ceil(x)); }; SysExps.prototype.sin = function(ret, x) { ret.set_float(Math.sin(cr.to_radians(x))); }; SysExps.prototype.cos = function(ret, x) { ret.set_float(Math.cos(cr.to_radians(x))); }; SysExps.prototype.tan = function(ret, x) { ret.set_float(Math.tan(cr.to_radians(x))); }; SysExps.prototype.asin = function(ret, x) { ret.set_float(cr.to_degrees(Math.asin(x))); }; SysExps.prototype.acos = function(ret, x) { ret.set_float(cr.to_degrees(Math.acos(x))); }; SysExps.prototype.atan = function(ret, x) { ret.set_float(cr.to_degrees(Math.atan(x))); }; SysExps.prototype.exp = function(ret, x) { ret.set_float(Math.exp(x)); }; SysExps.prototype.ln = function(ret, x) { ret.set_float(Math.log(x)); }; SysExps.prototype.log10 = function(ret, x) { ret.set_float(Math.log(x) / Math.LN10); }; SysExps.prototype.max = function(ret) { var max_ = arguments[1]; if (typeof max_ !== "number") max_ = 0; var i, len, a; for (i = 2, len = arguments.length; i < len; i++) { a = arguments[i]; if (typeof a !== "number") continue; // ignore non-numeric types if (max_ < a) max_ = a; } ret.set_float(max_); }; SysExps.prototype.min = function(ret) { var min_ = arguments[1]; if (typeof min_ !== "number") min_ = 0; var i, len, a; for (i = 2, len = arguments.length; i < len; i++) { a = arguments[i]; if (typeof a !== "number") continue; // ignore non-numeric types if (min_ > a) min_ = a; } ret.set_float(min_); }; SysExps.prototype.dt = function(ret) { ret.set_float(this.runtime.dt); }; SysExps.prototype.timescale = function(ret) { ret.set_float(this.runtime.timescale); }; SysExps.prototype.wallclocktime = function(ret) { ret.set_float((Date.now() - this.runtime.start_time) / 1000.0); }; SysExps.prototype.time = function(ret) { ret.set_float(this.runtime.kahanTime.sum); }; SysExps.prototype.tickcount = function(ret) { ret.set_int(this.runtime.tickcount); }; SysExps.prototype.objectcount = function(ret) { ret.set_int(this.runtime.objectcount); }; SysExps.prototype.fps = function(ret) { ret.set_int(this.runtime.fps); }; SysExps.prototype.loopindex = function(ret, name_) { var loop, i, len; if (!this.runtime.loop_stack.length) { ret.set_int(0); return; } if (name_) { for (i = this.runtime.loop_stack_index; i >= 0; --i) { loop = this.runtime.loop_stack[i]; if (loop.name === name_) { ret.set_int(loop.index); return; } } ret.set_int(0); } else { loop = this.runtime.getCurrentLoop(); ret.set_int(loop ? loop.index : -1); } }; SysExps.prototype.distance = function(ret, x1, y1, x2, y2) { ret.set_float(cr.distanceTo(x1, y1, x2, y2)); }; SysExps.prototype.angle = function(ret, x1, y1, x2, y2) { ret.set_float(cr.to_degrees(cr.angleTo(x1, y1, x2, y2))); }; SysExps.prototype.scrollx = function(ret) { ret.set_float(this.runtime.running_layout.scrollX); }; SysExps.prototype.scrolly = function(ret) { ret.set_float(this.runtime.running_layout.scrollY); }; SysExps.prototype.newline = function(ret) { ret.set_string("\n"); }; SysExps.prototype.lerp = function(ret, a, b, x) { ret.set_float(cr.lerp(a, b, x)); }; SysExps.prototype.qarp = function(ret, a, b, c, x) { ret.set_float(cr.qarp(a, b, c, x)); }; SysExps.prototype.cubic = function(ret, a, b, c, d, x) { ret.set_float(cr.cubic(a, b, c, d, x)); }; SysExps.prototype.cosp = function(ret, a, b, x) { ret.set_float(cr.cosp(a, b, x)); }; SysExps.prototype.windowwidth = function(ret) { ret.set_int(this.runtime.width); }; SysExps.prototype.windowheight = function(ret) { ret.set_int(this.runtime.height); }; SysExps.prototype.uppercase = function(ret, str) { ret.set_string(cr.is_string(str) ? str.toUpperCase() : ""); }; SysExps.prototype.lowercase = function(ret, str) { ret.set_string(cr.is_string(str) ? str.toLowerCase() : ""); }; SysExps.prototype.clamp = function(ret, x, l, u) { if (x < l) ret.set_float(l); else if (x > u) ret.set_float(u); else ret.set_float(x); }; SysExps.prototype.layerscale = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); if (!layer) ret.set_float(0); else ret.set_float(layer.scale); }; SysExps.prototype.layeropacity = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); if (!layer) ret.set_float(0); else ret.set_float(layer.opacity * 100); }; SysExps.prototype.layerscalerate = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); if (!layer) ret.set_float(0); else ret.set_float(layer.zoomRate); }; SysExps.prototype.layerparallaxx = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); if (!layer) ret.set_float(0); else ret.set_float(layer.parallaxX * 100); }; SysExps.prototype.layerparallaxy = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); if (!layer) ret.set_float(0); else ret.set_float(layer.parallaxY * 100); }; SysExps.prototype.layerindex = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); if (!layer) ret.set_int(-1); else ret.set_int(layer.index); }; SysExps.prototype.layoutscale = function (ret) { if (this.runtime.running_layout) ret.set_float(this.runtime.running_layout.scale); else ret.set_float(0); }; SysExps.prototype.layoutangle = function (ret) { ret.set_float(cr.to_degrees(this.runtime.running_layout.angle)); }; SysExps.prototype.layerangle = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); if (!layer) ret.set_float(0); else ret.set_float(cr.to_degrees(layer.angle)); }; SysExps.prototype.layoutwidth = function (ret) { ret.set_int(this.runtime.running_layout.width); }; SysExps.prototype.layoutheight = function (ret) { ret.set_int(this.runtime.running_layout.height); }; SysExps.prototype.find = function (ret, text, searchstr) { if (cr.is_string(text) && cr.is_string(searchstr)) ret.set_int(text.search(new RegExp(cr.regexp_escape(searchstr), "i"))); else ret.set_int(-1); }; SysExps.prototype.findcase = function (ret, text, searchstr) { if (cr.is_string(text) && cr.is_string(searchstr)) ret.set_int(text.search(new RegExp(cr.regexp_escape(searchstr), ""))); else ret.set_int(-1); }; SysExps.prototype.left = function (ret, text, n) { ret.set_string(cr.is_string(text) ? text.substr(0, n) : ""); }; SysExps.prototype.right = function (ret, text, n) { ret.set_string(cr.is_string(text) ? text.substr(text.length - n) : ""); }; SysExps.prototype.mid = function (ret, text, index_, length_) { ret.set_string(cr.is_string(text) ? text.substr(index_, length_) : ""); }; SysExps.prototype.tokenat = function (ret, text, index_, sep) { if (cr.is_string(text) && cr.is_string(sep)) { var arr = text.split(sep); var i = cr.floor(index_); if (i < 0 || i >= arr.length) ret.set_string(""); else ret.set_string(arr[i]); } else ret.set_string(""); }; SysExps.prototype.tokencount = function (ret, text, sep) { if (cr.is_string(text) && text.length) ret.set_int(text.split(sep).length); else ret.set_int(0); }; SysExps.prototype.replace = function (ret, text, find_, replace_) { if (cr.is_string(text) && cr.is_string(find_) && cr.is_string(replace_)) ret.set_string(text.replace(new RegExp(cr.regexp_escape(find_), "gi"), replace_)); else ret.set_string(cr.is_string(text) ? text : ""); }; SysExps.prototype.trim = function (ret, text) { ret.set_string(cr.is_string(text) ? text.trim() : ""); }; SysExps.prototype.pi = function (ret) { ret.set_float(cr.PI); }; SysExps.prototype.layoutname = function (ret) { if (this.runtime.running_layout) ret.set_string(this.runtime.running_layout.name); else ret.set_string(""); }; SysExps.prototype.renderer = function (ret) { ret.set_string(this.runtime.gl ? "webgl" : "canvas2d"); }; SysExps.prototype.rendererdetail = function (ret) { ret.set_string(this.runtime.glUnmaskedRenderer); }; SysExps.prototype.anglediff = function (ret, a, b) { ret.set_float(cr.to_degrees(cr.angleDiff(cr.to_radians(a), cr.to_radians(b)))); }; SysExps.prototype.choose = function (ret) { var index = cr.floor(Math.random() * (arguments.length - 1)); ret.set_any(arguments[index + 1]); }; SysExps.prototype.rgb = function (ret, r, g, b) { ret.set_int(cr.RGB(r, g, b)); }; SysExps.prototype.projectversion = function (ret) { ret.set_string(this.runtime.versionstr); }; SysExps.prototype.projectname = function (ret) { ret.set_string(this.runtime.projectName); }; SysExps.prototype.anglelerp = function (ret, a, b, x) { a = cr.to_radians(a); b = cr.to_radians(b); var diff = cr.angleDiff(a, b); if (cr.angleClockwise(b, a)) { ret.set_float(cr.to_clamped_degrees(a + diff * x)); } else { ret.set_float(cr.to_clamped_degrees(a - diff * x)); } }; SysExps.prototype.anglerotate = function (ret, a, b, c) { a = cr.to_radians(a); b = cr.to_radians(b); c = cr.to_radians(c); ret.set_float(cr.to_clamped_degrees(cr.angleRotate(a, b, c))); }; SysExps.prototype.zeropad = function (ret, n, d) { var s = (n < 0 ? "-" : ""); if (n < 0) n = -n; var zeroes = d - n.toString().length; for (var i = 0; i < zeroes; i++) s += "0"; ret.set_string(s + n.toString()); }; SysExps.prototype.cpuutilisation = function (ret) { ret.set_float(this.runtime.cpuutilisation / 1000); }; SysExps.prototype.viewportleft = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.viewLeft : 0); }; SysExps.prototype.viewporttop = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.viewTop : 0); }; SysExps.prototype.viewportright = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.viewRight : 0); }; SysExps.prototype.viewportbottom = function (ret, layerparam) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.viewBottom : 0); }; SysExps.prototype.loadingprogress = function (ret) { ret.set_float(this.runtime.loadingprogress); }; SysExps.prototype.unlerp = function(ret, a, b, y) { ret.set_float(cr.unlerp(a, b, y)); }; SysExps.prototype.canvassnapshot = function (ret) { ret.set_string(this.runtime.snapshotData); }; SysExps.prototype.urlencode = function (ret, s) { ret.set_string(encodeURIComponent(s)); }; SysExps.prototype.urldecode = function (ret, s) { ret.set_string(decodeURIComponent(s)); }; SysExps.prototype.canvastolayerx = function (ret, layerparam, x, y) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.canvasToLayer(x, y, true) : 0); }; SysExps.prototype.canvastolayery = function (ret, layerparam, x, y) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.canvasToLayer(x, y, false) : 0); }; SysExps.prototype.layertocanvasx = function (ret, layerparam, x, y) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.layerToCanvas(x, y, true) : 0); }; SysExps.prototype.layertocanvasy = function (ret, layerparam, x, y) { var layer = this.runtime.getLayer(layerparam); ret.set_float(layer ? layer.layerToCanvas(x, y, false) : 0); }; SysExps.prototype.savestatejson = function (ret) { ret.set_string(this.runtime.lastSaveJson); }; SysExps.prototype.imagememoryusage = function (ret) { if (this.runtime.glwrap) ret.set_float(Math.round(100 * this.runtime.glwrap.estimateVRAM() / (1024 * 1024)) / 100); else ret.set_float(0); }; SysExps.prototype.regexsearch = function (ret, str_, regex_, flags_) { var regex = getRegex(regex_, flags_); ret.set_int(str_ ? str_.search(regex) : -1); }; SysExps.prototype.regexreplace = function (ret, str_, regex_, flags_, replace_) { var regex = getRegex(regex_, flags_); ret.set_string(str_ ? str_.replace(regex, replace_) : ""); }; var regexMatches = []; var lastMatchesStr = ""; var lastMatchesRegex = ""; var lastMatchesFlags = ""; function updateRegexMatches(str_, regex_, flags_) { if (str_ === lastMatchesStr && regex_ === lastMatchesRegex && flags_ === lastMatchesFlags) return; var regex = getRegex(regex_, flags_); regexMatches = str_.match(regex); lastMatchesStr = str_; lastMatchesRegex = regex_; lastMatchesFlags = flags_; }; SysExps.prototype.regexmatchcount = function (ret, str_, regex_, flags_) { var regex = getRegex(regex_, flags_); updateRegexMatches(str_.toString(), regex_, flags_); ret.set_int(regexMatches ? regexMatches.length : 0); }; SysExps.prototype.regexmatchat = function (ret, str_, regex_, flags_, index_) { index_ = Math.floor(index_); var regex = getRegex(regex_, flags_); updateRegexMatches(str_.toString(), regex_, flags_); if (!regexMatches || index_ < 0 || index_ >= regexMatches.length) ret.set_string(""); else ret.set_string(regexMatches[index_]); }; SysExps.prototype.infinity = function (ret) { ret.set_float(Infinity); }; SysExps.prototype.setbit = function (ret, n, b, v) { n = n | 0; b = b | 0; v = (v !== 0 ? 1 : 0); ret.set_int((n & ~(1 << b)) | (v << b)); }; SysExps.prototype.togglebit = function (ret, n, b) { n = n | 0; b = b | 0; ret.set_int(n ^ (1 << b)); }; SysExps.prototype.getbit = function (ret, n, b) { n = n | 0; b = b | 0; ret.set_int((n & (1 << b)) ? 1 : 0); }; SysExps.prototype.originalwindowwidth = function (ret) { ret.set_int(this.runtime.original_width); }; SysExps.prototype.originalwindowheight = function (ret) { ret.set_int(this.runtime.original_height); }; sysProto.exps = new SysExps(); sysProto.runWaits = function () { var i, j, len, w, k, s, ss; var evinfo = this.runtime.getCurrentEventStack(); for (i = 0, len = this.waits.length; i < len; i++) { w = this.waits[i]; if (w.time === -1) // signalled wait { if (!w.signalled) continue; // not yet signalled } else // timer wait { if (w.time > this.runtime.kahanTime.sum) continue; // timer not yet expired } evinfo.current_event = w.ev; evinfo.actindex = w.actindex; evinfo.cndindex = 0; for (k in w.sols) { if (w.sols.hasOwnProperty(k)) { s = this.runtime.types_by_index[parseInt(k, 10)].getCurrentSol(); ss = w.sols[k]; s.select_all = ss.sa; cr.shallowAssignArray(s.instances, ss.insts); freeSolStateObject(ss); } } w.ev.resume_actions_and_subevents(); this.runtime.clearSol(w.solModifiers); w.deleteme = true; } for (i = 0, j = 0, len = this.waits.length; i < len; i++) { w = this.waits[i]; this.waits[j] = w; if (w.deleteme) freeWaitObject(w); else j++; } cr.truncateArray(this.waits, j); }; }()); ; (function () { cr.add_common_aces = function (m, pluginProto) { var singleglobal_ = m[1]; var position_aces = m[3]; var size_aces = m[4]; var angle_aces = m[5]; var appearance_aces = m[6]; var zorder_aces = m[7]; var effects_aces = m[8]; if (!pluginProto.cnds) pluginProto.cnds = {}; if (!pluginProto.acts) pluginProto.acts = {}; if (!pluginProto.exps) pluginProto.exps = {}; var cnds = pluginProto.cnds; var acts = pluginProto.acts; var exps = pluginProto.exps; if (position_aces) { cnds.CompareX = function (cmp, x) { return cr.do_cmp(this.x, cmp, x); }; cnds.CompareY = function (cmp, y) { return cr.do_cmp(this.y, cmp, y); }; cnds.IsOnScreen = function () { var layer = this.layer; this.update_bbox(); var bbox = this.bbox; return !(bbox.right < layer.viewLeft || bbox.bottom < layer.viewTop || bbox.left > layer.viewRight || bbox.top > layer.viewBottom); }; cnds.IsOutsideLayout = function () { this.update_bbox(); var bbox = this.bbox; var layout = this.runtime.running_layout; return (bbox.right < 0 || bbox.bottom < 0 || bbox.left > layout.width || bbox.top > layout.height); }; cnds.PickDistance = function (which, x, y) { var sol = this.getCurrentSol(); var instances = sol.getObjects(); if (!instances.length) return false; var inst = instances[0]; var pickme = inst; var dist = cr.distanceTo(inst.x, inst.y, x, y); var i, len, d; for (i = 1, len = instances.length; i < len; i++) { inst = instances[i]; d = cr.distanceTo(inst.x, inst.y, x, y); if ((which === 0 && d < dist) || (which === 1 && d > dist)) { dist = d; pickme = inst; } } sol.pick_one(pickme); return true; }; acts.SetX = function (x) { if (this.x !== x) { this.x = x; this.set_bbox_changed(); } }; acts.SetY = function (y) { if (this.y !== y) { this.y = y; this.set_bbox_changed(); } }; acts.SetPos = function (x, y) { if (this.x !== x || this.y !== y) { this.x = x; this.y = y; this.set_bbox_changed(); } }; acts.SetPosToObject = function (obj, imgpt) { var inst = obj.getPairedInstance(this); if (!inst) return; var newx, newy; if (inst.getImagePoint) { newx = inst.getImagePoint(imgpt, true); newy = inst.getImagePoint(imgpt, false); } else { newx = inst.x; newy = inst.y; } if (this.x !== newx || this.y !== newy) { this.x = newx; this.y = newy; this.set_bbox_changed(); } }; acts.MoveForward = function (dist) { if (dist !== 0) { this.x += Math.cos(this.angle) * dist; this.y += Math.sin(this.angle) * dist; this.set_bbox_changed(); } }; acts.MoveAtAngle = function (a, dist) { if (dist !== 0) { this.x += Math.cos(cr.to_radians(a)) * dist; this.y += Math.sin(cr.to_radians(a)) * dist; this.set_bbox_changed(); } }; exps.X = function (ret) { ret.set_float(this.x); }; exps.Y = function (ret) { ret.set_float(this.y); }; exps.dt = function (ret) { ret.set_float(this.runtime.getDt(this)); }; } if (size_aces) { cnds.CompareWidth = function (cmp, w) { return cr.do_cmp(this.width, cmp, w); }; cnds.CompareHeight = function (cmp, h) { return cr.do_cmp(this.height, cmp, h); }; acts.SetWidth = function (w) { if (this.width !== w) { this.width = w; this.set_bbox_changed(); } }; acts.SetHeight = function (h) { if (this.height !== h) { this.height = h; this.set_bbox_changed(); } }; acts.SetSize = function (w, h) { if (this.width !== w || this.height !== h) { this.width = w; this.height = h; this.set_bbox_changed(); } }; exps.Width = function (ret) { ret.set_float(this.width); }; exps.Height = function (ret) { ret.set_float(this.height); }; exps.BBoxLeft = function (ret) { this.update_bbox(); ret.set_float(this.bbox.left); }; exps.BBoxTop = function (ret) { this.update_bbox(); ret.set_float(this.bbox.top); }; exps.BBoxRight = function (ret) { this.update_bbox(); ret.set_float(this.bbox.right); }; exps.BBoxBottom = function (ret) { this.update_bbox(); ret.set_float(this.bbox.bottom); }; } if (angle_aces) { cnds.AngleWithin = function (within, a) { return cr.angleDiff(this.angle, cr.to_radians(a)) <= cr.to_radians(within); }; cnds.IsClockwiseFrom = function (a) { return cr.angleClockwise(this.angle, cr.to_radians(a)); }; cnds.IsBetweenAngles = function (a, b) { var lower = cr.to_clamped_radians(a); var upper = cr.to_clamped_radians(b); var angle = cr.clamp_angle(this.angle); var obtuse = (!cr.angleClockwise(upper, lower)); if (obtuse) return !(!cr.angleClockwise(angle, lower) && cr.angleClockwise(angle, upper)); else return cr.angleClockwise(angle, lower) && !cr.angleClockwise(angle, upper); }; acts.SetAngle = function (a) { var newangle = cr.to_radians(cr.clamp_angle_degrees(a)); if (isNaN(newangle)) return; if (this.angle !== newangle) { this.angle = newangle; this.set_bbox_changed(); } }; acts.RotateClockwise = function (a) { if (a !== 0 && !isNaN(a)) { this.angle += cr.to_radians(a); this.angle = cr.clamp_angle(this.angle); this.set_bbox_changed(); } }; acts.RotateCounterclockwise = function (a) { if (a !== 0 && !isNaN(a)) { this.angle -= cr.to_radians(a); this.angle = cr.clamp_angle(this.angle); this.set_bbox_changed(); } }; acts.RotateTowardAngle = function (amt, target) { var newangle = cr.angleRotate(this.angle, cr.to_radians(target), cr.to_radians(amt)); if (isNaN(newangle)) return; if (this.angle !== newangle) { this.angle = newangle; this.set_bbox_changed(); } }; acts.RotateTowardPosition = function (amt, x, y) { var dx = x - this.x; var dy = y - this.y; var target = Math.atan2(dy, dx); var newangle = cr.angleRotate(this.angle, target, cr.to_radians(amt)); if (isNaN(newangle)) return; if (this.angle !== newangle) { this.angle = newangle; this.set_bbox_changed(); } }; acts.SetTowardPosition = function (x, y) { var dx = x - this.x; var dy = y - this.y; var newangle = Math.atan2(dy, dx); if (isNaN(newangle)) return; if (this.angle !== newangle) { this.angle = newangle; this.set_bbox_changed(); } }; exps.Angle = function (ret) { ret.set_float(cr.to_clamped_degrees(this.angle)); }; } if (!singleglobal_) { cnds.CompareInstanceVar = function (iv, cmp, val) { return cr.do_cmp(this.instance_vars[iv], cmp, val); }; cnds.IsBoolInstanceVarSet = function (iv) { return this.instance_vars[iv]; }; cnds.PickInstVarHiLow = function (which, iv) { var sol = this.getCurrentSol(); var instances = sol.getObjects(); if (!instances.length) return false; var inst = instances[0]; var pickme = inst; var val = inst.instance_vars[iv]; var i, len, v; for (i = 1, len = instances.length; i < len; i++) { inst = instances[i]; v = inst.instance_vars[iv]; if ((which === 0 && v < val) || (which === 1 && v > val)) { val = v; pickme = inst; } } sol.pick_one(pickme); return true; }; cnds.PickByUID = function (u) { var i, len, j, inst, families, instances, sol; var cnd = this.runtime.getCurrentCondition(); if (cnd.inverted) { sol = this.getCurrentSol(); if (sol.select_all) { sol.select_all = false; cr.clearArray(sol.instances); cr.clearArray(sol.else_instances); instances = this.instances; for (i = 0, len = instances.length; i < len; i++) { inst = instances[i]; if (inst.uid === u) sol.else_instances.push(inst); else sol.instances.push(inst); } this.applySolToContainer(); return !!sol.instances.length; } else { for (i = 0, j = 0, len = sol.instances.length; i < len; i++) { inst = sol.instances[i]; sol.instances[j] = inst; if (inst.uid === u) { sol.else_instances.push(inst); } else j++; } cr.truncateArray(sol.instances, j); this.applySolToContainer(); return !!sol.instances.length; } } else { inst = this.runtime.getObjectByUID(u); if (!inst) return false; sol = this.getCurrentSol(); if (!sol.select_all && sol.instances.indexOf(inst) === -1) return false; // not picked if (this.is_family) { families = inst.type.families; for (i = 0, len = families.length; i < len; i++) { if (families[i] === this) { sol.pick_one(inst); this.applySolToContainer(); return true; } } } else if (inst.type === this) { sol.pick_one(inst); this.applySolToContainer(); return true; } return false; } }; cnds.OnCreated = function () { return true; }; cnds.OnDestroyed = function () { return true; }; acts.SetInstanceVar = function (iv, val) { var myinstvars = this.instance_vars; if (cr.is_number(myinstvars[iv])) { if (cr.is_number(val)) myinstvars[iv] = val; else myinstvars[iv] = parseFloat(val); } else if (cr.is_string(myinstvars[iv])) { if (cr.is_string(val)) myinstvars[iv] = val; else myinstvars[iv] = val.toString(); } else ; }; acts.AddInstanceVar = function (iv, val) { var myinstvars = this.instance_vars; if (cr.is_number(myinstvars[iv])) { if (cr.is_number(val)) myinstvars[iv] += val; else myinstvars[iv] += parseFloat(val); } else if (cr.is_string(myinstvars[iv])) { if (cr.is_string(val)) myinstvars[iv] += val; else myinstvars[iv] += val.toString(); } else ; }; acts.SubInstanceVar = function (iv, val) { var myinstvars = this.instance_vars; if (cr.is_number(myinstvars[iv])) { if (cr.is_number(val)) myinstvars[iv] -= val; else myinstvars[iv] -= parseFloat(val); } else ; }; acts.SetBoolInstanceVar = function (iv, val) { this.instance_vars[iv] = val ? 1 : 0; }; acts.ToggleBoolInstanceVar = function (iv) { this.instance_vars[iv] = 1 - this.instance_vars[iv]; }; acts.Destroy = function () { this.runtime.DestroyInstance(this); }; if (!acts.LoadFromJsonString) { acts.LoadFromJsonString = function (str_) { var o, i, len, binst; try { o = JSON.parse(str_); } catch (e) { return; } this.runtime.loadInstanceFromJSON(this, o, true); if (this.afterLoad) this.afterLoad(); if (this.behavior_insts) { for (i = 0, len = this.behavior_insts.length; i < len; ++i) { binst = this.behavior_insts[i]; if (binst.afterLoad) binst.afterLoad(); } } }; } exps.Count = function (ret) { var count = ret.object_class.instances.length; var i, len, inst; for (i = 0, len = this.runtime.createRow.length; i < len; i++) { inst = this.runtime.createRow[i]; if (ret.object_class.is_family) { if (inst.type.families.indexOf(ret.object_class) >= 0) count++; } else { if (inst.type === ret.object_class) count++; } } ret.set_int(count); }; exps.PickedCount = function (ret) { ret.set_int(ret.object_class.getCurrentSol().getObjects().length); }; exps.UID = function (ret) { ret.set_int(this.uid); }; exps.IID = function (ret) { ret.set_int(this.get_iid()); }; if (!exps.AsJSON) { exps.AsJSON = function (ret) { ret.set_string(JSON.stringify(this.runtime.saveInstanceToJSON(this, true))); }; } } if (appearance_aces) { cnds.IsVisible = function () { return this.visible; }; acts.SetVisible = function (v) { if (!v !== !this.visible) { this.visible = !!v; this.runtime.redraw = true; } }; cnds.CompareOpacity = function (cmp, x) { return cr.do_cmp(cr.round6dp(this.opacity * 100), cmp, x); }; acts.SetOpacity = function (x) { var new_opacity = x / 100.0; if (new_opacity < 0) new_opacity = 0; else if (new_opacity > 1) new_opacity = 1; if (new_opacity !== this.opacity) { this.opacity = new_opacity; this.runtime.redraw = true; } }; exps.Opacity = function (ret) { ret.set_float(cr.round6dp(this.opacity * 100.0)); }; } if (zorder_aces) { cnds.IsOnLayer = function (layer_) { if (!layer_) return false; return this.layer === layer_; }; cnds.PickTopBottom = function (which_) { var sol = this.getCurrentSol(); var instances = sol.getObjects(); if (!instances.length) return false; var inst = instances[0]; var pickme = inst; var i, len; for (i = 1, len = instances.length; i < len; i++) { inst = instances[i]; if (which_ === 0) { if (inst.layer.index > pickme.layer.index || (inst.layer.index === pickme.layer.index && inst.get_zindex() > pickme.get_zindex())) { pickme = inst; } } else { if (inst.layer.index < pickme.layer.index || (inst.layer.index === pickme.layer.index && inst.get_zindex() < pickme.get_zindex())) { pickme = inst; } } } sol.pick_one(pickme); return true; }; acts.MoveToTop = function () { var layer = this.layer; var layer_instances = layer.instances; if (layer_instances.length && layer_instances[layer_instances.length - 1] === this) return; // is already at top layer.removeFromInstanceList(this, false); layer.appendToInstanceList(this, false); this.runtime.redraw = true; }; acts.MoveToBottom = function () { var layer = this.layer; var layer_instances = layer.instances; if (layer_instances.length && layer_instances[0] === this) return; // is already at bottom layer.removeFromInstanceList(this, false); layer.prependToInstanceList(this, false); this.runtime.redraw = true; }; acts.MoveToLayer = function (layerMove) { if (!layerMove || layerMove == this.layer) return; this.layer.removeFromInstanceList(this, true); this.layer = layerMove; layerMove.appendToInstanceList(this, true); this.runtime.redraw = true; }; acts.ZMoveToObject = function (where_, obj_) { var isafter = (where_ === 0); if (!obj_) return; var other = obj_.getFirstPicked(this); if (!other || other.uid === this.uid) return; if (this.layer.index !== other.layer.index) { this.layer.removeFromInstanceList(this, true); this.layer = other.layer; other.layer.appendToInstanceList(this, true); } this.layer.moveInstanceAdjacent(this, other, isafter); this.runtime.redraw = true; }; exps.LayerNumber = function (ret) { ret.set_int(this.layer.number); }; exps.LayerName = function (ret) { ret.set_string(this.layer.name); }; exps.ZIndex = function (ret) { ret.set_int(this.get_zindex()); }; } if (effects_aces) { acts.SetEffectEnabled = function (enable_, effectname_) { if (!this.runtime.glwrap) return; var i = this.type.getEffectIndexByName(effectname_); if (i < 0) return; // effect name not found var enable = (enable_ === 1); if (this.active_effect_flags[i] === enable) return; // no change this.active_effect_flags[i] = enable; this.updateActiveEffects(); this.runtime.redraw = true; }; acts.SetEffectParam = function (effectname_, index_, value_) { if (!this.runtime.glwrap) return; var i = this.type.getEffectIndexByName(effectname_); if (i < 0) return; // effect name not found var et = this.type.effect_types[i]; var params = this.effect_params[i]; index_ = Math.floor(index_); if (index_ < 0 || index_ >= params.length) return; // effect index out of bounds if (this.runtime.glwrap.getProgramParameterType(et.shaderindex, index_) === 1) value_ /= 100.0; if (params[index_] === value_) return; // no change params[index_] = value_; if (et.active) this.runtime.redraw = true; }; } }; cr.set_bbox_changed = function () { this.bbox_changed = true; // will recreate next time box requested this.cell_changed = true; this.type.any_cell_changed = true; // avoid unnecessary updateAllBBox() calls this.runtime.redraw = true; // assume runtime needs to redraw var i, len, callbacks = this.bbox_changed_callbacks; for (i = 0, len = callbacks.length; i < len; ++i) { callbacks[i](this); } if (this.layer.useRenderCells) this.update_bbox(); }; cr.add_bbox_changed_callback = function (f) { if (f) { this.bbox_changed_callbacks.push(f); } }; cr.update_bbox = function () { if (!this.bbox_changed) return; // bounding box not changed var bbox = this.bbox; var bquad = this.bquad; bbox.set(this.x, this.y, this.x + this.width, this.y + this.height); bbox.offset(-this.hotspotX * this.width, -this.hotspotY * this.height); if (!this.angle) { bquad.set_from_rect(bbox); // make bounding quad from box } else { bbox.offset(-this.x, -this.y); // translate to origin bquad.set_from_rotated_rect(bbox, this.angle); // rotate around origin bquad.offset(this.x, this.y); // translate back to original position bquad.bounding_box(bbox); } bbox.normalize(); this.bbox_changed = false; // bounding box up to date this.update_render_cell(); }; var tmprc = new cr.rect(0, 0, 0, 0); cr.update_render_cell = function () { if (!this.layer.useRenderCells) return; var mygrid = this.layer.render_grid; var bbox = this.bbox; tmprc.set(mygrid.XToCell(bbox.left), mygrid.YToCell(bbox.top), mygrid.XToCell(bbox.right), mygrid.YToCell(bbox.bottom)); if (this.rendercells.equals(tmprc)) return; if (this.rendercells.right < this.rendercells.left) mygrid.update(this, null, tmprc); // first insertion with invalid rect: don't provide old range else mygrid.update(this, this.rendercells, tmprc); this.rendercells.copy(tmprc); this.layer.render_list_stale = true; }; cr.update_collision_cell = function () { if (!this.cell_changed || !this.collisionsEnabled) return; this.update_bbox(); var mygrid = this.type.collision_grid; var bbox = this.bbox; tmprc.set(mygrid.XToCell(bbox.left), mygrid.YToCell(bbox.top), mygrid.XToCell(bbox.right), mygrid.YToCell(bbox.bottom)); if (this.collcells.equals(tmprc)) return; if (this.collcells.right < this.collcells.left) mygrid.update(this, null, tmprc); // first insertion with invalid rect: don't provide old range else mygrid.update(this, this.collcells, tmprc); this.collcells.copy(tmprc); this.cell_changed = false; }; cr.inst_contains_pt = function (x, y) { if (!this.bbox.contains_pt(x, y)) return false; if (!this.bquad.contains_pt(x, y)) return false; if (this.tilemap_exists) return this.testPointOverlapTile(x, y); if (this.collision_poly && !this.collision_poly.is_empty()) { this.collision_poly.cache_poly(this.width, this.height, this.angle); return this.collision_poly.contains_pt(x - this.x, y - this.y); } else return true; }; cr.inst_get_iid = function () { this.type.updateIIDs(); return this.iid; }; cr.inst_get_zindex = function () { this.layer.updateZIndices(); return this.zindex; }; cr.inst_updateActiveEffects = function () { cr.clearArray(this.active_effect_types); var i, len, et; var preserves_opaqueness = true; for (i = 0, len = this.active_effect_flags.length; i < len; i++) { if (this.active_effect_flags[i]) { et = this.type.effect_types[i]; this.active_effect_types.push(et); if (!et.preservesOpaqueness) preserves_opaqueness = false; } } this.uses_shaders = !!this.active_effect_types.length; this.shaders_preserve_opaqueness = preserves_opaqueness; }; cr.inst_toString = function () { return "Inst" + this.puid; }; cr.type_getFirstPicked = function (frominst) { if (frominst && frominst.is_contained && frominst.type != this) { var i, len, s; for (i = 0, len = frominst.siblings.length; i < len; i++) { s = frominst.siblings[i]; if (s.type == this) return s; } } var instances = this.getCurrentSol().getObjects(); if (instances.length) return instances[0]; else return null; }; cr.type_getPairedInstance = function (inst) { var instances = this.getCurrentSol().getObjects(); if (instances.length) return instances[inst.get_iid() % instances.length]; else return null; }; cr.type_updateIIDs = function () { if (!this.stale_iids || this.is_family) return; // up to date or is family - don't want family to overwrite IIDs var i, len; for (i = 0, len = this.instances.length; i < len; i++) this.instances[i].iid = i; var next_iid = i; var createRow = this.runtime.createRow; for (i = 0, len = createRow.length; i < len; ++i) { if (createRow[i].type === this) createRow[i].iid = next_iid++; } this.stale_iids = false; }; cr.type_getInstanceByIID = function (i) { if (i < this.instances.length) return this.instances[i]; i -= this.instances.length; var createRow = this.runtime.createRow; var j, lenj; for (j = 0, lenj = createRow.length; j < lenj; ++j) { if (createRow[j].type === this) { if (i === 0) return createRow[j]; --i; } } ; return null; }; cr.type_getCurrentSol = function () { return this.solstack[this.cur_sol]; }; cr.type_pushCleanSol = function () { this.cur_sol++; if (this.cur_sol === this.solstack.length) { this.solstack.push(new cr.selection(this)); } else { this.solstack[this.cur_sol].select_all = true; // else clear next SOL cr.clearArray(this.solstack[this.cur_sol].else_instances); } }; cr.type_pushCopySol = function () { this.cur_sol++; if (this.cur_sol === this.solstack.length) this.solstack.push(new cr.selection(this)); var clonesol = this.solstack[this.cur_sol]; var prevsol = this.solstack[this.cur_sol - 1]; if (prevsol.select_all) { clonesol.select_all = true; } else { clonesol.select_all = false; cr.shallowAssignArray(clonesol.instances, prevsol.instances); } cr.clearArray(clonesol.else_instances); }; cr.type_popSol = function () { ; this.cur_sol--; }; cr.type_getBehaviorByName = function (behname) { var i, len, j, lenj, f, index = 0; if (!this.is_family) { for (i = 0, len = this.families.length; i < len; i++) { f = this.families[i]; for (j = 0, lenj = f.behaviors.length; j < lenj; j++) { if (behname === f.behaviors[j].name) { this.extra["lastBehIndex"] = index; return f.behaviors[j]; } index++; } } } for (i = 0, len = this.behaviors.length; i < len; i++) { if (behname === this.behaviors[i].name) { this.extra["lastBehIndex"] = index; return this.behaviors[i]; } index++; } return null; }; cr.type_getBehaviorIndexByName = function (behname) { var b = this.getBehaviorByName(behname); if (b) return this.extra["lastBehIndex"]; else return -1; }; cr.type_getEffectIndexByName = function (name_) { var i, len; for (i = 0, len = this.effect_types.length; i < len; i++) { if (this.effect_types[i].name === name_) return i; } return -1; }; cr.type_applySolToContainer = function () { if (!this.is_contained || this.is_family) return; var i, len, j, lenj, t, sol, sol2; this.updateIIDs(); sol = this.getCurrentSol(); var select_all = sol.select_all; var es = this.runtime.getCurrentEventStack(); var orblock = es && es.current_event && es.current_event.orblock; for (i = 0, len = this.container.length; i < len; i++) { t = this.container[i]; if (t === this) continue; t.updateIIDs(); sol2 = t.getCurrentSol(); sol2.select_all = select_all; if (!select_all) { cr.clearArray(sol2.instances); for (j = 0, lenj = sol.instances.length; j < lenj; ++j) sol2.instances[j] = t.getInstanceByIID(sol.instances[j].iid); if (orblock) { cr.clearArray(sol2.else_instances); for (j = 0, lenj = sol.else_instances.length; j < lenj; ++j) sol2.else_instances[j] = t.getInstanceByIID(sol.else_instances[j].iid); } } } }; cr.type_toString = function () { return "Type" + this.sid; }; cr.do_cmp = function (x, cmp, y) { if (typeof x === "undefined" || typeof y === "undefined") return false; switch (cmp) { case 0: // equal return x === y; case 1: // not equal return x !== y; case 2: // less return x < y; case 3: // less/equal return x <= y; case 4: // greater return x > y; case 5: // greater/equal return x >= y; default: ; return false; } }; })(); cr.shaders = {}; ; ; cr.plugins_.AJAX = function(runtime) { this.runtime = runtime; }; (function () { var isNWjs = false; var path = null; var fs = null; var nw_appfolder = ""; var pluginProto = cr.plugins_.AJAX.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; this.lastData = ""; this.curTag = ""; this.progress = 0; this.timeout = -1; isNWjs = this.runtime.isNWjs; if (isNWjs) { path = require("path"); fs = require("fs"); var process = window["process"] || nw["process"]; nw_appfolder = path["dirname"](process["execPath"]) + "\\"; } }; var instanceProto = pluginProto.Instance.prototype; var theInstance = null; window["C2_AJAX_DCSide"] = function (event_, tag_, param_) { if (!theInstance) return; if (event_ === "success") { theInstance.curTag = tag_; theInstance.lastData = param_; theInstance.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyComplete, theInstance); theInstance.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnComplete, theInstance); } else if (event_ === "error") { theInstance.curTag = tag_; theInstance.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyError, theInstance); theInstance.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnError, theInstance); } else if (event_ === "progress") { theInstance.progress = param_; theInstance.curTag = tag_; theInstance.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnProgress, theInstance); } }; instanceProto.onCreate = function() { theInstance = this; }; instanceProto.saveToJSON = function () { return { "lastData": this.lastData }; }; instanceProto.loadFromJSON = function (o) { this.lastData = o["lastData"]; this.curTag = ""; this.progress = 0; }; var next_request_headers = {}; var next_override_mime = ""; instanceProto.doRequest = function (tag_, url_, method_, data_) { if (this.runtime.isDirectCanvas) { AppMobi["webview"]["execute"]('C2_AJAX_WebSide("' + tag_ + '", "' + url_ + '", "' + method_ + '", ' + (data_ ? '"' + data_ + '"' : "null") + ');'); return; } var self = this; var request = null; var doErrorFunc = function () { self.curTag = tag_; self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnError, self); }; var errorFunc = function () { if (isNWjs) { var filepath = nw_appfolder + url_; if (fs["existsSync"](filepath)) { fs["readFile"](filepath, {"encoding": "utf8"}, function (err, data) { if (err) { doErrorFunc(); return; } self.curTag = tag_; self.lastData = data.replace(/\r\n/g, "\n") self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyComplete, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnComplete, self); }); } else doErrorFunc(); } else doErrorFunc(); }; var progressFunc = function (e) { if (!e["lengthComputable"]) return; self.progress = e.loaded / e.total; self.curTag = tag_; self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnProgress, self); }; try { if (this.runtime.isWindowsPhone8) request = new ActiveXObject("Microsoft.XMLHTTP"); else request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState === 4) { self.curTag = tag_; if (request.responseText) self.lastData = request.responseText.replace(/\r\n/g, "\n"); // fix windows style line endings else self.lastData = ""; if (request.status >= 400) { self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnError, self); } else { if ((!isNWjs || self.lastData.length) && !(!isNWjs && request.status === 0 && !self.lastData.length)) { self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyComplete, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnComplete, self); } } } }; if (!this.runtime.isWindowsPhone8) { request.onerror = errorFunc; request.ontimeout = errorFunc; request.onabort = errorFunc; request["onprogress"] = progressFunc; } request.open(method_, url_); if (!this.runtime.isWindowsPhone8) { if (this.timeout >= 0 && typeof request["timeout"] !== "undefined") request["timeout"] = this.timeout; } try { request.responseType = "text"; } catch (e) {} if (data_) { if (request["setRequestHeader"] && !next_request_headers.hasOwnProperty("Content-Type")) { request["setRequestHeader"]("Content-Type", "application/x-www-form-urlencoded"); } } if (request["setRequestHeader"]) { var p; for (p in next_request_headers) { if (next_request_headers.hasOwnProperty(p)) { try { request["setRequestHeader"](p, next_request_headers[p]); } catch (e) {} } } next_request_headers = {}; } if (next_override_mime && request["overrideMimeType"]) { try { request["overrideMimeType"](next_override_mime); } catch (e) {} next_override_mime = ""; } if (data_) request.send(data_); else request.send(); } catch (e) { errorFunc(); } }; function Cnds() {}; Cnds.prototype.OnComplete = function (tag) { return cr.equals_nocase(tag, this.curTag); }; Cnds.prototype.OnAnyComplete = function (tag) { return true; }; Cnds.prototype.OnError = function (tag) { return cr.equals_nocase(tag, this.curTag); }; Cnds.prototype.OnAnyError = function (tag) { return true; }; Cnds.prototype.OnProgress = function (tag) { return cr.equals_nocase(tag, this.curTag); }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Request = function (tag_, url_) { var self = this; if (this.runtime.isWKWebView && !this.runtime.isAbsoluteUrl(url_)) { this.runtime.fetchLocalFileViaCordovaAsText(url_, function (str) { self.curTag = tag_; self.lastData = str.replace(/\r\n/g, "\n"); // fix windows style line endings self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyComplete, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnComplete, self); }, function (err) { self.curTag = tag_; self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnError, self); }); } else { this.doRequest(tag_, url_, "GET"); } }; Acts.prototype.RequestFile = function (tag_, file_) { var self = this; if (this.runtime.isWKWebView) { this.runtime.fetchLocalFileViaCordovaAsText(file_, function (str) { self.curTag = tag_; self.lastData = str.replace(/\r\n/g, "\n"); // fix windows style line endings self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyComplete, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnComplete, self); }, function (err) { self.curTag = tag_; self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnError, self); }); } else { this.doRequest(tag_, file_, "GET"); } }; Acts.prototype.Post = function (tag_, url_, data_, method_) { this.doRequest(tag_, url_, method_, data_); }; Acts.prototype.SetTimeout = function (t) { this.timeout = t * 1000; }; Acts.prototype.SetHeader = function (n, v) { next_request_headers[n] = v; }; Acts.prototype.OverrideMIMEType = function (m) { next_override_mime = m; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.LastData = function (ret) { ret.set_string(this.lastData); }; Exps.prototype.Progress = function (ret) { ret.set_float(this.progress); }; Exps.prototype.Tag = function (ret) { ret.set_string(this.curTag); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Arr = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Arr.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; var arrCache = []; function allocArray() { if (arrCache.length) return arrCache.pop(); else return []; }; if (!Array.isArray) { Array.isArray = function (vArg) { return Object.prototype.toString.call(vArg) === "[object Array]"; }; } function freeArray(a) { var i, len; for (i = 0, len = a.length; i < len; i++) { if (Array.isArray(a[i])) freeArray(a[i]); } cr.clearArray(a); arrCache.push(a); }; instanceProto.onCreate = function() { this.cx = this.properties[0]; this.cy = this.properties[1]; this.cz = this.properties[2]; if (!this.recycled) this.arr = allocArray(); var a = this.arr; a.length = this.cx; var x, y, z; for (x = 0; x < this.cx; x++) { if (!a[x]) a[x] = allocArray(); a[x].length = this.cy; for (y = 0; y < this.cy; y++) { if (!a[x][y]) a[x][y] = allocArray(); a[x][y].length = this.cz; for (z = 0; z < this.cz; z++) a[x][y][z] = 0; } } this.forX = []; this.forY = []; this.forZ = []; this.forDepth = -1; }; instanceProto.onDestroy = function () { var x; for (x = 0; x < this.cx; x++) freeArray(this.arr[x]); // will recurse down and recycle other arrays cr.clearArray(this.arr); }; instanceProto.at = function (x, y, z) { x = Math.floor(x); y = Math.floor(y); z = Math.floor(z); if (isNaN(x) || x < 0 || x > this.cx - 1) return 0; if (isNaN(y) || y < 0 || y > this.cy - 1) return 0; if (isNaN(z) || z < 0 || z > this.cz - 1) return 0; return this.arr[x][y][z]; }; instanceProto.set = function (x, y, z, val) { x = Math.floor(x); y = Math.floor(y); z = Math.floor(z); if (isNaN(x) || x < 0 || x > this.cx - 1) return; if (isNaN(y) || y < 0 || y > this.cy - 1) return; if (isNaN(z) || z < 0 || z > this.cz - 1) return; this.arr[x][y][z] = val; }; instanceProto.getAsJSON = function () { return JSON.stringify({ "c2array": true, "size": [this.cx, this.cy, this.cz], "data": this.arr }); }; instanceProto.saveToJSON = function () { return { "size": [this.cx, this.cy, this.cz], "data": this.arr }; }; instanceProto.loadFromJSON = function (o) { var sz = o["size"]; this.cx = sz[0]; this.cy = sz[1]; this.cz = sz[2]; this.arr = o["data"]; }; instanceProto.setSize = function (w, h, d) { if (w < 0) w = 0; if (h < 0) h = 0; if (d < 0) d = 0; if (this.cx === w && this.cy === h && this.cz === d) return; // no change this.cx = w; this.cy = h; this.cz = d; var x, y, z; var a = this.arr; a.length = w; for (x = 0; x < this.cx; x++) { if (cr.is_undefined(a[x])) a[x] = allocArray(); a[x].length = h; for (y = 0; y < this.cy; y++) { if (cr.is_undefined(a[x][y])) a[x][y] = allocArray(); a[x][y].length = d; for (z = 0; z < this.cz; z++) { if (cr.is_undefined(a[x][y][z])) a[x][y][z] = 0; } } } }; instanceProto.getForX = function () { if (this.forDepth >= 0 && this.forDepth < this.forX.length) return this.forX[this.forDepth]; else return 0; }; instanceProto.getForY = function () { if (this.forDepth >= 0 && this.forDepth < this.forY.length) return this.forY[this.forDepth]; else return 0; }; instanceProto.getForZ = function () { if (this.forDepth >= 0 && this.forDepth < this.forZ.length) return this.forZ[this.forDepth]; else return 0; }; function Cnds() {}; Cnds.prototype.CompareX = function (x, cmp, val) { return cr.do_cmp(this.at(x, 0, 0), cmp, val); }; Cnds.prototype.CompareXY = function (x, y, cmp, val) { return cr.do_cmp(this.at(x, y, 0), cmp, val); }; Cnds.prototype.CompareXYZ = function (x, y, z, cmp, val) { return cr.do_cmp(this.at(x, y, z), cmp, val); }; instanceProto.doForEachTrigger = function (current_event) { this.runtime.pushCopySol(current_event.solModifiers); current_event.retrigger(); this.runtime.popSol(current_event.solModifiers); }; Cnds.prototype.ArrForEach = function (dims) { var current_event = this.runtime.getCurrentEventStack().current_event; this.forDepth++; var forDepth = this.forDepth; if (forDepth === this.forX.length) { this.forX.push(0); this.forY.push(0); this.forZ.push(0); } else { this.forX[forDepth] = 0; this.forY[forDepth] = 0; this.forZ[forDepth] = 0; } switch (dims) { case 0: for (this.forX[forDepth] = 0; this.forX[forDepth] < this.cx; this.forX[forDepth]++) { for (this.forY[forDepth] = 0; this.forY[forDepth] < this.cy; this.forY[forDepth]++) { for (this.forZ[forDepth] = 0; this.forZ[forDepth] < this.cz; this.forZ[forDepth]++) { this.doForEachTrigger(current_event); } } } break; case 1: for (this.forX[forDepth] = 0; this.forX[forDepth] < this.cx; this.forX[forDepth]++) { for (this.forY[forDepth] = 0; this.forY[forDepth] < this.cy; this.forY[forDepth]++) { this.doForEachTrigger(current_event); } } break; case 2: for (this.forX[forDepth] = 0; this.forX[forDepth] < this.cx; this.forX[forDepth]++) { this.doForEachTrigger(current_event); } break; } this.forDepth--; return false; }; Cnds.prototype.CompareCurrent = function (cmp, val) { return cr.do_cmp(this.at(this.getForX(), this.getForY(), this.getForZ()), cmp, val); }; Cnds.prototype.Contains = function(val) { var x, y, z; for (x = 0; x < this.cx; x++) { for (y = 0; y < this.cy; y++) { for (z = 0; z < this.cz; z++) { if (this.arr[x][y][z] === val) return true; } } } return false; }; Cnds.prototype.IsEmpty = function () { return this.cx === 0 || this.cy === 0 || this.cz === 0; }; Cnds.prototype.CompareSize = function (axis, cmp, value) { var s = 0; switch (axis) { case 0: s = this.cx; break; case 1: s = this.cy; break; case 2: s = this.cz; break; } return cr.do_cmp(s, cmp, value); }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Clear = function () { var x, y, z; for (x = 0; x < this.cx; x++) for (y = 0; y < this.cy; y++) for (z = 0; z < this.cz; z++) this.arr[x][y][z] = 0; }; Acts.prototype.SetSize = function (w, h, d) { this.setSize(w, h, d); }; Acts.prototype.SetX = function (x, val) { this.set(x, 0, 0, val); }; Acts.prototype.SetXY = function (x, y, val) { this.set(x, y, 0, val); }; Acts.prototype.SetXYZ = function (x, y, z, val) { this.set(x, y, z, val); }; Acts.prototype.Push = function (where, value, axis) { var x = 0, y = 0, z = 0; var a = this.arr; switch (axis) { case 0: // X axis if (where === 0) // back { x = a.length; a.push(allocArray()); } else // front { x = 0; a.unshift(allocArray()); } a[x].length = this.cy; for ( ; y < this.cy; y++) { a[x][y] = allocArray(); a[x][y].length = this.cz; for (z = 0; z < this.cz; z++) a[x][y][z] = value; } this.cx++; break; case 1: // Y axis for ( ; x < this.cx; x++) { if (where === 0) // back { y = a[x].length; a[x].push(allocArray()); } else // front { y = 0; a[x].unshift(allocArray()); } a[x][y].length = this.cz; for (z = 0; z < this.cz; z++) a[x][y][z] = value; } this.cy++; break; case 2: // Z axis for ( ; x < this.cx; x++) { for (y = 0; y < this.cy; y++) { if (where === 0) // back { a[x][y].push(value); } else // front { a[x][y].unshift(value); } } } this.cz++; break; } }; Acts.prototype.Pop = function (where, axis) { var x = 0, y = 0, z = 0; var a = this.arr; switch (axis) { case 0: // X axis if (this.cx === 0) break; if (where === 0) // back { freeArray(a.pop()); } else // front { freeArray(a.shift()); } this.cx--; break; case 1: // Y axis if (this.cy === 0) break; for ( ; x < this.cx; x++) { if (where === 0) // back { freeArray(a[x].pop()); } else // front { freeArray(a[x].shift()); } } this.cy--; break; case 2: // Z axis if (this.cz === 0) break; for ( ; x < this.cx; x++) { for (y = 0; y < this.cy; y++) { if (where === 0) // back { a[x][y].pop(); } else // front { a[x][y].shift(); } } } this.cz--; break; } }; Acts.prototype.Reverse = function (axis) { var x = 0, y = 0, z = 0; var a = this.arr; if (this.cx === 0 || this.cy === 0 || this.cz === 0) return; // no point reversing empty array switch (axis) { case 0: // X axis a.reverse(); break; case 1: // Y axis for ( ; x < this.cx; x++) a[x].reverse(); break; case 2: // Z axis for ( ; x < this.cx; x++) for (y = 0; y < this.cy; y++) a[x][y].reverse(); break; } }; function compareValues(va, vb) { if (cr.is_number(va) && cr.is_number(vb)) return va - vb; else { var sa = "" + va; var sb = "" + vb; if (sa < sb) return -1; else if (sa > sb) return 1; else return 0; } } Acts.prototype.Sort = function (axis) { var x = 0, y = 0, z = 0; var a = this.arr; if (this.cx === 0 || this.cy === 0 || this.cz === 0) return; // no point sorting empty array switch (axis) { case 0: // X axis a.sort(function (a, b) { return compareValues(a[0][0], b[0][0]); }); break; case 1: // Y axis for ( ; x < this.cx; x++) { a[x].sort(function (a, b) { return compareValues(a[0], b[0]); }); } break; case 2: // Z axis for ( ; x < this.cx; x++) { for (y = 0; y < this.cy; y++) { a[x][y].sort(compareValues); } } break; } }; Acts.prototype.Delete = function (index, axis) { var x = 0, y = 0, z = 0; index = Math.floor(index); var a = this.arr; if (index < 0) return; switch (axis) { case 0: // X axis if (index >= this.cx) break; freeArray(a[index]); a.splice(index, 1); this.cx--; break; case 1: // Y axis if (index >= this.cy) break; for ( ; x < this.cx; x++) { freeArray(a[x][index]); a[x].splice(index, 1); } this.cy--; break; case 2: // Z axis if (index >= this.cz) break; for ( ; x < this.cx; x++) { for (y = 0; y < this.cy; y++) { a[x][y].splice(index, 1); } } this.cz--; break; } }; Acts.prototype.Insert = function (value, index, axis) { var x = 0, y = 0, z = 0; index = Math.floor(index); var a = this.arr; if (index < 0) return; switch (axis) { case 0: // X axis if (index > this.cx) return; x = index; a.splice(x, 0, allocArray()); a[x].length = this.cy; for ( ; y < this.cy; y++) { a[x][y] = allocArray(); a[x][y].length = this.cz; for (z = 0; z < this.cz; z++) a[x][y][z] = value; } this.cx++; break; case 1: // Y axis if (index > this.cy) return; for ( ; x < this.cx; x++) { y = index; a[x].splice(y, 0, allocArray()); a[x][y].length = this.cz; for (z = 0; z < this.cz; z++) a[x][y][z] = value; } this.cy++; break; case 2: // Z axis if (index > this.cz) return; for ( ; x < this.cx; x++) { for (y = 0; y < this.cy; y++) { a[x][y].splice(index, 0, value); } } this.cz++; break; } }; Acts.prototype.JSONLoad = function (json_) { var o; try { o = JSON.parse(json_); } catch(e) { return; } if (!o["c2array"]) // presumably not a c2array object return; var sz = o["size"]; this.cx = sz[0]; this.cy = sz[1]; this.cz = sz[2]; this.arr = o["data"]; }; Acts.prototype.JSONDownload = function (filename) { var a = document.createElement("a"); if (typeof a.download === "undefined") { var str = 'data:text/html,' + encodeURIComponent("

Download link

"); window.open(str); } else { var body = document.getElementsByTagName("body")[0]; a.textContent = filename; a.href = "data:application/json," + encodeURIComponent(this.getAsJSON()); a.download = filename; body.appendChild(a); var clickEvent = document.createEvent("MouseEvent"); clickEvent.initMouseEvent("click", true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null); a.dispatchEvent(clickEvent); body.removeChild(a); } }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.At = function (ret, x, y_, z_) { var y = y_ || 0; var z = z_ || 0; ret.set_any(this.at(x, y, z)); }; Exps.prototype.Width = function (ret) { ret.set_int(this.cx); }; Exps.prototype.Height = function (ret) { ret.set_int(this.cy); }; Exps.prototype.Depth = function (ret) { ret.set_int(this.cz); }; Exps.prototype.CurX = function (ret) { ret.set_int(this.getForX()); }; Exps.prototype.CurY = function (ret) { ret.set_int(this.getForY()); }; Exps.prototype.CurZ = function (ret) { ret.set_int(this.getForZ()); }; Exps.prototype.CurValue = function (ret) { ret.set_any(this.at(this.getForX(), this.getForY(), this.getForZ())); }; Exps.prototype.Front = function (ret) { ret.set_any(this.at(0, 0, 0)); }; Exps.prototype.Back = function (ret) { ret.set_any(this.at(this.cx - 1, 0, 0)); }; Exps.prototype.IndexOf = function (ret, v) { for (var i = 0; i < this.cx; i++) { if (this.arr[i][0][0] === v) { ret.set_int(i); return; } } ret.set_int(-1); }; Exps.prototype.LastIndexOf = function (ret, v) { for (var i = this.cx - 1; i >= 0; i--) { if (this.arr[i][0][0] === v) { ret.set_int(i); return; } } ret.set_int(-1); }; Exps.prototype.AsJSON = function (ret) { ret.set_string(this.getAsJSON()); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Audio = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Audio.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; var audRuntime = null; var audInst = null; var audTag = ""; var appPath = ""; // for Cordova only var API_HTML5 = 0; var API_WEBAUDIO = 1; var API_CORDOVA = 2; var API_APPMOBI = 3; var api = API_HTML5; var context = null; var audioBuffers = []; // cache of buffers var audioInstances = []; // cache of instances var lastAudio = null; var useOgg = false; // determined at create time var timescale_mode = 0; var silent = false; var masterVolume = 1; var listenerX = 0; var listenerY = 0; var isContextSuspended = false; var panningModel = 1; // HRTF var distanceModel = 1; // Inverse var refDistance = 10; var maxDistance = 10000; var rolloffFactor = 1; var micSource = null; var micTag = ""; var useNextTouchWorkaround = false; // heuristic in case play() does not return a promise and we have to guess if the play was blocked var playOnNextInput = []; // C2AudioInstances with HTMLAudioElements to play on next input event var playMusicAsSoundWorkaround = false; // play music tracks with Web Audio API var hasPlayedDummyBuffer = false; // dummy buffer played to unblock AudioContext on some platforms function addAudioToPlayOnNextInput(a) { var i = playOnNextInput.indexOf(a); if (i === -1) playOnNextInput.push(a); }; function tryPlayAudioElement(a) { var audioElem = a.instanceObject; var playRet; try { playRet = audioElem.play(); } catch (err) { addAudioToPlayOnNextInput(a); return; } if (playRet) // promise was returned { playRet.catch(function (err) { addAudioToPlayOnNextInput(a); }); } else if (useNextTouchWorkaround && !audRuntime.isInUserInputEvent) { addAudioToPlayOnNextInput(a); } }; function playQueuedAudio() { var i, len, m, playRet; if (!hasPlayedDummyBuffer && !isContextSuspended && context) { playDummyBuffer(); if (context["state"] === "running") hasPlayedDummyBuffer = true; } var tryPlay = playOnNextInput.slice(0); cr.clearArray(playOnNextInput); if (!silent) { for (i = 0, len = tryPlay.length; i < len; ++i) { m = tryPlay[i]; if (!m.stopped && !m.is_paused) { playRet = m.instanceObject.play(); if (playRet) { playRet.catch(function (err) { addAudioToPlayOnNextInput(m); }); } } } } }; function playDummyBuffer() { if (context["state"] === "suspended" && context["resume"]) context["resume"](); if (!context["createBuffer"]) return; var buffer = context["createBuffer"](1, 220, 22050); var source = context["createBufferSource"](); source["buffer"] = buffer; source["connect"](context["destination"]); startSource(source); }; document.addEventListener("pointerup", playQueuedAudio, true); document.addEventListener("touchend", playQueuedAudio, true); document.addEventListener("click", playQueuedAudio, true); document.addEventListener("keydown", playQueuedAudio, true); document.addEventListener("gamepadconnected", playQueuedAudio, true); function dbToLinear(x) { var v = dbToLinear_nocap(x); if (!isFinite(v)) // accidentally passing a string can result in NaN; set volume to 0 if so v = 0; if (v < 0) v = 0; if (v > 1) v = 1; return v; }; function linearToDb(x) { if (x < 0) x = 0; if (x > 1) x = 1; return linearToDb_nocap(x); }; function dbToLinear_nocap(x) { return Math.pow(10, x / 20); }; function linearToDb_nocap(x) { return (Math.log(x) / Math.log(10)) * 20; }; var effects = {}; function getDestinationForTag(tag) { tag = tag.toLowerCase(); if (effects.hasOwnProperty(tag)) { if (effects[tag].length) return effects[tag][0].getInputNode(); } return context["destination"]; }; function createGain() { if (context["createGain"]) return context["createGain"](); else return context["createGainNode"](); }; function createDelay(d) { if (context["createDelay"]) return context["createDelay"](d); else return context["createDelayNode"](d); }; function startSource(s, scheduledTime) { if (s["start"]) s["start"](scheduledTime || 0); else s["noteOn"](scheduledTime || 0); }; function startSourceAt(s, x, d, scheduledTime) { if (s["start"]) s["start"](scheduledTime || 0, x); else s["noteGrainOn"](scheduledTime || 0, x, d - x); }; function stopSource(s) { try { if (s["stop"]) s["stop"](0); else s["noteOff"](0); } catch (e) {} }; function setAudioParam(ap, value, ramp, time) { if (!ap) return; // iOS is missing some parameters ap["cancelScheduledValues"](0); if (time === 0) { ap["value"] = value; return; } var curTime = context["currentTime"]; time += curTime; switch (ramp) { case 0: // step ap["setValueAtTime"](value, time); break; case 1: // linear ap["setValueAtTime"](ap["value"], curTime); // to set what to ramp from ap["linearRampToValueAtTime"](value, time); break; case 2: // exponential ap["setValueAtTime"](ap["value"], curTime); // to set what to ramp from ap["exponentialRampToValueAtTime"](value, time); break; } }; var filterTypes = ["lowpass", "highpass", "bandpass", "lowshelf", "highshelf", "peaking", "notch", "allpass"]; function FilterEffect(type, freq, detune, q, gain, mix) { this.type = "filter"; this.params = [type, freq, detune, q, gain, mix]; this.inputNode = createGain(); this.wetNode = createGain(); this.wetNode["gain"]["value"] = mix; this.dryNode = createGain(); this.dryNode["gain"]["value"] = 1 - mix; this.filterNode = context["createBiquadFilter"](); if (typeof this.filterNode["type"] === "number") this.filterNode["type"] = type; else this.filterNode["type"] = filterTypes[type]; this.filterNode["frequency"]["value"] = freq; if (this.filterNode["detune"]) // iOS 6 doesn't have detune yet this.filterNode["detune"]["value"] = detune; this.filterNode["Q"]["value"] = q; this.filterNode["gain"]["value"] = gain; this.inputNode["connect"](this.filterNode); this.inputNode["connect"](this.dryNode); this.filterNode["connect"](this.wetNode); }; FilterEffect.prototype.connectTo = function (node) { this.wetNode["disconnect"](); this.wetNode["connect"](node); this.dryNode["disconnect"](); this.dryNode["connect"](node); }; FilterEffect.prototype.remove = function () { this.inputNode["disconnect"](); this.filterNode["disconnect"](); this.wetNode["disconnect"](); this.dryNode["disconnect"](); }; FilterEffect.prototype.getInputNode = function () { return this.inputNode; }; FilterEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[5] = value; setAudioParam(this.wetNode["gain"], value, ramp, time); setAudioParam(this.dryNode["gain"], 1 - value, ramp, time); break; case 1: // filter frequency this.params[1] = value; setAudioParam(this.filterNode["frequency"], value, ramp, time); break; case 2: // filter detune this.params[2] = value; setAudioParam(this.filterNode["detune"], value, ramp, time); break; case 3: // filter Q this.params[3] = value; setAudioParam(this.filterNode["Q"], value, ramp, time); break; case 4: // filter/delay gain (note value is in dB here) this.params[4] = value; setAudioParam(this.filterNode["gain"], value, ramp, time); break; } }; function DelayEffect(delayTime, delayGain, mix) { this.type = "delay"; this.params = [delayTime, delayGain, mix]; this.inputNode = createGain(); this.wetNode = createGain(); this.wetNode["gain"]["value"] = mix; this.dryNode = createGain(); this.dryNode["gain"]["value"] = 1 - mix; this.mainNode = createGain(); this.delayNode = createDelay(delayTime); this.delayNode["delayTime"]["value"] = delayTime; this.delayGainNode = createGain(); this.delayGainNode["gain"]["value"] = delayGain; this.inputNode["connect"](this.mainNode); this.inputNode["connect"](this.dryNode); this.mainNode["connect"](this.wetNode); this.mainNode["connect"](this.delayNode); this.delayNode["connect"](this.delayGainNode); this.delayGainNode["connect"](this.mainNode); }; DelayEffect.prototype.connectTo = function (node) { this.wetNode["disconnect"](); this.wetNode["connect"](node); this.dryNode["disconnect"](); this.dryNode["connect"](node); }; DelayEffect.prototype.remove = function () { this.inputNode["disconnect"](); this.mainNode["disconnect"](); this.delayNode["disconnect"](); this.delayGainNode["disconnect"](); this.wetNode["disconnect"](); this.dryNode["disconnect"](); }; DelayEffect.prototype.getInputNode = function () { return this.inputNode; }; DelayEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[2] = value; setAudioParam(this.wetNode["gain"], value, ramp, time); setAudioParam(this.dryNode["gain"], 1 - value, ramp, time); break; case 4: // filter/delay gain (note value is passed in dB but needs to be linear here) this.params[1] = dbToLinear(value); setAudioParam(this.delayGainNode["gain"], dbToLinear(value), ramp, time); break; case 5: // delay time this.params[0] = value; setAudioParam(this.delayNode["delayTime"], value, ramp, time); break; } }; function ConvolveEffect(buffer, normalize, mix, src) { this.type = "convolve"; this.params = [normalize, mix, src]; this.inputNode = createGain(); this.wetNode = createGain(); this.wetNode["gain"]["value"] = mix; this.dryNode = createGain(); this.dryNode["gain"]["value"] = 1 - mix; this.convolveNode = context["createConvolver"](); if (buffer) { this.convolveNode["normalize"] = normalize; this.convolveNode["buffer"] = buffer; } this.inputNode["connect"](this.convolveNode); this.inputNode["connect"](this.dryNode); this.convolveNode["connect"](this.wetNode); }; ConvolveEffect.prototype.connectTo = function (node) { this.wetNode["disconnect"](); this.wetNode["connect"](node); this.dryNode["disconnect"](); this.dryNode["connect"](node); }; ConvolveEffect.prototype.remove = function () { this.inputNode["disconnect"](); this.convolveNode["disconnect"](); this.wetNode["disconnect"](); this.dryNode["disconnect"](); }; ConvolveEffect.prototype.getInputNode = function () { return this.inputNode; }; ConvolveEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[1] = value; setAudioParam(this.wetNode["gain"], value, ramp, time); setAudioParam(this.dryNode["gain"], 1 - value, ramp, time); break; } }; function FlangerEffect(delay, modulation, freq, feedback, mix) { this.type = "flanger"; this.params = [delay, modulation, freq, feedback, mix]; this.inputNode = createGain(); this.dryNode = createGain(); this.dryNode["gain"]["value"] = 1 - (mix / 2); this.wetNode = createGain(); this.wetNode["gain"]["value"] = mix / 2; this.feedbackNode = createGain(); this.feedbackNode["gain"]["value"] = feedback; this.delayNode = createDelay(delay + modulation); this.delayNode["delayTime"]["value"] = delay; this.oscNode = context["createOscillator"](); this.oscNode["frequency"]["value"] = freq; this.oscGainNode = createGain(); this.oscGainNode["gain"]["value"] = modulation; this.inputNode["connect"](this.delayNode); this.inputNode["connect"](this.dryNode); this.delayNode["connect"](this.wetNode); this.delayNode["connect"](this.feedbackNode); this.feedbackNode["connect"](this.delayNode); this.oscNode["connect"](this.oscGainNode); this.oscGainNode["connect"](this.delayNode["delayTime"]); startSource(this.oscNode); }; FlangerEffect.prototype.connectTo = function (node) { this.dryNode["disconnect"](); this.dryNode["connect"](node); this.wetNode["disconnect"](); this.wetNode["connect"](node); }; FlangerEffect.prototype.remove = function () { this.inputNode["disconnect"](); this.delayNode["disconnect"](); this.oscNode["disconnect"](); this.oscGainNode["disconnect"](); this.dryNode["disconnect"](); this.wetNode["disconnect"](); this.feedbackNode["disconnect"](); }; FlangerEffect.prototype.getInputNode = function () { return this.inputNode; }; FlangerEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[4] = value; setAudioParam(this.wetNode["gain"], value / 2, ramp, time); setAudioParam(this.dryNode["gain"], 1 - (value / 2), ramp, time); break; case 6: // modulation this.params[1] = value / 1000; setAudioParam(this.oscGainNode["gain"], value / 1000, ramp, time); break; case 7: // modulation frequency this.params[2] = value; setAudioParam(this.oscNode["frequency"], value, ramp, time); break; case 8: // feedback this.params[3] = value / 100; setAudioParam(this.feedbackNode["gain"], value / 100, ramp, time); break; } }; function PhaserEffect(freq, detune, q, modulation, modfreq, mix) { this.type = "phaser"; this.params = [freq, detune, q, modulation, modfreq, mix]; this.inputNode = createGain(); this.dryNode = createGain(); this.dryNode["gain"]["value"] = 1 - (mix / 2); this.wetNode = createGain(); this.wetNode["gain"]["value"] = mix / 2; this.filterNode = context["createBiquadFilter"](); if (typeof this.filterNode["type"] === "number") this.filterNode["type"] = 7; // all-pass else this.filterNode["type"] = "allpass"; this.filterNode["frequency"]["value"] = freq; if (this.filterNode["detune"]) // iOS 6 doesn't have detune yet this.filterNode["detune"]["value"] = detune; this.filterNode["Q"]["value"] = q; this.oscNode = context["createOscillator"](); this.oscNode["frequency"]["value"] = modfreq; this.oscGainNode = createGain(); this.oscGainNode["gain"]["value"] = modulation; this.inputNode["connect"](this.filterNode); this.inputNode["connect"](this.dryNode); this.filterNode["connect"](this.wetNode); this.oscNode["connect"](this.oscGainNode); this.oscGainNode["connect"](this.filterNode["frequency"]); startSource(this.oscNode); }; PhaserEffect.prototype.connectTo = function (node) { this.dryNode["disconnect"](); this.dryNode["connect"](node); this.wetNode["disconnect"](); this.wetNode["connect"](node); }; PhaserEffect.prototype.remove = function () { this.inputNode["disconnect"](); this.filterNode["disconnect"](); this.oscNode["disconnect"](); this.oscGainNode["disconnect"](); this.dryNode["disconnect"](); this.wetNode["disconnect"](); }; PhaserEffect.prototype.getInputNode = function () { return this.inputNode; }; PhaserEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[5] = value; setAudioParam(this.wetNode["gain"], value / 2, ramp, time); setAudioParam(this.dryNode["gain"], 1 - (value / 2), ramp, time); break; case 1: // filter frequency this.params[0] = value; setAudioParam(this.filterNode["frequency"], value, ramp, time); break; case 2: // filter detune this.params[1] = value; setAudioParam(this.filterNode["detune"], value, ramp, time); break; case 3: // filter Q this.params[2] = value; setAudioParam(this.filterNode["Q"], value, ramp, time); break; case 6: // modulation this.params[3] = value; setAudioParam(this.oscGainNode["gain"], value, ramp, time); break; case 7: // modulation frequency this.params[4] = value; setAudioParam(this.oscNode["frequency"], value, ramp, time); break; } }; function GainEffect(g) { this.type = "gain"; this.params = [g]; this.node = createGain(); this.node["gain"]["value"] = g; }; GainEffect.prototype.connectTo = function (node_) { this.node["disconnect"](); this.node["connect"](node_); }; GainEffect.prototype.remove = function () { this.node["disconnect"](); }; GainEffect.prototype.getInputNode = function () { return this.node; }; GainEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 4: // gain this.params[0] = dbToLinear(value); setAudioParam(this.node["gain"], dbToLinear(value), ramp, time); break; } }; function TremoloEffect(freq, mix) { this.type = "tremolo"; this.params = [freq, mix]; this.node = createGain(); this.node["gain"]["value"] = 1 - (mix / 2); this.oscNode = context["createOscillator"](); this.oscNode["frequency"]["value"] = freq; this.oscGainNode = createGain(); this.oscGainNode["gain"]["value"] = mix / 2; this.oscNode["connect"](this.oscGainNode); this.oscGainNode["connect"](this.node["gain"]); startSource(this.oscNode); }; TremoloEffect.prototype.connectTo = function (node_) { this.node["disconnect"](); this.node["connect"](node_); }; TremoloEffect.prototype.remove = function () { this.oscNode["disconnect"](); this.oscGainNode["disconnect"](); this.node["disconnect"](); }; TremoloEffect.prototype.getInputNode = function () { return this.node; }; TremoloEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[1] = value; setAudioParam(this.node["gain"]["value"], 1 - (value / 2), ramp, time); setAudioParam(this.oscGainNode["gain"]["value"], value / 2, ramp, time); break; case 7: // modulation frequency this.params[0] = value; setAudioParam(this.oscNode["frequency"], value, ramp, time); break; } }; function RingModulatorEffect(freq, mix) { this.type = "ringmod"; this.params = [freq, mix]; this.inputNode = createGain(); this.wetNode = createGain(); this.wetNode["gain"]["value"] = mix; this.dryNode = createGain(); this.dryNode["gain"]["value"] = 1 - mix; this.ringNode = createGain(); this.ringNode["gain"]["value"] = 0; this.oscNode = context["createOscillator"](); this.oscNode["frequency"]["value"] = freq; this.oscNode["connect"](this.ringNode["gain"]); startSource(this.oscNode); this.inputNode["connect"](this.ringNode); this.inputNode["connect"](this.dryNode); this.ringNode["connect"](this.wetNode); }; RingModulatorEffect.prototype.connectTo = function (node_) { this.wetNode["disconnect"](); this.wetNode["connect"](node_); this.dryNode["disconnect"](); this.dryNode["connect"](node_); }; RingModulatorEffect.prototype.remove = function () { this.oscNode["disconnect"](); this.ringNode["disconnect"](); this.inputNode["disconnect"](); this.wetNode["disconnect"](); this.dryNode["disconnect"](); }; RingModulatorEffect.prototype.getInputNode = function () { return this.inputNode; }; RingModulatorEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[1] = value; setAudioParam(this.wetNode["gain"], value, ramp, time); setAudioParam(this.dryNode["gain"], 1 - value, ramp, time); break; case 7: // modulation frequency this.params[0] = value; setAudioParam(this.oscNode["frequency"], value, ramp, time); break; } }; function DistortionEffect(threshold, headroom, drive, makeupgain, mix) { this.type = "distortion"; this.params = [threshold, headroom, drive, makeupgain, mix]; this.inputNode = createGain(); this.preGain = createGain(); this.postGain = createGain(); this.setDrive(drive, dbToLinear_nocap(makeupgain)); this.wetNode = createGain(); this.wetNode["gain"]["value"] = mix; this.dryNode = createGain(); this.dryNode["gain"]["value"] = 1 - mix; this.waveShaper = context["createWaveShaper"](); this.curve = new Float32Array(65536); this.generateColortouchCurve(threshold, headroom); this.waveShaper.curve = this.curve; this.inputNode["connect"](this.preGain); this.inputNode["connect"](this.dryNode); this.preGain["connect"](this.waveShaper); this.waveShaper["connect"](this.postGain); this.postGain["connect"](this.wetNode); }; DistortionEffect.prototype.setDrive = function (drive, makeupgain) { if (drive < 0.01) drive = 0.01; this.preGain["gain"]["value"] = drive; this.postGain["gain"]["value"] = Math.pow(1 / drive, 0.6) * makeupgain; }; function e4(x, k) { return 1.0 - Math.exp(-k * x); } DistortionEffect.prototype.shape = function (x, linearThreshold, linearHeadroom) { var maximum = 1.05 * linearHeadroom * linearThreshold; var kk = (maximum - linearThreshold); var sign = x < 0 ? -1 : +1; var absx = x < 0 ? -x : x; var shapedInput = absx < linearThreshold ? absx : linearThreshold + kk * e4(absx - linearThreshold, 1.0 / kk); shapedInput *= sign; return shapedInput; }; DistortionEffect.prototype.generateColortouchCurve = function (threshold, headroom) { var linearThreshold = dbToLinear_nocap(threshold); var linearHeadroom = dbToLinear_nocap(headroom); var n = 65536; var n2 = n / 2; var x = 0; for (var i = 0; i < n2; ++i) { x = i / n2; x = this.shape(x, linearThreshold, linearHeadroom); this.curve[n2 + i] = x; this.curve[n2 - i - 1] = -x; } }; DistortionEffect.prototype.connectTo = function (node) { this.wetNode["disconnect"](); this.wetNode["connect"](node); this.dryNode["disconnect"](); this.dryNode["connect"](node); }; DistortionEffect.prototype.remove = function () { this.inputNode["disconnect"](); this.preGain["disconnect"](); this.waveShaper["disconnect"](); this.postGain["disconnect"](); this.wetNode["disconnect"](); this.dryNode["disconnect"](); }; DistortionEffect.prototype.getInputNode = function () { return this.inputNode; }; DistortionEffect.prototype.setParam = function(param, value, ramp, time) { switch (param) { case 0: // mix value = value / 100; if (value < 0) value = 0; if (value > 1) value = 1; this.params[4] = value; setAudioParam(this.wetNode["gain"], value, ramp, time); setAudioParam(this.dryNode["gain"], 1 - value, ramp, time); break; } }; function CompressorEffect(threshold, knee, ratio, attack, release) { this.type = "compressor"; this.params = [threshold, knee, ratio, attack, release]; this.node = context["createDynamicsCompressor"](); try { this.node["threshold"]["value"] = threshold; this.node["knee"]["value"] = knee; this.node["ratio"]["value"] = ratio; this.node["attack"]["value"] = attack; this.node["release"]["value"] = release; } catch (e) {} }; CompressorEffect.prototype.connectTo = function (node_) { this.node["disconnect"](); this.node["connect"](node_); }; CompressorEffect.prototype.remove = function () { this.node["disconnect"](); }; CompressorEffect.prototype.getInputNode = function () { return this.node; }; CompressorEffect.prototype.setParam = function(param, value, ramp, time) { }; function AnalyserEffect(fftSize, smoothing) { this.type = "analyser"; this.params = [fftSize, smoothing]; this.node = context["createAnalyser"](); this.node["fftSize"] = fftSize; this.node["smoothingTimeConstant"] = smoothing; this.freqBins = new Float32Array(this.node["frequencyBinCount"]); this.signal = new Uint8Array(fftSize); this.peak = 0; this.rms = 0; }; AnalyserEffect.prototype.tick = function () { this.node["getFloatFrequencyData"](this.freqBins); this.node["getByteTimeDomainData"](this.signal); var fftSize = this.node["fftSize"]; var i = 0; this.peak = 0; var rmsSquaredSum = 0; var s = 0; for ( ; i < fftSize; i++) { s = (this.signal[i] - 128) / 128; if (s < 0) s = -s; if (this.peak < s) this.peak = s; rmsSquaredSum += s * s; } this.peak = linearToDb(this.peak); this.rms = linearToDb(Math.sqrt(rmsSquaredSum / fftSize)); }; AnalyserEffect.prototype.connectTo = function (node_) { this.node["disconnect"](); this.node["connect"](node_); }; AnalyserEffect.prototype.remove = function () { this.node["disconnect"](); }; AnalyserEffect.prototype.getInputNode = function () { return this.node; }; AnalyserEffect.prototype.setParam = function(param, value, ramp, time) { }; function ObjectTracker() { this.obj = null; this.loadUid = 0; }; ObjectTracker.prototype.setObject = function (obj_) { this.obj = obj_; }; ObjectTracker.prototype.hasObject = function () { return !!this.obj; }; ObjectTracker.prototype.tick = function (dt) { }; function C2AudioBuffer(src_, is_music) { this.src = src_; this.myapi = api; this.is_music = is_music; this.added_end_listener = false; var self = this; this.outNode = null; this.mediaSourceNode = null; this.panWhenReady = []; // for web audio API positioned sounds this.seekWhenReady = 0; this.pauseWhenReady = false; this.supportWebAudioAPI = false; this.failedToLoad = false; this.wasEverReady = false; // if a buffer is ever marked as ready, it's permanently considered ready after then. if (api === API_WEBAUDIO && is_music && !playMusicAsSoundWorkaround) { this.myapi = API_HTML5; this.outNode = createGain(); } this.bufferObject = null; // actual audio object this.audioData = null; // web audio api: ajax request result (compressed audio that needs decoding) var request; switch (this.myapi) { case API_HTML5: this.bufferObject = new Audio(); this.bufferObject.crossOrigin = "anonymous"; this.bufferObject.addEventListener("canplaythrough", function () { self.wasEverReady = true; // update loaded state so preload is considered complete }); if (api === API_WEBAUDIO && context["createMediaElementSource"] && !/wiiu/i.test(navigator.userAgent)) { this.supportWebAudioAPI = true; // can be routed through web audio api this.bufferObject.addEventListener("canplay", function () { if (!self.mediaSourceNode && self.bufferObject) { self.mediaSourceNode = context["createMediaElementSource"](self.bufferObject); self.mediaSourceNode["connect"](self.outNode); } }); } this.bufferObject.autoplay = false; // this is only a source buffer, not an instance this.bufferObject.preload = "auto"; this.bufferObject.src = src_; break; case API_WEBAUDIO: if (audRuntime.isWKWebView) { audRuntime.fetchLocalFileViaCordovaAsArrayBuffer(src_, function (arrayBuffer) { self.audioData = arrayBuffer; self.decodeAudioBuffer(); }, function (err) { self.failedToLoad = true; }); } else { request = new XMLHttpRequest(); request.open("GET", src_, true); request.responseType = "arraybuffer"; request.onload = function () { self.audioData = request.response; self.decodeAudioBuffer(); }; request.onerror = function () { self.failedToLoad = true; }; request.send(); } break; case API_CORDOVA: this.bufferObject = true; break; case API_APPMOBI: this.bufferObject = true; break; } }; C2AudioBuffer.prototype.release = function () { var i, len, j, a; for (i = 0, j = 0, len = audioInstances.length; i < len; ++i) { a = audioInstances[i]; audioInstances[j] = a; if (a.buffer === this) a.stop(); else ++j; // keep } audioInstances.length = j; if (this.mediaSourceNode) { this.mediaSourceNode["disconnect"](); this.mediaSourceNode = null; } if (this.outNode) { this.outNode["disconnect"](); this.outNode = null; } this.bufferObject = null; this.audioData = null; }; C2AudioBuffer.prototype.decodeAudioBuffer = function () { if (this.bufferObject || !this.audioData) return; // audio already decoded or AJAX request not yet complete var self = this; if (context["decodeAudioData"]) { context["decodeAudioData"](this.audioData, function (buffer) { self.bufferObject = buffer; self.audioData = null; // clear AJAX response to allow GC and save memory, only need the bufferObject now var p, i, len, a; if (!cr.is_undefined(self.playTagWhenReady) && !silent) { if (self.panWhenReady.length) { for (i = 0, len = self.panWhenReady.length; i < len; i++) { p = self.panWhenReady[i]; a = new C2AudioInstance(self, p.thistag); a.setPannerEnabled(true); if (typeof p.objUid !== "undefined") { p.obj = audRuntime.getObjectByUID(p.objUid); if (!p.obj) continue; } if (p.obj) { var px = cr.rotatePtAround(p.obj.x, p.obj.y, -p.obj.layer.getAngle(), listenerX, listenerY, true); var py = cr.rotatePtAround(p.obj.x, p.obj.y, -p.obj.layer.getAngle(), listenerX, listenerY, false); a.setPan(px, py, cr.to_degrees(p.obj.angle - p.obj.layer.getAngle()), p.ia, p.oa, p.og); a.setObject(p.obj); } else { a.setPan(p.x, p.y, p.a, p.ia, p.oa, p.og); } a.play(self.loopWhenReady, self.volumeWhenReady, self.seekWhenReady); if (self.pauseWhenReady) a.pause(); audioInstances.push(a); } cr.clearArray(self.panWhenReady); } else { a = new C2AudioInstance(self, self.playTagWhenReady || ""); // sometimes playTagWhenReady is not set - TODO: why? a.play(self.loopWhenReady, self.volumeWhenReady, self.seekWhenReady); if (self.pauseWhenReady) a.pause(); audioInstances.push(a); } } else if (!cr.is_undefined(self.convolveWhenReady)) { var convolveNode = self.convolveWhenReady.convolveNode; convolveNode["normalize"] = self.normalizeWhenReady; convolveNode["buffer"] = buffer; } }, function (e) { self.failedToLoad = true; }); } else { this.bufferObject = context["createBuffer"](this.audioData, false); this.audioData = null; // clear AJAX response to allow GC and save memory, only need the bufferObject now if (!cr.is_undefined(this.playTagWhenReady) && !silent) { var a = new C2AudioInstance(this, this.playTagWhenReady); a.play(this.loopWhenReady, this.volumeWhenReady, this.seekWhenReady); if (this.pauseWhenReady) a.pause(); audioInstances.push(a); } else if (!cr.is_undefined(this.convolveWhenReady)) { var convolveNode = this.convolveWhenReady.convolveNode; convolveNode["normalize"] = this.normalizeWhenReady; convolveNode["buffer"] = this.bufferObject; } } }; C2AudioBuffer.prototype.isLoaded = function () { switch (this.myapi) { case API_HTML5: var ret = this.bufferObject["readyState"] >= 4; // HAVE_ENOUGH_DATA if (ret) this.wasEverReady = true; return ret || this.wasEverReady; case API_WEBAUDIO: return !!this.audioData || !!this.bufferObject; case API_CORDOVA: return true; case API_APPMOBI: return true; } return false; }; C2AudioBuffer.prototype.isLoadedAndDecoded = function () { switch (this.myapi) { case API_HTML5: return this.isLoaded(); // no distinction between loaded and decoded in HTML5 audio, just rely on ready state case API_WEBAUDIO: return !!this.bufferObject; case API_CORDOVA: return true; case API_APPMOBI: return true; } return false; }; C2AudioBuffer.prototype.hasFailedToLoad = function () { switch (this.myapi) { case API_HTML5: return !!this.bufferObject["error"]; case API_WEBAUDIO: return this.failedToLoad; } return false; }; function C2AudioInstance(buffer_, tag_) { var self = this; this.tag = tag_; this.fresh = true; this.stopped = true; this.src = buffer_.src; this.buffer = buffer_; this.myapi = api; this.is_music = buffer_.is_music; this.playbackRate = 1; this.hasPlaybackEnded = true; // ended flag this.resume_me = false; // make sure resumes when leaving suspend this.is_paused = false; this.resume_position = 0; // for web audio api to resume from correct playback position this.looping = false; this.is_muted = false; this.is_silent = false; this.volume = 1; this.onended_handler = function (e) { if (self.is_paused || self.resume_me) return; var bufferThatEnded = this; if (!bufferThatEnded) bufferThatEnded = e.target; if (bufferThatEnded !== self.active_buffer) return; self.hasPlaybackEnded = true; self.stopped = true; audTag = self.tag; audRuntime.trigger(cr.plugins_.Audio.prototype.cnds.OnEnded, audInst); }; this.active_buffer = null; this.isTimescaled = ((timescale_mode === 1 && !this.is_music) || timescale_mode === 2); this.mutevol = 1; this.startTime = (this.isTimescaled ? audRuntime.kahanTime.sum : audRuntime.wallTime.sum); this.gainNode = null; this.pannerNode = null; this.pannerEnabled = false; this.objectTracker = null; this.panX = 0; this.panY = 0; this.panAngle = 0; this.panConeInner = 0; this.panConeOuter = 0; this.panConeOuterGain = 0; this.instanceObject = null; var add_end_listener = false; if (this.myapi === API_WEBAUDIO && this.buffer.myapi === API_HTML5 && !this.buffer.supportWebAudioAPI) this.myapi = API_HTML5; switch (this.myapi) { case API_HTML5: if (this.is_music) { this.instanceObject = buffer_.bufferObject; add_end_listener = !buffer_.added_end_listener; buffer_.added_end_listener = true; } else { this.instanceObject = new Audio(); this.instanceObject.crossOrigin = "anonymous"; this.instanceObject.autoplay = false; this.instanceObject.src = buffer_.bufferObject.src; add_end_listener = true; } if (add_end_listener) { this.instanceObject.addEventListener('ended', function () { audTag = self.tag; self.stopped = true; audRuntime.trigger(cr.plugins_.Audio.prototype.cnds.OnEnded, audInst); }); } break; case API_WEBAUDIO: this.gainNode = createGain(); this.gainNode["connect"](getDestinationForTag(tag_)); if (this.buffer.myapi === API_WEBAUDIO) { if (buffer_.bufferObject) { this.instanceObject = context["createBufferSource"](); this.instanceObject["buffer"] = buffer_.bufferObject; this.instanceObject["connect"](this.gainNode); } } else { this.instanceObject = this.buffer.bufferObject; // reference the audio element this.buffer.outNode["connect"](this.gainNode); if (!this.buffer.added_end_listener) { this.buffer.added_end_listener = true; this.buffer.bufferObject.addEventListener('ended', function () { audTag = self.tag; self.stopped = true; audRuntime.trigger(cr.plugins_.Audio.prototype.cnds.OnEnded, audInst); }); } } break; case API_CORDOVA: this.instanceObject = new window["Media"](appPath + this.src, null, null, function (status) { if (status === window["Media"]["MEDIA_STOPPED"]) { self.hasPlaybackEnded = true; self.stopped = true; audTag = self.tag; audRuntime.trigger(cr.plugins_.Audio.prototype.cnds.OnEnded, audInst); } }); break; case API_APPMOBI: this.instanceObject = true; break; } }; C2AudioInstance.prototype.hasEnded = function () { var time; switch (this.myapi) { case API_HTML5: return this.instanceObject.ended; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { if (!this.fresh && !this.stopped && this.instanceObject["loop"]) return false; if (this.is_paused) return false; return this.hasPlaybackEnded; } else return this.instanceObject.ended; case API_CORDOVA: return this.hasPlaybackEnded; case API_APPMOBI: true; // recycling an AppMobi sound does not matter because it will just do another throwaway playSound } return true; }; C2AudioInstance.prototype.canBeRecycled = function () { if (this.fresh || this.stopped) return true; // not yet used or is not playing return this.hasEnded(); }; C2AudioInstance.prototype.setPannerEnabled = function (enable_) { if (api !== API_WEBAUDIO) return; if (!this.pannerEnabled && enable_) { if (!this.gainNode) return; if (!this.pannerNode) { this.pannerNode = context["createPanner"](); if (typeof this.pannerNode["panningModel"] === "number") this.pannerNode["panningModel"] = panningModel; else this.pannerNode["panningModel"] = ["equalpower", "HRTF", "soundfield"][panningModel]; if (typeof this.pannerNode["distanceModel"] === "number") this.pannerNode["distanceModel"] = distanceModel; else this.pannerNode["distanceModel"] = ["linear", "inverse", "exponential"][distanceModel]; this.pannerNode["refDistance"] = refDistance; this.pannerNode["maxDistance"] = maxDistance; this.pannerNode["rolloffFactor"] = rolloffFactor; } this.gainNode["disconnect"](); this.gainNode["connect"](this.pannerNode); this.pannerNode["connect"](getDestinationForTag(this.tag)); this.pannerEnabled = true; } else if (this.pannerEnabled && !enable_) { if (!this.gainNode) return; this.pannerNode["disconnect"](); this.gainNode["disconnect"](); this.gainNode["connect"](getDestinationForTag(this.tag)); this.pannerEnabled = false; } }; C2AudioInstance.prototype.setPan = function (x, y, angle, innerangle, outerangle, outergain) { if (!this.pannerEnabled || api !== API_WEBAUDIO) return; this.pannerNode["setPosition"](x, y, 0); this.pannerNode["setOrientation"](Math.cos(cr.to_radians(angle)), Math.sin(cr.to_radians(angle)), 0); this.pannerNode["coneInnerAngle"] = innerangle; this.pannerNode["coneOuterAngle"] = outerangle; this.pannerNode["coneOuterGain"] = outergain; this.panX = x; this.panY = y; this.panAngle = angle; this.panConeInner = innerangle; this.panConeOuter = outerangle; this.panConeOuterGain = outergain; }; C2AudioInstance.prototype.setObject = function (o) { if (!this.pannerEnabled || api !== API_WEBAUDIO) return; if (!this.objectTracker) this.objectTracker = new ObjectTracker(); this.objectTracker.setObject(o); }; C2AudioInstance.prototype.tick = function (dt) { if (!this.pannerEnabled || api !== API_WEBAUDIO || !this.objectTracker || !this.objectTracker.hasObject() || !this.isPlaying()) { return; } this.objectTracker.tick(dt); var inst = this.objectTracker.obj; var px = cr.rotatePtAround(inst.x, inst.y, -inst.layer.getAngle(), listenerX, listenerY, true); var py = cr.rotatePtAround(inst.x, inst.y, -inst.layer.getAngle(), listenerX, listenerY, false); this.pannerNode["setPosition"](px, py, 0); var a = 0; if (typeof this.objectTracker.obj.angle !== "undefined") { a = inst.angle - inst.layer.getAngle(); this.pannerNode["setOrientation"](Math.cos(a), Math.sin(a), 0); } }; C2AudioInstance.prototype.play = function (looping, vol, fromPosition, scheduledTime) { var instobj = this.instanceObject; this.looping = looping; this.volume = vol; var seekPos = fromPosition || 0; scheduledTime = scheduledTime || 0; switch (this.myapi) { case API_HTML5: if (instobj.playbackRate !== 1.0) instobj.playbackRate = 1.0; if (instobj.volume !== vol * masterVolume) instobj.volume = vol * masterVolume; if (instobj.loop !== looping) instobj.loop = looping; if (instobj.muted) instobj.muted = false; if (instobj.currentTime !== seekPos) { try { instobj.currentTime = seekPos; } catch (err) { ; } } tryPlayAudioElement(this); break; case API_WEBAUDIO: this.muted = false; this.mutevol = 1; if (this.buffer.myapi === API_WEBAUDIO) { this.gainNode["gain"]["value"] = vol * masterVolume; if (!this.fresh) { this.instanceObject = context["createBufferSource"](); this.instanceObject["buffer"] = this.buffer.bufferObject; this.instanceObject["connect"](this.gainNode); } this.instanceObject["onended"] = this.onended_handler; this.active_buffer = this.instanceObject; this.instanceObject.loop = looping; this.hasPlaybackEnded = false; if (seekPos === 0) startSource(this.instanceObject, scheduledTime); else startSourceAt(this.instanceObject, seekPos, this.getDuration(), scheduledTime); } else { if (instobj.playbackRate !== 1.0) instobj.playbackRate = 1.0; if (instobj.loop !== looping) instobj.loop = looping; instobj.volume = vol * masterVolume; if (instobj.currentTime !== seekPos) { try { instobj.currentTime = seekPos; } catch (err) { ; } } tryPlayAudioElement(this); } break; case API_CORDOVA: if ((!this.fresh && this.stopped) || seekPos !== 0) instobj["seekTo"](seekPos); instobj["play"](); this.hasPlaybackEnded = false; break; case API_APPMOBI: if (audRuntime.isDirectCanvas) AppMobi["context"]["playSound"](this.src, looping); else AppMobi["player"]["playSound"](this.src, looping); break; } this.playbackRate = 1; this.startTime = (this.isTimescaled ? audRuntime.kahanTime.sum : audRuntime.wallTime.sum) - seekPos; this.fresh = false; this.stopped = false; this.is_paused = false; }; C2AudioInstance.prototype.stop = function () { switch (this.myapi) { case API_HTML5: if (!this.instanceObject.paused) this.instanceObject.pause(); break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) stopSource(this.instanceObject); else { if (!this.instanceObject.paused) this.instanceObject.pause(); } break; case API_CORDOVA: this.instanceObject["stop"](); break; case API_APPMOBI: if (audRuntime.isDirectCanvas) AppMobi["context"]["stopSound"](this.src); break; } this.stopped = true; this.is_paused = false; }; C2AudioInstance.prototype.pause = function () { if (this.fresh || this.stopped || this.hasEnded() || this.is_paused) return; switch (this.myapi) { case API_HTML5: if (!this.instanceObject.paused) this.instanceObject.pause(); break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { this.resume_position = this.getPlaybackTime(true); if (this.looping) this.resume_position = this.resume_position % this.getDuration(); this.is_paused = true; stopSource(this.instanceObject); } else { if (!this.instanceObject.paused) this.instanceObject.pause(); } break; case API_CORDOVA: this.instanceObject["pause"](); break; case API_APPMOBI: if (audRuntime.isDirectCanvas) AppMobi["context"]["stopSound"](this.src); break; } this.is_paused = true; }; C2AudioInstance.prototype.resume = function () { if (this.fresh || this.stopped || this.hasEnded() || !this.is_paused) return; switch (this.myapi) { case API_HTML5: tryPlayAudioElement(this); break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { this.instanceObject = context["createBufferSource"](); this.instanceObject["buffer"] = this.buffer.bufferObject; this.instanceObject["connect"](this.gainNode); this.instanceObject["onended"] = this.onended_handler; this.active_buffer = this.instanceObject; this.instanceObject.loop = this.looping; this.gainNode["gain"]["value"] = masterVolume * this.volume * this.mutevol; this.updatePlaybackRate(); this.startTime = (this.isTimescaled ? audRuntime.kahanTime.sum : audRuntime.wallTime.sum) - (this.resume_position / (this.playbackRate || 0.001)); startSourceAt(this.instanceObject, this.resume_position, this.getDuration()); } else { tryPlayAudioElement(this); } break; case API_CORDOVA: this.instanceObject["play"](); break; case API_APPMOBI: if (audRuntime.isDirectCanvas) AppMobi["context"]["resumeSound"](this.src); break; } this.is_paused = false; }; C2AudioInstance.prototype.seek = function (pos) { if (this.fresh || this.stopped || this.hasEnded()) return; switch (this.myapi) { case API_HTML5: try { this.instanceObject.currentTime = pos; } catch (e) {} break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { if (this.is_paused) this.resume_position = pos; else { this.pause(); this.resume_position = pos; this.resume(); } } else { try { this.instanceObject.currentTime = pos; } catch (e) {} } break; case API_CORDOVA: break; case API_APPMOBI: if (audRuntime.isDirectCanvas) AppMobi["context"]["seekSound"](this.src, pos); break; } }; C2AudioInstance.prototype.reconnect = function (toNode) { if (this.myapi !== API_WEBAUDIO) return; if (this.pannerEnabled) { this.pannerNode["disconnect"](); this.pannerNode["connect"](toNode); } else { this.gainNode["disconnect"](); this.gainNode["connect"](toNode); } }; C2AudioInstance.prototype.getDuration = function (applyPlaybackRate) { var ret = 0; switch (this.myapi) { case API_HTML5: if (typeof this.instanceObject.duration !== "undefined") ret = this.instanceObject.duration; break; case API_WEBAUDIO: ret = this.buffer.bufferObject["duration"]; break; case API_CORDOVA: ret = this.instanceObject["getDuration"](); break; case API_APPMOBI: if (audRuntime.isDirectCanvas) ret = AppMobi["context"]["getDurationSound"](this.src); break; } if (applyPlaybackRate) ret /= (this.playbackRate || 0.001); // avoid divide-by-zero return ret; }; C2AudioInstance.prototype.getPlaybackTime = function (applyPlaybackRate) { var duration = this.getDuration(); var ret = 0; switch (this.myapi) { case API_HTML5: if (typeof this.instanceObject.currentTime !== "undefined") ret = this.instanceObject.currentTime; break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { if (this.is_paused) return this.resume_position; else ret = (this.isTimescaled ? audRuntime.kahanTime.sum : audRuntime.wallTime.sum) - this.startTime; } else if (typeof this.instanceObject.currentTime !== "undefined") ret = this.instanceObject.currentTime; break; case API_CORDOVA: break; case API_APPMOBI: if (audRuntime.isDirectCanvas) ret = AppMobi["context"]["getPlaybackTimeSound"](this.src); break; } if (applyPlaybackRate) ret *= this.playbackRate; if (!this.looping && ret > duration) ret = duration; return ret; }; C2AudioInstance.prototype.isPlaying = function () { return !this.is_paused && !this.fresh && !this.stopped && !this.hasEnded(); }; C2AudioInstance.prototype.shouldSave = function () { return !this.fresh && !this.stopped && !this.hasEnded(); }; C2AudioInstance.prototype.setVolume = function (v) { this.volume = v; this.updateVolume(); }; C2AudioInstance.prototype.updateVolume = function () { var volToSet = this.volume * masterVolume; if (!isFinite(volToSet)) volToSet = 0; // HTMLMediaElement throws if setting non-finite volume switch (this.myapi) { case API_HTML5: if (typeof this.instanceObject.volume !== "undefined" && this.instanceObject.volume !== volToSet) this.instanceObject.volume = volToSet; break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { this.gainNode["gain"]["value"] = volToSet * this.mutevol; } else { if (typeof this.instanceObject.volume !== "undefined" && this.instanceObject.volume !== volToSet) this.instanceObject.volume = volToSet; } break; case API_CORDOVA: break; case API_APPMOBI: break; } }; C2AudioInstance.prototype.getVolume = function () { return this.volume; }; C2AudioInstance.prototype.doSetMuted = function (m) { switch (this.myapi) { case API_HTML5: if (this.instanceObject.muted !== !!m) this.instanceObject.muted = !!m; break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { this.mutevol = (m ? 0 : 1); this.gainNode["gain"]["value"] = masterVolume * this.volume * this.mutevol; } else { if (this.instanceObject.muted !== !!m) this.instanceObject.muted = !!m; } break; case API_CORDOVA: break; case API_APPMOBI: break; } }; C2AudioInstance.prototype.setMuted = function (m) { this.is_muted = !!m; this.doSetMuted(this.is_muted || this.is_silent); }; C2AudioInstance.prototype.setSilent = function (m) { this.is_silent = !!m; this.doSetMuted(this.is_muted || this.is_silent); }; C2AudioInstance.prototype.setLooping = function (l) { this.looping = l; switch (this.myapi) { case API_HTML5: if (this.instanceObject.loop !== !!l) this.instanceObject.loop = !!l; break; case API_WEBAUDIO: if (this.instanceObject.loop !== !!l) this.instanceObject.loop = !!l; break; case API_CORDOVA: break; case API_APPMOBI: if (audRuntime.isDirectCanvas) AppMobi["context"]["setLoopingSound"](this.src, l); break; } }; C2AudioInstance.prototype.setPlaybackRate = function (r) { this.playbackRate = r; this.updatePlaybackRate(); }; C2AudioInstance.prototype.updatePlaybackRate = function () { var r = this.playbackRate; if (this.isTimescaled) r *= audRuntime.timescale; switch (this.myapi) { case API_HTML5: if (this.instanceObject.playbackRate !== r) this.instanceObject.playbackRate = r; break; case API_WEBAUDIO: if (this.buffer.myapi === API_WEBAUDIO) { if (this.instanceObject["playbackRate"]["value"] !== r) this.instanceObject["playbackRate"]["value"] = r; } else { if (this.instanceObject.playbackRate !== r) this.instanceObject.playbackRate = r; } break; case API_CORDOVA: break; case API_APPMOBI: break; } }; C2AudioInstance.prototype.setSuspended = function (s) { switch (this.myapi) { case API_HTML5: if (s) { if (this.isPlaying()) { this.resume_me = true; this.instanceObject["pause"](); } else this.resume_me = false; } else { if (this.resume_me) { this.instanceObject["play"](); this.resume_me = false; } } break; case API_WEBAUDIO: if (s) { if (this.isPlaying()) { this.resume_me = true; if (this.buffer.myapi === API_WEBAUDIO) { this.resume_position = this.getPlaybackTime(true); if (this.looping) this.resume_position = this.resume_position % this.getDuration(); stopSource(this.instanceObject); } else this.instanceObject["pause"](); } else this.resume_me = false; } else { if (this.resume_me) { if (this.buffer.myapi === API_WEBAUDIO) { this.instanceObject = context["createBufferSource"](); this.instanceObject["buffer"] = this.buffer.bufferObject; this.instanceObject["connect"](this.gainNode); this.instanceObject["onended"] = this.onended_handler; this.active_buffer = this.instanceObject; this.instanceObject.loop = this.looping; this.gainNode["gain"]["value"] = masterVolume * this.volume * this.mutevol; this.updatePlaybackRate(); this.startTime = (this.isTimescaled ? audRuntime.kahanTime.sum : audRuntime.wallTime.sum) - (this.resume_position / (this.playbackRate || 0.001)); startSourceAt(this.instanceObject, this.resume_position, this.getDuration()); } else { this.instanceObject["play"](); } this.resume_me = false; } } break; case API_CORDOVA: if (s) { if (this.isPlaying()) { this.instanceObject["pause"](); this.resume_me = true; } else this.resume_me = false; } else { if (this.resume_me) { this.resume_me = false; this.instanceObject["play"](); } } break; case API_APPMOBI: break; } }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; audRuntime = this.runtime; audInst = this; this.listenerTracker = null; this.listenerZ = -600; if (this.runtime.isWKWebView) playMusicAsSoundWorkaround = true; if ((this.runtime.isiOS || (this.runtime.isAndroid && (this.runtime.isChrome || this.runtime.isAndroidStockBrowser))) && !this.runtime.isCrosswalk && !this.runtime.isDomFree && !this.runtime.isAmazonWebApp && !playMusicAsSoundWorkaround) { useNextTouchWorkaround = true; } context = null; if (typeof AudioContext !== "undefined") { api = API_WEBAUDIO; context = new AudioContext(); } else if (typeof webkitAudioContext !== "undefined") { api = API_WEBAUDIO; context = new webkitAudioContext(); } if (this.runtime.isiOS && context) { if (context.close) context.close(); if (typeof AudioContext !== "undefined") context = new AudioContext(); else if (typeof webkitAudioContext !== "undefined") context = new webkitAudioContext(); } if (api !== API_WEBAUDIO) { if (this.runtime.isCordova && typeof window["Media"] !== "undefined") api = API_CORDOVA; else if (this.runtime.isAppMobi) api = API_APPMOBI; } if (api === API_CORDOVA) { appPath = location.href; var i = appPath.lastIndexOf("/"); if (i > -1) appPath = appPath.substr(0, i + 1); appPath = appPath.replace("file://", ""); } if (this.runtime.isSafari && this.runtime.isWindows && typeof Audio === "undefined") { alert("It looks like you're using Safari for Windows without Quicktime. Audio cannot be played until Quicktime is installed."); this.runtime.DestroyInstance(this); } else { if (this.runtime.isDirectCanvas) useOgg = this.runtime.isAndroid; // AAC on iOS, OGG on Android else { try { useOgg = !!(new Audio().canPlayType('audio/ogg; codecs="vorbis"')) && !this.runtime.isWindows10; } catch (e) { useOgg = false; } } switch (api) { case API_HTML5: ; break; case API_WEBAUDIO: ; break; case API_CORDOVA: ; break; case API_APPMOBI: ; break; default: ; } this.runtime.tickMe(this); } }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function () { this.runtime.audioInstance = this; timescale_mode = this.properties[0]; // 0 = off, 1 = sounds only, 2 = all this.saveload = this.properties[1]; // 0 = all, 1 = sounds only, 2 = music only, 3 = none this.playinbackground = (this.properties[2] !== 0); this.nextPlayTime = 0; panningModel = this.properties[3]; // 0 = equalpower, 1 = hrtf, 3 = soundfield distanceModel = this.properties[4]; // 0 = linear, 1 = inverse, 2 = exponential this.listenerZ = -this.properties[5]; refDistance = this.properties[6]; maxDistance = this.properties[7]; rolloffFactor = this.properties[8]; this.listenerTracker = new ObjectTracker(); var draw_width = (this.runtime.draw_width || this.runtime.width); var draw_height = (this.runtime.draw_height || this.runtime.height); if (api === API_WEBAUDIO) { context["listener"]["setPosition"](draw_width / 2, draw_height / 2, this.listenerZ); context["listener"]["setOrientation"](0, 0, 1, 0, -1, 0); window["c2OnAudioMicStream"] = function (localMediaStream, tag) { if (micSource) micSource["disconnect"](); micTag = tag.toLowerCase(); micSource = context["createMediaStreamSource"](localMediaStream); micSource["connect"](getDestinationForTag(micTag)); }; } this.runtime.addSuspendCallback(function(s) { audInst.onSuspend(s); }); var self = this; this.runtime.addDestroyCallback(function (inst) { self.onInstanceDestroyed(inst); }); }; instanceProto.onInstanceDestroyed = function (inst) { var i, len, a; for (i = 0, len = audioInstances.length; i < len; i++) { a = audioInstances[i]; if (a.objectTracker) { if (a.objectTracker.obj === inst) { a.objectTracker.obj = null; if (a.pannerEnabled && a.isPlaying() && a.looping) a.stop(); } } } if (this.listenerTracker.obj === inst) this.listenerTracker.obj = null; }; instanceProto.saveToJSON = function () { var o = { "silent": silent, "masterVolume": masterVolume, "listenerZ": this.listenerZ, "listenerUid": this.listenerTracker.hasObject() ? this.listenerTracker.obj.uid : -1, "playing": [], "effects": {} }; var playingarr = o["playing"]; var i, len, a, d, p, panobj, playbackTime; for (i = 0, len = audioInstances.length; i < len; i++) { a = audioInstances[i]; if (!a.shouldSave()) continue; // no need to save stopped sounds if (this.saveload === 3) // not saving/loading any sounds/music continue; if (a.is_music && this.saveload === 1) // not saving/loading music continue; if (!a.is_music && this.saveload === 2) // not saving/loading sound continue; playbackTime = a.getPlaybackTime(); if (a.looping) playbackTime = playbackTime % a.getDuration(); d = { "tag": a.tag, "buffersrc": a.buffer.src, "is_music": a.is_music, "playbackTime": playbackTime, "volume": a.volume, "looping": a.looping, "muted": a.is_muted, "playbackRate": a.playbackRate, "paused": a.is_paused, "resume_position": a.resume_position }; if (a.pannerEnabled) { d["pan"] = {}; panobj = d["pan"]; if (a.objectTracker && a.objectTracker.hasObject()) { panobj["objUid"] = a.objectTracker.obj.uid; } else { panobj["x"] = a.panX; panobj["y"] = a.panY; panobj["a"] = a.panAngle; } panobj["ia"] = a.panConeInner; panobj["oa"] = a.panConeOuter; panobj["og"] = a.panConeOuterGain; } playingarr.push(d); } var fxobj = o["effects"]; var fxarr; for (p in effects) { if (effects.hasOwnProperty(p)) { fxarr = []; for (i = 0, len = effects[p].length; i < len; i++) { fxarr.push({ "type": effects[p][i].type, "params": effects[p][i].params }); } fxobj[p] = fxarr; } } return o; }; var objectTrackerUidsToLoad = []; instanceProto.loadFromJSON = function (o) { var setSilent = o["silent"]; masterVolume = o["masterVolume"]; this.listenerZ = o["listenerZ"]; this.listenerTracker.setObject(null); var listenerUid = o["listenerUid"]; if (listenerUid !== -1) { this.listenerTracker.loadUid = listenerUid; objectTrackerUidsToLoad.push(this.listenerTracker); } var playingarr = o["playing"]; var i, len, d, src, is_music, tag, playbackTime, looping, vol, b, a, p, pan, panObjUid; if (this.saveload !== 3) { for (i = 0, len = audioInstances.length; i < len; i++) { a = audioInstances[i]; if (a.is_music && this.saveload === 1) continue; // only saving/loading sound: leave music playing if (!a.is_music && this.saveload === 2) continue; // only saving/loading music: leave sound playing a.stop(); } } var fxarr, fxtype, fxparams, fx; for (p in effects) { if (effects.hasOwnProperty(p)) { for (i = 0, len = effects[p].length; i < len; i++) effects[p][i].remove(); } } cr.wipe(effects); for (p in o["effects"]) { if (o["effects"].hasOwnProperty(p)) { fxarr = o["effects"][p]; for (i = 0, len = fxarr.length; i < len; i++) { fxtype = fxarr[i]["type"]; fxparams = fxarr[i]["params"]; switch (fxtype) { case "filter": addEffectForTag(p, new FilterEffect(fxparams[0], fxparams[1], fxparams[2], fxparams[3], fxparams[4], fxparams[5])); break; case "delay": addEffectForTag(p, new DelayEffect(fxparams[0], fxparams[1], fxparams[2])); break; case "convolve": src = fxparams[2]; b = this.getAudioBuffer(src, false); if (b.bufferObject) { fx = new ConvolveEffect(b.bufferObject, fxparams[0], fxparams[1], src); } else { fx = new ConvolveEffect(null, fxparams[0], fxparams[1], src); b.normalizeWhenReady = fxparams[0]; b.convolveWhenReady = fx; } addEffectForTag(p, fx); break; case "flanger": addEffectForTag(p, new FlangerEffect(fxparams[0], fxparams[1], fxparams[2], fxparams[3], fxparams[4])); break; case "phaser": addEffectForTag(p, new PhaserEffect(fxparams[0], fxparams[1], fxparams[2], fxparams[3], fxparams[4], fxparams[5])); break; case "gain": addEffectForTag(p, new GainEffect(fxparams[0])); break; case "tremolo": addEffectForTag(p, new TremoloEffect(fxparams[0], fxparams[1])); break; case "ringmod": addEffectForTag(p, new RingModulatorEffect(fxparams[0], fxparams[1])); break; case "distortion": addEffectForTag(p, new DistortionEffect(fxparams[0], fxparams[1], fxparams[2], fxparams[3], fxparams[4])); break; case "compressor": addEffectForTag(p, new CompressorEffect(fxparams[0], fxparams[1], fxparams[2], fxparams[3], fxparams[4])); break; case "analyser": addEffectForTag(p, new AnalyserEffect(fxparams[0], fxparams[1])); break; } } } } for (i = 0, len = playingarr.length; i < len; i++) { if (this.saveload === 3) // not saving/loading any sounds/music continue; d = playingarr[i]; src = d["buffersrc"]; is_music = d["is_music"]; tag = d["tag"]; playbackTime = d["playbackTime"]; looping = d["looping"]; vol = d["volume"]; pan = d["pan"]; panObjUid = (pan && pan.hasOwnProperty("objUid")) ? pan["objUid"] : -1; if (is_music && this.saveload === 1) // not saving/loading music continue; if (!is_music && this.saveload === 2) // not saving/loading sound continue; a = this.getAudioInstance(src, tag, is_music, looping, vol); if (!a) { b = this.getAudioBuffer(src, is_music); b.seekWhenReady = playbackTime; b.pauseWhenReady = d["paused"]; if (pan) { if (panObjUid !== -1) { b.panWhenReady.push({ objUid: panObjUid, ia: pan["ia"], oa: pan["oa"], og: pan["og"], thistag: tag }); } else { b.panWhenReady.push({ x: pan["x"], y: pan["y"], a: pan["a"], ia: pan["ia"], oa: pan["oa"], og: pan["og"], thistag: tag }); } } continue; } a.resume_position = d["resume_position"]; a.setPannerEnabled(!!pan); a.play(looping, vol, playbackTime); a.updatePlaybackRate(); a.updateVolume(); a.doSetMuted(a.is_muted || a.is_silent); if (d["paused"]) a.pause(); if (d["muted"]) a.setMuted(true); a.doSetMuted(a.is_muted || a.is_silent); if (pan) { if (panObjUid !== -1) { a.objectTracker = a.objectTracker || new ObjectTracker(); a.objectTracker.loadUid = panObjUid; objectTrackerUidsToLoad.push(a.objectTracker); } else { a.setPan(pan["x"], pan["y"], pan["a"], pan["ia"], pan["oa"], pan["og"]); } } } if (setSilent && !silent) // setting silent { for (i = 0, len = audioInstances.length; i < len; i++) audioInstances[i].setSilent(true); silent = true; } else if (!setSilent && silent) // setting not silent { for (i = 0, len = audioInstances.length; i < len; i++) audioInstances[i].setSilent(false); silent = false; } }; instanceProto.afterLoad = function () { var i, len, ot, inst; for (i = 0, len = objectTrackerUidsToLoad.length; i < len; i++) { ot = objectTrackerUidsToLoad[i]; inst = this.runtime.getObjectByUID(ot.loadUid); ot.setObject(inst); ot.loadUid = -1; if (inst) { listenerX = inst.x; listenerY = inst.y; } } cr.clearArray(objectTrackerUidsToLoad); }; instanceProto.onSuspend = function (s) { if (this.playinbackground) return; if (!s && context && context["resume"]) { context["resume"](); isContextSuspended = false; } var i, len; for (i = 0, len = audioInstances.length; i < len; i++) audioInstances[i].setSuspended(s); if (s && context && context["suspend"]) { context["suspend"](); isContextSuspended = true; } }; instanceProto.tick = function () { var dt = this.runtime.dt; var i, len, a; for (i = 0, len = audioInstances.length; i < len; i++) { a = audioInstances[i]; a.tick(dt); if (timescale_mode !== 0) a.updatePlaybackRate(); } var p, arr, f; for (p in effects) { if (effects.hasOwnProperty(p)) { arr = effects[p]; for (i = 0, len = arr.length; i < len; i++) { f = arr[i]; if (f.tick) f.tick(); } } } if (api === API_WEBAUDIO && this.listenerTracker.hasObject()) { this.listenerTracker.tick(dt); listenerX = this.listenerTracker.obj.x; listenerY = this.listenerTracker.obj.y; context["listener"]["setPosition"](this.listenerTracker.obj.x, this.listenerTracker.obj.y, this.listenerZ); } }; var preload_list = []; instanceProto.setPreloadList = function (arr) { var i, len, p, filename, size, isOgg; var total_size = 0; for (i = 0, len = arr.length; i < len; ++i) { p = arr[i]; filename = p[0]; size = p[1] * 2; isOgg = (filename.length > 4 && filename.substr(filename.length - 4) === ".ogg"); if ((isOgg && useOgg) || (!isOgg && !useOgg)) { preload_list.push({ filename: filename, size: size, obj: null }); total_size += size; } } return total_size; }; instanceProto.startPreloads = function () { var i, len, p, src; for (i = 0, len = preload_list.length; i < len; ++i) { p = preload_list[i]; src = this.runtime.files_subfolder + p.filename; p.obj = this.getAudioBuffer(src, false); } }; instanceProto.getPreloadedSize = function () { var completed = 0; var i, len, p; for (i = 0, len = preload_list.length; i < len; ++i) { p = preload_list[i]; if (p.obj.isLoadedAndDecoded() || p.obj.hasFailedToLoad() || this.runtime.isDomFree || this.runtime.isAndroidStockBrowser) { completed += p.size; } else if (p.obj.isLoaded()) // downloaded but not decoded: only happens in Web Audio API, count as half-way progress { completed += Math.floor(p.size / 2); } }; return completed; }; instanceProto.releaseAllMusicBuffers = function () { var i, len, j, b; for (i = 0, j = 0, len = audioBuffers.length; i < len; ++i) { b = audioBuffers[i]; audioBuffers[j] = b; if (b.is_music) b.release(); else ++j; // keep } audioBuffers.length = j; }; instanceProto.getAudioBuffer = function (src_, is_music, dont_create) { var i, len, a, ret = null, j, k, lenj, ai; for (i = 0, len = audioBuffers.length; i < len; i++) { a = audioBuffers[i]; if (a.src === src_) { ret = a; break; } } if (!ret && !dont_create) { if (playMusicAsSoundWorkaround && is_music) this.releaseAllMusicBuffers(); ret = new C2AudioBuffer(src_, is_music); audioBuffers.push(ret); } return ret; }; instanceProto.getAudioInstance = function (src_, tag, is_music, looping, vol) { var i, len, a; for (i = 0, len = audioInstances.length; i < len; i++) { a = audioInstances[i]; if (a.src === src_ && (a.canBeRecycled() || is_music)) { a.tag = tag; return a; } } var b = this.getAudioBuffer(src_, is_music); if (!b.bufferObject) { if (tag !== "") { b.playTagWhenReady = tag; b.loopWhenReady = looping; b.volumeWhenReady = vol; } return null; } a = new C2AudioInstance(b, tag); audioInstances.push(a); return a; }; var taggedAudio = []; function SortByIsPlaying(a, b) { var an = a.isPlaying() ? 1 : 0; var bn = b.isPlaying() ? 1 : 0; if (an === bn) return 0; else if (an < bn) return 1; else return -1; }; function getAudioByTag(tag, sort_by_playing) { cr.clearArray(taggedAudio); if (!tag.length) { if (!lastAudio || lastAudio.hasEnded()) return; else { cr.clearArray(taggedAudio); taggedAudio[0] = lastAudio; return; } } var i, len, a; for (i = 0, len = audioInstances.length; i < len; i++) { a = audioInstances[i]; if (cr.equals_nocase(tag, a.tag)) taggedAudio.push(a); } if (sort_by_playing) taggedAudio.sort(SortByIsPlaying); }; function reconnectEffects(tag) { var i, len, arr, n, toNode = context["destination"]; if (effects.hasOwnProperty(tag)) { arr = effects[tag]; if (arr.length) { toNode = arr[0].getInputNode(); for (i = 0, len = arr.length; i < len; i++) { n = arr[i]; if (i + 1 === len) n.connectTo(context["destination"]); else n.connectTo(arr[i + 1].getInputNode()); } } } getAudioByTag(tag); for (i = 0, len = taggedAudio.length; i < len; i++) taggedAudio[i].reconnect(toNode); if (micSource && micTag === tag) { micSource["disconnect"](); micSource["connect"](toNode); } }; function addEffectForTag(tag, fx) { if (!effects.hasOwnProperty(tag)) effects[tag] = [fx]; else effects[tag].push(fx); reconnectEffects(tag); }; function Cnds() {}; Cnds.prototype.OnEnded = function (t) { return cr.equals_nocase(audTag, t); }; Cnds.prototype.PreloadsComplete = function () { var i, len; for (i = 0, len = audioBuffers.length; i < len; i++) { if (!audioBuffers[i].isLoadedAndDecoded() && !audioBuffers[i].hasFailedToLoad()) return false; } return true; }; Cnds.prototype.AdvancedAudioSupported = function () { return api === API_WEBAUDIO; }; Cnds.prototype.IsSilent = function () { return silent; }; Cnds.prototype.IsAnyPlaying = function () { var i, len; for (i = 0, len = audioInstances.length; i < len; i++) { if (audioInstances[i].isPlaying()) return true; } return false; }; Cnds.prototype.IsTagPlaying = function (tag) { getAudioByTag(tag); var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) { if (taggedAudio[i].isPlaying()) return true; } return false; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Play = function (file, looping, vol, tag) { if (silent) return; var v = dbToLinear(vol); var is_music = file[1]; var src = this.runtime.files_subfolder + file[0] + (useOgg ? ".ogg" : ".m4a"); lastAudio = this.getAudioInstance(src, tag, is_music, looping!==0, v); if (!lastAudio) return; lastAudio.setPannerEnabled(false); lastAudio.play(looping!==0, v, 0, this.nextPlayTime); this.nextPlayTime = 0; }; Acts.prototype.PlayAtPosition = function (file, looping, vol, x_, y_, angle_, innerangle_, outerangle_, outergain_, tag) { if (silent) return; var v = dbToLinear(vol); var is_music = file[1]; var src = this.runtime.files_subfolder + file[0] + (useOgg ? ".ogg" : ".m4a"); lastAudio = this.getAudioInstance(src, tag, is_music, looping!==0, v); if (!lastAudio) { var b = this.getAudioBuffer(src, is_music); b.panWhenReady.push({ x: x_, y: y_, a: angle_, ia: innerangle_, oa: outerangle_, og: dbToLinear(outergain_), thistag: tag }); return; } lastAudio.setPannerEnabled(true); lastAudio.setPan(x_, y_, angle_, innerangle_, outerangle_, dbToLinear(outergain_)); lastAudio.play(looping!==0, v, 0, this.nextPlayTime); this.nextPlayTime = 0; }; Acts.prototype.PlayAtObject = function (file, looping, vol, obj, innerangle, outerangle, outergain, tag) { if (silent || !obj) return; var inst = obj.getFirstPicked(); if (!inst) return; var v = dbToLinear(vol); var is_music = file[1]; var src = this.runtime.files_subfolder + file[0] + (useOgg ? ".ogg" : ".m4a"); lastAudio = this.getAudioInstance(src, tag, is_music, looping!==0, v); if (!lastAudio) { var b = this.getAudioBuffer(src, is_music); b.panWhenReady.push({ obj: inst, ia: innerangle, oa: outerangle, og: dbToLinear(outergain), thistag: tag }); return; } lastAudio.setPannerEnabled(true); var px = cr.rotatePtAround(inst.x, inst.y, -inst.layer.getAngle(), listenerX, listenerY, true); var py = cr.rotatePtAround(inst.x, inst.y, -inst.layer.getAngle(), listenerX, listenerY, false); lastAudio.setPan(px, py, cr.to_degrees(inst.angle - inst.layer.getAngle()), innerangle, outerangle, dbToLinear(outergain)); lastAudio.setObject(inst); lastAudio.play(looping!==0, v, 0, this.nextPlayTime); this.nextPlayTime = 0; }; Acts.prototype.PlayByName = function (folder, filename, looping, vol, tag) { if (silent) return; var v = dbToLinear(vol); var is_music = (folder === 1); var src = this.runtime.files_subfolder + filename.toLowerCase() + (useOgg ? ".ogg" : ".m4a"); lastAudio = this.getAudioInstance(src, tag, is_music, looping!==0, v); if (!lastAudio) return; lastAudio.setPannerEnabled(false); lastAudio.play(looping!==0, v, 0, this.nextPlayTime); this.nextPlayTime = 0; }; Acts.prototype.PlayAtPositionByName = function (folder, filename, looping, vol, x_, y_, angle_, innerangle_, outerangle_, outergain_, tag) { if (silent) return; var v = dbToLinear(vol); var is_music = (folder === 1); var src = this.runtime.files_subfolder + filename.toLowerCase() + (useOgg ? ".ogg" : ".m4a"); lastAudio = this.getAudioInstance(src, tag, is_music, looping!==0, v); if (!lastAudio) { var b = this.getAudioBuffer(src, is_music); b.panWhenReady.push({ x: x_, y: y_, a: angle_, ia: innerangle_, oa: outerangle_, og: dbToLinear(outergain_), thistag: tag }); return; } lastAudio.setPannerEnabled(true); lastAudio.setPan(x_, y_, angle_, innerangle_, outerangle_, dbToLinear(outergain_)); lastAudio.play(looping!==0, v, 0, this.nextPlayTime); this.nextPlayTime = 0; }; Acts.prototype.PlayAtObjectByName = function (folder, filename, looping, vol, obj, innerangle, outerangle, outergain, tag) { if (silent || !obj) return; var inst = obj.getFirstPicked(); if (!inst) return; var v = dbToLinear(vol); var is_music = (folder === 1); var src = this.runtime.files_subfolder + filename.toLowerCase() + (useOgg ? ".ogg" : ".m4a"); lastAudio = this.getAudioInstance(src, tag, is_music, looping!==0, v); if (!lastAudio) { var b = this.getAudioBuffer(src, is_music); b.panWhenReady.push({ obj: inst, ia: innerangle, oa: outerangle, og: dbToLinear(outergain), thistag: tag }); return; } lastAudio.setPannerEnabled(true); var px = cr.rotatePtAround(inst.x, inst.y, -inst.layer.getAngle(), listenerX, listenerY, true); var py = cr.rotatePtAround(inst.x, inst.y, -inst.layer.getAngle(), listenerX, listenerY, false); lastAudio.setPan(px, py, cr.to_degrees(inst.angle - inst.layer.getAngle()), innerangle, outerangle, dbToLinear(outergain)); lastAudio.setObject(inst); lastAudio.play(looping!==0, v, 0, this.nextPlayTime); this.nextPlayTime = 0; }; Acts.prototype.SetLooping = function (tag, looping) { getAudioByTag(tag); var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) taggedAudio[i].setLooping(looping === 0); }; Acts.prototype.SetMuted = function (tag, muted) { getAudioByTag(tag); var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) taggedAudio[i].setMuted(muted === 0); }; Acts.prototype.SetVolume = function (tag, vol) { getAudioByTag(tag); var v = dbToLinear(vol); var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) taggedAudio[i].setVolume(v); }; Acts.prototype.Preload = function (file) { if (silent) return; var is_music = file[1]; var src = this.runtime.files_subfolder + file[0] + (useOgg ? ".ogg" : ".m4a"); if (api === API_APPMOBI) { if (this.runtime.isDirectCanvas) AppMobi["context"]["loadSound"](src); else AppMobi["player"]["loadSound"](src); return; } else if (api === API_CORDOVA) { return; } this.getAudioInstance(src, "", is_music, false); }; Acts.prototype.PreloadByName = function (folder, filename) { if (silent) return; var is_music = (folder === 1); var src = this.runtime.files_subfolder + filename.toLowerCase() + (useOgg ? ".ogg" : ".m4a"); if (api === API_APPMOBI) { if (this.runtime.isDirectCanvas) AppMobi["context"]["loadSound"](src); else AppMobi["player"]["loadSound"](src); return; } else if (api === API_CORDOVA) { return; } this.getAudioInstance(src, "", is_music, false); }; Acts.prototype.SetPlaybackRate = function (tag, rate) { getAudioByTag(tag); if (rate < 0.0) rate = 0; var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) taggedAudio[i].setPlaybackRate(rate); }; Acts.prototype.Stop = function (tag) { getAudioByTag(tag); var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) taggedAudio[i].stop(); }; Acts.prototype.StopAll = function () { var i, len; for (i = 0, len = audioInstances.length; i < len; i++) audioInstances[i].stop(); }; Acts.prototype.SetPaused = function (tag, state) { getAudioByTag(tag); var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) { if (state === 0) taggedAudio[i].pause(); else taggedAudio[i].resume(); } }; Acts.prototype.Seek = function (tag, pos) { getAudioByTag(tag); var i, len; for (i = 0, len = taggedAudio.length; i < len; i++) { taggedAudio[i].seek(pos); } }; Acts.prototype.SetSilent = function (s) { var i, len; if (s === 2) // toggling s = (silent ? 1 : 0); // choose opposite state if (s === 0 && !silent) // setting silent { for (i = 0, len = audioInstances.length; i < len; i++) audioInstances[i].setSilent(true); silent = true; } else if (s === 1 && silent) // setting not silent { for (i = 0, len = audioInstances.length; i < len; i++) audioInstances[i].setSilent(false); silent = false; } }; Acts.prototype.SetMasterVolume = function (vol) { masterVolume = dbToLinear(vol); var i, len; for (i = 0, len = audioInstances.length; i < len; i++) audioInstances[i].updateVolume(); }; Acts.prototype.AddFilterEffect = function (tag, type, freq, detune, q, gain, mix) { if (api !== API_WEBAUDIO || type < 0 || type >= filterTypes.length || !context["createBiquadFilter"]) return; tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; addEffectForTag(tag, new FilterEffect(type, freq, detune, q, gain, mix)); }; Acts.prototype.AddDelayEffect = function (tag, delay, gain, mix) { if (api !== API_WEBAUDIO) return; tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; addEffectForTag(tag, new DelayEffect(delay, dbToLinear(gain), mix)); }; Acts.prototype.AddFlangerEffect = function (tag, delay, modulation, freq, feedback, mix) { if (api !== API_WEBAUDIO || !context["createOscillator"]) return; tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; addEffectForTag(tag, new FlangerEffect(delay / 1000, modulation / 1000, freq, feedback / 100, mix)); }; Acts.prototype.AddPhaserEffect = function (tag, freq, detune, q, mod, modfreq, mix) { if (api !== API_WEBAUDIO || !context["createOscillator"]) return; tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; addEffectForTag(tag, new PhaserEffect(freq, detune, q, mod, modfreq, mix)); }; Acts.prototype.AddConvolutionEffect = function (tag, file, norm, mix) { if (api !== API_WEBAUDIO || !context["createConvolver"]) return; var doNormalize = (norm === 0); var src = this.runtime.files_subfolder + file[0] + (useOgg ? ".ogg" : ".m4a"); var b = this.getAudioBuffer(src, false); tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; var fx; if (b.bufferObject) { fx = new ConvolveEffect(b.bufferObject, doNormalize, mix, src); } else { fx = new ConvolveEffect(null, doNormalize, mix, src); b.normalizeWhenReady = doNormalize; b.convolveWhenReady = fx; } addEffectForTag(tag, fx); }; Acts.prototype.AddGainEffect = function (tag, g) { if (api !== API_WEBAUDIO) return; tag = tag.toLowerCase(); addEffectForTag(tag, new GainEffect(dbToLinear(g))); }; Acts.prototype.AddMuteEffect = function (tag) { if (api !== API_WEBAUDIO) return; tag = tag.toLowerCase(); addEffectForTag(tag, new GainEffect(0)); // re-use gain effect with 0 gain }; Acts.prototype.AddTremoloEffect = function (tag, freq, mix) { if (api !== API_WEBAUDIO || !context["createOscillator"]) return; tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; addEffectForTag(tag, new TremoloEffect(freq, mix)); }; Acts.prototype.AddRingModEffect = function (tag, freq, mix) { if (api !== API_WEBAUDIO || !context["createOscillator"]) return; tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; addEffectForTag(tag, new RingModulatorEffect(freq, mix)); }; Acts.prototype.AddDistortionEffect = function (tag, threshold, headroom, drive, makeupgain, mix) { if (api !== API_WEBAUDIO || !context["createWaveShaper"]) return; tag = tag.toLowerCase(); mix = mix / 100; if (mix < 0) mix = 0; if (mix > 1) mix = 1; addEffectForTag(tag, new DistortionEffect(threshold, headroom, drive, makeupgain, mix)); }; Acts.prototype.AddCompressorEffect = function (tag, threshold, knee, ratio, attack, release) { if (api !== API_WEBAUDIO || !context["createDynamicsCompressor"]) return; tag = tag.toLowerCase(); addEffectForTag(tag, new CompressorEffect(threshold, knee, ratio, attack / 1000, release / 1000)); }; Acts.prototype.AddAnalyserEffect = function (tag, fftSize, smoothing) { if (api !== API_WEBAUDIO) return; tag = tag.toLowerCase(); addEffectForTag(tag, new AnalyserEffect(fftSize, smoothing)); }; Acts.prototype.RemoveEffects = function (tag) { if (api !== API_WEBAUDIO) return; tag = tag.toLowerCase(); var i, len, arr; if (effects.hasOwnProperty(tag)) { arr = effects[tag]; if (arr.length) { for (i = 0, len = arr.length; i < len; i++) arr[i].remove(); cr.clearArray(arr); reconnectEffects(tag); } } }; Acts.prototype.SetEffectParameter = function (tag, index, param, value, ramp, time) { if (api !== API_WEBAUDIO) return; tag = tag.toLowerCase(); index = Math.floor(index); var arr; if (!effects.hasOwnProperty(tag)) return; arr = effects[tag]; if (index < 0 || index >= arr.length) return; arr[index].setParam(param, value, ramp, time); }; Acts.prototype.SetListenerObject = function (obj_) { if (!obj_ || api !== API_WEBAUDIO) return; var inst = obj_.getFirstPicked(); if (!inst) return; this.listenerTracker.setObject(inst); listenerX = inst.x; listenerY = inst.y; }; Acts.prototype.SetListenerZ = function (z) { this.listenerZ = z; }; Acts.prototype.ScheduleNextPlay = function (t) { if (!context) return; // needs Web Audio API this.nextPlayTime = t; }; Acts.prototype.UnloadAudio = function (file) { var is_music = file[1]; var src = this.runtime.files_subfolder + file[0] + (useOgg ? ".ogg" : ".m4a"); var b = this.getAudioBuffer(src, is_music, true /* don't create if missing */); if (!b) return; // not loaded b.release(); cr.arrayFindRemove(audioBuffers, b); }; Acts.prototype.UnloadAudioByName = function (folder, filename) { var is_music = (folder === 1); var src = this.runtime.files_subfolder + filename.toLowerCase() + (useOgg ? ".ogg" : ".m4a"); var b = this.getAudioBuffer(src, is_music, true /* don't create if missing */); if (!b) return; // not loaded b.release(); cr.arrayFindRemove(audioBuffers, b); }; Acts.prototype.UnloadAll = function () { var i, len; for (i = 0, len = audioBuffers.length; i < len; ++i) { audioBuffers[i].release(); }; cr.clearArray(audioBuffers); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Duration = function (ret, tag) { getAudioByTag(tag, true); if (taggedAudio.length) ret.set_float(taggedAudio[0].getDuration()); else ret.set_float(0); }; Exps.prototype.PlaybackTime = function (ret, tag) { getAudioByTag(tag, true); if (taggedAudio.length) ret.set_float(taggedAudio[0].getPlaybackTime(true)); else ret.set_float(0); }; Exps.prototype.Volume = function (ret, tag) { getAudioByTag(tag, true); if (taggedAudio.length) { var v = taggedAudio[0].getVolume(); ret.set_float(linearToDb(v)); } else ret.set_float(0); }; Exps.prototype.MasterVolume = function (ret) { ret.set_float(linearToDb(masterVolume)); }; Exps.prototype.EffectCount = function (ret, tag) { tag = tag.toLowerCase(); var arr = null; if (effects.hasOwnProperty(tag)) arr = effects[tag]; ret.set_int(arr ? arr.length : 0); }; function getAnalyser(tag, index) { var arr = null; if (effects.hasOwnProperty(tag)) arr = effects[tag]; if (arr && index >= 0 && index < arr.length && arr[index].freqBins) return arr[index]; else return null; }; Exps.prototype.AnalyserFreqBinCount = function (ret, tag, index) { tag = tag.toLowerCase(); index = Math.floor(index); var analyser = getAnalyser(tag, index); ret.set_int(analyser ? analyser.node["frequencyBinCount"] : 0); }; Exps.prototype.AnalyserFreqBinAt = function (ret, tag, index, bin) { tag = tag.toLowerCase(); index = Math.floor(index); bin = Math.floor(bin); var analyser = getAnalyser(tag, index); if (!analyser) ret.set_float(0); else if (bin < 0 || bin >= analyser.node["frequencyBinCount"]) ret.set_float(0); else ret.set_float(analyser.freqBins[bin]); }; Exps.prototype.AnalyserPeakLevel = function (ret, tag, index) { tag = tag.toLowerCase(); index = Math.floor(index); var analyser = getAnalyser(tag, index); if (analyser) ret.set_float(analyser.peak); else ret.set_float(0); }; Exps.prototype.AnalyserRMSLevel = function (ret, tag, index) { tag = tag.toLowerCase(); index = Math.floor(index); var analyser = getAnalyser(tag, index); if (analyser) ret.set_float(analyser.rms); else ret.set_float(0); }; Exps.prototype.SampleRate = function (ret) { ret.set_int(context ? context.sampleRate : 0); }; Exps.prototype.CurrentTime = function (ret) { ret.set_float(context ? context.currentTime : cr.performance_now()); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Browser = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Browser.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; var offlineScriptReady = false; var browserPluginReady = false; document.addEventListener("DOMContentLoaded", function () { if (window["C2_RegisterSW"] && navigator["serviceWorker"]) { var offlineClientScript = document.createElement("script"); offlineClientScript.onload = function () { offlineScriptReady = true; checkReady() }; offlineClientScript.src = "offlineClient.js"; document.head.appendChild(offlineClientScript); } }); var browserInstance = null; typeProto.onAppBegin = function () { browserPluginReady = true; checkReady(); }; function checkReady() { if (offlineScriptReady && browserPluginReady && window["OfflineClientInfo"]) { window["OfflineClientInfo"]["SetMessageCallback"](function (e) { browserInstance.onSWMessage(e); }); } }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { var self = this; window.addEventListener("resize", function () { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnResize, self); }); browserInstance = this; if (typeof navigator.onLine !== "undefined") { window.addEventListener("online", function() { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnOnline, self); }); window.addEventListener("offline", function() { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnOffline, self); }); } if (!this.runtime.isDirectCanvas) { document.addEventListener("appMobi.device.update.available", function() { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnUpdateReady, self); }); document.addEventListener("backbutton", function() { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnBackButton, self); }); document.addEventListener("menubutton", function() { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnMenuButton, self); }); document.addEventListener("searchbutton", function() { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnSearchButton, self); }); document.addEventListener("tizenhwkey", function (e) { var ret; switch (e["keyName"]) { case "back": ret = self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnBackButton, self); if (!ret) { if (window["tizen"]) window["tizen"]["application"]["getCurrentApplication"]()["exit"](); } break; case "menu": ret = self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnMenuButton, self); if (!ret) e.preventDefault(); break; } }); } if (this.runtime.isWindows10 && typeof Windows !== "undefined") { Windows["UI"]["Core"]["SystemNavigationManager"]["getForCurrentView"]().addEventListener("backrequested", function (e) { var ret = self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnBackButton, self); if (ret) e["handled"] = true; }); } else if (this.runtime.isWinJS && WinJS["Application"]) { WinJS["Application"]["onbackclick"] = function (e) { return !!self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnBackButton, self); }; } this.runtime.addSuspendCallback(function(s) { if (s) { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnPageHidden, self); } else { self.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnPageVisible, self); } }); this.is_arcade = (typeof window["is_scirra_arcade"] !== "undefined"); }; instanceProto.onSWMessage = function (e) { var messageType = e["data"]["type"]; if (messageType === "downloading-update") this.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnUpdateFound, this); else if (messageType === "update-ready" || messageType === "update-pending") this.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnUpdateReady, this); else if (messageType === "offline-ready") this.runtime.trigger(cr.plugins_.Browser.prototype.cnds.OnOfflineReady, this); }; var batteryManager = null; var loadedBatteryManager = false; function maybeLoadBatteryManager() { if (loadedBatteryManager) return; if (!navigator["getBattery"]) return; var promise = navigator["getBattery"](); loadedBatteryManager = true; if (promise) { promise.then(function (manager) { batteryManager = manager; }); } }; function Cnds() {}; Cnds.prototype.CookiesEnabled = function() { return navigator ? navigator.cookieEnabled : false; }; Cnds.prototype.IsOnline = function() { return navigator ? navigator.onLine : false; }; Cnds.prototype.HasJava = function() { return navigator ? navigator.javaEnabled() : false; }; Cnds.prototype.OnOnline = function() { return true; }; Cnds.prototype.OnOffline = function() { return true; }; Cnds.prototype.IsDownloadingUpdate = function () { return false; // deprecated }; Cnds.prototype.OnUpdateReady = function () { return true; }; Cnds.prototype.PageVisible = function () { return !this.runtime.isSuspended; }; Cnds.prototype.OnPageVisible = function () { return true; }; Cnds.prototype.OnPageHidden = function () { return true; }; Cnds.prototype.OnResize = function () { return true; }; Cnds.prototype.IsFullscreen = function () { return !!(document["mozFullScreen"] || document["webkitIsFullScreen"] || document["fullScreen"] || this.runtime.isNodeFullscreen); }; Cnds.prototype.OnBackButton = function () { return true; }; Cnds.prototype.OnMenuButton = function () { return true; }; Cnds.prototype.OnSearchButton = function () { return true; }; Cnds.prototype.IsMetered = function () { var connection = navigator["connection"] || navigator["mozConnection"] || navigator["webkitConnection"]; if (!connection) return false; return !!connection["metered"]; }; Cnds.prototype.IsCharging = function () { var battery = navigator["battery"] || navigator["mozBattery"] || navigator["webkitBattery"]; if (battery) { return !!battery["charging"] } else { maybeLoadBatteryManager(); if (batteryManager) { return !!batteryManager["charging"]; } else { return true; // if unknown, default to charging (powered) } } }; Cnds.prototype.IsPortraitLandscape = function (p) { var current = (window.innerWidth <= window.innerHeight ? 0 : 1); return current === p; }; Cnds.prototype.SupportsFullscreen = function () { if (this.runtime.isNodeWebkit) return true; var elem = this.runtime.canvasdiv || this.runtime.canvas; return !!(elem["requestFullscreen"] || elem["mozRequestFullScreen"] || elem["msRequestFullscreen"] || elem["webkitRequestFullScreen"]); }; Cnds.prototype.OnUpdateFound = function () { return true; }; Cnds.prototype.OnUpdateReady = function () { return true; }; Cnds.prototype.OnOfflineReady = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Alert = function (msg) { if (!this.runtime.isDomFree) alert(msg.toString()); }; Acts.prototype.Close = function () { if (this.runtime.isCocoonJs) CocoonJS["App"]["forceToFinish"](); else if (window["tizen"]) window["tizen"]["application"]["getCurrentApplication"]()["exit"](); else if (navigator["app"] && navigator["app"]["exitApp"]) navigator["app"]["exitApp"](); else if (navigator["device"] && navigator["device"]["exitApp"]) navigator["device"]["exitApp"](); else if (!this.is_arcade && !this.runtime.isDomFree) window.close(); }; Acts.prototype.Focus = function () { if (this.runtime.isNodeWebkit) { var win = window["nwgui"]["Window"]["get"](); win["focus"](); } else if (!this.is_arcade && !this.runtime.isDomFree) window.focus(); }; Acts.prototype.Blur = function () { if (this.runtime.isNodeWebkit) { var win = window["nwgui"]["Window"]["get"](); win["blur"](); } else if (!this.is_arcade && !this.runtime.isDomFree) window.blur(); }; Acts.prototype.GoBack = function () { if (navigator["app"] && navigator["app"]["backHistory"]) navigator["app"]["backHistory"](); else if (!this.is_arcade && !this.runtime.isDomFree && window.back) window.back(); }; Acts.prototype.GoForward = function () { if (!this.is_arcade && !this.runtime.isDomFree && window.forward) window.forward(); }; Acts.prototype.GoHome = function () { if (!this.is_arcade && !this.runtime.isDomFree && window.home) window.home(); }; Acts.prototype.GoToURL = function (url, target) { if (this.runtime.isCocoonJs) CocoonJS["App"]["openURL"](url); else if (this.runtime.isEjecta) ejecta["openURL"](url); else if (this.runtime.isWinJS) Windows["System"]["Launcher"]["launchUriAsync"](new Windows["Foundation"]["Uri"](url)); else if (navigator["app"] && navigator["app"]["loadUrl"]) navigator["app"]["loadUrl"](url, { "openExternal": true }); else if (this.runtime.isCordova) window.open(url, "_system"); else if (!this.is_arcade && !this.runtime.isDomFree) { if (target === 2 && !this.is_arcade) // top window.top.location = url; else if (target === 1 && !this.is_arcade) // parent window.parent.location = url; else // self window.location = url; } }; Acts.prototype.GoToURLWindow = function (url, tag) { if (this.runtime.isCocoonJs) CocoonJS["App"]["openURL"](url); else if (this.runtime.isEjecta) ejecta["openURL"](url); else if (this.runtime.isWinJS) Windows["System"]["Launcher"]["launchUriAsync"](new Windows["Foundation"]["Uri"](url)); else if (navigator["app"] && navigator["app"]["loadUrl"]) navigator["app"]["loadUrl"](url, { "openExternal": true }); else if (this.runtime.isCordova) window.open(url, "_system"); else if (!this.is_arcade && !this.runtime.isDomFree) window.open(url, tag); }; Acts.prototype.Reload = function () { if (!this.is_arcade && !this.runtime.isDomFree) window.location.reload(); }; var firstRequestFullscreen = true; var crruntime = null; function onFullscreenError(e) { if (console && console.warn) console.warn("Fullscreen request failed: ", e); crruntime["setSize"](window.innerWidth, window.innerHeight); }; Acts.prototype.RequestFullScreen = function (stretchmode) { if (this.runtime.isDomFree) { cr.logexport("[Construct 2] Requesting fullscreen is not supported on this platform - the request has been ignored"); return; } if (stretchmode >= 2) stretchmode += 1; if (stretchmode === 6) stretchmode = 2; if (this.runtime.isNodeWebkit) { if (this.runtime.isDebug) { debuggerFullscreen(true); } else if (!this.runtime.isNodeFullscreen && window["nwgui"]) { window["nwgui"]["Window"]["get"]()["enterFullscreen"](); this.runtime.isNodeFullscreen = true; this.runtime.fullscreen_scaling = (stretchmode >= 2 ? stretchmode : 0); } } else { if (document["mozFullScreen"] || document["webkitIsFullScreen"] || !!document["msFullscreenElement"] || document["fullScreen"] || document["fullScreenElement"]) { return; } this.runtime.fullscreen_scaling = (stretchmode >= 2 ? stretchmode : 0); var elem = document.documentElement; if (firstRequestFullscreen) { firstRequestFullscreen = false; crruntime = this.runtime; elem.addEventListener("mozfullscreenerror", onFullscreenError); elem.addEventListener("webkitfullscreenerror", onFullscreenError); elem.addEventListener("MSFullscreenError", onFullscreenError); elem.addEventListener("fullscreenerror", onFullscreenError); } if (elem["requestFullscreen"]) elem["requestFullscreen"](); else if (elem["mozRequestFullScreen"]) elem["mozRequestFullScreen"](); else if (elem["msRequestFullscreen"]) elem["msRequestFullscreen"](); else if (elem["webkitRequestFullScreen"]) { if (typeof Element !== "undefined" && typeof Element["ALLOW_KEYBOARD_INPUT"] !== "undefined") elem["webkitRequestFullScreen"](Element["ALLOW_KEYBOARD_INPUT"]); else elem["webkitRequestFullScreen"](); } } }; Acts.prototype.CancelFullScreen = function () { if (this.runtime.isDomFree) { cr.logexport("[Construct 2] Exiting fullscreen is not supported on this platform - the request has been ignored"); return; } if (this.runtime.isNodeWebkit) { if (this.runtime.isDebug) { debuggerFullscreen(false); } else if (this.runtime.isNodeFullscreen && window["nwgui"]) { window["nwgui"]["Window"]["get"]()["leaveFullscreen"](); this.runtime.isNodeFullscreen = false; } } else { if (document["exitFullscreen"]) document["exitFullscreen"](); else if (document["mozCancelFullScreen"]) document["mozCancelFullScreen"](); else if (document["msExitFullscreen"]) document["msExitFullscreen"](); else if (document["webkitCancelFullScreen"]) document["webkitCancelFullScreen"](); } }; Acts.prototype.Vibrate = function (pattern_) { try { var arr = pattern_.split(","); var i, len; for (i = 0, len = arr.length; i < len; i++) { arr[i] = parseInt(arr[i], 10); } if (navigator["vibrate"]) navigator["vibrate"](arr); else if (navigator["mozVibrate"]) navigator["mozVibrate"](arr); else if (navigator["webkitVibrate"]) navigator["webkitVibrate"](arr); else if (navigator["msVibrate"]) navigator["msVibrate"](arr); } catch (e) {} }; Acts.prototype.InvokeDownload = function (url_, filename_) { var a = document.createElement("a"); if (typeof a["download"] === "undefined") { window.open(url_); } else { var body = document.getElementsByTagName("body")[0]; a.textContent = filename_; a.href = url_; a["download"] = filename_; body.appendChild(a); var clickEvent = new MouseEvent("click"); a.dispatchEvent(clickEvent); body.removeChild(a); } }; Acts.prototype.InvokeDownloadString = function (str_, mimetype_, filename_) { var datauri = "data:" + mimetype_ + "," + encodeURIComponent(str_); var a = document.createElement("a"); if (typeof a["download"] === "undefined") { window.open(datauri); } else { var body = document.getElementsByTagName("body")[0]; a.textContent = filename_; a.href = datauri; a["download"] = filename_; body.appendChild(a); var clickEvent = new MouseEvent("click"); a.dispatchEvent(clickEvent); body.removeChild(a); } }; Acts.prototype.ConsoleLog = function (type_, msg_) { if (typeof console === "undefined") return; if (type_ === 0 && console.log) console.log(msg_.toString()); if (type_ === 1 && console.warn) console.warn(msg_.toString()); if (type_ === 2 && console.error) console.error(msg_.toString()); }; Acts.prototype.ConsoleGroup = function (name_) { if (console && console.group) console.group(name_); }; Acts.prototype.ConsoleGroupEnd = function () { if (console && console.groupEnd) console.groupEnd(); }; Acts.prototype.ExecJs = function (js_) { try { if (eval) eval(js_); } catch (e) { if (console && console.error) console.error("Error executing Javascript: ", e); } }; var orientations = [ "portrait", "landscape", "portrait-primary", "portrait-secondary", "landscape-primary", "landscape-secondary" ]; Acts.prototype.LockOrientation = function (o) { o = Math.floor(o); if (o < 0 || o >= orientations.length) return; this.runtime.autoLockOrientation = false; var orientation = orientations[o]; if (screen["orientation"] && screen["orientation"]["lock"]) screen["orientation"]["lock"](orientation); else if (screen["lockOrientation"]) screen["lockOrientation"](orientation); else if (screen["webkitLockOrientation"]) screen["webkitLockOrientation"](orientation); else if (screen["mozLockOrientation"]) screen["mozLockOrientation"](orientation); else if (screen["msLockOrientation"]) screen["msLockOrientation"](orientation); }; Acts.prototype.UnlockOrientation = function () { this.runtime.autoLockOrientation = false; if (screen["orientation"] && screen["orientation"]["unlock"]) screen["orientation"]["unlock"](); else if (screen["unlockOrientation"]) screen["unlockOrientation"](); else if (screen["webkitUnlockOrientation"]) screen["webkitUnlockOrientation"](); else if (screen["mozUnlockOrientation"]) screen["mozUnlockOrientation"](); else if (screen["msUnlockOrientation"]) screen["msUnlockOrientation"](); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.URL = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : window.location.toString()); }; Exps.prototype.Protocol = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : window.location.protocol); }; Exps.prototype.Domain = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : window.location.hostname); }; Exps.prototype.PathName = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : window.location.pathname); }; Exps.prototype.Hash = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : window.location.hash); }; Exps.prototype.Referrer = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : document.referrer); }; Exps.prototype.Title = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : document.title); }; Exps.prototype.Name = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : navigator.appName); }; Exps.prototype.Version = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : navigator.appVersion); }; Exps.prototype.Language = function (ret) { if (navigator && navigator.language) ret.set_string(navigator.language); else ret.set_string(""); }; Exps.prototype.Platform = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : navigator.platform); }; Exps.prototype.Product = function (ret) { if (navigator && navigator.product) ret.set_string(navigator.product); else ret.set_string(""); }; Exps.prototype.Vendor = function (ret) { if (navigator && navigator.vendor) ret.set_string(navigator.vendor); else ret.set_string(""); }; Exps.prototype.UserAgent = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : navigator.userAgent); }; Exps.prototype.QueryString = function (ret) { ret.set_string(this.runtime.isDomFree ? "" : window.location.search); }; Exps.prototype.QueryParam = function (ret, paramname) { if (this.runtime.isDomFree) { ret.set_string(""); return; } var match = RegExp('[?&]' + paramname + '=([^&]*)').exec(window.location.search); if (match) ret.set_string(decodeURIComponent(match[1].replace(/\+/g, ' '))); else ret.set_string(""); }; Exps.prototype.Bandwidth = function (ret) { var connection = navigator["connection"] || navigator["mozConnection"] || navigator["webkitConnection"]; if (!connection) ret.set_float(Number.POSITIVE_INFINITY); else { if (typeof connection["bandwidth"] !== "undefined") ret.set_float(connection["bandwidth"]); else if (typeof connection["downlinkMax"] !== "undefined") ret.set_float(connection["downlinkMax"]); else ret.set_float(Number.POSITIVE_INFINITY); } }; Exps.prototype.ConnectionType = function (ret) { var connection = navigator["connection"] || navigator["mozConnection"] || navigator["webkitConnection"]; if (!connection) ret.set_string("unknown"); else { ret.set_string(connection["type"] || "unknown"); } }; Exps.prototype.BatteryLevel = function (ret) { var battery = navigator["battery"] || navigator["mozBattery"] || navigator["webkitBattery"]; if (battery) { ret.set_float(battery["level"]); } else { maybeLoadBatteryManager(); if (batteryManager) { ret.set_float(batteryManager["level"]); } else { ret.set_float(1); // not supported/unknown: assume charged } } }; Exps.prototype.BatteryTimeLeft = function (ret) { var battery = navigator["battery"] || navigator["mozBattery"] || navigator["webkitBattery"]; if (battery) { ret.set_float(battery["dischargingTime"]); } else { maybeLoadBatteryManager(); if (batteryManager) { ret.set_float(batteryManager["dischargingTime"]); } else { ret.set_float(Number.POSITIVE_INFINITY); // not supported/unknown: assume infinite time left } } }; Exps.prototype.ExecJS = function (ret, js_) { if (!eval) { ret.set_any(0); return; } var result = 0; try { result = eval(js_); } catch (e) { if (console && console.error) console.error("Error executing Javascript: ", e); } if (typeof result === "number") ret.set_any(result); else if (typeof result === "string") ret.set_any(result); else if (typeof result === "boolean") ret.set_any(result ? 1 : 0); else ret.set_any(0); }; Exps.prototype.ScreenWidth = function (ret) { ret.set_int(screen.width); }; Exps.prototype.ScreenHeight = function (ret) { ret.set_int(screen.height); }; Exps.prototype.DevicePixelRatio = function (ret) { ret.set_float(this.runtime.devicePixelRatio); }; Exps.prototype.WindowInnerWidth = function (ret) { ret.set_int(window.innerWidth); }; Exps.prototype.WindowInnerHeight = function (ret) { ret.set_int(window.innerHeight); }; Exps.prototype.WindowOuterWidth = function (ret) { ret.set_int(window.outerWidth); }; Exps.prototype.WindowOuterHeight = function (ret) { ret.set_int(window.outerHeight); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.CBhash = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.CBhash.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; this.lastResult = ""; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.hexcase = 0; this.b64pad = " "; }; pluginProto.cnds = {}; var cnds = pluginProto.cnds; cnds.OnHashed = function () { return true; }; instanceProto.hex_md5 = function(s) { return this.rstr2hex(rstr_md5(str2rstr_utf8(s))); } instanceProto.b64_md5 = function(s) { return this.rstr2b64(rstr_md5(str2rstr_utf8(s))); } instanceProto.any_md5 = function(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); } instanceProto.hex_hmac_md5 = function(k, d) { return this.rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } instanceProto.b64_hmac_md5 = function(k, d) { return this.rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); } instanceProto.any_hmac_md5= function(k, d, e) { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); } instanceProto.hex_sha1 = function(s) { return this.rstr2hex(rstr_sha1(str2rstr_utf8(s))); } instanceProto.b64_sha1 = function(s) { return this.rstr2b64(rstr_sha1(str2rstr_utf8(s))); } instanceProto.any_sha1 = function(s, e) { return rstr2any(rstr_sha1(str2rstr_utf8(s)), e); } instanceProto.hex_hmac_sha1 = function(k, d) { return this.rstr2hex(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } instanceProto.b64_hmac_sha1 = function(k, d) { return this.rstr2b64(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d))); } instanceProto.any_hmac_sha1 = function(k, d, e) { return rstr2any(rstr_hmac_sha1(str2rstr_utf8(k), str2rstr_utf8(d)), e); } instanceProto.hex_sha256 = function(s) { return this.rstr2hex(rstr_sha256(str2rstr_utf8(s))); } instanceProto.b64_sha256 = function(s) { return this.rstr2b64(rstr_sha256(str2rstr_utf8(s))); } instanceProto.any_sha256 = function(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); } instanceProto.hex_hmac_sha256 = function(k, d) { return this.rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); } instanceProto.b64_hmac_sha256 = function(k, d) { return this.rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); } instanceProto.any_hmac_sha256 = function(k, d, e) { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); } /* * Convert a raw string to a hex string */ instanceProto.rstr2hex = function(input) { try { this.hexcase } catch(e) { this.hexcase = 0; } var hex_tab = this.hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; var output = ""; var x; for(var i = 0; i < input.length; i++) { x = input.charCodeAt(i); output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt( x & 0x0F); } return output; } /* * Convert a raw string to a base-64 string */ instanceProto.rstr2b64 = function(input) { try { this.b64pad } catch(e) { this.b64pad=''; } var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; var output = ""; var len = input.length; for(var i = 0; i < len; i += 3) { var triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i+2) : 0); for(var j = 0; j < 4; j++) { if(i * 8 + j * 6 > input.length * 8) output += this.b64pad; else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); } } return output; } pluginProto.acts = {}; var acts = pluginProto.acts; acts.set_hexoutput = function (format) { if (format == 0) this.hexcase = 0; else this.hexcase = 1; }; acts.set_bpad = function (charac) { this.b64pad = charac; }; acts.MD5_hash = function (string, format) { var outF = format; if (outF == 0) this.lastResult = this.hex_md5(string); else this.lastResult = this.b64_md5(string); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.MD5_pass = function (string, encoding) { this.lastResult = this.any_md5(string, encoding); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.HMAC_hash = function (key, data, Format) { if (Format == 0) this.lastResult = this.hex_hmac_md5(key, data); else this.lastResult = this.b64_hmac_md5(key, data); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.HMAC_pass = function (key, data, charString) { this.lastResult = this.any_hmac_md5(key, data, charString); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.SHA1_hash = function (string, format) { var outF = format; if (outF == 0) this.lastResult = this.hex_sha1(string); else this.lastResult = this.b64_sha1(string); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.SHA1_pass = function (string, encoding) { this.lastResult = this.any_sha1(string, encoding); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.HMACSHA1_hash = function (key, data, Format) { if (Format == 0) this.lastResult = this.hex_hmac_sha1(key, data); else this.lastResult = this.b64_hmac_sha1(key, data); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.HMACSHA1_pass = function (key, data, charString) { this.lastResult = this.any_hmac_sha1(key, data, charString); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.SHA256_hash = function (string, format) { var outF = format; if (outF == 0) this.lastResult = this.hex_sha256(string); else this.lastResult = this.b64_sha256(string); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.SHA256_pass = function (string, encoding) { this.lastResult = this.any_sha256(string, encoding); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.HMACSHA256_hash = function (key, data, Format) { if (Format == 0) this.lastResult = this.hex_hmac_sha256(key, data); else this.lastResult = this.b64_hmac_sha256(key, data); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; acts.HMACSHA256_pass = function (key, data, charString) { this.lastResult = this.any_hmac_sha256(key, data, charString); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; pluginProto.exps = {}; var exps = pluginProto.exps; exps.get_lastResult = function (ret) { ret.set_string(this.lastResult); }; exps.MD5 = function (ret, data) { ret.set_string(this.hex_md5(data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.MD5B = function (ret, data) { ret.set_string(this.b64_md5(data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.MD5pass = function (ret, data, charstring) { ret.set_string(this.any_md5(data, charstring)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACMD5 = function (ret, key, data) { ret.set_string(this.hex_hmac_md5(key, data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACMD5B = function (ret, key, data) { ret.set_string(this.b64_hmac_md5(key, data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACMD5pass = function (ret, key, data, charstring) { ret.set_string(this.any_hmac_md5(key, data, charstring)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.SHA1 = function (ret, data) { ret.set_string(this.hex_sha1(data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.SHA1B = function (ret, data) { ret.set_string(this.b64_sha1(data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.SHA1pass = function (ret, data, charstring) { ret.set_string(this.any_sha1(data, charstring)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACSHA1 = function (ret, key, data) { ret.set_string(this.hex_hmac_sha1(key, data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACSHA1B = function (ret, key, data) { ret.set_string(this.b64_hmac_sha1(key, data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACSHA1pass = function (ret, key, data, charstring) { ret.set_string(this.any_hmac_sha1(key, data, charstring)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.SHA256 = function (ret, data) { ret.set_string(this.hex_sha256(data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.SHA256B = function (ret, data) { ret.set_string(this.b64_sha256(data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.SHA256pass = function (ret, data, charstring) { ret.set_string(this.any_sha256(data, charstring)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACSHA256 = function (ret, key, data) { ret.set_string(this.hex_hmac_sha256(key, data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACSHA256B = function (ret, key, data) { ret.set_string(this.b64_hmac_sha256(key, data)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; exps.HMACSHA256pass = function (ret, key, data, charstring) { ret.set_string(this.any_hmac_sha256(key, data, charstring)); this.runtime.trigger(cr.plugins_.CBhash.prototype.cnds.OnHashed, this); }; /* * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message * Digest Algorithm, as defined in RFC 1321. * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for more info. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * The JavaScript code implementing the algorithm is derived from the C code in RFC 1321 and is covered by the following copyright: * License to copy and use this software is granted provided that it is identified as the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing this software or this function. * License is also granted to make and use derivative works provided that such works are identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning or referencing the derived work. * RSA Data Security, Inc. makes no representations concerning either the merchantability of this software or the suitability of this software for any particular purpose. It is provided "as is" without express or implied warranty of any kind. * These notices must be retained in any copies of any part of this documentation and/or software. * This copyright does not prohibit distribution of the JavaScript MD5 code under the BSD license. */ /* * Calculate the MD5 of a raw string */ function rstr_md5(s) { return binl2rstr(binl_md5(rstr2binl(s), s.length * 8)); } /* * Calculate the HMAC-MD5, of a key and some data (raw strings) */ function rstr_hmac_md5(key, data) { var bkey = rstr2binl(key); if(bkey.length > 16) bkey = binl_md5(bkey, key.length * 8); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8); return binl2rstr(binl_md5(opad.concat(hash), 512 + 128)); } /* * Convert a raw string to an arbitrary string encoding */ function rstr2any(input, encoding) { var divisor = encoding.length; var i, j, q, x, quotient; /* Convert to an array of 16-bit big-endian values, forming the dividend */ var dividend = Array(Math.ceil(input.length / 2)); for(i = 0; i < dividend.length; i++) { dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); } /* * Repeatedly perform a long division. The binary array forms the dividend, * the length of the encoding is the divisor. Once computed, the quotient * forms the dividend for the next step. All remainders are stored for later * use. */ var full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2))); var remainders = Array(full_length); for(j = 0; j < full_length; j++) { quotient = Array(); x = 0; for(i = 0; i < dividend.length; i++) { x = (x << 16) + dividend[i]; q = Math.floor(x / divisor); x -= q * divisor; if(quotient.length > 0 || q > 0) quotient[quotient.length] = q; } remainders[j] = x; dividend = quotient; } /* Convert the remainders to the output string */ var output = ""; for(i = remainders.length - 1; i >= 0; i--) output += encoding.charAt(remainders[i]); return output; } /* * Encode a string as utf-8. * For efficiency, this assumes the input is valid utf-16. */ function str2rstr_utf8(input) { var output = ""; var i = -1; var x, y; while(++i < input.length) { /* Decode utf-16 surrogate pairs */ x = input.charCodeAt(i); y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) { x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); i++; } /* Encode output as utf-8 */ if(x <= 0x7F) output += String.fromCharCode(x); else if(x <= 0x7FF) output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), 0x80 | ( x & 0x3F)); else if(x <= 0xFFFF) output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); else if(x <= 0x1FFFFF) output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), 0x80 | ((x >>> 12) & 0x3F), 0x80 | ((x >>> 6 ) & 0x3F), 0x80 | ( x & 0x3F)); } return output; } /* * Encode a string as utf-16 */ function str2rstr_utf16le(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF); return output; } function str2rstr_utf16be(input) { var output = ""; for(var i = 0; i < input.length; i++) output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF); return output; } /* * Convert a raw string to an array of little-endian words * Characters >255 have their high-byte silently ignored. */ function rstr2binl(input) { var output = Array(input.length >> 2); for(var i = 0; i < output.length; i++) output[i] = 0; for(var i = 0; i < input.length * 8; i += 8) output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32); return output; } /* * Convert an array of little-endian words to a string */ function binl2rstr(input) { var output = ""; for(var i = 0; i < input.length * 32; i += 8) output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF); return output; } /* * Calculate the MD5 of an array of little-endian words, and a bit length. */ function binl_md5(x, len) { /* append padding */ x[len >> 5] |= 0x80 << ((len) % 32); x[(((len + 64) >>> 9) << 4) + 14] = len; var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; for(var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936); d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586); c = md5_ff(c, d, a, b, x[i+ 2], 17, 606105819); b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330); a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897); d = md5_ff(d, a, b, c, x[i+ 5], 12, 1200080426); c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341); b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983); a = md5_ff(a, b, c, d, x[i+ 8], 7 , 1770035416); d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417); c = md5_ff(c, d, a, b, x[i+10], 17, -42063); b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162); a = md5_ff(a, b, c, d, x[i+12], 7 , 1804603682); d = md5_ff(d, a, b, c, x[i+13], 12, -40341101); c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290); b = md5_ff(b, c, d, a, x[i+15], 22, 1236535329); a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510); d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632); c = md5_gg(c, d, a, b, x[i+11], 14, 643717713); b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302); a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691); d = md5_gg(d, a, b, c, x[i+10], 9 , 38016083); c = md5_gg(c, d, a, b, x[i+15], 14, -660478335); b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848); a = md5_gg(a, b, c, d, x[i+ 9], 5 , 568446438); d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690); c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961); b = md5_gg(b, c, d, a, x[i+ 8], 20, 1163531501); a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467); d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784); c = md5_gg(c, d, a, b, x[i+ 7], 14, 1735328473); b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734); a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558); d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463); c = md5_hh(c, d, a, b, x[i+11], 16, 1839030562); b = md5_hh(b, c, d, a, x[i+14], 23, -35309556); a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060); d = md5_hh(d, a, b, c, x[i+ 4], 11, 1272893353); c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632); b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640); a = md5_hh(a, b, c, d, x[i+13], 4 , 681279174); d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222); c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979); b = md5_hh(b, c, d, a, x[i+ 6], 23, 76029189); a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487); d = md5_hh(d, a, b, c, x[i+12], 11, -421815835); c = md5_hh(c, d, a, b, x[i+15], 16, 530742520); b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651); a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844); d = md5_ii(d, a, b, c, x[i+ 7], 10, 1126891415); c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905); b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055); a = md5_ii(a, b, c, d, x[i+12], 6 , 1700485571); d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606); c = md5_ii(c, d, a, b, x[i+10], 15, -1051523); b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799); a = md5_ii(a, b, c, d, x[i+ 8], 6 , 1873313359); d = md5_ii(d, a, b, c, x[i+15], 10, -30611744); c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380); b = md5_ii(b, c, d, a, x[i+13], 21, 1309151649); a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070); d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379); c = md5_ii(c, d, a, b, x[i+ 2], 15, 718787259); b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551); a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); } return Array(a, b, c, d); } /* * These functions implement the four basic operations the algorithm uses. */ function md5_cmn(q, a, b, x, s, t) { return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b); } function md5_ff(a, b, c, d, x, s, t) { return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t); } function md5_gg(a, b, c, d, x, s, t) { return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t); } function md5_hh(a, b, c, d, x, s, t) { return md5_cmn(b ^ c ^ d, a, b, x, s, t); } function md5_ii(a, b, c, d, x, s, t) { return md5_cmn(c ^ (b | (~d)), a, b, x, s, t); } /* * Add integers, wrapping at 2^32. This uses 16-bit operations internally * to work around bugs in some JS interpreters. */ function safe_add(x, y) { var lsw = (x & 0xFFFF) + (y & 0xFFFF); var msw = (x >> 16) + (y >> 16) + (lsw >> 16); return (msw << 16) | (lsw & 0xFFFF); } /* * Bitwise rotate a 32-bit number to the left. */ function bit_rol(num, cnt) { return (num << cnt) | (num >>> (32 - cnt)); } /* * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined * in FIPS 180-1 * Version 2.2 Copyright Paul Johnston 2000 - 2009. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for details. */ /* * Calculate the SHA1 of a raw string */ function rstr_sha1(s) { return binb2rstr(binb_sha1(rstr2binb(s), s.length * 8)); } /* * Calculate the HMAC-SHA1 of a key and some data (raw strings) */ function rstr_hmac_sha1(key, data) { var bkey = rstr2binb(key); if(bkey.length > 16) bkey = binb_sha1(bkey, key.length * 8); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = binb_sha1(ipad.concat(rstr2binb(data)), 512 + data.length * 8); return binb2rstr(binb_sha1(opad.concat(hash), 512 + 160)); } /* * Convert a raw string to an array of big-endian words * Characters >255 have their high-byte silently ignored. */ function rstr2binb(input) { var output = Array(input.length >> 2); for(var i = 0; i < output.length; i++) output[i] = 0; for(var i = 0; i < input.length * 8; i += 8) output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); return output; } /* * Convert an array of big-endian words to a string */ function binb2rstr(input) { var output = ""; for(var i = 0; i < input.length * 32; i += 8) output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF); return output; } /* * Calculate the SHA-1 of an array of big-endian words, and a bit length */ function binb_sha1(x, len) { /* append padding */ x[len >> 5] |= 0x80 << (24 - len % 32); x[((len + 64 >> 9) << 4) + 15] = len; var w = Array(80); var a = 1732584193; var b = -271733879; var c = -1732584194; var d = 271733878; var e = -1009589776; for(var i = 0; i < x.length; i += 16) { var olda = a; var oldb = b; var oldc = c; var oldd = d; var olde = e; for(var j = 0; j < 80; j++) { if(j < 16) w[j] = x[i + j]; else w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1); var t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)), safe_add(safe_add(e, w[j]), sha1_kt(j))); e = d; d = c; c = bit_rol(b, 30); b = a; a = t; } a = safe_add(a, olda); b = safe_add(b, oldb); c = safe_add(c, oldc); d = safe_add(d, oldd); e = safe_add(e, olde); } return Array(a, b, c, d, e); } /* * Perform the appropriate triplet combination function for the current * iteration */ function sha1_ft(t, b, c, d) { if(t < 20) return (b & c) | ((~b) & d); if(t < 40) return b ^ c ^ d; if(t < 60) return (b & c) | (b & d) | (c & d); return b ^ c ^ d; } /* * Determine the appropriate additive constant for the current iteration */ function sha1_kt(t) { return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 : (t < 60) ? -1894007588 : -899497514; } /* * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined * in FIPS 180-2 * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009. * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet * Distributed under the BSD License * See http://pajhome.org.uk/crypt/md5 for details. * Also http://anmar.eu.org/projects/jssha2/ */ /* * Calculate the sha256 of a raw string */ function rstr_sha256(s) { return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8)); } /* * Calculate the HMAC-sha256 of a key and some data (raw strings) */ function rstr_hmac_sha256(key, data) { var bkey = rstr2binb(key); if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8); var ipad = Array(16), opad = Array(16); for(var i = 0; i < 16; i++) { ipad[i] = bkey[i] ^ 0x36363636; opad[i] = bkey[i] ^ 0x5C5C5C5C; } var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8); return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256)); } /* * Main sha256 function, with its support functions */ function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));} function sha256_R (X, n) {return ( X >>> n );} function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));} function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));} function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));} function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));} function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));} function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));} function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));} function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));} function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));} function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));} var sha256_K = new Array ( 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998 ); function binb_sha256(m, l) { var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534, 1359893119, -1694144372, 528734635, 1541459225); var W = new Array(64); var a, b, c, d, e, f, g, h; var i, j, T1, T2; /* append padding */ m[l >> 5] |= 0x80 << (24 - l % 32); m[((l + 64 >> 9) << 4) + 15] = l; for(i = 0; i < m.length; i += 16) { a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7]; for(j = 0; j < 64; j++) { if (j < 16) W[j] = m[j + i]; else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), sha256_Gamma0256(W[j - 15])), W[j - 16]); T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), sha256_K[j]), W[j]); T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c)); h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2); } HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]); } return HASH; } }()); ; ; var lastCSS = ""; var importList = []; function importcssfile(filename){ if (importList.indexOf(filename)==-1){ //Only imports if file of same name not already imported var fileref=document.createElement("link") fileref.setAttribute("rel", "stylesheet") fileref.setAttribute("type", "text/css") fileref.setAttribute("href", filename) document.getElementsByTagName("head")[0].appendChild(fileref) importList.push(filename) } }; if(!Array.prototype.indexOf) { Array.prototype.indexOf = function(what, i) { i = i || 0; var L = this.length; while (i < L) { if(this[i] === what) return i; ++i; } return -1; }; }; function removecssfile(filename){ var removeList=document.getElementsByTagName("link") for (var i=removeList.length; i>=0; i--){ //search backwards within nodelist for matching elements to remove if (removeList[i] && removeList[i].getAttribute("href")!=null && removeList[i].getAttribute("href").indexOf(filename)!=-1) removeList[i].parentNode.removeChild(removeList[i]) //remove element by calling parentNode.removeChild() } importList.splice(importList.indexOf(filename), 1); }; cr.plugins_.CSS_import = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.CSS_import.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { if (this.properties[0] != ""){ importcssfile(this.properties[0]); lastCSS = this.properties[0]; } }; instanceProto.onDestroy = function () { }; instanceProto.draw = function(ctx) { }; instanceProto.drawGL = function(glw) { }; pluginProto.cnds = {}; var cnds = pluginProto.cnds; cnds.CompareCSS = function (text, case_) { return this.properties[0] === text; }; pluginProto.acts = {}; var acts = pluginProto.acts; acts.SetCSS = function (setName) { importcssfile(setName); lastCSS = setName; }; acts.RemCSS = function (remName) { removecssfile(remName); }; pluginProto.exps = {}; var exps = pluginProto.exps; exps.GetCSS = function (ret) { if (lastCSS != ""){ ret.set_string(lastCSS); } else if (this.properties[0] != ""){ ret.set_string(this.properties[0]); } else { ret.set_string(""); } }; }()); ; ; cr.plugins_.Function = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Function.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; var funcStack = []; var funcStackPtr = -1; var isInPreview = false; // set in onCreate function FuncStackEntry() { this.name = ""; this.retVal = 0; this.params = []; }; function pushFuncStack() { funcStackPtr++; if (funcStackPtr === funcStack.length) funcStack.push(new FuncStackEntry()); return funcStack[funcStackPtr]; }; function getCurrentFuncStack() { if (funcStackPtr < 0) return null; return funcStack[funcStackPtr]; }; function getOneAboveFuncStack() { if (!funcStack.length) return null; var i = funcStackPtr + 1; if (i >= funcStack.length) i = funcStack.length - 1; return funcStack[i]; }; function popFuncStack() { ; funcStackPtr--; }; instanceProto.onCreate = function() { isInPreview = (typeof cr_is_preview !== "undefined"); var self = this; window["c2_callFunction"] = function (name_, params_) { var i, len, v; var fs = pushFuncStack(); fs.name = name_.toLowerCase(); fs.retVal = 0; if (params_) { fs.params.length = params_.length; for (i = 0, len = params_.length; i < len; ++i) { v = params_[i]; if (typeof v === "number" || typeof v === "string") fs.params[i] = v; else if (typeof v === "boolean") fs.params[i] = (v ? 1 : 0); else fs.params[i] = 0; } } else { cr.clearArray(fs.params); } self.runtime.trigger(cr.plugins_.Function.prototype.cnds.OnFunction, self, fs.name); popFuncStack(); return fs.retVal; }; }; function Cnds() {}; Cnds.prototype.OnFunction = function (name_) { var fs = getCurrentFuncStack(); if (!fs) return false; return cr.equals_nocase(name_, fs.name); }; Cnds.prototype.CompareParam = function (index_, cmp_, value_) { var fs = getCurrentFuncStack(); if (!fs) return false; index_ = cr.floor(index_); if (index_ < 0 || index_ >= fs.params.length) return false; return cr.do_cmp(fs.params[index_], cmp_, value_); }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.CallFunction = function (name_, params_) { var fs = pushFuncStack(); fs.name = name_.toLowerCase(); fs.retVal = 0; cr.shallowAssignArray(fs.params, params_); var ran = this.runtime.trigger(cr.plugins_.Function.prototype.cnds.OnFunction, this, fs.name); if (isInPreview && !ran) { ; } popFuncStack(); }; Acts.prototype.SetReturnValue = function (value_) { var fs = getCurrentFuncStack(); if (fs) fs.retVal = value_; else ; }; Acts.prototype.CallExpression = function (unused) { }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.ReturnValue = function (ret) { var fs = getOneAboveFuncStack(); if (fs) ret.set_any(fs.retVal); else ret.set_int(0); }; Exps.prototype.ParamCount = function (ret) { var fs = getCurrentFuncStack(); if (fs) ret.set_int(fs.params.length); else { ; ret.set_int(0); } }; Exps.prototype.Param = function (ret, index_) { index_ = cr.floor(index_); var fs = getCurrentFuncStack(); if (fs) { if (index_ >= 0 && index_ < fs.params.length) { ret.set_any(fs.params[index_]); } else { ; ret.set_int(0); } } else { ; ret.set_int(0); } }; Exps.prototype.Call = function (ret, name_) { var fs = pushFuncStack(); fs.name = name_.toLowerCase(); fs.retVal = 0; cr.clearArray(fs.params); var i, len; for (i = 2, len = arguments.length; i < len; i++) fs.params.push(arguments[i]); var ran = this.runtime.trigger(cr.plugins_.Function.prototype.cnds.OnFunction, this, fs.name); if (isInPreview && !ran) { ; } popFuncStack(); ret.set_any(fs.retVal); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.GameAnalytics = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.GameAnalytics.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.build = this.properties[0]; this.customUserId = this.properties[1]; this.enableManualSessionHandling = this.properties[2]; this.enableInfoLog = this.properties[3]; this.enableVerboseLog = this.properties[4]; this.autoDetectAppVersion = this.properties[5]; this.gameKeyBrowser = this.properties[6]; this.secretKeyBrowser = this.properties[7]; this.gameKeyAndroid = this.properties[8]; this.secretKeyAndroid = this.properties[9]; this.gameKeyIOS = this.properties[10]; this.secretKeyIOS = this.properties[11]; this.customDimensions01 = []; this.customDimensions02 = []; this.customDimensions03 = []; this.resourceCurrencies = []; this.resourceItemTypes = []; }; instanceProto.onDestroy = function () { }; instanceProto.saveToJSON = function () { return { }; }; instanceProto.loadFromJSON = function (o) { }; instanceProto.draw = function(ctx) { }; instanceProto.drawGL = function (glw) { }; function Cnds() {}; Cnds.prototype.isRemoteConfigsReady = function (functionName) { if(typeof window["GameAnalytics"]["isRemoteConfigsReady"] == "function") { var callback = function(result) { if(functionName && window["c2_callFunction"]) { window["c2_callFunction"](functionName, [result ? 1 : 0]); } } window["GameAnalytics"]["isRemoteConfigsReady"](callback); return false; } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { return window["gameanalytics"]["GameAnalytics"]["isRemoteConfigsReady"](); } else { console.log("isRemoteConfigsReady: GameAnalytics object not found"); return false; } }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.addAvailableCustomDimension01 = function (dimension) { this.customDimensions01.push(dimension); }; Acts.prototype.addAvailableCustomDimension02 = function (dimension) { this.customDimensions02.push(dimension); }; Acts.prototype.addAvailableCustomDimension03 = function (dimension) { this.customDimensions03.push(dimension); }; Acts.prototype.addAvailableResourceCurrency = function (currency) { this.resourceCurrencies.push(currency); }; Acts.prototype.addAvailableResourceItemType = function (itemType) { this.resourceItemTypes.push(itemType); }; Acts.prototype.initialize = function () { var VERSION = "3.0.14"; if(typeof window["GameAnalytics"]["initialize"] == "function") { var ga = window["GameAnalytics"]; if(this.enableInfoLog) { ga["setEnabledInfoLog"](true); } if(this.enableVerboseLog) { ga["setEnabledVerboseLog"](true); } if(this.enableManualSessionHandling) { ga["setEnabledManualSessionHandling"](true); } if(this.customDimensions01.length > 0) { ga["configureAvailableCustomDimensions01"](this.customDimensions01); } if(this.customDimensions02.length > 0) { ga["configureAvailableCustomDimensions02"](this.customDimensions02); } if(this.customDimensions03.length > 0) { ga["configureAvailableCustomDimensions03"](this.customDimensions03); } if(this.resourceCurrencies.length > 0) { ga["configureAvailableResourceCurrencies"](this.resourceCurrencies); } if(this.resourceItemTypes.length > 0) { ga["configureAvailableResourceItemTypes"](this.resourceItemTypes); } ga["configureBuild"](this.build); if(this.autoDetectAppVersion) { ga["configureAutoDetectAppVersion"](true); } var sdkVersion = "construct " + VERSION; var gameKey = window["device"]["platform"] === "Android" ? this.gameKeyAndroid : this.gameKeyIOS; var secretKey = window["device"]["platform"] === "Android" ? this.secretKeyAndroid : this.secretKeyIOS; ga["initialize"]({ "gameKey": gameKey, "secretKey": secretKey, "sdkVersion": sdkVersion }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { var ga = window["gameanalytics"]["GameAnalytics"]; if(this.enableInfoLog) { ga["setEnabledInfoLog"](true); } if(this.enableVerboseLog) { ga["setEnabledVerboseLog"](true); } if(this.enableManualSessionHandling) { ga["setEnabledManualSessionHandling"](true); } if(this.customDimensions01.length > 0) { ga["configureAvailableCustomDimensions01"](this.customDimensions01); } if(this.customDimensions02.length > 0) { ga["configureAvailableCustomDimensions02"](this.customDimensions02); } if(this.customDimensions03.length > 0) { ga["configureAvailableCustomDimensions03"](this.customDimensions03); } if(this.resourceCurrencies.length > 0) { ga["configureAvailableResourceCurrencies"](this.resourceCurrencies); } if(this.resourceItemTypes.length > 0) { ga["configureAvailableResourceItemTypes"](this.resourceItemTypes); } ga["configureBuild"](this.build); ga["configureSdkGameEngineVersion"]("construct " + VERSION); ga["initialize"](this.gameKeyBrowser, this.secretKeyBrowser); } else { console.log("initialize: GameAnalytics object not found"); return; } }; Acts.prototype.addBusinessEvent = function (currency, amount, itemType, itemId, cartType) { if(typeof window["GameAnalytics"]["addBusinessEvent"] == "function") { window["GameAnalytics"]["addBusinessEvent"]({ "currency": currency, "amount": amount, "itemType": itemType, "itemId": itemId, "cartType": cartType }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["addBusinessEvent"](currency, amount, itemType, itemId, cartType); } else { console.log("addBusinessEvent: GameAnalytics object not found"); return; } }; Acts.prototype.addResourceEvent = function (flowType, currency, amount, itemType, itemId) { if(typeof window["GameAnalytics"]["addResourceEvent"] == "function") { window["GameAnalytics"]["addResourceEvent"]({ "flowType": flowType, "currency": currency, "amount": amount, "itemType": itemType, "itemId": itemId }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["addResourceEvent"](flowType, currency, amount, itemType, itemId); } else { console.log("addResourceEvent: GameAnalytics object not found"); return; } }; Acts.prototype.addProgressionEvent = function (progressionStatus, progression01, progression02, progression03) { if(typeof window["GameAnalytics"]["addProgressionEvent"] == "function") { window["GameAnalytics"]["addProgressionEvent"]({ "progressionStatus": progressionStatus, "progression01": progression01, "progression02": progression02, "progression03": progression03 }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["addProgressionEvent"](progressionStatus, progression01, progression02, progression03); } else { console.log("addProgressionEvent: GameAnalytics object not found"); return; } }; Acts.prototype.addProgressionEventWithScore = function (progressionStatus, progression01, progression02, progression03, score) { if(typeof window["GameAnalytics"]["addProgressionEvent"] == "function") { window["GameAnalytics"]["addProgressionEvent"]({ "progressionStatus": progressionStatus, "progression01": progression01, "progression02": progression02, "progression03": progression03, "score": score }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["addProgressionEvent"](progressionStatus, progression01, progression02, progression03, score); } else { console.log("addProgressionEventWithScore: GameAnalytics object not found"); return; } }; Acts.prototype.addDesignEvent = function (eventId) { if(typeof window["GameAnalytics"]["addDesignEvent"] == "function") { window["GameAnalytics"]["addDesignEvent"]({ "eventId": eventId }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["addDesignEvent"](eventId); } else { console.log("addDesignEvent: GameAnalytics object not found"); return; } }; Acts.prototype.addDesignEventWithValue = function (eventId, value) { if(typeof window["GameAnalytics"]["addDesignEvent"] == "function") { window["GameAnalytics"]["addDesignEvent"]({ "eventId": eventId, "value": value }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["addDesignEvent"](eventId, value); } else { console.log("addDesignEventWithValue: GameAnalytics object not found"); return; } }; Acts.prototype.addErrorEvent = function (severity, message) { if(typeof window["GameAnalytics"]["addErrorEvent"] == "function") { window["GameAnalytics"]["addErrorEvent"]({ "severity": severity, "message": message }); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["addErrorEvent"](severity, message); } else { console.log("addErrorEvent: GameAnalytics object not found"); return; } }; Acts.prototype.setEnabledEventSubmission = function (flag) { if(typeof window["GameAnalytics"]["setEnabledEventSubmission"] == "function") { window["GameAnalytics"]["setEnabledEventSubmission"](flag ? true : false); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["setEnabledEventSubmission"](flag ? true : false); } else { console.log("setEnabledEventSubmission: GameAnalytics object not found"); return; } }; Acts.prototype.setEnabledManualSessionHandling = function (flag) { if(typeof window["GameAnalytics"]["setEnabledManualSessionHandling"] == "function") { window["GameAnalytics"]["setEnabledManualSessionHandling"](flag ? true : false); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["setEnabledManualSessionHandling"](flag ? true : false); } else { console.log("setEnabledManualSessionHandling: GameAnalytics object not found"); return; } }; Acts.prototype.setCustomDimension01 = function (dimension) { if(typeof window["GameAnalytics"]["setCustomDimension01"] == "function") { window["GameAnalytics"]["setCustomDimension01"](dimension); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["setCustomDimension01"](dimension); } else { console.log("setCustomDimension01: GameAnalytics object not found"); return; } }; Acts.prototype.setCustomDimension02 = function (dimension) { if(typeof window["GameAnalytics"]["setCustomDimension02"] == "function") { window["GameAnalytics"]["setCustomDimension02"](dimension); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["setCustomDimension02"](dimension); } else { console.log("setCustomDimension02: GameAnalytics object not found"); return; } }; Acts.prototype.setCustomDimension03 = function (dimension) { if(typeof window["GameAnalytics"]["setCustomDimension03"] == "function") { window["GameAnalytics"]["setCustomDimension03"](dimension); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["setCustomDimension03"](dimension); } else { console.log("setCustomDimension03: GameAnalytics object not found"); return; } }; Acts.prototype.startSession = function () { if(typeof window["GameAnalytics"]["startSession"] == "function") { window["GameAnalytics"]["startSession"](); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["startSession"](); } else { console.log("startSession: GameAnalytics object not found"); return; } }; Acts.prototype.endSession = function () { if(typeof window["GameAnalytics"]["endSession"] == "function") { window["GameAnalytics"]["endSession"](); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { window["gameanalytics"]["GameAnalytics"]["endSession"](); } else { console.log("endSession: GameAnalytics object not found"); return; } }; Acts.prototype.configureBuild = function (buildNumber) { this.build = buildNumber; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.getRemoteConfigsValueAsString = function (ret, key, defaultValue, functionName) { if(typeof window["GameAnalytics"]["getRemoteConfigsValueAsString"] == "function") { var callback = function(result) { if(functionName && window["c2_callFunction"]) { window["c2_callFunction"](functionName, [result]); } } window["GameAnalytics"]["getRemoteConfigsValueAsString"]({ "key": key, "defaultValue": defaultValue }, ); ret.set_string(""); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { ret.set_string(window["gameanalytics"]["GameAnalytics"]["getRemoteConfigsValueAsString"](key, defaultValue)); } else { console.log("getRemoteConfigsValueAsString: GameAnalytics object not found"); ret.set_string(""); } }; Exps.prototype.getRemoteConfigsContentAsString = function (ret, functionName) { if(typeof window["GameAnalytics"]["getRemoteConfigsContentAsString"] == "function") { var callback = function(result) { if(functionName && window["c2_callFunction"]) { window["c2_callFunction"](functionName, [result]); } } window["GameAnalytics"]["getRemoteConfigsContentAsString"](callback); ret.set_string(""); } else if(typeof window["gameanalytics"]["GameAnalytics"] != "undefined") { ret.set_string(window["gameanalytics"]["GameAnalytics"]["getRemoteConfigsContentAsString"]()); } else { console.log("endSession: GameAnalytics object not found"); ret.set_string(""); } }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Globals = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Globals.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.defaultVarsValues = JSON.stringify(this.instance_vars); }; instanceProto.saveToJSON = function () { return { "v": JSON.stringify(this.instance_vars) }; }; instanceProto.loadFromJSON = function (o) { this.instance_vars = JSON.parse(o["v"]); }; function Cnds() {}; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.ResetVariables = function() { this.instance_vars = JSON.parse(this.defaultVarsValues); }; Acts.prototype.LoadVariables = function(varsJSON_) { this.instance_vars = JSON.parse(varsJSON_); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.GetVariablesAsJSON = function(ret) { ret.set_string(JSON.stringify(this.instance_vars)); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Keyboard = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Keyboard.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; this.keyMap = new Array(256); // stores key up/down state this.usedKeys = new Array(256); this.triggerKey = 0; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { var self = this; if (!this.runtime.isDomFree) { jQuery(document).keydown( function(info) { self.onKeyDown(info); } ); jQuery(document).keyup( function(info) { self.onKeyUp(info); } ); } }; var keysToBlockWhenFramed = [32, 33, 34, 35, 36, 37, 38, 39, 40, 44]; instanceProto.onKeyDown = function (info) { var alreadyPreventedDefault = false; if (window != window.top && keysToBlockWhenFramed.indexOf(info.which) > -1) { info.preventDefault(); alreadyPreventedDefault = true; info.stopPropagation(); } if (this.keyMap[info.which]) { if (this.usedKeys[info.which] && !alreadyPreventedDefault) info.preventDefault(); return; } this.keyMap[info.which] = true; this.triggerKey = info.which; this.runtime.isInUserInputEvent = true; this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnAnyKey, this); var eventRan = this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnKey, this); var eventRan2 = this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnKeyCode, this); this.runtime.isInUserInputEvent = false; if (eventRan || eventRan2) { this.usedKeys[info.which] = true; if (!alreadyPreventedDefault) info.preventDefault(); } }; instanceProto.onKeyUp = function (info) { this.keyMap[info.which] = false; this.triggerKey = info.which; this.runtime.isInUserInputEvent = true; this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnAnyKeyReleased, this); var eventRan = this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnKeyReleased, this); var eventRan2 = this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnKeyCodeReleased, this); this.runtime.isInUserInputEvent = false; if (eventRan || eventRan2 || this.usedKeys[info.which]) { this.usedKeys[info.which] = true; info.preventDefault(); } }; instanceProto.onWindowBlur = function () { var i; for (i = 0; i < 256; ++i) { if (!this.keyMap[i]) continue; // key already up this.keyMap[i] = false; this.triggerKey = i; this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnAnyKeyReleased, this); var eventRan = this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnKeyReleased, this); var eventRan2 = this.runtime.trigger(cr.plugins_.Keyboard.prototype.cnds.OnKeyCodeReleased, this); if (eventRan || eventRan2) this.usedKeys[i] = true; } }; instanceProto.saveToJSON = function () { return { "triggerKey": this.triggerKey }; }; instanceProto.loadFromJSON = function (o) { this.triggerKey = o["triggerKey"]; }; function Cnds() {}; Cnds.prototype.IsKeyDown = function(key) { return this.keyMap[key]; }; Cnds.prototype.OnKey = function(key) { return (key === this.triggerKey); }; Cnds.prototype.OnAnyKey = function(key) { return true; }; Cnds.prototype.OnAnyKeyReleased = function(key) { return true; }; Cnds.prototype.OnKeyReleased = function(key) { return (key === this.triggerKey); }; Cnds.prototype.IsKeyCodeDown = function(key) { key = Math.floor(key); if (key < 0 || key >= this.keyMap.length) return false; return this.keyMap[key]; }; Cnds.prototype.OnKeyCode = function(key) { return (key === this.triggerKey); }; Cnds.prototype.OnKeyCodeReleased = function(key) { return (key === this.triggerKey); }; pluginProto.cnds = new Cnds(); function Acts() {}; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.LastKeyCode = function (ret) { ret.set_int(this.triggerKey); }; function fixedStringFromCharCode(kc) { kc = Math.floor(kc); switch (kc) { case 8: return "backspace"; case 9: return "tab"; case 13: return "enter"; case 16: return "shift"; case 17: return "control"; case 18: return "alt"; case 19: return "pause"; case 20: return "capslock"; case 27: return "esc"; case 33: return "pageup"; case 34: return "pagedown"; case 35: return "end"; case 36: return "home"; case 37: return "โ†"; case 38: return "โ†‘"; case 39: return "โ†’"; case 40: return "โ†“"; case 45: return "insert"; case 46: return "del"; case 91: return "left window key"; case 92: return "right window key"; case 93: return "select"; case 96: return "numpad 0"; case 97: return "numpad 1"; case 98: return "numpad 2"; case 99: return "numpad 3"; case 100: return "numpad 4"; case 101: return "numpad 5"; case 102: return "numpad 6"; case 103: return "numpad 7"; case 104: return "numpad 8"; case 105: return "numpad 9"; case 106: return "numpad *"; case 107: return "numpad +"; case 109: return "numpad -"; case 110: return "numpad ."; case 111: return "numpad /"; case 112: return "F1"; case 113: return "F2"; case 114: return "F3"; case 115: return "F4"; case 116: return "F5"; case 117: return "F6"; case 118: return "F7"; case 119: return "F8"; case 120: return "F9"; case 121: return "F10"; case 122: return "F11"; case 123: return "F12"; case 144: return "numlock"; case 145: return "scroll lock"; case 186: return ";"; case 187: return "="; case 188: return ","; case 189: return "-"; case 190: return "."; case 191: return "/"; case 192: return "'"; case 219: return "["; case 220: return "\\"; case 221: return "]"; case 222: return "#"; case 223: return "`"; default: return String.fromCharCode(kc); } }; Exps.prototype.StringFromKeyCode = function (ret, kc) { ret.set_string(fixedStringFromCharCode(kc)); }; pluginProto.exps = new Exps(); }()); ; ; var localForageInitFailed = false; try { /*! localForage -- Offline Storage, Improved Version 1.4.0 https://mozilla.github.io/localForage (c) 2013-2015 Mozilla, Apache License 2.0 */ !function(){var a,b,c,d;!function(){var e={},f={};a=function(a,b,c){e[a]={deps:b,callback:c}},d=c=b=function(a){function c(b){if("."!==b.charAt(0))return b;for(var c=b.split("/"),d=a.split("/").slice(0,-1),e=0,f=c.length;f>e;e++){var g=c[e];if(".."===g)d.pop();else{if("."===g)continue;d.push(g)}}return d.join("/")}if(d._eak_seen=e,f[a])return f[a];if(f[a]={},!e[a])throw new Error("Could not find module "+a);for(var g,h=e[a],i=h.deps,j=h.callback,k=[],l=0,m=i.length;m>l;l++)"exports"===i[l]?k.push(g={}):k.push(b(c(i[l])));var n=j.apply(this,k);return f[a]=g||n}}(),a("promise/all",["./utils","exports"],function(a,b){"use strict";function c(a){var b=this;if(!d(a))throw new TypeError("You must pass an array to all.");return new b(function(b,c){function d(a){return function(b){f(a,b)}}function f(a,c){h[a]=c,0===--i&&b(h)}var g,h=[],i=a.length;0===i&&b([]);for(var j=0;jc;c++){var e=a[c];this.supports(e)&&b.push(e)}return b},a.prototype._wrapLibraryMethodsWithReady=function(){for(var a=0;ae;e++)d[e]=a.charCodeAt(e);return c}function d(a){return new Promise(function(b,c){var d=new XMLHttpRequest;d.open("GET",a),d.withCredentials=!0,d.responseType="arraybuffer",d.onreadystatechange=function(){return 4===d.readyState?200===d.status?b({response:d.response,type:d.getResponseHeader("Content-Type")}):void c({status:d.status,response:d.response}):void 0},d.send()})}function e(a){return new Promise(function(c,e){var f=b([""],{type:"image/png"}),g=a.transaction([D],"readwrite");g.objectStore(D).put(f,"key"),g.oncomplete=function(){var b=a.transaction([D],"readwrite"),f=b.objectStore(D).get("key");f.onerror=e,f.onsuccess=function(a){var b=a.target.result,e=URL.createObjectURL(b);d(e).then(function(a){c(!(!a||"image/png"!==a.type))},function(){c(!1)}).then(function(){URL.revokeObjectURL(e)})}},g.onerror=g.onabort=e})["catch"](function(){return!1})}function f(a){return"boolean"==typeof B?Promise.resolve(B):e(a).then(function(a){return B=a})}function g(a){return new Promise(function(b,c){var d=new FileReader;d.onerror=c,d.onloadend=function(c){var d=btoa(c.target.result||"");b({__local_forage_encoded_blob:!0,data:d,type:a.type})},d.readAsBinaryString(a)})}function h(a){var d=c(atob(a.data));return b([d],{type:a.type})}function i(a){return a&&a.__local_forage_encoded_blob}function j(a){var b=this,c=b._initReady().then(function(){var a=C[b._dbInfo.name];return a&&a.dbReady?a.dbReady:void 0});return c.then(a,a),c}function k(a){var b=C[a.name],c={};c.promise=new Promise(function(a){c.resolve=a}),b.deferredOperations.push(c),b.dbReady?b.dbReady=b.dbReady.then(function(){return c.promise}):b.dbReady=c.promise}function l(a){var b=C[a.name],c=b.deferredOperations.pop();c&&c.resolve()}function m(a){function b(){return Promise.resolve()}var c=this,d={db:null};if(a)for(var e in a)d[e]=a[e];C||(C={});var f=C[d.name];f||(f={forages:[],db:null,dbReady:null,deferredOperations:[]},C[d.name]=f),f.forages.push(c),c._initReady||(c._initReady=c.ready,c.ready=j);for(var g=[],h=0;hb.db.version;if(e&&(b.version!==c&&a.console.warn('The database "'+b.name+"\" can't be downgraded from version "+b.db.version+" to version "+b.version+"."),b.version=b.db.version),f||d){if(d){var g=b.db.version+1;g>b.version&&(b.version=g)}return!0}return!1}function r(b,c){var d=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var e=new Promise(function(a,c){d.ready().then(function(){var e=d._dbInfo,f=e.db.transaction(e.storeName,"readonly").objectStore(e.storeName),g=f.get(b);g.onsuccess=function(){var b=g.result;void 0===b&&(b=null),i(b)&&(b=h(b)),a(b)},g.onerror=function(){c(g.error)}})["catch"](c)});return z(e,c),e}function s(a,b){var c=this,d=new Promise(function(b,d){c.ready().then(function(){var e=c._dbInfo,f=e.db.transaction(e.storeName,"readonly").objectStore(e.storeName),g=f.openCursor(),j=1;g.onsuccess=function(){var c=g.result;if(c){var d=c.value;i(d)&&(d=h(d));var e=a(d,c.key,j++);void 0!==e?b(e):c["continue"]()}else b()},g.onerror=function(){d(g.error)}})["catch"](d)});return z(d,b),d}function t(b,c,d){var e=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var h=new Promise(function(a,d){var h;e.ready().then(function(){return h=e._dbInfo,c instanceof Blob?f(h.db).then(function(a){return a?c:g(c)}):c}).then(function(c){var e=h.db.transaction(h.storeName,"readwrite"),f=e.objectStore(h.storeName);null===c&&(c=void 0),e.oncomplete=function(){void 0===c&&(c=null),a(c)},e.onabort=e.onerror=function(){var a=g.error?g.error:g.transaction.error;d(a)};var g=f.put(c,b)})["catch"](d)});return z(h,d),h}function u(b,c){var d=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var e=new Promise(function(a,c){d.ready().then(function(){var e=d._dbInfo,f=e.db.transaction(e.storeName,"readwrite"),g=f.objectStore(e.storeName),h=g["delete"](b);f.oncomplete=function(){a()},f.onerror=function(){c(h.error)},f.onabort=function(){var a=h.error?h.error:h.transaction.error;c(a)}})["catch"](c)});return z(e,c),e}function v(a){var b=this,c=new Promise(function(a,c){b.ready().then(function(){var d=b._dbInfo,e=d.db.transaction(d.storeName,"readwrite"),f=e.objectStore(d.storeName),g=f.clear();e.oncomplete=function(){a()},e.onabort=e.onerror=function(){var a=g.error?g.error:g.transaction.error;c(a)}})["catch"](c)});return z(c,a),c}function w(a){var b=this,c=new Promise(function(a,c){b.ready().then(function(){var d=b._dbInfo,e=d.db.transaction(d.storeName,"readonly").objectStore(d.storeName),f=e.count();f.onsuccess=function(){a(f.result)},f.onerror=function(){c(f.error)}})["catch"](c)});return z(c,a),c}function x(a,b){var c=this,d=new Promise(function(b,d){return 0>a?void b(null):void c.ready().then(function(){var e=c._dbInfo,f=e.db.transaction(e.storeName,"readonly").objectStore(e.storeName),g=!1,h=f.openCursor();h.onsuccess=function(){var c=h.result;return c?void(0===a?b(c.key):g?b(c.key):(g=!0,c.advance(a))):void b(null)},h.onerror=function(){d(h.error)}})["catch"](d)});return z(d,b),d}function y(a){var b=this,c=new Promise(function(a,c){b.ready().then(function(){var d=b._dbInfo,e=d.db.transaction(d.storeName,"readonly").objectStore(d.storeName),f=e.openCursor(),g=[];f.onsuccess=function(){var b=f.result;return b?(g.push(b.key),void b["continue"]()):void a(g)},f.onerror=function(){c(f.error)}})["catch"](c)});return z(c,a),c}function z(a,b){b&&a.then(function(a){b(null,a)},function(a){b(a)})}var A=A||a.indexedDB||a.webkitIndexedDB||a.mozIndexedDB||a.OIndexedDB||a.msIndexedDB;if(A){var B,C,D="local-forage-detect-blob-support",E={_driver:"asyncStorage",_initStorage:m,iterate:s,getItem:r,setItem:t,removeItem:u,clear:v,length:w,key:x,keys:y};return E}}("undefined"!=typeof window?window:self);b["default"]=c,a.exports=b["default"]},function(a,b,c){"use strict";b.__esModule=!0;var d=function(a){function b(a){var b=this,d={};if(a)for(var e in a)d[e]=a[e];return d.keyPrefix=d.name+"/",d.storeName!==b._defaultConfig.storeName&&(d.keyPrefix+=d.storeName+"/"),b._dbInfo=d,new Promise(function(a,b){a(c(3))}).then(function(a){return d.serializer=a,Promise.resolve()})}function d(a){var b=this,c=b.ready().then(function(){for(var a=b._dbInfo.keyPrefix,c=m.length-1;c>=0;c--){var d=m.key(c);0===d.indexOf(a)&&m.removeItem(d)}});return l(c,a),c}function e(b,c){var d=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var e=d.ready().then(function(){var a=d._dbInfo,c=m.getItem(a.keyPrefix+b);return c&&(c=a.serializer.deserialize(c)),c});return l(e,c),e}function f(a,b){var c=this,d=c.ready().then(function(){for(var b=c._dbInfo,d=b.keyPrefix,e=d.length,f=m.length,g=1,h=0;f>h;h++){var i=m.key(h);if(0===i.indexOf(d)){var j=m.getItem(i);if(j&&(j=b.serializer.deserialize(j)),j=a(j,i.substring(e),g++),void 0!==j)return j}}});return l(d,b),d}function g(a,b){var c=this,d=c.ready().then(function(){var b,d=c._dbInfo;try{b=m.key(a)}catch(e){b=null}return b&&(b=b.substring(d.keyPrefix.length)),b});return l(d,b),d}function h(a){var b=this,c=b.ready().then(function(){for(var a=b._dbInfo,c=m.length,d=[],e=0;c>e;e++)0===m.key(e).indexOf(a.keyPrefix)&&d.push(m.key(e).substring(a.keyPrefix.length));return d});return l(c,a),c}function i(a){var b=this,c=b.keys().then(function(a){return a.length});return l(c,a),c}function j(b,c){var d=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var e=d.ready().then(function(){var a=d._dbInfo;m.removeItem(a.keyPrefix+b)});return l(e,c),e}function k(b,c,d){var e=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var f=e.ready().then(function(){void 0===c&&(c=null);var a=c;return new Promise(function(d,f){var g=e._dbInfo;g.serializer.serialize(c,function(c,e){if(e)f(e);else try{m.setItem(g.keyPrefix+b,c),d(a)}catch(h){("QuotaExceededError"===h.name||"NS_ERROR_DOM_QUOTA_REACHED"===h.name)&&f(h),f(h)}})})});return l(f,d),f}function l(a,b){b&&a.then(function(a){b(null,a)},function(a){b(a)})}var m=null;try{if(!(a.localStorage&&"setItem"in a.localStorage))return;m=a.localStorage}catch(n){return}var o={_driver:"localStorageWrapper",_initStorage:b,iterate:f,getItem:e,setItem:k,removeItem:j,clear:d,length:i,key:g,keys:h};return o}("undefined"!=typeof window?window:self);b["default"]=d,a.exports=b["default"]},function(a,b){"use strict";b.__esModule=!0;var c=function(a){function b(b,c){b=b||[],c=c||{};try{return new Blob(b,c)}catch(d){if("TypeError"!==d.name)throw d;for(var e=a.BlobBuilder||a.MSBlobBuilder||a.MozBlobBuilder||a.WebKitBlobBuilder,f=new e,g=0;gb;b+=4)c=g.indexOf(a[b]),d=g.indexOf(a[b+1]),e=g.indexOf(a[b+2]),f=g.indexOf(a[b+3]),l[j++]=c<<2|d>>4,l[j++]=(15&d)<<4|e>>2,l[j++]=(3&e)<<6|63&f;return k}function f(a){var b,c=new Uint8Array(a),d="";for(b=0;b>2],d+=g[(3&c[b])<<4|c[b+1]>>4],d+=g[(15&c[b+1])<<2|c[b+2]>>6],d+=g[63&c[b+2]];return c.length%3===2?d=d.substring(0,d.length-1)+"=":c.length%3===1&&(d=d.substring(0,d.length-2)+"=="),d}var g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",h="~~local_forage_type~",i=/^~~local_forage_type~([^~]+)~/,j="__lfsc__:",k=j.length,l="arbf",m="blob",n="si08",o="ui08",p="uic8",q="si16",r="si32",s="ur16",t="ui32",u="fl32",v="fl64",w=k+l.length,x={serialize:c,deserialize:d,stringToBuffer:e,bufferToString:f};return x}("undefined"!=typeof window?window:self);b["default"]=c,a.exports=b["default"]},function(a,b,c){"use strict";b.__esModule=!0;var d=function(a){function b(a){var b=this,d={db:null};if(a)for(var e in a)d[e]="string"!=typeof a[e]?a[e].toString():a[e];var f=new Promise(function(a,c){try{d.db=m(d.name,String(d.version),d.description,d.size)}catch(e){return c(e)}d.db.transaction(function(e){e.executeSql("CREATE TABLE IF NOT EXISTS "+d.storeName+" (id INTEGER PRIMARY KEY, key unique, value)",[],function(){b._dbInfo=d,a()},function(a,b){c(b)})})});return new Promise(function(a,b){a(c(3))}).then(function(a){return d.serializer=a,f})}function d(b,c){var d=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var e=new Promise(function(a,c){d.ready().then(function(){var e=d._dbInfo;e.db.transaction(function(d){d.executeSql("SELECT * FROM "+e.storeName+" WHERE key = ? LIMIT 1",[b],function(b,c){var d=c.rows.length?c.rows.item(0).value:null;d&&(d=e.serializer.deserialize(d)),a(d)},function(a,b){c(b)})})})["catch"](c)});return l(e,c),e}function e(a,b){var c=this,d=new Promise(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT * FROM "+e.storeName,[],function(c,d){for(var f=d.rows,g=f.length,h=0;g>h;h++){var i=f.item(h),j=i.value;if(j&&(j=e.serializer.deserialize(j)),j=a(j,i.key,h+1),void 0!==j)return void b(j)}b()},function(a,b){d(b)})})})["catch"](d)});return l(d,b),d}function f(b,c,d){var e=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var f=new Promise(function(a,d){e.ready().then(function(){void 0===c&&(c=null);var f=c,g=e._dbInfo;g.serializer.serialize(c,function(c,e){e?d(e):g.db.transaction(function(e){e.executeSql("INSERT OR REPLACE INTO "+g.storeName+" (key, value) VALUES (?, ?)",[b,c],function(){a(f)},function(a,b){d(b)})},function(a){a.code===a.QUOTA_ERR&&d(a)})})})["catch"](d)});return l(f,d),f}function g(b,c){var d=this;"string"!=typeof b&&(a.console.warn(b+" used as a key, but it is not a string."),b=String(b));var e=new Promise(function(a,c){d.ready().then(function(){var e=d._dbInfo;e.db.transaction(function(d){d.executeSql("DELETE FROM "+e.storeName+" WHERE key = ?",[b],function(){a()},function(a,b){c(b)})})})["catch"](c)});return l(e,c),e}function h(a){var b=this,c=new Promise(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("DELETE FROM "+d.storeName,[],function(){a()},function(a,b){c(b)})})})["catch"](c)});return l(c,a),c}function i(a){var b=this,c=new Promise(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("SELECT COUNT(key) as c FROM "+d.storeName,[],function(b,c){var d=c.rows.item(0).c;a(d)},function(a,b){c(b)})})})["catch"](c)});return l(c,a),c}function j(a,b){var c=this,d=new Promise(function(b,d){c.ready().then(function(){var e=c._dbInfo;e.db.transaction(function(c){c.executeSql("SELECT key FROM "+e.storeName+" WHERE id = ? LIMIT 1",[a+1],function(a,c){var d=c.rows.length?c.rows.item(0).key:null;b(d)},function(a,b){d(b)})})})["catch"](d)});return l(d,b),d}function k(a){var b=this,c=new Promise(function(a,c){b.ready().then(function(){var d=b._dbInfo;d.db.transaction(function(b){b.executeSql("SELECT key FROM "+d.storeName,[],function(b,c){for(var d=[],e=0;e 0; }; Cnds.prototype.IsProcessingGets = function () { return this.pendingGets > 0; }; Cnds.prototype.OnAllSetsComplete = function () { return true; }; Cnds.prototype.OnAllGetsComplete = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetItem = function (keyNoPrefix, value) { if (localForageInitFailed) { TriggerStorageError(this, "storage failed to initialise - may be disabled in browser settings"); return; } var keyPrefix = prefix + keyNoPrefix; this.pendingSets++; var self = this; localforage["setItem"](keyPrefix, value, function (err, valueSet) { debugDataChanged = true; self.pendingSets--; if (err) { errorMessage = getErrorString(err); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnError, self); } else { currentKey = keyNoPrefix; lastValue = valueSet; self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnAnyItemSet, self); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnItemSet, self); currentKey = ""; lastValue = ""; } if (self.pendingSets === 0) { self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnAllSetsComplete, self); } }); }; Acts.prototype.GetItem = function (keyNoPrefix) { if (localForageInitFailed) { TriggerStorageError(this, "storage failed to initialise - may be disabled in browser settings"); return; } var keyPrefix = prefix + keyNoPrefix; this.pendingGets++; var self = this; localforage["getItem"](keyPrefix, function (err, value) { self.pendingGets--; if (err) { errorMessage = getErrorString(err); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnError, self); } else { currentKey = keyNoPrefix; lastValue = value; if (typeof lastValue === "undefined" || lastValue === null) lastValue = ""; self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnAnyItemGet, self); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnItemGet, self); currentKey = ""; lastValue = ""; } if (self.pendingGets === 0) { self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnAllGetsComplete, self); } }); }; Acts.prototype.CheckItemExists = function (keyNoPrefix) { if (localForageInitFailed) { TriggerStorageError(this, "storage failed to initialise - may be disabled in browser settings"); return; } var keyPrefix = prefix + keyNoPrefix; var self = this; localforage["getItem"](keyPrefix, function (err, value) { if (err) { errorMessage = getErrorString(err); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnError, self); } else { currentKey = keyNoPrefix; if (value === null) // null value indicates key missing { lastValue = ""; // prevent ItemValue meaning anything self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnItemMissing, self); } else { lastValue = value; // make available to ItemValue expression self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnItemExists, self); } currentKey = ""; lastValue = ""; } }); }; Acts.prototype.RemoveItem = function (keyNoPrefix) { if (localForageInitFailed) { TriggerStorageError(this, "storage failed to initialise - may be disabled in browser settings"); return; } var keyPrefix = prefix + keyNoPrefix; var self = this; localforage["removeItem"](keyPrefix, function (err) { debugDataChanged = true; if (err) { errorMessage = getErrorString(err); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnError, self); } else { currentKey = keyNoPrefix; lastValue = ""; self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnAnyItemRemoved, self); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnItemRemoved, self); currentKey = ""; } }); }; Acts.prototype.ClearStorage = function () { if (localForageInitFailed) { TriggerStorageError(this, "storage failed to initialise - may be disabled in browser settings"); return; } if (is_arcade) return; var self = this; localforage["clear"](function (err) { debugDataChanged = true; if (err) { errorMessage = getErrorString(err); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnError, self); } else { currentKey = ""; lastValue = ""; cr.clearArray(keyNamesList); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnCleared, self); } }); }; Acts.prototype.GetAllKeyNames = function () { if (localForageInitFailed) { TriggerStorageError(this, "storage failed to initialise - may be disabled in browser settings"); return; } var self = this; localforage["keys"](function (err, keyList) { var i, len, k; if (err) { errorMessage = getErrorString(err); self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnError, self); } else { cr.clearArray(keyNamesList); for (i = 0, len = keyList.length; i < len; ++i) { k = keyList[i]; if (!hasRequiredPrefix(k)) continue; keyNamesList.push(removePrefix(k)); } self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnAllKeyNamesLoaded, self); } }); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.ItemValue = function (ret) { ret.set_any(lastValue); }; Exps.prototype.Key = function (ret) { ret.set_string(currentKey); }; Exps.prototype.KeyCount = function (ret) { ret.set_int(keyNamesList.length); }; Exps.prototype.KeyAt = function (ret, i) { i = Math.floor(i); if (i < 0 || i >= keyNamesList.length) { ret.set_string(""); return; } ret.set_string(keyNamesList[i]); }; Exps.prototype.ErrorMessage = function (ret) { ret.set_string(errorMessage); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.MM_Debugger = function(runtime) { this.runtime = runtime; }; (function () { var pluginStates = { DEBUG: 0, PRODUCTION: 1, DISABLED: 2 }; var currentState = pluginStates.DEBUG; var timestampModes = { UNIX: { MILLISECONDS: 0, SECONDS: 1 }, DATE: { MM_DD_YYYY: 2, DD_MM_YYYY: 3, YYYY_MM_DD: 4 }, NONE: 5 }; var assertionReportType = { SIMPLE: 0, DETAILED: 1 }; var outputTypes = { ALL: 0, CONSOLE: 1, STACK_TRACE: 2, CUSTOM: 3 }; var currentTimestampMode = timestampModes.UNIX.MILLISECONDS; var timestampOffset = 0; var stackTrace = []; var stackTraceLimit = 100; var lastLog = ""; var lastConsoleLog = ""; var lastStackTraceLog = ""; var lastCustomLog = ""; var disabledTags = []; var spotlightTags = []; var isGlobalSpotlightModeOn = false; var currentAssertionReportType = assertionReportType.SIMPLE; var MoMod = null; var pluginProto = cr.plugins_.MM_Debugger.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { var self = this; currentState = this.properties[1]; currentTimestampMode = this.properties[2]; timestampOffset = this.properties[3]; stackTraceLimit = this.properties[4]; currentAssertionReportType = this.properties[5]; this.executionTimers = {}; this.MoMod = { isReadyFlag: false, instance: null, type: null, actions: null, isReady: function() { if (this.isReadyFlag) return true; if(cr.plugins_.MoMod) { var type; for (type in self.runtime.types) { if ( ! self.runtime.types.hasOwnProperty(type)) continue; if (self.runtime.types[type].plugin instanceof cr.plugins_.MoMod) { this.type = self.runtime.types[type]; } } if (this.type) { this.instance = this.type.instances[0]; this.actions = cr.plugins_.MoMod.prototype.acts; this.isReadyFlag = true; return true; } } return false; } }; window.addEventListener("error", function (e) { self.streamLog(outputTypes.ALL, "[console error] " + e.message + "; file: " + e.filename + ", line: " + e.lineno + ", col: " + e.colno); }); if(typeof console !== "undefined" && console.warn) { console.warn = (function() { var w = console.warn; return function() { self.streamLog(outputTypes.ALL, "[console warning] " + arguments[0]); w.apply(console, arguments); } })(); } }; instanceProto.onDestroy = function () { }; instanceProto.getTimestampPrefix = function() { var timestampPrefix = null; var now = timestampOffset === 0 ? (new Date()) : (new Date((new Date()).getTime() + timestampOffset * 3600000)); switch (currentTimestampMode) { case timestampModes.UNIX.MILLISECONDS: timestampPrefix = now.getTime(); break; case timestampModes.UNIX.SECONDS: timestampPrefix = now.getTime() / 1000|0; break; case timestampModes.DATE.MM_DD_YYYY: timestampPrefix = (now.getUTCMonth()+1) + "-" + now.getUTCDate() + "-" + now.getUTCFullYear() + " " + now.getUTCHours() + ":" + now.getUTCMinutes() + ":" + now.getUTCSeconds() + "." + now.getUTCMilliseconds(); break; case timestampModes.DATE.DD_MM_YYYY: timestampPrefix = now.getUTCDate() + "-" + (now.getUTCMonth()+1) + "-" + now.getUTCFullYear() + " " + now.getUTCHours() + ":" + now.getUTCMinutes() + ":" + now.getUTCSeconds() + "." + now.getUTCMilliseconds(); break; case timestampModes.DATE.YYYY_MM_DD: timestampPrefix = now.getUTCFullYear() + "-" + (now.getUTCMonth()+1) + "-" + now.getUTCDate() + " " + now.getUTCHours() + ":" + now.getUTCMinutes() + ":" + now.getUTCSeconds() + "." + now.getUTCMilliseconds(); break; } if(timestampPrefix !== null) { timestampPrefix = timestampPrefix.toString() + ": "; } else { timestampPrefix = ""; } return timestampPrefix; }; instanceProto.isTagEnabled = function(tags) { if(disabledTags.length === 0) return true; var i = 0; var tagsArray = tags.split(","); for (i; i < tagsArray.length; ++i) { if(disabledTags.indexOf(tagsArray[i]) > -1) { return false; } } return true; }; instanceProto.isTagInSpotlight = function(tags) { var i = 0; var tagsArray = tags.split(","); for (i; i < tagsArray.length; ++i) { if(spotlightTags.indexOf(tagsArray[i]) > -1) { return true; } } return false; }; instanceProto.streamLog = function(outputType, data) { var self = this; lastLog = this.getTimestampPrefix() + data; if ((outputType === outputTypes.CONSOLE || outputType === outputTypes.ALL) && currentState === pluginStates.DEBUG) // console log { lastConsoleLog = lastLog; if(typeof console !== "undefined" && console.log) { console.log(lastConsoleLog); } self.runtime.trigger(cr.plugins_.MM_Debugger.prototype.cnds.OnConsoleLog, self); } if ((outputType === outputTypes.STACK_TRACE || outputType === outputTypes.ALL) && (currentState === pluginStates.DEBUG || currentState == pluginStates.PRODUCTION)) { lastStackTraceLog = lastLog; stackTrace.push(lastStackTraceLog); if(stackTraceLimit > 0 && stackTrace.length > stackTraceLimit) { stackTrace = stackTrace.slice(-stackTraceLimit); } self.runtime.trigger(cr.plugins_.MM_Debugger.prototype.cnds.OnStackTraceLog, self); } if ((outputType === outputTypes.CUSTOM || outputType === outputTypes.ALL) && currentState === pluginStates.DEBUG) { lastCustomLog = lastLog; self.runtime.trigger(cr.plugins_.MM_Debugger.prototype.cnds.OnCustomLog, self); } self.runtime.trigger(cr.plugins_.MM_Debugger.prototype.cnds.OnAnyLog, self); }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnConsoleLog = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnStackTraceLog = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnCustomLog = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnAnyLog = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.IsInState = function (stateToCompare) { return stateToCompare === currentState; }; /** * @returns {boolean} */ Cnds.prototype.OnAssertionFailed = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Log = function (outputType, data, tags) { this.log(outputType, data, tags); }; Acts.prototype.ClearStackTrace = function () { if(currentState === pluginStates.DISABLED) return null; stackTrace = []; }; Acts.prototype.SetTagState = function (tags, state) { var i = 0; var disabledTagIndex = 0; var tagsArray = tags.split(","); for (i; i < tagsArray.length; ++i) { if(disabledTagIndex = disabledTags.indexOf(tagsArray[i]) === -1) { if(state === 0) { disabledTags.push(tagsArray[i]); } } else { if(state === 1) { disabledTags.splice(disabledTagIndex, 1); } } } }; Acts.prototype.StartTagSpotlight = function (tags) { var i = 0; var tagsArray = tags.split(","); for (i; i < tagsArray.length; ++i) { spotlightTags.push(tagsArray[i]); } }; Acts.prototype.EndTagSpotlight = function () { spotlightTags = []; }; Acts.prototype.StartGlobalSpotlight = function () { isGlobalSpotlightModeOn = true; }; Acts.prototype.EndGlobalSpotlight = function () { isGlobalSpotlightModeOn = false; }; Acts.prototype.AssertAssertion = function (assertion, warningMessage) { if (currentState === pluginStates.DISABLED) return null; if ( ! assertion) { var currentEvent = this.runtime.getCurrentEventStack().current_event; var directEventSheet = currentEvent.actions[0].block.sheet.name; var line = currentEvent.display_number; if (currentAssertionReportType == assertionReportType.DETAILED) { var groupName = ""; while(currentEvent.parent !== null) { if (currentEvent.parent.group_name !== 'undefined' && currentEvent.parent.group_name !== '') { groupName = currentEvent.parent.group_name; break; } currentEvent = currentEvent.parent; } this.streamLog(outputTypes.ALL, "[ASSERTION FAILED on line " + line + ", es: "+ directEventSheet +"]"); this.streamLog(outputTypes.ALL, "[message] " + warningMessage); this.streamLog(outputTypes.ALL, "[layout]: " + this.runtime.running_layout.name); this.streamLog(outputTypes.ALL, "[layout es]: " + this.runtime.running_layout.event_sheet); this.streamLog(outputTypes.ALL, "[action es]: " + directEventSheet); this.streamLog(outputTypes.ALL, "[group]: " + groupName); this.streamLog(outputTypes.ALL, "[line]: " + line); this.streamLog(outputTypes.ALL, "***************************"); } else { this.streamLog(outputTypes.ALL, "[ASSERTION FAILED on line "+ line +", es: "+ directEventSheet +"] " + warningMessage); } this.runtime.trigger(cr.plugins_.MM_Debugger.prototype.cnds.OnAssertionFailed, this); } }; Acts.prototype.StartExecutionTimer = function (tag_) { this.executionTimers[tag_] = +new Date(); }; Acts.prototype.ClearExecutionTimer = function (tag_) { if (this.executionTimers[tag_]) delete this.executionTimers[tag_]; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.GetStackTrace = function (ret, separator) { ret.set_string(stackTrace.join(separator)); }; /** PRO +++ **/ Exps.prototype.GetProjectInfo = function (ret, separator) { var startTime = new Date(this.runtime.start_time); startTime = startTime.getUTCFullYear() + "-" + (startTime.getUTCMonth()+1) + "-" + startTime.getUTCDate() + " " + startTime.getUTCHours() + ":" + startTime.getUTCMinutes() + ":" + startTime.getUTCSeconds() + "." + startTime.getUTCMilliseconds(); var output = [ "launched: " + startTime + " (" + this.runtime.start_time + ")", this.runtime.name + " v" + this.runtime.versionstr, this.runtime.glUnmaskedRenderer ]; ret.set_string(output.join(separator)); }; /** PRO --- **/ /** PRO +++ **/ Exps.prototype.GetCurrentState = function (ret) { var ram = 0; if (this.runtime.glwrap) ram = Math.round(100 * this.runtime.glwrap.estimateVRAM() / (1024 * 1024)) / 100; var output = "FPS: " + this.runtime.fps + ", CPU: " + (Math.round(this.runtime.cpuutilisation*100) / 100000) + ", RAM: " + ram; ret.set_string(output); }; /** PRO --- **/ Exps.prototype.GetStackTraceSize = function (ret) { ret.set_int(stackTrace.length); }; Exps.prototype.GetLastStackTraceLog = function (ret) { ret.set_string(lastStackTraceLog); }; Exps.prototype.GetLastCustomLog = function (ret) { ret.set_string(lastCustomLog); }; Exps.prototype.GetLastLog = function (ret) { ret.set_string(lastLog); }; Exps.prototype.GetLastConsoleLog = function (ret) { ret.set_string(lastConsoleLog); }; Exps.prototype.GetDataType = function (ret, data) { ret.set_string(typeof data); }; Exps.prototype.GetExecutionTime = function (ret, tag_) { var executionTime = -1; if (this.executionTimers[tag_]) { executionTime = +new Date() - this.executionTimers[tag_]; } ret.set_int(executionTime); }; pluginProto.exps = new Exps(); /* //Shared functions function Shared() {} Shared.prototype.log = function(outputType, data, tags) { this.log(outputType, data, tags); }; pluginProto.shared = new Shared();*/ instanceProto.log = function(outputType, data, tags) { if (currentState === pluginStates.DISABLED) return null; if(isGlobalSpotlightModeOn === false) { if (spotlightTags.length > 0) { if(this.isTagInSpotlight(tags) === false) return null; } else if (this.isTagEnabled(tags) === false) return null; } if(this.MoMod.isReady()) { data = "[" + this.MoMod.instance.getModuleName() + "]" + "[" + this.MoMod.instance.getSectionName() + "]: " + data; } this.streamLog(outputType, data); } }()); ; ; cr.plugins_.MM_Preloader = function(runtime) { this.runtime = runtime; }; (function () { var preloader = { items: [], itemsCompleted: 0, itemsCount: 0, isLazyPreloading: false, lazyInterval: 0 }; var MoMod = null; var MM_Debugger = null; var THIS_TAG = "MM_Preloader"; var thisInstance = null; var objectPreloadId = 0; var OBJECT_PRELOAD_KEY = "mm_preloader_object_preload_"; var objectPreloadQueue = []; var isPreloadingObjects = false; var tickForNextObjectPreloadTrigger = 0; var intervalObject = null; var objectsPreloadingState = 0; var isC2EnginePreloaderAdded = false; var C2_ENGINE_PRELOADER_KEY = "mm_preloader_c2_engine_"; var spriterInterval = null; var spriterInst = null; var spriterIndex = null; var pluginProto = cr.plugins_.MM_Preloader.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { thisInstance = this; stabilizer.isEnabled = !!this.properties[1]; stabilizer.maxChecks = Math.max(this.properties[2], 1); stabilizer.frequency = this.properties[3]; stabilizer.minFps = Math.max(this.properties[4], 1); stabilizer.confirmations = Math.max(this.properties[5], 1); if(typeof cr.plugins_.MoMod !== 'undefined' && cr.plugins_.MoMod) { MoMod = cr.plugins_.MoMod.prototype.shared; } if(typeof cr.plugins_.MM_Debugger !== 'undefined' && cr.plugins_.MM_Debugger) { MM_Debugger = cr.plugins_.MM_Debugger.prototype.shared; } }; instanceProto.onDestroy = function () { }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnProgress = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnCompleted = function() { preloader.items = []; preloader.itemsCompleted = 0; preloader.itemsCount = 0; objectPreloadId = 0; objectPreloadQueue = []; isPreloadingObjects = false; tickForNextObjectPreloadTrigger = 0; intervalObject = null; objectsPreloadingState = 0; isC2EnginePreloaderAdded = false; if(stabilizer.isEnabled) { clearTimeout(stabilizer.instance.timerInstance); stabilizer.instance.currentCheck = 0; stabilizer.instance.currentConfirmations = 0; stabilizer.instance.timerInstance = null; } return true; }; /** * @returns {boolean} */ Cnds.prototype.HasItem = function(key_) { return (typeof preloader.items[key_.toLowerCase()] !== 'undefined' && preloader.items[key_.toLowerCase()]); }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.AddItem = function(key_, trigger_, dependency_) { addPreloaderItem(key_, trigger_, dependency_); }; Acts.prototype.SetItemState = function(key_, newState_) { setItemState(key_, newState_, this); }; Acts.prototype.Start = function() { preloader.isLazyPreloading = false; if(preloader.itemsCount === 0 && stabilizer.isEnabled === false) { preloaderLog("[Preloader]: Cannot start Preloader, the list is empty.", this); return; } if(stabilizer.isEnabled) { var key; var dependencyList = []; for (key in preloader.items) { if (preloader.items.hasOwnProperty(key)) { dependencyList.push(key); } } for (key in preloader.items) { if (preloader.items.hasOwnProperty(key) && preloader.items[key].dependency == "_last") { var localDependencyList = dependencyList; localDependencyList.splice(dependencyList.indexOf(key), 1); preloader.items[key].dependency = localDependencyList.join(); } } addPreloaderItem("Stabilizer", "true", "_last"); } preloaderProcessItems(this); }; Acts.prototype.StartLazy = function(lazyInterval_) { if(preloader.itemsCount === 0) { preloaderLog("[Preloader]: Cannot start Preloader, the list is empty.", this); return; } preloader.isLazyPreloading = true; preloader.lazyInterval = lazyInterval_; preloaderProcessItems(this); }; Acts.prototype.StabilizerSetState = function(state_) { stabilizer.isEnabled = !!state_; }; Acts.prototype.PreloadObject = function(obj_) { if ( ! obj_) return; addObjectToPreloader(obj_); }; Acts.prototype.AddFromLayoutByName = function(layoutName_) { var l, layout; for (l in this.runtime.layouts) { if (this.runtime.layouts.hasOwnProperty(l) && cr.equals_nocase(l, layoutName_)) { layout = this.runtime.layouts[l]; break; } } if( ! layout) { preloaderLog("[Preloader ERROR]: Cannot load objects from layout \"" + layoutName_ + "\" because such layout does not exist.", this); return; } addObjectFromLayout(layout); }; Acts.prototype.AddFromLayout = function(layout) { if( ! layout) return; addObjectFromLayout(layout); }; Acts.prototype.AddC2EngineProgress = function() { isC2EnginePreloaderAdded = true; addPreloaderItem(C2_ENGINE_PRELOADER_KEY, "", ""); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Progress = function(ret) { var generalPreloadProgress = Math.floor((preloader.itemsCompleted / preloader.itemsCount) * 10000) / 100; var detailedPreloadProgress = 0; var unitValue = 1 / preloader.itemsCount; var key; for (key in preloader.items) { if (preloader.items.hasOwnProperty(key) && preloader.items[key].currentState < 100 && preloader.items[key].currentState > 0) { detailedPreloadProgress += unitValue * (preloader.items[key].currentState / 100) } } detailedPreloadProgress = Math.floor(detailedPreloadProgress * 10000) / 100; ret.set_float(Math.floor((generalPreloadProgress + detailedPreloadProgress) * 100) / 100); }; Exps.prototype.ItemProgress = function(ret, key_) { key_ = key_.toLowerCase(); if(typeof preloader.items[key_] === 'undefined' || ! preloader.items[key_]) { preloaderLog("[Preloader ERROR]: Cannot get state of \"" + key_ + "\" item, because such item does not exist on preloader list.", this); ret.set_int(0); return; } ret.set_float(Math.floor(preloader.items[key_].currentState * 100) / 100); }; Exps.prototype.ItemsCount = function(ret) { ret.set_int(preloader.itemsCount); }; Exps.prototype.ObjectsProgress = function(ret) { if(objectPreloadQueue.length === 0) { preloaderLog("[Preloader ERROR]: Cannot get state of preloading objects, because none object has been added to the preloader list.", this); ret.set_int(0); return; } ret.set_float(Math.floor(objectsPreloadingState * 100) / 100); }; Exps.prototype.C2EngineProgress = function(ret) { if(typeof preloader.items[C2_ENGINE_PRELOADER_KEY] === 'undefined' || ! preloader.items[C2_ENGINE_PRELOADER_KEY]) { preloaderLog("[Preloader ERROR]: Cannot get state of \"C2 Engine\" item, because it does not exist on preloader list.", this); ret.set_int(0); return; } ret.set_float(Math.floor(preloader.items[C2_ENGINE_PRELOADER_KEY].currentState * 100) / 100); }; pluginProto.exps = new Exps(); var stabilizer = { isEnabled: true, maxChecks: 0, frequency: 0, minFps: 60, confirmations: 1, instance: { currentCheck: 0, currentConfirmations: 0, timerInstance: null, currentDis: null }, checkFunction: function() { if (stabilizer.maxChecks > stabilizer.instance.currentCheck) { ++stabilizer.instance.currentCheck; if (stabilizer.minFps <= thisInstance.runtime.fps) { ++stabilizer.instance.currentConfirmations; if (stabilizer.instance.currentConfirmations >= stabilizer.confirmations) { setItemState("Stabilizer", 100, stabilizer.instance.currentDis); return; } } var currentState = (stabilizer.instance.currentCheck / stabilizer.maxChecks) * 100; setItemState("Stabilizer", currentState, stabilizer.instance.currentDis); if(currentState < 100) { stabilizer.instance.timerInstance = setTimeout(stabilizer.checkFunction, stabilizer.frequency * 1000); } } else { setItemState("Stabilizer", 100, stabilizer.instance.currentDis); } } }; function addPreloaderItem(key_, trigger_, dependency_) { key_ = key_.toLowerCase(); if(typeof preloader.items[key_] !== 'undefined' && preloader.items[key_]) { preloaderLog("[Preloader]: Duplicate entry \"" + key_ + "\". This item already exists on preloader list.", this); return; } preloader.items[key_] = { trigger: trigger_.toLowerCase(), dependency: dependency_.toLowerCase(), currentState: 0, isProcessing: ! trigger_ }; ++preloader.itemsCount; } function preloaderProcessItems(dis_) { if(isC2EnginePreloaderAdded) { if( ! intervalObject) { intervalObject = setInterval(function() { var state = dis_.runtime.loadingprogress * 100; if(state == 100) { clearInterval(intervalObject); isC2EnginePreloaderAdded = false; } setItemState(C2_ENGINE_PRELOADER_KEY, state, dis_); }, 50); } return; } var key; for (key in preloader.items) { if( ! preloader.items.hasOwnProperty(key) || preloader.items[key].currentState === 100 || preloader.items[key].isProcessing === true) continue; if( ! preloader.items[key].dependency) { preloaderTriggerItem(key); } else if(preloader.items[key].dependency === "_last") { if(preloader.itemsCompleted === preloader.itemsCount - 1) { if(stabilizer.isEnabled) { preloader.items[key].isProcessing = true; stabilizer.instance.currentDis = dis_; stabilizer.instance.timerInstance = setTimeout(stabilizer.checkFunction, stabilizer.frequency * 1000); } else { preloaderTriggerItem(key); } } } else if(preloader.items[key].dependency === OBJECT_PRELOAD_KEY) { if(isPreloadingObjects === false) { isPreloadingObjects = true; triggerObjectsPreloadingQueue(dis_); } } else { var dependencies = preloader.items[key].dependency.split(","); var allDependenciesReady = true; var i; for(i = 0; i < dependencies.length; i++) { if( ! preloader.items[dependencies[i]]) { preloaderLog("[Preloader ERROR]: item \"" + key + "\" has dependency \"" + dependencies[i] + "\" but \"" + dependencies[i] + "\" item does not exist in preloader's list.", dis_); return; } if(preloader.items[dependencies[i]].currentState < 100) { allDependenciesReady = false; break; } } if (allDependenciesReady) { preloaderTriggerItem(key); } } if(preloader.isLazyPreloading) { return; } } } function addObjectToPreloader(obj_) { /* deadCache seems to be unpredictable and can't rely on it when it comes to sprites. Also it isn't the factor for texture in the memory, meaning that it happens that even thoug there's deadCache available, the texture isn't loaded. if(obj_.deadCache.length > 0 || obj_.instances.length > 0) { return; } */ var itemKey = OBJECT_PRELOAD_KEY + objectPreloadId; objectPreloadQueue.push({ object: obj_, key: itemKey, isPreloaded: false }); addPreloaderItem(itemKey, "automatic", OBJECT_PRELOAD_KEY); ++objectPreloadId; } function addObjectFromLayout(layout) { var i; for(i = 0; i < layout.initial_types.length; i++) { if(typeof layout.initial_types[i].plugin !== 'object') continue; if(cr.plugins_.Sprite && layout.initial_types[i].plugin instanceof cr.plugins_.Sprite) { if(layout.initial_types[i].has_loaded_textures) continue; } if(cr.plugins_.TiledBg && layout.initial_types[i].plugin instanceof cr.plugins_.TiledBg) { if(layout.initial_types[i].webGL_texture) continue; } if(cr.plugins_.Tilemap && layout.initial_types[i].plugin instanceof cr.plugins_.Tilemap) { if(layout.initial_types[i].cut_tiles_valid) continue; } if((cr.plugins_.SpriteFontPlus && layout.initial_types[i].plugin instanceof cr.plugins_.SpriteFontPlus) || (cr.plugins_.Spritefont2 && layout.initial_types[i].plugin instanceof cr.plugins_.Spritefont2)) { if(layout.initial_types[i].webGL_texture) continue; } if(cr.plugins_.Spriter && layout.initial_types[i].plugin instanceof cr.plugins_.Spriter) { if(layout.initial_types[i].deadCache.length > 0 /* || layout.initial_types[i].instances.length > 0 */ ) continue; } addObjectToPreloader(layout.initial_types[i]); } } var isWaitingForSpriterobject = false; function triggerObjectsPreloadingQueue(dis_) { if(intervalObject) { clearInterval(intervalObject); } if(spriterInterval) return; var i; var isLastItem = false; for(i = 0; i < objectPreloadQueue.length; i++) { if( ! objectPreloadQueue[i].isPreloaded) { isLastItem = i === objectPreloadQueue.length - 1; var inst = dis_.runtime.createInstance(objectPreloadQueue[i].object, dis_.runtime.running_layout.layers[0], -10000, -10000); if (inst) { if(cr.plugins_.Spriter && inst.type.plugin instanceof cr.plugins_.Spriter) { isWaitingForSpriterobject = true; spriterInst = inst; spriterIndex = i; spriterInterval = setInterval(function() { if(spriterInst.entities) { clearInterval(spriterInterval); spriterInterval = null; objectPreloadQueue[spriterIndex].isPreloaded = true; objectsPreloadingState = ((spriterIndex + 1) / objectPreloadQueue.length * 10000) / 100; setTimeout(function() // whitout this delay it breaks 50% of time { dis_.runtime.isEndingLayout = true; dis_.runtime.DestroyInstance(spriterInst); dis_.runtime.isEndingLayout = false; }, 50); setItemState(objectPreloadQueue[spriterIndex].key, 100, dis_); isWaitingForSpriterobject = false; } }, 10); } else { objectPreloadQueue[i].isPreloaded = true; objectsPreloadingState = ((i + 1) / objectPreloadQueue.length * 10000) / 100; setItemState(objectPreloadQueue[i].key, 100, dis_); dis_.runtime.isEndingLayout = true; dis_.runtime.DestroyInstance(inst); dis_.runtime.isEndingLayout = false; } } break; } } if( ! isLastItem) { tickForNextObjectPreloadTrigger = dis_.runtime.tickcount + 2; intervalObject = setInterval(function() { if(tickForNextObjectPreloadTrigger < dis_.runtime.tickcount) { triggerObjectsPreloadingQueue(dis_) } }, preloader.isLazyPreloading ? preloader.lazyInterval * 1000 : 50); } else { isPreloadingObjects = false; } } function setItemState(key_, newState_, dis_) { key_ = key_.toLowerCase(); if (typeof preloader.items[key_] === 'undefined' || !preloader.items[key_]) { preloaderLog("[Preloader ERROR]: Cannot update \"" + key_ + "\" item, because such item does not exist on preloader list.", dis_); return; } if (preloader.items[key_].currentState >= 100) return; // avoid redundant state 100 preloader.items[key_].currentState = cr.clamp(newState_, 0, 100); if (preloader.items[key_].currentState === 100) { ++preloader.itemsCompleted; } dis_.runtime.trigger(cr.plugins_.MM_Preloader.prototype.cnds.OnProgress, dis_); if (preloader.itemsCompleted === preloader.itemsCount) { dis_.runtime.trigger(cr.plugins_.MM_Preloader.prototype.cnds.OnCompleted, dis_); } else { if( ! isC2EnginePreloaderAdded) { if(preloader.isLazyPreloading && preloader.items[key_].currentState === 100) { setTimeout(function() { preloaderProcessItems(dis_); }, preloader.lazyInterval * 1000); } else { preloaderProcessItems(dis_); } } } } function preloaderTriggerItem(key_) { if(MoMod && preloader.items[key_].trigger.indexOf(" >>> ") !== -1) { var moduleName = preloader.items[key_].trigger.substring(0, preloader.items[key_].trigger.indexOf(" >>> ")); var eventName = preloader.items[key_].trigger.substring(preloader.items[key_].trigger.indexOf(" >>> ") + 5, preloader.items[key_].trigger.length); preloader.items[key_].isProcessing = true; MoMod.dispatchEvent(moduleName, eventName, []); } else if (window['c2_callFunction']) { preloader.items[key_].isProcessing = true; window['c2_callFunction'](preloader.items[key_].trigger, []); } } function preloaderLog(message_, dis_) { MM_Debugger ? MM_Debugger.log(0, message_, THIS_TAG, dis_) : console.log(message_); } }()); ; ; cr.plugins_.MM_Unloader = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.MM_Unloader.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { }; instanceProto.onDestroy = function () { }; function Cnds() {}; /** * @returns {boolean} */ /*Cnds.prototype.OnDataMissing = function() { return true; };*/ pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.UnloadAllUnused = function() { var i, len, type; if (this.runtime.glwrap) { for (i = 0, len = this.runtime.types_by_index.length; i < len; ++i) { type = this.runtime.types_by_index[i]; if (type.is_family) continue; this.unload(type); } } this.runtime.redraw = true; }; Acts.prototype.UnloadObject = function(obj_) { this.unload(obj_); this.runtime.redraw = true; }; Acts.prototype.HardDestroyObject = function(obj_) { this.hardDestroy(obj_); }; Acts.prototype.HardDestroyLayer = function(layer_) { var uniqueObjects = []; var i, len = layer_.instances.length; for (i = 0; i < len; ++i) { if (uniqueObjects.indexOf(layer_.instances[i].type) === -1) uniqueObjects.push(layer_.instances[i].type); } len = uniqueObjects.length; for (i = 0; i < len; ++i) { this.hardDestroy(uniqueObjects[i]); } }; Acts.prototype.DestroyLayer = function(layer_) { var i, len = layer_.instances.length; for (i = 0; i < len; ++i) { this.runtime.DestroyInstance(layer_.instances[i]); } }; pluginProto.acts = new Acts(); function Exps() {}; /*Exps.prototype.GetData = function(ret, dataIndex_) { ret.set_any(this.data[dataIndex_]); };*/ pluginProto.exps = new Exps(); instanceProto.unload = function(type_) { if (type_.is_family) { var i, len; for (i = 0, len = type_.members.length; i < len; ++i) { this.unloadType(type_.members[i]); } } else { this.unloadType(type_); } }; instanceProto.unloadType = function(type_) { if (type_.unloadTextures && (!type_.global || type_.instances.length === 0)) { type_.unloadTextures(); } } instanceProto.hardDestroy = function(obj_) { var i, len; for (i = 0, len = obj_.instances.length; i < len; ++i) { this.runtime.DestroyInstance(obj_.instances[i]); } if(obj_.instances.length === 0) { this.unload(obj_); this.runtime.redraw = true; } else { var self = this; var instanceMonitor = setInterval(function() { if(obj_.instances.length === 0) { self.unload(obj_); clearInterval(instanceMonitor); self.runtime.redraw = true; } }, 10); } } }()); ; ; cr.plugins_.MoMod = function(runtime) { this.runtime = runtime; }; (function () { var moduleSection = { HEAD: 'Head', BODY: 'Body' }; var branchStates = { DISABLED: 0, ENABLED: 1, TOGGLE: 2 }; var currentlyProcessingModule = ''; var customBodySections = {}; var customHeadSections = {}; var eventsStack = []; var eventsStackPointer = -1; var MM_Debugger = null; function MMsEventsStackEntry() { this.module = ""; this.event = ""; this.params = []; } function mmsPushEventsStack() { eventsStackPointer++; if (eventsStackPointer === eventsStack.length) eventsStack.push(new MMsEventsStackEntry()); return eventsStack[eventsStackPointer]; } function mmsGetCurrentEventsStack() { if (eventsStackPointer < 0) return null; return eventsStack[eventsStackPointer]; } function mmsPopEventsStack() { ; eventsStackPointer--; } var pluginProto = cr.plugins_.MoMod.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function () { var self = this; this.MMD = { isReadyFlag: false, instance: null, type: null, actions: null, isReady: function() { if (this.isReadyFlag) return true; if(cr.plugins_.MM_Debugger) { var type; for (type in self.runtime.types) { if ( ! self.runtime.types.hasOwnProperty(type)) continue; if (self.runtime.types[type].plugin instanceof cr.plugins_.MM_Debugger) { this.type = self.runtime.types[type]; } } if (this.type) { this.instance = this.type.instances[0]; this.actions = cr.plugins_.MM_Debugger.prototype.acts; this.isReadyFlag = true; return true; } } return false; } }; }; instanceProto.onDestroy = function () { }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnModuleEvent = function (eventName_) { var es = mmsGetCurrentEventsStack(); if (!es) return false; return cr.equals_nocase(this.getModuleName() + eventName_, es.module + es.event); }; /** * @returns {boolean} */ Cnds.prototype.OnCustomModuleEvent = function (moduleName_, eventName_) { var es = mmsGetCurrentEventsStack(); if (!es) return false; return cr.equals_nocase(moduleName_ + eventName_, es.module + es.event); }; /** * @returns {boolean} */ Cnds.prototype.IsModuleEnabled = function (moduleName_) { if(this.getBranchState(moduleName_, null, null) !== branchStates.ENABLED || this.isModuleShutdown(moduleName_)) { return false; } if(Array.isArray(customBodySections[moduleName_]) === true) { var i; for(i = 0; i < customBodySections[moduleName_].length; i++) { if(this.getBranchState(moduleName_, customBodySections[moduleName_][i], null) === branchStates.DISABLED) return false; } } return true; }; /** * @returns {boolean} */ Cnds.prototype.IfModuleExists = function (moduleName_) { return this.isModule(moduleName_); }; /** * @returns {boolean} */ Cnds.prototype.OnModuleEnabled = function () { return cr.equals_nocase(currentlyProcessingModule, this.getModuleName()); }; /** * @returns {boolean} */ Cnds.prototype.OnModuleDisabled = function () { return cr.equals_nocase(currentlyProcessingModule, this.getModuleName()); }; /** * @returns {boolean} */ Cnds.prototype.IsSectionEnabled = function (section_, branch_) { var thisModuleName = this.getModuleName(); thisModuleName = this.parseName(thisModuleName); if ( ! this.isModule(thisModuleName)) return false; if ( ! this.isSection(thisModuleName, section_)) return false; return this.getBranchState(thisModuleName, section_, branch_) === branchStates.ENABLED; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetModuleState = function (moduleName_, newState_) { if (this.isModule(moduleName_) === false) return; moduleName_ = this.parseName(moduleName_); if(this.isModuleShutdown(moduleName_)) { this.MMD.isReady() && this.log("[Set module state]: Can't change module's state because '" + moduleName_ + "' is shutdown.", this); return; } if(this.sectionExists(moduleName_, moduleSection.BODY.toLocaleLowerCase())) { this.setBranchState(newState_, moduleName_, moduleSection.BODY, null); } if(Array.isArray(customBodySections[moduleName_]) === true) { var i; for(i = 0; i < customBodySections[moduleName_].length; i++) { this.setBranchState(newState_, moduleName_, customBodySections[moduleName_][i], null); } } currentlyProcessingModule = moduleName_; if(newState_) { this.runtime.trigger(cr.plugins_.MoMod.prototype.cnds.OnModuleEnabled, this); } else { this.runtime.trigger(cr.plugins_.MoMod.prototype.cnds.OnModuleDisabled, this); } this.dispatchEvent(moduleName_, newState_ ? "OnEnabled" : "OnDisabled", []); }; Acts.prototype.TriggerModuleEvent = function (eventName_, params_) { this.dispatchEvent(this.getModuleName(), eventName_, params_); }; Acts.prototype.TriggerCustomModuleEvent = function (moduleName_, eventName_, params_) { this.dispatchEvent(moduleName_, eventName_, params_); }; Acts.prototype.SetSection = function (sectionName_, branchName_, newState_) { this.setBranchState(newState_, this.getModuleName(), sectionName_, branchName_); }; Acts.prototype.ShutdownModule = function (moduleName_) { if ( ! this.isModule(moduleName_)) return; moduleName_ = this.parseName(moduleName_); this.setBranchState(branchStates.DISABLED, moduleName_, null, null); if(this.sectionExists(moduleName_, moduleSection.HEAD.toLocaleLowerCase())) { this.setBranchState(branchStates.DISABLED, moduleName_, moduleSection.HEAD, null); } if(Array.isArray(customHeadSections[moduleName_]) === true) { var i; for(i = 0; i < customHeadSections[moduleName_].length; i++) { this.setBranchState(branchStates.DISABLED, moduleName_, customHeadSections[moduleName_][i], null); } } }; Acts.prototype.StartUpModule = function (moduleName_) { if ( ! this.isModule(moduleName_)) return; moduleName_ = this.parseName(moduleName_); this.setBranchState(branchStates.ENABLED, moduleName_, null, null); if(this.sectionExists(moduleName_, moduleSection.HEAD.toLocaleLowerCase())) { this.setBranchState(branchStates.ENABLED, moduleName_, moduleSection.HEAD, null); } if(Array.isArray(customHeadSections[moduleName_]) === true) { var i; for(i = 0; i < customHeadSections[moduleName_].length; i++) { this.setBranchState(branchStates.ENABLED, moduleName_, customHeadSections[moduleName_][i], null); } } }; Acts.prototype.RegisterBodySection = function (sectionName_) { var thisModuleName = this.getModuleName(); thisModuleName = this.parseName(thisModuleName); if ( ! this.isModule(thisModuleName) || ! this.isSection(thisModuleName, sectionName_)) return; if(Array.isArray(customBodySections[thisModuleName]) === false) { customBodySections[thisModuleName] = []; } if(customBodySections[thisModuleName].indexOf(sectionName_) === -1) { customBodySections[thisModuleName].push(sectionName_); } }; Acts.prototype.RegisterHeadSection = function (sectionName_) { var thisModuleName = this.getModuleName(); thisModuleName = this.parseName(thisModuleName); if ( ! this.isModule(thisModuleName) || ! this.isSection(thisModuleName, sectionName_)) return; if(Array.isArray(customHeadSections[thisModuleName]) === false) { customHeadSections[thisModuleName] = []; } if(customHeadSections[thisModuleName].indexOf(sectionName_) === -1) { customHeadSections[thisModuleName].push(sectionName_); } }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.ThisModule = function (ret) { ret.set_string(this.getModuleName()); }; Exps.prototype.ThisController = function (ret) { ret.set_string(this.getControllerName()); }; Exps.prototype.ThisSection = function (ret) { ret.set_string(this.getSectionName()); }; Exps.prototype.Param = function (ret, index_) { index_ = cr.floor(index_); var es = mmsGetCurrentEventsStack(); if (es) { if (index_ >= 0 && index_ < es.params.length) { ret.set_any(es.params[index_]); } else { this.MMD.isReady() && this.log("[Event param]: In module event \"" + es.event + "@" + es.module + "\", accessed parameter out of bounds (accessed index " + index_ + ", " + es.params.length + " params available)", this); ret.set_int(0); } } else { this.MMD.isReady() && this.log("[Module event]: used \"MoMod.EventParam\" expression when not in a module event observer.", this); ret.set_int(0); } }; Exps.prototype.ThisBranch = function (ret) { ret.set_string(this.getBranchName()); }; pluginProto.exps = new Exps(); /* // Shared functions function Shared() {} Shared.prototype.getModuleName = function(dis_) { return dis_.getModuleName(); }; Shared.prototype.getControllerName = function(dis_) { return dis_.getControllerName(); }; Shared.prototype.getSectionName = function(dis_) { var sectionName = dis_.getSectionName(); return sectionName.charAt(0).toUpperCase() + sectionName.slice(1); }; Shared.prototype.dispatchEvent = function(moduleName_, eventName_, params_) { this.dispatchEvent(moduleName_, eventName_, params_); }; pluginProto.shared = new Shared();*/ instanceProto.dispatchEvent = function (moduleName_, eventName_, params_) { var es = mmsPushEventsStack(); es.module = this.parseName(moduleName_); es.event = this.parseName(eventName_); cr.shallowAssignArray(es.params, params_); this.runtime.trigger(cr.plugins_.MoMod.prototype.cnds.OnModuleEvent, this); this.runtime.trigger(cr.plugins_.MoMod.prototype.cnds.OnCustomModuleEvent, this); mmsPopEventsStack(); }; instanceProto.isModule = function (moduleName_) { moduleName_ = this.parseName(moduleName_); if (moduleName_ === "MM_Core".toLocaleLowerCase()) return true; if ( ! this.runtime.groups_by_name[moduleName_]) { this.MMD.isReady() && this.log("[Module]: \"" + moduleName_ + "\" is not a valid module or does not exist.", this); return false; } return true; }; instanceProto.isSection = function (moduleName_, sectionName_) { moduleName_ = this.parseName(moduleName_); sectionName_ = this.parseName(sectionName_); if( ! this.sectionExists(moduleName_, sectionName_)) { this.MMD.isReady() && this.log("[Module]: \"" + sectionName_ + "\" is not a valid section of \"" + moduleName_ + "\" module.", this); return false; } return true; }; instanceProto.sectionExists = function (moduleName_, sectionName_) { moduleName_ = this.parseName(moduleName_); sectionName_ = this.parseName(sectionName_); return !! this.runtime.groups_by_name[moduleName_ + '[' + sectionName_ + ']']; }; instanceProto.isModuleShutdown = function (moduleName_) { moduleName_ = this.parseName(moduleName_); if ( ! this.runtime.groups_by_name.hasOwnProperty(moduleName_)) { return false; } return ! this.runtime.groups_by_name[moduleName_].group_active; }; instanceProto.setBranchState = function (newState_, moduleName_, sectionName_, branch_) { moduleName_ = this.parseName(moduleName_); sectionName_ = this.parseName(sectionName_); branch_ = this.parseName(branch_); if ( ! this.isModule(moduleName_)) return; var groupName = moduleName_; if (sectionName_) { if( ! this.isSection(moduleName_, sectionName_)) return; groupName += '[' + sectionName_ + ']'; } if(branch_) { groupName += " > " + branch_; } var branch = this.runtime.groups_by_name[groupName]; if( ! branch) { this.MMD.isReady() && this.log("[MoMod]: \"" + groupName + "\" is not a valid branch of \"" + moduleName_ + "\" module.", this); return false; } switch(newState_) { case branchStates.DISABLED: newState_ = false; break; case branchStates.ENABLED: newState_ = true; break; case branchStates.TOGGLE: newState_ = ! branch.group_active; break; } branch.setGroupActive(newState_); }; instanceProto.getBranchState = function (moduleName_, sectionName_, branch_) { moduleName_ = this.parseName(moduleName_); sectionName_ = this.parseName(sectionName_); branch_ = this.parseName(branch_); if ( ! this.isModule(moduleName_)) return branchStates.DISABLED; var groupName = moduleName_; if (sectionName_) { if( ! this.isSection(moduleName_, sectionName_)) return branchStates.DISABLED; groupName += '[' + sectionName_ + ']'; } if(branch_) { groupName += " > " + branch_; } var branch = this.runtime.groups_by_name[groupName]; if( ! branch) { this.MMD.isReady() && this.log("[Get branch]: \"" + groupName + "\" is not a valid branch of \"" + moduleName_ + "\" module.", this); return branchStates.DISABLED; } return +branch.group_active; }; instanceProto.parseName = function (branchName_) { if (branchName_) branchName_ = branchName_.toLowerCase(); return branchName_; }; instanceProto.getControllerName = function () { var currentEvent = this.getCurrentRuntimeEvent(); if ( ! currentEvent.momod.controller) { currentEvent.momod.controller = String(this.runtime.running_layout.event_sheet); } return currentEvent.momod.controller; }; instanceProto.getModuleName = function () { return this.runtime.getCurrentEventStack().current_event.sheet.name; /* --- Accessing sheet.name directly is slightly faster var currentEvent = this.getCurrentRuntimeEvent(); if ( ! currentEvent.momod.module) { currentEvent.momod.module = currentEvent.sheet.name; } return currentEvent.momod.module; */ }; instanceProto.getBranchName = function () { var currentEvent = this.getCurrentRuntimeEvent(); if ( ! currentEvent.momod.branch) { var groupName = this.getThisGroupName(); var sectionStartPos = groupName.indexOf(">"); if (sectionStartPos === -1) { return ""; } currentEvent.momod.branch = groupName.substring(sectionStartPos + 2, groupName.length); } return currentEvent.momod.branch; }; instanceProto.getSectionName = function () { var currentEvent = this.getCurrentRuntimeEvent(); if ( ! currentEvent.momod.section) { var groupName = this.getThisGroupName(); if (groupName) { var sectionStartPos = groupName.indexOf("["); var sectionEndPos = groupName.indexOf("]"); } if( ! groupName || sectionStartPos === -1 || sectionEndPos === -1 || sectionStartPos + 1 === sectionEndPos) { this.MMD.isReady() && this.log("[Get section name]: This event doesn't belong to any section."); return ""; } currentEvent.momod.section = groupName.substring(sectionStartPos + 1, sectionEndPos); } return currentEvent.momod.section; }; instanceProto.getThisGroupName = function () { var currentEvent = this.getCurrentRuntimeEvent(); if ( ! currentEvent.momod.group) { var eventPointer = currentEvent; while(eventPointer.parent !== null) { if (eventPointer.parent.group_name !== 'undefined' && eventPointer.parent.group_name !== '') { currentEvent.momod.group = eventPointer.parent.group_name; break; } eventPointer = eventPointer.parent; } } return currentEvent.momod.group; }; instanceProto.getCurrentRuntimeEvent = function () { if ( ! this.runtime.getCurrentEventStack().current_event.momod) { this.runtime.getCurrentEventStack().current_event.momod = {}; } return this.runtime.getCurrentEventStack().current_event; }; instanceProto.log = function (message_) { var currentEvent = this.runtime.getCurrentEventStack().current_event; var directEventSheet = currentEvent.actions[0].block.sheet.name; var line = currentEvent.display_number; message_ = "[MoMod ERROR on line " + line + ", sheet " + directEventSheet + "]" + message_; var es = mmsPushEventsStack(); es.module = "MM_Core".toLowerCase(); es.event = "Log".toLocaleLowerCase(); cr.shallowAssignArray(es.params, [message_]); this.MMD.isReady() && this.MMD.instance.log(0, message_, 'MoMod', this); this.runtime.trigger(cr.plugins_.MoMod.prototype.cnds.OnCustomModuleEvent, this); mmsPopEventsStack(); }; }()); ; ; cr.plugins_.Mouse = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Mouse.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; this.buttonMap = new Array(4); // mouse down states this.mouseXcanvas = 0; // mouse position relative to canvas this.mouseYcanvas = 0; this.triggerButton = 0; this.triggerType = 0; this.triggerDir = 0; this.handled = false; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { var self = this; if (!this.runtime.isDomFree) { jQuery(document).mousemove( function(info) { self.onMouseMove(info); } ); jQuery(document).mousedown( function(info) { self.onMouseDown(info); } ); jQuery(document).mouseup( function(info) { self.onMouseUp(info); } ); jQuery(document).dblclick( function(info) { self.onDoubleClick(info); } ); var wheelevent = function(info) { self.onWheel(info); }; document.addEventListener("mousewheel", wheelevent, false); document.addEventListener("DOMMouseScroll", wheelevent, false); } }; var dummyoffset = {left: 0, top: 0}; instanceProto.onMouseMove = function(info) { var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset(); this.mouseXcanvas = info.pageX - offset.left; this.mouseYcanvas = info.pageY - offset.top; }; instanceProto.mouseInGame = function () { if (this.runtime.fullscreen_mode > 0) return true; return this.mouseXcanvas >= 0 && this.mouseYcanvas >= 0 && this.mouseXcanvas < this.runtime.width && this.mouseYcanvas < this.runtime.height; }; instanceProto.onMouseDown = function(info) { if (!this.mouseInGame()) return; this.buttonMap[info.which] = true; this.runtime.isInUserInputEvent = true; this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnAnyClick, this); this.triggerButton = info.which - 1; // 1-based this.triggerType = 0; // single click this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnClick, this); this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnObjectClicked, this); this.runtime.isInUserInputEvent = false; }; instanceProto.onMouseUp = function(info) { if (!this.buttonMap[info.which]) return; if (this.runtime.had_a_click && !this.runtime.isMobile) info.preventDefault(); this.runtime.had_a_click = true; this.buttonMap[info.which] = false; this.runtime.isInUserInputEvent = true; this.triggerButton = info.which - 1; // 1-based this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnRelease, this); this.runtime.isInUserInputEvent = false; }; instanceProto.onDoubleClick = function(info) { if (!this.mouseInGame()) return; info.preventDefault(); this.runtime.isInUserInputEvent = true; this.triggerButton = info.which - 1; // 1-based this.triggerType = 1; // double click this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnClick, this); this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnObjectClicked, this); this.runtime.isInUserInputEvent = false; }; instanceProto.onWheel = function (info) { var delta = info.wheelDelta ? info.wheelDelta : info.detail ? -info.detail : 0; this.triggerDir = (delta < 0 ? 0 : 1); this.handled = false; this.runtime.isInUserInputEvent = true; this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnWheel, this); this.runtime.isInUserInputEvent = false; if (this.handled && cr.isCanvasInputEvent(info)) info.preventDefault(); }; instanceProto.onWindowBlur = function () { var i, len; for (i = 0, len = this.buttonMap.length; i < len; ++i) { if (!this.buttonMap[i]) continue; this.buttonMap[i] = false; this.triggerButton = i - 1; this.runtime.trigger(cr.plugins_.Mouse.prototype.cnds.OnRelease, this); } }; function Cnds() {}; Cnds.prototype.OnClick = function (button, type) { return button === this.triggerButton && type === this.triggerType; }; Cnds.prototype.OnAnyClick = function () { return true; }; Cnds.prototype.IsButtonDown = function (button) { return this.buttonMap[button + 1]; // jQuery uses 1-based buttons for some reason }; Cnds.prototype.OnRelease = function (button) { return button === this.triggerButton; }; Cnds.prototype.IsOverObject = function (obj) { var cnd = this.runtime.getCurrentCondition(); var mx = this.mouseXcanvas; var my = this.mouseYcanvas; return cr.xor(this.runtime.testAndSelectCanvasPointOverlap(obj, mx, my, cnd.inverted), cnd.inverted); }; Cnds.prototype.OnObjectClicked = function (button, type, obj) { if (button !== this.triggerButton || type !== this.triggerType) return false; // wrong click type return this.runtime.testAndSelectCanvasPointOverlap(obj, this.mouseXcanvas, this.mouseYcanvas, false); }; Cnds.prototype.OnWheel = function (dir) { this.handled = true; return dir === this.triggerDir; }; pluginProto.cnds = new Cnds(); function Acts() {}; var lastSetCursor = null; Acts.prototype.SetCursor = function (c) { if (this.runtime.isDomFree) return; var cursor_style = ["auto", "pointer", "text", "crosshair", "move", "help", "wait", "none"][c]; if (lastSetCursor === cursor_style) return; // redundant lastSetCursor = cursor_style; document.body.style.cursor = cursor_style; }; Acts.prototype.SetCursorSprite = function (obj) { if (this.runtime.isDomFree || this.runtime.isMobile || !obj) return; var inst = obj.getFirstPicked(); if (!inst || !inst.curFrame) return; var frame = inst.curFrame; if (lastSetCursor === frame) return; // already set this frame lastSetCursor = frame; var datauri = frame.getDataUri(); var cursor_style = "url(" + datauri + ") " + Math.round(frame.hotspotX * frame.width) + " " + Math.round(frame.hotspotY * frame.height) + ", auto"; document.body.style.cursor = ""; document.body.style.cursor = cursor_style; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.X = function (ret, layerparam) { var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.mouseXcanvas, this.mouseYcanvas, true)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.mouseXcanvas, this.mouseYcanvas, true)); else ret.set_float(0); } }; Exps.prototype.Y = function (ret, layerparam) { var layer, oldScale, oldZoomRate, oldParallaxY, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxY = layer.parallaxY; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxY = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.mouseXcanvas, this.mouseYcanvas, false)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxY = oldParallaxY; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.mouseXcanvas, this.mouseYcanvas, false)); else ret.set_float(0); } }; Exps.prototype.AbsoluteX = function (ret) { ret.set_float(this.mouseXcanvas); }; Exps.prototype.AbsoluteY = function (ret) { ret.set_float(this.mouseYcanvas); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.NSG_DataBag = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_DataBag.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.bags = []; }; function Cnds() {}; Cnds.prototype.IsBagEmpty = function (bagId_) { bagId_ = this.parseBagId(bagId_); return this.isBagEmpty(bagId_); }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.AddData = function (data_, bagId_) { bagId_ = this.parseBagId(bagId_); if (typeof this.bags[bagId_] === "undefined") { this.bags[bagId_] = []; } this.bags[bagId_].push(data_); }; Acts.prototype.ClearBag = function (bagId_) { bagId_ = this.parseBagId(bagId_); if (typeof this.bags[bagId_] === "undefined") return; this.bags[bagId_] = []; }; Acts.prototype.ClearAllBags = function () { this.bags = []; }; Acts.prototype.RemoveData = function (data_, bagId_) { bagId_ = this.parseBagId(bagId_); if (typeof this.bags[bagId_] === "undefined") return; this.bags[bagId_].splice(this.bags[bagId_].indexOf(data_), 1); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.CutRandomData = function (ret, bagId_) // 'ret' must always be the first parameter - always return the expression's result through it! { bagId_ = this.parseBagId(bagId_); if (this.isBagEmpty(bagId_)) { ret.set_any(-1); } else { var dataIndex = Math.floor(Math.random()*this.bags[bagId_].length); ret.set_any(this.bags[bagId_][dataIndex]); this.bags[bagId_].splice(dataIndex, 1); } }; pluginProto.exps = new Exps(); instanceProto.parseBagId = function (bagId_) { return bagId_.trim().toLowerCase(); } instanceProto.isBagEmpty = function(bagId_) { return typeof this.bags[bagId_] === "undefined" || this.bags[bagId_].length === 0; } }()); window['trSmartRedirect'] = function(url_) { function inIframe () { try { return window.self !== window.top; } catch (e) { return true; } } if(inIframe()) { window.top.location.href = url_; } else { window.location.href = url_; } }; ; ; cr.plugins_.NSG_MobilePopup = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_MobilePopup.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.android = { image: this.properties[0], URL: this.properties[1] }; this.iOS = { image: this.properties[2], URL: this.properties[3] }; this.closeButtonImageUrl = this.properties[4]; this.currentPlatform = this.runtime.isAndroid ? this.android : this.iOS; if ( ! this.currentPlatform.image || ! this.currentPlatform.URL) return; this.isActive = false; if ( ! this.runtime.isMobile) return; var i, exceptSources = [ "crazygames.com", "1001juegos.com", "speelspelletjes.nl", "gioca.re", "onlinegame.co.id" ]; for (i = 0; i < exceptSources.length; ++i) { if (document.referrer.indexOf(exceptSources[i]) !== -1) { this.isActive = false; return; } } this.isActive = true; this.popupDiv = document.createElement("div"); var parent = this.runtime.canvasdiv ? this.runtime.canvasdiv : document.body; parent.appendChild(this.popupDiv); this.popupDiv.id = "NSG-mobile-popup"; this.popupDiv.style.width = "100%"; this.popupDiv.style.height = "100%"; this.popupDiv.style.display = "flex"; this.popupDiv.style.backgroundColor = "rgba(0, 0, 0, 0.8)"; this.popupDiv.style.top = "1px"; this.popupDiv.style.left = "1px"; this.popupDiv.style.zIndex = "9997"; this.popupDiv.style.position = "absolute"; this.popupDiv.style.justifyContent = "center"; this.popupDiv.style.alignItems = "center"; this.popupImage = document.createElement("img"); this.popupDiv.appendChild(this.popupImage); this.popupImage.id = "NSG-mobile-popup-image"; this.popupImage.style.display = "block"; this.popupImage.src = this.currentPlatform.image; this.popupImage.style.zIndex = "9998"; this.popupImage.style.maxHeight = "90%"; this.popupImage.style.maxWidth = "85%"; this.closeBtn = document.createElement("img"); parent.appendChild(this.closeBtn); this.closeBtn.id = "NSG-mobile-popup-close-btn"; this.closeBtn.style.display = "flex"; this.closeBtn.src = this.closeButtonImageUrl; this.closeBtn.style.top = "5%"; this.closeBtn.style.right = "3%"; this.closeBtn.style.zIndex = "9999"; this.closeBtn.style.position = "absolute"; var self = this; this.popupImage.onclick = function () { window["trSmartRedirect"](self.currentPlatform.URL); }; this.closeBtn.onclick = function () { self.isActive = false; self.popupDiv.remove(); self.closeBtn.remove(); self.runtime.trigger(cr.plugins_.NSG_MobilePopup.prototype.cnds.OnClose, self); } }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.IsActive = function () { return !!this.isActive; }; /** * @returns {boolean} */ Cnds.prototype.OnClose = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.IsActive = function (ret) // 'ret' must always be the first parameter - always return the expression's result through it! { ret.set_int( !! this.isActive); // return our value }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.NSG_NicknamesDB = function(runtime) { this.runtime = runtime; }; (function () { var isNWjs = false; var path = null; var fs = null; var nw_appfolder = ""; var pluginProto = cr.plugins_.NSG_NicknamesDB.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this._DB = []; this.lockedNicknames = []; this.errorMessage = ""; this.filenamePrefix = this.properties[0]; this.filesQty = this.properties[1]; this.filesRemaining = []; var i; for (i = 0; i < this.filesQty; ++i) { this.filesRemaining.push(i+1); } isNWjs = this.runtime.isNWjs; if (isNWjs) { path = require("path"); fs = require("fs"); var process = window["process"] || nw["process"]; nw_appfolder = path["dirname"](process["execPath"]) + "\\"; } }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnLoadingCompleted = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnLoadingFailed = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnAnyError = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Load = function () { var self = this; if (this.filesRemaining.length === 0) { self.errorMessage = "No more files to load"; self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingFailed, self); return; } var currentFileNumber, currentFileIndex = Math.floor(Math.random() * this.filesRemaining.length); currentFileNumber = this.filesRemaining[currentFileIndex]; this.filesRemaining.splice(currentFileIndex, 1); var file_ = this.filenamePrefix + currentFileNumber; if (this.runtime.isWKWebView) { this.runtime.fetchLocalFileViaCordovaAsText(file_, function (newNicknames_) { newNicknames_ = B.decode(newNicknames_.substring(5<<1^3)).split(","); self._DB = self._DB.concat(newNicknames_); self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingCompleted, self); }, function (err) { self.errorMessage = err.message; self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingFailed, self); }); } else { this.doRequest("NicknamesDB_call", file_, "GET"); } }; instanceProto.doRequest = function (tag_, url_, method_, data_) { if (this.runtime.isDirectCanvas) { AppMobi["webview"]["execute"]('C2_AJAX_WebSide("' + tag_ + '", "' + url_ + '", "' + method_ + '", ' + (data_ ? '"' + data_ + '"' : "null") + ');'); return; } var self = this; var request = null; var doErrorFunc = function () { self.errorMessage = "=== loading error 1"; self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingFailed, self); }; var errorFunc = function () { if (isNWjs) { var filepath = nw_appfolder + url_; if (fs["existsSync"](filepath)) { fs["readFile"](filepath, {"encoding": "utf8"}, function (err, newNicknames_) { if (err) { doErrorFunc(); return; } newNicknames_ = B.decode(newNicknames_.substring(5<<1^3)).split(","); self._DB = self._DB.concat(newNicknames_); self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingCompleted, self); }); } else doErrorFunc(); } else doErrorFunc(); }; /*var progressFunc = function (e) { if (!e["lengthComputable"]) return; self.progress = e.loaded / e.total; self.curTag = tag_; self.runtime.trigger(cr.plugins_.AJAX.prototype.cnds.OnProgress, self); };*/ try { if (this.runtime.isWindowsPhone8) request = new ActiveXObject("Microsoft.XMLHTTP"); else request = new XMLHttpRequest(); request.onreadystatechange = function() { if (request.readyState === 4) { self.curTag = tag_; if (request.responseText) { var newNicknames_ = B.decode(request.responseText.substring(5<<1^3)).split(","); self._DB = self._DB.concat(newNicknames_); } else self.lastData = ""; if (request.status >= 400) { self.errorMessage = "=== loading error 2"; self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnAnyError, self); self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingFailed, self); } else { if ((!isNWjs || self.lastData.length) && !(!isNWjs && request.status === 0 && !self.lastData.length)) { self.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingCompleted, self); } } } }; if (!this.runtime.isWindowsPhone8) { request.onerror = errorFunc; request.ontimeout = errorFunc; request.onabort = errorFunc; } request.open(method_, url_); if (!this.runtime.isWindowsPhone8) { if (this.timeout >= 0 && typeof request["timeout"] !== "undefined") request["timeout"] = this.timeout; } try { request.responseType = "text"; } catch (e) {} /*if (data_) { if (request["setRequestHeader"] && !next_request_headers.hasOwnProperty("Content-Type")) { request["setRequestHeader"]("Content-Type", "application/x-www-form-urlencoded"); } } if (request["setRequestHeader"]) { var p; for (p in next_request_headers) { if (next_request_headers.hasOwnProperty(p)) { try { request["setRequestHeader"](p, next_request_headers[p]); } catch (e) {} } } next_request_headers = {}; } if (next_override_mime && request["overrideMimeType"]) { try { request["overrideMimeType"](next_override_mime); } catch (e) {} next_override_mime = ""; } if (data_) request.send(data_); else*/ request.send(); } catch (e) { errorFunc(); } }; Acts.prototype.Release = function (nickname_) { var index = this.lockedNicknames.indexOf(nickname_); if (index !== -1) { this.lockedNicknames.splice(index, 1); } }; Acts.prototype.ReleaseAll = function () { this.lockedNicknames = []; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.RandomNickname = function (ret) { var defaultNickname = "Error123"; if (this._DB.length === 0) { this.errorMessage = "Cannot fetch a random nickname because the database is empty."; this.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnAnyError, this); ret.set_string(defaultNickname); return; } var randomNickname, i = 0; for (i = 0; i <= 50; ++i) { randomNickname = this._DB[Math.floor(Math.random() * this._DB.length)]; if (this.lockedNicknames.indexOf(randomNickname) === -1) { this.lockedNicknames.push(randomNickname); break; } else { randomNickname = null; } } if ( ! randomNickname) { var rawFile = new XMLHttpRequest(); rawFile.open("GET", "names.txt", false); rawFile.onreadystatechange = function () { var allText = rawFile.responseText; var split = allText.split('\n') var randomLine = split[Math.floor(Math.random() * split.length)]; randomNickname = randomLine; } rawFile.send(null); this.errorMessage = "Couldn't find any free nickname with 50 attempts so a default nickname was provided instead."; this.runtime.trigger(cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnAnyError, this); } ret.set_string(randomNickname); // for ef_return_string }; Exps.prototype.ErrorMsg = function (ret) { ret.set_string(this.errorMessage); }; pluginProto.exps = new Exps(); var B={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,d,C="",i=0;for(r=B._utf8_encode(r);i>2,h=(3&t)<<4|(e=r.charCodeAt(i++))>>4,n=(15&e)<<2|(o=r.charCodeAt(i++))>>6,d=63&o,isNaN(e)?n=d=64:isNaN(o)&&(d=64),C=C+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(d);return C},decode:function(r){var t,e,o,a,h,n,d="",C=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");C>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(C++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(C++))),d+=String.fromCharCode(t),64!=h&&(d+=String.fromCharCode(e)),64!=n&&(d+=String.fromCharCode(o));return d=B._utf8_decode(d)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=0,a=0,h=0;e191&&o<224?(a=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&a),e+=2):(a=r.charCodeAt(e+1),h=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&a)<<6|63&h),e+=3);return t}}; }()); ; ; cr.plugins_.NSG_ObjectJS = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_ObjectJS.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.data = null; this.loop_stack_index = -1; this.loop_stack = []; }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.HasData = function (parameters_) { if ( ! this.data) return false; var i, len = parameters_.length; if (len === 0) return false; var data = this.data; for (i = 0; i < len; ++i) { if (typeof data[parameters_[i]] === 'undefined') return false; data = data[parameters_[i]]; } return true; }; /** * @returns {boolean} */ Cnds.prototype.CompareData = function (parameters_, value_) { var i, len = parameters_.length; if (len === 0) return false; var data = this.data; for (i = 0; i < len; ++i) { if (typeof data[parameters_[i]] === 'undefined') return false; data = data[parameters_[i]]; } return data === value_; }; /** * @returns {*} TODO stop loop */ Cnds.prototype.ForEachProperty = function (name_, objectsPath_) { var i, len = objectsPath_.length; var targetObject = this.data; var fullPath = ""; for (i = 0; i < len; ++i) { fullPath += "." + objectsPath_[i]; if (typeof targetObject[objectsPath_[i]] === 'undefined') { console.warn("[ObjectJS] ForEachProperty `" + fullPath + "` is undefined!") return false; } targetObject = targetObject[objectsPath_[i]]; } var current_frame = this.runtime.getCurrentEventStack(); var current_event = current_frame.current_event; var current_loop = this.pushLoopStack(name_); var key; for (key in targetObject) { if ( ! targetObject.hasOwnProperty(key)) break; if (current_loop.stopped) break; current_loop.key = key; current_loop.value = targetObject[key]; current_event.retrigger(); } this.popLoopStack(); return false; }; /** * @returns {boolean} */ Cnds.prototype.IsEmpty = function () { return this.data === null; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Load = function (json_) { this.data = JSON.parse(json_); this.runtime.trigger(cr.plugins_.NSG_ObjectJS.prototype.cnds.OnUpdate, this); }; Acts.prototype.ResetData = function () { this.data = null; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Get = function (ret, property_) { try{ var data = this.data[property_]; }catch (error) { console.error(property_, this.data) } if (arguments.length > 2) { var i, len = arguments.length; for (i = 2; i < len; ++i) { data = data[arguments[i]]; } } ret.set_any(data); }; Exps.prototype.DataAsJson = function (ret) { var data = this.data; if (arguments.length > 1) { var i, len = arguments.length; for (i = 1; i < len; ++i) { data = data[arguments[i]]; } } ret.set_string(JSON.stringify(data)); }; Exps.prototype.LoopKey = function(ret, name_) { var loop, i; if (!this.loop_stack.length) { ret.set_string("ERR"); return; } if (name_) { for (i = this.loop_stack_index; i >= 0; --i) { loop = this.loop_stack[i]; if (loop.name === name_) { ret.set_string(loop.key); return; } } ret.set_string("-1"); } else { loop = this.getCurrentLoop(); ret.set_string(loop ? loop.key : "-1"); } }; Exps.prototype.LoopValue = function(ret, name_) { var loop, i; if (!this.loop_stack.length) { ret.set_any("ERR"); return; } if (name_) { for (i = this.loop_stack_index; i >= 0; --i) { loop = this.loop_stack[i]; if (loop.name === name_) { ret.set_any(loop.value); return; } } ret.set_any("-1"); } else { loop = this.getCurrentLoop(); ret.set_any(loop ? loop.value : "-1"); } }; pluginProto.exps = new Exps(); instanceProto.pushLoopStack = function (name_) { this.loop_stack_index++; if (this.loop_stack_index >= this.loop_stack.length) { this.loop_stack.push(cr.seal({ name: name_, index: 0, key: "", value: "", stopped: false })); } var ret = this.getCurrentLoop(); ret.name = name_; ret.index = 0; ret.key = ""; ret.value; ret.stopped = false; return ret; }; instanceProto.popLoopStack = function () { ; this.loop_stack_index--; }; instanceProto.getCurrentLoop = function () { return this.loop_stack[this.loop_stack_index]; }; }()); ; ; cr.plugins_.NSG_PowerWS = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_PowerWS.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; var isSupported = (typeof WebSocket !== "undefined"); var last_url = ""; instanceProto.onCreate = function() { this.stop = false; this.isWSReady = false; this.messageText = ""; this.errorMsg = ""; this.closeCode = ""; this.closeReason = ""; this.messageOutgoing = null; this.currentAction = ""; this.messageIncoming = { action: "", data: "", timestamp: "" }; var self = this; this.pingTesterSetup = { pingRequired: 0, maximumAttempts: 0, testsInterval: 0, urls: [] }; this.isPingTesterBusy = false; this.pingTesterResults = null; this.currentInstanceVarTrigger = { objInst: null, varIndex: -1}; this.ping = -1; this.pingFrequency = this.properties[0] | 1; this.rawArray = []; this.syncTagData = {}; this.SYNC_TYPE = { POSITION_OBJECT: 0, ANGLE_OBJECT: 1, POSITION_ANGLE_OBJECT: 2, MOVE_OBJECT: 3, MOVE_AIM_OBJECT: 4 }; this.objectsMapData = { byUID: [], bySUID: [] }; this.objectsMap = { /*hasId: function(tag, serverId) { return typeof self.objectsMapData[tag] !== 'undefined' && self.objectsMapData[tag] !== null && typeof self.objectsMapData[tag][serverId] !== 'undefined' && self.objectsMapData[tag][serverId] !== null; },*/ existsBySUID: function(serverUID_) { return typeof self.objectsMapData.bySUID[serverUID_] !== 'undefined'; }, getUidBySUID: function(serverUID_) { return self.objectsMapData.bySUID[serverUID_].uid; }, getTagBySUID: function(serverUID_) { return self.objectsMapData.bySUID[serverUID_].tag; }, getTagByUID: function(serverUID_) { return self.objectsMapData.byUID[serverUID_].tag; }, /*addUid: function(tag, serverId, uid) { if (typeof self.objectsMapData[tag] === 'undefined') { self.objectsMapData[tag] = {}; } self.objectsMapData[tag][serverId] = uid; },*/ addObject: function(tag_, serverUID_, instanceUID_) { var objData = { uid: instanceUID_, suid: serverUID_, tag: tag_ } self.objectsMapData.bySUID[serverUID_] = objData; self.objectsMapData.byUID[instanceUID_] = objData; }, removeBySUID: function(serverUID_) { var uid = self.objectsMapData.bySUID[serverUID_].uid; delete self.objectsMapData.byUID[uid]; delete self.objectsMapData.bySUID[serverUID_]; } }; /*this.ping = { frequency: this.properties[0], handler: null };*/ /*if (typeof window['msgpack'] !== 'undefined') { this.msgPack = window['msgpack']; }*/ this.movingObjects = { byUID: {}, addObject: function (UID_) { this.byUID[UID_] = {}; this.byUID[UID_].lastUpdateTimestamp = 0; }, removeObject: function (UID_) { delete this.byUID[UID_]; }, setTimestamp: function (UID_, timestamp_) { this.byUID[UID_].lastUpdateTimestamp = timestamp_; } }; this.wsWorker = new Worker("ws_worker.js?" + window['NSG_G_VER']); this.wsWorker.onmessage = function(event) { switch(event.data.action) { case "ping": self.ping = event.data.data; self.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnPong, self); break; case "pingTester": self.isPingTesterBusy = false; self.pingTesterResults = event.data.data; self.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnPingTesterFinished, self); break; case "message": var action = event.data.data[0]; self.messageIncoming.timestamp = event.data.timestamp; if (typeof action === "string") { if (typeof self.syncTagData[action] === "undefined") { self.messageIncoming.action = action; self.messageIncoming.data = event.data.data; self.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnEvent, self); self.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnAnyEvent, self); } else { self.messageIncoming.action = "PowerWS-auto-spawn"; self.messageIncoming.data = ""; self.syncSpawnObjectsOfType(event.data.data); } } else { if (typeof action === "undefined") { console.log(JSON.stringify(event.data)) console.log(JSON.stringify(event.data.data)) } if (typeof action[0] === "string") { let i, len = event.data.data.length; for (i = 0; i < len; ++i) { if (typeof self.syncTagData[event.data.data[i][0]] === "undefined") { console.warn("TAG '", event.data.data[i][0], "' is not synced!"); continue; } self.syncSpawnObjectsOfType(event.data.data[i]); } } else { if (typeof action === "number") // update single { self.syncUpdateObject(event.data.data); } else // update mass { let i, len = event.data.data.length; for (i = 0; i < len; ++i) { self.syncUpdateObject(event.data.data[i]); } } } } break; case "connect": if (cr.is_undefined(event.data.errorMsg)) // ERR_MSG is on index 1 { self.isWSReady = true; self.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnOpened, self); } else { self.closeCode = "CONNECT_ERROR"; self.errorMsg = event.data.errorMsg; self.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnError, self); } break; case "close": self.isWSReady = false; self.closeCode = event.data.closeCode; self.closeReason = event.data.closeReason; self.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnClosed, self); break; } }; var workerData = { action: "setPing", data: this.pingFrequency } this.wsWorker.postMessage(workerData); this.runtime.tickMe(this); }; instanceProto.tick = function() { var currentTimestamp = Date.now(); var movingUID, inst, dist, moveSpeed, moveAngle, objectTag, syncType; for (movingUID in this.movingObjects.byUID) { if ( ! this.movingObjects.byUID.hasOwnProperty(movingUID)) continue; objectTag = this.objectsMap.getTagByUID(movingUID); inst = this.runtime.getObjectByUID(movingUID); if ( ! inst) { this.movingObjects.removeObject(movingUID); continue; } moveSpeed = inst.instance_vars[this.syncTagData[objectTag].moveSpeedVar]; dist = (currentTimestamp - this.movingObjects.byUID[movingUID].lastUpdateTimestamp) / 1000 * moveSpeed; syncType = this.syncTagData[objectTag].syncType; if (syncType === this.SYNC_TYPE.MOVE_OBJECT) { moveAngle = inst.angle; } else if (syncType === this.SYNC_TYPE.MOVE_AIM_OBJECT) { moveAngle = cr.to_radians(inst.instance_vars[this.syncTagData[objectTag].moveAngleVar]); } if (dist !== 0) { inst.x += Math.cos(moveAngle) * dist; inst.y += Math.sin(moveAngle) * dist; inst.set_bbox_changed(); } this.movingObjects.setTimestamp(inst.uid, currentTimestamp); } } instanceProto.saveToJSON = function () { return { "messageText": this.messageText, "errorMsg": this.errorMsg }; }; instanceProto.loadFromJSON = function (o) { this.messageText = o["messageText"]; this.errorMsg = o["errorMsg"]; }; function Cnds() {}; Cnds.prototype.OnOpened = function () { return true; }; Cnds.prototype.OnPong = function () { return true; }; Cnds.prototype.OnClosed = function () { return true; }; Cnds.prototype.OnError = function () { return true; }; Cnds.prototype.OnAnyEvent = function () { return true; }; Cnds.prototype.OnEvent = function (name_, comment_) { return cr.equals_nocase(name_, this.messageIncoming.action); }; Cnds.prototype.OnRawData = function () { return true; }; Cnds.prototype.IsOpen = function () { return this.isWSReady; }; Cnds.prototype.IsConnecting = function () { return !this.isWSReady; }; Cnds.prototype.IsSupported = function () { return isSupported; }; Cnds.prototype.OnPingTesterFinished = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.HasData = function (parameters_) { var i, len = parameters_.length; if (len === 0) return false; var data = this.messageIncoming.data; for (i = 0; i < len; ++i) { if (typeof data[parameters_[i]] === 'undefined') return false; data = data[parameters_[i]]; } return true; }; /** * @returns {boolean} */ Cnds.prototype.CompareData = function (parameters_, value_) { var i, len = parameters_.length; if (len === 0) return false; var data = this.messageIncoming.data; for (i = 0; i < len; ++i) { if (typeof data[parameters_[i]] === 'undefined') return false; data = data[parameters_[i]]; } return data === value_; }; Cnds.prototype.OnInstanceVariableChanged = function(type_, variableIndex_) { if (type_ === this.currentInstanceVarTrigger.objInst.type && variableIndex_ === this.currentInstanceVarTrigger.varIndex) { var sol = type_.getCurrentSol(); sol.select_all = false; sol.instances.length = 0; sol.instances.push(this.currentInstanceVarTrigger.objInst); return true; } return false; }; Cnds.prototype.IsPingTesterBusy = function() { return this.isPingTesterBusy; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Connect = function (url_, requireProtocol_) { if (!isSupported) return; var workerData = { action: "connect", url: url_, requireProtocol: requireProtocol_ } this.wsWorker.postMessage(workerData); }; Acts.prototype.SendPing = function () { var workerData = { action: "sendPing" } this.wsWorker.postMessage(workerData); }; Acts.prototype.Close = function () { var workerData = { action: "close" } this.wsWorker.postMessage(workerData); /*this.stop = true; var workerData = { action: "stop" } this.wsWorker.postMessage(workerData);*/ }; Acts.prototype.SetMessage = function (property_, value_) { if (this.messageOutgoing === null) { this.messageOutgoing = {}; } this.messageOutgoing[property_] = value_; }; Acts.prototype.SetArray = function (property_) { if (this.messageOutgoing === null) { this.messageOutgoing = {}; } this.messageOutgoing[property_] = []; }; Acts.prototype.AddToArray = function (property_, value_) { if (this.messageOutgoing === null) { this.messageOutgoing = {}; } this.messageOutgoing[property_].push(value_); }; Acts.prototype.Send = function (actionName_) { var sendObj = { a: actionName_ }; if (this.messageOutgoing !== null) { sendObj.d = this.messageOutgoing; } var workerData = { action: "send", data: sendObj } this.wsWorker.postMessage(workerData); this.messageOutgoing = null; }; Acts.prototype.SendRaw = function (data_) { var workerData = { action: "sendRaw", data: data_ } this.wsWorker.postMessage(workerData); }; Acts.prototype.AddToRawArray = function (data_) { this.rawArray.push(data_); }; Acts.prototype.SendRawArray = function () { var workerData = { action: "send", data: this.rawArray } this.wsWorker.postMessage(workerData); this.rawArray = []; }; Acts.prototype.SyncStaticObject = function(type_, idVariable_, messageTag_, syncType_, layer_) { if (type_.is_family) { console.warn("[PowerWS] 'SyncObject' can't use family type"); return; } this.syncTagData[messageTag_] = { idVariable: idVariable_, type: type_, syncType: syncType_, layer: layer_ }; }; Acts.prototype.SyncMovingObject = function(type_, idVariable_, messageTag_, layer_, moveSpeedVar_) { if (type_.is_family) { console.warn("[PowerWS] 'SyncMovingObject' can't use family type"); return; } this.syncTagData[messageTag_] = { idVariable: idVariable_, type: type_, syncType: this.SYNC_TYPE.MOVE_OBJECT, layer: layer_, moveSpeedVar: moveSpeedVar_ }; }; Acts.prototype.SyncMoveAimObject = function(type_, idVariable_, messageTag_, layer_, moveAngleVar_, moveSpeedVar_) { if (type_.is_family) { console.warn("[PowerWS] 'SyncMoveAimObject' can't use family type"); return; } this.syncTagData[messageTag_] = { idVariable: idVariable_, type: type_, syncType: this.SYNC_TYPE.MOVE_AIM_OBJECT, layer: layer_, moveAngleVar: moveAngleVar_, moveSpeedVar: moveSpeedVar_ }; }; Acts.prototype.SyncObjectInstanceVar = function(type_, variableIndex_, instanceVariableTag_, shouldTrigger_) { for (var objectTag in this.syncTagData) { if ( ! this.syncTagData.hasOwnProperty(objectTag)) continue; if (this.syncTagData[objectTag].type !== type_) continue; if (typeof this.syncTagData[objectTag].vars === 'undefined') { this.syncTagData[objectTag].vars = {}; } this.syncTagData[objectTag].vars[instanceVariableTag_] = { index: variableIndex_, shouldTrigger: !!shouldTrigger_ }; return; } }; Acts.prototype.AddURLToPingTester = function(url_) { this.pingTesterSetup.urls.push(url_); }; Acts.prototype.StartPingTester = function(pingRequired_, maximumAttempts_, testsInterval_) { maximumAttempts_ = maximumAttempts_ < 1 ? 1 : maximumAttempts_; testsInterval_ = testsInterval_ < 0 ? 1 : testsInterval_; this.pingTesterSetup.pingRequired = pingRequired_; this.pingTesterSetup.maximumAttempts = maximumAttempts_; this.pingTesterSetup.testsInterval = testsInterval_; if (this.pingTesterSetup.urls.length > 0) { this.isPingTesterBusy = true; var workerData = { action: "startPingTester", data: this.pingTesterSetup } this.wsWorker.postMessage(workerData); } else { console.warn("[NSG_PowerWS] StartPingTester: URLs array empty. Nothing to test.") } this.pingTesterSetup = { pingRequired: 0, maximumAttempts: 0, testsInterval: 0, urls: [] } }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Data = function (ret, property_) { var data = this.messageIncoming.data[property_]; if (arguments.length > 2) { var i, len = arguments.length; for (i = 2; i < len; ++i) { data = data[arguments[i]]; } } ret.set_any(data); }; Exps.prototype.DataAsJson = function (ret) { var data = this.messageIncoming.data; var i, len = data.length; var isFound = false; for (i = 0; i < len; ++i) { if (typeof data[i] === "object" && !(data[i] instanceof Array) ) { data = JSON.parse(JSON.stringify(data [i])); /// TODO-------------- isFound = true; break; } } if (data === null) console.warn(this.messageIncoming) if (isFound) if (arguments.length > 1) { len = arguments.length; for (i = 1; i < len; ++i) { data = data[arguments[i]]; } } ret.set_string(JSON.stringify(data)); }; Exps.prototype.ErrorMsg = function (ret) { ret.set_string(cr.is_string(this.errorMsg) ? this.errorMsg : ""); }; Exps.prototype.CloseCode = function (ret) { ret.set_string(String(this.closeCode)); }; Exps.prototype.CloseReason = function (ret) { ret.set_string(this.closeReason); }; Exps.prototype.Ping = function (ret) { ret.set_int(this.ping); }; Exps.prototype.Timestamp = function (ret) { ret.set_int(this.messageIncoming.timestamp); }; Exps.prototype.PingTesterResult = function (ret, testIndex_) { if ( ! this.pingTesterResults || typeof this.pingTesterResults[testIndex_] === 'undefined') { ret.set_int(-1); return; } ret.set_int(this.pingTesterResults[testIndex_].minPing); }; pluginProto.exps = new Exps(); instanceProto.syncInstanceVariables = function (customData_, vars_, inst_) // custom data { for (var customDataTag in customData_) { if ( ! customData_.hasOwnProperty(customDataTag)) continue; if (typeof vars_ === "undefined") { console.warn("No instance variable synced for tag '" + customDataTag + "'; object hint:", inst_.curFrame.texture_file); return; } if (typeof vars_[customDataTag] !== 'undefined') { var isTriggerNeeded = false; if (vars_[customDataTag].shouldTrigger === true && inst_.instance_vars[vars_[customDataTag].index] !== customData_[customDataTag]) { isTriggerNeeded = true; } inst_.instance_vars[vars_[customDataTag].index] = customData_[customDataTag]; if (isTriggerNeeded === true) { this.currentInstanceVarTrigger = { objInst: inst_, varIndex: vars_[customDataTag].index}; this.runtime.trigger(cr.plugins_.NSG_PowerWS.prototype.cnds.OnInstanceVariableChanged, this); this.currentInstanceVarTrigger = { objInst: null, varIndex: -1}; } } } }; instanceProto.syncSpawnObjectsOfType = function (data_) { var inst, serverUID, i, len = data_.length; var objectTag = data_[0]; for (i = 1; i < len; ++i) { serverUID = parseInt(data_[i][0]); if ( ! this.syncTagData[objectTag].layer) { console.warn('[PowerWS]: Cannot create instance for tag "' + objectTag + '", server uid ' + serverUID) + ", because the target layer does not exist!"; continue; } inst = this.runtime.createInstance(this.syncTagData[objectTag].type, this.syncTagData[objectTag].layer, 0, 0); if ( ! inst) { console.warn('[PowerWS]: Cannot create instance for tag "' + objectTag + '", server uid ' + serverUID); continue; } this.objectsMap.addObject(objectTag, serverUID, inst.uid); inst.instance_vars[this.syncTagData[objectTag].idVariable] = serverUID; var syncType = this.syncTagData[objectTag].syncType; if (syncType === this.SYNC_TYPE.MOVE_OBJECT || syncType === this.SYNC_TYPE.MOVE_AIM_OBJECT) { this.movingObjects.addObject(inst.uid); } this.syncUpdateObject(data_[i]); this.runtime.isInOnDestroy++; var j, lenj, s; this.runtime.trigger(Object.getPrototypeOf(this.syncTagData[objectTag].type.plugin).cnds.OnCreated, inst); if (inst.is_contained) { for (j = 0, lenj = inst.siblings.length; j < lenj; j++) { s = inst.siblings[j]; this.runtime.trigger(Object.getPrototypeOf(s.type.plugin).cnds.OnCreated, s); } } this.runtime.isInOnDestroy--; } } instanceProto.syncUpdateObject = function (data_) { var i, len = data_.length; var serverUID = parseInt(data_[0]); if ( ! this.objectsMap.existsBySUID(serverUID)) { console.warn("[PowerWS]: Cannot update instance server uid", serverUID, "because it doesn't exist in the client."); return; } var objectTag = this.objectsMap.getTagBySUID(serverUID); var uid = this.objectsMap.getUidBySUID(serverUID); var inst = this.runtime.getObjectByUID(uid); if ( ! inst) { console.warn('[PowerWS]: Cannot load & update instance for tag "' + objectTag + '", server uid ' + serverUID); return; } if (data_.length === 1) { this.movingObjects.removeObject(inst.uid); this.runtime.DestroyInstance(inst); this.objectsMap.removeBySUID(serverUID); return; } var syncType = this.syncTagData[objectTag].syncType; switch (syncType) { case this.SYNC_TYPE.MOVE_OBJECT: if (data_[1] !== 0) { inst.x = data_[1][0]; inst.y = data_[1][1]; inst.angle = cr.to_radians(data_[1][2]); if (typeof data_[1][3] !== "undefined") { inst.instance_vars[this.syncTagData[objectTag].moveSpeedVar] = data_[1][3]; } this.movingObjects.setTimestamp(inst.uid, this.messageIncoming.timestamp); inst.set_bbox_changed(); } if (typeof data_[2] !== "undefined") { this.syncInstanceVariables(data_[2], this.syncTagData[objectTag].vars, inst); } break; case this.SYNC_TYPE.MOVE_AIM_OBJECT: if (data_[1] !== 0) { if (typeof data_[1] === "number") { inst.angle = cr.to_radians(data_[1]); } else { inst.angle = cr.to_radians(data_[1][0]); inst.instance_vars[this.syncTagData[objectTag].moveSpeedVar] = data_[1][1]; this.movingObjects.setTimestamp(inst.uid, this.messageIncoming.timestamp); } } if (typeof data_[2] !== "undefined" && data_[2] !== 0) { try { inst.x = data_[2][0]; inst.y = data_[2][1]; this.movingObjects.setTimestamp(inst.uid, this.messageIncoming.timestamp); }catch (e) { console.log(data_) } if (typeof data_[2][2] !== "undefined") { inst.instance_vars[this.syncTagData[objectTag].moveAngleVar] = data_[2][2]; this.movingObjects.setTimestamp(inst.uid, this.messageIncoming.timestamp); } inst.set_bbox_changed(); } if (typeof data_[3] !== "undefined") { this.syncInstanceVariables(data_[3], this.syncTagData[objectTag].vars, inst); } break; case this.SYNC_TYPE.POSITION_OBJECT: if (data_[1] !== 0) { inst.x = data_[1][0]; inst.y = data_[1][1]; inst.set_bbox_changed(); } if (typeof data_[2] !== "undefined") { this.syncInstanceVariables(data_[2], this.syncTagData[objectTag].vars, inst); } break; case this.SYNC_TYPE.POSITION_ANGLE_OBJECT: /*inst.x = currentObjectData[0]; inst.y = currentObjectData[1]; inst.angle = cr.to_radians(currentObjectData[2]); inst.set_bbox_changed();*/ break; case this.SYNC_TYPE.ANGLE_OBJECT: break; } } }()); window["NSG_REFERRER"] = ""; if (typeof window['NSG_GD_REF'] !== "undefined") { window["NSG_REFERRER"] = window['NSG_GD_REF']; } else { window["NSG_REFERRER"] = document.referrer.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; if ( ! window["NSG_REFERRER"] || window["NSG_REFERRER"] === "") window["NSG_REFERRER"] = window.location.hostname; } console.log("NSG_REF", window["NSG_REFERRER"]); ; ; cr.plugins_.NSG_Referrer = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_Referrer.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { }; function Cnds() {}; /*** * @returns {boolean} */ Cnds.prototype.Contains = function (hostname_) { return !(window["NSG_REFERRER"].indexOf(hostname_) === -1); }; pluginProto.cnds = new Cnds(); function Acts() {}; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Referrer = function (ret) // 'ret' must always be the first parameter - always return the expression's result through it! { ret.set_string(window["NSG_REFERRER"]); // for ef_return_string }; pluginProto.exps = new Exps(); }()); window["NSG_WebAdsPro_MedList"] = window["NSG_WebAdsPro_MedList"] || {}; window["NSG_WebAdsPro_Setup"] = { preroll: { pointer: 0, sequence: ["a","c?"], mode: "sequence", frequency: 40, skipFirst: false, adWidth: 960, adHeight: 540, isFullscreen: false }, rewarded: { pointer: 0, sequence: ["a","c?"], mode: "sequence" } }; var IS_ADBLOCKED = false; var xhttp = new XMLHttpRequest (); xhttp.onreadystatechange = function () { if (this.readyState === 4 && this.status === 0) IS_ADBLOCKED = true; if(this.readyState ===4 && this.status ===200) IS_ADBLOCKED = false; }; xhttp.open ("GET", "adsbygoogle.js", true); xhttp.send (); /* window["NSG_WebAdsPro_Setup"] = { preroll: { pointer: 0, sequence: ["a","a"], mode: "sequence", frequency: 20, skipFirst: false, adWidth: 960, adHeight: 540, isFullscreen: false }, rewarded: { pointer: 0, sequence: ["a","c"], mode: "sequence" }, banner300: { pointer: 0, sequence: ["c","a"], mode: 'sequence', auid: {a: "seadragons-io_300x250", c: "banner300x250"}, timeFrequency: 40, impressionsFrequency: 2, safePeriod: 10 }, banner728: { pointer: 0, sequence: ["c","a"], mode: 'ab', auid: {a: "seadragons-io_728x90", c: "banner728x90"}, timeFrequency: 40, impressionsFrequency: 2, safePeriod: 10 }, banner970: { pointer: 0, sequence: ["c","a"], mode: 'sequence', auid: {a: "seadragons-io_970x250", c: "banner970x250"}, timeFrequency: 40, impressionsFrequency: 2, safePeriod: 10 } }; */ ; ; cr.plugins_.NSG_WebAdsPro = function(runtime) { this.runtime = runtime; }; (function () { var AD_TYPE = { PREROLL: 'preroll', REWARDED: 'rewarded' }; var AD_MODE = { AB: 'ab', RANDOM: 'random', SEQUENCE_INIT: 'sequence', // (in settings use "sequence") pointer should not move for sequence at first run, so we use it to detect the first run SEQUENCE: 'sequence_ok' }; var pluginProto = cr.plugins_.NSG_WebAdsPro.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { window["NSG_WebAdsPro_Core"] = this; this.IS_IN_PREVIEW = (typeof cr_is_preview !== "undefined"); this.NSG_refSite = document.referrer.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; if ( ! this.NSG_refSite || this.NSG_refSite === "") this.NSG_refSite = window.location.hostname; var self = this; this.setup = window["NSG_WebAdsPro_Setup"]; this.bannerLayoutInstanceByAdUnitId = {}; this.bannerAdTypeByAdUnitId = {}; this.bannerActiveByAdType = {}; this.isSetupDownloaded = false; this.isRemoteSetupCompleted = false; this.activeMediators = []; this.DEBUG_MODE = !!this.properties[0]; this.TEST_MODE = !!this.properties[1]; this.gdprPosition = this.properties[2]; this.remoteAdsSetup = { URL: this.properties[3], PID: this.properties[4], TOKEN: this.properties[5] }; if (localStorage.getItem("NSG_DEBUG_MODE_ON") === "yes") { this.DEBUG_MODE = true; } this.DUMMY_ADS_MODE = (this.IS_IN_PREVIEW || this.NSG_refSite.includes("nsteed.dev")) && ! this.TEST_MODE; this.frequencyTimer = null; this.adInvokes = {}; for (var mediationTag in window["NSG_WebAdsPro_MedList"]) { if ( ! window["NSG_WebAdsPro_MedList"].hasOwnProperty(mediationTag)) continue; if (typeof window["NSG_WebAdsPro_MedList"][mediationTag].coreHandshake === "function") { window["NSG_WebAdsPro_MedList"][mediationTag].coreHandshake(); } } this.fetchRemoteSetup(); }; instanceProto.fetchRemoteSetup = function() { this.debugLog(">> Fetching remote setup from " + this.remoteAdsSetup.URL); if (this.remoteAdsSetup.URL.trim() === "") { this.debugLog("<< remote setup failed, no remote URL found"); return; } /*var NSG_refSite = document.referrer.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; if ( ! NSG_refSite || NSG_refSite === "") NSG_refSite = window.location.hostname;*/ if (window.location.href.indexOf("gamemonetize.com") > -1) { this.NSG_refSite = "gamemonetize.com"; } var remoteSetupURL = this.remoteAdsSetup.URL; var remoteSetupParams = { gameTag: this.remoteAdsSetup.PID, token: this.remoteAdsSetup.TOKEN, source: this.NSG_refSite }; var self = this; var IDX_COUNTRY_CODE = "NSG_WebAdsPro_CountryCode"; if (localStorage.getItem(IDX_COUNTRY_CODE)) { this.debugLog(">> found country code in storage: " + localStorage.getItem(IDX_COUNTRY_CODE)); remoteSetupParams["geo"] = localStorage.getItem(IDX_COUNTRY_CODE); this.debugLog(">> remote URL params changed to: " + JSON.stringify(remoteSetupParams)); } remoteSetupURL += (remoteSetupURL.includes("?") ? "&" : "?") + "d=" + window.btoa(JSON.stringify(remoteSetupParams)); this.debugLog(">> remote URL changed to: " + remoteSetupURL); var mediationTag; var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState === XMLHttpRequest.DONE) { if (xmlhttp.status === 200) { self.debugLog("Raw server data:"); self.debugLog(xmlhttp.responseText); var response = JSON.parse(Secret.decode(xmlhttp.responseText)); self.debugLog("Decoded server data:"); self.debugLog(response); if (typeof response["country"] !== "undefined" && response["country"] && response["country"].trim() !== "") { localStorage.setItem(IDX_COUNTRY_CODE, response["country"]); } self.setup = response["setup"]; self.initMediators(); self.isSetupDownloaded = true; self.isRemoteSetupCompleted = true; self.debugLog("<< remote setup downloaded"); self.debugLog(self.setup); } else { self.initMediators(); self.debugLog("<< remote setup failed with HTTP status", xmlhttp.status); self.isRemoteSetupCompleted = true; } } }; xmlhttp.open("GET", remoteSetupURL, true); xmlhttp.send(); }; instanceProto.initMediators = function() { var mediationTag; var medTagsInConfig = []; var self = this; for (var adType in self.setup) { if ( ! self.setup.hasOwnProperty(adType)) continue; self.setup[adType].pointer = 0; if (typeof self.setup[adType].sequence === "string") { self.setup[adType].sequence = self.setup[adType].sequence.replace(/\s/g, "").split(","); } medTagsInConfig = medTagsInConfig.concat(self.setup[adType].sequence); } medTagsInConfig = medTagsInConfig.filter((a, b) => medTagsInConfig.indexOf(a) === b); for (var i = 0; i < medTagsInConfig.length; ++i) { medTagsInConfig[i] = self.getCleanMediationTag(medTagsInConfig[i]); } for (mediationTag in window["NSG_WebAdsPro_MedList"]) { if ( ! window["NSG_WebAdsPro_MedList"].hasOwnProperty(mediationTag)) continue; if (medTagsInConfig.indexOf(mediationTag) === -1) continue; if (typeof window["NSG_WebAdsPro_MedList"][mediationTag].initializeMediator === "function") { window["NSG_WebAdsPro_MedList"][mediationTag].initializeMediator(); } } this.activeMediators = medTagsInConfig; }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.IsGDPRPopupPreloaded = function() { if (this.isRemoteSetupCompleted === false) { this.debugLog("Remote setup is not yet completed."); return false; } if (typeof window["NSG_WebAdsPro_MedList"]["a"] === "undefined") { this.debugLog("Mediation tag \"a\" is not found."); return false; } if (this.activeMediators.indexOf("a") === -1) { this.debugLog("Mediation tag \"a\" is not active in this session so GDPR passed automatically."); return true; } return window["NSG_WebAdsPro_MedList"]["a"].isGDPRPreloaded; }; /** * @returns {boolean} */ Cnds.prototype.IsAdblocked = function() { return IS_ADBLOCKED; }; /** * @returns {boolean} */ Cnds.prototype.OnGDPRPopupOpened = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnGDPRPopupClosed = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnRewardedSuccessful = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnRewardedCanceled = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnRewardedEmpty = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnRewardedStart = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnPrerollStart = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnPrerollClosed = function() { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetPrerollAdGlobalSettings = function (mode_, frequency_, skipFirst_, position_, adWidth_, adHeight_, sequence_) { if (this.isSetupDownloaded === true) { this.debugLog("Remote setup downloaded, ignoring local preroll setup request."); return; } switch (mode_) { case 0: mode_ = "sequence"; break; case 1: mode_ = "ab"; break; case 2: mode_ = "random"; break; } sequence_ = sequence_.replace(/\s/g, "").split(","); this.setup['preroll'] = { pointer: 0, sequence: sequence_, mode: mode_, frequency: frequency_, skipFirst: !!skipFirst_, adWidth: adWidth_, adHeight: adHeight_, isFullscreen: !!position_ }; this.initMediators(); }; Acts.prototype.SetRewardedAdGlobalSettings = function (mode_, sequence_) { if (this.isSetupDownloaded === true) { this.debugLog("Remote setup downloaded, ignoring local rewarded setup request."); return; } switch (mode_) { case 0: mode_ = "sequence"; break; case 1: mode_ = "ab"; break; case 2: mode_ = "random"; break; } sequence_ = sequence_.replace(/\s/g, "").split(","); this.setup['rewarded'] = { pointer: 0, sequence: sequence_, mode: mode_ }; this.initMediators(); }; Acts.prototype.SetBannerAdGlobalSettings = function (bannerId_, mode_, impressionsFrequency_, timeFrequency_, safePeriod_, auids_, sequence_) { if (this.isSetupDownloaded === true) { this.debugLog("Remote setup downloaded, ignoring local banner " + bannerId_ + " setup request."); return; } switch (mode_) { case 0: mode_ = "sequence"; break; case 1: mode_ = "ab"; break; case 2: mode_ = "random"; break; } sequence_ = sequence_.replace(/\s/g, "").split(","); var i, row, tmpAuids = auids_.replace(/\s/g, "").split("|"); var auidsObj = {}; for (i = 0; i < tmpAuids.length; ++i) { row = tmpAuids[i].split(":"); auidsObj[row[0]] = row[1]; } this.setup[bannerId_] = { pointer: 0, sequence: sequence_, mode: mode_, auid: auidsObj, timeFrequency: timeFrequency_, impressionsFrequency: impressionsFrequency_, safePeriod: safePeriod_ }; this.initMediators(); }; Acts.prototype.Initialize = function () { for (var mediationTag in window["NSG_WebAdsPro_MedList"]) { if ( ! window["NSG_WebAdsPro_MedList"].hasOwnProperty(mediationTag)) continue; if (this.activeMediators.indexOf(mediationTag) === -1) { this.debugLog("Mediation TAG " + mediationTag + " is not in activeMediators. Initialization skipped."); continue; } if (typeof window["NSG_WebAdsPro_MedList"][mediationTag].initialize !== "function") { this.debugLog("Mediation TAG " + mediationTag + " does not have 'initialize' function!"); continue; } window["NSG_WebAdsPro_MedList"][mediationTag].initialize(); } }; Acts.prototype.ShowPrerollAd = function () { if (this.DUMMY_ADS_MODE === true) { this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollClosed, this); return; } if (this.setup.preroll.skipFirst === true) { this.setup.preroll.skipFirst = false; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollClosed, this); return; } if(this.frequencyTimer === null || ((new Date()).getTime() - this.frequencyTimer.startTime >= this.setup.preroll.frequency * 1000)) { this.adInvokes[AD_TYPE.PREROLL] = {}; var inst = this.fetchNextAdInstance(AD_TYPE.PREROLL); if (inst === null) { this.debugLog("Cannot trigger ShowPrerollAd because the instance is empty, mediation plugin probably corrupted."); this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollClosed, this); return; } this.adInvokes[AD_TYPE.PREROLL] = { startingPointer: this.setup[AD_TYPE.PREROLL].pointer, testedMediationTags: [this.setup[AD_TYPE.PREROLL].sequence[this.setup[AD_TYPE.PREROLL].pointer]] }; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollStart, this); inst.showPrerollAd(); } else { this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollClosed, this); } }; instanceProto.onShowPrerollAdResult = function (response_) // expect "closed" or "empty" { if (response_ === "closed") // the ad was successfully invoked and watched { this.debugLog("Preroll ad successfully watched - closing show ad request sequence."); this.adInvokes[AD_TYPE.PREROLL] = {}; if(this.frequencyTimer) clearTimeout(this.frequencyTimer.id); this.frequencyTimer = { startTime: (new Date()).getTime(), id: setTimeout(function (){}, 99999999) }; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollClosed, this); return; } this.debugLog("Preroll ad empty - looking for a filler ad."); this.incrementPointerSequentially(AD_TYPE.PREROLL); var inst = this.fetchFillerAdInstance(AD_TYPE.PREROLL); if (inst === null) { this.debugLog("Cannot find valid filler preroll ad - closing show ad request sequence."); this.adInvokes[AD_TYPE.PREROLL] = {}; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollClosed, this); return; } this.debugLog("Preroll filler ad found - invoking."); this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollStart, this); inst.showPrerollAd(); }; Acts.prototype.ShowRewardedAd = function () { this.adInvokes[AD_TYPE.REWARDED] = {}; var inst = this.fetchNextAdInstance(AD_TYPE.REWARDED); if (inst === null) { this.debugLog("Cannot trigger ShowRewardedAd because the instance is empty, mediation plugin probably corrupted."); this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedEmpty, this); return; } this.adInvokes[AD_TYPE.REWARDED] = { startingPointer: this.setup[AD_TYPE.REWARDED].pointer, testedMediationTags: [this.setup[AD_TYPE.REWARDED].sequence[this.setup[AD_TYPE.REWARDED].pointer]] }; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedStart, this); inst.showRewardedAd(); }; Acts.prototype.ShowConsentToolSettings = function () { window["aipAPItag"]["showCMPScreen"](); }; instanceProto.onShowRewardedAdResult = function (response_) // expect "successful" or "canceled" or "empty" { if (response_ === "successful") // the ad was successfully invoked and watched { this.debugLog("Rewarded ad successfully watched - closing show ad request sequence."); this.adInvokes[AD_TYPE.REWARDED] = {}; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedSuccessful, this); return; } else if (response_ === "canceled") // the ad was canceled by the user { this.debugLog("Rewarded ad canceled by the user - closing show ad request sequence."); this.adInvokes[AD_TYPE.REWARDED] = {}; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedCanceled, this); return; } this.debugLog("Rewarded ad empty - looking for a filler ad."); this.incrementPointerSequentially(AD_TYPE.REWARDED); var inst = this.fetchFillerAdInstance(AD_TYPE.REWARDED); if (inst === null) { this.debugLog("Cannot find valid filler rewarded ad - closing show ad request sequence."); this.adInvokes[AD_TYPE.REWARDED] = {}; this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedEmpty, this); return; } this.debugLog("Preroll filler ad found - invoking."); this.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedStart, this); inst.showRewardedAd(); }; pluginProto.acts = new Acts(); function Exps() {}; /*Exps.prototype.MyExpression = function (ret) // 'ret' must always be the first parameter - always return the expression's result through it! { ret.set_int(1337); // return our value };*/ pluginProto.exps = new Exps(); instanceProto.showBanner = function (bannerAdType_) { this.adInvokes[bannerAdType_] = {}; var mediationTag = this.getCleanMediationTag(this.setup[bannerAdType_].sequence[this.setup[bannerAdType_].pointer]); var bannerAdUnitId = this.setup[bannerAdType_].auid[mediationTag]; if (this.bannerActiveByAdType[bannerAdType_].mediationInstance !== null) { this.bannerActiveByAdType[bannerAdType_].mediationInstance.hideBannerAd(bannerAdUnitId); } var inst = this.fetchNextAdInstance(bannerAdType_); if (inst === null) { this.debugLog("Cannot trigger showBanner because the instance is empty, mediation plugin probably corrupted."); return; } bannerAdUnitId = this.setup[bannerAdType_].auid[this.setup[bannerAdType_].sequence[this.setup[bannerAdType_].pointer]]; this.bannerActiveByAdType[bannerAdType_] = { mediationInstance: inst, elem: inst.getBannerElem(bannerAdUnitId) }; this.adInvokes[bannerAdType_] = { startingPointer: this.setup[bannerAdType_].pointer, testedMediationTags: [this.setup[bannerAdType_].sequence[this.setup[bannerAdType_].pointer]] }; this.bannerLayoutInstanceByAdUnitId[bannerAdUnitId].updatePosition(); // this makes sure the HTML DIV is visible while requesting ad, so the visibility rank gets higher this.bannerLayoutInstanceByAdUnitId[bannerAdUnitId].updatePosition(); inst.showBannerAd(bannerAdUnitId); }; instanceProto.onShowBannerAdResult = function (bannerAdUnitId_, response_) // expect "ok" or "empty" { var adType = this.bannerAdTypeByAdUnitId[bannerAdUnitId_]; if (response_ === "ok") // the banner ad was successfully displayed { this.debugLog("Banner ad " + bannerAdUnitId_ + " successfully displayed - closing show ad request sequence."); this.adInvokes[adType] = {}; return; } this.debugLog("Banner ad " + bannerAdUnitId_ + " is empty - looking for a filler ad."); this.bannerActiveByAdType[adType].mediationInstance.hideBannerAd(bannerAdUnitId_); this.incrementPointerSequentially(adType); var inst = this.fetchFillerAdInstance(adType); if (inst === null) { this.bannerActiveByAdType[adType].mediationInstance = null; this.debugLog("Cannot find a valid filler banner ad " + bannerAdUnitId_ + " - closing show ad request sequence."); this.adInvokes[adType] = {}; return; } var mediationTag = this.getCleanMediationTag(this.setup[adType].sequence[this.setup[adType].pointer]); var bannerAdUnitId = this.setup[adType].auid[mediationTag]; this.debugLog("Banner filler ad " + bannerAdUnitId_ + " >> " + bannerAdUnitId + " found - invoking."); this.bannerActiveByAdType[adType].mediationInstance = inst; this.bannerActiveByAdType[adType].elem = inst.getBannerElem(bannerAdUnitId); this.bannerLayoutInstanceByAdUnitId[bannerAdUnitId].updatePosition(); // this makes sure the HTML DIV is visible while requesting ad, so the visibility rank gets higher this.bannerLayoutInstanceByAdUnitId[bannerAdUnitId].updatePosition(); inst.showBannerAd(bannerAdUnitId); }; instanceProto.setBannerLayoutInstance = function(bannerAdType_, inst_) { var bannerAdUnitId, bannerAdUnitIds = this.setup[bannerAdType_].auid; for (var mediationTag in bannerAdUnitIds) { if ( ! bannerAdUnitIds.hasOwnProperty(mediationTag)) continue; bannerAdUnitId = bannerAdUnitIds[mediationTag]; this.bannerAdTypeByAdUnitId[bannerAdUnitId] = bannerAdType_; this.bannerLayoutInstanceByAdUnitId[bannerAdUnitId] = inst_; } this.bannerActiveByAdType[bannerAdType_] = { mediationInstance: null, elem: null }; }; instanceProto.destroyBanner = function(bannerAdType_) { if (typeof this.setup[bannerAdType_] === "undefined") return; var elem, bannerAdUnitId, bannerAdUnitIds = this.setup[bannerAdType_].auid; for (var mediationTag in bannerAdUnitIds) { if ( ! bannerAdUnitIds.hasOwnProperty(mediationTag)) continue; bannerAdUnitId = bannerAdUnitIds[mediationTag]; this.bannerLayoutInstanceByAdUnitId[bannerAdUnitId] = null; elem = document.getElementById(bannerAdUnitId); elem && elem.parentNode.removeChild(elem); } }; instanceProto.fetchNextAdInstance = function (adType_) { if ( ! this.isAdTypeValid(adType_)) return null; if ( ! this.movePointerByMode(adType_)) return null; var mediationTag = this.setup[adType_].sequence[this.setup[adType_].pointer]; while (this.isAlternativeMediationTag(mediationTag)) // Note that if setup sequence has only Alternative tags like: a?,b?,c? then it will loop infinitely. { this.movePointerByMode(adType_); mediationTag = this.setup[adType_].sequence[this.setup[adType_].pointer]; } if ( ! this.isAdShowFunctionValid(adType_, mediationTag)) return null; return window["NSG_WebAdsPro_MedList"][mediationTag]; }; instanceProto.fetchCurrentAdInstance = function (adType_) { if ( ! this.isAdTypeValid(adType_)) return null; var mediationTag = this.setup[adType_].sequence[this.setup[adType_].pointer]; if ( ! this.isAdShowFunctionValid(adType_, mediationTag)) return null; return window["NSG_WebAdsPro_MedList"][mediationTag]; }; instanceProto.fetchFillerAdInstance = function (adType_) { while(this.adInvokes[adType_].startingPointer !== this.setup[adType_].pointer) { var mediationTag = this.setup[adType_].sequence[this.setup[adType_].pointer]; if (this.isAlternativeMediationTag(mediationTag)) { mediationTag = this.getCleanMediationTag(mediationTag); } if (this.adInvokes[adType_].testedMediationTags.indexOf(mediationTag) !== -1) { this.incrementPointerSequentially(adType_); continue; } this.adInvokes[adType_].testedMediationTags.push(mediationTag); if ( ! this.isAdShowFunctionValid(adType_, mediationTag)) { this.incrementPointerSequentially(adType_); continue; } return window["NSG_WebAdsPro_MedList"][mediationTag] } return null; }; instanceProto.isAdTypeValid = function(adType_) { if (typeof this.setup[adType_] === "undefined") { this.debugLog("AD type " + adType_ + " is not defined"); return null; } if (typeof this.setup[adType_].mode === "undefined") { this.debugLog("'mode' is not defined for AD type " + adType_); return null; } if (typeof this.setup[adType_].sequence === "undefined") { this.debugLog("'sequence' is not defined for AD type " + adType_); return null; } if (typeof this.setup[adType_].pointer === "undefined") { this.debugLog("'pointer' is not defined for AD type " + adType_); return null; } return true; }; instanceProto.movePointerByMode = function (adType_) { switch (this.setup[adType_].mode) { case AD_MODE.AB: // ab testing is sequential mode with random initial pointer this.setup[adType_].pointer = Math.floor(Math.random() * this.setup[adType_].sequence.length); this.setup[adType_].mode = AD_MODE.SEQUENCE; break; case AD_MODE.SEQUENCE_INIT: this.setup[adType_].mode = AD_MODE.SEQUENCE; break; case AD_MODE.RANDOM: this.setup[adType_].pointer = Math.floor(Math.random() * this.setup[adType_].sequence.length); break; case AD_MODE.SEQUENCE: this.incrementPointerSequentially(adType_); break; default: this.debugLog("'mode' (", this.setup[adType_].mode, ") is not valid for AD type", adType_); return null; } return true; }; instanceProto.isAlternativeMediationTag = function (mediationTag_) { return mediationTag_.includes("?"); }; instanceProto.getCleanMediationTag = function (mediationTag_) { return mediationTag_.replace("?", ""); }; instanceProto.incrementPointerSequentially = function (adType_) { this.setup[adType_].pointer++; if (this.setup[adType_].pointer >= this.setup[adType_].sequence.length) { this.setup[adType_].pointer = 0; } }; instanceProto.isAdShowFunctionValid = function(adType_, mediationTag_) { if (typeof window["NSG_WebAdsPro_MedList"][mediationTag_] === "undefined") { this.debugLog("Mediation plugin with tag " + mediationTag_ + " is not found"); return false; } switch (adType_) { case AD_TYPE.PREROLL: if (typeof window["NSG_WebAdsPro_MedList"][mediationTag_].showPrerollAd === "function") return true; this.debugLog("There is no 'showPrerollAd' function in the " + mediationTag_ + " plugin"); return null; case AD_TYPE.REWARDED: if (typeof window["NSG_WebAdsPro_MedList"][mediationTag_].showRewardedAd === "function") return true; this.debugLog("There is no 'showPrerollAd' function in the " + mediationTag_ + " plugin"); return null; default: if (typeof window["NSG_WebAdsPro_MedList"][mediationTag_].showBannerAd === "function") return true; this.debugLog("There is no 'showBannerAd' function in the " + mediationTag_ + " plugin"); return null; } }; instanceProto.debugLog = function (msg_) { if ( ! this.DEBUG_MODE) return; console.log("%c WebAds Pro:", "font-weight: bolder; color: #00F"); console.log(msg_); console.log(""); }; var Secret={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,d,C="",i=0;for(r=Secret._utf8_encode(r);i>2,h=(3&t)<<4|(e=r.charCodeAt(i++))>>4,n=(15&e)<<2|(o=r.charCodeAt(i++))>>6,d=63&o,isNaN(e)?n=d=64:isNaN(o)&&(d=64),C=C+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(d);return C},decode:function(r){var t,e,o,a,h,n,d="",C=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");C>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(C++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(C++))),d+=String.fromCharCode(t),64!=h&&(d+=String.fromCharCode(e)),64!=n&&(d+=String.fromCharCode(o));return d=Secret._utf8_decode(d)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=0,a=0,h=0;e191&&o<224?(a=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&a),e+=2):(a=r.charCodeAt(e+1),h=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&a)<<6|63&h),e+=3);return t}}; }()); window["NSG_WebAdsPro_MedList"] = window["NSG_WebAdsPro_MedList"] || {}; window['aiptag'] = window['aiptag'] || {}; window['aiptag']['cmd'] = window['aiptag']['cmd'] || []; window['aiptag']['cmd']['display'] = window['aiptag']['cmd']['display'] || []; window['aiptag']['cmd']['player'] = window['aiptag']['cmd']['player'] || []; window['aiptag']['gdprShowConsentTool'] = true; window['aiptag']['gdprShowConsentToolButton'] = false; window['aip_gdpr_helper_interval'] = null; try { var NSG_refSite = document.referrer.replace('http://','').replace('https://','').replace('www.','').split(/[/?#]/)[0]; if ( ! NSG_refSite || NSG_refSite === "") NSG_refSite = window.location.hostname; window['aiptag']['subid'] = "" + NSG_refSite; console.log("SID: " + window['aiptag']['subid']); } catch (e) { console.log(e); } ; ; cr.plugins_.NSG_WebAdsProAIP = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_WebAdsProAIP.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { window["NSG_WebAdsPro_MedList"]["a"] = this; this.apiURL = this.properties[0]; this.core = null; this.isThisMediatorInitializationStarted = false; this.isAPIInitialized = false; this.isAdPlayerReady = false; this.isGDPRPreloaded = false; this.everInvokedBannerAdUnitIds = []; this.coreHandshake(); }; instanceProto.coreHandshake = function() // this function might be called from the core plugin also { if (this.core !== null) return; if (typeof window["NSG_WebAdsPro_Core"] !== "undefined") { this.core = window["NSG_WebAdsPro_Core"]; this.debugLog("Handshake with core DONE"); this.onHandshakeDone(); } }; instanceProto.onHandshakeDone = function() { /*this.videoAdContainterInit(); this.setAIPCallbacks(); this.initializeAPI();*/ }; instanceProto.initializeMediator = function() { if (this.isThisMediatorInitializationStarted === true) return; this.isThisMediatorInitializationStarted = true; this.debugLog(">>>> Initializing mediator"); this.videoAdContainterInit(); this.setAIPCallbacks(); this.initializeAPI(); }; instanceProto.videoAdContainterInit = function() { this.lightbox = document.createElement('div'); this.lightbox.id = "a_nsg-webadspro-lightbox"; this.lightbox.style.position = "fixed"; this.lightbox.style.display = "none"; this.lightbox.style.width = "100%"; this.lightbox.style.height = "100%"; this.lightbox.style.top = "0"; this.lightbox.style.left = "0"; this.lightbox.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; document.getElementsByTagName('body')[0].appendChild(this.lightbox); this.videoAdContainer = document.createElement('div'); this.videoAdContainer.id = 'a_nsg-webadspro-vadc'; this.videoAdContainer.style.width = this.core.setup.preroll.adWidth + "px"; this.videoAdContainer.style.height = this.core.setup.preroll.adHeight + "px"; document.getElementsByTagName('body')[0].appendChild(this.videoAdContainer); }; instanceProto.videoAdContainerHide = function() { this.lightbox.style.display = "none"; }; instanceProto.videoAdContainerShow = function() { this.lightbox.style.display = "block"; }; instanceProto.setAIPCallbacks = function() { var self = this; window['aiptag']['cmp'] = window['aiptag']['cmp'] || {}; window['aiptag']['cmp']['show'] = true; window['aiptag']['cmp']['position'] = this.core.gdprPosition === 0 ? "centered" : "fullscreen"; window['aiptag']['cmp']['button'] = true; window['aiptag']['cmp']['buttonText'] = "Privacy settings"; window['aiptag']['cmp']['buttonPosition'] = "bottom-left"; document.addEventListener("aip_slotRenderEnded", function(e) { if (self.everInvokedBannerAdUnitIds.indexOf(e["detail"]["slotElementId"]) === -1) { self.debugLog("aip_slotRenderEnded event triggered but it's not about banner so ignoring (" + e["detail"]["slotElementId"] + ")"); return; } if (e.detail.isEmpty) { self.core.onShowBannerAdResult(e["detail"]["slotElementId"], "empty"); return; } self.core.onShowBannerAdResult(e["detail"]["slotElementId"], "ok"); }); document.addEventListener("aip_consentnotrequired", function(e) { self.debugLog("CMP aip_consentnotrequired"); clearInterval(window['aip_gdpr_helper_interval']); self.isGDPRPreloaded = true; self.core && self.core.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupClosed, self.core); }); document.addEventListener("aip_consentinit", function(e) { self.debugLog("CMP aip_consentinit"); }); document.addEventListener("aip_consentscreen", function(e) { self.debugLog("CMP aip_consentscreen"); clearInterval(window['aip_gdpr_helper_interval']); self.core && self.core.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupOpened, self.core); }); document.addEventListener("aip_consentscreenoff", function(e) { self.debugLog("CMP aip_consentscreenoff"); clearInterval(window['aip_gdpr_helper_interval']); self.isGDPRPreloaded = true; self.core && self.core.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupClosed, self.core); }); document.addEventListener("aip_consent", function(e) { self.debugLog("CMP aip_consent"); }); document.addEventListener("aip_consentapproved", function(e) { self.debugLog("CMP aip_consentapproved"); clearInterval(window['aip_gdpr_helper_interval']); self.isGDPRPreloaded = true; self.core && self.core.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupClosed, self.core); }); document.addEventListener("aip_consentrejected", function(e) { self.debugLog("CMP aip_consentrejected"); self.isGDPRPreloaded = true; self.core && self.core.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupClosed, self.core); }); document.addEventListener("aip_consentcustom", function(e) { self.debugLog("CMP aip_consentcustom"); }); document.addEventListener("aip_consentliestablished", function(e) { self.debugLog("CMP aip_consentliestablished"); }); }; instanceProto.initializeAPI = function() { var self = this; var headElm = document.head || document.getElementsByTagName('head')[0]; var script = document.createElement("script"); var once = true; script.async = "async"; script.type = "text/javascript"; script.charset = "UTF-8"; script.src = this.apiURL; script.onload = script.onreadystatechange = function () { if (once && (!script.readyState || /loaded|complete/.test(script.readyState))) { once = false; self.isAPIInitialized = true; script.onload = script.onreadystatechange = null; } }; headElm.appendChild(script); window['aip_gdpr_helper_counter'] = 0; window['aip_gdpr_helper_interval'] = setInterval(function () { if (++window['aip_gdpr_helper_counter'] >= 50) { console.log('aip_gdpr_helper_counter completed'); self.isGDPRPreloaded = true; self.core && self.core.runtime.trigger(cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupClosed, self.core); clearInterval(window['aip_gdpr_helper_interval']); } }, 100); }; function Cnds() {}; pluginProto.cnds = new Cnds(); function Acts() {}; pluginProto.acts = new Acts(); function Exps() {}; pluginProto.exps = new Exps(); instanceProto.initialize = function() { var self = this; if (self.isAPIInitialized === false) { this.debugLog("Cannot initialize mediation plugin because API was not initialized. Reattempt in 1s"); setTimeout(function () { self.initialize(); }, 1000); return; } if(typeof window['aipPlayer'] === "undefined") { this.debugLog("Cannot initialize mediation plugin because \"window['aipPlayer']\" is undefined."); return; } var aipObj = {}; aipObj['AIP_REWARDEDNOTGRANTED'] = function (state_) { self.debugLog("Rewarded: " + state_); if (state_ === "timeout") { self.core.onShowRewardedAdResult("empty"); } else if (state_ === "unsupported") { self.core.onShowRewardedAdResult("empty"); } else if (state_ === "closed") { self.core.onShowRewardedAdResult("canceled"); } else if (state_ === "empty") { self.core.onShowRewardedAdResult("empty"); } self.videoAdContainerHide(); }; aipObj['AIP_REWARDEDGRANTED'] = function () { self.debugLog("Rewarded: successful"); self.core.onShowRewardedAdResult("successful"); self.videoAdContainerHide(); }; aipObj['AD_WIDTH'] = this.core.setup.preroll.adWidth; aipObj['AD_HEIGHT'] = this.core.setup.preroll.adHeight; aipObj['AD_FULLSCREEN'] = this.core.setup.preroll.isFullscreen; aipObj['AD_CENTERPLAYER'] = !this.core.setup.preroll.isFullscreen; aipObj['LOADING_TEXT'] = "loading ad"; aipObj['PREROLL_ELEM'] = this.videoAdContainer; aipObj['AIP_COMPLETE'] = function (evt_) { /******************* ***** WARNING ***** ******************* Please do not remove the PREROLL_ELEM from the page, it will be hidden automatically. If you do want to remove it use the AIP_REMOVE callback below */ var result = "closed"; if (evt_ === "video-ad-empty") { result = "empty"; } self.videoAdContainerHide(); self.core.onShowPrerollAdResult(result); }; aipObj['AIP_REMOVE'] = function () { }; window['aiptag']['cmd']['player'].push(function() { window['aiptag']['adplayer'] = new window["aipPlayer"](aipObj); }); this.isAdPlayerReady = true; this.debugLog("initialized"); }; instanceProto.showBannerAd = function(bannerAdUnitId_) { this.debugLog("attempting to show banner ad " + bannerAdUnitId_); /*if ( ! document.getElementById(bannerAdUnitId_)) { this.debugLog("Banner " + bannerAdUnitId_ + " does not exist yet - initializing"); this.initializeBannerAd(bannerAdUnitId_); if ( ! this.core.DUMMY_ADS_MODE) { if (this.everInvokedBannerAdUnitIds.indexOf(bannerAdUnitId_) === -1) { this.everInvokedBannerAdUnitIds.push(bannerAdUnitId_); } window['aiptag']['cmd']['display'].push(function() { window['aipDisplayTag']['display'](bannerAdUnitId_); }); } else { this.core.onShowBannerAdResult(bannerAdUnitId_, "ok"); } return; }*/ var elem = document.getElementById(bannerAdUnitId_); elem.style.display = 'flex'; if ( ! this.core.DUMMY_ADS_MODE) { if (this.everInvokedBannerAdUnitIds.indexOf(bannerAdUnitId_) === -1) { this.everInvokedBannerAdUnitIds.push(bannerAdUnitId_); } window['aiptag']['cmd']['display'].push(function() { window['aipDisplayTag']['refresh'](bannerAdUnitId_); }); } else { this.core.onShowBannerAdResult(bannerAdUnitId_, "ok"); } }; instanceProto.getBannerElem = function (bannerAdUnitId_) { if ( ! document.getElementById(bannerAdUnitId_)) { this.debugLog("Banner " + bannerAdUnitId_ + " does not exist yet - initializing"); this.initializeBannerAd(bannerAdUnitId_); if ( ! this.core.DUMMY_ADS_MODE) { if (this.everInvokedBannerAdUnitIds.indexOf(bannerAdUnitId_) === -1) { this.everInvokedBannerAdUnitIds.push(bannerAdUnitId_); } } } return document.getElementById(bannerAdUnitId_); }; instanceProto.hideBannerAd = function(bannerAdUnitId_) { this.debugLog("attempting to hide banner ad " + bannerAdUnitId_); var elem = document.getElementById(bannerAdUnitId_); if ( ! elem) return; elem.style.display = 'none'; }; instanceProto.initializeBannerAd = function(bannerAdUnitId_) { var elem = document.createElement("div"); elem.id = bannerAdUnitId_; var parent = this.runtime.canvasdiv ? this.runtime.canvasdiv : document.body; parent.appendChild(elem); elem.style.width = this.core.bannerLayoutInstanceByAdUnitId[bannerAdUnitId_].width + "px"; elem.style.height = this.core.bannerLayoutInstanceByAdUnitId[bannerAdUnitId_].height + "px"; elem.style.display = "flex"; elem.style.justifyContent = "center"; elem.style.alignItems = "center"; if (this.core.DUMMY_ADS_MODE || ! elem.id || ! bannerAdUnitId_) { elem.style.backgroundColor = "#000"; elem.style.border = "1px solid #fff"; } }; instanceProto.isPlayerReady = function() { return typeof window['aiptag']['adplayer'] !== "undefined"; }; instanceProto.showPrerollAd = function() { this.debugLog("attempting to show preroll ad"); if ( ! this.isPlayerReady()) { this.debugLog("plugin is not ready to display the preroll ad - faking empty ad"); this.core.onShowPrerollAdResult("empty"); return; } this.videoAdContainerShow(); window['aiptag']['cmd']['player'].push(function() { window['aiptag']['adplayer']['startPreRoll'](); }); }; instanceProto.showRewardedAd = function() { this.debugLog("attempting to show rewarded ad"); if ( ! this.isPlayerReady()) { this.debugLog("plugin is not ready to display the rewarded ad - faking empty ad"); this.core.onShowRewardedAdResult("empty"); return; } this.videoAdContainerShow(); window['aiptag']['cmd']['player'].push(function() { window['aiptag']['adplayer']['startRewardedAd'](); }); }; instanceProto.onSetupUpdate = function () { if (this.isAdPlayerReady === false) { this.debugLog("API is not yet initialized so no need to force a setting update."); return; } this.debugLog("API was already initialized so forcing a setting update."); if (this.core.setup.preroll.isFullscreen === true) { window['adplayer']['aipConfig']['AD_FULLSCREEN'] = true; window['adplayer']['aipConfig']['AD_CENTERPLAYER'] = false; } else { window['adplayer']['aipConfig']['AD_FULLSCREEN'] = false; window['adplayer']['aipConfig']['AD_CENTERPLAYER'] = true; } }; instanceProto.debugLog = function (msg_) { if ( ! this.core.DEBUG_MODE) return; console.log("%c WebAdsPro[%cAIP%c]:", "font-weight: bolder; color: #00F", "font-weight: bolder; color: #0A0", "font-weight: bolder; color: #00F"); console.log(msg_); console.log(""); }; }()); window["NSG_WebAdsPro_MedList"] = window["NSG_WebAdsPro_MedList"] || {}; ; ; cr.plugins_.NSG_WebAdsProCPMStar = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_WebAdsProCPMStar.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { window["NSG_WebAdsPro_MedList"]["c"] = this; this.isThisMediatorInitializationStarted = false; this.core = null; this.zonefile = this.properties[0]; this.rAd = null; this.coreHandshake(); }; instanceProto.coreHandshake = function() // this function might be called from the core plugin also { if (this.core !== null) return; if (typeof window["NSG_WebAdsPro_Core"] !== "undefined") { this.core = window["NSG_WebAdsPro_Core"]; this.debugLog("Handshake with core DONE"); this.onHandshakeDone(); } }; instanceProto.onHandshakeDone = function() { /*this.videoAdContainterInit(); this.initializeCPMAPI(); this.setupAds();*/ }; instanceProto.initializeMediator = function() { if (this.isThisMediatorInitializationStarted === true) return; this.isThisMediatorInitializationStarted = true; this.debugLog(">>>> Initializing mediator"); this.videoAdContainterInit(); this.initializeCPMAPI(); this.setupAds(); }; instanceProto.videoAdContainterInit = function() { this.lightbox = document.createElement('div'); this.lightbox.id = "c_nsg-webadspro-lightbox"; this.lightbox.style.position = "fixed"; this.lightbox.style.display = "none"; this.lightbox.style.width = "100%"; this.lightbox.style.height = "100%"; this.lightbox.style.top = "0"; this.lightbox.style.left = "0"; this.lightbox.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; document.getElementsByTagName('body')[0].appendChild(this.lightbox); this.videoAdContainer = document.createElement('div'); this.videoAdContainer.id = 'c_nsg-webadspro-vadc'; this.videoAdContainer.style.width = this.core.setup.preroll.adWidth + "px"; this.videoAdContainer.style.height = this.core.setup.preroll.adHeight + "px"; this.videoAdContainer.style.position = "fixed"; this.videoAdContainer.style.display = "none"; this.videoAdContainer.style.top = "50%"; this.videoAdContainer.style.left = "50%"; this.videoAdContainer.style.transform = "translate(-50%, -50%)"; this.videoAdContainer.style.zIndex = "999999"; document.getElementsByTagName('body')[0].appendChild(this.videoAdContainer); }; instanceProto.videoAdContainerHide = function() { this.lightbox.style.display = "none"; this.videoAdContainer.style.display = "none"; }; instanceProto.videoAdContainerShow = function() { this.lightbox.style.display = "block"; this.videoAdContainer.style.display = "block"; }; instanceProto.setupAds = function() { var self = this; if (typeof window['cpmstarAPI'] === 'undefined') { setTimeout(function () { self.setupAds(); }, 100); return; } window["cpmstarAPI"](function (api) { api["game"]["setTarget"](self.videoAdContainer); self.rAd = new api["game"]["RewardedVideoView"]("rewardedvideo"); self.rAd.addEventListener("loaded", function (e) { self.debugLog("Rewarded ad loaded"); }); self.rAd.addEventListener("load_failed", function (e) { self.debugLog("Rewarded ad failed to load - reattempt in 10s"); setTimeout(function () { if ( ! self.rAd["isLoaded"]()) { self.debugLog("Rewarded ad - start preloading"); self.rAd["load"](); } else { self.debugLog("Rewarded was about to start preloading, but it's already loaded - ignoring"); } }, 10000); }); self.rAd.addEventListener("ad_closed", function (e) { self.videoAdContainerHide(); self.core.onShowRewardedAdResult("successful"); setTimeout(function () { if ( ! self.rAd["isLoaded"]()) { self.debugLog("Rewarded ad - start preloading2"); self.rAd["load"](); } else { self.debugLog("Rewarded was about to start preloading, but it's already loaded - ignoring2"); } }, 1000); }); self.debugLog("Rewarded ad - start preloading3"); self.rAd["load"](); }); window["cpmstarAPI"]({ kind: "game.createInterstitial", onAdOpened: function(){ console.log(">>>> CPM Preroll started"); }, onAdClosed: function(){ self.videoAdContainerHide(); self.core.onShowPrerollAdResult("closed"); }/*, fail: function() { console.log(arguments); self.core.onShowPrerollAdResult("empty"); }*/ }); }; instanceProto.initializeCPMAPI = function () { if (typeof window['cpmstarAPI'] === 'undefined') { /*(function (zonefile) { var rnd = Math.round(Math.random() * 999999); var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; var host = "go.bloxplay.com"; if (window.location.hash == "#urlzing") { host = "//staging.urlzing.com"; } s.src = "//" + host + "/" + zonefile + "?rnd=" + rnd; var s2 = document.getElementsByTagName('script')[0]; s2.parentNode.insertBefore(s, s2); var y = window.location.href.split('#')[0].split('').reduce(function (a, b) { return (a << 5) - a + b.charCodeAt(0) >>> 1 }, 0); y = (10 + ((y * 7) % 26)).toString(36) + y.toString(36); var drutObj = window[y] = window[y] || {}; window['cpmstarAPI'] = window["_" + zonefile] = function (o) { (drutObj.cmd = drutObj.cmd || []).push(o); } }(this.zonefile));*/ (function(zonefile) { var y=window.location.href.split('#')[0].split('').reduce(function(a,b){return(a<<5)-a+b.charCodeAt(0)>>>1},0);y=(10+((y*7)%26)).toString(36)+y.toString(36); var drutObj = window[y] = window[y] || {}; function failCpmstarAPI() { var failFn = function(o) { o && typeof(o) === "object" && o.fail && o.fail(); }; drutObj && Array.isArray(drutObj.cmd) && drutObj.cmd.forEach(failFn) && (drutObj.cmd.length = 0); window.cpmstarAPI = window["_"+zonefile] = failFn; } var rnd = Math.round(Math.random()*999999); var s = document.createElement('script'); s.type = 'text/javascript'; s.async = true; s.onerror=failCpmstarAPI; var proto = document.location.protocol; var host = ( proto == "https:" || proto == "file:")?"https://server":"//cdn"; if(window.location.hash=="#cpmstarDev") host = "//dev.server"; if(window.location.hash=="#cpmstarStaging") host = "//staging.server"; s.src = host + ".cpmstar.com/cached/zonefiles/" + zonefile + ".js?rnd="+rnd; var s2=document.getElementsByTagName('script')[0]; s2.parentNode.insertBefore(s, s2); window['cpmstarAPI'] = function(o) { (drutObj.cmd = drutObj.cmd || []).push(o); } }(this.zonefile)); } }; function Cnds() {}; pluginProto.cnds = new Cnds(); function Acts() {}; pluginProto.acts = new Acts(); function Exps() {}; pluginProto.exps = new Exps(); instanceProto.initialize = function() { this.debugLog("initialized"); }; instanceProto.showPrerollAd = function() { var self = this; this.debugLog("attempting to show preroll ad"); this.videoAdContainerShow(); window['cpmstarAPI']({ kind: "game.displayInterstitial", fail: function() { self.videoAdContainerHide(); self.core.onShowPrerollAdResult("empty"); } }); }; instanceProto.showRewardedAd = function() { this.debugLog("attempting to show rewarded ad"); if(this.rAd && this.rAd["isLoaded"]()) { this.videoAdContainerShow(); this.rAd["show"](); } else { this.videoAdContainerHide(); this.core.onShowRewardedAdResult("empty"); } }; instanceProto.showBannerAd = function(bannerAdUnitId_) { this.debugLog("attempting to show banner ad " + bannerAdUnitId_); /*if ( ! document.getElementById(bannerAdUnitId_)) { this.debugLog("Banner " + bannerAdUnitId_ + " does not exist yet - initializing"); this.initializeBannerAd(bannerAdUnitId_); if ( ! this.core.DUMMY_ADS_MODE) { cpmstarAPI({kind:"go",module:bannerAdUnitId_, config: {target:{find:'#' +bannerAdUnitId_,kind:'replace'}}}); this.core.onShowBannerAdResult(bannerAdUnitId_, "ok"); } else { this.core.onShowBannerAdResult(bannerAdUnitId_, "ok"); } return; }*/ var elem = document.getElementById(bannerAdUnitId_); elem.style.display = 'flex'; if ( ! this.core.DUMMY_ADS_MODE) { cpmstarAPI({kind:'go',module:bannerAdUnitId_, config: { conditions: { target: { find:'#' +bannerAdUnitId_, kind: 'replace' } }}}); this.core.onShowBannerAdResult(bannerAdUnitId_, "ok"); } else { this.core.onShowBannerAdResult(bannerAdUnitId_, "ok"); } }; instanceProto.getBannerElem = function (bannerAdUnitId_) { if ( ! document.getElementById(bannerAdUnitId_)) { this.debugLog("Banner " + bannerAdUnitId_ + " does not exist yet - initializing"); this.initializeBannerAd(bannerAdUnitId_); } return document.getElementById(bannerAdUnitId_); }; instanceProto.hideBannerAd = function(bannerAdUnitId_) { this.debugLog("attempting to hide banner ad " + bannerAdUnitId_); var elem = document.getElementById(bannerAdUnitId_); if ( ! elem) return; elem.style.display = 'none'; }; instanceProto.initializeBannerAd = function(bannerAdUnitId_) { var elem = document.createElement("div"); elem.id = bannerAdUnitId_; var parent = this.runtime.canvasdiv ? this.runtime.canvasdiv : document.body; parent.appendChild(elem); elem.style.width = this.core.bannerLayoutInstanceByAdUnitId[bannerAdUnitId_].width + "px"; elem.style.height = this.core.bannerLayoutInstanceByAdUnitId[bannerAdUnitId_].height + "px"; elem.style.display = "flex"; elem.style.justifyContent = "center"; elem.style.alignItems = "center"; if (this.core.DUMMY_ADS_MODE || ! elem.id || ! bannerAdUnitId_) { elem.style.backgroundColor = "#000"; elem.style.border = "1px solid #fff"; } }; instanceProto.onSetupUpdate = function () { }; instanceProto.debugLog = function (msg_) { if ( ! this.core.DEBUG_MODE) return; console.log("%c WebAdsPro[%cCPMStar%c]:", "font-weight: bolder; color: #00F", "font-weight: bolder; color: #0A0", "font-weight: bolder; color: #00F"); console.log(msg_); console.log(""); }; }()); ; ; cr.plugins_.NSG_WebAdsProCrazyGames = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_WebAdsProCrazyGames.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; var AD_TYPE = { MIDGAME: 1, REWARDED: 2 }; instanceProto.onCreate = function() { window["NSG_WebAdsPro_MedList"]["cg"] = this; this.crazysdk = null; this.core = null; this.isThisMediatorInitializationStarted = false; this.isAPIInitialized = false; this.currentlyPlayingAdType = null; this.everInvokedBannerAdUnitIds = []; this.coreHandshake(); }; instanceProto.coreHandshake = function() // this function might be called from the core plugin also { if (this.core !== null) return; if (typeof window["NSG_WebAdsPro_Core"] !== "undefined") { this.core = window["NSG_WebAdsPro_Core"]; this.debugLog("Handshake with core DONE"); this.onHandshakeDone(); } }; instanceProto.onHandshakeDone = function() { }; instanceProto.initializeMediator = function() { if (this.isThisMediatorInitializationStarted === true) return; this.isThisMediatorInitializationStarted = true; this.debugLog(">>>> Initializing mediator"); this.videoAdContainerInit(); this.initializeAPI(); }; instanceProto.videoAdContainerInit = function() { }; instanceProto.installSDKListeners = function() { var self = this; this.crazysdk.addEventListener('adStarted', function () { }); this.crazysdk.addEventListener('adError', function () { if ( ! self.currentlyPlayingAdType) return; switch(self.currentlyPlayingAdType) { case AD_TYPE.REWARDED: self.core.onShowRewardedAdResult("empty"); break; case AD_TYPE.MIDGAME: self.core.onShowPrerollAdResult("empty"); break; } self.currentlyPlayingAdType = null; }); this.crazysdk.addEventListener('adFinished', function () { if ( ! self.currentlyPlayingAdType) return; switch(self.currentlyPlayingAdType) { case AD_TYPE.REWARDED: self.core.onShowRewardedAdResult("successful"); break; case AD_TYPE.MIDGAME: self.core.onShowPrerollAdResult("closed"); break; } self.currentlyPlayingAdType = null; }); this.crazysdk.addEventListener('bannerRendered', function (event) { self.debugLog('Banner ' + event.containerId + ' has been rendered!'); self.core.onShowBannerAdResult(event.containerId, "ok"); }); this.crazysdk.addEventListener('bannerError', function (event) { self.debugLog('Banner ' + event.containerId + ' render error: ' + event.error); self.core.onShowBannerAdResult(event.containerId, "empty"); }); }; instanceProto.videoAdContainerHide = function() { }; instanceProto.videoAdContainerShow = function() { }; instanceProto.initializeAPI = function() { var self = this; var headElm = document.head || document.getElementsByTagName('head')[0]; var script = document.createElement("script"); var once = true; script.async = "async"; script.type = "text/javascript"; script.charset = "UTF-8"; script.src = "https://sdk.crazygames.com/crazygames-sdk-v1.js"; script.onload = script.onreadystatechange = function () { if (once && (!script.readyState || /loaded|complete/.test(script.readyState))) { once = false; self.isAPIInitialized = true; script.onload = script.onreadystatechange = null; self.crazysdk = window["CrazyGames"]["CrazySDK"]["getInstance"](); self.crazysdk["init"](); self.installSDKListeners(); } }; headElm.appendChild(script); }; function Cnds() {}; pluginProto.cnds = new Cnds(); function Acts() {}; pluginProto.acts = new Acts(); function Exps() {}; pluginProto.exps = new Exps(); instanceProto.initialize = function() { var self = this; if (self.isAPIInitialized === false) { this.debugLog("Cannot initialize mediation plugin because API was not initialized. Reattempt in 1s"); setTimeout(function () { self.initialize(); }, 1000); return; } this.debugLog("initialized"); }; instanceProto.showBannerAd = function(bannerAdUnitId_) { var adType = this.core.bannerAdTypeByAdUnitId[bannerAdUnitId_]; if (typeof this.core.setup[adType].custom !== "undefined") { if (typeof this.core.setup[adType].custom.ignore !== "undefined") return; this.showDoubleBanner(this.core.setup[adType].custom); return; } this.debugLog("attempting to show banner ad " + bannerAdUnitId_); var elem = document.getElementById(bannerAdUnitId_); elem.style.display = 'flex'; if ( ! this.core.DUMMY_ADS_MODE) { if (this.everInvokedBannerAdUnitIds.indexOf(bannerAdUnitId_) === -1) { this.everInvokedBannerAdUnitIds.push(bannerAdUnitId_); } this.crazysdk["requestBanner"]([ { containerId: elem.id, size: elem.id.substring(elem.id.indexOf('-') + 1) //'300x250', } ]); } else { this.core.onShowBannerAdResult(bannerAdUnitId_, "ok"); } }; instanceProto.showDoubleBanner = function(customData_) { this.debugLog("Starting custom trigger - double banner request..."); var i, len, adUnitId, cgBannersSetup = []; len = customData_.p.length; for (i = 0; i < len; ++i) { adUnitId = customData_.p[i]; this.debugLog("attempting to show banner ad " + adUnitId); var elem = this.getBannerElem(adUnitId); elem.style.display = 'flex'; if ( ! this.core.DUMMY_ADS_MODE) { if (this.everInvokedBannerAdUnitIds.indexOf(adUnitId) === -1) { this.everInvokedBannerAdUnitIds.push(adUnitId); } cgBannersSetup.push( { containerId: elem.id, size: elem.id.substring(elem.id.indexOf('-') + 1) //'300x250', } ); } else { this.core.onShowBannerAdResult(adUnitId, "ok"); } } this.debugLog("requesting setup:"); this.debugLog(cgBannersSetup); this.crazysdk["requestBanner"](cgBannersSetup); }; instanceProto.getBannerElem = function (bannerAdUnitId_) { if ( ! document.getElementById(bannerAdUnitId_)) { this.debugLog("Banner " + bannerAdUnitId_ + " does not exist yet - initializing"); this.initializeBannerAd(bannerAdUnitId_); } return document.getElementById(bannerAdUnitId_); }; instanceProto.hideBannerAd = function(bannerAdUnitId_) { this.debugLog("attempting to hide banner ad " + bannerAdUnitId_); var elem = document.getElementById(bannerAdUnitId_); if ( ! elem) return; elem.style.display = 'none'; }; instanceProto.initializeBannerAd = function(bannerAdUnitId_) { var elem = document.createElement("div"); elem.id = bannerAdUnitId_; var parent = this.runtime.canvasdiv ? this.runtime.canvasdiv : document.body; parent.appendChild(elem); elem.style.width = this.core.bannerLayoutInstanceByAdUnitId[bannerAdUnitId_].width + "px"; elem.style.height = this.core.bannerLayoutInstanceByAdUnitId[bannerAdUnitId_].height + "px"; elem.style.display = "flex"; elem.style.justifyContent = "center"; elem.style.alignItems = "center"; if (this.core.DUMMY_ADS_MODE || ! elem.id || ! bannerAdUnitId_) { elem.style.backgroundColor = "#000"; elem.style.border = "1px solid #fff"; } }; instanceProto.isPlayerReady = function() { }; instanceProto.showPrerollAd = function() { this.debugLog("attempting to show preroll ad"); /*if ( ! this.isPlayerReady()) { this.debugLog("plugin is not ready to display the preroll ad - faking empty ad"); this.core.onShowPrerollAdResult("empty"); return; } this.videoAdContainerShow();*/ this.currentlyPlayingAdType = AD_TYPE.MIDGAME; this.crazysdk["requestAd"]('midgame'); }; instanceProto.showRewardedAd = function() { this.debugLog("attempting to show rewarded ad"); /*if ( ! this.isPlayerReady()) { this.debugLog("plugin is not ready to display the rewarded ad - faking empty ad"); this.core.onShowRewardedAdResult("empty"); return; }*/ this.currentlyPlayingAdType = AD_TYPE.REWARDED; this.crazysdk["requestAd"]('rewarded'); }; instanceProto.onSetupUpdate = function () { /*if (this.isAdPlayerReady === false) { this.debugLog("API is not yet initialized so no need to force a setting update."); return; } this.debugLog("API was already initialized so forcing a setting update."); if (this.core.setup.preroll.isFullscreen === true) { window['adplayer']['aipConfig']['AD_FULLSCREEN'] = true; window['adplayer']['aipConfig']['AD_CENTERPLAYER'] = false; } else { window['adplayer']['aipConfig']['AD_FULLSCREEN'] = false; window['adplayer']['aipConfig']['AD_CENTERPLAYER'] = true; }*/ }; instanceProto.debugLog = function (msg_) { if ( ! this.core.DEBUG_MODE) return; console.log("%c WebAdsPro[%cCG%c]:", "font-weight: bolder; color: #00F", "font-weight: bolder; color: #0A0", "font-weight: bolder; color: #00F"); console.log(msg_); console.log(""); }; }()); ; ; cr.plugins_.NSG_WebAdsPro_Banner = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NSG_WebAdsPro_Banner.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.core = null; this.bannerId = this.properties[0]; this.upscaleLock = !!this.properties[1]; this.scaleOffset = this.properties[2]; this.lastImpressionTimestamp = null; this.impressionsCounter = 0; this.coreHandshake(); this.element_hidden = false; this.lastLeft = 0; this.lastTop = 0; this.lastRight = 0; this.lastBottom = 0; this.lastWinWidth = 0; this.lastWinHeight = 0; }; instanceProto.draw = function(ctx){}; instanceProto.drawGL = function (glw){}; instanceProto.coreHandshake = function() // this function might be called from the core plugin also { if (this.core !== null) return; if (typeof window["NSG_WebAdsPro_Core"] !== "undefined") { this.core = window["NSG_WebAdsPro_Core"]; this.debugLog("Handshake with core DONE"); this.onHandshakeDone(); } else { console.log("[Web Ads Pro Banner] Cannot finalize handshake!!!!!!!!!!!"); } }; instanceProto.onHandshakeDone = function() { /*this.core.setBannerLayoutInstance(this.bannerId, this); var self = this; this.bannerPositionAdjuster = setInterval(function () { if (self.core.bannerActiveByAdType[self.bannerId].elem === null) return; self.updatePosition(); }, 100);*/ }; instanceProto.onDestroy = function() { this.core.destroyBanner(this.bannerId); }; instanceProto.getScale = function() { var widthScale = $(window).width() / this.runtime.original_width; var heightScale = $(window).height() / this.runtime.original_height; return Math.min(widthScale, heightScale); }; instanceProto.updatePosition = function () { var left = this.layer.layerToCanvas(this.x, this.y, true); var top = this.layer.layerToCanvas(this.x, this.y, false); var right = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, true); var bottom = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, false); var rightEdge = this.runtime.width / this.runtime.devicePixelRatio; var bottomEdge = this.runtime.height / this.runtime.devicePixelRatio; var curScale = this.getScale() + this.scaleOffset; var elem = this.core.bannerActiveByAdType[this.bannerId].elem; if (!this.visible || !this.layer.visible || right <= 0 || bottom <= 0 || left >= rightEdge || top >= bottomEdge) { if (!this.element_hidden) { elem.style.display = 'none'; } elem.style.display = 'none'; this.element_hidden = true; return; } elem.style.display = "flex"; this.element_hidden = false; if (left < 1) left = 1; if (top < 1) top = 1; if (right >= rightEdge) right = rightEdge - 1; if (bottom >= bottomEdge) bottom = bottomEdge - 1; var curWinWidth = window.innerWidth; var curWinHeight = window.innerHeight; if (this.lastScale === curScale && this.lastLeft === left && this.lastTop === top && this.lastRight === right && this.lastBottom === bottom && this.lastWinWidth === curWinWidth && this.lastWinHeight === curWinHeight) { /*if (this.element_hidden) { this.popupDiv.style = ''; this.element_hidden = false; }*/ --this.fixesLeft; if (this.fixesLeft < 0) return; } else { this.fixesLeft = 10; } this.lastLeft = left; this.lastTop = top; this.lastRight = right; this.lastBottom = bottom; this.lastWinWidth = curWinWidth; this.lastWinHeight = curWinHeight; if (this.element_hidden) { elem.style.display = "flex"; this.element_hidden = false; } var rect = this.runtime.canvas.getBoundingClientRect(); var offx = Math.round(left) + rect.left + document.body.scrollLeft; var offy = Math.round(top) + rect.top + document.body.scrollTop; /*if (this.scaleOffset !== 0) { offx *= (this.scaleOffset * 0.5 + 1); offy *= (this.scaleOffset * 0.5 + 1); }*/ elem.style.position = "absolute"; if (this.upscaleLock && curScale > 1) { jQuery(elem).offset({ left: offx + ((curScale - 1) * this.width * 0.5), top: offy + ((curScale - 1) * this.height * 0.5) }); elem.style.transform = 'scale(1)'; } else { jQuery(elem).offset({left: offx, top: offy}); elem.style.transform = 'scale(' + (curScale) + ')'; } }; function Cnds() {}; /* // the example condition Cnds.prototype.MyCondition = function (myparam) { return myparam >= 0; };*/ pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.ShowBanner = function () { if (this.core === null) { this.debugLog("The core instance is not handshaked yet - ignoring Show Banner request") } if (this.lastImpressionTimestamp === null) { this.core.setBannerLayoutInstance(this.bannerId, this); var self = this; if (this.bannerPositionAdjuster) clearTimeout(this.bannerPositionAdjuster); this.bannerPositionAdjuster = setInterval(function () { if (self.core.bannerActiveByAdType[self.bannerId].elem === null) return; self.updatePosition(); }, 100); /*window.addEventListener('resize', function() { if (self.core.bannerActiveByAdType[self.bannerId].elem === null) return; self.updatePositionTickTarget = self.runtime.tickcount + 3; self.updatePosition(); self.bannerPositionAdjuster = setInterval(function () { self.updatePosition(); if (self.updatePositionTickTarget < self.runtime.tickcount) { clearInterval(self.bannerPositionAdjuster); self.bannerPositionAdjuster = null; } }, 17); }, true);*/ this.lastImpressionTimestamp = new Date(); this.impressionsCounter = 0; this.core.showBanner(this.bannerId); return; } ++this.impressionsCounter; var now = new Date(); var timePassed = now - this.lastImpressionTimestamp; timePassed /= 1000; if (timePassed < this.core.setup[this.bannerId].safePeriod) { this.debugLog("Cannot refresh banner " + this.bannerId + " because it's in SAFE PERIOD. " + timePassed + " >= " + this.core.setup[this.bannerId].safePeriod); return; // cannot refresh during safe period } var canShowAd = false; if (this.impressionsCounter >= this.core.setup[this.bannerId].impressionsFrequency) { canShowAd = true; this.debugLog("Banner " + this.bannerId + " impressions frequency requirements met. " + this.impressionsCounter + " >= " + this.core.setup[this.bannerId].impressionsFrequency); } else { this.debugLog("Banner " + this.bannerId + " impressions frequency requirements not met. " + this.impressionsCounter + " >= " + this.core.setup[this.bannerId].impressionsFrequency); } if (canShowAd === false) { if (timePassed >= this.core.setup[this.bannerId].timeFrequency) { canShowAd = true; this.debugLog("Banner " + this.bannerId + " time frequency requirements met. " + timePassed + " >= " + this.core.setup[this.bannerId].timeFrequency); } else { this.debugLog("Banner " + this.bannerId + " time frequency requirements not met. " + timePassed + " >= " + this.core.setup[this.bannerId].timeFrequency); } } if (canShowAd === false) return; this.core.showBanner(this.bannerId); this.lastImpressionTimestamp = new Date(); this.impressionsCounter = 0; }; pluginProto.acts = new Acts(); function Exps() {}; /*Exps.prototype.MyExpression = function (ret) // 'ret' must always be the first parameter - always return the expression's result through it! { ret.set_int(1337); // return our value };*/ pluginProto.exps = new Exps(); instanceProto.debugLog = function (msg_) { if ( ! this.core.DEBUG_MODE) return; console.log("%c WebAdsPro[%cBANNER-" + this.bannerId + "%c]:", "font-weight: bolder; color: #00F", "font-weight: bolder; color: #0A0", "font-weight: bolder; color: #00F"); console.log(msg_); console.log(""); }; }()); ; ; cr.plugins_.NinePatch = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.NinePatch.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { if (this.is_family) return; this.texture_img = new Image(); this.texture_img.cr_filesize = this.texture_filesize; this.runtime.waitForImageLoad(this.texture_img, this.texture_file); this.fillPattern = null; this.leftPattern = null; this.rightPattern = null; this.topPattern = null; this.bottomPattern = null; this.webGL_texture = null; this.webGL_fillTexture = null; this.webGL_leftTexture = null; this.webGL_rightTexture = null; this.webGL_topTexture = null; this.webGL_bottomTexture = null; }; typeProto.onLostWebGLContext = function () { if (this.is_family) return; this.webGL_texture = null; this.webGL_fillTexture = null; this.webGL_leftTexture = null; this.webGL_rightTexture = null; this.webGL_topTexture = null; this.webGL_bottomTexture = null; }; typeProto.onRestoreWebGLContext = function () { if (this.is_family || !this.instances.length) return; if (!this.webGL_texture) { this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, true, this.runtime.linearSampling, this.texture_pixelformat); } }; typeProto.unloadTextures = function () { if (this.is_family || this.instances.length) return; if (this.runtime.glwrap) { this.runtime.glwrap.deleteTexture(this.webGL_texture); this.runtime.glwrap.deleteTexture(this.webGL_fillTexture); this.runtime.glwrap.deleteTexture(this.webGL_leftTexture); this.runtime.glwrap.deleteTexture(this.webGL_rightTexture); this.runtime.glwrap.deleteTexture(this.webGL_topTexture); this.runtime.glwrap.deleteTexture(this.webGL_bottomTexture); this.webGL_texture = null; this.webGL_fillTexture = null; this.webGL_leftTexture = null; this.webGL_rightTexture = null; this.webGL_topTexture = null; this.webGL_bottomTexture = null; } }; typeProto.slicePatch = function (x1, y1, x2, y2) { var tmpcanvas = document.createElement("canvas"); var w = x2 - x1; var h = y2 - y1; tmpcanvas.width = w; tmpcanvas.height = h; var tmpctx = tmpcanvas.getContext("2d"); tmpctx.drawImage(this.texture_img, x1, y1, w, h, 0, 0, w, h); return tmpcanvas; }; typeProto.createPatch = function (lm, rm, tm, bm) { var iw = this.texture_img.width; var ih = this.texture_img.height; var re = iw - rm; var be = ih - bm; if (this.runtime.glwrap) { if (this.webGL_fillTexture) return; // already created var glwrap = this.runtime.glwrap; var ls = this.runtime.linearSampling; var tf = this.texture_pixelformat; if (re > lm && be > tm) this.webGL_fillTexture = glwrap.loadTexture(this.slicePatch(lm, tm, re, be), true, ls, tf); if (lm > 0 && be > tm) this.webGL_leftTexture = glwrap.loadTexture(this.slicePatch(0, tm, lm, be), true, ls, tf, "repeat-y"); if (rm > 0 && be > tm) this.webGL_rightTexture = glwrap.loadTexture(this.slicePatch(re, tm, iw, be), true, ls, tf, "repeat-y"); if (tm > 0 && re > lm) this.webGL_topTexture = glwrap.loadTexture(this.slicePatch(lm, 0, re, tm), true, ls, tf, "repeat-x"); if (bm > 0 && re > lm) this.webGL_bottomTexture = glwrap.loadTexture(this.slicePatch(lm, be, re, ih), true, ls, tf, "repeat-x"); } else { if (this.fillPattern) return; // already created var ctx = this.runtime.ctx; if (re > lm && be > tm) this.fillPattern = ctx.createPattern(this.slicePatch(lm, tm, re, be), "repeat"); if (lm > 0 && be > tm) this.leftPattern = ctx.createPattern(this.slicePatch(0, tm, lm, be), "repeat"); if (rm > 0 && be > tm) this.rightPattern = ctx.createPattern(this.slicePatch(re, tm, iw, be), "repeat"); if (tm > 0 && re > lm) this.topPattern = ctx.createPattern(this.slicePatch(lm, 0, re, tm), "repeat"); if (bm > 0 && re > lm) this.bottomPattern = ctx.createPattern(this.slicePatch(lm, be, re, ih), "repeat"); } }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.leftMargin = this.properties[0]; this.rightMargin = this.properties[1]; this.topMargin = this.properties[2]; this.bottomMargin = this.properties[3]; this.edges = this.properties[4]; // 0=tile, 1=stretch this.fill = this.properties[5]; // 0=tile, 1=stretch, 2=transparent this.visible = (this.properties[6] === 0); // 0=visible, 1=invisible this.seamless = (this.properties[8] !== 0); // 1px overdraw to hide seams if (this.recycled) this.rcTex.set(0, 0, 0, 0); else this.rcTex = new cr.rect(0, 0, 0, 0); if (this.runtime.glwrap) { if (!this.type.webGL_texture) { this.type.webGL_texture = this.runtime.glwrap.loadTexture(this.type.texture_img, false, this.runtime.linearSampling, this.type.texture_pixelformat); } } this.type.createPatch(this.leftMargin, this.rightMargin, this.topMargin, this.bottomMargin); }; function drawPatternProperly(ctx, pattern, pw, ph, drawX, drawY, w, h, ox, oy) { ctx.save(); ctx.fillStyle = pattern; var offX = drawX % pw; var offY = drawY % ph; if (offX < 0) offX += pw; if (offY < 0) offY += ph; ctx.translate(offX + ox, offY + oy); ctx.fillRect(drawX - offX - ox, drawY - offY - oy, w, h); ctx.restore(); }; instanceProto.draw = function(ctx) { var img = this.type.texture_img; var lm = this.leftMargin; var rm = this.rightMargin; var tm = this.topMargin; var bm = this.bottomMargin; var iw = img.width; var ih = img.height; var re = iw - rm; var be = ih - bm; ctx.globalAlpha = this.opacity; ctx.save(); var myx = this.x; var myy = this.y; var myw = this.width; var myh = this.height; if (this.runtime.pixel_rounding) { myx = Math.round(myx); myy = Math.round(myy); } var drawX = -(this.hotspotX * this.width); var drawY = -(this.hotspotY * this.height); var offX = drawX % iw; var offY = drawY % ih; if (offX < 0) offX += iw; if (offY < 0) offY += ih; ctx.translate(myx + offX, myy + offY); var x = drawX - offX; var y = drawY - offY; var s = (this.seamless ? 1 : 0); if (lm > 0 && tm > 0) ctx.drawImage(img, 0, 0, lm + s, tm + s, x, y, lm + s, tm + s); if (rm > 0 && tm > 0) ctx.drawImage(img, re - s, 0, rm + s, tm + s, x + myw - rm - s, y, rm + s, tm + s); if (rm > 0 && bm > 0) ctx.drawImage(img, re - s, be - s, rm + s, bm + s, x + myw - rm - s, y + myh - bm - s, rm + s, bm + s); if (lm > 0 && bm > 0) ctx.drawImage(img, 0, be - s, lm + s, bm + s, x, y + myh - bm - s, lm + s, bm + s); if (this.edges === 0) // tile edges { var off = (this.fill === 2 ? 0 : s); if (lm > 0 && be > tm) drawPatternProperly(ctx, this.type.leftPattern, lm, be - tm, x, y + tm, lm + off, myh - tm - bm, 0, 0); if (rm > 0 && be > tm) drawPatternProperly(ctx, this.type.rightPattern, rm, be - tm, x + myw - rm - off, y + tm, rm + off, myh - tm - bm, off, 0); if (tm > 0 && re > lm) drawPatternProperly(ctx, this.type.topPattern, re - lm, tm, x + lm, y, myw - lm - rm, tm + off, 0, 0); if (bm > 0 && re > lm) drawPatternProperly(ctx, this.type.bottomPattern, re - lm, bm, x + lm, y + myh - bm - off, myw - lm - rm, bm + off, 0, off); } else if (this.edges === 1) // stretch edges { if (lm > 0 && be > tm && myh - tm - bm > 0) ctx.drawImage(img, 0, tm, lm, be - tm, x, y + tm, lm, myh - tm - bm); if (rm > 0 && be > tm && myh - tm - bm > 0) ctx.drawImage(img, re, tm, rm, be - tm, x + myw - rm, y + tm, rm, myh - tm - bm); if (tm > 0 && re > lm && myw - lm - rm > 0) ctx.drawImage(img, lm, 0, re - lm, tm, x + lm, y, myw - lm - rm, tm); if (bm > 0 && re > lm && myw - lm - rm > 0) ctx.drawImage(img, lm, be, re - lm, bm, x + lm, y + myh - bm, myw - lm - rm, bm); } if (be > tm && re > lm) { if (this.fill === 0) // tile fill { drawPatternProperly(ctx, this.type.fillPattern, re - lm, be - tm, x + lm, y + tm, myw - lm - rm, myh - tm - bm, 0, 0); } else if (this.fill === 1) // stretch fill { if (myw - lm - rm > 0 && myh - tm - bm > 0) { ctx.drawImage(img, lm, tm, re - lm, be - tm, x + lm, y + tm, myw - lm - rm, myh - tm - bm); } } } ctx.restore(); }; instanceProto.drawPatch = function(glw, tex, sx, sy, sw, sh, dx, dy, dw, dh) { glw.setTexture(tex); var rcTex = this.rcTex; rcTex.left = sx / tex.c2width; rcTex.top = sy / tex.c2height; rcTex.right = (sx + sw) / tex.c2width; rcTex.bottom = (sy + sh) / tex.c2height; glw.quadTex(dx, dy, dx + dw, dy, dx + dw, dy + dh, dx, dy + dh, rcTex); }; instanceProto.tilePatch = function(glw, tex, dx, dy, dw, dh, ox, oy) { glw.setTexture(tex); var rcTex = this.rcTex; rcTex.left = -ox / tex.c2width; rcTex.top = -oy / tex.c2height; rcTex.right = (dw - ox) / tex.c2width; rcTex.bottom = (dh - oy) / tex.c2height; glw.quadTex(dx, dy, dx + dw, dy, dx + dw, dy + dh, dx, dy + dh, rcTex); }; instanceProto.drawGL_earlyZPass = function(glw) { this.drawGL(glw); }; instanceProto.drawGL = function(glw) { var lm = this.leftMargin; var rm = this.rightMargin; var tm = this.topMargin; var bm = this.bottomMargin; var iw = this.type.texture_img.width; var ih = this.type.texture_img.height; var re = iw - rm; var be = ih - bm; glw.setOpacity(this.opacity); var rcTex = this.rcTex; var q = this.bquad; var myx = q.tlx; var myy = q.tly; var myw = this.width; var myh = this.height; if (this.runtime.pixel_rounding) { myx = Math.round(myx); myy = Math.round(myy); } var s = (this.seamless ? 1 : 0); if (lm > 0 && tm > 0) this.drawPatch(glw, this.type.webGL_texture, 0, 0, lm + s, tm + s, myx, myy, lm + s, tm + s); if (rm > 0 && tm > 0) this.drawPatch(glw, this.type.webGL_texture, re - s, 0, rm + s, tm + s, myx + myw - rm - s, myy, rm + s, tm + s); if (rm > 0 && bm > 0) this.drawPatch(glw, this.type.webGL_texture, re - s, be - s, rm + s, bm + s, myx + myw - rm - s, myy + myh - bm - s, rm + s, bm + s); if (lm > 0 && bm > 0) this.drawPatch(glw, this.type.webGL_texture, 0, be - s, lm + s, bm + s, myx, myy + myh - bm - s, lm + s, bm + s); if (this.edges === 0) // tile edges { var off = (this.fill === 2 ? 0 : s); if (lm > 0 && be > tm) this.tilePatch(glw, this.type.webGL_leftTexture, myx, myy + tm, lm + off, myh - tm - bm, 0, 0); if (rm > 0 && be > tm) this.tilePatch(glw, this.type.webGL_rightTexture, myx + myw - rm - off, myy + tm, rm + off, myh - tm - bm, off, 0); if (tm > 0 && re > lm) this.tilePatch(glw, this.type.webGL_topTexture, myx + lm, myy, myw - lm - rm, tm + off, 0, 0); if (bm > 0 && re > lm) this.tilePatch(glw, this.type.webGL_bottomTexture, myx + lm, myy + myh - bm - off, myw - lm - rm, bm + off, 0, off); } else if (this.edges === 1) // stretch edges { if (lm > 0 && be > tm) this.drawPatch(glw, this.type.webGL_texture, 0, tm, lm, be - tm, myx, myy + tm, lm, myh - tm - bm); if (rm > 0 && be > tm) this.drawPatch(glw, this.type.webGL_texture, re, tm, rm, be - tm, myx + myw - rm, myy + tm, rm, myh - tm - bm); if (tm > 0 && re > lm) this.drawPatch(glw, this.type.webGL_texture, lm, 0, re - lm, tm, myx + lm, myy, myw - lm - rm, tm); if (bm > 0 && re > lm) this.drawPatch(glw, this.type.webGL_texture, lm, be, re - lm, bm, myx + lm, myy + myh - bm, myw - lm - rm, bm); } if (be > tm && re > lm) { if (this.fill === 0) // tile fill { this.tilePatch(glw, this.type.webGL_fillTexture, myx + lm, myy + tm, myw - lm - rm, myh - tm - bm, 0, 0); } else if (this.fill === 1) // stretch fill { this.drawPatch(glw, this.type.webGL_texture, lm, tm, re - lm, be - tm, myx + lm, myy + tm, myw - lm - rm, myh - tm - bm); } } }; function Cnds() {}; Cnds.prototype.OnURLLoaded = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetEffect = function (effect) { this.blend_mode = effect; this.compositeOp = cr.effectToCompositeOp(effect); cr.setGLBlend(this, effect, this.runtime.gl); this.runtime.redraw = true; }; pluginProto.acts = new Acts(); function Exps() {}; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Particles = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Particles.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { if (this.is_family) return; this.texture_img = new Image(); this.texture_img.cr_filesize = this.texture_filesize; this.webGL_texture = null; this.runtime.waitForImageLoad(this.texture_img, this.texture_file); }; typeProto.onLostWebGLContext = function () { if (this.is_family) return; this.webGL_texture = null; }; typeProto.onRestoreWebGLContext = function () { if (this.is_family || !this.instances.length) return; if (!this.webGL_texture) { this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, true, this.runtime.linearSampling, this.texture_pixelformat); } }; typeProto.loadTextures = function () { if (this.is_family || this.webGL_texture || !this.runtime.glwrap) return; this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, true, this.runtime.linearSampling, this.texture_pixelformat); }; typeProto.unloadTextures = function () { if (this.is_family || this.instances.length || !this.webGL_texture) return; this.runtime.glwrap.deleteTexture(this.webGL_texture); this.webGL_texture = null; }; typeProto.preloadCanvas2D = function (ctx) { ctx.drawImage(this.texture_img, 0, 0); }; function Particle(owner) { this.owner = owner; this.active = false; this.x = 0; this.y = 0; this.speed = 0; this.angle = 0; this.opacity = 1; this.grow = 0; this.size = 0; this.gs = 0; // gravity speed this.age = 0; cr.seal(this); }; Particle.prototype.init = function () { var owner = this.owner; this.x = owner.x - (owner.xrandom / 2) + (Math.random() * owner.xrandom); this.y = owner.y - (owner.yrandom / 2) + (Math.random() * owner.yrandom); this.speed = owner.initspeed - (owner.speedrandom / 2) + (Math.random() * owner.speedrandom); this.angle = owner.angle - (owner.spraycone / 2) + (Math.random() * owner.spraycone); this.opacity = owner.initopacity; this.size = owner.initsize - (owner.sizerandom / 2) + (Math.random() * owner.sizerandom); this.grow = owner.growrate - (owner.growrandom / 2) + (Math.random() * owner.growrandom); this.gs = 0; this.age = 0; }; Particle.prototype.tick = function (dt) { var owner = this.owner; this.x += Math.cos(this.angle) * this.speed * dt; this.y += Math.sin(this.angle) * this.speed * dt; this.y += this.gs * dt; this.speed += owner.acc * dt; this.size += this.grow * dt; this.gs += owner.g * dt; this.age += dt; if (this.size < 1) { this.active = false; return; } if (owner.lifeanglerandom !== 0) this.angle += (Math.random() * owner.lifeanglerandom * dt) - (owner.lifeanglerandom * dt / 2); if (owner.lifespeedrandom !== 0) this.speed += (Math.random() * owner.lifespeedrandom * dt) - (owner.lifespeedrandom * dt / 2); if (owner.lifeopacityrandom !== 0) { this.opacity += (Math.random() * owner.lifeopacityrandom * dt) - (owner.lifeopacityrandom * dt / 2); if (this.opacity < 0) this.opacity = 0; else if (this.opacity > 1) this.opacity = 1; } if (owner.destroymode <= 1 && this.age >= owner.timeout) { this.active = false; } if (owner.destroymode === 2 && this.speed <= 0) { this.active = false; } }; Particle.prototype.draw = function (ctx) { var curopacity = this.owner.opacity * this.opacity; if (curopacity === 0) return; if (this.owner.destroymode === 0) curopacity *= 1 - (this.age / this.owner.timeout); ctx.globalAlpha = curopacity; var drawx = this.x - this.size / 2; var drawy = this.y - this.size / 2; if (this.owner.runtime.pixel_rounding) { drawx = (drawx + 0.5) | 0; drawy = (drawy + 0.5) | 0; } ctx.drawImage(this.owner.type.texture_img, drawx, drawy, this.size, this.size); }; Particle.prototype.drawGL = function (glw) { var curopacity = this.owner.opacity * this.opacity; if (this.owner.destroymode === 0) curopacity *= 1 - (this.age / this.owner.timeout); var drawsize = this.size; var scaleddrawsize = drawsize * this.owner.particlescale; var drawx = this.x - drawsize / 2; var drawy = this.y - drawsize / 2; if (this.owner.runtime.pixel_rounding) { drawx = (drawx + 0.5) | 0; drawy = (drawy + 0.5) | 0; } if (scaleddrawsize < 1 || curopacity === 0) return; if (scaleddrawsize < glw.minPointSize || scaleddrawsize > glw.maxPointSize) { glw.setOpacity(curopacity); glw.quad(drawx, drawy, drawx + drawsize, drawy, drawx + drawsize, drawy + drawsize, drawx, drawy + drawsize); } else glw.point(this.x, this.y, scaleddrawsize, curopacity); }; Particle.prototype.left = function () { return this.x - this.size / 2; }; Particle.prototype.right = function () { return this.x + this.size / 2; }; Particle.prototype.top = function () { return this.y - this.size / 2; }; Particle.prototype.bottom = function () { return this.y + this.size / 2; }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; var deadparticles = []; instanceProto.onCreate = function() { var props = this.properties; this.rate = props[0]; this.spraycone = cr.to_radians(props[1]); this.spraytype = props[2]; // 0 = continuous, 1 = one-shot this.spraying = true; // for continuous mode only this.initspeed = props[3]; this.initsize = props[4]; this.initopacity = props[5] / 100.0; this.growrate = props[6]; this.xrandom = props[7]; this.yrandom = props[8]; this.speedrandom = props[9]; this.sizerandom = props[10]; this.growrandom = props[11]; this.acc = props[12]; this.g = props[13]; this.lifeanglerandom = props[14]; this.lifespeedrandom = props[15]; this.lifeopacityrandom = props[16]; this.destroymode = props[17]; // 0 = fade, 1 = timeout, 2 = stopped this.timeout = props[18]; this.particleCreateCounter = 0; this.particlescale = 1; this.particleBoxLeft = this.x; this.particleBoxTop = this.y; this.particleBoxRight = this.x; this.particleBoxBottom = this.y; this.add_bbox_changed_callback(function (self) { self.bbox.set(self.particleBoxLeft, self.particleBoxTop, self.particleBoxRight, self.particleBoxBottom); self.bquad.set_from_rect(self.bbox); self.bbox_changed = false; self.update_collision_cell(); self.update_render_cell(); }); if (!this.recycled) this.particles = []; this.runtime.tickMe(this); this.type.loadTextures(); if (this.spraytype === 1) { for (var i = 0; i < this.rate; i++) this.allocateParticle().opacity = 0; } this.first_tick = true; // for re-init'ing one-shot particles on first tick so they assume any new angle/position }; instanceProto.saveToJSON = function () { var o = { "r": this.rate, "sc": this.spraycone, "st": this.spraytype, "s": this.spraying, "isp": this.initspeed, "isz": this.initsize, "io": this.initopacity, "gr": this.growrate, "xr": this.xrandom, "yr": this.yrandom, "spr": this.speedrandom, "szr": this.sizerandom, "grnd": this.growrandom, "acc": this.acc, "g": this.g, "lar": this.lifeanglerandom, "lsr": this.lifespeedrandom, "lor": this.lifeopacityrandom, "dm": this.destroymode, "to": this.timeout, "pcc": this.particleCreateCounter, "ft": this.first_tick, "p": [] }; var i, len, p; var arr = o["p"]; for (i = 0, len = this.particles.length; i < len; i++) { p = this.particles[i]; arr.push([p.x, p.y, p.speed, p.angle, p.opacity, p.grow, p.size, p.gs, p.age]); } return o; }; instanceProto.loadFromJSON = function (o) { this.rate = o["r"]; this.spraycone = o["sc"]; this.spraytype = o["st"]; this.spraying = o["s"]; this.initspeed = o["isp"]; this.initsize = o["isz"]; this.initopacity = o["io"]; this.growrate = o["gr"]; this.xrandom = o["xr"]; this.yrandom = o["yr"]; this.speedrandom = o["spr"]; this.sizerandom = o["szr"]; this.growrandom = o["grnd"]; this.acc = o["acc"]; this.g = o["g"]; this.lifeanglerandom = o["lar"]; this.lifespeedrandom = o["lsr"]; this.lifeopacityrandom = o["lor"]; this.destroymode = o["dm"]; this.timeout = o["to"]; this.particleCreateCounter = o["pcc"]; this.first_tick = o["ft"]; deadparticles.push.apply(deadparticles, this.particles); cr.clearArray(this.particles); var i, len, p, d; var arr = o["p"]; for (i = 0, len = arr.length; i < len; i++) { p = this.allocateParticle(); d = arr[i]; p.x = d[0]; p.y = d[1]; p.speed = d[2]; p.angle = d[3]; p.opacity = d[4]; p.grow = d[5]; p.size = d[6]; p.gs = d[7]; p.age = d[8]; } }; instanceProto.onDestroy = function () { deadparticles.push.apply(deadparticles, this.particles); cr.clearArray(this.particles); }; instanceProto.allocateParticle = function () { var p; if (deadparticles.length) { p = deadparticles.pop(); p.owner = this; } else p = new Particle(this); this.particles.push(p); p.active = true; return p; }; instanceProto.tick = function() { var dt = this.runtime.getDt(this); var i, len, p, n, j; if (this.spraytype === 0 && this.spraying) { this.particleCreateCounter += dt * this.rate; n = cr.floor(this.particleCreateCounter); this.particleCreateCounter -= n; for (i = 0; i < n; i++) { p = this.allocateParticle(); p.init(); } } this.particleBoxLeft = this.x; this.particleBoxTop = this.y; this.particleBoxRight = this.x; this.particleBoxBottom = this.y; for (i = 0, j = 0, len = this.particles.length; i < len; i++) { p = this.particles[i]; this.particles[j] = p; this.runtime.redraw = true; if (this.spraytype === 1 && this.first_tick) p.init(); p.tick(dt); if (!p.active) { deadparticles.push(p); continue; } if (p.left() < this.particleBoxLeft) this.particleBoxLeft = p.left(); if (p.right() > this.particleBoxRight) this.particleBoxRight = p.right(); if (p.top() < this.particleBoxTop) this.particleBoxTop = p.top(); if (p.bottom() > this.particleBoxBottom) this.particleBoxBottom = p.bottom(); j++; } cr.truncateArray(this.particles, j); this.set_bbox_changed(); this.first_tick = false; if (this.spraytype === 1 && this.particles.length === 0) this.runtime.DestroyInstance(this); }; instanceProto.draw = function (ctx) { var i, len, p, layer = this.layer; for (i = 0, len = this.particles.length; i < len; i++) { p = this.particles[i]; if (p.right() >= layer.viewLeft && p.bottom() >= layer.viewTop && p.left() <= layer.viewRight && p.top() <= layer.viewBottom) { p.draw(ctx); } } }; instanceProto.drawGL = function (glw) { this.particlescale = this.layer.getScale(); glw.setTexture(this.type.webGL_texture); var i, len, p, layer = this.layer; for (i = 0, len = this.particles.length; i < len; i++) { p = this.particles[i]; if (p.right() >= layer.viewLeft && p.bottom() >= layer.viewTop && p.left() <= layer.viewRight && p.top() <= layer.viewBottom) { p.drawGL(glw); } } }; function Cnds() {}; Cnds.prototype.IsSpraying = function () { return this.spraying; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetSpraying = function (set_) { this.spraying = (set_ !== 0); }; Acts.prototype.SetEffect = function (effect) { this.blend_mode = effect; this.compositeOp = cr.effectToCompositeOp(effect); cr.setGLBlend(this, effect, this.runtime.gl); this.runtime.redraw = true; }; Acts.prototype.SetRate = function (x) { this.rate = x; var diff, i; if (this.spraytype === 1 && this.first_tick) { if (x < this.particles.length) { diff = this.particles.length - x; for (i = 0; i < diff; i++) deadparticles.push(this.particles.pop()); } else if (x > this.particles.length) { diff = x - this.particles.length; for (i = 0; i < diff; i++) this.allocateParticle().opacity = 0; } } }; Acts.prototype.SetSprayCone = function (x) { this.spraycone = cr.to_radians(x); }; Acts.prototype.SetInitSpeed = function (x) { this.initspeed = x; }; Acts.prototype.SetInitSize = function (x) { this.initsize = x; }; Acts.prototype.SetInitOpacity = function (x) { this.initopacity = x / 100; }; Acts.prototype.SetGrowRate = function (x) { this.growrate = x; }; Acts.prototype.SetXRandomiser = function (x) { this.xrandom = x; }; Acts.prototype.SetYRandomiser = function (x) { this.yrandom = x; }; Acts.prototype.SetSpeedRandomiser = function (x) { this.speedrandom = x; }; Acts.prototype.SetSizeRandomiser = function (x) { this.sizerandom = x; }; Acts.prototype.SetGrowRateRandomiser = function (x) { this.growrandom = x; }; Acts.prototype.SetParticleAcc = function (x) { this.acc = x; }; Acts.prototype.SetGravity = function (x) { this.g = x; }; Acts.prototype.SetAngleRandomiser = function (x) { this.lifeanglerandom = x; }; Acts.prototype.SetLifeSpeedRandomiser = function (x) { this.lifespeedrandom = x; }; Acts.prototype.SetOpacityRandomiser = function (x) { this.lifeopacityrandom = x; }; Acts.prototype.SetTimeout = function (x) { this.timeout = x; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.ParticleCount = function (ret) { ret.set_int(this.particles.length); }; Exps.prototype.Rate = function (ret) { ret.set_float(this.rate); }; Exps.prototype.SprayCone = function (ret) { ret.set_float(cr.to_degrees(this.spraycone)); }; Exps.prototype.InitSpeed = function (ret) { ret.set_float(this.initspeed); }; Exps.prototype.InitSize = function (ret) { ret.set_float(this.initsize); }; Exps.prototype.InitOpacity = function (ret) { ret.set_float(this.initopacity * 100); }; Exps.prototype.InitGrowRate = function (ret) { ret.set_float(this.growrate); }; Exps.prototype.XRandom = function (ret) { ret.set_float(this.xrandom); }; Exps.prototype.YRandom = function (ret) { ret.set_float(this.yrandom); }; Exps.prototype.InitSpeedRandom = function (ret) { ret.set_float(this.speedrandom); }; Exps.prototype.InitSizeRandom = function (ret) { ret.set_float(this.sizerandom); }; Exps.prototype.InitGrowRandom = function (ret) { ret.set_float(this.growrandom); }; Exps.prototype.ParticleAcceleration = function (ret) { ret.set_float(this.acc); }; Exps.prototype.Gravity = function (ret) { ret.set_float(this.g); }; Exps.prototype.ParticleAngleRandom = function (ret) { ret.set_float(this.lifeanglerandom); }; Exps.prototype.ParticleSpeedRandom = function (ret) { ret.set_float(this.lifespeedrandom); }; Exps.prototype.ParticleOpacityRandom = function (ret) { ret.set_float(this.lifeopacityrandom); }; Exps.prototype.Timeout = function (ret) { ret.set_float(this.timeout); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Rex_EventBalancer = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Rex_EventBalancer.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.is_dynamic_mode = (this.properties[0] == 0); this.processing_time = percentage2time(this.properties[1]); this.repeat_count = this.properties[2]; this.is_running = false; this.elapsed_ticks = 0; this.trigger_mode_init = false; this.is_looping = false; }; var percentage2time = function (percentage) { if (percentage < 0.01) percentage = 0.01; return (1/60)*1000*percentage; }; instanceProto.tick = function() { if (!this.is_running) return; this.elapsed_ticks += 1; if (this.is_dynamic_mode) this._run_dynamic_mode() else this._run_static_mode() }; instanceProto._run_dynamic_mode = function() { var is_timeout = false; var start_time = Date.now(); while (!is_timeout) { this.runtime.trigger(cr.plugins_.Rex_EventBalancer.prototype.cnds.OnProcessing, this); if (!this.is_running) break; is_timeout = ((Date.now() - start_time) > this.processing_time); } }; instanceProto._run_static_mode = function() { var i; for (i=0; i= this.cur_animation.frames.length) this.cur_frame = this.cur_animation.frames.length - 1; var curanimframe = this.cur_animation.frames[this.cur_frame]; this.collision_poly.set_pts(curanimframe.poly_pts); this.hotspotX = curanimframe.hotspotX; this.hotspotY = curanimframe.hotspotY; this.cur_anim_speed = this.cur_animation.speed; this.cur_anim_repeatto = this.cur_animation.repeatto; if (!(this.type.animations.length === 1 && this.type.animations[0].frames.length === 1) && this.cur_anim_speed !== 0) { this.runtime.tickMe(this); this.isTicking = true; } if (this.recycled) this.animTimer.reset(); else this.animTimer = new cr.KahanAdder(); this.frameStart = this.getNowTime(); this.animPlaying = true; this.animRepeats = 0; this.animForwards = true; this.animTriggerName = ""; this.changeAnimName = ""; this.changeAnimFrom = 0; this.changeAnimFrame = -1; this.type.loadTextures(); var i, leni, j, lenj; var anim, frame, uv, maintex; for (i = 0, leni = this.type.animations.length; i < leni; i++) { anim = this.type.animations[i]; for (j = 0, lenj = anim.frames.length; j < lenj; j++) { frame = anim.frames[j]; if (frame.width === 0) { frame.width = frame.texture_img.width; frame.height = frame.texture_img.height; } if (frame.spritesheeted) { maintex = frame.texture_img; uv = frame.sheetTex; uv.left = frame.offx / maintex.width; uv.top = frame.offy / maintex.height; uv.right = (frame.offx + frame.width) / maintex.width; uv.bottom = (frame.offy + frame.height) / maintex.height; if (frame.offx === 0 && frame.offy === 0 && frame.width === maintex.width && frame.height === maintex.height) { frame.spritesheeted = false; } } } } this.curFrame = this.cur_animation.frames[this.cur_frame]; this.curWebGLTexture = this.curFrame.webGL_texture; }; instanceProto.saveToJSON = function () { var o = { "a": this.cur_animation.sid, "f": this.cur_frame, "cas": this.cur_anim_speed, "fs": this.frameStart, "ar": this.animRepeats, "at": this.animTimer.sum, "rt": this.cur_anim_repeatto }; if (!this.animPlaying) o["ap"] = this.animPlaying; if (!this.animForwards) o["af"] = this.animForwards; return o; }; instanceProto.loadFromJSON = function (o) { var anim = this.getAnimationBySid(o["a"]); if (anim) this.cur_animation = anim; this.cur_frame = o["f"]; if (this.cur_frame < 0) this.cur_frame = 0; if (this.cur_frame >= this.cur_animation.frames.length) this.cur_frame = this.cur_animation.frames.length - 1; this.cur_anim_speed = o["cas"]; this.frameStart = o["fs"]; this.animRepeats = o["ar"]; this.animTimer.reset(); this.animTimer.sum = o["at"]; this.animPlaying = o.hasOwnProperty("ap") ? o["ap"] : true; this.animForwards = o.hasOwnProperty("af") ? o["af"] : true; if (o.hasOwnProperty("rt")) this.cur_anim_repeatto = o["rt"]; else this.cur_anim_repeatto = this.cur_animation.repeatto; this.curFrame = this.cur_animation.frames[this.cur_frame]; this.curWebGLTexture = this.curFrame.webGL_texture; this.collision_poly.set_pts(this.curFrame.poly_pts); this.hotspotX = this.curFrame.hotspotX; this.hotspotY = this.curFrame.hotspotY; }; instanceProto.animationFinish = function (reverse) { this.cur_frame = reverse ? 0 : this.cur_animation.frames.length - 1; this.animPlaying = false; this.animTriggerName = this.cur_animation.name; this.inAnimTrigger = true; this.runtime.trigger(cr.plugins_.Sprite.prototype.cnds.OnAnyAnimFinished, this); this.runtime.trigger(cr.plugins_.Sprite.prototype.cnds.OnAnimFinished, this); this.inAnimTrigger = false; this.animRepeats = 0; }; instanceProto.getNowTime = function() { return this.animTimer.sum; }; instanceProto.tick = function() { this.animTimer.add(this.runtime.getDt(this)); if (this.changeAnimName.length) this.doChangeAnim(); if (this.changeAnimFrame >= 0) this.doChangeAnimFrame(); var now = this.getNowTime(); var cur_animation = this.cur_animation; var prev_frame = cur_animation.frames[this.cur_frame]; var next_frame; var cur_frame_time = prev_frame.duration / this.cur_anim_speed; if (this.animPlaying && now >= this.frameStart + cur_frame_time) { if (this.animForwards) { this.cur_frame++; } else { this.cur_frame--; } this.frameStart += cur_frame_time; if (this.cur_frame >= cur_animation.frames.length) { if (cur_animation.pingpong) { this.animForwards = false; this.cur_frame = cur_animation.frames.length - 2; } else if (cur_animation.loop) { this.cur_frame = this.cur_anim_repeatto; } else { this.animRepeats++; if (this.animRepeats >= cur_animation.repeatcount) { this.animationFinish(false); } else { this.cur_frame = this.cur_anim_repeatto; } } } if (this.cur_frame < 0) { if (cur_animation.pingpong) { this.cur_frame = 1; this.animForwards = true; if (!cur_animation.loop) { this.animRepeats++; if (this.animRepeats >= cur_animation.repeatcount) { this.animationFinish(true); } } } else { if (cur_animation.loop) { this.cur_frame = this.cur_anim_repeatto; } else { this.animRepeats++; if (this.animRepeats >= cur_animation.repeatcount) { this.animationFinish(true); } else { this.cur_frame = this.cur_anim_repeatto; } } } } if (this.cur_frame < 0) this.cur_frame = 0; else if (this.cur_frame >= cur_animation.frames.length) this.cur_frame = cur_animation.frames.length - 1; if (now > this.frameStart + (cur_animation.frames[this.cur_frame].duration / this.cur_anim_speed)) { this.frameStart = now; } next_frame = cur_animation.frames[this.cur_frame]; this.OnFrameChanged(prev_frame, next_frame); this.runtime.redraw = true; } }; instanceProto.getAnimationByName = function (name_) { var i, len, a; for (i = 0, len = this.type.animations.length; i < len; i++) { a = this.type.animations[i]; if (cr.equals_nocase(a.name, name_)) return a; } return null; }; instanceProto.getAnimationBySid = function (sid_) { var i, len, a; for (i = 0, len = this.type.animations.length; i < len; i++) { a = this.type.animations[i]; if (a.sid === sid_) return a; } return null; }; instanceProto.doChangeAnim = function () { var prev_frame = this.cur_animation.frames[this.cur_frame]; var anim = this.getAnimationByName(this.changeAnimName); this.changeAnimName = ""; if (!anim) return; if (cr.equals_nocase(anim.name, this.cur_animation.name) && this.animPlaying) return; this.cur_animation = anim; this.cur_anim_speed = anim.speed; this.cur_anim_repeatto = anim.repeatto; if (this.cur_frame < 0) this.cur_frame = 0; if (this.cur_frame >= this.cur_animation.frames.length) this.cur_frame = this.cur_animation.frames.length - 1; if (this.changeAnimFrom === 1) this.cur_frame = 0; this.animPlaying = true; this.frameStart = this.getNowTime(); this.animForwards = true; this.OnFrameChanged(prev_frame, this.cur_animation.frames[this.cur_frame]); this.runtime.redraw = true; }; instanceProto.doChangeAnimFrame = function () { var prev_frame = this.cur_animation.frames[this.cur_frame]; var prev_frame_number = this.cur_frame; this.cur_frame = cr.floor(this.changeAnimFrame); if (this.cur_frame < 0) this.cur_frame = 0; if (this.cur_frame >= this.cur_animation.frames.length) this.cur_frame = this.cur_animation.frames.length - 1; if (prev_frame_number !== this.cur_frame) { this.OnFrameChanged(prev_frame, this.cur_animation.frames[this.cur_frame]); this.frameStart = this.getNowTime(); this.runtime.redraw = true; } this.changeAnimFrame = -1; }; instanceProto.OnFrameChanged = function (prev_frame, next_frame) { var oldw = prev_frame.width; var oldh = prev_frame.height; var neww = next_frame.width; var newh = next_frame.height; if (oldw != neww) this.width *= (neww / oldw); if (oldh != newh) this.height *= (newh / oldh); this.hotspotX = next_frame.hotspotX; this.hotspotY = next_frame.hotspotY; this.collision_poly.set_pts(next_frame.poly_pts); this.set_bbox_changed(); this.curFrame = next_frame; this.curWebGLTexture = next_frame.webGL_texture; var i, len, b; for (i = 0, len = this.behavior_insts.length; i < len; i++) { b = this.behavior_insts[i]; if (b.onSpriteFrameChanged) b.onSpriteFrameChanged(prev_frame, next_frame); } this.runtime.trigger(cr.plugins_.Sprite.prototype.cnds.OnFrameChanged, this); }; instanceProto.draw = function(ctx) { ctx.globalAlpha = this.opacity; var cur_frame = this.curFrame; var spritesheeted = cur_frame.spritesheeted; var cur_image = cur_frame.texture_img; var myx = this.x; var myy = this.y; var w = this.width; var h = this.height; if (this.angle === 0 && w >= 0 && h >= 0) { myx -= this.hotspotX * w; myy -= this.hotspotY * h; if (this.runtime.pixel_rounding) { myx = Math.round(myx); myy = Math.round(myy); } if (spritesheeted) { ctx.drawImage(cur_image, cur_frame.offx, cur_frame.offy, cur_frame.width, cur_frame.height, myx, myy, w, h); } else { ctx.drawImage(cur_image, myx, myy, w, h); } } else { if (this.runtime.pixel_rounding) { myx = Math.round(myx); myy = Math.round(myy); } ctx.save(); var widthfactor = w > 0 ? 1 : -1; var heightfactor = h > 0 ? 1 : -1; ctx.translate(myx, myy); if (widthfactor !== 1 || heightfactor !== 1) ctx.scale(widthfactor, heightfactor); ctx.rotate(this.angle * widthfactor * heightfactor); var drawx = 0 - (this.hotspotX * cr.abs(w)) var drawy = 0 - (this.hotspotY * cr.abs(h)); if (spritesheeted) { ctx.drawImage(cur_image, cur_frame.offx, cur_frame.offy, cur_frame.width, cur_frame.height, drawx, drawy, cr.abs(w), cr.abs(h)); } else { ctx.drawImage(cur_image, drawx, drawy, cr.abs(w), cr.abs(h)); } ctx.restore(); } /* ctx.strokeStyle = "#f00"; ctx.lineWidth = 3; ctx.beginPath(); this.collision_poly.cache_poly(this.width, this.height, this.angle); var i, len, ax, ay, bx, by; for (i = 0, len = this.collision_poly.pts_count; i < len; i++) { ax = this.collision_poly.pts_cache[i*2] + this.x; ay = this.collision_poly.pts_cache[i*2+1] + this.y; bx = this.collision_poly.pts_cache[((i+1)%len)*2] + this.x; by = this.collision_poly.pts_cache[((i+1)%len)*2+1] + this.y; ctx.moveTo(ax, ay); ctx.lineTo(bx, by); } ctx.stroke(); ctx.closePath(); */ /* if (this.behavior_insts.length >= 1 && this.behavior_insts[0].draw) { this.behavior_insts[0].draw(ctx); } */ }; instanceProto.drawGL_earlyZPass = function(glw) { this.drawGL(glw); }; instanceProto.drawGL = function(glw) { glw.setTexture(this.curWebGLTexture); glw.setOpacity(this.opacity); var cur_frame = this.curFrame; var q = this.bquad; if (this.runtime.pixel_rounding) { var ox = Math.round(this.x) - this.x; var oy = Math.round(this.y) - this.y; if (cur_frame.spritesheeted) 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, cur_frame.sheetTex); else glw.quad(q.tlx + ox, q.tly + oy, q.trx + ox, q.try_ + oy, q.brx + ox, q.bry + oy, q.blx + ox, q.bly + oy); } else { if (cur_frame.spritesheeted) glw.quadTex(q.tlx, q.tly, q.trx, q.try_, q.brx, q.bry, q.blx, q.bly, cur_frame.sheetTex); else glw.quad(q.tlx, q.tly, q.trx, q.try_, q.brx, q.bry, q.blx, q.bly); } }; instanceProto.getImagePointIndexByName = function(name_) { var cur_frame = this.curFrame; var i, len; for (i = 0, len = cur_frame.image_points.length; i < len; i++) { if (cr.equals_nocase(name_, cur_frame.image_points[i][0])) return i; } return -1; }; instanceProto.getImagePoint = function(imgpt, getX) { var cur_frame = this.curFrame; var image_points = cur_frame.image_points; var index; if (cr.is_string(imgpt)) index = this.getImagePointIndexByName(imgpt); else index = imgpt - 1; // 0 is origin index = cr.floor(index); if (index < 0 || index >= image_points.length) return getX ? this.x : this.y; // return origin var x = (image_points[index][1] - cur_frame.hotspotX) * this.width; var y = image_points[index][2]; y = (y - cur_frame.hotspotY) * this.height; var cosa = Math.cos(this.angle); var sina = Math.sin(this.angle); var x_temp = (x * cosa) - (y * sina); y = (y * cosa) + (x * sina); x = x_temp; x += this.x; y += this.y; return getX ? x : y; }; function Cnds() {}; var arrCache = []; function allocArr() { if (arrCache.length) return arrCache.pop(); else return [0, 0, 0]; }; function freeArr(a) { a[0] = 0; a[1] = 0; a[2] = 0; arrCache.push(a); }; function makeCollKey(a, b) { if (a < b) return "" + a + "," + b; else return "" + b + "," + a; }; function collmemory_add(collmemory, a, b, tickcount) { var a_uid = a.uid; var b_uid = b.uid; var key = makeCollKey(a_uid, b_uid); if (collmemory.hasOwnProperty(key)) { collmemory[key][2] = tickcount; return; } var arr = allocArr(); arr[0] = a_uid; arr[1] = b_uid; arr[2] = tickcount; collmemory[key] = arr; }; function collmemory_remove(collmemory, a, b) { var key = makeCollKey(a.uid, b.uid); if (collmemory.hasOwnProperty(key)) { freeArr(collmemory[key]); delete collmemory[key]; } }; function collmemory_removeInstance(collmemory, inst) { var uid = inst.uid; var p, entry; for (p in collmemory) { if (collmemory.hasOwnProperty(p)) { entry = collmemory[p]; if (entry[0] === uid || entry[1] === uid) { freeArr(collmemory[p]); delete collmemory[p]; } } } }; var last_coll_tickcount = -2; function collmemory_has(collmemory, a, b) { var key = makeCollKey(a.uid, b.uid); if (collmemory.hasOwnProperty(key)) { last_coll_tickcount = collmemory[key][2]; return true; } else { last_coll_tickcount = -2; return false; } }; var candidates1 = []; Cnds.prototype.OnCollision = function (rtype) { if (!rtype) return false; var runtime = this.runtime; var cnd = runtime.getCurrentCondition(); var ltype = cnd.type; var collmemory = null; if (cnd.extra["collmemory"]) { collmemory = cnd.extra["collmemory"]; } else { collmemory = {}; cnd.extra["collmemory"] = collmemory; } if (!cnd.extra["spriteCreatedDestroyCallback"]) { cnd.extra["spriteCreatedDestroyCallback"] = true; runtime.addDestroyCallback(function(inst) { collmemory_removeInstance(cnd.extra["collmemory"], inst); }); } var lsol = ltype.getCurrentSol(); var rsol = rtype.getCurrentSol(); var linstances = lsol.getObjects(); var rinstances; var registeredInstances; var l, linst, r, rinst; var curlsol, currsol; var tickcount = this.runtime.tickcount; var lasttickcount = tickcount - 1; var exists, run; var current_event = runtime.getCurrentEventStack().current_event; var orblock = current_event.orblock; for (l = 0; l < linstances.length; l++) { linst = linstances[l]; if (rsol.select_all) { linst.update_bbox(); this.runtime.getCollisionCandidates(linst.layer, rtype, linst.bbox, candidates1); rinstances = candidates1; this.runtime.addRegisteredCollisionCandidates(linst, rtype, rinstances); } else { rinstances = rsol.getObjects(); } for (r = 0; r < rinstances.length; r++) { rinst = rinstances[r]; if (runtime.testOverlap(linst, rinst) || runtime.checkRegisteredCollision(linst, rinst)) { exists = collmemory_has(collmemory, linst, rinst); run = (!exists || (last_coll_tickcount < lasttickcount)); collmemory_add(collmemory, linst, rinst, tickcount); if (run) { runtime.pushCopySol(current_event.solModifiers); curlsol = ltype.getCurrentSol(); currsol = rtype.getCurrentSol(); curlsol.select_all = false; currsol.select_all = false; if (ltype === rtype) { curlsol.instances.length = 2; // just use lsol, is same reference as rsol curlsol.instances[0] = linst; curlsol.instances[1] = rinst; ltype.applySolToContainer(); } else { curlsol.instances.length = 1; currsol.instances.length = 1; curlsol.instances[0] = linst; currsol.instances[0] = rinst; ltype.applySolToContainer(); rtype.applySolToContainer(); } current_event.retrigger(); runtime.popSol(current_event.solModifiers); } } else { collmemory_remove(collmemory, linst, rinst); } } cr.clearArray(candidates1); } return false; }; var rpicktype = null; var rtopick = new cr.ObjectSet(); var needscollisionfinish = false; var candidates2 = []; var temp_bbox = new cr.rect(0, 0, 0, 0); function DoOverlapCondition(rtype, offx, offy) { if (!rtype) return false; var do_offset = (offx !== 0 || offy !== 0); var oldx, oldy, ret = false, r, lenr, rinst; var cnd = this.runtime.getCurrentCondition(); var ltype = cnd.type; var inverted = cnd.inverted; var rsol = rtype.getCurrentSol(); var orblock = this.runtime.getCurrentEventStack().current_event.orblock; var rinstances; if (rsol.select_all) { this.update_bbox(); temp_bbox.copy(this.bbox); temp_bbox.offset(offx, offy); this.runtime.getCollisionCandidates(this.layer, rtype, temp_bbox, candidates2); rinstances = candidates2; } else if (orblock) { if (this.runtime.isCurrentConditionFirst() && !rsol.else_instances.length && rsol.instances.length) rinstances = rsol.instances; else rinstances = rsol.else_instances; } else { rinstances = rsol.instances; } rpicktype = rtype; needscollisionfinish = (ltype !== rtype && !inverted); if (do_offset) { oldx = this.x; oldy = this.y; this.x += offx; this.y += offy; this.set_bbox_changed(); } for (r = 0, lenr = rinstances.length; r < lenr; r++) { rinst = rinstances[r]; if (this.runtime.testOverlap(this, rinst)) { ret = true; if (inverted) break; if (ltype !== rtype) rtopick.add(rinst); } } if (do_offset) { this.x = oldx; this.y = oldy; this.set_bbox_changed(); } cr.clearArray(candidates2); return ret; }; typeProto.finish = function (do_pick) { if (!needscollisionfinish) return; if (do_pick) { var orblock = this.runtime.getCurrentEventStack().current_event.orblock; var sol = rpicktype.getCurrentSol(); var topick = rtopick.valuesRef(); var i, len, inst; if (sol.select_all) { sol.select_all = false; cr.clearArray(sol.instances); for (i = 0, len = topick.length; i < len; ++i) { sol.instances[i] = topick[i]; } if (orblock) { cr.clearArray(sol.else_instances); for (i = 0, len = rpicktype.instances.length; i < len; ++i) { inst = rpicktype.instances[i]; if (!rtopick.contains(inst)) sol.else_instances.push(inst); } } } else { if (orblock) { var initsize = sol.instances.length; for (i = 0, len = topick.length; i < len; ++i) { sol.instances[initsize + i] = topick[i]; cr.arrayFindRemove(sol.else_instances, topick[i]); } } else { cr.shallowAssignArray(sol.instances, topick); } } rpicktype.applySolToContainer(); } rtopick.clear(); needscollisionfinish = false; }; Cnds.prototype.IsOverlapping = function (rtype) { return DoOverlapCondition.call(this, rtype, 0, 0); }; Cnds.prototype.IsOverlappingOffset = function (rtype, offx, offy) { return DoOverlapCondition.call(this, rtype, offx, offy); }; Cnds.prototype.IsAnimPlaying = function (animname) { if (this.changeAnimName.length) return cr.equals_nocase(this.changeAnimName, animname); else return cr.equals_nocase(this.cur_animation.name, animname); }; Cnds.prototype.CompareFrame = function (cmp, framenum) { return cr.do_cmp(this.cur_frame, cmp, framenum); }; Cnds.prototype.CompareAnimSpeed = function (cmp, x) { var s = (this.animForwards ? this.cur_anim_speed : -this.cur_anim_speed); return cr.do_cmp(s, cmp, x); }; Cnds.prototype.OnAnimFinished = function (animname) { return cr.equals_nocase(this.animTriggerName, animname); }; Cnds.prototype.OnAnyAnimFinished = function () { return true; }; Cnds.prototype.OnFrameChanged = function () { return true; }; Cnds.prototype.IsMirrored = function () { return this.width < 0; }; Cnds.prototype.IsFlipped = function () { return this.height < 0; }; Cnds.prototype.OnURLLoaded = function () { return true; }; Cnds.prototype.IsCollisionEnabled = function () { return this.collisionsEnabled; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Spawn = function (obj, layer, imgpt) { if (!obj || !layer) return; var inst = this.runtime.createInstance(obj, layer, this.getImagePoint(imgpt, true), this.getImagePoint(imgpt, false)); if (!inst) return; if (typeof inst.angle !== "undefined") { inst.angle = this.angle; inst.set_bbox_changed(); } this.runtime.isInOnDestroy++; var i, len, s; this.runtime.trigger(Object.getPrototypeOf(obj.plugin).cnds.OnCreated, inst); if (inst.is_contained) { for (i = 0, len = inst.siblings.length; i < len; i++) { s = inst.siblings[i]; this.runtime.trigger(Object.getPrototypeOf(s.type.plugin).cnds.OnCreated, s); } } this.runtime.isInOnDestroy--; var cur_act = this.runtime.getCurrentAction(); var reset_sol = false; if (cr.is_undefined(cur_act.extra["Spawn_LastExec"]) || cur_act.extra["Spawn_LastExec"] < this.runtime.execcount) { reset_sol = true; cur_act.extra["Spawn_LastExec"] = this.runtime.execcount; } var sol; if (obj != this.type) { sol = obj.getCurrentSol(); sol.select_all = false; if (reset_sol) { cr.clearArray(sol.instances); sol.instances[0] = inst; } else sol.instances.push(inst); if (inst.is_contained) { for (i = 0, len = inst.siblings.length; i < len; i++) { s = inst.siblings[i]; sol = s.type.getCurrentSol(); sol.select_all = false; if (reset_sol) { cr.clearArray(sol.instances); sol.instances[0] = s; } else sol.instances.push(s); } } } }; Acts.prototype.SetEffect = function (effect) { this.blend_mode = effect; this.compositeOp = cr.effectToCompositeOp(effect); cr.setGLBlend(this, effect, this.runtime.gl); this.runtime.redraw = true; }; Acts.prototype.StopAnim = function () { this.animPlaying = false; }; Acts.prototype.StartAnim = function (from) { this.animPlaying = true; this.frameStart = this.getNowTime(); if (from === 1 && this.cur_frame !== 0) { this.changeAnimFrame = 0; if (!this.inAnimTrigger) this.doChangeAnimFrame(); } if (!this.isTicking) { this.runtime.tickMe(this); this.isTicking = true; } }; Acts.prototype.SetAnim = function (animname, from) { this.changeAnimName = animname; this.changeAnimFrom = from; if (!this.isTicking) { this.runtime.tickMe(this); this.isTicking = true; } if (!this.inAnimTrigger) this.doChangeAnim(); }; Acts.prototype.SetAnimFrame = function (framenumber) { this.changeAnimFrame = framenumber; if (!this.isTicking) { this.runtime.tickMe(this); this.isTicking = true; } if (!this.inAnimTrigger) this.doChangeAnimFrame(); }; Acts.prototype.SetAnimSpeed = function (s) { this.cur_anim_speed = cr.abs(s); this.animForwards = (s >= 0); if (!this.isTicking) { this.runtime.tickMe(this); this.isTicking = true; } }; Acts.prototype.SetAnimRepeatToFrame = function (s) { s = Math.floor(s); if (s < 0) s = 0; if (s >= this.cur_animation.frames.length) s = this.cur_animation.frames.length - 1; this.cur_anim_repeatto = s; }; Acts.prototype.SetMirrored = function (m) { var neww = cr.abs(this.width) * (m === 0 ? -1 : 1); if (this.width === neww) return; this.width = neww; this.set_bbox_changed(); }; Acts.prototype.SetFlipped = function (f) { var newh = cr.abs(this.height) * (f === 0 ? -1 : 1); if (this.height === newh) return; this.height = newh; this.set_bbox_changed(); }; Acts.prototype.SetScale = function (s) { var cur_frame = this.curFrame; var mirror_factor = (this.width < 0 ? -1 : 1); var flip_factor = (this.height < 0 ? -1 : 1); var new_width = cur_frame.width * s * mirror_factor; var new_height = cur_frame.height * s * flip_factor; if (this.width !== new_width || this.height !== new_height) { this.width = new_width; this.height = new_height; this.set_bbox_changed(); } }; Acts.prototype.LoadURL = function (url_, resize_, crossOrigin_) { var img = new Image(); var self = this; var curFrame_ = this.curFrame; img.onload = function () { if (curFrame_.texture_img.src === img.src) { if (self.runtime.glwrap && self.curFrame === curFrame_) self.curWebGLTexture = curFrame_.webGL_texture; if (resize_ === 0) // resize to image size { self.width = img.width; self.height = img.height; self.set_bbox_changed(); } self.runtime.redraw = true; self.runtime.trigger(cr.plugins_.Sprite.prototype.cnds.OnURLLoaded, self); return; } curFrame_.texture_img = img; curFrame_.offx = 0; curFrame_.offy = 0; curFrame_.width = img.width; curFrame_.height = img.height; curFrame_.spritesheeted = false; curFrame_.datauri = ""; curFrame_.pixelformat = 0; // reset to RGBA, since we don't know what type of image will have come in if (self.runtime.glwrap) { if (curFrame_.webGL_texture) self.runtime.glwrap.deleteTexture(curFrame_.webGL_texture); curFrame_.webGL_texture = self.runtime.glwrap.loadTexture(img, false, self.runtime.linearSampling); if (self.curFrame === curFrame_) self.curWebGLTexture = curFrame_.webGL_texture; self.type.updateAllCurrentTexture(); } if (resize_ === 0) // resize to image size { self.width = img.width; self.height = img.height; self.set_bbox_changed(); } self.runtime.redraw = true; self.runtime.trigger(cr.plugins_.Sprite.prototype.cnds.OnURLLoaded, self); }; if (url_.substr(0, 5) !== "data:" && crossOrigin_ === 0) img["crossOrigin"] = "anonymous"; this.runtime.setImageSrc(img, url_); }; Acts.prototype.SetCollisions = function (set_) { if (this.collisionsEnabled === (set_ !== 0)) return; // no change this.collisionsEnabled = (set_ !== 0); if (this.collisionsEnabled) this.set_bbox_changed(); // needs to be added back to cells else { if (this.collcells.right >= this.collcells.left) this.type.collision_grid.update(this, this.collcells, null); this.collcells.set(0, 0, -1, -1); } }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.AnimationFrame = function (ret) { ret.set_int(this.cur_frame); }; Exps.prototype.AnimationFrameCount = function (ret) { ret.set_int(this.cur_animation.frames.length); }; Exps.prototype.AnimationName = function (ret) { ret.set_string(this.cur_animation.name); }; Exps.prototype.AnimationSpeed = function (ret) { ret.set_float(this.animForwards ? this.cur_anim_speed : -this.cur_anim_speed); }; Exps.prototype.ImagePointX = function (ret, imgpt) { ret.set_float(this.getImagePoint(imgpt, true)); }; Exps.prototype.ImagePointY = function (ret, imgpt) { ret.set_float(this.getImagePoint(imgpt, false)); }; Exps.prototype.ImagePointCount = function (ret) { ret.set_int(this.curFrame.image_points.length); }; Exps.prototype.ImageWidth = function (ret) { ret.set_float(this.curFrame.width); }; Exps.prototype.ImageHeight = function (ret) { ret.set_float(this.curFrame.height); }; pluginProto.exps = new Exps(); }()); /* global cr,log,assert2 */ /* jshint globalstrict: true */ /* jshint strict: true */ ; ; var jText = ''; cr.plugins_.SpriteFontPlus = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.SpriteFontPlus.prototype; pluginProto.onCreate = function () { }; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { if (this.is_family) return; this.texture_img = new Image(); this.texture_img["idtkLoadDisposed"] = true; this.texture_img.src = this.texture_file; this.runtime.wait_for_textures.push(this.texture_img); this.webGL_texture = null; }; typeProto.onLostWebGLContext = function () { if (this.is_family) return; this.webGL_texture = null; }; typeProto.onRestoreWebGLContext = function () { if (this.is_family || !this.instances.length) return; if (!this.webGL_texture) { this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, false, this.runtime.linearSampling, this.texture_pixelformat); } var i, len; for (i = 0, len = this.instances.length; i < len; i++) this.instances[i].webGL_texture = this.webGL_texture; }; typeProto.unloadTextures = function () { if (this.is_family || this.instances.length || !this.webGL_texture) return; this.runtime.glwrap.deleteTexture(this.webGL_texture); this.webGL_texture = null; }; typeProto.preloadCanvas2D = function (ctx) { ctx.drawImage(this.texture_img, 0, 0); }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onDestroy = function() { freeAllLines (this.lines); freeAllClip (this.clipList); freeAllClipUV(this.clipUV); cr.wipe(this.characterWidthList); }; instanceProto.onCreate = function() { this.texture_img = this.type.texture_img; this.characterWidth = this.properties[0]; this.characterHeight = this.properties[1]; this.characterSet = this.properties[2]; this.text = this.properties[3]; this.characterScale = this.properties[4]; this.visible = (this.properties[5] === 0); // 0=visible, 1=invisible this.halign = this.properties[6]/2.0; // 0=left, 1=center, 2=right this.valign = this.properties[7]/2.0; // 0=top, 1=center, 2=bottom this.wrapbyword = (this.properties[9] === 0); // 0=word, 1=character this.characterSpacing = this.properties[10]; this.lineHeight = this.properties[11]; this.textWidth = 0; this.textHeight = 0; this.charWidthJSON = this.properties[12]; this.spaceWidth = this.properties[13]; jText = this.charWidthJSON; if (this.recycled) { this.lines.length = 0; cr.wipe(this.clipList); cr.wipe(this.clipUV); cr.wipe(this.characterWidthList); } else { this.lines = []; this.clipList = {}; this.clipUV = {}; this.characterWidthList = {}; } try{ if(this.charWidthJSON){ if(this.charWidthJSON.indexOf('""c2array""') !== -1) { var jStr = jQuery.parseJSON(this.charWidthJSON.replace(/""/g,'"')); var l = jStr.size[1]; for(var s = 0; s < l; s++) { var cs = jStr.data[1][s][0]; var w = jStr.data[0][s][0]; for(var c = 0; c < cs.length; c++) { this.characterWidthList[cs.charAt(c)] = w } } } else { var jStr = jQuery.parseJSON(this.charWidthJSON); var l = jStr.length; for(var s = 0; s < l; s++) { var cs = jStr[s][1]; var w = jStr[s][0]; for(var c = 0; c < cs.length; c++) { this.characterWidthList[cs.charAt(c)] = w } } } } if(this.spaceWidth !== -1) { this.characterWidthList[' '] = this.spaceWidth; } } catch(e){ if(window.console && window.console.log) { window.console.log('SpriteFont+ Failure: ' + e); } } this.text_changed = true; this.lastwrapwidth = this.width; if (this.runtime.glwrap) { if (!this.type.webGL_texture) { this.type.webGL_texture = this.runtime.glwrap.loadTexture(this.type.texture_img, false, this.runtime.linearSampling, this.type.texture_pixelformat); } this.webGL_texture = this.type.webGL_texture; } this.SplitSheet(); }; instanceProto.saveToJSON = function () { var save = { "t": this.text, "csc": this.characterScale, "csp": this.characterSpacing, "lh": this.lineHeight, "tw": this.textWidth, "th": this.textHeight, "lrt": this.last_render_tick, "cw": {} }; for (var ch in this.characterWidthList) save["cw"][ch] = this.characterWidthList[ch]; return save; }; instanceProto.loadFromJSON = function (o) { this.text = o["t"]; this.characterScale = o["csc"]; this.characterSpacing = o["csp"]; this.lineHeight = o["lh"]; this.textWidth = o["tw"]; this.textHeight = o["th"]; this.last_render_tick = o["lrt"]; for(var ch in o["cw"]) this.characterWidthList[ch] = o["cw"][ch]; this.text_changed = true; this.lastwrapwidth = this.width; }; function trimRight(text) { return text.replace(/\s\s*$/, ''); } var MAX_CACHE_SIZE = 1000; function alloc(cache,Constructor) { if (cache.length) return cache.pop(); else return new Constructor(); } function free(cache,data) { if (cache.length < MAX_CACHE_SIZE) { cache.push(data); } } function freeAll(cache,dataList,isArray) { if (isArray) { var i, len; for (i = 0, len = dataList.length; i < len; i++) { free(cache,dataList[i]); } dataList.length = 0; } else { var prop; for(prop in dataList) { if(Object.prototype.hasOwnProperty.call(dataList,prop)) { free(cache,dataList[prop]); delete dataList[prop]; } } } } function addLine(inst,lineIndex,cur_line) { var lines = inst.lines; var line; cur_line = trimRight(cur_line); if (lineIndex >= lines.length) lines.push(allocLine()); line = lines[lineIndex]; line.text = cur_line; line.width = inst.measureWidth(cur_line); inst.textWidth = cr.max(inst.textWidth,line.width); } var linesCache = []; function allocLine() { return alloc(linesCache,Object); } function freeLine(l) { free(linesCache,l); } function freeAllLines(arr) { freeAll(linesCache,arr,true); } function addClip(obj,property,x,y,w,h) { if (obj[property] === undefined) { obj[property] = alloc(clipCache,Object); } obj[property].x = x; obj[property].y = y; obj[property].w = w; obj[property].h = h; } var clipCache = []; function allocClip() { return alloc(clipCache,Object); } function freeAllClip(obj) { freeAll(clipCache,obj,false);} function addClipUV(obj,property,left,top,right,bottom) { if (obj[property] === undefined) { obj[property] = alloc(clipUVCache,cr.rect); } obj[property].left = left; obj[property].top = top; obj[property].right = right; obj[property].bottom = bottom; } var clipUVCache = []; function allocClipUV() { return alloc(clipUVCache,cr.rect);} function freeAllClipUV(obj) { freeAll(clipUVCache,obj,false);} instanceProto.SplitSheet = function() { var texture = this.texture_img; var texWidth = texture.width; var texHeight = texture.height; var charWidth = this.characterWidth; var charHeight = this.characterHeight; var charU = charWidth /texWidth; var charV = charHeight/texHeight; var charSet = this.characterSet ; var cols = Math.floor(texWidth/charWidth); var rows = Math.floor(texHeight/charHeight); for ( var c = 0; c < charSet.length; c++) { if (c >= cols * rows) break; var x = c%cols; var y = Math.floor(c/cols); var letter = charSet.charAt(c); if (this.runtime.glwrap) { addClipUV( this.clipUV, letter, x * charU , y * charV , (x+1) * charU , (y+1) * charV ); } else { addClip( this.clipList, letter, x * charWidth, y * charHeight, charWidth, charHeight ); } } }; /* * Word-Wrapping */ var wordsCache = []; pluginProto.TokeniseWords = function (text) { wordsCache.length = 0; var cur_word = ""; var ch; var i = 0; while (i < text.length) { ch = text.charAt(i); if (ch === "\n") { if (cur_word.length) { wordsCache.push(cur_word); cur_word = ""; } wordsCache.push("\n"); ++i; } else if (ch === " " || ch === "\t" || ch === "-") { do { cur_word += text.charAt(i); i++; } while (i < text.length && (text.charAt(i) === " " || text.charAt(i) === "\t")); wordsCache.push(cur_word); cur_word = ""; } else if (i < text.length) { cur_word += ch; i++; } } if (cur_word.length) wordsCache.push(cur_word); }; pluginProto.WordWrap = function (inst) { var text = inst.text; var lines = inst.lines; if (!text || !text.length) { freeAllLines(lines); return; } var width = inst.width; if (width <= 2.0) { freeAllLines(lines); return; } var charWidth = inst.characterWidth; var charScale = inst.characterScale; var charSpacing = inst.characterSpacing; if ( (text.length * (charWidth * charScale + charSpacing) - charSpacing) <= width && text.indexOf("\n") === -1) { var all_width = inst.measureWidth(text); if (all_width <= width) { freeAllLines(lines); lines.push(allocLine()); lines[0].text = text; lines[0].width = all_width; inst.textWidth = all_width; inst.textHeight = inst.characterHeight * charScale + inst.lineHeight; return; } } var wrapbyword = inst.wrapbyword; this.WrapText(inst); inst.textHeight = lines.length * (inst.characterHeight * charScale + inst.lineHeight); }; pluginProto.WrapText = function (inst) { var wrapbyword = inst.wrapbyword; var text = inst.text; var lines = inst.lines; var width = inst.width; var wordArray; if (wrapbyword) { this.TokeniseWords(text); // writes to wordsCache wordArray = wordsCache; } else { wordArray = text; } var cur_line = ""; var prev_line; var line_width; var i; var lineIndex = 0; var line; var ignore_newline = false; for (i = 0; i < wordArray.length; i++) { if (wordArray[i] === "\n") { if (ignore_newline === true) { ignore_newline = false; } else { addLine(inst,lineIndex,cur_line); lineIndex++; } cur_line = ""; continue; } ignore_newline = false; prev_line = cur_line; cur_line += wordArray[i]; line_width = inst.measureWidth(trimRight(cur_line)); if (line_width > width) { if (prev_line === "") { addLine(inst,lineIndex,cur_line); cur_line = ""; ignore_newline = true; } else { addLine(inst,lineIndex,prev_line); cur_line = wordArray[i]; } lineIndex++; if (!wrapbyword && cur_line === " ") cur_line = ""; } } if (trimRight(cur_line).length) { addLine(inst,lineIndex,cur_line); lineIndex++; } for (i = lineIndex; i < lines.length; i++) freeLine(lines[i]); lines.length = lineIndex; }; instanceProto.measureWidth = function(text) { var spacing = this.characterSpacing; var len = text.length; var width = 0; for (var i = 0; i < len; i++) { width += this.getCharacterWidth(text.charAt(i)) * this.characterScale + spacing; } width -= (width > 0) ? spacing : 0; return width; }; /***/ instanceProto.getCharacterWidth = function(character) { var widthList = this.characterWidthList; if (widthList[character] !== undefined) { return widthList[character]; } else { return this.characterWidth; } }; instanceProto.rebuildText = function() { if (this.text_changed || this.width !== this.lastwrapwidth) { this.textWidth = 0; this.textHeight = 0; this.type.plugin.WordWrap(this); this.text_changed = false; this.lastwrapwidth = this.width; } }; var EPSILON = 0.00001; instanceProto.draw = function(ctx, glmode) { var texture = this.texture_img; if (this.text !== "" && texture != null) { this.rebuildText(); if (this.height < this.characterHeight*this.characterScale + this.lineHeight) { return; } ctx.globalAlpha = this.opacity; var myx = this.x; var myy = this.y; if (this.runtime.pixel_rounding) { myx = (myx + 0.5) | 0; myy = (myy + 0.5) | 0; } ctx.save(); ctx.translate(myx, myy); ctx.rotate(this.angle); var ha = this.halign; var va = this.valign; var scale = this.characterScale; var charHeight = this.characterHeight * scale; var lineHeight = this.lineHeight; var charSpace = this.characterSpacing; var lines = this.lines; var textHeight = this.textHeight; var halign; var valign = va * cr.max(0,(this.height - textHeight)); var offx = -(this.hotspotX * this.width); var offy = -(this.hotspotY * this.height); offy += valign; var drawX ; var drawY = offy; for(var i = 0; i < lines.length; i++) { var line = lines[i].text; var len = lines[i].width; halign = ha * cr.max(0,this.width - len); drawX = offx + halign; drawY += lineHeight; for(var j = 0; j < line.length; j++) { var letter = line.charAt(j); var clip = this.clipList[letter]; if ( drawX + this.getCharacterWidth(letter) * scale > this.width + EPSILON ) { break; } if (clip !== undefined) { ctx.drawImage( this.texture_img, clip.x, clip.y, clip.w, clip.h, Math.round(drawX),Math.round(drawY),clip.w*scale,clip.h*scale); } drawX += this.getCharacterWidth(letter) * scale + charSpace; } drawY += charHeight; if ( drawY + charHeight + lineHeight > this.height) { break; } } ctx.restore(); } }; var dQuad = new cr.quad(); function rotateQuad(quad,cosa,sina) { var x_temp; x_temp = (quad.tlx * cosa) - (quad.tly * sina); quad.tly = (quad.tly * cosa) + (quad.tlx * sina); quad.tlx = x_temp; x_temp = (quad.trx * cosa) - (quad.try_ * sina); quad.try_ = (quad.try_ * cosa) + (quad.trx * sina); quad.trx = x_temp; x_temp = (quad.blx * cosa) - (quad.bly * sina); quad.bly = (quad.bly * cosa) + (quad.blx * sina); quad.blx = x_temp; x_temp = (quad.brx * cosa) - (quad.bry * sina); quad.bry = (quad.bry * cosa) + (quad.brx * sina); quad.brx = x_temp; } instanceProto.drawGL = function(glw) { glw.setTexture(this.webGL_texture); glw.setOpacity(this.opacity); if (this.text !== "") { this.rebuildText(); if (this.height < this.characterHeight*this.characterScale + this.lineHeight) { return; } this.update_bbox(); var q = this.bquad; var ox = 0; var oy = 0; if (this.runtime.pixel_rounding) { ox = ((this.x + 0.5) | 0) - this.x; oy = ((this.y + 0.5) | 0) - this.y; } var angle = this.angle; var ha = this.halign; var va = this.valign; var scale = this.characterScale; var charHeight = this.characterHeight * scale; // to precalculate in onCreate or on change var lineHeight = this.lineHeight; var charSpace = this.characterSpacing; var lines = this.lines; var textHeight = this.textHeight; var cosa,sina; if (angle !== 0) { cosa = Math.cos(angle); sina = Math.sin(angle); } var halign; var valign = va * cr.max(0,(this.height - textHeight)); var offx = q.tlx + ox; var offy = q.tly + oy; var drawX ; var drawY = valign; for(var i = 0; i < lines.length; i++) { var line = lines[i].text; var lineWidth = lines[i].width; halign = ha * cr.max(0,this.width - lineWidth); drawX = halign; drawY += lineHeight; for(var j = 0; j < line.length; j++) { var letter = line.charAt(j); var clipUV = this.clipUV[letter]; if ( drawX + this.getCharacterWidth(letter) * scale > this.width + EPSILON) { break; } if (clipUV !== undefined) { var clipWidth = this.characterWidth*scale; var clipHeight = this.characterHeight*scale; dQuad.tlx = drawX; dQuad.tly = drawY; dQuad.trx = drawX + clipWidth; dQuad.try_ = drawY ; dQuad.blx = drawX; dQuad.bly = drawY + clipHeight; dQuad.brx = drawX + clipWidth; dQuad.bry = drawY + clipHeight; if(angle !== 0) { rotateQuad(dQuad,cosa,sina); } dQuad.offset(offx,offy); glw.quadTex( dQuad.tlx, dQuad.tly, dQuad.trx, dQuad.try_, dQuad.brx, dQuad.bry, dQuad.blx, dQuad.bly, clipUV ); } drawX += this.getCharacterWidth(letter) * scale + charSpace; } drawY += charHeight; if ( drawY + charHeight + lineHeight > this.height) { break; } } } }; function Cnds() {} Cnds.prototype.CompareText = function(text_to_compare, case_sensitive) { if (case_sensitive) return this.text == text_to_compare; else return cr.equals_nocase(this.text, text_to_compare); }; pluginProto.cnds = new Cnds(); function Acts() {} Acts.prototype.SetText = function(param) { if (cr.is_number(param) && param < 1e9) param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors var text_to_set = param.toString(); if (this.text !== text_to_set) { this.text = text_to_set; this.text_changed = true; this.runtime.redraw = true; } }; Acts.prototype.AppendText = function(param) { if (cr.is_number(param)) param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors var text_to_append = param.toString(); if (text_to_append) // not empty { this.text += text_to_append; this.text_changed = true; this.runtime.redraw = true; } }; Acts.prototype.SetScale = function(param) { if (param !== this.characterScale) { this.characterScale = param; this.text_changed = true; this.runtime.redraw = true; } }; Acts.prototype.SetCharacterSpacing = function(param) { if (param !== this.CharacterSpacing) { this.characterSpacing = param; this.text_changed = true; this.runtime.redraw = true; } }; Acts.prototype.SetLineHeight = function(param) { if (param !== this.lineHeight) { this.lineHeight = param; this.text_changed = true; this.runtime.redraw = true; } }; instanceProto.SetCharWidth = function(character,width) { var w = parseInt(width,10); if (this.characterWidthList[character] !== w) { this.characterWidthList[character] = w; this.text_changed = true; this.runtime.redraw = true; } }; Acts.prototype.SetCharacterWidth = function(characterSet,width) { if (characterSet !== "") { for(var c = 0; c < characterSet.length; c++) { this.SetCharWidth(characterSet.charAt(c),width); } } }; Acts.prototype.SetEffect = function (effect) { this.compositeOp = cr.effectToCompositeOp(effect); cr.setGLBlend(this, effect, this.runtime.gl); this.runtime.redraw = true; }; pluginProto.acts = new Acts(); function Exps() {} Exps.prototype.CharacterWidth = function(ret,character) { ret.set_int(this.getCharacterWidth(character)); }; Exps.prototype.CharacterHeight = function(ret) { ret.set_int(this.characterHeight); }; Exps.prototype.CharacterScale = function(ret) { ret.set_float(this.characterScale); }; Exps.prototype.CharacterSpacing = function(ret) { ret.set_int(this.characterSpacing); }; Exps.prototype.LineHeight = function(ret) { ret.set_int(this.lineHeight); }; Exps.prototype.Text = function(ret) { ret.set_string(this.text); }; Exps.prototype.TextWidth = function (ret) { this.rebuildText(); ret.set_float(this.textWidth); }; Exps.prototype.TextHeight = function (ret) { this.rebuildText(); ret.set_float(this.textHeight); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.SyncStorage = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.SyncStorage.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.data = {}; this.isStorageLoaded = false; this.storageIndex = this.properties[1]; this.isEncodingEnabled = !this.properties[3]; this.headSalt = this.properties[4]; this.tailSalt = this.properties[5]; this.isLocalStorageLoaded = null; this.LS_Instance = null; this.LS_ProtoActions = null; this.lastErrorMsg = null; }; instanceProto.onDestroy = function () { }; instanceProto.isLocalStorageReady = function() { if (this.isLocalStorageLoaded) return true; if ( ! this.storageIndex) return false; if(cr.plugins_.LocalStorage) // check if LocalStorage plugin is added to the project { var type, LS_Type; for (type in this.runtime.types) { if ( ! this.runtime.types.hasOwnProperty(type)) continue; if (this.runtime.types[type].plugin instanceof cr.plugins_.LocalStorage) { LS_Type = this.runtime.types[type]; break; } } if (LS_Type) { this.LS_Instance = LS_Type.instances[0]; this.LS_ProtoActions = cr.plugins_.LocalStorage.prototype.acts; return true; } } console.log("\n*\n*\n*\nERROR: LocalStorage plugin not found. You must add LocalStorage plugin to the project. It's a JS library for SyncStorage plugin.\n*\n*\n*\n"); return false; }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnLoaded = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnLoadError = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.IsLoaded = function() { return this.isStorageLoaded; }; /** * @returns {boolean} */ Cnds.prototype.HasData = function(index_) { return this.hasData(index_); }; /** * @returns {boolean} */ Cnds.prototype.CompareData = function(dataIndex_, cmp_, value_) { return cr.do_cmp(this.data[dataIndex_], cmp_, value_); }; /** * @returns {boolean} */ Cnds.prototype.OnSave = function() { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnDataMissing = function() { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetData = function(index_, value_) { this.data[index_] = value_; }; Acts.prototype.SaveData = function() { if(this.isLocalStorageReady()) { this.LS_ProtoActions.SetItem.call(this.LS_Instance, this.storageIndex, this.isEncodingEnabled ? this.encode(JSON.stringify(this.data)) : JSON.stringify(this.data)); } this.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnSave, this); }; Acts.prototype.LoadData = function() { if( ! this.isLocalStorageReady()) { this.lastErrorMsg = "Could not load data from LocalStorage. Possible reasons: \"LocalStorage IDX\" property not set or LocalStorage plugin is not added to the project."; this.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnLoadError, this); this.lastErrorMsg = ""; return; } var self = this; localforage["getItem"](this.storageIndex, function (err, value) { if (err) { if ( ! err) err = "unknown error"; else if (typeof err.message === "string") err = err.message; else if (typeof err.name === "string") err = err.name; else if (typeof err.data === "string") err = err.data; else if (typeof err !== "string") err = "unknown error"; self.isStorageLoaded = false; self.lastErrorMsg = err; self.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnLoadError, self); self.lastErrorMsg = null; } else { if (typeof value === "undefined" || value === null || value === "") { self.data = {}; self.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnDataMissing, self); } else { if(self.isEncodingEnabled) { try { self.data = JSON.parse(self.decode(value)); } catch (e) { self.data = JSON.parse(value); } } else { try { self.data = JSON.parse(value); } catch (e) { self.data = JSON.parse(self.decode(value)); } } } self.isStorageLoaded = true; self.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnLoaded, self); } }); }; Acts.prototype.ClearData = function() { this.data = {}; }; Acts.prototype.RemoveData = function(index_) { if(typeof this.data[index_] !== "undefined") { delete this.data[index_]; } }; Acts.prototype.LoadString = function(data_) { try { if(data_ == "") { this.data = {}; this.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnDataMissing, this); } else { if(data_.charAt(0) === "{") { this.data = JSON.parse(data_); } else { this.data = JSON.parse(this.decode(data_)); } } this.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnLoaded, this); } catch(e) { this.lastErrorMsg = e.message; this.runtime.trigger(cr.plugins_.SyncStorage.prototype.cnds.OnLoadError, this); this.lastErrorMsg = ""; } }; Acts.prototype.AddValue = function(index_, value_) { if ( ! this.hasData(index_)) { this.data[index_] = 0; } if ( ! isNaN(parseFloat(value_)) && isFinite(value_)) { this.data[index_] += value_; } }; Acts.prototype.SubtractValue = function(index_, value_) { if ( ! this.hasData(index_)) { this.data[index_] = 0; } if ( ! isNaN(parseFloat(value_)) && isFinite(value_)) { this.data[index_] -= value_; } }; Acts.prototype.AppendValue = function(index_, value_) { if ( ! this.hasData(index_)) { this.data[index_] = ""; } if (typeof value_ === "string") { this.data[index_] += value_; } }; Acts.prototype.PrependValue = function(index_, value_) { if ( ! this.hasData(index_)) { this.data[index_] = ""; } if (typeof value_ === "string") { this.data[index_] = value_ + this.data[index_]; } }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.GetData = function(ret, dataIndex_) { ret.set_any(this.data[dataIndex_]); }; Exps.prototype.StorageIndex = function(ret) { ret.set_string(this.storageIndex); }; Exps.prototype.HasData = function(ret, index_) { ret.set_int(+this.hasData(index_)); }; Exps.prototype.AsJSON = function(ret) { ret.set_string(JSON.stringify(this.data)); }; Exps.prototype.AsString = function(ret) { ret.set_string(this.isEncodingEnabled ? this.encode(JSON.stringify(this.data)) : JSON.stringify(this.data)); }; Exps.prototype.ErrorMsg = function(ret) { ret.set_string(this.lastErrorMsg); }; Exps.prototype.Get = function(ret, dataIndex_) { ret.set_any(this.data[dataIndex_]); }; Exps.prototype.Has = function(ret, index_) { ret.set_int(+this.hasData(index_)); }; instanceProto.encode = function (rawData) { var encodedData = Secret.encode(rawData); var i; for (i = 0; i < this.headSalt; i++) { encodedData = encodedData.charAt(Math.floor((Math.random() * (encodedData.length-1)))) + encodedData; } for (i = 0; i < this.tailSalt; i++) { encodedData += encodedData.charAt(Math.floor((Math.random() * (encodedData.length-1)))); } return encodedData; }; instanceProto.decode = function (encodedData) { var rawData = encodedData.substring(this.headSalt); rawData = rawData.substring(0, rawData.length - this.tailSalt); rawData = Secret.decode(rawData); return rawData; }; instanceProto.hasData = function(index_) { return typeof this.data[index_] !== 'undefined'; }; pluginProto.exps = new Exps(); var Secret={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(r){var t,e,o,a,h,n,d,C="",i=0;for(r=Secret._utf8_encode(r);i>2,h=(3&t)<<4|(e=r.charCodeAt(i++))>>4,n=(15&e)<<2|(o=r.charCodeAt(i++))>>6,d=63&o,isNaN(e)?n=d=64:isNaN(o)&&(d=64),C=C+this._keyStr.charAt(a)+this._keyStr.charAt(h)+this._keyStr.charAt(n)+this._keyStr.charAt(d);return C},decode:function(r){var t,e,o,a,h,n,d="",C=0;for(r=r.replace(/[^A-Za-z0-9\+\/\=]/g,"");C>4,e=(15&a)<<4|(h=this._keyStr.indexOf(r.charAt(C++)))>>2,o=(3&h)<<6|(n=this._keyStr.indexOf(r.charAt(C++))),d+=String.fromCharCode(t),64!=h&&(d+=String.fromCharCode(e)),64!=n&&(d+=String.fromCharCode(o));return d=Secret._utf8_decode(d)},_utf8_encode:function(r){r=r.replace(/\r\n/g,"\n");for(var t="",e=0;e127&&o<2048?(t+=String.fromCharCode(o>>6|192),t+=String.fromCharCode(63&o|128)):(t+=String.fromCharCode(o>>12|224),t+=String.fromCharCode(o>>6&63|128),t+=String.fromCharCode(63&o|128))}return t},_utf8_decode:function(r){for(var t="",e=0,o=0,a=0,h=0;e191&&o<224?(a=r.charCodeAt(e+1),t+=String.fromCharCode((31&o)<<6|63&a),e+=2):(a=r.charCodeAt(e+1),h=r.charCodeAt(e+2),t+=String.fromCharCode((15&o)<<12|(63&a)<<6|63&h),e+=3);return t}}; }()); ; ; cr.plugins_.TR_ClockParser = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.TR_ClockParser.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { }; instanceProto.onDestroy = function () { }; function Cnds() {}; pluginProto.cnds = new Cnds(); function Acts() {}; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Minimal = function(ret, seconds_) { seconds_ = parseInt(seconds_, 10); var hours = Math.floor(seconds_ / 3600); var minutes = Math.floor((seconds_ - (hours * 3600)) / 60); var seconds = seconds_ - (hours * 3600) - (minutes * 60); var clockString = ""; if(hours > 0) { clockString += (hours < 10 ? "0" + hours : hours) + ":"; } if(hours > 0 || minutes > 0) { clockString += (minutes < 10 ? "0" + minutes : minutes) + ":"; } clockString += (seconds < 10 ? "0" + seconds : seconds); ret.set_string(clockString); }; Exps.prototype.MMSS = function(ret, seconds_) { seconds_ = parseInt(seconds_, 10); var minutes = Math.floor(seconds_ / 60); var seconds = seconds_ - minutes * 60; if (minutes < 10) { minutes = "0" +minutes; } if (seconds < 10) { seconds = "0" + seconds; } ret.set_string(minutes + ':' + seconds); }; Exps.prototype.HHMMSS = function(ret, seconds_) { seconds_ = parseInt(seconds_, 10); var hours = Math.floor(seconds_ / 3600); var minutes = Math.floor((seconds_ - (hours * 3600)) / 60); var seconds = seconds_ - (hours * 3600) - (minutes * 60); if (hours < 10) { hours = "0" + hours; } if (minutes < 10) { minutes = "0" +minutes; } if (seconds < 10) { seconds = "0" + seconds; } ret.set_string(hours + ':' + minutes + ':' + seconds); }; Exps.prototype.ToSeconds = function(ret, clockString_) { var a = clockString_.split(':'); var hours = +(a.length === 3 ? a[0] : 0); var minutes = +(a.length === 3 ? a[1] : (a.length === 2 ? a[0] : 0)); var seconds = +(a.length === 3 ? a[2] : (a.length === 2 ? a[1] : (a.length === 1 ? a[0] : 0))); seconds = hours * 3600 + minutes * 60 + seconds; ret.set_int(seconds); }; pluginProto.exps = new Exps(); }()); window['tr_cp_cfg_data'] = null; window['nsgSmartRedirect'] = function(url_) { function inIframe () { try { return window.self !== window.top; } catch (e) { return true; } } var a = document.createElement('a'); var linkText = document.createTextNode(url_); a.appendChild(linkText); a.id="externallink"; a.style="display: none"; a.href = url_; if(inIframe()) { a.target = "_blank"; } document.body.appendChild(a); $('#externallink')[0].click(); }; ; ; cr.plugins_.TR_CrossPromo = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.TR_CrossPromo.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState === 4) { if (xmlhttp.status === 200) { window['tr_cp_cfg_data'] = JSON.parse(xmlhttp.responseText || '{}'); } else { window['tr_cp_cfg_data'] = {}; } } }; var platform = 'web'; if (typeof window["FBInstant"] !== 'undefined') { platform = 'fig'; } else if (this.runtime.isAndroid) { platform = 'android'; } else if (this.runtime.isiOS) { platform = 'ios'; } xmlhttp.open("GET", "https://tools.nightsteed.com/tr_cr/get_data3.php?r=" + Math.floor(Math.random() * 100000) + "&token=nnaQesObz9UnXxAZtV68&source=" + document.referrer + "&source_game=" + this.properties[0] + "&platform=" + platform, true); xmlhttp.send(); this.currentGame = ""; this.currentlyLoading = ""; if(window['tr_cp_cfg_data']) { this.serverData = window['tr_cp_cfg_data']; } else { var self = this; var checking = setInterval(function () { if(window['tr_cp_cfg_data']) { self.serverData = window['tr_cp_cfg_data']; clearInterval(checking); } }, 10); } }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnBannerReady = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.PickRandomBanner = function () { if( ! this.serverData || typeof this.serverData['draw'] === 'undefined' || this.serverData['draw'].length === 0) { this.currentGame = ''; return; } var RND = Math.floor(Math.random() * 100); var i, len = this.serverData['draw'].length; for (i = len - 1; i >= 0; --i) { if (this.serverData['draw'][i]['draw_value'] <= RND) { this.currentlyLoading = this.serverData['draw'][i]['game_name']; break; } } if (this.currentGame !== this.currentlyLoading) { if (this.serverData['games'][this.currentlyLoading]['img'].substring(0, 4) !== 'http') { this.currentGame = this.currentlyLoading; this.currentlyLoading = ""; this.runtime.trigger(cr.plugins_.TR_CrossPromo.prototype.cnds.OnBannerReady, this); return; } this.loadCPImage(this.serverData['games'][this.currentlyLoading]['img']); } }; Acts.prototype.SmartRedirect = function (url_) { window['nsgSmartRedirect'](url_); }; pluginProto.acts = new Acts(); instanceProto.loadCPImage = function(url_) { var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange = function() { if (xmlhttp.readyState === 4) { if (xmlhttp.status === 200) { window['tr_cp_get_image'] = xmlhttp.responseText; } else { console.log('ajax err when loading image 64 txt'); } } }; xmlhttp.open("GET", url_ + "?r=" + Math.floor(Math.random() * 100000), true); xmlhttp.send(); var self = this; var checking2 = setInterval(function () { if(window['tr_cp_get_image']) { self.serverData['games'][self.currentlyLoading]['img'] = window['tr_cp_get_image']; window['tr_cp_get_image'] = null; self.currentGame = self.currentlyLoading; self.currentlyLoading = ""; self.runtime.trigger(cr.plugins_.TR_CrossPromo.prototype.cnds.OnBannerReady, self); clearInterval(checking2); } }, 10); }; function Exps() {}; Exps.prototype.MoreGamesURL = function (ret) { var url = document.createElement('a'); url.href = document.referrer; var moreGamesURL = url.protocol + '//' + url.hostname; if(this.serverData && typeof this.serverData['mg'] !== 'undefined' && this.serverData['mg'].trim() !== '') { moreGamesURL = this.serverData['mg']; } ret.set_string(moreGamesURL); }; Exps.prototype.CurrentBannerURL = function (ret) { var currentBannerUrl = ''; if(this.serverData && typeof this.serverData['games'] !== 'undefined' && typeof this.serverData['games'][this.currentGame] !== 'undefined' && typeof this.serverData['games'][this.currentGame]['url'] !== 'undefined') { currentBannerUrl = this.serverData['games'][this.currentGame]['url']; } ret.set_any(currentBannerUrl); }; Exps.prototype.CurrentBannerIMG = function (ret) { ret.set_string(this.serverData['games'][this.currentGame]['img']); }; Exps.prototype.CurrentBannerLabel = function (ret) { ret.set_string(this.serverData['games'][this.currentGame]['label']); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.TR_DateTime = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.TR_DateTime.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.timers = []; this.currentTimerTag = ""; }; instanceProto.onDestroy = function () { }; instanceProto.setTimer = function(tag_, interval_, repeats_, data_, triggerCounter_) { this.timers[tag_] = { isReady: false, interval: interval_, repeatsLeft: repeats_, data: data_ || "", triggerCounter: triggerCounter_ || 0, startTime: (new Date()).getTime(), id: null }; var self = this; this.timers[tag_].id = setTimeout(function() { self.timers[tag_].isReady = true; self.timers[tag_].isOriginal = true; --self.timers[tag_].repeatsLeft; ++self.timers[tag_].triggerCounter; self.currentTimerTag = tag_; self.runtime.trigger(cr.plugins_.TR_DateTime.prototype.cnds.OnTimer, self); self.runtime.trigger(cr.plugins_.TR_DateTime.prototype.cnds.OnAnyTimer, self); if ( ! self.timers[tag_] ) return; // timer can be cancelled in OnTimer condition if ( ! self.timers[tag_].isOriginal) return; // isOriginal does not exist if tag was overriden in "OnTimer" events if(self.timers[tag_].repeatsLeft <= 0) { self.timers[tag_] = null; } else { self.setTimer(tag_, interval_, self.timers[tag_].repeatsLeft, self.timers[tag_].data, self.timers[tag_].triggerCounter); } } , this.timers[tag_].interval * 1000); this.runtime.trigger(cr.plugins_.TR_DateTime.prototype.cnds.OnTimerStarted, this); }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnTimestamp = function(timestamp) { var cnd = this.runtime.getCurrentCondition(); if (typeof cnd.extra["OnTimestamp_tickSkipsLeft"] === "undefined") { cnd.extra["OnTimestamp_tickSkipsLeft"] = 0; cnd.extra["OnTimestamp_isOff"] = false; } if(cnd.extra["OnTimestamp_isOff"] === true) return false; if(cnd.extra["OnTimestamp_tickSkipsLeft"] === 0) { var timestampDiff = timestamp - ((new Date()).getTime() / 1000|0); if(timestampDiff === 0) { cnd.extra["OnTimestamp_isOff"] = true; return true; } if(timestampDiff < 0) { cnd.extra["OnTimestamp_isOff"] = true; return false; } if(timestampDiff > 1) { cnd.extra["OnTimestamp_tickSkipsLeft"] = Math.floor(timestampDiff * this.runtime.fps / 2); } else { cnd.extra["OnTimestamp_tickSkipsLeft"] = Math.floor(this.runtime.fps / 10); } return false; } else { --cnd.extra["OnTimestamp_tickSkipsLeft"]; return false; } }; /** * @returns {boolean} */ Cnds.prototype.OnTimer = function(tag) { if(typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null && this.currentTimerTag === tag) { return true; } }; /** * @returns {boolean} */ Cnds.prototype.IsActive = function(tag) { return (typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null) }; /** * @returns {boolean} */ Cnds.prototype.OnAnyTimer = function() { return true; }; Cnds.prototype.OnTimerStarted = function(tag) { if(typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null) { return true; } }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.StartTimer = function(tag, interval, repeats) { if(typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null) { clearTimeout(this.timers[tag].id); this.timers[tag] = null; } this.setTimer(tag, interval, repeats); }; Acts.prototype.StartDataTimer = function(tag, interval, repeats, data_) { if(typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null) { clearTimeout(this.timers[tag].id); this.timers[tag] = null; } this.setTimer(tag, interval, repeats, data_); }; Acts.prototype.StopTimer = function(tag) { if(typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null) { clearTimeout(this.timers[tag].id); this.timers[tag] = null; } }; Acts.prototype.StopAllTimers = function() { for(var tag in this.timers) { if(this.timers.hasOwnProperty(tag) && typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null) { clearTimeout(this.timers[tag].id); this.timers[tag] = null; } } }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Timestamp = function(ret) { ret.set_int((new Date()).getTime() / 1000|0); }; Exps.prototype.FullTimestamp = function(ret) { ret.set_int((new Date()).getTime()); }; Exps.prototype.Date = function(ret, format_, offset_) { var now = offset_ === 0 ? (new Date()) : (new Date((new Date()).getTime() + offset_ * 3600000)); format_ = format_ .replace(/yy/g, now.getUTCFullYear()) .replace(/y/g, now.getUTCFullYear().toString().slice(-2)) .replace(/mm/g, ("0" + (now.getUTCMonth() + 1)).slice(-2)) .replace(/m/g, (now.getUTCMonth() + 1)) .replace(/dd/g, ("0" + now.getUTCDate()).slice(-2)) .replace(/d/g, now.getUTCDate()) .replace(/hh/g, ("0" + now.getUTCHours()).slice(-2)) .replace(/h/g, now.getUTCHours()) .replace(/ii/g, ("0" + now.getUTCMinutes()).slice(-2)) .replace(/i/g, now.getUTCMinutes()) .replace(/ss/g, ("0" + now.getUTCSeconds()).slice(-2)) .replace(/s/g, now.getUTCSeconds()) .replace(/u/g, now.getUTCMilliseconds()); ret.set_string(format_); }; Exps.prototype.TimerTimeLeft = function (ret, tag_, secondsFormat_) { if(typeof this.timers[tag_] === 'undefined' || ! this.timers[tag_]) { ret.set_int(-1); return; } var timeDiff = (new Date()).getTime() - this.timers[tag_].startTime; var remainingTime = this.timers[tag_].interval * 1000 - timeDiff; ret.set_int(secondsFormat_ === 0 ? remainingTime : remainingTime / 1000|0); }; Exps.prototype.TimerAge = function (ret, tag_, secondsFormat_) { if(typeof this.timers[tag_] === 'undefined' || ! this.timers[tag_]) { ret.set_int(-1); return; } var timeDiff = (new Date()).getTime() - this.timers[tag_].startTime; ret.set_int(secondsFormat_ === 0 ? timeDiff : timeDiff / 1000|0); }; Exps.prototype.TriggerAge = function (ret, tag_) { if(typeof this.timers[tag_] === 'undefined' || ! this.timers[tag_]) { ret.set_int(-1); return; } ret.set_int(this.timers[tag_].triggerCounter); }; Exps.prototype.TriggersLeft = function (ret, tag_) { if(typeof this.timers[tag_] === 'undefined' || ! this.timers[tag_]) { ret.set_int(-1); return; } ret.set_int(this.timers[tag_].repeatsLeft); }; Exps.prototype.Data = function (ret, tag_) { if(typeof this.timers[tag_] === 'undefined' || ! this.timers[tag_]) { ret.set_int(-1); return; } ret.set_any(this.timers[tag_].data); }; Exps.prototype.Tag = function (ret) { ret.set_string(this.currentTimerTag); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.TR_HtmlText = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.TR_HtmlText.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.draw = function(ctx) {}; instanceProto.drawGL = function(glw) {}; instanceProto.tick2 = function () { this.updatePosition(); }; instanceProto.onCreate = function() { this.elem = document.createElement("div"); this.elem.innerHTML = this.properties[0]; this.text = this.properties[0]; this.text_changed = false; this.elem.id = this.properties[10] || this.makeID(); this.elem.class = this.properties[11]; this.elem.setAttribute("id", this.elem.id); if (this.elem.class) this.elem.setAttribute("class", this.elem.class); this.elem.style.fontSize = this.properties[1] + 'em'; if (this.properties[5]) this.elem.setAttribute("title", this.properties[5]); if (this.properties[2]) $(this.elem).css("font-family", this.properties[2]); this.elem.style.background = this.properties[4]; this.elem.style.border = this.properties[6]; this.elem.style.color = this.properties[3]; this.elem.style.width = this.width + "px"; this.elem.style.height = this.height + "px"; if( ! this.properties[8]) { $(this.elem).css("user-select", "none"); $(this.elem).css("cursor", "default"); } switch (this.properties[7]) { case 0: this.elem.setAttribute("scrolling", "no"); this.elem.style.overflow = "hidden"; break; case 1: this.elem.style.overflow = "auto"; break; case 2: this.elem.style.overflowX = "auto"; this.elem.style.overflowY = "hidden"; break; case 3: this.elem.style.overflowX = "hidden"; this.elem.style.overflowY = "auto"; break; } switch (this.properties[9]) { case 0: this.elem.style.textAlign = "center"; break; case 1: this.elem.style.textAlign = "left"; break; case 2: this.elem.style.textAlign = "right"; break; } $(this.elem).appendTo(this.runtime.canvasdiv ? this.runtime.canvasdiv : "body"); this.updatePosition(true); this.fixesLeft = 10; this.runtime.tick2Me(this); }; instanceProto.getScale = function() { var widthScale = $(window).width() / this.runtime.original_width; var heightScale = $(window).height() / this.runtime.original_height; return Math.min(widthScale, heightScale); }; instanceProto.makeID = function() { return "tr_html_text_" + this.uid; }; instanceProto.updatePosition = function (forceUpdate) { if (!this.visible || !this.layer.visible) { if (!this.element_hidden) { this.originalDisplay = this.elem.style.display; this.elem.style.display = 'none'; } this.element_hidden = true; return; } if (this.runtime.isDomFree) return; if(this.text_changed === true) { this.elem.innerHTML = this.text; this.text_changed = false; } var divX = this.x - this.width * 0.5; var divY = this.y - this.height * 0.5; var left = this.layer.layerToCanvas(divX, divY, true); var top = this.layer.layerToCanvas(divX , divY, false); var right = this.layer.layerToCanvas(divX + this.width, divY + this.height, true); var bottom = this.layer.layerToCanvas(divX + this.width, divY + this.height, false); var rightEdge = this.runtime.width / this.runtime.devicePixelRatio; var bottomEdge = this.runtime.height / this.runtime.devicePixelRatio; var curScale = this.getScale(); if (right <= 0 || bottom <= 0 || left >= rightEdge || top >= bottomEdge) { if (!this.element_hidden) { this.originalDisplay = this.elem.style.display; this.elem.style.display = 'none'; } this.element_hidden = true; return; } if (this.element_hidden) { this.elem.style.display = this.originalDisplay; this.element_hidden = false; } if (left < 1) left = 1; if (top < 1) top = 1; if (right >= rightEdge) right = rightEdge - 1; if (bottom >= bottomEdge) bottom = bottomEdge - 1; var curWinWidth = window.innerWidth; var curWinHeight = window.innerHeight; if (this.lastScale === curScale && this.lastLeft === left && this.lastTop === top && this.lastRight === right && this.lastBottom === bottom && this.lastWinWidth === curWinWidth && this.lastWinHeight === curWinHeight) { /*if (this.element_hidden) { this.popupDiv.style = ''; this.element_hidden = false; }*/ --this.fixesLeft; if (this.fixesLeft < 0) return; } else { this.fixesLeft = 10; } this.elem.style.width = this.width + "px"; this.elem.style.height = this.height + "px"; this.lastScale = curScale; this.lastLeft = left; this.lastTop = top; this.lastRight = right; this.lastBottom = bottom; this.lastWinWidth = curWinWidth; this.lastWinHeight = curWinHeight; var rect = this.runtime.canvas.getBoundingClientRect(); var offx = Math.round(left) + rect.left + document.body.scrollLeft; var offy = Math.round(top) + rect.top + document.body.scrollTop; this.elem.style.position = "absolute"; jQuery(this.elem).offset({left: offx, top: offy}); this.elem.style.transform = 'scale(' + this.getScale() + ')'; }; instanceProto.onDestroy = function () { if (this.runtime.isDomFree) return; this.elem.parentNode.removeChild(this.elem); this.elem = null; }; function Cnds() {}; /*// the example condition Cnds.prototype.MyCondition = function (myparam) { return myparam >= 0; };*/ pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.AddNewFamily = function (familyName_, url_) { var style = document.createElement("style"); style.appendChild(document.createTextNode("")); document.head.appendChild(style); style.sheet.insertRule("@font-face { font-family: " + familyName_ + "; src: url('" + url_ + "'); }", 0); }; Acts.prototype.SetText = function (newText_) { this.text = newText_; this.elem.innerHTML = newText_; }; Acts.prototype.SetTextSize = function (newSize_) { this.elem.style.fontSize = newSize_ + 'em'; }; Acts.prototype.SetTextColor = function (newColor_) { this.elem.style.color = newColor_; }; Acts.prototype.SetCSSClass = function (newClass_) { this.elem.setAttribute("class", newClass_); }; Acts.prototype.SetHorizontalAlignment = function (alignmentIdx_) { var newAlignment; switch (alignmentIdx_) { case 0: newAlignment = "left"; break; case 1: newAlignment = "center"; break; case 2: newAlignment = "right"; break; } this.elem.style.textAlign = newAlignment; }; pluginProto.acts = new Acts(); function Exps() {}; /*Exps.prototype.MyExpression = function (ret) // 'ret' must always be the first parameter - always return the expression's result through it! { ret.set_int(1337); // return our value };*/ pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.TR_Leaderboard = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.TR_Leaderboard.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; this.sortType = { DESC: 0, ASC: 1 }; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; /*this.leaderboardByUsers = {}; this.leaderboardByScore = []; this.textInstances = []; this.requiredUsers = []; this.drawnUsers = []; this.x = 0; this.y = 0; this.layer = null; this.columnSetup = { position: { font: null, width: 0 }, name: { font: null, width: 0 }, score: { font: null, width: 0 } }; this.hasNewData = false;*/ }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.sortType = this.properties[0]; this.topEntriesQty = this.properties[1]; this.verticalMargin = this.properties[2]; this.allowLowerScore = this.properties[3]; this.leaderboardByUsers = {}; this.leaderboardByScore = []; this.textInstances = []; this.requiredUsers = []; this.drawnUsers = []; this.x = 0; this.y = 0; this.layer = null; this.columnSetup = { position: { font: null, width: 0 }, name: { font: null, width: 0 }, score: { font: null, width: 0 } }; this.hasNewData = false; /*if (this.type.isFirstInit) { this.type.isFirstInit = false; this.runtime.DestroyInstance(this); }*/ }; instanceProto.onDestroy = function () { }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnChange = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.HasNewData = function () { return this.hasNewData; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetPositionColumn = function (font_, columnWidth_) { this.columnSetup.position.font = font_; this.columnSetup.position.width = columnWidth_; }; Acts.prototype.SetNameColumn = function (font_, columnWidth_) { this.columnSetup.name.font = font_; this.columnSetup.name.width = columnWidth_; }; Acts.prototype.SetScoreColumn = function (font_, columnWidth_) { this.columnSetup.score.font = font_; this.columnSetup.score.width = columnWidth_; }; Acts.prototype.SetEntry = function (playerId_, name_, score_) { playerId_ = playerId_.toLowerCase(); score_ = parseInt(score_); if (typeof this.leaderboardByUsers[playerId_] === 'undefined') { this.leaderboardByUsers[playerId_] = { playerId: playerId_, index: this.leaderboardByScore.length }; this.leaderboardByScore.push(this.leaderboardByUsers[playerId_]); } if ((this.sortType === this.type.sortType.DESC && this.leaderboardByUsers[playerId_].score >= score_) // TODO score can now be lower || (this.sortType === this.type.sortType.ASC && this.leaderboardByUsers[playerId_].score <= score_)) { if(!this.allowLowerScore){ return; } var checkJumpSize = Math.ceil(this.leaderboardByScore.length * 0.1); var i, startIndex = null; for (i = this.leaderboardByUsers[playerId_].index + 1; i >= 0; ++i) // TODO or + checkJumpSize { if (typeof this.leaderboardByScore[i] === 'undefined' || (this.sortType === this.type.sortType.DESC && this.leaderboardByScore[i].score < score_) || (this.sortType === this.type.sortType.ASC && this.leaderboardByScore[i].score > score_)) { startIndex = i; break; } } var shuffleStartIndex = this.leaderboardByUsers[playerId_].index; this.leaderboardByUsers[playerId_].index = startIndex - 1; for (i = shuffleStartIndex; i >= 0; ++i) { if (i === this.leaderboardByUsers[playerId_].index) { this.leaderboardByScore[i] = this.leaderboardByUsers[playerId_]; break; } else if (this.leaderboardByScore[i + 1]) { this.leaderboardByScore[i] = this.leaderboardByScore[i + 1]; this.leaderboardByScore[i].index = i; } } this.leaderboardByUsers[playerId_].name = name_; this.leaderboardByUsers[playerId_].score = score_; this.hasNewData = true; return; } this.leaderboardByUsers[playerId_].name = name_; this.leaderboardByUsers[playerId_].score = score_; var scoreOfPlayerAbove = this.leaderboardByScore[this.leaderboardByUsers[playerId_].index - 1]; // TODO check player below if new score is lower than earlier score var scoreOfPlayerBelow = this.leaderboardByScore[this.leaderboardByUsers[playerId_].index + 1]; if ( ! scoreOfPlayerAbove || ((this.sortType === this.type.sortType.DESC && scoreOfPlayerAbove.score >= score_) || (this.sortType === this.type.sortType.ASC && scoreOfPlayerAbove.score <= score_))) { if (this.requiredUsers.indexOf(playerId_) !== -1 || this.topEntriesQty > this.leaderboardByUsers[playerId_].index) { this.hasNewData = true; } return; } var checkJumpSize = Math.ceil(this.leaderboardByScore.length * 0.1); var i, startIndex = null; for (i = this.leaderboardByUsers[playerId_].index - checkJumpSize; i >= 0; i -= checkJumpSize) // TODO or + checkJumpSize { if ((this.sortType === this.type.sortType.DESC && this.leaderboardByScore[i].score > score_) || (this.sortType === this.type.sortType.ASC && this.leaderboardByScore[i].score < score_)) { startIndex = i; break; } } if (startIndex === null) { startIndex = 0; } var entryIndex = 0, len = this.leaderboardByScore.length; for (i = startIndex; i < len; ++i) // TODO... { if (this.leaderboardByScore[i] && ((this.sortType === this.type.sortType.DESC && this.leaderboardByScore[i].score < score_) || (this.sortType === this.type.sortType.ASC && this.leaderboardByScore[i].score > score_))) { entryIndex = i; break; } } var shuffleStartIndex = this.leaderboardByUsers[playerId_].index; this.leaderboardByUsers[playerId_].index = entryIndex; for (i = shuffleStartIndex; i >= 0; --i) { if (i === this.leaderboardByUsers[playerId_].index) { this.leaderboardByScore[i] = this.leaderboardByUsers[playerId_]; break; } else if (this.leaderboardByScore[i - 1]) { this.leaderboardByScore[i] = this.leaderboardByScore[i - 1]; this.leaderboardByScore[i].index = i; } } this.hasNewData = true; }; Acts.prototype.RemoveEntry = function (playerId_) { playerId_ = playerId_.toLowerCase(); if ( ! this.leaderboardByUsers[playerId_]) return; var i, len = this.leaderboardByScore.length; var shuffleStartIndex = this.leaderboardByUsers[playerId_].index; for (i = shuffleStartIndex; i < len; ++i) { if (this.leaderboardByScore[i + 1]) { this.leaderboardByScore[i] = this.leaderboardByScore[i + 1]; this.leaderboardByScore[i].index = i; } } this.leaderboardByScore.pop(); delete this.leaderboardByUsers[playerId_]; if (this.requiredUsers.indexOf(playerId_) !== -1) { this.requiredUsers.splice(this.requiredUsers.indexOf(playerId_), 1); } this.hasNewData = true; }; Acts.prototype.ClearLeaderboard = function () { this.leaderboardByScore = []; this.leaderboardByUsers = {}; this.requiredUsers = []; this.drawnUsers = []; this.destroyFontFrom(0); }; Acts.prototype.ClearDestroy = function () { this.leaderboardByScore = []; this.leaderboardByUsers = {}; this.requiredUsers = []; this.drawnUsers = []; this.destroyFontFrom(0); this.runtime.DestroyInstance(this); }; Acts.prototype.SetRequired = function (playerId_) { playerId_ = playerId_.toLowerCase(); if (this.requiredUsers.indexOf(playerId_) === -1) { this.requiredUsers.push(playerId_); } }; Acts.prototype.SetPosition = function (x_, y_, layer_) { this.x = x_; this.y = y_; this.layer = layer_; }; Acts.prototype.DrawLeaderboard = function () { if (this.layer === null) return; if (this.columnSetup.position.font === null) return; if (this.columnSetup.name.font === null) return; if (this.columnSetup.score.font === null) return; this.drawnUsers.length = 0; var inst, i, len = Math.min(this.leaderboardByScore.length - this.requiredUsers.length, this.topEntriesQty - this.requiredUsers.length); for (i = 0; i < len; ++i) { this.drawUser(i, i); } if (this.requiredUsers.length === 0) { this.destroyFontFrom(i); this.hasNewData = false; return; } var currentUser, j; len = this.requiredUsers.length; for (j = 0; j < len; ++j) { currentUser = this.leaderboardByUsers[this.requiredUsers[j]]; if ( ! currentUser) continue; if (this.drawnUsers.indexOf(currentUser.playerId) !== -1) { this.drawUser(i, i); } else { var userIndex = currentUser.index; this.drawUser(i, userIndex); } ++i; } this.destroyFontFrom(i); this.hasNewData = false; }; instanceProto.drawUser = function(leaderboardIndex_, userIndex_) { var inst, i = leaderboardIndex_; if (this.textInstances[i]) { inst = this.textInstances[i].position; inst.type.plugin.acts.SetText.call(inst, (userIndex_ + 1) + "."); inst = this.textInstances[i].name; inst.type.plugin.acts.SetText.call(inst, this.leaderboardByScore[userIndex_].name); inst = this.textInstances[i].score; inst.type.plugin.acts.SetText.call(inst, this.leaderboardByScore[userIndex_].score); } else { this.textInstances.push( { position: null, name: null, score: null} ); inst = this.runtime.createInstance(this.columnSetup.position.font, this.layer, this.x, this.y + i * this.verticalMargin); inst.type.plugin.acts.SetWidth.call(inst, this.columnSetup.position.width); inst.type.plugin.acts.SetText.call(inst, (userIndex_+1) + "."); this.textInstances[i].position = inst; this.runtime.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnCreated, inst); inst = this.runtime.createInstance(this.columnSetup.name.font, this.layer, this.x + this.columnSetup.position.width, this.y + i * this.verticalMargin); inst.type.plugin.acts.SetWidth.call(inst, this.columnSetup.name.width); inst.type.plugin.acts.SetText.call(inst, this.leaderboardByScore[userIndex_].name); this.textInstances[i].name = inst; this.runtime.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnCreated, inst); inst = this.runtime.createInstance(this.columnSetup.score.font, this.layer, this.x + this.columnSetup.name.width + this.columnSetup.position.width, this.y + i * this.verticalMargin); inst.type.plugin.acts.SetWidth.call(inst, this.columnSetup.score.width); inst.type.plugin.acts.SetText.call(inst, this.leaderboardByScore[userIndex_].score); this.textInstances[i].score = inst; this.runtime.trigger(Object.getPrototypeOf(inst.type.plugin).cnds.OnCreated, inst); } this.drawnUsers.push(this.leaderboardByScore[userIndex_].playerId); }; instanceProto.destroyFontFrom = function(index_) { var i, len = this.textInstances.length; for (i = index_; i < len; ++i) { if ( ! this.textInstances[i]) continue; this.runtime.DestroyInstance(this.textInstances[i].position); this.runtime.DestroyInstance(this.textInstances[i].name); this.runtime.DestroyInstance(this.textInstances[i].score); } this.textInstances.length = index_; }; Acts.prototype.ImportFromJSON = function (json_) { }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.AsJSON = function (ret) { ret.set_string(""); }; Exps.prototype.GetPosition = function (ret, playerId_) { playerId_ = playerId_.toLowerCase(); if ( ! this.leaderboardByUsers[playerId_]) { ret.set_int(-1); return; } var position = this.leaderboardByUsers[playerId_] ? this.leaderboardByUsers[playerId_].index + 1 : -1; ret.set_int(position); }; Exps.prototype.GetX = function (ret) { var x = this.textInstances[0] ? this.textInstances[0].position.x : -1; ret.set_int(x); }; Exps.prototype.GetY = function (ret, playerId_) { playerId_ = playerId_.toLowerCase(); if ( ! this.leaderboardByUsers[playerId_]) { ret.set_int(-1); return; } var position = this.drawnUsers.indexOf(playerId_); if (position === -1) { ret.set_int(-1); return; } position = this.textInstances[position].position.y; ret.set_int(position); }; Exps.prototype.GetScoreByPosition = function (ret, position_) { position_ = Math.round(position_); if(position_ < 1 || position_ > this.leaderboardByScore.length) { ret.set_int(-1); return; } var score = this.leaderboardByScore[position_ - 1].score; ret.set_int(score); }; Exps.prototype.GetIdByPosition = function (ret, position_) { position_ = Math.round(position_); if(position_ < 1 || position_ > this.leaderboardByScore.length) { ret.set_string("-1"); return; } var playerId = this.leaderboardByScore[position_ - 1].playerId; ret.set_string(playerId); }; Exps.prototype.GetNameByPosition = function (ret, position_) { position_ = Math.round(position_); if(position_ < 1 || position_ > this.leaderboardByScore.length) { ret.set_string("-1"); return; } var name = this.leaderboardByScore[position_ - 1].name; ret.set_string(name); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Text = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Text.prototype; pluginProto.onCreate = function () { pluginProto.acts.SetWidth = function (w) { if (this.width !== w) { this.width = w; this.text_changed = true; // also recalculate text wrapping this.set_bbox_changed(); } }; }; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; typeProto.onLostWebGLContext = function () { if (this.is_family) return; var i, len, inst; for (i = 0, len = this.instances.length; i < len; i++) { inst = this.instances[i]; inst.mycanvas = null; inst.myctx = null; inst.mytex = null; } }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; if (this.recycled) cr.clearArray(this.lines); else this.lines = []; // for word wrapping this.text_changed = true; }; var instanceProto = pluginProto.Instance.prototype; var requestedWebFonts = {}; // already requested web fonts have an entry here instanceProto.onCreate = function() { this.text = this.properties[0]; this.visible = (this.properties[1] === 0); // 0=visible, 1=invisible this.font = this.properties[2]; this.color = this.properties[3]; this.halign = this.properties[4]; // 0=left, 1=center, 2=right this.valign = this.properties[5]; // 0=top, 1=center, 2=bottom this.wrapbyword = (this.properties[7] === 0); // 0=word, 1=character this.lastwidth = this.width; this.lastwrapwidth = this.width; this.lastheight = this.height; this.line_height_offset = this.properties[8]; this.facename = ""; this.fontstyle = ""; this.ptSize = 0; this.textWidth = 0; this.textHeight = 0; this.parseFont(); this.mycanvas = null; this.myctx = null; this.mytex = null; this.need_text_redraw = false; this.last_render_tick = this.runtime.tickcount; if (this.recycled) this.rcTex.set(0, 0, 1, 1); else this.rcTex = new cr.rect(0, 0, 1, 1); if (this.runtime.glwrap) this.runtime.tickMe(this); ; }; instanceProto.parseFont = function () { var arr = this.font.split(" "); var i; for (i = 0; i < arr.length; i++) { if (arr[i].substr(arr[i].length - 2, 2) === "pt") { this.ptSize = parseInt(arr[i].substr(0, arr[i].length - 2)); this.pxHeight = Math.ceil((this.ptSize / 72.0) * 96.0) + 4; // assume 96dpi... if (i > 0) this.fontstyle = arr[i - 1]; this.facename = arr[i + 1]; for (i = i + 2; i < arr.length; i++) this.facename += " " + arr[i]; break; } } }; instanceProto.saveToJSON = function () { return { "t": this.text, "f": this.font, "c": this.color, "ha": this.halign, "va": this.valign, "wr": this.wrapbyword, "lho": this.line_height_offset, "fn": this.facename, "fs": this.fontstyle, "ps": this.ptSize, "pxh": this.pxHeight, "tw": this.textWidth, "th": this.textHeight, "lrt": this.last_render_tick }; }; instanceProto.loadFromJSON = function (o) { this.text = o["t"]; this.font = o["f"]; this.color = o["c"]; this.halign = o["ha"]; this.valign = o["va"]; this.wrapbyword = o["wr"]; this.line_height_offset = o["lho"]; this.facename = o["fn"]; this.fontstyle = o["fs"]; this.ptSize = o["ps"]; this.pxHeight = o["pxh"]; this.textWidth = o["tw"]; this.textHeight = o["th"]; this.last_render_tick = o["lrt"]; this.text_changed = true; this.lastwidth = this.width; this.lastwrapwidth = this.width; this.lastheight = this.height; }; instanceProto.tick = function () { if (this.runtime.glwrap && this.mytex && (this.runtime.tickcount - this.last_render_tick >= 300)) { var layer = this.layer; this.update_bbox(); var bbox = this.bbox; if (bbox.right < layer.viewLeft || bbox.bottom < layer.viewTop || bbox.left > layer.viewRight || bbox.top > layer.viewBottom) { this.runtime.glwrap.deleteTexture(this.mytex); this.mytex = null; this.myctx = null; this.mycanvas = null; } } }; instanceProto.onDestroy = function () { this.myctx = null; this.mycanvas = null; if (this.runtime.glwrap && this.mytex) this.runtime.glwrap.deleteTexture(this.mytex); this.mytex = null; }; instanceProto.updateFont = function () { this.font = this.fontstyle + " " + this.ptSize.toString() + "pt " + this.facename; this.text_changed = true; this.runtime.redraw = true; }; instanceProto.draw = function(ctx, glmode) { ctx.font = this.font; ctx.textBaseline = "top"; ctx.fillStyle = this.color; ctx.globalAlpha = glmode ? 1 : this.opacity; var myscale = 1; if (glmode) { myscale = Math.abs(this.layer.getScale()); ctx.save(); ctx.scale(myscale, myscale); } if (this.text_changed || this.width !== this.lastwrapwidth) { this.type.plugin.WordWrap(this.text, this.lines, ctx, this.width, this.wrapbyword); this.text_changed = false; this.lastwrapwidth = this.width; } this.update_bbox(); var penX = glmode ? 0 : this.bquad.tlx; var penY = glmode ? 0 : this.bquad.tly; if (this.runtime.pixel_rounding) { penX = (penX + 0.5) | 0; penY = (penY + 0.5) | 0; } if (this.angle !== 0 && !glmode) { ctx.save(); ctx.translate(penX, penY); ctx.rotate(this.angle); penX = 0; penY = 0; } var endY = penY + this.height; var line_height = this.pxHeight; line_height += this.line_height_offset; var drawX; var i; if (this.valign === 1) // center penY += Math.max(this.height / 2 - (this.lines.length * line_height) / 2, 0); else if (this.valign === 2) // bottom penY += Math.max(this.height - (this.lines.length * line_height) - 2, 0); for (i = 0; i < this.lines.length; i++) { drawX = penX; if (this.halign === 1) // center drawX = penX + (this.width - this.lines[i].width) / 2; else if (this.halign === 2) // right drawX = penX + (this.width - this.lines[i].width); ctx.fillText(this.lines[i].text, drawX, penY); penY += line_height; if (penY >= endY - line_height) break; } if (this.angle !== 0 || glmode) ctx.restore(); this.last_render_tick = this.runtime.tickcount; }; instanceProto.drawGL = function(glw) { if (this.width < 1 || this.height < 1) return; var need_redraw = this.text_changed || this.need_text_redraw; this.need_text_redraw = false; var layer_scale = this.layer.getScale(); var layer_angle = this.layer.getAngle(); var rcTex = this.rcTex; var floatscaledwidth = layer_scale * this.width; var floatscaledheight = layer_scale * this.height; var scaledwidth = Math.ceil(floatscaledwidth); var scaledheight = Math.ceil(floatscaledheight); var absscaledwidth = Math.abs(scaledwidth); var absscaledheight = Math.abs(scaledheight); var halfw = this.runtime.draw_width / 2; var halfh = this.runtime.draw_height / 2; if (!this.myctx) { this.mycanvas = document.createElement("canvas"); this.mycanvas.width = absscaledwidth; this.mycanvas.height = absscaledheight; this.lastwidth = absscaledwidth; this.lastheight = absscaledheight; need_redraw = true; this.myctx = this.mycanvas.getContext("2d"); } if (absscaledwidth !== this.lastwidth || absscaledheight !== this.lastheight) { this.mycanvas.width = absscaledwidth; this.mycanvas.height = absscaledheight; if (this.mytex) { glw.deleteTexture(this.mytex); this.mytex = null; } need_redraw = true; } if (need_redraw) { this.myctx.clearRect(0, 0, absscaledwidth, absscaledheight); this.draw(this.myctx, true); if (!this.mytex) this.mytex = glw.createEmptyTexture(absscaledwidth, absscaledheight, this.runtime.linearSampling, this.runtime.isMobile); glw.videoToTexture(this.mycanvas, this.mytex, this.runtime.isMobile); } this.lastwidth = absscaledwidth; this.lastheight = absscaledheight; glw.setTexture(this.mytex); glw.setOpacity(this.opacity); glw.resetModelView(); glw.translate(-halfw, -halfh); glw.updateModelView(); var q = this.bquad; var tlx = this.layer.layerToCanvas(q.tlx, q.tly, true, true); var tly = this.layer.layerToCanvas(q.tlx, q.tly, false, true); var trx = this.layer.layerToCanvas(q.trx, q.try_, true, true); var try_ = this.layer.layerToCanvas(q.trx, q.try_, false, true); var brx = this.layer.layerToCanvas(q.brx, q.bry, true, true); var bry = this.layer.layerToCanvas(q.brx, q.bry, false, true); var blx = this.layer.layerToCanvas(q.blx, q.bly, true, true); var bly = this.layer.layerToCanvas(q.blx, q.bly, false, true); if (this.runtime.pixel_rounding || (this.angle === 0 && layer_angle === 0)) { var ox = ((tlx + 0.5) | 0) - tlx; var oy = ((tly + 0.5) | 0) - tly tlx += ox; tly += oy; trx += ox; try_ += oy; brx += ox; bry += oy; blx += ox; bly += oy; } if (this.angle === 0 && layer_angle === 0) { trx = tlx + scaledwidth; try_ = tly; brx = trx; bry = tly + scaledheight; blx = tlx; bly = bry; rcTex.right = 1; rcTex.bottom = 1; } else { rcTex.right = floatscaledwidth / scaledwidth; rcTex.bottom = floatscaledheight / scaledheight; } glw.quadTex(tlx, tly, trx, try_, brx, bry, blx, bly, rcTex); glw.resetModelView(); glw.scale(layer_scale, layer_scale); glw.rotateZ(-this.layer.getAngle()); glw.translate((this.layer.viewLeft + this.layer.viewRight) / -2, (this.layer.viewTop + this.layer.viewBottom) / -2); glw.updateModelView(); this.last_render_tick = this.runtime.tickcount; }; var wordsCache = []; pluginProto.TokeniseWords = function (text) { cr.clearArray(wordsCache); var cur_word = ""; var ch; var i = 0; while (i < text.length) { ch = text.charAt(i); if (ch === "\n") { if (cur_word.length) { wordsCache.push(cur_word); cur_word = ""; } wordsCache.push("\n"); ++i; } else if (ch === " " || ch === "\t" || ch === "-") { do { cur_word += text.charAt(i); i++; } while (i < text.length && (text.charAt(i) === " " || text.charAt(i) === "\t")); wordsCache.push(cur_word); cur_word = ""; } else if (i < text.length) { cur_word += ch; i++; } } if (cur_word.length) wordsCache.push(cur_word); }; var linesCache = []; function allocLine() { if (linesCache.length) return linesCache.pop(); else return {}; }; function freeLine(l) { linesCache.push(l); }; function freeAllLines(arr) { var i, len; for (i = 0, len = arr.length; i < len; i++) { freeLine(arr[i]); } cr.clearArray(arr); }; pluginProto.WordWrap = function (text, lines, ctx, width, wrapbyword) { if (!text || !text.length) { freeAllLines(lines); return; } if (width <= 2.0) { freeAllLines(lines); return; } if (text.length <= 100 && text.indexOf("\n") === -1) { var all_width = ctx.measureText(text).width; if (all_width <= width) { freeAllLines(lines); lines.push(allocLine()); lines[0].text = text; lines[0].width = all_width; return; } } this.WrapText(text, lines, ctx, width, wrapbyword); }; function trimSingleSpaceRight(str) { if (!str.length || str.charAt(str.length - 1) !== " ") return str; return str.substring(0, str.length - 1); }; pluginProto.WrapText = function (text, lines, ctx, width, wrapbyword) { var wordArray; if (wrapbyword) { this.TokeniseWords(text); // writes to wordsCache wordArray = wordsCache; } else wordArray = text; var cur_line = ""; var prev_line; var line_width; var i; var lineIndex = 0; var line; for (i = 0; i < wordArray.length; i++) { if (wordArray[i] === "\n") { if (lineIndex >= lines.length) lines.push(allocLine()); cur_line = trimSingleSpaceRight(cur_line); // for correct center/right alignment line = lines[lineIndex]; line.text = cur_line; line.width = ctx.measureText(cur_line).width; lineIndex++; cur_line = ""; continue; } prev_line = cur_line; cur_line += wordArray[i]; line_width = ctx.measureText(cur_line).width; if (line_width >= width) { if (lineIndex >= lines.length) lines.push(allocLine()); prev_line = trimSingleSpaceRight(prev_line); line = lines[lineIndex]; line.text = prev_line; line.width = ctx.measureText(prev_line).width; lineIndex++; cur_line = wordArray[i]; if (!wrapbyword && cur_line === " ") cur_line = ""; } } if (cur_line.length) { if (lineIndex >= lines.length) lines.push(allocLine()); cur_line = trimSingleSpaceRight(cur_line); line = lines[lineIndex]; line.text = cur_line; line.width = ctx.measureText(cur_line).width; lineIndex++; } for (i = lineIndex; i < lines.length; i++) freeLine(lines[i]); lines.length = lineIndex; }; function Cnds() {}; Cnds.prototype.CompareText = function(text_to_compare, case_sensitive) { if (case_sensitive) return this.text == text_to_compare; else return cr.equals_nocase(this.text, text_to_compare); }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetText = function(param) { if (cr.is_number(param) && param < 1e9) param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors var text_to_set = param.toString(); if (this.text !== text_to_set) { this.text = text_to_set; this.text_changed = true; this.runtime.redraw = true; } }; Acts.prototype.AppendText = function(param) { if (cr.is_number(param)) param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors var text_to_append = param.toString(); if (text_to_append) // not empty { this.text += text_to_append; this.text_changed = true; this.runtime.redraw = true; } }; Acts.prototype.SetFontFace = function (face_, style_) { var newstyle = ""; switch (style_) { case 1: newstyle = "bold"; break; case 2: newstyle = "italic"; break; case 3: newstyle = "bold italic"; break; } if (face_ === this.facename && newstyle === this.fontstyle) return; // no change this.facename = face_; this.fontstyle = newstyle; this.updateFont(); }; Acts.prototype.SetFontSize = function (size_) { if (this.ptSize === size_) return; this.ptSize = size_; this.pxHeight = Math.ceil((this.ptSize / 72.0) * 96.0) + 4; // assume 96dpi... this.updateFont(); }; Acts.prototype.SetFontColor = function (rgb) { var newcolor = "rgb(" + cr.GetRValue(rgb).toString() + "," + cr.GetGValue(rgb).toString() + "," + cr.GetBValue(rgb).toString() + ")"; if (newcolor === this.color) return; this.color = newcolor; this.need_text_redraw = true; this.runtime.redraw = true; }; Acts.prototype.SetWebFont = function (familyname_, cssurl_) { if (this.runtime.isDomFree) { cr.logexport("[Construct 2] Text plugin: 'Set web font' not supported on this platform - the action has been ignored"); return; // DC todo } var self = this; var refreshFunc = (function () { self.runtime.redraw = true; self.text_changed = true; }); if (requestedWebFonts.hasOwnProperty(cssurl_)) { var newfacename = "'" + familyname_ + "'"; if (this.facename === newfacename) return; // no change this.facename = newfacename; this.updateFont(); for (var i = 1; i < 10; i++) { setTimeout(refreshFunc, i * 100); setTimeout(refreshFunc, i * 1000); } return; } var wf = document.createElement("link"); wf.href = cssurl_; wf.rel = "stylesheet"; wf.type = "text/css"; wf.onload = refreshFunc; document.getElementsByTagName('head')[0].appendChild(wf); requestedWebFonts[cssurl_] = true; this.facename = "'" + familyname_ + "'"; this.updateFont(); for (var i = 1; i < 10; i++) { setTimeout(refreshFunc, i * 100); setTimeout(refreshFunc, i * 1000); } ; }; Acts.prototype.SetEffect = function (effect) { this.blend_mode = effect; this.compositeOp = cr.effectToCompositeOp(effect); cr.setGLBlend(this, effect, this.runtime.gl); this.runtime.redraw = true; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Text = function(ret) { ret.set_string(this.text); }; Exps.prototype.FaceName = function (ret) { ret.set_string(this.facename); }; Exps.prototype.FaceSize = function (ret) { ret.set_int(this.ptSize); }; Exps.prototype.TextWidth = function (ret) { var w = 0; var i, len, x; for (i = 0, len = this.lines.length; i < len; i++) { x = this.lines[i].width; if (w < x) w = x; } ret.set_int(w); }; Exps.prototype.TextHeight = function (ret) { ret.set_int(this.lines.length * (this.pxHeight + this.line_height_offset) - this.line_height_offset); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.TextBox = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.TextBox.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; var elemTypes = ["text", "password", "email", "number", "tel", "url"]; if (navigator.userAgent.indexOf("MSIE 9") > -1) { elemTypes[2] = "text"; elemTypes[3] = "text"; elemTypes[4] = "text"; elemTypes[5] = "text"; } instanceProto.onCreate = function() { if (this.runtime.isDomFree) { cr.logexport("[Construct 2] Textbox plugin not supported on this platform - the object will not be created"); return; } if (this.properties[7] === 6) // textarea { this.elem = document.createElement("textarea"); jQuery(this.elem).css("resize", "none"); } else { this.elem = document.createElement("input"); this.elem.type = elemTypes[this.properties[7]]; } this.elem.id = this.properties[9]; jQuery(this.elem).appendTo(this.runtime.canvasdiv ? this.runtime.canvasdiv : "body"); this.elem["autocomplete"] = "off"; this.elem.value = this.properties[0]; this.elem["placeholder"] = this.properties[1]; this.elem.title = this.properties[2]; this.elem.disabled = (this.properties[4] === 0); this.elem["readOnly"] = (this.properties[5] === 1); this.elem["spellcheck"] = (this.properties[6] === 1); this.autoFontSize = (this.properties[8] !== 0); this.element_hidden = false; if (this.properties[3] === 0) { jQuery(this.elem).hide(); this.visible = false; this.element_hidden = true; } var onchangetrigger = (function (self) { return function() { self.runtime.trigger(cr.plugins_.TextBox.prototype.cnds.OnTextChanged, self); }; })(this); this.elem["oninput"] = onchangetrigger; if (navigator.userAgent.indexOf("MSIE") !== -1) this.elem["oncut"] = onchangetrigger; this.elem.onclick = (function (self) { return function(e) { e.stopPropagation(); self.runtime.isInUserInputEvent = true; self.runtime.trigger(cr.plugins_.TextBox.prototype.cnds.OnClicked, self); self.runtime.isInUserInputEvent = false; }; })(this); this.elem.ondblclick = (function (self) { return function(e) { e.stopPropagation(); self.runtime.isInUserInputEvent = true; self.runtime.trigger(cr.plugins_.TextBox.prototype.cnds.OnDoubleClicked, self); self.runtime.isInUserInputEvent = false; }; })(this); this.elem.addEventListener("touchstart", function (e) { e.stopPropagation(); }, false); this.elem.addEventListener("touchmove", function (e) { e.stopPropagation(); }, false); this.elem.addEventListener("touchend", function (e) { e.stopPropagation(); }, false); jQuery(this.elem).mousedown(function (e) { e.stopPropagation(); }); jQuery(this.elem).mouseup(function (e) { e.stopPropagation(); }); jQuery(this.elem).keydown(function (e) { if (e.which !== 13 && e.which != 27) // allow enter and escape e.stopPropagation(); }); jQuery(this.elem).keyup(function (e) { if (e.which !== 13 && e.which != 27) // allow enter and escape e.stopPropagation(); }); this.lastLeft = 0; this.lastTop = 0; this.lastRight = 0; this.lastBottom = 0; this.lastWinWidth = 0; this.lastWinHeight = 0; this.updatePosition(true); this.runtime.tickMe(this); }; instanceProto.saveToJSON = function () { return { "text": this.elem.value, "placeholder": this.elem.placeholder, "tooltip": this.elem.title, "disabled": !!this.elem.disabled, "readonly": !!this.elem.readOnly, "spellcheck": !!this.elem["spellcheck"] }; }; instanceProto.loadFromJSON = function (o) { this.elem.value = o["text"]; this.elem.placeholder = o["placeholder"]; this.elem.title = o["tooltip"]; this.elem.disabled = o["disabled"]; this.elem.readOnly = o["readonly"]; this.elem["spellcheck"] = o["spellcheck"]; }; instanceProto.onDestroy = function () { if (this.runtime.isDomFree) return; jQuery(this.elem).remove(); this.elem = null; }; instanceProto.tick = function () { this.updatePosition(); }; instanceProto.updatePosition = function (first) { if (this.runtime.isDomFree) return; var left = this.layer.layerToCanvas(this.x, this.y, true); var top = this.layer.layerToCanvas(this.x, this.y, false); var right = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, true); var bottom = this.layer.layerToCanvas(this.x + this.width, this.y + this.height, false); var rightEdge = this.runtime.width / this.runtime.devicePixelRatio; var bottomEdge = this.runtime.height / this.runtime.devicePixelRatio; if (!this.visible || !this.layer.visible || right <= 0 || bottom <= 0 || left >= rightEdge || top >= bottomEdge) { if (!this.element_hidden) jQuery(this.elem).hide(); this.element_hidden = true; return; } if (left < 1) left = 1; if (top < 1) top = 1; if (right >= rightEdge) right = rightEdge - 1; if (bottom >= bottomEdge) bottom = bottomEdge - 1; var curWinWidth = window.innerWidth; var curWinHeight = window.innerHeight; if (!first && this.lastLeft === left && this.lastTop === top && this.lastRight === right && this.lastBottom === bottom && this.lastWinWidth === curWinWidth && this.lastWinHeight === curWinHeight) { if (this.element_hidden) { jQuery(this.elem).show(); this.element_hidden = false; } return; } this.lastLeft = left; this.lastTop = top; this.lastRight = right; this.lastBottom = bottom; this.lastWinWidth = curWinWidth; this.lastWinHeight = curWinHeight; if (this.element_hidden) { jQuery(this.elem).show(); this.element_hidden = false; } var offx = Math.round(left) + jQuery(this.runtime.canvas).offset().left; var offy = Math.round(top) + jQuery(this.runtime.canvas).offset().top; jQuery(this.elem).css("position", "absolute"); jQuery(this.elem).offset({left: offx, top: offy}); jQuery(this.elem).width(Math.round(right - left)); jQuery(this.elem).height(Math.round(bottom - top)); if (this.autoFontSize) jQuery(this.elem).css("font-size", ((this.layer.getScale(true) / this.runtime.devicePixelRatio) - 0.2) + "em"); }; instanceProto.draw = function(ctx) { }; instanceProto.drawGL = function(glw) { }; function Cnds() {}; Cnds.prototype.CompareText = function (text, case_) { if (this.runtime.isDomFree) return false; if (case_ === 0) // insensitive return cr.equals_nocase(this.elem.value, text); else return this.elem.value === text; }; Cnds.prototype.OnTextChanged = function () { return true; }; Cnds.prototype.OnClicked = function () { return true; }; Cnds.prototype.OnDoubleClicked = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetText = function (text) { if (this.runtime.isDomFree) return; this.elem.value = text; }; Acts.prototype.SetPlaceholder = function (text) { if (this.runtime.isDomFree) return; this.elem.placeholder = text; }; Acts.prototype.SetTooltip = function (text) { if (this.runtime.isDomFree) return; this.elem.title = text; }; Acts.prototype.SetVisible = function (vis) { if (this.runtime.isDomFree) return; this.visible = (vis !== 0); }; Acts.prototype.SetEnabled = function (en) { if (this.runtime.isDomFree) return; this.elem.disabled = (en === 0); }; Acts.prototype.SetReadOnly = function (ro) { if (this.runtime.isDomFree) return; this.elem.readOnly = (ro === 0); }; Acts.prototype.SetFocus = function () { if (this.runtime.isDomFree) return; this.elem.focus(); }; Acts.prototype.SetBlur = function () { if (this.runtime.isDomFree) return; this.elem.blur(); }; Acts.prototype.SetCSSStyle = function (p, v) { if (this.runtime.isDomFree) return; jQuery(this.elem).css(p, v); }; Acts.prototype.ScrollToBottom = function () { if (this.runtime.isDomFree) return; this.elem.scrollTop = this.elem.scrollHeight; }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.Text = function (ret) { if (this.runtime.isDomFree) { ret.set_string(""); return; } ret.set_string(this.elem.value); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.TiledBg = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.TiledBg.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { if (this.is_family) return; this.texture_img = new Image(); this.texture_img.cr_filesize = this.texture_filesize; this.runtime.waitForImageLoad(this.texture_img, this.texture_file); this.pattern = null; this.webGL_texture = null; }; typeProto.onLostWebGLContext = function () { if (this.is_family) return; this.webGL_texture = null; }; typeProto.onRestoreWebGLContext = function () { if (this.is_family || !this.instances.length) return; if (!this.webGL_texture) { this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, true, this.runtime.linearSampling, this.texture_pixelformat); } var i, len; for (i = 0, len = this.instances.length; i < len; i++) this.instances[i].webGL_texture = this.webGL_texture; }; typeProto.loadTextures = function () { if (this.is_family || this.webGL_texture || !this.runtime.glwrap) return; this.webGL_texture = this.runtime.glwrap.loadTexture(this.texture_img, true, this.runtime.linearSampling, this.texture_pixelformat); }; typeProto.unloadTextures = function () { if (this.is_family || this.instances.length || !this.webGL_texture) return; this.runtime.glwrap.deleteTexture(this.webGL_texture); this.webGL_texture = null; }; typeProto.preloadCanvas2D = function (ctx) { ctx.drawImage(this.texture_img, 0, 0); }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; }; var instanceProto = pluginProto.Instance.prototype; instanceProto.onCreate = function() { this.visible = (this.properties[0] === 0); // 0=visible, 1=invisible this.rcTex = new cr.rect(0, 0, 0, 0); this.has_own_texture = false; // true if a texture loaded in from URL this.texture_img = this.type.texture_img; if (this.runtime.glwrap) { this.type.loadTextures(); this.webGL_texture = this.type.webGL_texture; } else { if (!this.type.pattern) this.type.pattern = this.runtime.ctx.createPattern(this.type.texture_img, "repeat"); this.pattern = this.type.pattern; } }; instanceProto.afterLoad = function () { this.has_own_texture = false; this.texture_img = this.type.texture_img; }; instanceProto.onDestroy = function () { if (this.runtime.glwrap && this.has_own_texture && this.webGL_texture) { this.runtime.glwrap.deleteTexture(this.webGL_texture); this.webGL_texture = null; } }; instanceProto.draw = function(ctx) { ctx.globalAlpha = this.opacity; ctx.save(); ctx.fillStyle = this.pattern; var myx = this.x; var myy = this.y; if (this.runtime.pixel_rounding) { myx = Math.round(myx); myy = Math.round(myy); } var drawX = -(this.hotspotX * this.width); var drawY = -(this.hotspotY * this.height); var offX = drawX % this.texture_img.width; var offY = drawY % this.texture_img.height; if (offX < 0) offX += this.texture_img.width; if (offY < 0) offY += this.texture_img.height; ctx.translate(myx, myy); ctx.rotate(this.angle); ctx.translate(offX, offY); ctx.fillRect(drawX - offX, drawY - offY, this.width, this.height); ctx.restore(); }; instanceProto.drawGL_earlyZPass = function(glw) { this.drawGL(glw); }; instanceProto.drawGL = function(glw) { glw.setTexture(this.webGL_texture); glw.setOpacity(this.opacity); var rcTex = this.rcTex; rcTex.right = this.width / this.texture_img.width; rcTex.bottom = this.height / this.texture_img.height; var q = this.bquad; if (this.runtime.pixel_rounding) { var ox = Math.round(this.x) - this.x; var oy = Math.round(this.y) - this.y; 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); } else glw.quadTex(q.tlx, q.tly, q.trx, q.try_, q.brx, q.bry, q.blx, q.bly, rcTex); }; function Cnds() {}; Cnds.prototype.OnURLLoaded = function () { return true; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetEffect = function (effect) { this.blend_mode = effect; this.compositeOp = cr.effectToCompositeOp(effect); cr.setGLBlend(this, effect, this.runtime.gl); this.runtime.redraw = true; }; Acts.prototype.LoadURL = function (url_, crossOrigin_) { var img = new Image(); var self = this; img.onload = function () { self.texture_img = img; if (self.runtime.glwrap) { if (self.has_own_texture && self.webGL_texture) self.runtime.glwrap.deleteTexture(self.webGL_texture); self.webGL_texture = self.runtime.glwrap.loadTexture(img, true, self.runtime.linearSampling); } else { self.pattern = self.runtime.ctx.createPattern(img, "repeat"); } self.has_own_texture = true; self.runtime.redraw = true; self.runtime.trigger(cr.plugins_.TiledBg.prototype.cnds.OnURLLoaded, self); }; if (url_.substr(0, 5) !== "data:" && crossOrigin_ === 0) img.crossOrigin = "anonymous"; this.runtime.setImageSrc(img, url_); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.ImageWidth = function (ret) { ret.set_float(this.texture_img.width); }; Exps.prototype.ImageHeight = function (ret) { ret.set_float(this.texture_img.height); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.Touch = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.Touch.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; this.touches = []; this.mouseDown = false; }; var instanceProto = pluginProto.Instance.prototype; var dummyoffset = {left: 0, top: 0}; instanceProto.findTouch = function (id) { var i, len; for (i = 0, len = this.touches.length; i < len; i++) { if (this.touches[i]["id"] === id) return i; } return -1; }; var appmobi_accx = 0; var appmobi_accy = 0; var appmobi_accz = 0; function AppMobiGetAcceleration(evt) { appmobi_accx = evt.x; appmobi_accy = evt.y; appmobi_accz = evt.z; }; var pg_accx = 0; var pg_accy = 0; var pg_accz = 0; function PhoneGapGetAcceleration(evt) { pg_accx = evt.x; pg_accy = evt.y; pg_accz = evt.z; }; var theInstance = null; var touchinfo_cache = []; function AllocTouchInfo(x, y, id, index) { var ret; if (touchinfo_cache.length) ret = touchinfo_cache.pop(); else ret = new TouchInfo(); ret.init(x, y, id, index); return ret; }; function ReleaseTouchInfo(ti) { if (touchinfo_cache.length < 100) touchinfo_cache.push(ti); }; var GESTURE_HOLD_THRESHOLD = 15; // max px motion for hold gesture to register var GESTURE_HOLD_TIMEOUT = 500; // time for hold gesture to register var GESTURE_TAP_TIMEOUT = 333; // time for tap gesture to register var GESTURE_DOUBLETAP_THRESHOLD = 25; // max distance apart for taps to be function TouchInfo() { this.starttime = 0; this.time = 0; this.lasttime = 0; this.startx = 0; this.starty = 0; this.x = 0; this.y = 0; this.lastx = 0; this.lasty = 0; this["id"] = 0; this.startindex = 0; this.triggeredHold = false; this.tooFarForHold = false; }; TouchInfo.prototype.init = function (x, y, id, index) { var nowtime = cr.performance_now(); this.time = nowtime; this.lasttime = nowtime; this.starttime = nowtime; this.startx = x; this.starty = y; this.x = x; this.y = y; this.lastx = x; this.lasty = y; this.width = 0; this.height = 0; this.pressure = 0; this["id"] = id; this.startindex = index; this.triggeredHold = false; this.tooFarForHold = false; }; TouchInfo.prototype.update = function (nowtime, x, y, width, height, pressure) { this.lasttime = this.time; this.time = nowtime; this.lastx = this.x; this.lasty = this.y; this.x = x; this.y = y; this.width = width; this.height = height; this.pressure = pressure; if (!this.tooFarForHold && cr.distanceTo(this.startx, this.starty, this.x, this.y) >= GESTURE_HOLD_THRESHOLD) { this.tooFarForHold = true; } }; TouchInfo.prototype.maybeTriggerHold = function (inst, index) { if (this.triggeredHold) return; // already triggered this gesture var nowtime = cr.performance_now(); if (nowtime - this.starttime >= GESTURE_HOLD_TIMEOUT && !this.tooFarForHold && cr.distanceTo(this.startx, this.starty, this.x, this.y) < GESTURE_HOLD_THRESHOLD) { this.triggeredHold = true; inst.trigger_index = this.startindex; inst.trigger_id = this["id"]; inst.getTouchIndex = index; inst.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnHoldGesture, inst); inst.curTouchX = this.x; inst.curTouchY = this.y; inst.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnHoldGestureObject, inst); inst.getTouchIndex = 0; } }; var lastTapX = -1000; var lastTapY = -1000; var lastTapTime = -10000; TouchInfo.prototype.maybeTriggerTap = function (inst, index) { if (this.triggeredHold) return; var nowtime = cr.performance_now(); if (nowtime - this.starttime <= GESTURE_TAP_TIMEOUT && !this.tooFarForHold && cr.distanceTo(this.startx, this.starty, this.x, this.y) < GESTURE_HOLD_THRESHOLD) { inst.trigger_index = this.startindex; inst.trigger_id = this["id"]; inst.getTouchIndex = index; if ((nowtime - lastTapTime <= GESTURE_TAP_TIMEOUT * 2) && cr.distanceTo(lastTapX, lastTapY, this.x, this.y) < GESTURE_DOUBLETAP_THRESHOLD) { inst.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnDoubleTapGesture, inst); inst.curTouchX = this.x; inst.curTouchY = this.y; inst.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnDoubleTapGestureObject, inst); lastTapX = -1000; lastTapY = -1000; lastTapTime = -10000; } else { inst.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTapGesture, inst); inst.curTouchX = this.x; inst.curTouchY = this.y; inst.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTapGestureObject, inst); lastTapX = this.x; lastTapY = this.y; lastTapTime = nowtime; } inst.getTouchIndex = 0; } }; instanceProto.onCreate = function() { theInstance = this; this.isWindows8 = !!(typeof window["c2isWindows8"] !== "undefined" && window["c2isWindows8"]); this.orient_alpha = 0; this.orient_beta = 0; this.orient_gamma = 0; this.acc_g_x = 0; this.acc_g_y = 0; this.acc_g_z = 0; this.acc_x = 0; this.acc_y = 0; this.acc_z = 0; this.curTouchX = 0; this.curTouchY = 0; this.trigger_index = 0; this.trigger_id = 0; this.trigger_permission = 0; this.getTouchIndex = 0; this.useMouseInput = (this.properties[0] !== 0); var elem = (this.runtime.fullscreen_mode > 0) ? document : this.runtime.canvas; var elem2 = document; if (this.runtime.isDirectCanvas) elem2 = elem = window["Canvas"]; else if (this.runtime.isCocoonJs) elem2 = elem = window; var self = this; if (typeof PointerEvent !== "undefined") { elem.addEventListener("pointerdown", function(info) { self.onPointerStart(info); }, false ); elem.addEventListener("pointermove", function(info) { self.onPointerMove(info); }, false ); elem2.addEventListener("pointerup", function(info) { self.onPointerEnd(info, false); }, false ); elem2.addEventListener("pointercancel", function(info) { self.onPointerEnd(info, true); }, false ); if (this.runtime.canvas) { this.runtime.canvas.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); document.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); this.runtime.canvas.addEventListener("gesturehold", function(e) { e.preventDefault(); }, false); document.addEventListener("gesturehold", function(e) { e.preventDefault(); }, false); } } else if (window.navigator["msPointerEnabled"]) { elem.addEventListener("MSPointerDown", function(info) { self.onPointerStart(info); }, false ); elem.addEventListener("MSPointerMove", function(info) { self.onPointerMove(info); }, false ); elem2.addEventListener("MSPointerUp", function(info) { self.onPointerEnd(info, false); }, false ); elem2.addEventListener("MSPointerCancel", function(info) { self.onPointerEnd(info, true); }, false ); if (this.runtime.canvas) { this.runtime.canvas.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); document.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); } } else { elem.addEventListener("touchstart", function(info) { self.onTouchStart(info); }, false ); elem.addEventListener("touchmove", function(info) { self.onTouchMove(info); }, false ); elem2.addEventListener("touchend", function(info) { self.onTouchEnd(info, false); }, false ); elem2.addEventListener("touchcancel", function(info) { self.onTouchEnd(info, true); }, false ); } if (this.isWindows8) { var win8accelerometerFn = function(e) { var reading = e["reading"]; self.acc_x = reading["accelerationX"]; self.acc_y = reading["accelerationY"]; self.acc_z = reading["accelerationZ"]; }; var win8inclinometerFn = function(e) { var reading = e["reading"]; self.orient_alpha = reading["yawDegrees"]; self.orient_beta = reading["pitchDegrees"]; self.orient_gamma = reading["rollDegrees"]; }; var accelerometer = Windows["Devices"]["Sensors"]["Accelerometer"]["getDefault"](); if (accelerometer) { accelerometer["reportInterval"] = Math.max(accelerometer["minimumReportInterval"], 16); accelerometer.addEventListener("readingchanged", win8accelerometerFn); } var inclinometer = Windows["Devices"]["Sensors"]["Inclinometer"]["getDefault"](); if (inclinometer) { inclinometer["reportInterval"] = Math.max(inclinometer["minimumReportInterval"], 16); inclinometer.addEventListener("readingchanged", win8inclinometerFn); } document.addEventListener("visibilitychange", function(e) { if (document["hidden"] || document["msHidden"]) { if (accelerometer) accelerometer.removeEventListener("readingchanged", win8accelerometerFn); if (inclinometer) inclinometer.removeEventListener("readingchanged", win8inclinometerFn); } else { if (accelerometer) accelerometer.addEventListener("readingchanged", win8accelerometerFn); if (inclinometer) inclinometer.addEventListener("readingchanged", win8inclinometerFn); } }, false); } else { window.addEventListener("deviceorientation", function (eventData) { self.orient_alpha = eventData["alpha"] || 0; self.orient_beta = eventData["beta"] || 0; self.orient_gamma = eventData["gamma"] || 0; }, false); window.addEventListener("devicemotion", function (eventData) { if (eventData["accelerationIncludingGravity"]) { self.acc_g_x = eventData["accelerationIncludingGravity"]["x"] || 0; self.acc_g_y = eventData["accelerationIncludingGravity"]["y"] || 0; self.acc_g_z = eventData["accelerationIncludingGravity"]["z"] || 0; } if (eventData["acceleration"]) { self.acc_x = eventData["acceleration"]["x"] || 0; self.acc_y = eventData["acceleration"]["y"] || 0; self.acc_z = eventData["acceleration"]["z"] || 0; } }, false); } if (this.useMouseInput && !this.runtime.isDomFree) { jQuery(document).mousemove( function(info) { self.onMouseMove(info); } ); jQuery(document).mousedown( function(info) { self.onMouseDown(info); } ); jQuery(document).mouseup( function(info) { self.onMouseUp(info); } ); } if (!this.runtime.isiOS && this.runtime.isCordova && navigator["accelerometer"] && navigator["accelerometer"]["watchAcceleration"]) { navigator["accelerometer"]["watchAcceleration"](PhoneGapGetAcceleration, null, { "frequency": 40 }); } this.runtime.tick2Me(this); }; instanceProto.onPointerMove = function (info) { if (info["pointerType"] === info["MSPOINTER_TYPE_MOUSE"] || info["pointerType"] === "mouse") return; if (info.preventDefault) info.preventDefault(); var i = this.findTouch(info["pointerId"]); var nowtime = cr.performance_now(); if (i >= 0) { var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset(); var t = this.touches[i]; if (nowtime - t.time < 2) return; t.update(nowtime, info.pageX - offset.left, info.pageY - offset.top, info.width || 0, info.height || 0, info.pressure || 0); } }; instanceProto.onPointerStart = function (info) { if (info["pointerType"] === info["MSPOINTER_TYPE_MOUSE"] || info["pointerType"] === "mouse") return; if (info.preventDefault && cr.isCanvasInputEvent(info)) info.preventDefault(); var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset(); var touchx = info.pageX - offset.left; var touchy = info.pageY - offset.top; var nowtime = cr.performance_now(); this.trigger_index = this.touches.length; this.trigger_id = info["pointerId"]; this.touches.push(AllocTouchInfo(touchx, touchy, info["pointerId"], this.trigger_index)); this.runtime.isInUserInputEvent = true; this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnNthTouchStart, this); this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTouchStart, this); this.curTouchX = touchx; this.curTouchY = touchy; this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTouchObject, this); this.runtime.isInUserInputEvent = false; }; instanceProto.onPointerEnd = function (info, isCancel) { if (info["pointerType"] === info["MSPOINTER_TYPE_MOUSE"] || info["pointerType"] === "mouse") return; if (info.preventDefault && cr.isCanvasInputEvent(info)) info.preventDefault(); var i = this.findTouch(info["pointerId"]); this.trigger_index = (i >= 0 ? this.touches[i].startindex : -1); this.trigger_id = (i >= 0 ? this.touches[i]["id"] : -1); this.runtime.isInUserInputEvent = true; this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnNthTouchEnd, this); this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTouchEnd, this); if (i >= 0) { if (!isCancel) this.touches[i].maybeTriggerTap(this, i); ReleaseTouchInfo(this.touches[i]); this.touches.splice(i, 1); } this.runtime.isInUserInputEvent = false; }; instanceProto.onTouchMove = function (info) { if (info.preventDefault) info.preventDefault(); var nowtime = cr.performance_now(); var i, len, t, u; for (i = 0, len = info.changedTouches.length; i < len; i++) { t = info.changedTouches[i]; var j = this.findTouch(t["identifier"]); if (j >= 0) { var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset(); u = this.touches[j]; if (nowtime - u.time < 2) continue; var touchWidth = (t.radiusX || t.webkitRadiusX || t.mozRadiusX || t.msRadiusX || 0) * 2; var touchHeight = (t.radiusY || t.webkitRadiusY || t.mozRadiusY || t.msRadiusY || 0) * 2; var touchForce = t.force || t.webkitForce || t.mozForce || t.msForce || 0; u.update(nowtime, t.pageX - offset.left, t.pageY - offset.top, touchWidth, touchHeight, touchForce); } } }; instanceProto.onTouchStart = function (info) { if (info.preventDefault && cr.isCanvasInputEvent(info)) info.preventDefault(); var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset(); var nowtime = cr.performance_now(); this.runtime.isInUserInputEvent = true; var i, len, t, j; for (i = 0, len = info.changedTouches.length; i < len; i++) { t = info.changedTouches[i]; j = this.findTouch(t["identifier"]); if (j !== -1) continue; var touchx = t.pageX - offset.left; var touchy = t.pageY - offset.top; this.trigger_index = this.touches.length; this.trigger_id = t["identifier"]; this.touches.push(AllocTouchInfo(touchx, touchy, t["identifier"], this.trigger_index)); this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnNthTouchStart, this); this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTouchStart, this); this.curTouchX = touchx; this.curTouchY = touchy; this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTouchObject, this); } this.runtime.isInUserInputEvent = false; }; instanceProto.onTouchEnd = function (info, isCancel) { if (info.preventDefault && cr.isCanvasInputEvent(info)) info.preventDefault(); this.runtime.isInUserInputEvent = true; var i, len, t, j; for (i = 0, len = info.changedTouches.length; i < len; i++) { t = info.changedTouches[i]; j = this.findTouch(t["identifier"]); if (j >= 0) { this.trigger_index = this.touches[j].startindex; this.trigger_id = this.touches[j]["id"]; this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnNthTouchEnd, this); this.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnTouchEnd, this); if (!isCancel) this.touches[j].maybeTriggerTap(this, j); ReleaseTouchInfo(this.touches[j]); this.touches.splice(j, 1); } } this.runtime.isInUserInputEvent = false; }; instanceProto.getAlpha = function () { if (this.runtime.isCordova && this.orient_alpha === 0 && pg_accz !== 0) return pg_accz * 90; else return this.orient_alpha; }; instanceProto.getBeta = function () { if (this.runtime.isCordova && this.orient_beta === 0 && pg_accy !== 0) return pg_accy * 90; else return this.orient_beta; }; instanceProto.getGamma = function () { if (this.runtime.isCordova && this.orient_gamma === 0 && pg_accx !== 0) return pg_accx * 90; else return this.orient_gamma; }; var noop_func = function(){}; function isCompatibilityMouseEvent(e) { return (e["sourceCapabilities"] && e["sourceCapabilities"]["firesTouchEvents"]) || (e.originalEvent && e.originalEvent["sourceCapabilities"] && e.originalEvent["sourceCapabilities"]["firesTouchEvents"]); }; instanceProto.onMouseDown = function(info) { if (isCompatibilityMouseEvent(info)) return; var t = { pageX: info.pageX, pageY: info.pageY, "identifier": 0 }; var fakeinfo = { changedTouches: [t] }; this.onTouchStart(fakeinfo); this.mouseDown = true; }; instanceProto.onMouseMove = function(info) { if (!this.mouseDown) return; if (isCompatibilityMouseEvent(info)) return; var t = { pageX: info.pageX, pageY: info.pageY, "identifier": 0 }; var fakeinfo = { changedTouches: [t] }; this.onTouchMove(fakeinfo); }; instanceProto.onMouseUp = function(info) { if (info.preventDefault && this.runtime.had_a_click && !this.runtime.isMobile) info.preventDefault(); this.runtime.had_a_click = true; if (isCompatibilityMouseEvent(info)) return; var t = { pageX: info.pageX, pageY: info.pageY, "identifier": 0 }; var fakeinfo = { changedTouches: [t] }; this.onTouchEnd(fakeinfo); this.mouseDown = false; }; instanceProto.tick2 = function() { var i, len, t; var nowtime = cr.performance_now(); for (i = 0, len = this.touches.length; i < len; ++i) { t = this.touches[i]; if (t.time <= nowtime - 50) t.lasttime = nowtime; t.maybeTriggerHold(this, i); } }; function Cnds() {}; Cnds.prototype.OnTouchStart = function () { return true; }; Cnds.prototype.OnTouchEnd = function () { return true; }; Cnds.prototype.IsInTouch = function () { return this.touches.length; }; Cnds.prototype.OnTouchObject = function (type) { if (!type) return false; return this.runtime.testAndSelectCanvasPointOverlap(type, this.curTouchX, this.curTouchY, false); }; var touching = []; Cnds.prototype.IsTouchingObject = function (type) { if (!type) return false; var sol = type.getCurrentSol(); var instances = sol.getObjects(); var px, py; var i, leni, j, lenj; for (i = 0, leni = instances.length; i < leni; i++) { var inst = instances[i]; inst.update_bbox(); for (j = 0, lenj = this.touches.length; j < lenj; j++) { var touch = this.touches[j]; px = inst.layer.canvasToLayer(touch.x, touch.y, true); py = inst.layer.canvasToLayer(touch.x, touch.y, false); if (inst.contains_pt(px, py)) { touching.push(inst); break; } } } if (touching.length) { sol.select_all = false; cr.shallowAssignArray(sol.instances, touching); type.applySolToContainer(); cr.clearArray(touching); return true; } else return false; }; Cnds.prototype.CompareTouchSpeed = function (index, cmp, s) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) return false; var t = this.touches[index]; var dist = cr.distanceTo(t.x, t.y, t.lastx, t.lasty); var timediff = (t.time - t.lasttime) / 1000; var speed = 0; if (timediff > 0) speed = dist / timediff; return cr.do_cmp(speed, cmp, s); }; Cnds.prototype.OrientationSupported = function () { return typeof window["DeviceOrientationEvent"] !== "undefined"; }; Cnds.prototype.MotionSupported = function () { return typeof window["DeviceMotionEvent"] !== "undefined"; }; Cnds.prototype.CompareOrientation = function (orientation_, cmp_, angle_) { var v = 0; if (orientation_ === 0) v = this.getAlpha(); else if (orientation_ === 1) v = this.getBeta(); else v = this.getGamma(); return cr.do_cmp(v, cmp_, angle_); }; Cnds.prototype.CompareAcceleration = function (acceleration_, cmp_, angle_) { var v = 0; if (acceleration_ === 0) v = this.acc_g_x; else if (acceleration_ === 1) v = this.acc_g_y; else if (acceleration_ === 2) v = this.acc_g_z; else if (acceleration_ === 3) v = this.acc_x; else if (acceleration_ === 4) v = this.acc_y; else if (acceleration_ === 5) v = this.acc_z; return cr.do_cmp(v, cmp_, angle_); }; Cnds.prototype.OnNthTouchStart = function (touch_) { touch_ = Math.floor(touch_); return touch_ === this.trigger_index; }; Cnds.prototype.OnNthTouchEnd = function (touch_) { touch_ = Math.floor(touch_); return touch_ === this.trigger_index; }; Cnds.prototype.HasNthTouch = function (touch_) { touch_ = Math.floor(touch_); return this.touches.length >= touch_ + 1; }; Cnds.prototype.OnHoldGesture = function () { return true; }; Cnds.prototype.OnTapGesture = function () { return true; }; Cnds.prototype.OnDoubleTapGesture = function () { return true; }; Cnds.prototype.OnHoldGestureObject = function (type) { if (!type) return false; return this.runtime.testAndSelectCanvasPointOverlap(type, this.curTouchX, this.curTouchY, false); }; Cnds.prototype.OnTapGestureObject = function (type) { if (!type) return false; return this.runtime.testAndSelectCanvasPointOverlap(type, this.curTouchX, this.curTouchY, false); }; Cnds.prototype.OnDoubleTapGestureObject = function (type) { if (!type) return false; return this.runtime.testAndSelectCanvasPointOverlap(type, this.curTouchX, this.curTouchY, false); }; Cnds.prototype.OnPermissionGranted = function (type) { return this.trigger_permission === type; }; Cnds.prototype.OnPermissionDenied = function (type) { return this.trigger_permission === type; }; pluginProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.RequestPermission = function (type) { var self = this; var promise = Promise.resolve(true); if (type === 0) // orientation { if (window["DeviceOrientationEvent"] && window["DeviceOrientationEvent"]["requestPermission"]) { promise = window["DeviceOrientationEvent"]["requestPermission"]() .then(function (state) { return state === "granted"; }); } } else // motion { if (window["DeviceMotionEvent"] && window["DeviceMotionEvent"]["requestPermission"]) { promise = window["DeviceMotionEvent"]["requestPermission"]() .then(function (state) { return state === "granted"; }); } } promise.then(function (result) { self.trigger_permission = type; if (result) self.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnPermissionGranted, self); else self.runtime.trigger(cr.plugins_.Touch.prototype.cnds.OnPermissionDenied, self); }); }; pluginProto.acts = new Acts(); function Exps() {}; Exps.prototype.TouchCount = function (ret) { ret.set_int(this.touches.length); }; Exps.prototype.X = function (ret, layerparam) { var index = this.getTouchIndex; if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true)); else ret.set_float(0); } }; Exps.prototype.XAt = function (ret, index, layerparam) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true)); else ret.set_float(0); } }; Exps.prototype.XForID = function (ret, id, layerparam) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(touch.x, touch.y, true)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(touch.x, touch.y, true)); else ret.set_float(0); } }; Exps.prototype.Y = function (ret, layerparam) { var index = this.getTouchIndex; if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var layer, oldScale, oldZoomRate, oldParallaxY, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxY = layer.parallaxY; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxY = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxY = oldParallaxY; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false)); else ret.set_float(0); } }; Exps.prototype.YAt = function (ret, index, layerparam) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var layer, oldScale, oldZoomRate, oldParallaxY, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxY = layer.parallaxY; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxY = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxY = oldParallaxY; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false)); else ret.set_float(0); } }; Exps.prototype.YForID = function (ret, id, layerparam) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; var layer, oldScale, oldZoomRate, oldParallaxY, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxY = layer.parallaxY; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxY = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(touch.x, touch.y, false)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxY = oldParallaxY; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(touch.x, touch.y, false)); else ret.set_float(0); } }; Exps.prototype.AbsoluteX = function (ret) { if (this.touches.length) ret.set_float(this.touches[0].x); else ret.set_float(0); }; Exps.prototype.AbsoluteXAt = function (ret, index) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } ret.set_float(this.touches[index].x); }; Exps.prototype.AbsoluteXForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(touch.x); }; Exps.prototype.AbsoluteY = function (ret) { if (this.touches.length) ret.set_float(this.touches[0].y); else ret.set_float(0); }; Exps.prototype.AbsoluteYAt = function (ret, index) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } ret.set_float(this.touches[index].y); }; Exps.prototype.AbsoluteYForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(touch.y); }; Exps.prototype.SpeedAt = function (ret, index) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var t = this.touches[index]; var dist = cr.distanceTo(t.x, t.y, t.lastx, t.lasty); var timediff = (t.time - t.lasttime) / 1000; if (timediff <= 0) ret.set_float(0); else ret.set_float(dist / timediff); }; Exps.prototype.SpeedForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; var dist = cr.distanceTo(touch.x, touch.y, touch.lastx, touch.lasty); var timediff = (touch.time - touch.lasttime) / 1000; if (timediff <= 0) ret.set_float(0); else ret.set_float(dist / timediff); }; Exps.prototype.AngleAt = function (ret, index) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var t = this.touches[index]; ret.set_float(cr.to_degrees(cr.angleTo(t.lastx, t.lasty, t.x, t.y))); }; Exps.prototype.AngleForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(cr.to_degrees(cr.angleTo(touch.lastx, touch.lasty, touch.x, touch.y))); }; Exps.prototype.Alpha = function (ret) { ret.set_float(this.getAlpha()); }; Exps.prototype.Beta = function (ret) { ret.set_float(this.getBeta()); }; Exps.prototype.Gamma = function (ret) { ret.set_float(this.getGamma()); }; Exps.prototype.AccelerationXWithG = function (ret) { ret.set_float(this.acc_g_x); }; Exps.prototype.AccelerationYWithG = function (ret) { ret.set_float(this.acc_g_y); }; Exps.prototype.AccelerationZWithG = function (ret) { ret.set_float(this.acc_g_z); }; Exps.prototype.AccelerationX = function (ret) { ret.set_float(this.acc_x); }; Exps.prototype.AccelerationY = function (ret) { ret.set_float(this.acc_y); }; Exps.prototype.AccelerationZ = function (ret) { ret.set_float(this.acc_z); }; Exps.prototype.TouchIndex = function (ret) { ret.set_int(this.trigger_index); }; Exps.prototype.TouchID = function (ret) { ret.set_float(this.trigger_id); }; Exps.prototype.WidthForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(touch.width); }; Exps.prototype.HeightForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(touch.height); }; Exps.prototype.PressureForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(touch.pressure); }; pluginProto.exps = new Exps(); }()); ; ; cr.plugins_.aekiro_proui2 = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.aekiro_proui2.prototype; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; this.touches = []; this.mouseDown = false; this.touchDown = false; this.cursor = {x:null, y:null}; this._callbackObjs = {}; this._callbackObjs["touch"] = []; this._callbackObjs["wheel"] = []; this.handled = false; }; var instanceProto = pluginProto.Instance.prototype; var dummyoffset = {left: 0, top: 0}; instanceProto.findTouch = function (id) { var i, len; for (i = 0, len = this.touches.length; i < len; i++) { if (this.touches[i]["id"] === id) return i; } return -1; }; var theInstance = null; var touchinfo_cache = []; function AllocTouchInfo(x, y, id, index) { var ret; if (touchinfo_cache.length) ret = touchinfo_cache.pop(); else ret = new TouchInfo(); ret.init(x, y, id, index); return ret; }; function ReleaseTouchInfo(ti) { if (touchinfo_cache.length < 100) touchinfo_cache.push(ti); }; var GESTURE_HOLD_THRESHOLD = 15; // max px motion for hold gesture to register var GESTURE_HOLD_TIMEOUT = 500; // time for hold gesture to register var GESTURE_TAP_TIMEOUT = 333; // time for tap gesture to register var GESTURE_DOUBLETAP_THRESHOLD = 25; // max distance apart for taps to be function TouchInfo() { this.starttime = 0; this.time = 0; this.lasttime = 0; this.startx = 0; this.starty = 0; this.x = 0; this.y = 0; this.lastx = 0; this.lasty = 0; this["id"] = 0; this.startindex = 0; this.triggeredHold = false; this.tooFarForHold = false; }; TouchInfo.prototype.init = function (x, y, id, index) { var nowtime = cr.performance_now(); this.time = nowtime; this.lasttime = nowtime; this.starttime = nowtime; this.startx = x; this.starty = y; this.x = x; this.y = y; this.lastx = x; this.lasty = y; this.width = 0; this.height = 0; this.pressure = 0; this["id"] = id; this.startindex = index; this.triggeredHold = false; this.tooFarForHold = false; }; TouchInfo.prototype.update = function (nowtime, x, y, width, height, pressure) { this.lasttime = this.time; this.time = nowtime; this.lastx = this.x; this.lasty = this.y; this.x = x; this.y = y; this.width = width; this.height = height; this.pressure = pressure; if (!this.tooFarForHold && cr.distanceTo(this.startx, this.starty, this.x, this.y) >= GESTURE_HOLD_THRESHOLD) { this.tooFarForHold = true; } }; var lastTapX = -1000; var lastTapY = -1000; var lastTapTime = -10000; TouchInfo.prototype.maybeTriggerTap = function (inst, index) { if (this.triggeredHold) return; var nowtime = cr.performance_now(); if (nowtime - this.starttime <= GESTURE_TAP_TIMEOUT && !this.tooFarForHold && cr.distanceTo(this.startx, this.starty, this.x, this.y) < GESTURE_HOLD_THRESHOLD) { inst.trigger_index = this.startindex; inst.trigger_id = this["id"]; inst.getTouchIndex = index; if ((nowtime - lastTapTime <= GESTURE_TAP_TIMEOUT * 2) && cr.distanceTo(lastTapX, lastTapY, this.x, this.y) < GESTURE_DOUBLETAP_THRESHOLD) { inst.curTouchX = this.x; inst.curTouchY = this.y; lastTapX = -1000; lastTapY = -1000; lastTapTime = -10000; } else { inst.curTouchX = this.x; inst.curTouchY = this.y; lastTapX = this.x; lastTapY = this.y; lastTapTime = nowtime; } inst.getTouchIndex = 0; } }; instanceProto.onCreate = function() { theInstance = this; this.isWindows8 = !!(typeof window["c2isWindows8"] !== "undefined" && window["c2isWindows8"]); this.curTouchX = 0; this.curTouchY = 0; this.trigger_index = 0; this.trigger_id = 0; this.getTouchIndex = 0; this.useMouseInput = true; var elem = (this.runtime.fullscreen_mode > 0) ? document : this.runtime.canvas; var elem2 = document; if (this.runtime.isDirectCanvas) elem2 = elem = window["Canvas"]; else if (this.runtime.isCocoonJs) elem2 = elem = window; var self = this; if (typeof PointerEvent !== "undefined") { elem.addEventListener("pointerdown", function(info) { self.onPointerStart(info); }, false ); elem.addEventListener("pointermove", function(info) { self.onPointerMove(info); }, false ); elem2.addEventListener("pointerup", function(info) { self.onPointerEnd(info, false); }, false ); elem2.addEventListener("pointercancel", function(info) { self.onPointerEnd(info, true); }, false ); if (this.runtime.canvas) { this.runtime.canvas.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); document.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); this.runtime.canvas.addEventListener("gesturehold", function(e) { e.preventDefault(); }, false); document.addEventListener("gesturehold", function(e) { e.preventDefault(); }, false); } } else if (window.navigator["msPointerEnabled"]) { elem.addEventListener("MSPointerDown", function(info) { self.onPointerStart(info); }, false ); elem.addEventListener("MSPointerMove", function(info) { self.onPointerMove(info); }, false ); elem2.addEventListener("MSPointerUp", function(info) { self.onPointerEnd(info, false); }, false ); elem2.addEventListener("MSPointerCancel", function(info) { self.onPointerEnd(info, true); }, false ); if (this.runtime.canvas) { this.runtime.canvas.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); document.addEventListener("MSGestureHold", function(e) { e.preventDefault(); }, false); } } else { elem.addEventListener("touchstart", function(info) { self.onTouchStart(info); }, false ); elem.addEventListener("touchmove", function(info) { self.onTouchMove(info); }, false ); elem2.addEventListener("touchend", function(info) { self.onTouchEnd(info, false); }, false ); elem2.addEventListener("touchcancel", function(info) { self.onTouchEnd(info, true); }, false ); } if (this.useMouseInput && !this.runtime.isDomFree) { jQuery(document).mousemove( function(info) { self.onMouseMove(info); } ); jQuery(document).mousedown( function(info) { self.onMouseDown(info); } ); jQuery(document).mouseup( function(info) { self.onMouseUp(info); } ); } if (!this.runtime.isDomFree) { var wheelevent = function(info){ self.onWheel(info); }; document.addEventListener("mousewheel", wheelevent, false); document.addEventListener("DOMMouseScroll", wheelevent, false); } this.runtime.tick2Me(this); this.enable = true; this.lastTouchX = null; this.lastTouchY = null; cr.proui = this; this.cssURL = this.properties[0]; this.fontFamily = this.properties[1]; this.firstFrame = true; /*The following is to get around not being able to destroy other instance in onDestroy of an instance, cf onDestroy of radiogroup */ var runtime = this.runtime; this.toBeDestroyed = []; this.currentDialogs = []; this.currentDialogs_lastResetTick = 0; this.tags = {}; this.tags_lastResetTick = 0; this.iter = 0; this.notRegister = false; }; instanceProto.getIter = function(){ this.iter++; return this.iter; }; instanceProto.setNoRegister = function(){ }; instanceProto.addTag = function(tag,inst){ if(this.runtime.extra.notRegister || !tag){ return; } /*if(this.runtime.changelayout && this.tags_lastResetTick != this.runtime.tickcount){ this.tags = {} ; this.tags_lastResetTick = this.runtime.tickcount; }*/ if(this.tags.hasOwnProperty(tag)){ console.error("PROUI: Tag %s already exist !",tag); return; } this.tags[tag] = inst; }; instanceProto.removeTag = function(tag){ delete this.tags[tag]; }; instanceProto.addDialog = function(behavior){ if(this.runtime.changelayout && this.currentDialogs_lastResetTick != this.runtime.tickcount){ this.currentDialogs.length = 0; this.currentDialogs_lastResetTick = this.runtime.tickcount; } this.currentDialogs.push(behavior); }; instanceProto.isModalDialogOpened = function(){ for (var i = 0; i < this.currentDialogs.length; i++) { if(this.currentDialogs[i].isModal){ return true; } } return false; }; instanceProto.removeDialog = function(behavior){ this.removeFromArray(this.currentDialogs,behavior); }; instanceProto.removeFromArray = function(array,e){ for (var i = 0,l=array.length; i < l; i++) { if(array[i] == e){ array.splice(i, 1); return; } } }; instanceProto.clearDestroyList = function (){ var toBeDestroyed = this.toBeDestroyed; for (var i = 0,l=toBeDestroyed.length; i < l; i++) { this.runtime.DestroyInstance(toBeDestroyed[i]); } toBeDestroyed.length = 0; }; instanceProto.playAudio = function (fileName){ this.getDependency(cr.plugins_.Audio,"audio"); if(this["audio"]){ cr.plugins_.Audio.prototype.acts.PlayByName.call(this["audio"],0,fileName, 0, 0, "sound"); }else{ console.error("ProUI: Please add the Audio plugin to the project."); } }; instanceProto.getDependency = function (dependency, dependencyRef) { if (this[dependencyRef] != null){ return this[dependencyRef]; } if(!dependency){ console.error("ProUI: Can not find the "+dependencyRef+" object."); return; } var plugins = this.runtime.types var name, inst; for (name in plugins) { inst = plugins[name].instances[0]; if (inst instanceof dependency.prototype.Instance) { this[dependencyRef] = inst; return this[dependencyRef]; } } if(!this[dependencyRef]){ console.error("ProUI: Can not find "+dependencyRef+" object."); } }; instanceProto.isTypeValid = function (inst,types,errorMsg){ var test; for (var i = 0, l= types.length; i < l; i++) { test = types[i]?(inst.type.plugin instanceof types[i]):false; if(test){ return; } } throw new Error(errorMsg); }; /*behinstProto.runCallback = function () { if(this.callbackName == ""){ return; } var params = this.callbackParams.split(","); if(this.callbackName[0]=="$"){ //$41$transitionToLayout var callback = this.callbackName.split("$"); console.log(callback); var inst = this.runtime.getObjectByUID(parseInt(callback[1])); if(inst){ console.log(inst.type); } }else{ c2_callFunction(this.callbackName,params); } };*/ instanceProto.runCallback = function (callbackName,callbackParams) { if(callbackName == ""){ return; } var params = callbackParams.split(","); var callFunction = window["c2_callFunction"]; if(callFunction){ callFunction(callbackName,params); }else{ console.error("ProUI : Please add the Function plugin to the project."); } }; instanceProto.validateSimpleValue = function(value, default_value) { var o; if (value === true){ o = 1; } else if (value === false){ o = 0; } else if (value == null || value == undefined || typeof(value) == "object") { if (default_value != null && default_value != undefined) o = default_value; else o = 0; } else{ o = value; } return o; }; instanceProto.HookMe = function (obj,types) { var type; for (var i = 0,l=types.length; i < l; i++) { type = types[i]; this._callbackObjs[type].push(obj); } }; instanceProto.UnHookMe = function (obj,types) { var type; for (var i = 0,l=types.length; i < l; i++) { type = types[i]; cr.arrayFindRemove(this._callbackObjs[type], obj); } }; function getThisBehavior(inst,behaviorProto) { var i, len; for (i = 0, len = inst.behavior_insts.length; i < len; i++) { if (inst.behavior_insts[i] instanceof behaviorProto.Instance) return inst.behavior_insts[i]; } return null; }; /*var dispatchTouchStart = function(touchX, touchY) { var instances = this.my_instances.valuesRef(); var instance; var lx, ly; var objectInstances = []; for (var i=0,l=instances.length; i maxZInstance.layer.index) || ( (objectInstances[i].layer.index == maxZInstance.layer.index) && (objectInstances[i].get_zindex() > maxZInstance.get_zindex()) ) ) { maxZInstance = objectInstances[i]; } } var maxZInstanceBehavior = getThisBehavior(maxZInstance,this); if(maxZInstanceBehavior.OnTouchStart){ maxZInstanceBehavior.OnTouchStart(); } objectInstances.length = 0; };*/ var dispatchTouchStart = function(touchX, touchY) { var instances = this.my_instances.valuesRef(); var instance; var instanceBehavior; var lx, ly; for (var i=0,l=instances.length; i= 0) { var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset(); var t = this.touches[i]; if (nowtime - t.time < 2) return; t.update(nowtime, info.pageX - offset.left, info.pageY - offset.top, info.width || 0, info.height || 0, info.pressure || 0); var touchx = info.pageX - offset.left; var touchy = info.pageY - offset.top; /*var cnt=this._callbackObjs.length, hooki; for (hooki=0; hooki= 0 ? this.touches[i].startindex : -1); this.trigger_id = (i >= 0 ? this.touches[i]["id"] : -1); this.runtime.isInUserInputEvent = true; if (i >= 0) { this.lastTouchX = this.touches[i].x; this.lastTouchY = this.touches[i].y; } var cnt=this._callbackObjs["touch"].length, hooki; for (hooki=0; hooki= 0) { if (!isCancel) this.touches[i].maybeTriggerTap(this, i); ReleaseTouchInfo(this.touches[i]); this.touches.splice(i, 1); } this.runtime.isInUserInputEvent = false; }; instanceProto.onTouchMove = function (info) { if (!this.enable) return; if (info.preventDefault) info.preventDefault(); var nowtime = cr.performance_now(); var i, len, t, u; var cnt=this._callbackObjs["touch"].length, hooki; for (i = 0, len = info.changedTouches.length; i < len; i++) { t = info.changedTouches[i]; var j = this.findTouch(t["identifier"]); if (j >= 0) { var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset(); u = this.touches[j]; if (nowtime - u.time < 2) continue; var touchWidth = (t.radiusX || t.webkitRadiusX || t.mozRadiusX || t.msRadiusX || 0) * 2; var touchHeight = (t.radiusY || t.webkitRadiusY || t.mozRadiusY || t.msRadiusY || 0) * 2; var touchForce = t.force || t.webkitForce || t.mozForce || t.msForce || 0; u.update(nowtime, t.pageX - offset.left, t.pageY - offset.top, touchWidth, touchHeight, touchForce); var touchx = t.pageX - offset.left; var touchy = t.pageY - offset.top; /*for (hooki=0; hooki= 0) { this.trigger_index = this.touches[j].startindex; this.trigger_id = this.touches[j]["id"]; this.lastTouchX = this.touches[j].x; this.lastTouchY = this.touches[j].y; for (hooki=0; hooki= this.touches.length) { result = 0; return result; } var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; result = layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) result = layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true); else result = 0; } return result; }; instanceProto.XAt = function (ret, index, layerparam) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, true)); else ret.set_float(0); } }; instanceProto.XForID = function (ret, id, layerparam) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(touch.x, touch.y, true)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(touch.x, touch.y, true)); else ret.set_float(0); } }; instanceProto.Y = function (layerparam) { var index = this.getTouchIndex; var result; if (index < 0 || index >= this.touches.length) { result = 0; return; } var layer, oldScale, oldZoomRate, oldParallaxY, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxY = layer.parallaxY; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxY = 1.0; layer.angle = 0; result = layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxY = oldParallaxY; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) result = layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false); else result = 0; } return result; }; instanceProto.YAt = function (ret, index, layerparam) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } var layer, oldScale, oldZoomRate, oldParallaxY, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxY = layer.parallaxY; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxY = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxY = oldParallaxY; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(this.touches[index].x, this.touches[index].y, false)); else ret.set_float(0); } }; instanceProto.YForID = function (ret, id, layerparam) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; var layer, oldScale, oldZoomRate, oldParallaxY, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxY = layer.parallaxY; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxY = 1.0; layer.angle = 0; ret.set_float(layer.canvasToLayer(touch.x, touch.y, false)); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxY = oldParallaxY; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) ret.set_float(layer.canvasToLayer(touch.x, touch.y, false)); else ret.set_float(0); } }; instanceProto.AbsoluteX = function (ret) { if (this.touches.length) ret.set_float(this.touches[0].x); else ret.set_float(0); }; instanceProto.AbsoluteXAt = function (ret, index) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } ret.set_float(this.touches[index].x); }; instanceProto.AbsoluteXForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(touch.x); }; instanceProto.AbsoluteY = function (ret) { if (this.touches.length) ret.set_float(this.touches[0].y); else ret.set_float(0); }; instanceProto.AbsoluteYAt = function (ret, index) { index = Math.floor(index); if (index < 0 || index >= this.touches.length) { ret.set_float(0); return; } ret.set_float(this.touches[index].y); }; instanceProto.AbsoluteYForID = function (ret, id) { var index = this.findTouch(id); if (index < 0) { ret.set_float(0); return; } var touch = this.touches[index]; ret.set_float(touch.y); }; instanceProto.IsInTouch = function () { return (this.touches.length > 0); }; instanceProto.CursorX = function (layerparam) { if (this.cursor.x == null) return null; var x; var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; x = layer.canvasToLayer(this.cursor.x, this.cursor.y, true); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) x = layer.canvasToLayer(this.cursor.x, this.cursor.y, true); else x = 0; } return x; }; instanceProto.CursorY = function (layerparam) { if (this.cursor.y == null) return null; var y; var layer, oldScale, oldZoomRate, oldParallaxX, oldAngle; if (cr.is_undefined(layerparam)) { layer = this.runtime.getLayerByNumber(0); oldScale = layer.scale; oldZoomRate = layer.zoomRate; oldParallaxX = layer.parallaxX; oldAngle = layer.angle; layer.scale = 1; layer.zoomRate = 1.0; layer.parallaxX = 1.0; layer.angle = 0; y = layer.canvasToLayer(this.cursor.x, this.cursor.y, false); layer.scale = oldScale; layer.zoomRate = oldZoomRate; layer.parallaxX = oldParallaxX; layer.angle = oldAngle; } else { if (cr.is_number(layerparam)) layer = this.runtime.getLayerByNumber(layerparam); else layer = this.runtime.getLayerByName(layerparam); if (layer) y = layer.canvasToLayer(this.cursor.x, this.cursor.y, false); else y = 0; } return y; }; instanceProto.CursorAbsoluteX = function () { return this.cursor.x; }; instanceProto.CursorAbsoluteY = function () { return this.cursor.y; }; }()); ; ; cr.plugins_.rex_bbcodeText = function(runtime) { this.runtime = runtime; }; (function () { var pluginProto = cr.plugins_.rex_bbcodeText.prototype; pluginProto.onCreate = function () { pluginProto.acts.SetWidth = function (w) { if (this.width !== w) { this.width = w; this.set_bbox_changed(); if (!this.isCanvasSizeLocked) this.render_text(this.is_force_render); } }; }; pluginProto.Type = function(plugin) { this.plugin = plugin; this.runtime = plugin.runtime; }; var typeProto = pluginProto.Type.prototype; typeProto.onCreate = function() { }; typeProto.onLostWebGLContext = function () { if (this.is_family) return; var i, len, inst; for (i = 0, len = this.instances.length; i < len; i++) { inst = this.instances[i]; inst.mycanvas = null; inst.myctx = null; inst.mytex = null; } }; pluginProto.Instance = function(type) { this.type = type; this.runtime = type.runtime; this.text_changed = true; }; var instanceProto = pluginProto.Instance.prototype; var requestedWebFonts = {}; // already requested web fonts have an entry here var lineJoinMode = ["miter", "round", "bevel"]; instanceProto.onCreate = function() { this.text = ""; this.set_text(this.properties[0]); this.visible = (this.properties[1] === 0); // 0=visible, 1=invisible this.font = this.properties[2]; this.color = this.properties[3]; this.halign = this.properties[4]; // 0=left, 1=center, 2=right this.valign = this.properties[5]; // 0=top, 1=center, 2=bottom this.textShadow = ""; this.wrapbyword = (this.properties[7] === 0); // 0=word, 1=character this.lastwidth = this.width; this.lastwrapwidth = this.width; this.lastheight = this.height; this.line_height_offset = this.properties[8]; this.baseLine_mode = this.properties[9]; this.vshift = this.properties[10]; this.is_force_render = (this.properties[11] === 1); this.LockCanvasSize( (this.properties[12] === 1), this.width, this.height); this.facename = ""; this.fontstyle = ""; this.ptSize = 0; this.textWidth = 0; this.textHeight = 0; this.parseFont(); this.mycanvas = null; this.myctx = null; this.mytex = null; this.need_text_redraw = false; this.last_render_tick = this.runtime.tickcount; if (this.recycled) this.rcTex.set(0, 0, 1, 1); else this.rcTex = new cr.rect(0, 0, 1, 1); if (this.runtime.glwrap) this.runtime.tickMe(this); ; this._tag = null; if (!this.recycled) { this.canvas_text = new CanvasText(); } this.canvas_text.Reset(this); this.canvas_text.textBaseline = (this.baseLine_mode === 0)? "alphabetic":"top"; this.canvas_text.stroke.lineWidth = this.properties[13]; this.canvas_text.stroke.lineJoin = lineJoinMode[this.properties[14]]; this.canvas_text.underline.thickness = this.properties[15]; this.canvas_text.underline.offset = this.properties[16]; this.setShadow(this.properties[17], this.properties[18], this.properties[19], this.properties[20]); this.canvas_text.backgroundColor = this.properties[21]; if (this.text) this.render_text(this.is_force_render); }; instanceProto.parseFont = function () { var arr = this.font.split(" "); var i; for (i = 0; i < arr.length; i++) { if (arr[i].substr(arr[i].length - 2, 2) === "pt") { this.ptSize = parseInt(arr[i].substr(0, arr[i].length - 2)); this.pxHeight = Math.ceil((this.ptSize / 72.0) * 96.0) + 4; // assume 96dpi... if (i > 0) this.fontstyle = arr[i - 1]; this.facename = arr[i + 1]; for (i = i + 2; i < arr.length; i++) this.facename += " " + arr[i]; break; } } }; instanceProto.saveToJSON = function () { return { "t": this.text, "f": this.font, "c": this.color, "ha": this.halign, "va": this.valign, "wr": this.wrapbyword, "lho": this.line_height_offset, "vs": this.vshift, "fn": this.facename, "fs": this.fontstyle, "ps": this.ptSize, "pxh": this.pxHeight, "tw": this.textWidth, "th": this.textHeight, "ts": this.textShadow, "lrt": this.last_render_tick, "bl": this.canvas_text.textBaseline, "txtObj": this.canvas_text.saveToJSON(), "isLcs": this.isCanvasSizeLocked, "lcw": this.lockedCanvasWidth, "lch": this.lockedCanvasHeight }; }; instanceProto.loadFromJSON = function (o) { this.text = o["t"]; this.font = o["f"]; this.color = o["c"]; this.halign = o["ha"]; this.valign = o["va"]; this.wrapbyword = o["wr"]; this.line_height_offset = o["lho"]; this.vshift = o["vs"]; this.facename = o["fn"]; this.fontstyle = o["fs"]; this.ptSize = o["ps"]; this.pxHeight = o["pxh"]; this.textWidth = o["tw"]; this.textHeight = o["th"]; this.textShadow = o["ts"]; this.last_render_tick = o["lrt"]; this.text_changed = true; this.lastwidth = this.width; this.lastwrapwidth = this.width; this.lastheight = this.height; this.canvas_text.textBaseline = o["bl"]; this.canvas_text.loadFromJSON(o["txtObj"]); this.isCanvasSizeLocked = o["isLcs"]; this.lockedCanvasWidth = o["lcw"]; this.lockedCanvasHeight = o["lch"]; }; instanceProto.tick = function () { if (this.runtime.glwrap && this.mytex && (this.runtime.tickcount - this.last_render_tick >= 300)) { var layer = this.layer; this.update_bbox(); var bbox = this.bbox; if (bbox.right < layer.viewLeft || bbox.bottom < layer.viewTop || bbox.left > layer.viewRight || bbox.top > layer.viewBottom) { this.runtime.glwrap.deleteTexture(this.mytex); this.mytex = null; this.myctx = null; this.mycanvas = null; } } }; instanceProto.onDestroy = function () { this.myctx = null; this.mycanvas = null; if (this.runtime.glwrap && this.mytex) this.runtime.glwrap.deleteTexture(this.mytex); this.mytex = null; }; instanceProto.updateFont = function () { this.font = this.fontstyle + " " + this.ptSize.toString() + "pt " + this.facename; this.render_text(this.is_force_render); }; instanceProto.draw = function(ctx, glmode, is_ignore) { var isCtxSave = false; var width = (this.isCanvasSizeLocked)? this.lockedCanvasWidth : this.width; var height = (this.isCanvasSizeLocked)? this.lockedCanvasHeight : this.height; ctx.globalAlpha = glmode ? 1 : this.opacity; var myscale = 1; if (glmode) { myscale = this.layer.getScale(); if (!isCtxSave) { ctx.save(); isCtxSave = true; } ctx.scale(myscale, myscale); } if (this.text_changed || width !== this.lastwrapwidth) { this.canvas_text.text_changed = true; // it will update pens (wordwrap) to redraw this.text_changed = false; this.lastwrapwidth = width; } this.update_bbox(); var penX = glmode ? 0 : this.bquad.tlx; var penY = glmode ? 0 : this.bquad.tly; if (this.runtime.pixel_rounding) { penX = (penX + 0.5) | 0; penY = (penY + 0.5) | 0; } if (!glmode) { var isResized = (width !== this.width) || (height !== this.height); var isRotated = (this.angle !== 0 ); if ( isRotated || isResized ) { if (!isCtxSave) { ctx.save(); isCtxSave = true; } if (isResized) { var scalew = this.width/width; var scaleh = this.height/height; ctx.scale(scalew, scaleh); ctx.translate(penX/scalew, penY/scaleh); penX = 0; penY = 0; } if (isRotated) { if ((penX !== 0) || (penY !== 0)) ctx.translate(penX, penY); ctx.rotate(this.angle); } } } var line_height = this.pxHeight; line_height += (this.line_height_offset * this.runtime.devicePixelRatio); this.canvas_text.canvas = ctx.canvas; this.canvas_text.context = ctx; this.canvas_text.default_propScope.family = this.facename; this.canvas_text.default_propScope.ptSize = this.ptSize.toString() + "pt"; this.canvas_text.default_propScope.style = this.fontstyle; this.canvas_text.default_propScope.color = this.color; this.canvas_text.default_propScope.shadow = this.textShadow; this.canvas_text.lineHeight = line_height; this.canvas_text.textInfo["text"] = this.text; this.canvas_text.textInfo["x"] = penX; this.canvas_text.textInfo["y"] = penY; this.canvas_text.textInfo["boxWidth"] = width; this.canvas_text.textInfo["boxHeight"] = height; this.canvas_text.textInfo["ignore"] = is_ignore; this.canvas_text.drawText(); if (isCtxSave) ctx.restore(); this.last_render_tick = this.runtime.tickcount; }; instanceProto.drawGL = function(glw) { if (this.width < 1 || this.height < 1) return; var need_redraw = this.text_changed || this.need_text_redraw; this.need_text_redraw = false; var layer_scale = this.layer.getScale(); var layer_angle = this.layer.getAngle(); var rcTex = this.rcTex; var floatscaledwidth = layer_scale * this.width; var floatscaledheight = layer_scale * this.height; var scaledwidth = Math.ceil(floatscaledwidth); var scaledheight = Math.ceil(floatscaledheight); var halfw = this.runtime.draw_width / 2; var halfh = this.runtime.draw_height / 2; var canvaswidth = (!this.isCanvasSizeLocked)? scaledwidth : Math.ceil(layer_scale * this.lockedCanvasWidth); var canvasheight = (!this.isCanvasSizeLocked)? scaledheight: Math.ceil(layer_scale * this.lockedCanvasHeight); if (!this.myctx) { this.mycanvas = document.createElement("canvas"); this.mycanvas.width = canvaswidth; this.mycanvas.height = canvasheight; this.lastwidth = canvaswidth; this.lastheight = canvasheight; need_redraw = true; this.myctx = this.mycanvas.getContext("2d"); } if (canvaswidth !== this.lastwidth || canvasheight !== this.lastheight) { this.mycanvas.width = canvaswidth; this.mycanvas.height = canvasheight; if (this.mytex) { glw.deleteTexture(this.mytex); this.mytex = null; } need_redraw = true; } if (need_redraw) { this.myctx.clearRect(0, 0, canvaswidth, canvasheight); this.draw(this.myctx, true); if (!this.mytex) this.mytex = glw.createEmptyTexture(scaledwidth, scaledheight, this.runtime.linearSampling, this.runtime.isMobile); glw.videoToTexture(this.mycanvas, this.mytex, this.runtime.isMobile); } this.lastwidth = canvaswidth; this.lastheight = canvasheight; glw.setTexture(this.mytex); glw.setOpacity(this.opacity); glw.resetModelView(); glw.translate(-halfw, -halfh); glw.updateModelView(); var q = this.bquad; var tlx = this.layer.layerToCanvas(q.tlx, q.tly, true, true); var tly = this.layer.layerToCanvas(q.tlx, q.tly, false, true); var trx = this.layer.layerToCanvas(q.trx, q.try_, true, true); var try_ = this.layer.layerToCanvas(q.trx, q.try_, false, true); var brx = this.layer.layerToCanvas(q.brx, q.bry, true, true); var bry = this.layer.layerToCanvas(q.brx, q.bry, false, true); var blx = this.layer.layerToCanvas(q.blx, q.bly, true, true); var bly = this.layer.layerToCanvas(q.blx, q.bly, false, true); if (this.runtime.pixel_rounding || (this.angle === 0 && layer_angle === 0)) { var ox = ((tlx + 0.5) | 0) - tlx; var oy = ((tly + 0.5) | 0) - tly tlx += ox; tly += oy; trx += ox; try_ += oy; brx += ox; bry += oy; blx += ox; bly += oy; } if (this.angle === 0 && layer_angle === 0) { trx = tlx + scaledwidth; try_ = tly; brx = trx; bry = tly + scaledheight; blx = tlx; bly = bry; rcTex.right = 1; rcTex.bottom = 1; } else { rcTex.right = floatscaledwidth / scaledwidth; rcTex.bottom = floatscaledheight / scaledheight; } glw.quadTex(tlx, tly, trx, try_, brx, bry, blx, bly, rcTex); glw.resetModelView(); glw.scale(layer_scale, layer_scale); glw.rotateZ(-this.layer.getAngle()); glw.translate((this.layer.viewLeft + this.layer.viewRight) / -2, (this.layer.viewTop + this.layer.viewBottom) / -2); glw.updateModelView(); this.last_render_tick = this.runtime.tickcount; }; instanceProto._get_webgl_ctx = function () { var inst = this; var ctx = inst.myctx; if (!ctx) { inst.mycanvas = document.createElement("canvas"); var scaledwidth = Math.ceil(inst.layer.getScale()*inst.width); var scaledheight = Math.ceil(inst.layer.getAngle()*inst.height); inst.mycanvas.width = scaledwidth; inst.mycanvas.height = scaledheight; inst.lastwidth = scaledwidth; inst.lastheight = scaledheight; inst.myctx = inst.mycanvas.getContext("2d"); ctx = inst.myctx; } return ctx; }; instanceProto.fake_render = function () { var inst = this; var ctx = (this.runtime.enableWebGL)? this._get_webgl_ctx():this.runtime.ctx; inst.draw(ctx, null, true); }; instanceProto.render_text = function (is_render_now) { if (is_render_now) { this.text_changed = true; this.fake_render(); } this.text_changed = true; this.runtime.redraw = true; }; instanceProto.set_text = function (txt) { if (this.text !== txt) { this.text = txt; this.render_text(this.is_force_render); } }; instanceProto.setShadow = function(offsetX, offsetY, blur_, color_) { color_ = color_.replace(/ /g,''); var shadow = offsetX.toString() + "px " + offsetY.toString() + "px " + blur_.toString() + "px " + color_; this.textShadow = shadow; }; instanceProto.LockCanvasSize = function(isLocked, width, height) { this.isCanvasSizeLocked = isLocked; this.lockedCanvasWidth = width; this.lockedCanvasHeight = height; }; var copy_dict = function (in_obj, out_obj, is_merge) { if (out_obj == null) out_obj = {}; if (!is_merge) { for (var k in out_obj) { if (!in_obj.hasOwnProperty(k)) delete out_obj[k]; } } for (var k in in_obj) out_obj[k] = in_obj[k]; return out_obj; }; instanceProto.getRawText = function (text) { return this.canvas_text.getRawText(text); }; instanceProto.getSubText = function (start, end, text) { return this.canvas_text.getSubText(start, end, text); }; instanceProto.copyPensMgr = function (pensMgr) { return this.canvas_text.copyPensMgr(pensMgr); }; function Cnds() {}; pluginProto.cnds = new Cnds(); Cnds.prototype.CompareText = function(text_to_compare, case_sensitive) { if (case_sensitive) return this.text == text_to_compare; else return cr.equals_nocase(this.text, text_to_compare); }; function Acts() {}; pluginProto.acts = new Acts(); Acts.prototype.SetText = function(param) { if (cr.is_number(param) && param < 1e9) param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors var text_to_set = param.toString(); this.set_text(text_to_set); }; Acts.prototype.AppendText = function(param) { if (cr.is_number(param)) param = Math.round(param * 1e10) / 1e10; // round to nearest ten billionth - hides floating point errors var text_to_append = param.toString(); if (text_to_append.length > 0) // not empty this.set_text(this.text+text_to_append); }; Acts.prototype.SetFontFace = function (face_, style_) { var newstyle = ""; switch (style_) { case 1: newstyle = "bold"; break; case 2: newstyle = "italic"; break; case 3: newstyle = "bold italic"; break; } if (face_ === this.facename && newstyle === this.fontstyle) return; // no change this.facename = face_; this.fontstyle = newstyle; this.updateFont(); }; Acts.prototype.SetFontSize = function (size_) { if (this.ptSize === size_) return; this.ptSize = size_; this.pxHeight = Math.ceil((this.ptSize / 72.0) * 96.0) + 4; // assume 96dpi... this.updateFont(); }; Acts.prototype.SetFontColor = function (rgb) { var newcolor; if (typeof(rgb) == "number") newcolor = "rgb(" + cr.GetRValue(rgb).toString() + "," + cr.GetGValue(rgb).toString() + "," + cr.GetBValue(rgb).toString() + ")"; else newcolor = rgb; if (newcolor === this.color) return; this.color = newcolor; this.render_text(this.is_force_render); }; Acts.prototype.SetWebFont = function (familyname_, cssurl_) { if (this.runtime.isDomFree) { cr.logexport("[Construct 2] Text plugin: 'Set web font' not supported on this platform - the action has been ignored"); return; // DC todo } var self = this; var refreshFunc = (function () { self.runtime.redraw = true; self.text_changed = true; }); var newfacename = "'" + familyname_ + "'"; if (requestedWebFonts.hasOwnProperty(cssurl_)) { if (this.facename === newfacename) return; // no change this.facename = newfacename; this.updateFont(); for (var i = 1; i < 10; i++) { setTimeout(refreshFunc, i * 100); setTimeout(refreshFunc, i * 1000); } return; } var wf = document.createElement("link"); wf.href = cssurl_; wf.rel = "stylesheet"; wf.type = "text/css"; wf.onload = refreshFunc; document.getElementsByTagName('head')[0].appendChild(wf); requestedWebFonts[cssurl_] = true; this.facename = "'" + familyname_ + "'"; this.updateFont(); for (var i = 1; i < 10; i++) { setTimeout(refreshFunc, i * 100); setTimeout(refreshFunc, i * 1000); } ; }; Acts.prototype.SetEffect = function (effect) { this.compositeOp = cr.effectToCompositeOp(effect); cr.setGLBlend(this, effect, this.runtime.gl); this.render_text(this.is_force_render); }; Acts.prototype.SetFontStyle = function (style_) { var newstyle = ""; switch (style_) { case 1: newstyle = "bold"; break; case 2: newstyle = "italic"; break; case 3: newstyle = "bold italic"; break; } if (newstyle === this.fontstyle) return; // no change this.fontstyle = newstyle; this.updateFont(); }; Acts.prototype.SetFontFace2 = function (face_) { if (face_ === this.facename) return; // no change this.facename = face_; this.updateFont(); }; Acts.prototype.SetLineHeight = function(line_height_offset) { if (this.line_height_offset === line_height_offset) return; this.line_height_offset = line_height_offset; this.render_text(this.is_force_render); }; Acts.prototype.SetHorizontalAlignment = function(align) { if (this.halign === align) return; this.halign = align; // 0=left, 1=center, 2=right this.render_text(this.is_force_render); }; Acts.prototype.SetVerticalAlignment = function(align) { if (this.valign === align) return; this.valign = align; // 0=top, 1=center, 2=bottom this.render_text(this.is_force_render); }; Acts.prototype.SetWrapping = function(wrap_mode) { wrap_mode = (wrap_mode === 0); // 0=word, 1=character if (this.wrapbyword === wrap_mode) return; this.wrapbyword = wrap_mode; this.render_text(this.is_force_render); }; Acts.prototype.SetShadow = function(offsetX, offsetY, blur_, color_) { this.setShadow(offsetX, offsetY, blur_, color_); this.render_text(this.is_force_render); }; Acts.prototype.SetThickness = function(w) { if (w === this.canvas_text.underline.thickness) return; this.canvas_text.underline.thickness = w; this.need_text_redraw = true; this.runtime.redraw = true; }; Acts.prototype.SetOffsetY = function(offset) { if (offset === this.canvas_text.underline.offset) return; this.canvas_text.underline.offset = offset; this.need_text_redraw = true; this.runtime.redraw = true; }; Acts.prototype.SetStrokeLineWidth = function(w) { if (w === this.canvas_text.stroke.lineWidth) return; this.canvas_text.stroke.lineWidth = w; this.need_text_redraw = true; this.runtime.redraw = true; }; Acts.prototype.SetStrokeLineJoin = function(m) { m = lineJoinMode[m]; if (m === this.canvas_text.stroke.lineJoin) return; this.canvas_text.stroke.lineJoin = m; this.need_text_redraw = true; this.runtime.redraw = true; }; Acts.prototype.SetBackgroundColor = function(color) { if (color === this.canvas_text.backgroundColor) return; this.canvas_text.backgroundColor = color; this.need_text_redraw = true; this.runtime.redraw = true; }; Acts.prototype.LockCanvasSize = function(width, height) { this.LockCanvasSize(true, width, height); }; Acts.prototype.UnLockCanvasSize = function() { this.LockCanvasSize(false); }; Acts.prototype.AddImage = function (key, objs, yoffset) { if (!objs) return; window.RexImageBank.AddImage(key, objs.getFirstPicked(), yoffset); this.render_text(this.is_force_render); }; Acts.prototype.RemoveImage = function (key) { window.RexImageBank.RemoveImage(key); this.render_text(this.is_force_render); }; Acts.prototype.RemoveAll = function () { window.RexImageBank.RemoveAll(); this.render_text(this.is_force_render); }; function Exps() {}; pluginProto.exps = new Exps(); Exps.prototype.Text = function(ret, start, end) { var txt; if ((start == null) && (end == null)) txt = this.text; else txt = this.getSubText(start, end); ret.set_string(txt); }; Exps.prototype.FaceName = function (ret) { ret.set_string(this.facename); }; Exps.prototype.FaceSize = function (ret) { ret.set_int(this.ptSize); }; Exps.prototype.TextWidth = function (ret) { ret.set_int(this.canvas_text.getTextWidth()); }; Exps.prototype.TextHeight = function (ret) { var total_line_count = this.canvas_text.getLines().length; var text_height = total_line_count * (this.pxHeight + this.line_height_offset) - this.line_height_offset; if (this.baseLine_mode === 0) // alphabetic text_height += this.vshift; ret.set_float(text_height); }; Exps.prototype.RawText = function(ret) { ret.set_string(this.canvas_text.getRawText()); }; Exps.prototype.LastClassPropValue = function(ret, name, default_value) { var val; var last_pen = this.canvas_text.getLastPen(); if (last_pen) val = last_pen.prop[name]; if (!val) val = default_value || 0; ret.set_any(val); }; var ObjCacheKlass = function () { this.lines = []; }; var ObjCacheKlassProto = ObjCacheKlass.prototype; ObjCacheKlassProto.allocLine = function() { return (this.lines.length > 0)? this.lines.pop(): null; }; ObjCacheKlassProto.freeLine = function (l) { this.lines.push(l); }; ObjCacheKlassProto.freeAllLines= function (arr) { var i, len; for (i = 0, len = arr.length; i < len; i++) this.freeLine(arr[i]); arr.length = 0; }; var CanvasText = function () { this.canvas = null; this.context = null; this.savedClasses = {}; // class define this.textInfo = { "text":"", "x":0, "y":0, "boxWidth":0, "boxHeight":0, "ignore":null, }; this.pensMgr = new PensMgrKlass(); this.text_changed = true; // update this.pens to redraw /* * Default values, overwrite before draw by plugin */ this.default_propScope = { family:"Verdana", weight:"", ptSize:"12pt", color:"#000000", style:"normal", shadow:"", }; this.stroke = {lineWidth: 1, lineJoin: "miter"}; this.underline = {thickness: 1, offset:0}; this.textAlign = "start"; this.lineHeight = "16"; this.textBaseline = "alphabetic"; this.backgroundColor = ""; }; var CanvasTextProto = CanvasText.prototype; CanvasTextProto.Reset = function(plugin) { this.plugin = plugin; }; CanvasTextProto.getLines = function() { return this.pensMgr.getLines(); }; CanvasTextProto.apply_propScope = function (propScope) { if (this.isTextMode(propScope)) { var style; if (propScope.hasOwnProperty("b") || propScope.hasOwnProperty("i")) { if (propScope["b"] && propScope["i"]) style = "bold italic"; else if (propScope["b"]) style = "bold"; else if (propScope["i"]) style = "italic"; } else { style = this.default_propScope.weight; } var weight = propScope["weight"] || this.default_propScope.weight; var ptSize = this.getTextSize(propScope); var family = propScope["family"] || this.default_propScope.family; this.context.font = style + " " + weight + " " + ptSize + " " + family; var color = this.getFillColor(propScope); if (color.toLowerCase() !== "none") this.context.fillStyle = color; var stroke = this.getStokeColor(propScope); if (stroke.toLowerCase() !== "none") { this.context.strokeStyle = stroke; this.context.lineWidth = this.stroke.lineWidth; this.context.lineJoin = this.stroke.lineJoin; this.context.miterLimit = 2; } } var shadow = (propScope["shadow"])? this.default_propScope.shadow : ""; if (shadow !== "") { shadow = shadow.split(" "); this.context.shadowOffsetX = parseFloat(shadow[0].replace("px", "")); this.context.shadowOffsetY = parseFloat(shadow[1].replace("px", "")); this.context.shadowBlur = parseFloat(shadow[2].replace("px", "")); this.context.shadowColor = shadow[3]; } }; CanvasTextProto.isTextMode = function(propScope) { var isImageMode = propScope.hasOwnProperty("img"); return !isImageMode; }; CanvasTextProto.getTextSize = function(propScope) { var size; if (propScope.hasOwnProperty("size")) size = propScope["size"]; else size = this.default_propScope.ptSize; return size; }; CanvasTextProto.getFillColor = function(propScope) { var color; if (propScope.hasOwnProperty("color")) color = propScope["color"]; else color = this.default_propScope.color; return color; }; CanvasTextProto.getStokeColor = function(propScope) { var color; if (propScope.hasOwnProperty("stroke")) color = propScope["stroke"]; else color = "none"; return color; }; CanvasTextProto.draw_pen = function (pen, offset_x, offset_y) { var ctx = this.context; ctx.save(); this.apply_propScope(pen.prop); var startX = offset_x + pen.x; var startY = offset_y + pen.y; var underline = pen.prop["u"]; if (underline) { var color = (underline === true)? this.getFillColor(pen.prop) : underline; this.draw_underline(pen.text, startX, startY, this.getTextSize(pen.prop), color ); } if (pen.prop.hasOwnProperty("img")) { var img = window.RexImageBank.GetImage(pen.prop["img"]); if (img) { var y = startY+img.yoffset; if (this.textBaseline == "alphabetic") { y -= this.lineHeight; } ctx.drawImage(img.img, startX, y, img.width, img.height); } } else { if (this.getStokeColor(pen.prop).toLowerCase() !== "none") ctx.strokeText(pen.text, startX, startY); if (this.getFillColor(pen.prop).toLowerCase() !== "none") ctx.fillText(pen.text, startX, startY); } ctx.restore(); }; CanvasTextProto.draw_underline = function (text, x, y, size, color) { var ctx = this.context; var width = ctx.measureText(text).width; y += this.underline.offset; if (this.textBaseline === "top") y += parseInt(size); ctx.beginPath(); ctx.strokeStyle = color; ctx.lineWidth = this.underline.thickness; ctx.moveTo(x,y); ctx.lineTo(x+width,y); ctx.stroke(); }; CanvasTextProto.preProcess = function() { if (this.backgroundColor !== "") { var ctx = this.context; ctx.fillStyle = this.backgroundColor; ctx.fillRect(0, 0, this.textInfo["boxWidth"], this.textInfo["boxHeight"]); } }; CanvasTextProto.drawPens = function (pensMgr, textInfo) { var boxWidth=textInfo["boxWidth"], boxHeight=textInfo["boxHeight"]; var start_x = textInfo["x"], start_y = textInfo["y"]; var lines=pensMgr.getLines(), lcnt=lines.length; var offset_x, offset_y; if (this.plugin.valign === 1) // center offset_y = Math.max( (boxHeight - (lcnt * this.lineHeight)) / 2, 0); else if (this.plugin.valign === 2) // bottom offset_y = Math.max(boxHeight - (lcnt * this.lineHeight) - 2, 0); else offset_y = 0; offset_y += start_y; if (this.textBaseline == "alphabetic") offset_y += (this.plugin.vshift * this.plugin.runtime.devicePixelRatio); // shift line down var li, line_width; var pi, pcnt, pens, pen; for (li=0; li boxWidth - (cursor_x-start_x) ) { cursor_x = start_x; cursor_y += this.lineHeight; } pensMgr.addPen(null, // text cursor_x, // x cursor_y, // y img.width, // width __curr_propScope, // prop 0 // new_line_mode ); cursor_x += img.width; } else { pensMgr.addPen(null, // text null, // x null, // y null, // width __curr_propScope, // prop 0 // new_line_mode ); } update_propScope(__curr_propScope, PROP_REMOVE, "img"); continue; } else if (__re_image_close.test(m)) { update_propScope(__curr_propScope, PROP_REMOVE, "img"); continue; } else { proText = m; if (!ignore_wrap) { this.context.save(); this.apply_propScope(__curr_propScope); var wrap_lines = wordWrap(proText, this.context, boxWidth, this.plugin.wrapbyword, cursor_x-start_x ); var lcnt=wrap_lines.length, n, wrap_line; for (n=0; n= lines.length) lines.push(lineCache.newline(cur_line, ctx.measureText(cur_line).width, RAW_NEWLINE)); lineIndex++; cur_line = ""; offset_x = 0; continue; } prev_line = cur_line; cur_line += wordArray[i]; line_width = ctx.measureText(cur_line).width; if (line_width >= (width - offset_x)) { if (lineIndex >= lines.length) lines.push(lineCache.newline(prev_line, ctx.measureText(prev_line).width, WRAPPED_NEWLINE)); lineIndex++; cur_line = wordArray[i]; if (!wrapbyword && cur_line === " ") cur_line = ""; offset_x = 0; } } if (cur_line.length) { if (lineIndex >= lines.length) lines.push(lineCache.newline(cur_line, ctx.measureText(cur_line).width, NO_NEWLINE)); lineIndex++; } for (i = lineIndex; i < lines.length; i++) lineCache.freeLine(lines[i]); lines.length = lineIndex; return lines; }; var __wordsCache = []; var TokeniseWords = function (text) { __wordsCache.length = 0; var cur_word = ""; var ch; var i = 0; while (i < text.length) { ch = text.charAt(i); if (ch === "\n") { if (cur_word.length) { __wordsCache.push(cur_word); cur_word = ""; } __wordsCache.push("\n"); ++i; } else if (ch === " " || ch === "\t" || ch === "-") { do { cur_word += text.charAt(i); i++; } while (i < text.length && (text.charAt(i) === " " || text.charAt(i) === "\t")); __wordsCache.push(cur_word); cur_word = ""; } else if (i < text.length) { cur_word += ch; i++; } } if (cur_word.length) __wordsCache.push(cur_word); return __wordsCache; }; var __penMgr_penCache = new ObjCacheKlass(); var __penMgr_lineCache =new ObjCacheKlass(); var PensMgrKlass = function () { this.pens = []; // all pens this.lines= []; // pens in lines [ [],[],[],.. ] }; var PensMgrKlassProto = PensMgrKlass.prototype; PensMgrKlassProto.freePens = function () { var li, lcnt=this.lines.length; for(li=0; li=0; li--) { line = this.lines[li]; has_last_pen = (line != null) && (line.length>0); if (has_last_pen) break; } if (!has_last_pen) return 0; var last_pen = line[line.length-1]; return last_pen.getEndIndex(); }; PensMgrKlassProto.copy = function (targetPensMgr) { if (targetPensMgr == null) targetPensMgr = new PensMgrKlass(); targetPensMgr.freePens(); var li, lcnt=this.lines.length; var pens, pi, pcnt, pen; for (li=0; li maxW) maxW = w; } return maxW; }; PensMgrKlassProto.getRawText = function () { var txt="", i, cnt=this.pens.length, pen; for(i=0; i= start) && (pen_ei < end); if (!in_range) { pen_txt = pen_txt.substring(start-pen_si, end-pen_si); } txt += prop2TagText(pen_txt, pen.prop, pre_prop); pre_prop = pen.prop; if (pen_ei >= end) break; } return txt; }; var __empty_prop = {}; var prop2TagText = function (txt, prop, pre_prop) { if (pre_prop == null) pre_prop = __empty_prop; for (var k in pre_prop) { if (prop.hasOwnProperty(k)) continue; txt = "[/" + k + "]" + txt; } var header = ""; for (var k in prop) { if (pre_prop[k] === prop[k]) continue; if (k === "size") header += ("[size=" + prop[k].replace("pt", "") + "]"); else if ((k === "color") || (k === "stroke") || (k === "img")) header += ("[" + k + "=" + prop[k] + "]"); else if (k === "u") { if (prop[k] === true) header += "[u]"; else header += ("[u=" + prop[k] + "]"); } else header += ("[" + k + "]"); } txt = header + txt; return txt; }; var has_key = function (o) { for (var k in o) return true; return false; } var PenKlass = function () { this.text = null; this.x = null; this.y = null; this.width = null; this.prop = {}; this.newLineMode = null; this.startIndex = null; } var PenKlassProto = PenKlass.prototype; PenKlassProto.setPen = function (txt, x, y, width, prop, new_line_mode, start_index) { this.text = txt; this.x = x; this.y = y; this.width = width; copy_dict(prop, this.prop); // font, size, color, shadow, etc... this.newLineMode = new_line_mode; // 0= no new line, 1=raw "\n", 2=wrapped "\n" this.startIndex = start_index; }; PenKlassProto.getRawText = function () { var txt = this.text || ""; if (this.newLineMode == RAW_NEWLINE) txt += "\n"; return txt; } PenKlassProto.getNextStartIndex = function() { return this.startIndex + this.getRawText().length; }; PenKlassProto.getEndIndex = function() { return this.getNextStartIndex() - 1; }; PenKlassProto.getLastX = function() { return this.x + this.width; }; var ImageBankKlass = function () { this.images = {}; } var ImageBankKlassProto = ImageBankKlass.prototype; ImageBankKlassProto.AddImage = function (name, inst, yoffset_) { var img = getImage(inst) if (!inst) return; this.images[name] = { img: img, width: inst.width, height: inst.height, yoffset: yoffset_ }; }; ImageBankKlassProto.GetImage = function (name, inst) { return this.images[name]; }; ImageBankKlassProto.RemoveImage = function (name) { if (this.images.hasOwnProperty(name)) delete this.images[name]; }; ImageBankKlassProto.RemoveAll = function () { for (var n in this.images) delete this.images[n]; }; var getImage = function (inst) { if (!inst) return null; var img; if (inst.canvas) img = inst.canvas; else if (inst.curFrame && inst.curFrame.texture_img) img = inst.curFrame.texture_img; else img = null; return img; }; window.RexImageBank = new ImageBankKlass(); }()); ; ; cr.behaviors.Anchor = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Anchor.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.anch_left = this.properties[0]; // 0 = left, 1 = right, 2 = none this.anch_top = this.properties[1]; // 0 = top, 1 = bottom, 2 = none this.anch_right = this.properties[2]; // 0 = none, 1 = right this.anch_bottom = this.properties[3]; // 0 = none, 1 = bottom this.inst.update_bbox(); this.xleft = this.inst.bbox.left; this.ytop = this.inst.bbox.top; this.xright = this.runtime.original_width - this.inst.bbox.left; this.ybottom = this.runtime.original_height - this.inst.bbox.top; this.rdiff = this.runtime.original_width - this.inst.bbox.right; this.bdiff = this.runtime.original_height - this.inst.bbox.bottom; this.enabled = (this.properties[4] !== 0); }; behinstProto.saveToJSON = function () { return { "xleft": this.xleft, "ytop": this.ytop, "xright": this.xright, "ybottom": this.ybottom, "rdiff": this.rdiff, "bdiff": this.bdiff, "enabled": this.enabled }; }; behinstProto.loadFromJSON = function (o) { this.xleft = o["xleft"]; this.ytop = o["ytop"]; this.xright = o["xright"]; this.ybottom = o["ybottom"]; this.rdiff = o["rdiff"]; this.bdiff = o["bdiff"]; this.enabled = o["enabled"]; }; behinstProto.tick = function () { if (!this.enabled) return; var n; var layer = this.inst.layer; var inst = this.inst; var bbox = this.inst.bbox; if (this.anch_left === 0) { inst.update_bbox(); n = (layer.viewLeft + this.xleft) - bbox.left; if (n !== 0) { inst.x += n; inst.set_bbox_changed(); } } else if (this.anch_left === 1) { inst.update_bbox(); n = (layer.viewRight - this.xright) - bbox.left; if (n !== 0) { inst.x += n; inst.set_bbox_changed(); } } if (this.anch_top === 0) { inst.update_bbox(); n = (layer.viewTop + this.ytop) - bbox.top; if (n !== 0) { inst.y += n; inst.set_bbox_changed(); } } else if (this.anch_top === 1) { inst.update_bbox(); n = (layer.viewBottom - this.ybottom) - bbox.top; if (n !== 0) { inst.y += n; inst.set_bbox_changed(); } } if (this.anch_right === 1) { inst.update_bbox(); n = (layer.viewRight - this.rdiff) - bbox.right; if (n !== 0) { inst.width += n; if (inst.width < 0) inst.width = 0; inst.set_bbox_changed(); } } if (this.anch_bottom === 1) { inst.update_bbox(); n = (layer.viewBottom - this.bdiff) - bbox.bottom; if (n !== 0) { inst.height += n; if (inst.height < 0) inst.height = 0; inst.set_bbox_changed(); } } }; function Cnds() {}; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetEnabled = function (e) { if (this.enabled && e === 0) this.enabled = false; else if (!this.enabled && e !== 0) { this.inst.update_bbox(); this.xleft = this.inst.bbox.left; this.ytop = this.inst.bbox.top; this.xright = this.runtime.original_width - this.inst.bbox.left; this.ybottom = this.runtime.original_height - this.inst.bbox.top; this.rdiff = this.runtime.original_width - this.inst.bbox.right; this.bdiff = this.runtime.original_height - this.inst.bbox.bottom; this.enabled = true; } }; behaviorProto.acts = new Acts(); function Exps() {}; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.Bullet = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Bullet.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { var speed = this.properties[0]; this.acc = this.properties[1]; this.g = this.properties[2]; this.bounceOffSolid = (this.properties[3] !== 0); this.setAngle = (this.properties[4] !== 0); this.dx = Math.cos(this.inst.angle) * speed; this.dy = Math.sin(this.inst.angle) * speed; this.lastx = this.inst.x; this.lasty = this.inst.y; this.lastKnownAngle = this.inst.angle; this.travelled = 0; this.enabled = (this.properties[5] !== 0); }; behinstProto.saveToJSON = function () { return { "acc": this.acc, "g": this.g, "dx": this.dx, "dy": this.dy, "lx": this.lastx, "ly": this.lasty, "lka": this.lastKnownAngle, "t": this.travelled, "e": this.enabled }; }; behinstProto.loadFromJSON = function (o) { this.acc = o["acc"]; this.g = o["g"]; this.dx = o["dx"]; this.dy = o["dy"]; this.lastx = o["lx"]; this.lasty = o["ly"]; this.lastKnownAngle = o["lka"]; this.travelled = o["t"]; this.enabled = o["e"]; }; behinstProto.tick = function () { if (!this.enabled) return; var dt = this.runtime.getDt(this.inst); var s, a; var bounceSolid, bounceAngle; if (this.inst.angle !== this.lastKnownAngle) { if (this.setAngle) { s = cr.distanceTo(0, 0, this.dx, this.dy); this.dx = Math.cos(this.inst.angle) * s; this.dy = Math.sin(this.inst.angle) * s; } this.lastKnownAngle = this.inst.angle; } if (this.acc !== 0) { s = cr.distanceTo(0, 0, this.dx, this.dy); if (this.dx === 0 && this.dy === 0) a = this.inst.angle; else a = cr.angleTo(0, 0, this.dx, this.dy); s += this.acc * dt; if (s < 0) s = 0; this.dx = Math.cos(a) * s; this.dy = Math.sin(a) * s; } if (this.g !== 0) this.dy += this.g * dt; this.lastx = this.inst.x; this.lasty = this.inst.y; if (this.dx !== 0 || this.dy !== 0) { this.inst.x += this.dx * dt; this.inst.y += this.dy * dt; this.travelled += cr.distanceTo(0, 0, this.dx * dt, this.dy * dt) if (this.setAngle) { this.inst.angle = cr.angleTo(0, 0, this.dx, this.dy); this.inst.set_bbox_changed(); this.lastKnownAngle = this.inst.angle; } this.inst.set_bbox_changed(); if (this.bounceOffSolid) { bounceSolid = this.runtime.testOverlapSolid(this.inst); if (bounceSolid) { this.runtime.registerCollision(this.inst, bounceSolid); s = cr.distanceTo(0, 0, this.dx, this.dy); bounceAngle = this.runtime.calculateSolidBounceAngle(this.inst, this.lastx, this.lasty); this.dx = Math.cos(bounceAngle) * s; this.dy = Math.sin(bounceAngle) * s; this.inst.x += this.dx * dt; // move out for one tick since the object can't have spent a tick in the solid this.inst.y += this.dy * dt; this.inst.set_bbox_changed(); if (this.setAngle) { this.inst.angle = bounceAngle; this.lastKnownAngle = bounceAngle; this.inst.set_bbox_changed(); } if (!this.runtime.pushOutSolid(this.inst, this.dx / s, this.dy / s, Math.max(s * 2.5 * dt, 30))) this.runtime.pushOutSolidNearest(this.inst, 100); } } } }; function Cnds() {}; Cnds.prototype.CompareSpeed = function (cmp, s) { return cr.do_cmp(cr.distanceTo(0, 0, this.dx, this.dy), cmp, s); }; Cnds.prototype.CompareTravelled = function (cmp, d) { return cr.do_cmp(this.travelled, cmp, d); }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetSpeed = function (s) { var a = cr.angleTo(0, 0, this.dx, this.dy); this.dx = Math.cos(a) * s; this.dy = Math.sin(a) * s; }; Acts.prototype.SetAcceleration = function (a) { this.acc = a; }; Acts.prototype.SetGravity = function (g) { this.g = g; }; Acts.prototype.SetAngleOfMotion = function (a) { a = cr.to_radians(a); var s = cr.distanceTo(0, 0, this.dx, this.dy) this.dx = Math.cos(a) * s; this.dy = Math.sin(a) * s; }; Acts.prototype.Bounce = function (objtype) { if (!objtype) return; var otherinst = objtype.getFirstPicked(this.inst); if (!otherinst) return; var dt = this.runtime.getDt(this.inst); var s = cr.distanceTo(0, 0, this.dx, this.dy); var bounceAngle = this.runtime.calculateSolidBounceAngle(this.inst, this.lastx, this.lasty, otherinst); this.dx = Math.cos(bounceAngle) * s; this.dy = Math.sin(bounceAngle) * s; this.inst.x += this.dx * dt; // move out for one tick since the object can't have spent a tick in the solid this.inst.y += this.dy * dt; this.inst.set_bbox_changed(); if (this.setAngle) { this.inst.angle = bounceAngle; this.lastKnownAngle = bounceAngle; this.inst.set_bbox_changed(); } if (s !== 0) // prevent divide-by-zero { if (this.bounceOffSolid) { if (!this.runtime.pushOutSolid(this.inst, this.dx / s, this.dy / s, Math.max(s * 2.5 * dt, 30))) this.runtime.pushOutSolidNearest(this.inst, 100); } else { this.runtime.pushOut(this.inst, this.dx / s, this.dy / s, Math.max(s * 2.5 * dt, 30), otherinst) } } }; Acts.prototype.SetDistanceTravelled = function (d) { this.travelled = d; }; Acts.prototype.SetEnabled = function (en) { this.enabled = (en === 1); }; behaviorProto.acts = new Acts(); function Exps() {}; Exps.prototype.Speed = function (ret) { var s = cr.distanceTo(0, 0, this.dx, this.dy); s = cr.round6dp(s); ret.set_float(s); }; Exps.prototype.Acceleration = function (ret) { ret.set_float(this.acc); }; Exps.prototype.AngleOfMotion = function (ret) { ret.set_float(cr.to_degrees(cr.angleTo(0, 0, this.dx, this.dy))); }; Exps.prototype.DistanceTravelled = function (ret) { ret.set_float(this.travelled); }; Exps.prototype.Gravity = function (ret) { ret.set_float(this.g); }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.Fade = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Fade.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.activeAtStart = this.properties[0] === 1; this.setMaxOpacity = false; // used to retrieve maxOpacity once in first 'Start fade' action if initially inactive this.fadeInTime = this.properties[1]; this.waitTime = this.properties[2]; this.fadeOutTime = this.properties[3]; this.destroy = this.properties[4]; // 0 = no, 1 = after fade out this.stage = this.activeAtStart ? 0 : 3; // 0 = fade in, 1 = wait, 2 = fade out, 3 = done if (this.recycled) this.stageTime.reset(); else this.stageTime = new cr.KahanAdder(); this.maxOpacity = (this.inst.opacity ? this.inst.opacity : 1.0); if (this.activeAtStart) { if (this.fadeInTime === 0) { this.stage = 1; if (this.waitTime === 0) this.stage = 2; } else { this.inst.opacity = 0; this.runtime.redraw = true; } } }; behinstProto.saveToJSON = function () { return { "fit": this.fadeInTime, "wt": this.waitTime, "fot": this.fadeOutTime, "s": this.stage, "st": this.stageTime.sum, "mo": this.maxOpacity, }; }; behinstProto.loadFromJSON = function (o) { this.fadeInTime = o["fit"]; this.waitTime = o["wt"]; this.fadeOutTime = o["fot"]; this.stage = o["s"]; this.stageTime.reset(); this.stageTime.sum = o["st"]; this.maxOpacity = o["mo"]; }; behinstProto.tick = function () { this.stageTime.add(this.runtime.getDt(this.inst)); if (this.stage === 0) { this.inst.opacity = (this.stageTime.sum / this.fadeInTime) * this.maxOpacity; this.runtime.redraw = true; if (this.inst.opacity >= this.maxOpacity) { this.inst.opacity = this.maxOpacity; this.stage = 1; // wait stage this.stageTime.reset(); this.runtime.trigger(cr.behaviors.Fade.prototype.cnds.OnFadeInEnd, this.inst); } } if (this.stage === 1) { if (this.stageTime.sum >= this.waitTime) { this.stage = 2; // fade out stage this.stageTime.reset(); this.runtime.trigger(cr.behaviors.Fade.prototype.cnds.OnWaitEnd, this.inst); } } if (this.stage === 2) { if (this.fadeOutTime !== 0) { this.inst.opacity = this.maxOpacity - ((this.stageTime.sum / this.fadeOutTime) * this.maxOpacity); this.runtime.redraw = true; if (this.inst.opacity < 0) { this.inst.opacity = 0; this.stage = 3; // done this.stageTime.reset(); this.runtime.trigger(cr.behaviors.Fade.prototype.cnds.OnFadeOutEnd, this.inst); if (this.destroy === 1) this.runtime.DestroyInstance(this.inst); } } } }; behinstProto.doStart = function () { this.stage = 0; this.stageTime.reset(); if (this.fadeInTime === 0) { this.stage = 1; if (this.waitTime === 0) this.stage = 2; } else { this.inst.opacity = 0; this.runtime.redraw = true; } }; function Cnds() {}; Cnds.prototype.OnFadeOutEnd = function () { return true; }; Cnds.prototype.OnFadeInEnd = function () { return true; }; Cnds.prototype.OnWaitEnd = function () { return true; }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.StartFade = function () { if (!this.activeAtStart && !this.setMaxOpacity) { this.maxOpacity = (this.inst.opacity ? this.inst.opacity : 1.0); this.setMaxOpacity = true; } if (this.stage === 3) this.doStart(); }; Acts.prototype.RestartFade = function () { this.doStart(); }; Acts.prototype.SetFadeInTime = function (t) { if (t < 0) t = 0; this.fadeInTime = t; }; Acts.prototype.SetWaitTime = function (t) { if (t < 0) t = 0; this.waitTime = t; }; Acts.prototype.SetFadeOutTime = function (t) { if (t < 0) t = 0; this.fadeOutTime = t; }; behaviorProto.acts = new Acts(); function Exps() {}; Exps.prototype.FadeInTime = function (ret) { ret.set_float(this.fadeInTime); }; Exps.prototype.WaitTime = function (ret) { ret.set_float(this.waitTime); }; Exps.prototype.FadeOutTime = function (ret) { ret.set_float(this.fadeOutTime); }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.NSG_TrueTimer = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.NSG_TrueTimer.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; function TimStackEntry() { this.tag = ""; this.params = []; }; behinstProto.onCreate = function() { this.isInPreview = (typeof cr_is_preview !== "undefined"); this.timers = {}; this.params = []; this.timStack = []; this.timStackPtr = -1; }; behinstProto.onDestroy = function () { var tag; for (tag in this.timers) { if (this.timers.hasOwnProperty(tag) && this.timers[tag] !== null) { clearInterval(this.timers[tag].id); this.timers[tag] = null; } } }; behinstProto.pushTimStack = function() { this.timStackPtr++; if (this.timStackPtr === this.timStack.length) this.timStack.push(new TimStackEntry()); return this.timStack[this.timStackPtr]; }; behinstProto.getCurrentTimStack = function() { if (this.timStackPtr < 0) return null; return this.timStack[this.timStackPtr]; }; behinstProto.popTimStack = function() { ; this.timStackPtr--; }; behinstProto.parseTag = function(tag_) { return tag_.toLowerCase().trim(); }; behinstProto.timerExists = function(tag_) { return typeof this.timers[tag_] !== 'undefined'; }; behinstProto.setTimer = function(tag_, interval_, repeats_) { if (repeats_ <= 0) { this.params = []; return; } var currentTimerData = this.pushTimStack(); currentTimerData.tag = tag_; currentTimerData.params = this.params; this.timers[tag_] = { tag: tag_, interval: interval_, repeatsLeft: repeats_, params: this.params, triggerCounter: 0, isActive: true, startTime: (new Date()).getTime(), id: null }; this.params = []; var self = this; this.timers[tag_].id = setInterval( function () { self.onTimerTrigger(tag_) } ,this.timers[tag_].interval * 1000); this.runtime.trigger(cr.behaviors.NSG_TrueTimer.prototype.cnds.OnTimerStarted, this.inst); this.popTimStack(); }; behinstProto.onTimerTrigger = function(tag_) { var currentTimerData = this.pushTimStack(); currentTimerData.tag = tag_; currentTimerData.params = this.timers[tag_].params; --this.timers[tag_].repeatsLeft; ++this.timers[tag_].triggerCounter; if (this.timers[tag_].repeatsLeft === 0) { this.timers[tag_].isActive = false; } this.runtime.trigger(cr.behaviors.NSG_TrueTimer.prototype.cnds.OnTimer, this.inst); this.runtime.trigger(cr.behaviors.NSG_TrueTimer.prototype.cnds.OnAnyTimer, this.inst); if ( ! this.timers[tag_] ) { this.popTimStack(); return; } // timer can be cancelled in OnTimer condition if(this.timers[tag_].repeatsLeft <= 0) { clearInterval(this.timers[tag_].id); delete this.timers[tag_]; } this.popTimStack(); } behinstProto.tick = function () { }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnTimer = function(tag_) { var currentTimerData = this.getCurrentTimStack(); if ( ! currentTimerData) return false; tag_ = this.parseTag(tag_); if(this.timerExists(tag_) && currentTimerData.tag === tag_) { return true; } }; /** * @returns {boolean} */ Cnds.prototype.IsActive = function(tag_) { tag_ = this.parseTag(tag_); if ( ! this.timerExists(tag_)) return false; return this.timers[tag_].isActive; }; /** * @returns {boolean} */ Cnds.prototype.OnAnyTimer = function() { return true; }; Cnds.prototype.OnTimerStarted = function(tag_) { var currentTimerData = this.getCurrentTimStack(); if ( ! currentTimerData) return false; tag_ = this.parseTag(tag_); return currentTimerData.tag === tag_; }; /** * @returns {boolean} */ Cnds.prototype.OnTimerStopped = function(tag_) { var currentTimerData = this.getCurrentTimStack(); if ( ! currentTimerData) return false; tag_ = this.parseTag(tag_); return currentTimerData.tag === tag_; }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.StartTimer = function(tag_, interval_, repeats_) { tag_ = this.parseTag(tag_); if(this.timerExists(tag_)) { clearTimeout(this.timers[tag_].id); delete this.timers[tag_]; } this.setTimer(tag_, interval_, repeats_); }; Acts.prototype.StopTimer = function(tag_) { tag_ = this.parseTag(tag_); if(this.timerExists(tag_)) { var currentTimerData = this.pushTimStack(); currentTimerData.tag = tag_; currentTimerData.params = this.timers[tag_].params; clearTimeout(this.timers[tag_].id); delete this.timers[tag_]; this.runtime.trigger(cr.behaviors.NSG_TrueTimer.prototype.cnds.OnTimerStopped, this.inst); this.popTimStack(); } }; Acts.prototype.StopAllTimers = function() { for(var tag in this.timers) { if(this.timers.hasOwnProperty(tag) && typeof this.timers[tag] !== 'undefined' && this.timers[tag] !== null) { var currentTimerData = this.pushTimStack(); currentTimerData.tag = tag; currentTimerData.params = this.timers[tag].params; clearTimeout(this.timers[tag].id); delete this.timers[tag]; this.runtime.trigger(cr.behaviors.NSG_TrueTimer.prototype.cnds.OnTimerStopped, this.inst); this.popTimStack(); } } }; Acts.prototype.SetParam = function(paramId_, value_) { this.params[paramId_] = value_; }; behaviorProto.acts = new Acts(); function Exps() {}; Exps.prototype.TimerTimeLeft = function (ret, tag_, secondsFormat_) { tag_ = this.parseTag(tag_); if( ! this.timerExists(tag_)) { ret.set_int(-1); return; } var timeDiff = (new Date()).getTime() - this.timers[tag_].startTime; var remainingTime = this.timers[tag_].interval * 1000 - timeDiff; ret.set_int(secondsFormat_ === 0 ? remainingTime : remainingTime / 1000|0); }; Exps.prototype.TimerAge = function (ret, tag_, secondsFormat_) { tag_ = this.parseTag(tag_); if( ! this.timerExists(tag_)) { ret.set_int(-1); return; } var timeDiff = (new Date()).getTime() - this.timers[tag_].startTime; ret.set_int(secondsFormat_ === 0 ? timeDiff : timeDiff / 1000|0); }; Exps.prototype.TimerAgePercent = function (ret, tag_) { tag_ = this.parseTag(tag_); if( ! this.timerExists(tag_)) { ret.set_int(-1); return; } var percentTimePassed = (Date.now() - this.timers[tag_].startTime) / (this.timers[tag_].interval * 1000); ret.set_float(percentTimePassed); }; Exps.prototype.TriggerAge = function (ret, tag_) { tag_ = this.parseTag(tag_); if( ! this.timerExists(tag_)) { ret.set_int(-1); return; } ret.set_int(this.timers[tag_].triggerCounter); }; Exps.prototype.TriggersLeft = function (ret, tag_) { tag_ = this.parseTag(tag_); if( ! this.timerExists(tag_)) { ret.set_int(-1); return; } ret.set_int(this.timers[tag_].repeatsLeft); }; Exps.prototype.Param = function (ret, tag_, paramId_) { tag_ = this.parseTag(tag_); if( ! this.timerExists(tag_) || typeof this.timers[tag_].params[paramId_] === 'undefined') { ret.set_string(""); return; } ret.set_any(this.timers[tag_].params[paramId_]); }; Exps.prototype.Tag = function (ret) { var currentTimerData = this.getCurrentTimStack(); if ( ! currentTimerData) { if (this.isInPreview) { console.warn("Cannot read timer TrueTimer Tag because expression is not in a timer call.") } ret.set_string(""); } else { ret.set_string(currentTimerData.tag); } }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.Pin = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Pin.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.pinObject = null; this.pinObjectUid = -1; // for loading this.pinAngle = 0; this.pinDist = 0; this.myStartAngle = 0; this.theirStartAngle = 0; this.lastKnownAngle = 0; this.mode = 0; // 0 = position & angle; 1 = position; 2 = angle; 3 = rope; 4 = bar var self = this; if (!this.recycled) { this.myDestroyCallback = (function(inst) { self.onInstanceDestroyed(inst); }); } this.runtime.addDestroyCallback(this.myDestroyCallback); }; behinstProto.saveToJSON = function () { return { "uid": this.pinObject ? this.pinObject.uid : -1, "pa": this.pinAngle, "pd": this.pinDist, "msa": this.myStartAngle, "tsa": this.theirStartAngle, "lka": this.lastKnownAngle, "m": this.mode }; }; behinstProto.loadFromJSON = function (o) { this.pinObjectUid = o["uid"]; // wait until afterLoad to look up this.pinAngle = o["pa"]; this.pinDist = o["pd"]; this.myStartAngle = o["msa"]; this.theirStartAngle = o["tsa"]; this.lastKnownAngle = o["lka"]; this.mode = o["m"]; }; behinstProto.afterLoad = function () { if (this.pinObjectUid === -1) this.pinObject = null; else { this.pinObject = this.runtime.getObjectByUID(this.pinObjectUid); ; } this.pinObjectUid = -1; }; behinstProto.onInstanceDestroyed = function (inst) { if (this.pinObject == inst) this.pinObject = null; }; behinstProto.onDestroy = function() { this.pinObject = null; this.runtime.removeDestroyCallback(this.myDestroyCallback); }; behinstProto.tick = function () { }; behinstProto.tick2 = function () { if (!this.pinObject) return; if (this.lastKnownAngle !== this.inst.angle) this.myStartAngle = cr.clamp_angle(this.myStartAngle + (this.inst.angle - this.lastKnownAngle)); var newx = this.inst.x; var newy = this.inst.y; if (this.mode === 3 || this.mode === 4) // rope mode or bar mode { var dist = cr.distanceTo(this.inst.x, this.inst.y, this.pinObject.x, this.pinObject.y); if ((dist > this.pinDist) || (this.mode === 4 && dist < this.pinDist)) { var a = cr.angleTo(this.pinObject.x, this.pinObject.y, this.inst.x, this.inst.y); newx = this.pinObject.x + Math.cos(a) * this.pinDist; newy = this.pinObject.y + Math.sin(a) * this.pinDist; } } else { newx = this.pinObject.x + Math.cos(this.pinObject.angle + this.pinAngle) * this.pinDist; newy = this.pinObject.y + Math.sin(this.pinObject.angle + this.pinAngle) * this.pinDist; } var newangle = cr.clamp_angle(this.myStartAngle + (this.pinObject.angle - this.theirStartAngle)); this.lastKnownAngle = newangle; if ((this.mode === 0 || this.mode === 1 || this.mode === 3 || this.mode === 4) && (this.inst.x !== newx || this.inst.y !== newy)) { this.inst.x = newx; this.inst.y = newy; this.inst.set_bbox_changed(); } if ((this.mode === 0 || this.mode === 2) && (this.inst.angle !== newangle)) { this.inst.angle = newangle; this.inst.set_bbox_changed(); } }; function Cnds() {}; Cnds.prototype.IsPinned = function () { return !!this.pinObject; }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.Pin = function (obj, mode_) { if (!obj) return; var otherinst = obj.getFirstPicked(this.inst); if (!otherinst) return; this.pinObject = otherinst; this.pinAngle = cr.angleTo(otherinst.x, otherinst.y, this.inst.x, this.inst.y) - otherinst.angle; this.pinDist = cr.distanceTo(otherinst.x, otherinst.y, this.inst.x, this.inst.y); this.myStartAngle = this.inst.angle; this.lastKnownAngle = this.inst.angle; this.theirStartAngle = otherinst.angle; this.mode = mode_; }; Acts.prototype.Unpin = function () { this.pinObject = null; }; behaviorProto.acts = new Acts(); function Exps() {}; Exps.prototype.PinnedUID = function (ret) { ret.set_int(this.pinObject ? this.pinObject.uid : -1); }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.Rex_RotateTo = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Rex_RotateTo.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.activated = (this.properties[0] == 1); this.move = {"max":this.properties[1], "acc":this.properties[2], "dec":this.properties[3]}; this.target = {"a":0, "cw":true}; this.is_rotating = false; this.current_speed = 0; this.remain_distance = 0; this.is_my_call = false; }; behinstProto.tick = function () { if ( (!this.activated) || (!this.is_rotating) ) { return; } var dt = this.runtime.getDt(this.inst); if (dt==0) // can not move if dt == 0 return; var is_slow_down = false; if (this.move["dec"] != 0) { var _speed = this.current_speed; var _distance = (_speed*_speed)/(2*this.move["dec"]); // (v*v)/(2*a) is_slow_down = (_distance >= this.remain_distance); } var acc = (is_slow_down)? (-this.move["dec"]):this.move["acc"]; if (acc != 0) { this.SetCurrentSpeed( this.current_speed + (acc * dt) ); } var distance = this.current_speed * dt; this.remain_distance -= distance; var is_hit_target = false; if ( (this.remain_distance <= 0) || (this.current_speed <= 0) ) { this.is_rotating = false; this.inst.angle = cr.to_clamped_radians(this.target["a"]); this.SetCurrentSpeed(0); is_hit_target = true; } else { if (this.target["cw"]) this.inst.angle += cr.to_clamped_radians(distance); else this.inst.angle -= cr.to_clamped_radians(distance); } this.inst.set_bbox_changed(); if (is_hit_target) { this.is_my_call = true; this.runtime.trigger(cr.behaviors.Rex_RotateTo.prototype.cnds.OnHitTarget, this.inst); this.is_my_call = false; } }; behinstProto.tick2 = function () { }; behinstProto.SetCurrentSpeed = function(speed) { if (speed != null) { this.current_speed = (speed > this.move["max"])? this.move["max"]: speed; } else if (this.move["acc"]==0) { this.current_speed = this.move["max"]; } }; behinstProto.SetTargetAngle = function (target_angle_radians, clockwise_mode) // in radians { this.is_rotating = true; var cur_angle_radians = this.inst.angle; this.target["cw"] = (clockwise_mode == 2)? cr.angleClockwise(target_angle_radians, cur_angle_radians) : (clockwise_mode == 1); var remain_distance = (clockwise_mode == 2)? cr.angleDiff(cur_angle_radians, target_angle_radians) : (clockwise_mode == 1)? (target_angle_radians - cur_angle_radians) : (cur_angle_radians - target_angle_radians); this.remain_distance = cr.to_clamped_degrees(remain_distance); this.target["a"] = cr.to_clamped_degrees(target_angle_radians); this.SetCurrentSpeed(null); }; behinstProto.saveToJSON = function () { return { "en": this.activated, "v": this.move, "t": this.target, "ir": this.is_rotating, "cs": this.current_speed, "rd": this.remain_distance }; }; behinstProto.loadFromJSON = function (o) { this.activated = o["en"]; this.move = o["v"]; this.target = o["t"]; this.is_rotating = o["ir"]; this.current_speed = o["cs"]; this.remain_distance = o["rd"]; }; function Cnds() {}; behaviorProto.cnds = new Cnds(); Cnds.prototype.OnHitTarget = function () { return (this.is_my_call); }; Cnds.prototype.CompareSpeed = function (cmp, s) { return cr.do_cmp(this.current_speed, cmp, s); }; Cnds.prototype.OnMoving = function () // deprecated { return false; }; Cnds.prototype.IsRotating = function () { return (this.activated && this.is_rotating); }; function Acts() {}; behaviorProto.acts = new Acts(); Acts.prototype.SetActivated = function (s) { this.activated = (s == 1); }; Acts.prototype.SetMaxSpeed = function (s) { this.move["max"] = s; this.SetCurrentSpeed(null); }; Acts.prototype.SetAcceleration = function (a) { this.move["acc"] = a; this.SetCurrentSpeed(null); }; Acts.prototype.SetDeceleration = function (a) { this.move["dec"] = a; }; Acts.prototype.SetTargetAngle = function (angle, clockwise_mode) { this.SetTargetAngle(cr.to_clamped_radians(angle), clockwise_mode) }; Acts.prototype.SetCurrentSpeed = function (s) { this.SetCurrentSpeed(s); }; Acts.prototype.SetTargetAngleOnObject = function (objtype, clockwise_mode) { if (!objtype) return; var inst = objtype.getFirstPicked(); if (inst != null) { var angle = Math.atan2(inst.y-this.inst.y , inst.x-this.inst.x); this.SetTargetAngle(angle, clockwise_mode); } }; Acts.prototype.SetTargetAngleByDeltaAngle = function (dA, clockwise_mode) { var dA_rad = cr.to_clamped_radians(dA); if (clockwise_mode==0) dA_rad = -dA_rad; var angle = this.inst.angle + dA_rad; this.SetTargetAngle(angle, clockwise_mode); }; Acts.prototype.SetTargetAngleToPos = function (tx, ty, clockwise_mode) { var angle = Math.atan2(ty-this.inst.y , tx-this.inst.x); this.SetTargetAngle(angle, clockwise_mode); }; Acts.prototype.Stop = function () { this.is_rotating = false; }; function Exps() {}; behaviorProto.exps = new Exps(); Exps.prototype.Activated = function (ret) { ret.set_int((this.activated)? 1:0); }; Exps.prototype.Speed = function (ret) { ret.set_float(this.current_speed); }; Exps.prototype.MaxSpeed = function (ret) { ret.set_float(this.move["max"]); }; Exps.prototype.Acc = function (ret) { ret.set_float(this.move["acc"]); }; Exps.prototype.Dec = function (ret) { ret.set_float(this.move["dec"]); }; Exps.prototype.TargetAngle = function (ret) { var x = (this.is_rotating)? this.target["a"]:0; ret.set_float(x); }; }()); ; ; cr.behaviors.Rex_pinOffsetXY = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Rex_pinOffsetXY.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.pinObject = null; this.pinObjectUid = -1; // for loading this.pinOffsetX = 0; this.pinOffsetY = 0; var self = this; if (!this.recycled) { this.myDestroyCallback = (function(inst) { self.onInstanceDestroyed(inst); }); } this.runtime.addDestroyCallback(this.myDestroyCallback); }; behinstProto.saveToJSON = function () { return { "uid": this.pinObject ? this.pinObject.uid : -1, "offx": this.pinOffsetX, "offy": this.pinOffsetY, }; }; behinstProto.loadFromJSON = function (o) { this.pinObjectUid = o["uid"]; // wait until afterLoad to look up this.pinOffsetX = o["offx"]; this.pinOffsetY = o["offy"]; }; behinstProto.afterLoad = function () { if (this.pinObjectUid === -1) this.pinObject = null; else { this.pinObject = this.runtime.getObjectByUID(this.pinObjectUid); ; } this.pinObjectUid = -1; }; behinstProto.onInstanceDestroyed = function (inst) { if (this.pinObject == inst) this.pinObject = null; }; behinstProto.onDestroy = function() { this.pinObject = null; this.runtime.removeDestroyCallback(this.myDestroyCallback); }; behinstProto.tick = function () { }; behinstProto.tick2 = function () { if (!this.pinObject) return; var newx = this.pinObject.x + this.pinOffsetX; var newy = this.pinObject.y + this.pinOffsetY; if (this.inst.x !== newx || this.inst.y !== newy) { this.inst.x = newx; this.inst.y = newy; this.inst.set_bbox_changed(); } }; function Cnds() {}; behaviorProto.cnds = new Cnds(); Cnds.prototype.IsPinned = function () { return !!this.pinObject; }; function Acts() {}; behaviorProto.acts = new Acts(); Acts.prototype.Pin = function (obj, offsetX, offsetY) { if (!obj) return; var otherinst = obj.getFirstPicked(this.inst); if (!otherinst) return; if (offsetX == null) offsetX = this.inst.x - otherinst.x; if (offsetY == null) offsetY = this.inst.y - otherinst.y; this.pinObject = otherinst; this.pinOffsetX = offsetX; this.pinOffsetY = offsetY; }; Acts.prototype.Unpin = function () { this.pinObject = null; }; function Exps() {}; behaviorProto.exps = new Exps(); Exps.prototype.PinnedUID = function (ret) { ret.set_int(this.pinObject ? this.pinObject.uid : -1); }; }()); ; ; cr.behaviors.Sin = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Sin.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; this.i = 0; // period offset (radians) }; var behinstProto = behaviorProto.Instance.prototype; var _2pi = 2 * Math.PI; var _pi_2 = Math.PI / 2; var _3pi_2 = (3 * Math.PI) / 2; behinstProto.onCreate = function() { this.active = (this.properties[0] === 1); this.movement = this.properties[1]; // 0=Horizontal|1=Vertical|2=Size|3=Width|4=Height|5=Angle|6=Opacity|7=Value only this.wave = this.properties[2]; // 0=Sine|1=Triangle|2=Sawtooth|3=Reverse sawtooth|4=Square this.period = this.properties[3]; this.period += Math.random() * this.properties[4]; // period random if (this.period === 0) this.i = 0; else { this.i = (this.properties[5] / this.period) * _2pi; // period offset this.i += ((Math.random() * this.properties[6]) / this.period) * _2pi; // period offset random } this.mag = this.properties[7]; // magnitude this.mag += Math.random() * this.properties[8]; // magnitude random this.initialValue = 0; this.initialValue2 = 0; this.ratio = 0; if (this.movement === 5) // angle this.mag = cr.to_radians(this.mag); this.init(); }; behinstProto.saveToJSON = function () { return { "i": this.i, "a": this.active, "mv": this.movement, "w": this.wave, "p": this.period, "mag": this.mag, "iv": this.initialValue, "iv2": this.initialValue2, "r": this.ratio, "lkv": this.lastKnownValue, "lkv2": this.lastKnownValue2 }; }; behinstProto.loadFromJSON = function (o) { this.i = o["i"]; this.active = o["a"]; this.movement = o["mv"]; this.wave = o["w"]; this.period = o["p"]; this.mag = o["mag"]; this.initialValue = o["iv"]; this.initialValue2 = o["iv2"] || 0; this.ratio = o["r"]; this.lastKnownValue = o["lkv"]; this.lastKnownValue2 = o["lkv2"] || 0; }; behinstProto.init = function () { switch (this.movement) { case 0: // horizontal this.initialValue = this.inst.x; break; case 1: // vertical this.initialValue = this.inst.y; break; case 2: // size this.initialValue = this.inst.width; this.ratio = this.inst.height / this.inst.width; break; case 3: // width this.initialValue = this.inst.width; break; case 4: // height this.initialValue = this.inst.height; break; case 5: // angle this.initialValue = this.inst.angle; break; case 6: // opacity this.initialValue = this.inst.opacity; break; case 7: this.initialValue = 0; break; case 8: // forwards/backwards this.initialValue = this.inst.x; this.initialValue2 = this.inst.y; break; default: ; } this.lastKnownValue = this.initialValue; this.lastKnownValue2 = this.initialValue2; }; behinstProto.waveFunc = function (x) { x = x % _2pi; switch (this.wave) { case 0: // sine return Math.sin(x); case 1: // triangle if (x <= _pi_2) return x / _pi_2; else if (x <= _3pi_2) return 1 - (2 * (x - _pi_2) / Math.PI); else return (x - _3pi_2) / _pi_2 - 1; case 2: // sawtooth return 2 * x / _2pi - 1; case 3: // reverse sawtooth return -2 * x / _2pi + 1; case 4: // square return x < Math.PI ? -1 : 1; }; return 0; }; behinstProto.tick = function () { var dt = this.runtime.getDt(this.inst); if (!this.active || dt === 0) return; if (this.period === 0) this.i = 0; else { this.i += (dt / this.period) * _2pi; this.i = this.i % _2pi; } this.updateFromPhase(); }; behinstProto.updateFromPhase = function () { switch (this.movement) { case 0: // horizontal if (this.inst.x !== this.lastKnownValue) this.initialValue += this.inst.x - this.lastKnownValue; this.inst.x = this.initialValue + this.waveFunc(this.i) * this.mag; this.lastKnownValue = this.inst.x; break; case 1: // vertical if (this.inst.y !== this.lastKnownValue) this.initialValue += this.inst.y - this.lastKnownValue; this.inst.y = this.initialValue + this.waveFunc(this.i) * this.mag; this.lastKnownValue = this.inst.y; break; case 2: // size this.inst.width = this.initialValue + this.waveFunc(this.i) * this.mag; this.inst.height = this.inst.width * this.ratio; break; case 3: // width this.inst.width = this.initialValue + this.waveFunc(this.i) * this.mag; break; case 4: // height this.inst.height = this.initialValue + this.waveFunc(this.i) * this.mag; break; case 5: // angle if (this.inst.angle !== this.lastKnownValue) this.initialValue = cr.clamp_angle(this.initialValue + (this.inst.angle - this.lastKnownValue)); this.inst.angle = cr.clamp_angle(this.initialValue + this.waveFunc(this.i) * this.mag); this.lastKnownValue = this.inst.angle; break; case 6: // opacity this.inst.opacity = this.initialValue + (this.waveFunc(this.i) * this.mag) / 100; if (this.inst.opacity < 0) this.inst.opacity = 0; else if (this.inst.opacity > 1) this.inst.opacity = 1; break; case 8: // forwards/backwards if (this.inst.x !== this.lastKnownValue) this.initialValue += this.inst.x - this.lastKnownValue; if (this.inst.y !== this.lastKnownValue2) this.initialValue2 += this.inst.y - this.lastKnownValue2; this.inst.x = this.initialValue + Math.cos(this.inst.angle) * this.waveFunc(this.i) * this.mag; this.inst.y = this.initialValue2 + Math.sin(this.inst.angle) * this.waveFunc(this.i) * this.mag; this.lastKnownValue = this.inst.x; this.lastKnownValue2 = this.inst.y; break; } this.inst.set_bbox_changed(); }; behinstProto.onSpriteFrameChanged = function (prev_frame, next_frame) { switch (this.movement) { case 2: // size this.initialValue *= (next_frame.width / prev_frame.width); this.ratio = next_frame.height / next_frame.width; break; case 3: // width this.initialValue *= (next_frame.width / prev_frame.width); break; case 4: // height this.initialValue *= (next_frame.height / prev_frame.height); break; } }; function Cnds() {}; Cnds.prototype.IsActive = function () { return this.active; }; Cnds.prototype.CompareMovement = function (m) { return this.movement === m; }; Cnds.prototype.ComparePeriod = function (cmp, v) { return cr.do_cmp(this.period, cmp, v); }; Cnds.prototype.CompareMagnitude = function (cmp, v) { if (this.movement === 5) return cr.do_cmp(this.mag, cmp, cr.to_radians(v)); else return cr.do_cmp(this.mag, cmp, v); }; Cnds.prototype.CompareWave = function (w) { return this.wave === w; }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetActive = function (a) { this.active = (a === 1); }; Acts.prototype.SetPeriod = function (x) { this.period = x; }; Acts.prototype.SetMagnitude = function (x) { this.mag = x; if (this.movement === 5) // angle this.mag = cr.to_radians(this.mag); }; Acts.prototype.SetMovement = function (m) { if (this.movement === 5 && m !== 5) this.mag = cr.to_degrees(this.mag); this.movement = m; this.init(); }; Acts.prototype.SetWave = function (w) { this.wave = w; }; Acts.prototype.SetPhase = function (x) { this.i = (x * _2pi) % _2pi; this.updateFromPhase(); }; Acts.prototype.UpdateInitialState = function () { this.init(); }; behaviorProto.acts = new Acts(); function Exps() {}; Exps.prototype.CyclePosition = function (ret) { ret.set_float(this.i / _2pi); }; Exps.prototype.Period = function (ret) { ret.set_float(this.period); }; Exps.prototype.Magnitude = function (ret) { if (this.movement === 5) // angle ret.set_float(cr.to_degrees(this.mag)); else ret.set_float(this.mag); }; Exps.prototype.Value = function (ret) { ret.set_float(this.waveFunc(this.i) * this.mag); }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.TR_Level = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.TR_Level.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.lvl = { baseExp: this.properties[1], expScale: this.properties[2], maxLevel: this.properties[3], isDelevelingAllowed: !!this.properties[4], expScaleMode: this.properties[5], customExpScale: String(this.properties[6]).trim().split(","), currentLevel: 1, totalExp: 0, levelExp: 0, levelExpPool: 0 }; this.lvl.levelExpPool = this.getLevelExpPool(1); this.levelChangeValue = 0; }; behinstProto.onDestroy = function () { }; behinstProto.saveToJSON = function () { return { "lvl": JSON.stringify(this.lvl), }; }; behinstProto.loadFromJSON = function (o) { this.lvl = JSON.parse(o["lvl"]); }; behinstProto.tick = function () { }; var EXP_SCALE_MODES = { PROGRESSIVE: 0, CONSTANT: 1, CUSTOM: 2 }; behinstProto.cleanArray = function(_array) { var i, j = 0, len = _array.length; for (i = 0; i < len; ++i) { if (_array[i] === null) continue; _array[j] = _array[i]; ++j; } _array.length = j; }; behinstProto.getLevelExpPool = function(level_) { var levelExpPool; switch(this.lvl.expScaleMode) { case EXP_SCALE_MODES.PROGRESSIVE: levelExpPool = this.lvl.baseExp * Math.pow(this.lvl.expScale, (level_ - 1)); break; case EXP_SCALE_MODES.CONSTANT: levelExpPool = this.lvl.baseExp + this.lvl.expScale * (level_ - 1); break; case EXP_SCALE_MODES.CUSTOM: levelExpPool = this.lvl.customExpScale[level_ - 1] || this.lvl.customExpScale[this.lvl.customExpScale.length - 1]; break; } return Math.floor(levelExpPool); }; behinstProto.addExperience = function(experience_) { if(this.lvl.currentLevel === this.lvl.maxLevel) return; var levelChangeQty = 0; while(experience_ > 0) { var missingExp = this.lvl.levelExpPool - this.lvl.levelExp; if(missingExp > experience_) { this.lvl.levelExp += experience_; this.lvl.totalExp += experience_; experience_ = 0; } else { this.lvl.totalExp += missingExp; experience_ -= missingExp; ++levelChangeQty; ++this.lvl.currentLevel; this.lvl.levelExp = 0; this.lvl.levelExpPool = this.getLevelExpPool(this.lvl.currentLevel); this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnLevelUp, this.inst); if(this.lvl.currentLevel === this.lvl.maxLevel) break; } } if(levelChangeQty > 0) { this.levelChangeValue = levelChangeQty; this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnLevelChange, this.inst); this.levelChangeValue = 0; if(this.lvl.currentLevel === this.lvl.maxLevel) { this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnMaxLevelReached, this.inst); } } this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnExpAdded, this.inst); this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnExpChanged, this.inst); }; behinstProto.subtractExperience = function(experience_) { if(this.lvl.totalExp < 1) return; var levelChangeQty = 0; while(experience_ > 0 && this.lvl.totalExp > 0) { if(this.lvl.levelExp >= experience_) { this.lvl.levelExp -= experience_; this.lvl.totalExp -= experience_; experience_ = 0; } else { experience_ -= this.lvl.levelExp; this.lvl.totalExp -= this.lvl.levelExp; this.lvl.levelExp = 0; if(this.lvl.isDelevelingAllowed && this.lvl.currentLevel > 1) { --levelChangeQty; --this.lvl.currentLevel; this.lvl.levelExpPool = this.getLevelExpPool(this.lvl.currentLevel); this.lvl.levelExp = this.lvl.levelExpPool; this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnLevelDown, this.inst); } else { break; } } } if(levelChangeQty < 0) { this.levelChangeValue = levelChangeQty; this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnLevelChange, this.inst); this.levelChangeValue = 0; } this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnExpSubtracted, this.inst); this.runtime.trigger(cr.behaviors.TR_Level.prototype.cnds.OnExpChanged, this.inst); }; behinstProto.getTotalExp = function(level_) { if(level_ < 1) return 0; var i, totalExp = 0; for(i = 1; i <= level_; ++i) { totalExp += this.getLevelExpPool(i); } return totalExp; }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnLevelUp = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnLevelDown = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnLevelChange = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnExpAdded = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnExpSubtracted = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnExpChanged = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnMaxLevelReached = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.OnLevelReached = function (level_) { return true; }; /** * @returns {boolean} */ Cnds.prototype.LevelCompare = function (cmp_, value_) { return cr.do_cmp(this.lvl.currentLevel, cmp_, value_); }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.AddExperience = function (experience_) { this.addExperience(experience_); }; Acts.prototype.SubtractExperience = function (experience_) { this.subtractExperience(experience_); }; Acts.prototype.SetExperience = function (experience_) { if(experience_ > this.lvl.totalExp) { this.addExperience(experience_ - this.lvl.totalExp); } else if(experience_ < this.lvl.totalExp) { this.subtractExperience(this.lvl.totalExp - experience_); } }; Acts.prototype.SetExperienceScale = function (scale_) { this.lvl.expScale = scale_; }; Acts.prototype.SetMaxLevel = function (level_) { this.lvl.maxLevel = level_; }; Acts.prototype.LoadFromJSON = function (JSON_) { this.lvl = JSON.parse(JSON_); }; behaviorProto.acts = new Acts(); function Exps() {}; /*Exps.prototype.MyExpression = function (ret) // 'ret' must always be the first parameter - always return the expression's result through it! { ret.set_int(1337); // return our value };*/ Exps.prototype.AsJSON = function (ret) { ret.set_string(JSON.stringify(this.lvl)); }; Exps.prototype.CurrentLevel = function (ret) { ret.set_int(this.lvl.currentLevel); }; Exps.prototype.MaxLevel = function (ret) { ret.set_int(this.lvl.maxLevel); }; Exps.prototype.LevelExpValue = function (ret) { ret.set_int(this.lvl.levelExp); }; Exps.prototype.LevelExpProgress = function (ret) { ret.set_float(Math.floor((this.lvl.levelExp/this.lvl.levelExpPool) * 100) / 100); }; Exps.prototype.LevelExpPool = function (ret) { var level = arguments[1] || this.lvl.currentLevel; var value = level === this.lvl.currentLevel ? this.lvl.levelExpPool : this.getLevelExpPool(level); ret.set_int(value); }; Exps.prototype.TotalExp = function (ret) { var value; if(arguments[1]) { value = this.getTotalExp(arguments[1]); } else { value = this.lvl.totalExp; } ret.set_int(value); }; Exps.prototype.LevelChangeValue = function (ret) { ret.set_int(this.levelChangeValue); }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.TR_Scale = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.TR_Scale.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { this.SCALE_DIMENSION = { GENERAL: 0, WIDTH: 1, HEIGHT: 2 }; this.SCALE_TYPE = { SELF: 0, MASTER: 1, IMAGE: 2 }; }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.initialDimensions = {}; this.isParentValidObject = (this.inst.type.plugin.acts.SetSize && typeof this.inst.width !== "undefined" && typeof this.inst.height !== "undefined"); /*if (this.isParentValidObject) { var self = this; var loop = setInterval(function() { if ( ! self.inst.curFrame) return; // this will most probably be never true, but let's leave it here just in case clearInterval(loop); /!* initialWidthScale = self.inst.width / self.inst.curFrame.width; initialHeightScale = self.inst.height / self.inst.curFrame.height; var i, j, len, len2, a, f; for (i = 0, len = self.inst.type.animations.length; i < len; ++i) { a = self.inst.type.animations[i]; self.initialDimensions[a.name] = []; for (j = 0, len2 = a.frames.length; j < len2; ++j) { f = a.frames[j]; self.initialDimensions[a.name].push( { width: f.width * initialWidthScale, height: f.height * initialHeightScale } ); } }*!/ }, 1); }*/ }; behinstProto.postCreate = function() { if ( ! this.isParentValidObject) return; var initialWidthScale = null; var initialHeightScale = null; var self = this; initialWidthScale = self.inst.width / self.inst.curFrame.width; initialHeightScale = self.inst.height / self.inst.curFrame.height; var i, j, len, len2, a, f; for (i = 0, len = self.inst.type.animations.length; i < len; ++i) { a = self.inst.type.animations[i]; self.initialDimensions[a.name] = []; for (j = 0, len2 = a.frames.length; j < len2; ++j) { f = a.frames[j]; self.initialDimensions[a.name].push( { width: f.width * initialWidthScale, height: f.height * initialHeightScale } ); } } }; behinstProto.getInitialWidth = function() { if(this.initialDimensions[this.inst.cur_animation.name] && this.initialDimensions[this.inst.cur_animation.name][this.inst.cur_frame]) { return this.initialDimensions[this.inst.cur_animation.name][this.inst.cur_frame].width; } else { return NaN; } }; behinstProto.getInitialHeight = function() { if(this.initialDimensions[this.inst.cur_animation.name] && this.initialDimensions[this.inst.cur_animation.name][this.inst.cur_frame]) { return this.initialDimensions[this.inst.cur_animation.name][this.inst.cur_frame].height; } else { return NaN; } }; behinstProto.onDestroy = function () { }; /*// called when saving the full state of the game behinstProto.saveToJSON = function () { return { }; };*/ /*// called when loading the full state of the game behinstProto.loadFromJSON = function (o) { };*/ behinstProto.tick = function () { }; behinstProto.setScale = function(dimensionType_, scaleType_, value_) { if ( ! this.isParentValidObject) return; var height, width, baseHeight, baseWidth; var mirrorFactor = (this.inst.width < 0 ? -1 : 1); var flipFactor = (this.inst.height < 0 ? -1 : 1); switch (scaleType_) { case this.type.SCALE_TYPE.SELF: baseWidth = this.getInitialWidth(); baseHeight = this.getInitialHeight(); break; /*case this.type.SCALE_TYPE.MASTER: break;*/ case this.type.SCALE_TYPE.IMAGE: baseWidth = this.inst.curFrame.width; baseHeight = this.inst.curFrame.height; break; } switch (dimensionType_) { case this.type.SCALE_DIMENSION.GENERAL: width = value_ * baseWidth * mirrorFactor; height = value_ * baseHeight * flipFactor; this.inst.type.plugin.acts.SetSize.call(this.inst, width, height); break; case this.type.SCALE_DIMENSION.WIDTH: width = value_ * baseWidth * mirrorFactor; this.inst.type.plugin.acts.SetWidth.call(this.inst, width); break; case this.type.SCALE_DIMENSION.HEIGHT: height = value_ * baseHeight * flipFactor; this.inst.type.plugin.acts.SetHeight.call(this.inst, height); break; } this.runtime.trigger(cr.behaviors.TR_Scale.prototype.cnds.OnScaleChanged, this.inst); }; behinstProto.getScale = function(dimensionType_, scaleType_) { if ( ! this.isParentValidObject) return -1; var scale, baseHeight, baseWidth; switch (scaleType_) { case this.type.SCALE_TYPE.SELF: baseWidth = this.getInitialWidth(); baseHeight = this.getInitialHeight(); break; /*case this.type.SCALE_TYPE.MASTER: break;*/ case this.type.SCALE_TYPE.IMAGE: baseWidth = this.inst.curFrame.width; baseHeight = this.inst.curFrame.height; break; } switch (dimensionType_) { case this.type.SCALE_DIMENSION.GENERAL: var scaleWidth = this.inst.width / baseWidth; var scaleHeight = this.inst.height / baseHeight; scale = (scaleWidth + scaleHeight) / 2; break; case this.type.SCALE_DIMENSION.WIDTH: scale = this.inst.width / baseWidth; break; case this.type.SCALE_DIMENSION.HEIGHT: scale = this.inst.height / baseHeight; break; } return scale; }; behinstProto.isValidObject = function() { return this.isParentValidObject; }; function Cnds() {}; /** * @returns {boolean} */ Cnds.prototype.OnScaleChanged = function () { return true; }; /** * @returns {boolean} */ Cnds.prototype.CompareScaleSelf = function (scaleDimension_, cmp_, value_) { return cr.do_cmp(this.getScale(scaleDimension_, this.type.SCALE_TYPE.SELF), cmp_, value_); }; /** * @returns {boolean} */ Cnds.prototype.CompareScaleImage = function (scaleDimension_, cmp_, value_) { return cr.do_cmp(this.getScale(scaleDimension_, this.type.SCALE_TYPE.IMAGE), cmp_, value_); }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetScaleSelf = function (scaleDimension_, value_) { this.setScale(scaleDimension_, this.type.SCALE_TYPE.SELF, value_); }; Acts.prototype.SetScaleImage = function (scaleDimension_, value_) { this.setScale(scaleDimension_, this.type.SCALE_TYPE.IMAGE, value_); }; behaviorProto.acts = new Acts(); function Exps() {}; /*Exps.prototype.MyExpression = function (ret) // 'ret' must always be the first parameter - always return the expression's result through it! { ret.set_int(1337); // return our value };*/ Exps.prototype.Self = function (ret) { ret.set_float(this.getScale(this.type.SCALE_DIMENSION.GENERAL, this.type.SCALE_TYPE.SELF)); // for returning floats }; Exps.prototype.SelfWidth = function (ret) { ret.set_float(this.getScale(this.type.SCALE_DIMENSION.WIDTH, this.type.SCALE_TYPE.SELF)); // for returning floats }; Exps.prototype.SelfHeight = function (ret) { ret.set_float(this.getScale(this.type.SCALE_DIMENSION.HEIGHT, this.type.SCALE_TYPE.SELF)); // for returning floats }; Exps.prototype.Image = function (ret) { ret.set_float(this.getScale(this.type.SCALE_DIMENSION.GENERAL, this.type.SCALE_TYPE.IMAGE)); // for returning floats }; Exps.prototype.ImageWidth = function (ret) { ret.set_float(this.getScale(this.type.SCALE_DIMENSION.WIDTH, this.type.SCALE_TYPE.IMAGE)); // for returning floats }; Exps.prototype.ImageHeight = function (ret) { ret.set_float(this.getScale(this.type.SCALE_DIMENSION.HEIGHT, this.type.SCALE_TYPE.IMAGE)); // for returning floats }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.Timer = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.Timer.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.timers = {}; }; behinstProto.onDestroy = function () { cr.wipe(this.timers); }; behinstProto.saveToJSON = function () { var o = {}; var p, t; for (p in this.timers) { if (this.timers.hasOwnProperty(p)) { t = this.timers[p]; o[p] = { "c": t.current.sum, "t": t.total.sum, "d": t.duration, "r": t.regular }; } } return o; }; behinstProto.loadFromJSON = function (o) { this.timers = {}; var p; for (p in o) { if (o.hasOwnProperty(p)) { this.timers[p] = { current: new cr.KahanAdder(), total: new cr.KahanAdder(), duration: o[p]["d"], regular: o[p]["r"] }; this.timers[p].current.sum = o[p]["c"]; this.timers[p].total.sum = o[p]["t"]; } } }; behinstProto.tick = function () { var dt = this.runtime.getDt(this.inst); var p, t; for (p in this.timers) { if (this.timers.hasOwnProperty(p)) { t = this.timers[p]; t.current.add(dt); t.total.add(dt); } } }; behinstProto.tick2 = function () { var p, t; for (p in this.timers) { if (this.timers.hasOwnProperty(p)) { t = this.timers[p]; if (t.current.sum >= t.duration) { if (t.regular) t.current.sum -= t.duration; else delete this.timers[p]; } } } }; function Cnds() {}; Cnds.prototype.OnTimer = function (tag_) { tag_ = tag_.toLowerCase(); var t = this.timers[tag_]; if (!t) return false; return t.current.sum >= t.duration; }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.StartTimer = function (duration_, type_, tag_) { this.timers[tag_.toLowerCase()] = { current: new cr.KahanAdder(), total: new cr.KahanAdder(), duration: duration_, regular: (type_ === 1) }; }; Acts.prototype.StopTimer = function (tag_) { tag_ = tag_.toLowerCase(); if (this.timers.hasOwnProperty(tag_)) delete this.timers[tag_]; }; behaviorProto.acts = new Acts(); function Exps() {}; Exps.prototype.CurrentTime = function (ret, tag_) { var t = this.timers[tag_.toLowerCase()]; ret.set_float(t ? t.current.sum : 0); }; Exps.prototype.TotalTime = function (ret, tag_) { var t = this.timers[tag_.toLowerCase()]; ret.set_float(t ? t.total.sum : 0); }; Exps.prototype.Duration = function (ret, tag_) { var t = this.timers[tag_.toLowerCase()]; ret.set_float(t ? t.duration : 0); }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.aekiro_progress = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.aekiro_progress.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; this.runtime = type.runtime; if(!cr.proui){ throw new Error("ProUI Plugin not found. Please add it to the project."); return; } }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.proui = cr.proui; this.proui.isTypeValid(this.inst,[cr.plugins_.Sprite,cr.plugins_.NinePatch,cr.plugins_.TiledBg],"Pro UI: ProgressBar behavior is only applicable to Sprite , 9-patch or Tiled Background objects."); this.progressType = 0; this.maxValue = this.properties[0]; this.value = cr.clamp(this.properties[1],0,this.maxValue); this.animation = this.properties[2]; this.firstFrame = true; this.inst.uiType = "progress"; this.uiType = "progress"; this.inst._proui = this; this.compParent = this; this.isInit = false; this.initWidth = 0; this.initHeight = 0; this.tween = new TWEEN["Tween"](this.inst); if(this.animation == 1){ this.tween["easing"](TWEEN["Easing"]["Linear"]["None"]); }else if(this.animation == 2){ this.tween["easing"](TWEEN["Easing"]["Quadratic"]["Out"]); } }; behinstProto.updateFromModel = function (){ if(this.runtime.extra.notRegister){ return; } var modelB = this.inst.proui_model; if(modelB){ var value = modelB.getFromModel(); if(value == null){ return; } value = this.proui.validateSimpleValue(value,0); value = cr.clamp(value,0,this.maxValue); if(this.value!=value){ this.value = value; } } }; behinstProto.setValue = function (value){ this.firstSetValue = true; if(this._setValue(value)){ var modelB = this.inst.proui_model; if(modelB){ modelB.setModelValue(value,{except:this.compParent}); } if(this.inst.proui_bind){ this.inst.proui_bind.updateGridViewModel(value,{except:this.compParent}); } } }; behinstProto._setValue = function (value){ if(value == null){ return false; } value = this.proui.validateSimpleValue(value,0); value = cr.clamp(value,0,this.maxValue); if(this.value!=value){ this.value = value; this.updateView(); return true; }else{ return false; } }; behinstProto.updateView = function (){ if(!this.isInit){ return; } var targetProp = 0; var progress = this.value/this.maxValue; if(this.progressType == 0){ targetProp = progress*this.initWidth; }else if (this.progressType == 1){ targetProp = progress*this.initHeight; } if(this.firstFrame || !this.animation){ if(this.progressType == 0){ this.inst.width = targetProp; }else if (this.progressType == 1){ this.inst.height = targetProp; } this.inst.set_bbox_changed(); }else if(this.animation){ if(this.progressType == 0){ this.tween["to"]({ width:targetProp}, 500)["start"](); }else if (this.progressType == 1){ this.tween["to"]({ height:targetProp}, 500)["start"](); } } }; behinstProto.init = function (){ if(this.isInit){ return; } this.inst.cur_anim_speed = 0; this.initWidth = this.inst.width; this.initHeight = this.inst.height; this.isInit = true; }; behinstProto.tick = function () { if(this.firstFrame){ this.init(); if(!this.firstSetValue){ this.updateFromModel(); } this.updateView(); this.firstFrame = false; // has to be after the updateView so that no animation is played in the begining } if(this.tween["isPlaying"]){ var dt = this.runtime.getDt(this.inst)*1000 this.tween["update"](dt); this.inst.set_bbox_changed(); } }; behinstProto.onDestroy = function () { }; behinstProto.saveToJSON = function () { return { "maxValue" : this.maxValue, "animation" : this.animation, "value" : this.value, "progressType" : this.progressType, "initWidth":this.initWidth, "initHeight":this.initHeight, }; }; behinstProto.loadFromJSON = function (o) { this.maxValue = o["maxValue"]; this.animation = o["animation"]; this.value = o["value"]; this.progressType = o["progressType"]; this.initWidth = o["initWidth"]; this.initHeight = o["initHeight"]; this.inst.width = this.initWidth; this.inst.height = this.initHeight; }; function Cnds() {}; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.setValue = function (value){ this.setValue(value); }; behaviorProto.acts = new Acts(); function Exps() {}; Exps.prototype.value = function (ret) { ret.set_float(this.value); }; behaviorProto.exps = new Exps(); }()); ; ; cr.behaviors.bound = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.bound.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; this.mode = 0; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.mode = this.properties[0]; // 0 = origin, 1 = edge }; behinstProto.tick = function () { }; behinstProto.tick2 = function () { this.inst.update_bbox(); var bbox = this.inst.bbox; var layout = this.inst.layer.layout; var changed = false; if (this.mode === 0) // origin { if (this.inst.x < 0) { this.inst.x = 0; changed = true; } if (this.inst.y < 0) { this.inst.y = 0; changed = true; } if (this.inst.x > layout.width) { this.inst.x = layout.width; changed = true; } if (this.inst.y > layout.height) { this.inst.y = layout.height; changed = true; } } else { if (bbox.left < 0) { this.inst.x -= bbox.left; changed = true; } if (bbox.top < 0) { this.inst.y -= bbox.top; changed = true; } if (bbox.right > layout.width) { this.inst.x -= (bbox.right - layout.width); changed = true; } if (bbox.bottom > layout.height) { this.inst.y -= (bbox.bottom - layout.height); changed = true; } } if (changed) this.inst.set_bbox_changed(); }; }()); ; ; cr.behaviors.destroy = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.destroy.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { }; behinstProto.tick = function () { this.inst.update_bbox(); var bbox = this.inst.bbox; var layout = this.inst.layer.layout; if (bbox.right < 0 || bbox.bottom < 0 || bbox.left > layout.width || bbox.top > layout.height) this.runtime.DestroyInstance(this.inst); }; }()); var easeOutBounceArray = []; var easeInElasticArray = []; var easeOutElasticArray = []; var easeInOutElasticArray = []; var easeInCircle = []; var easeOutCircle = []; var easeInOutCircle = []; var easeInBack = []; var easeOutBack = []; var easeInOutBack = []; var litetween_precision = 10000; var updateLimit = 0; //0.0165; function easeOutBouncefunc(t) { var b=0.0; var c=1.0; var d=1.0; if ((t/=d) < (1/2.75)) { result = c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { result = c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { result = c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { result = c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } return result; } function integerize(t, d) { return Math.round(t/d*litetween_precision); } function easeFunc(easing, t, b, c, d, flip, param) { var ret_ease = 0; switch (easing) { case 0: // linear ret_ease = c*t/d + b; break; case 1: // easeInQuad ret_ease = c*(t/=d)*t + b; break; case 2: // easeOutQuad ret_ease = -c *(t/=d)*(t-2) + b; break; case 3: // easeInOutQuad if ((t/=d/2) < 1) ret_ease = c/2*t*t + b else ret_ease = -c/2 * ((--t)*(t-2) - 1) + b; break; case 4: // easeInCubic ret_ease = c*(t/=d)*t*t + b; break; case 5: // easeOutCubic ret_ease = c*((t=t/d-1)*t*t + 1) + b; break; case 6: // easeInOutCubic if ((t/=d/2) < 1) ret_ease = c/2*t*t*t + b else ret_ease = c/2*((t-=2)*t*t + 2) + b; break; case 7: // easeInQuart ret_ease = c*(t/=d)*t*t*t + b; break; case 8: // easeOutQuart ret_ease = -c * ((t=t/d-1)*t*t*t - 1) + b; break; case 9: // easeInOutQuart if ((t/=d/2) < 1) ret_ease = c/2*t*t*t*t + b else ret_ease = -c/2 * ((t-=2)*t*t*t - 2) + b; break; case 10: // easeInQuint ret_ease = c*(t/=d)*t*t*t*t + b; break; case 11: // easeOutQuint ret_ease = c*((t=t/d-1)*t*t*t*t + 1) + b; break; case 12: // easeInOutQuint if ((t/=d/2) < 1) ret_ease = c/2*t*t*t*t*t + b else ret_ease = c/2*((t-=2)*t*t*t*t + 2) + b; break; case 13: // easeInCircle if (param.optimized) { ret_ease = easeInCircle[integerize(t,d)]; } else { ret_ease = -(Math.sqrt(1-t*t) - 1); } break; case 14: // easeOutCircle if (param.optimized) { ret_ease = easeOutCircle[integerize(t,d)]; } else { ret_ease = Math.sqrt(1 - ((t-1)*(t-1))); } break; case 15: // easeInOutCircle if (param.optimized) { ret_ease = easeInOutCircle[integerize(t,d)]; } else { if ((t/=d/2) < 1) ret_ease = -c/2 * (Math.sqrt(1 - t*t) - 1) + b else ret_ease = c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; } break; case 16: // easeInBack if (param.optimized) { ret_ease = easeInBack[integerize(t,d)]; } else { var s = param.s; ret_ease = c*(t/=d)*t*((s+1)*t - s) + b; } break; case 17: // easeOutBack if (param.optimized) { ret_ease = easeOutBack[integerize(t,d)]; } else { var s = param.s; ret_ease = c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; } break; case 18: // easeInOutBack if (param.optimized) { ret_ease = easeInOutBack[integerize(t,d)]; } else { var s = param.s if ((t/=d/2) < 1) ret_ease = c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b else ret_ease = c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; } break; case 19: //easeInElastic if (param.optimized) { ret_ease = easeInElasticArray[integerize(t, d)]; } else { var a = param.a; var p = param.p; var s = 0; if (t==0) ret_ease = b; if ((t/=d)==1) ret_ease = b+c; if (p==0) p=d*.3; if (a==0 || a < Math.abs(c)) { a=c; s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); ret_ease = -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; } break; case 20: //easeOutElastic if (param.optimized) { ret_ease = easeOutElasticArray[integerize(t,d)]; } else { var a = param.a; var p = param.p; var s = 0; if (t==0) ret_ease= b; if ((t/=d)==1) ret_ease= b+c; if (p == 0) p=d*.3; if (a==0 || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); ret_ease= (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b); } break; case 21: //easeInOutElastic if (param.optimized) { ret_ease = easeInOutElasticArray[integerize(t,d)]; } else { var a = param.a; var p = param.p; var s = 0; if (t==0) ret_ease = b; if ((t/=d/2)==2) ret_ease = b+c; if (p==0) p=d*(.3*1.5); if (a==0 || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) ret_ease = -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b else ret_ease = a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; } break; case 22: //easeInBounce if (param.optimized) { ret_ease = c - easeOutBounceArray[integerize(d-t, d)] + b; } else { ret_ease = c - easeOutBouncefunc(d-t/d) + b; } break; case 23: //easeOutBounce if (param.optimized) { ret_ease = easeOutBounceArray[integerize(t, d)]; } else { ret_ease = easeOutBouncefunc(t/d); } break; case 24: //easeInOutBounce if (param.optimized) { if (t < d/2) ret_ease = (c - easeOutBounceArray[integerize(d-(t*2), d)] + b) * 0.5 +b; else ret_ease = easeOutBounceArray[integerize(t*2-d, d)] * .5 + c*.5 + b; } else { if (t < d/2) ret_ease = (c - easeOutBouncefunc(d-(t*2)) + b) * 0.5 +b; else ret_ease = easeOutBouncefunc((t*2-d)/d) * .5 + c *.5 + b; } break; case 25: //easeInSmoothstep var mt = (t/d) / 2; ret_ease = (2*(mt * mt * (3 - 2*mt))); break; case 26: //easeOutSmoothstep var mt = ((t/d) + 1) / 2; ret_ease = ((2*(mt * mt * (3 - 2*mt))) - 1); break; case 27: //easeInOutSmoothstep var mt = (t / d); ret_ease = (mt * mt * (3 - 2*mt)); break; }; if (flip) return (c - b) - ret_ease else return ret_ease; }; (function preCalculateArray() { var d = 1.0; var b = 0.0; var c = 1.0; var result = 0.0; var a = 0.0; var p = 0.0; var t = 0.0; var s = 0.0; for (var ti = 0; ti <= litetween_precision; ti++) { t = ti/litetween_precision; if ((t/=d) < (1/2.75)) { result = c*(7.5625*t*t) + b; } else if (t < (2/2.75)) { result = c*(7.5625*(t-=(1.5/2.75))*t + .75) + b; } else if (t < (2.5/2.75)) { result = c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b; } else { result = c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b; } easeOutBounceArray[ti] = result; t = ti/litetween_precision; a = 0; p = 0; if (t==0) result = b; if ((t/=d)==1) result = b+c; if (p==0) p=d*.3; if (a==0 || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); result = -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b; easeInElasticArray[ti] = result; t = ti/litetween_precision; a = 0; p = 0; if (t==0) result= b; if ((t/=d)==1) result= b+c; if (p == 0) p=d*.3; if (a==0 || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); result= (a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b); easeOutElasticArray[ti] = result; t = ti/litetween_precision; a = 0; p = 0; if (t==0) result = b; if ((t/=d/2)==2) result = b+c; if (p==0) p=d*(.3*1.5); if (a==0 || a < Math.abs(c)) { a=c; var s=p/4; } else var s = p/(2*Math.PI) * Math.asin (c/a); if (t < 1) result = -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b else result = a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b; easeInOutElasticArray[ti] = result; t = ti/litetween_precision; easeInCircle[ti] = -(Math.sqrt(1-t*t) - 1); t = ti/litetween_precision; easeOutCircle[ti] = Math.sqrt(1 - ((t-1)*(t-1))); t = ti/litetween_precision; if ((t/=d/2) < 1) result = -c/2 * (Math.sqrt(1 - t*t) - 1) + b else result = c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b; easeInOutCircle[ti] = result; t = ti/litetween_precision; s = 0; if (s==0) s = 1.70158; result = c*(t/=d)*t*((s+1)*t - s) + b; easeInBack[ti] = result; t = ti/litetween_precision; s = 0; if (s==0) s = 1.70158; result = c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b; easeOutBack[ti] = result; t = ti/litetween_precision; s = 0; if (s==0) s = 1.70158; if ((t/=d/2) < 1) result = c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b else result = c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b; easeInOutBack[ti] = result; } }()); var TweenObject = function() { var constructor = function (tname, tweened, easefunc, initial, target, duration, enforce) { this.name = tname; this.value = 0; this.setInitial(initial); this.setTarget(target); this.easefunc = easefunc; this.tweened = tweened; this.duration = duration; this.progress = 0; this.state = 0; this.onStart = false; this.onEnd = false; this.onReverseStart = false; this.onReverseEnd = false; this.lastKnownValue = 0; this.lastKnownValue2 = 0; this.enforce = enforce; this.pingpong = 1.0; this.flipEase = false; this.easingparam = []; this.lastState = 1; for (var i=0; i<28; i++) { this.easingparam[i] = {}; this.easingparam[i].a = 0.0; this.easingparam[i].p = 0.0; this.easingparam[i].t = 0.0; this.easingparam[i].s = 0.0; this.easingparam[i].optimized = true; } } return constructor; }(); (function () { TweenObject.prototype = { }; TweenObject.prototype.flipTarget = function () { var x1 = this.initialparam1; var x2 = this.initialparam2; this.initialparam1 = this.targetparam1; this.initialparam2 = this.targetparam2; this.targetparam1 = x1; this.targetparam2 = x2; this.lastKnownValue = 0; this.lastKnownValue2 = 0; } TweenObject.prototype.setInitial = function (initial) { this.initialparam1 = parseFloat(initial.split(",")[0]); this.initialparam2 = parseFloat(initial.split(",")[1]); this.lastKnownValue = 0; this.lastKnownValue2 = 0; } TweenObject.prototype.setTarget = function (target) { this.targetparam1 = parseFloat(target.split(",")[0]); this.targetparam2 = parseFloat(target.split(",")[1]); if (isNaN(this.targetparam2)) this.targetparam2 = this.targetparam1; } TweenObject.prototype.OnTick = function(dt) { if (this.state === 0) return -1.0; if (this.state === 1) this.progress += dt; if (this.state === 2) this.progress -= dt; if (this.state === 3) { this.state = 0; } if ((this.state === 4) || (this.state === 6)) { this.progress += dt * this.pingpong; } if (this.state === 5) { this.progress += dt * this.pingpong; } if (this.progress < 0) { this.progress = 0; if (this.state === 4) { this.pingpong = 1; } else if (this.state === 6) { this.pingpong = 1; this.flipEase = false; } else { this.state = 0; } this.onReverseEnd = true; return 0.0; } else if (this.progress > this.duration) { this.progress = this.duration; if (this.state === 4) { this.pingpong = -1; } else if (this.state === 6) { this.pingpong = -1; this.flipEase = true; } else if (this.state === 5) { this.progress = 0.0; } else { this.state = 0; } this.onEnd = true; return 1.0; } else { if (this.flipEase) { var factor = easeFunc(this.easefunc, this.duration - this.progress, 0, 1, this.duration, this.flipEase, this.easingparam[this.easefunc]); } else { var factor = easeFunc(this.easefunc, this.progress, 0, 1, this.duration, this.flipEase, this.easingparam[this.easefunc]); } return factor; } }; }()); ; ; function trim (str) { return str.replace(/^\s\s*/, '').replace(/\s\s*$/, ''); } cr.behaviors.lunarray_LiteTween = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.lunarray_LiteTween.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; this.i = 0; // progress }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.playmode = this.properties[0]; this.active = (this.playmode == 1) || (this.playmode == 2) || (this.playmode == 3) || (this.playmode == 4); this.tweened = this.properties[1]; // 0=Position|1=Size|2=Width|3=Height|4=Angle|5=Opacity|6=Value only|7=Horizontal|8=Vertical|9=Scale this.easing = this.properties[2]; this.target = this.properties[3]; this.targetmode = this.properties[4]; this.useCurrent = false; if (this.targetmode === 1) this.target = "relative("+this.target+")"; this.duration = this.properties[5]; this.enforce = (this.properties[6] === 1); this.value = 0; this.tween_list = {}; this.addToTweenList("default", this.tweened, this.easing, "current", this.target, this.duration, this.enforce); if (this.properties[0] === 1) this.startTween(0) if (this.properties[0] === 2) this.startTween(2) if (this.properties[0] === 3) this.startTween(3) if (this.properties[0] === 4) this.startTween(4) }; behinstProto.parseCurrent = function(tweened, parseText) { if (parseText === undefined) parseText = "current"; var parsed = trim(parseText); parseText = trim(parseText); var value = this.value; if (parseText === "current") { switch (tweened) { case 0: parsed = this.inst.x + "," + this.inst.y; break; case 1: parsed = this.inst.width + "," + this.inst.height; break; case 2: parsed = this.inst.width + "," + this.inst.height; break; case 3: parsed = this.inst.width + "," + this.inst.height; break; case 4: parsed = cr.to_degrees(this.inst.angle) + "," + cr.to_degrees(this.inst.angle); break; case 5: parsed = (this.inst.opacity*100) + "," + (this.inst.opacity*100); break; case 6: parsed = value + "," + value; break; case 7: parsed = this.inst.x + "," + this.inst.y; break; case 8: parsed = this.inst.x + "," + this.inst.y; break; case 9: if (this.inst.curFrame !== undefined) parsed = (this.inst.width/this.inst.curFrame.width) + "," +(this.inst.height/this.inst.curFrame.height) else parsed = "1,1"; break; default: break; } } if (parseText.substring(0,8) === "relative") { var param1 = parseText.match(/\((.*?)\)/); if (param1) { var relativex = parseFloat(param1[1].split(",")[0]); var relativey = parseFloat(param1[1].split(",")[1]); } if (isNaN(relativex)) relativex = 0; if (isNaN(relativey)) relativey = 0; switch (tweened) { case 0: parsed = (this.inst.x+relativex) + "," + (this.inst.y+relativey); break; case 1: parsed = (this.inst.width+relativex) + "," + (this.inst.height+relativey); break; case 2: parsed = (this.inst.width+relativex) + "," + (this.inst.height+relativey); break; case 3: parsed = (this.inst.width+relativex) + "," + (this.inst.height+relativey); break; case 4: parsed = (cr.to_degrees(this.inst.angle)+relativex) + "," + (cr.to_degrees(this.inst.angle)+relativey); break; case 5: parsed = (this.inst.opacity*100+relativex) + "," + (this.inst.opacity*100+relativey); break; case 6: parsed = value+relativex + "," + value+relativex; break; case 7: parsed = (this.inst.x+relativex) + "," + (this.inst.y); break; case 8: parsed = (this.inst.x) + "," + (this.inst.y+relativex); break; case 9: parsed = (relativex) + "," + (relativey); break; default: break; } } return parsed; }; behinstProto.addToTweenList = function(tname, tweened, easing, init, targ, duration, enforce) { init = this.parseCurrent(tweened, init); targ = this.parseCurrent(tweened, targ); if (this.tween_list[tname] !== undefined) { delete this.tween_list[tname] } this.tween_list[tname] = new TweenObject(tname, tweened, easing, init, targ, duration, enforce); this.tween_list[tname].dt = 0; }; behinstProto.saveToJSON = function () { var v = JSON.stringify(this.tween_list["default"]); return { "playmode": this.playmode, "active": this.active, "tweened": this.tweened, "easing": this.easing, "target": this.target, "targetmode": this.targetmode, "useCurrent": this.useCurrent, "duration": this.duration, "enforce": this.enforce, "value": this.value, "tweenlist": JSON.stringify(this.tween_list["default"]) }; }; TweenObject.Load = function(rawObj, tname, tweened, easing, init, targ, duration, enforce) { var obj = new TweenObject(tname, tweened, easing, init, targ, duration, enforce); for(var i in rawObj) obj[i] = rawObj[i]; return obj; }; behinstProto.loadFromJSON = function (o) { var x = JSON.parse(o["tweenlist"]); var tempObj = TweenObject.Load(x, x.name, x.tweened, x.easefunc, x.initialparam1+","+x.initialparam2, x.targetparam1+","+x.targetparam2, x.duration, x.enforce); this.tween_list["default"] = tempObj; this.playmode = o["playmode"]; this.active = o["active"]; this.movement = o["tweened"]; this.easing = o["easing"]; this.target = o["target"]; this.targetmode = o["targetmode"]; this.useCurrent = o["useCurrent"]; this.duration = o["duration"]; this.enforce = o["enforce"]; this.value = o["value"]; }; behinstProto.setProgressTo = function (mark) { if (mark > 1.0) mark = 1.0; if (mark < 0.0) mark = 0.0; for (var i in this.tween_list) { var inst = this.tween_list[i]; inst.lastKnownValue = 0; inst.lastKnownValue2 = 0; inst.state = 3; inst.progress = mark * inst.duration; var factor = inst.OnTick(0); this.updateTween(inst, factor); } } behinstProto.startTween = function (startMode) { for (var i in this.tween_list) { var inst = this.tween_list[i]; if (this.useCurrent) { var init = this.parseCurrent(inst.tweened, "current"); var target = this.parseCurrent(inst.tweened, this.target); inst.setInitial(init); inst.setTarget(target); } if (startMode === 0) { inst.progress = 0.000001; inst.lastKnownValue = 0; inst.lastKnownValue2 = 0; inst.onStart = true; inst.state = 1; } if (startMode === 1) { inst.state = inst.lastState; } if ((startMode === 2) || (startMode === 4)) { inst.progress = 0.000001; inst.lastKnownValue = 0; inst.lastKnownValue2 = 0; inst.onStart = true; if (startMode == 2) inst.state = 4; //state ping pong if (startMode == 4) inst.state = 6; //state flip flop } if (startMode === 3) { inst.progress = 0.000001; inst.lastKnownValue = 0; inst.lastKnownValue2 = 0; inst.onStart = true; inst.state = 5; } } } behinstProto.stopTween = function (stopMode) { for (var i in this.tween_list) { var inst = this.tween_list[i]; if ((inst.state != 3) && (inst.state != 0)) //don't save paused/seek state inst.lastState = inst.state; if (stopMode === 1) inst.progress = 0.0; if (stopMode === 2) inst.progress = inst.duration; inst.state = 3; var factor = inst.OnTick(0); this.updateTween(inst, factor); } } behinstProto.reverseTween = function(reverseMode) { for (var i in this.tween_list) { var inst = this.tween_list[i]; if (reverseMode === 1) { inst.progress = inst.duration; inst.lastKnownValue = 0; inst.lastKnownValue2 = 0; inst.onReverseStart = true; } inst.state = 2; } } behinstProto.updateTween = function (inst, factor) { if (inst.tweened === 0) { if (inst.enforce) { this.inst.x = inst.initialparam1 + (inst.targetparam1 - inst.initialparam1) * factor; this.inst.y = inst.initialparam2 + (inst.targetparam2 - inst.initialparam2) * factor; } else { this.inst.x += ((inst.targetparam1 - inst.initialparam1) * factor) - inst.lastKnownValue; this.inst.y += ((inst.targetparam2 - inst.initialparam2) * factor) - inst.lastKnownValue2; inst.lastKnownValue = ((inst.targetparam1 - inst.initialparam1) * factor); inst.lastKnownValue2 = ((inst.targetparam2 - inst.initialparam2) * factor); } } else if (inst.tweened === 1) { if (inst.enforce) { this.inst.width = (inst.initialparam1 + ((inst.targetparam1 - inst.initialparam1) * (factor))); this.inst.height = (inst.initialparam2 + ((inst.targetparam2 - inst.initialparam2) * (factor))); } else { this.inst.width += ((inst.targetparam1 - inst.initialparam1) * factor) - inst.lastKnownValue; this.inst.height += ((inst.targetparam2 - inst.initialparam2) * factor) - inst.lastKnownValue2; inst.lastKnownValue = ((inst.targetparam1 - inst.initialparam1) * factor); inst.lastKnownValue2 = ((inst.targetparam2 - inst.initialparam2) * factor); } } else if (inst.tweened === 2) { if (inst.enforce) { this.inst.width = (inst.initialparam1 + ((inst.targetparam1 - inst.initialparam1) * (factor))); } else { this.inst.width += ((inst.targetparam1 - inst.initialparam1) * factor) - inst.lastKnownValue; inst.lastKnownValue = ((inst.targetparam1 - inst.initialparam1) * factor); } } else if (inst.tweened === 3) { if (inst.enforce) { this.inst.height = (inst.initialparam2 + ((inst.targetparam2 - inst.initialparam2) * (factor))); } else { this.inst.height += ((inst.targetparam2 - inst.initialparam2) * factor) - inst.lastKnownValue2; inst.lastKnownValue2 = ((inst.targetparam2 - inst.initialparam2) * factor); } } else if (inst.tweened === 4) { if (inst.enforce) { var tangle = inst.initialparam1 + (inst.targetparam1 - inst.initialparam1) * factor; this.inst.angle = cr.clamp_angle(cr.to_radians(tangle)); } else { var tangle = ((inst.targetparam1 - inst.initialparam1) * factor) - inst.lastKnownValue; this.inst.angle = cr.clamp_angle(this.inst.angle + cr.to_radians(tangle)); inst.lastKnownValue = (inst.targetparam1 - inst.initialparam1) * factor; } } else if (inst.tweened === 5) { if (inst.enforce) { this.inst.opacity = (inst.initialparam1 + (inst.targetparam1 - inst.initialparam1) * factor) / 100; } else { this.inst.opacity += (((inst.targetparam1 - inst.initialparam1) * factor) - inst.lastKnownValue) / 100; inst.lastKnownValue = ((inst.targetparam1 - inst.initialparam1) * factor); } } else if (inst.tweened === 6) { if (inst.enforce) { this.value = (inst.initialparam1 + (inst.targetparam1 - inst.initialparam1) * factor); } else { this.value += (((inst.targetparam1 - inst.initialparam1) * factor) - inst.lastKnownValue); inst.lastKnownValue = ((inst.targetparam1 - inst.initialparam1) * factor); } } else if (inst.tweened === 7) { if (inst.enforce) { this.inst.x = inst.initialparam1 + (inst.targetparam1 - inst.initialparam1) * factor; } else { this.inst.x += ((inst.targetparam1 - inst.initialparam1) * factor) - inst.lastKnownValue; inst.lastKnownValue = ((inst.targetparam1 - inst.initialparam1) * factor); } } else if (inst.tweened === 8) { if (inst.enforce) { this.inst.y = inst.initialparam2 + (inst.targetparam2 - inst.initialparam2) * factor; } else { this.inst.y += ((inst.targetparam2 - inst.initialparam2) * factor) - inst.lastKnownValue2; inst.lastKnownValue2 = ((inst.targetparam2 - inst.initialparam2) * factor); } } else if (inst.tweened === 9) { var scalex = inst.initialparam1 + (inst.targetparam1 - inst.initialparam1) * factor; var scaley = inst.initialparam2 + (inst.targetparam2 - inst.initialparam2) * factor; if (this.inst.width < 0) scalex = inst.initialparam1 + (inst.targetparam1 + inst.initialparam1) * -factor; if (this.inst.height < 0) scaley = inst.initialparam2 + (inst.targetparam2 + inst.initialparam2) * -factor; if (inst.enforce) { this.inst.width = this.inst.curFrame.width * scalex; this.inst.height = this.inst.curFrame.height * scaley; } else { if (this.inst.width < 0) { this.inst.width = scalex * (this.inst.width / (-1+inst.lastKnownValue)); inst.lastKnownValue = scalex + 1 } else { this.inst.width = scalex * (this.inst.width / (1+inst.lastKnownValue)); inst.lastKnownValue = scalex - 1; } if (this.inst.height < 0) { this.inst.height = scaley * (this.inst.height / (-1+inst.lastKnownValue2)); inst.lastKnownValue2 = scaley + 1 } else { this.inst.height = scaley * (this.inst.height / (1+inst.lastKnownValue2)); inst.lastKnownValue2 = scaley - 1; } } } this.inst.set_bbox_changed(); } behinstProto.tick = function () { var dt = this.runtime.getDt(this.inst); var inst = this.tween_list["default"]; if (inst.state !== 0) { if (inst.onStart) { this.runtime.trigger(cr.behaviors.lunarray_LiteTween.prototype.cnds.OnStart, this.inst); inst.onStart = false; } if (inst.onReverseStart) { this.runtime.trigger(cr.behaviors.lunarray_LiteTween.prototype.cnds.OnReverseStart, this.inst); inst.onReverseStart = false; } this.active = (inst.state == 1) || (inst.state == 2) || (inst.state == 4) || (inst.state == 5) || (inst.state == 6); var factor = inst.OnTick(dt); this.updateTween(inst, factor); if (inst.onEnd) { this.runtime.trigger(cr.behaviors.lunarray_LiteTween.prototype.cnds.OnEnd, this.inst); inst.onEnd = false; } if (inst.onReverseEnd) { this.runtime.trigger(cr.behaviors.lunarray_LiteTween.prototype.cnds.OnReverseEnd, this.inst); inst.onReverseEnd = false; } } }; behaviorProto.cnds = {}; var cnds = behaviorProto.cnds; cnds.IsActive = function () { return (this.tween_list["default"].state !== 0); }; cnds.IsReversing = function () { return (this.tween_list["default"].state == 2); }; cnds.CompareProgress = function (cmp, v) { var inst = this.tween_list["default"]; return cr.do_cmp((inst.progress / inst.duration), cmp, v); }; cnds.OnThreshold = function (cmp, v) { var inst = this.tween_list["default"]; this.threshold = (cr.do_cmp((inst.progress / inst.duration), cmp, v)); var ret = (this.oldthreshold != this.threshold) && (this.threshold); if (ret) { this.oldthreshold = this.threshold; } return ret; }; cnds.OnStart = function () { if (this.tween_list["default"] === undefined) return false; return this.tween_list["default"].onStart; }; cnds.OnReverseStart = function () { if (this.tween_list["default"] === undefined) return false; return this.tween_list["default"].onReverseStart; }; cnds.OnEnd = function () { if (this.tween_list["default"] === undefined) return false; return this.tween_list["default"].onEnd; }; cnds.OnReverseEnd = function () { if (this.tween_list["default"] === undefined) return false; return this.tween_list["default"].onReverseEnd; }; behaviorProto.acts = {}; var acts = behaviorProto.acts; acts.Start = function (startmode, current) { this.threshold = false; this.oldthreshold = false; this.useCurrent = (current == 1); this.startTween(startmode); }; acts.Stop = function (stopmode) { this.stopTween(stopmode); }; acts.Reverse = function (revMode) { this.threshold = false; this.oldthreshold = false; this.reverseTween(revMode); }; acts.ProgressTo = function (progress) { this.setProgressTo(progress); }; acts.SetDuration = function (x) { if (isNaN(x)) return; if (x < 0) return; if (this.tween_list["default"] === undefined) return; this.tween_list["default"].duration = x; }; acts.SetEnforce = function (x) { if (this.tween_list["default"] === undefined) return; this.tween_list["default"].enforce = (x===1); }; acts.SetInitial = function (x) { if (this.tween_list["default"] === undefined) return; var init = this.parseCurrent(this.tween_list["default"].tweened, x); this.tween_list["default"].setInitial(init); }; acts.SetTarget = function (targettype, absrel, x) { if (this.tween_list["default"] === undefined) return; if (isNaN(x)) return; var inst = this.tween_list["default"]; var parsed = x + ""; this.targetmode = absrel; var x1 = ""; var x2 = ""; if (absrel === 1) { this.target = "relative(" + parsed + ")"; switch (targettype) { case 0: x1 = (this.inst.x + x); x2 = inst.targetparam2; break; case 1: x1 = inst.targetparam1; x2 = (this.inst.y + x); break; case 2: x1 = "" + cr.to_degrees(this.inst.angle + cr.to_radians(x)); x2 = x1; break; //angle case 3: x1 = "" + (this.inst.opacity*100) + x; x2 = x1; break; //opacity case 4: x1 = (this.inst.width + x); x2 = inst.targetparam2; break; //width case 5: x1 = inst.targetparam1; x2 = (this.inst.height + x); break; //height case 6: x1 = x; x2 = x; break; //value default: break; } parsed = x1 + "," + x2; } else { switch (targettype) { case 0: x1 = x; x2 = inst.targetparam2; break; case 1: x1 = inst.targetparam1; x2 = x; break; case 2: x1 = x; x2 = x; break; //angle case 3: x1 = x; x2 = x; break; //opacity case 4: x1 = x; x2 = inst.targetparam2; break; //width case 5: x1 = inst.targetparam1; x2 = x; break; //height case 6: x1 = x; x2 = x; break; //value default: break; } parsed = x1 + "," + x2; this.target = parsed; } var init = this.parseCurrent(this.tween_list["default"].tweened, "current"); var targ = this.parseCurrent(this.tween_list["default"].tweened, parsed); inst.setInitial(init); inst.setTarget(targ); }; acts.SetTweenedProperty = function (x) { if (this.tween_list["default"] === undefined) return; this.tween_list["default"].tweened = x; }; acts.SetEasing = function (x) { if (this.tween_list["default"] === undefined) return; this.tween_list["default"].easefunc = x; }; acts.SetEasingParam = function (x, a, p, t, s) { if (this.tween_list["default"] === undefined) return; this.tween_list["default"].easingparam[x].optimized = false; this.tween_list["default"].easingparam[x].a = a; this.tween_list["default"].easingparam[x].p = p; this.tween_list["default"].easingparam[x].t = t; this.tween_list["default"].easingparam[x].s = s; }; acts.ResetEasingParam = function () { if (this.tween_list["default"] === undefined) return; this.tween_list["default"].optimized = true; }; acts.SetValue = function (x) { var inst = this.tween_list["default"]; this.value = x; if (inst.tweened === 6) inst.setInitial( this.parseCurrent(inst.tweened, "current") ); }; acts.SetParameter = function (tweened, easefunction, target, duration, enforce) { if (this.tween_list["default"] === undefined) { this.addToTweenList("default", tweened, easefunction, initial, target, duration, enforce, 0); } else { var inst = this.tween_list["default"]; inst.tweened = tweened; inst.easefunc = easefunction; inst.setInitial( this.parseCurrent(tweened, "current") ); inst.setTarget( this.parseCurrent(tweened, target) ); inst.duration = duration; inst.enforce = (enforce === 1); } }; behaviorProto.exps = {}; var exps = behaviorProto.exps; exps.State = function (ret) { var parsed = "N/A"; switch (this.tween_list["default"].state) { case 0: parsed = "paused"; break; case 1: parsed = "playing"; break; case 2: parsed = "reversing"; break; case 3: parsed = "seeking"; break; default: break; } ret.set_string(parsed); }; exps.Progress = function (ret) { var progress = this.tween_list["default"].progress/this.tween_list["default"].duration; ret.set_float(progress); }; exps.Duration = function (ret) { ret.set_float(this.tween_list["default"].duration); }; exps.Target = function (ret) { var inst = this.tween_list["default"]; var parsed = "N/A"; switch (inst.tweened) { case 0: parsed = inst.targetparam1; break; case 1: parsed = inst.targetparam2; break; case 2: parsed = inst.targetparam1; break; case 3: parsed = inst.targetparam1; break; case 4: parsed = inst.targetparam1; break; case 5: parsed = inst.targetparam2; break; case 6: parsed = inst.targetparam1; break; default: break; } ret.set_float(parsed); }; exps.Value = function (ret) { var tval = this.value; ret.set_float(tval); }; exps.Tween = function (ret, a_, b_, x_, easefunc_) { var currX = (x_>1.0?1.0:x_); var factor = easeFunc(easefunc_, currX<0.0?0.0:currX, 0.0, 1.0, 1.0, false, false); ret.set_float(a_ + factor * (b_-a_)); }; }()); ; ; cr.behaviors.scrollto = function(runtime) { this.runtime = runtime; this.shakeMag = 0; this.shakeStart = 0; this.shakeEnd = 0; this.shakeMode = 0; }; (function () { var behaviorProto = cr.behaviors.scrollto.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.enabled = (this.properties[0] !== 0); }; behinstProto.saveToJSON = function () { return { "smg": this.behavior.shakeMag, "ss": this.behavior.shakeStart, "se": this.behavior.shakeEnd, "smd": this.behavior.shakeMode }; }; behinstProto.loadFromJSON = function (o) { this.behavior.shakeMag = o["smg"]; this.behavior.shakeStart = o["ss"]; this.behavior.shakeEnd = o["se"]; this.behavior.shakeMode = o["smd"]; }; behinstProto.tick = function () { }; function getScrollToBehavior(inst) { var i, len, binst; for (i = 0, len = inst.behavior_insts.length; i < len; ++i) { binst = inst.behavior_insts[i]; if (binst.behavior instanceof cr.behaviors.scrollto) return binst; } return null; }; behinstProto.tick2 = function () { if (!this.enabled) return; var all = this.behavior.my_instances.valuesRef(); var sumx = 0, sumy = 0; var i, len, binst, count = 0; for (i = 0, len = all.length; i < len; i++) { binst = getScrollToBehavior(all[i]); if (!binst || !binst.enabled) continue; sumx += all[i].x; sumy += all[i].y; ++count; } var layout = this.inst.layer.layout; var now = this.runtime.kahanTime.sum; var offx = 0, offy = 0; if (now >= this.behavior.shakeStart && now < this.behavior.shakeEnd) { var mag = this.behavior.shakeMag * Math.min(this.runtime.timescale, 1); if (this.behavior.shakeMode === 0) mag *= 1 - (now - this.behavior.shakeStart) / (this.behavior.shakeEnd - this.behavior.shakeStart); var a = Math.random() * Math.PI * 2; var d = Math.random() * mag; offx = Math.cos(a) * d; offy = Math.sin(a) * d; } layout.scrollToX(sumx / count + offx); layout.scrollToY(sumy / count + offy); }; function Acts() {}; Acts.prototype.Shake = function (mag, dur, mode) { this.behavior.shakeMag = mag; this.behavior.shakeStart = this.runtime.kahanTime.sum; this.behavior.shakeEnd = this.behavior.shakeStart + dur; this.behavior.shakeMode = mode; }; Acts.prototype.SetEnabled = function (e) { this.enabled = (e !== 0); }; behaviorProto.acts = new Acts(); }()); ; ; cr.behaviors.solid = function(runtime) { this.runtime = runtime; }; (function () { var behaviorProto = cr.behaviors.solid.prototype; behaviorProto.Type = function(behavior, objtype) { this.behavior = behavior; this.objtype = objtype; this.runtime = behavior.runtime; }; var behtypeProto = behaviorProto.Type.prototype; behtypeProto.onCreate = function() { }; behaviorProto.Instance = function(type, inst) { this.type = type; this.behavior = type.behavior; this.inst = inst; // associated object instance to modify this.runtime = type.runtime; }; var behinstProto = behaviorProto.Instance.prototype; behinstProto.onCreate = function() { this.inst.extra["solidEnabled"] = (this.properties[0] !== 0); }; behinstProto.tick = function () { }; function Cnds() {}; Cnds.prototype.IsEnabled = function () { return this.inst.extra["solidEnabled"]; }; behaviorProto.cnds = new Cnds(); function Acts() {}; Acts.prototype.SetEnabled = function (e) { this.inst.extra["solidEnabled"] = !!e; }; behaviorProto.acts = new Acts(); }()); cr.getObjectRefTable = function () { return [ cr.plugins_.NinePatch, cr.plugins_.aekiro_proui2, cr.plugins_.AJAX, cr.plugins_.Audio, cr.plugins_.Arr, cr.plugins_.Browser, cr.plugins_.CBhash, cr.plugins_.GameAnalytics, cr.plugins_.CSS_import, cr.plugins_.Function, cr.plugins_.LocalStorage, cr.plugins_.Keyboard, cr.plugins_.Globals, cr.plugins_.MM_Preloader, cr.plugins_.MM_Debugger, cr.plugins_.MoMod, cr.plugins_.MM_Unloader, cr.plugins_.NSG_NicknamesDB, cr.plugins_.Mouse, cr.plugins_.NSG_MobilePopup, cr.plugins_.NSG_DataBag, cr.plugins_.NSG_WebAdsProCPMStar, cr.plugins_.NSG_ObjectJS, cr.plugins_.NSG_PowerWS, cr.plugins_.NSG_WebAdsProCrazyGames, cr.plugins_.NSG_WebAdsProAIP, cr.plugins_.NSG_Referrer, cr.plugins_.NSG_WebAdsPro_Banner, cr.plugins_.Particles, cr.plugins_.NSG_WebAdsPro, cr.plugins_.rex_bbcodeText, cr.plugins_.Rex_EventBalancer, cr.plugins_.Sprite, cr.plugins_.SpriteFontPlus, cr.plugins_.SyncStorage, cr.plugins_.Touch, cr.plugins_.TiledBg, cr.plugins_.TR_DateTime, cr.plugins_.TR_ClockParser, cr.plugins_.TR_CrossPromo, cr.plugins_.TR_HtmlText, cr.plugins_.TextBox, cr.plugins_.Text, cr.plugins_.TR_Leaderboard, cr.behaviors.Sin, cr.behaviors.lunarray_LiteTween, cr.behaviors.Pin, cr.behaviors.Anchor, cr.behaviors.solid, cr.behaviors.Bullet, cr.behaviors.Fade, cr.behaviors.aekiro_progress, cr.behaviors.destroy, cr.behaviors.scrollto, cr.behaviors.TR_Scale, cr.behaviors.Rex_RotateTo, cr.behaviors.Timer, cr.behaviors.bound, cr.behaviors.Rex_pinOffsetXY, cr.behaviors.NSG_TrueTimer, cr.behaviors.TR_Level, cr.system_object.prototype.cnds.IsGroupActive, cr.system_object.prototype.cnds.OnLayoutStart, cr.plugins_.Globals.prototype.acts.SetInstanceVar, cr.system_object.prototype.exps.layoutwidth, cr.system_object.prototype.exps.layoutheight, cr.plugins_.Globals.prototype.acts.SetBoolInstanceVar, cr.system_object.prototype.acts.SetLayerVisible, cr.system_object.prototype.acts.SetLayerOpacity, cr.system_object.prototype.acts.SetGroupActive, cr.plugins_.MM_Preloader.prototype.acts.AddItem, cr.plugins_.MM_Preloader.prototype.acts.StabilizerSetState, cr.plugins_.MM_Preloader.prototype.acts.Start, cr.plugins_.Sprite.prototype.acts.SetPos, cr.plugins_.Function.prototype.acts.CallFunction, cr.plugins_.MoMod.prototype.acts.StartUpModule, cr.behaviors.aekiro_progress.prototype.acts.setValue, cr.system_object.prototype.cnds.IsMobile, cr.plugins_.TiledBg.prototype.cnds.IsOnLayer, cr.plugins_.TiledBg.prototype.acts.SetPos, cr.system_object.prototype.exps.viewportleft, cr.system_object.prototype.exps.viewporttop, cr.plugins_.TiledBg.prototype.acts.SetSize, cr.system_object.prototype.exps.viewportright, cr.system_object.prototype.exps.viewportbottom, cr.plugins_.TR_DateTime.prototype.cnds.IsActive, cr.plugins_.NSG_NicknamesDB.prototype.acts.ReleaseAll, cr.plugins_.TR_DateTime.prototype.acts.StartTimer, cr.plugins_.Globals.prototype.acts.AddInstanceVar, cr.plugins_.GameAnalytics.prototype.acts.addDesignEventWithValue, cr.system_object.prototype.cnds.For, cr.system_object.prototype.acts.Wait, cr.plugins_.MM_Preloader.prototype.acts.SetItemState, cr.plugins_.MM_Preloader.prototype.cnds.OnProgress, cr.plugins_.MM_Preloader.prototype.exps.Progress, cr.plugins_.SpriteFontPlus.prototype.cnds.CompareInstanceVar, cr.plugins_.SpriteFontPlus.prototype.acts.SetText, cr.system_object.prototype.exps.round, cr.system_object.prototype.exps.min, cr.plugins_.MM_Preloader.prototype.cnds.OnCompleted, cr.plugins_.Globals.prototype.cnds.IsBoolInstanceVarSet, cr.plugins_.Audio.prototype.acts.Play, cr.behaviors.Pin.prototype.acts.Pin, cr.behaviors.Anchor.prototype.acts.SetEnabled, cr.system_object.prototype.cnds.LayerVisible, cr.plugins_.Function.prototype.cnds.OnFunction, cr.system_object.prototype.cnds.ForEach, cr.plugins_.NSG_DataBag.prototype.acts.AddData, cr.system_object.prototype.exps.str, cr.plugins_.CSS_import.prototype.acts.SetCSS, cr.system_object.prototype.exps.projectversion, cr.plugins_.TR_HtmlText.prototype.acts.AddNewFamily, cr.plugins_.Browser.prototype.acts.ConsoleLog, cr.plugins_.MM_Preloader.prototype.acts.AddC2EngineProgress, cr.plugins_.SyncStorage.prototype.acts.LoadData, cr.plugins_.NSG_Referrer.prototype.cnds.Contains, cr.system_object.prototype.cnds.Else, cr.system_object.prototype.acts.SetVar, cr.plugins_.SyncStorage.prototype.cnds.OnLoadError, cr.plugins_.SyncStorage.prototype.cnds.OnLoaded, cr.plugins_.SyncStorage.prototype.cnds.HasData, cr.plugins_.Globals.prototype.acts.LoadVariables, cr.plugins_.SyncStorage.prototype.exps.Get, cr.plugins_.SyncStorage.prototype.acts.SetData, cr.plugins_.Globals.prototype.exps.GetVariablesAsJSON, cr.plugins_.SyncStorage.prototype.cnds.CompareData, cr.system_object.prototype.cnds.CompareVar, cr.plugins_.TR_DateTime.prototype.exps.Timestamp, cr.plugins_.MoMod.prototype.cnds.OnCustomModuleEvent, cr.plugins_.SyncStorage.prototype.acts.SaveData, cr.plugins_.NSG_WebAdsPro.prototype.acts.Initialize, cr.system_object.prototype.cnds.IsPreview, cr.plugins_.GameAnalytics.prototype.acts.configureBuild, cr.plugins_.GameAnalytics.prototype.acts.initialize, cr.plugins_.Globals.prototype.cnds.CompareInstanceVar, cr.plugins_.Sprite.prototype.acts.SetVisible, cr.plugins_.SpriteFontPlus.prototype.acts.SetVisible, cr.system_object.prototype.acts.GoToLayout, cr.plugins_.Touch.prototype.cnds.OnTapGestureObject, cr.plugins_.Sprite.prototype.cnds.IsVisible, cr.plugins_.Browser.prototype.acts.RequestFullScreen, cr.plugins_.Browser.prototype.acts.ExecJs, cr.plugins_.NSG_WebAdsPro.prototype.cnds.IsGDPRPopupPreloaded, cr.system_object.prototype.cnds.TriggerOnce, cr.plugins_.NSG_WebAdsPro.prototype.acts.SetPrerollAdGlobalSettings, cr.plugins_.NSG_WebAdsPro.prototype.acts.SetBannerAdGlobalSettings, cr.plugins_.NSG_WebAdsPro.prototype.acts.SetRewardedAdGlobalSettings, cr.plugins_.NSG_NicknamesDB.prototype.acts.Load, cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingCompleted, cr.plugins_.NSG_NicknamesDB.prototype.cnds.OnLoadingFailed, cr.system_object.prototype.cnds.PickByComparison, cr.plugins_.TR_HtmlText.prototype.acts.SetText, cr.plugins_.Browser.prototype.exps.URL, cr.plugins_.NSG_WebAdsPro.prototype.cnds.IsAdblocked, cr.plugins_.GameAnalytics.prototype.acts.addDesignEvent, cr.plugins_.SyncStorage.prototype.acts.RemoveData, cr.plugins_.TextBox.prototype.acts.SetText, cr.system_object.prototype.exps.trim, cr.plugins_.Sprite.prototype.acts.SetAnimFrame, cr.plugins_.TR_HtmlText.prototype.cnds.CompareInstanceVar, cr.plugins_.TR_ClockParser.prototype.exps.HHMMSS, cr.plugins_.Globals.prototype.acts.ResetVariables, cr.plugins_.Audio.prototype.cnds.IsTagPlaying, cr.plugins_.Function.prototype.exps.Call, cr.plugins_.Arr.prototype.exps.Width, cr.plugins_.NSG_MobilePopup.prototype.cnds.IsActive, cr.plugins_.TextBox.prototype.acts.SetCSSStyle, cr.plugins_.TR_HtmlText.prototype.acts.SetVisible, cr.plugins_.Sprite.prototype.cnds.CompareInstanceVar, cr.plugins_.TiledBg.prototype.acts.MoveToLayer, cr.plugins_.TiledBg.prototype.acts.MoveToBottom, cr.plugins_.MM_Unloader.prototype.acts.DestroyLayer, cr.plugins_.TextBox.prototype.acts.SetVisible, cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollStart, cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnPrerollClosed, cr.plugins_.Audio.prototype.acts.SetMuted, cr.plugins_.Sprite.prototype.cnds.CompareFrame, cr.system_object.prototype.cnds.Compare, cr.plugins_.TR_DateTime.prototype.exps.TimerTimeLeft, cr.plugins_.NSG_WebAdsPro.prototype.acts.ShowPrerollAd, cr.plugins_.NSG_WebAdsPro.prototype.acts.ShowRewardedAd, cr.plugins_.Touch.prototype.cnds.OnTouchObject, cr.plugins_.Globals.prototype.acts.ToggleBoolInstanceVar, cr.plugins_.Audio.prototype.acts.Stop, cr.plugins_.SyncStorage.prototype.acts.SubtractValue, cr.plugins_.TextBox.prototype.exps.Text, cr.system_object.prototype.exps.left, cr.plugins_.Sprite.prototype.acts.Spawn, cr.plugins_.Sprite.prototype.exps.LayerName, cr.plugins_.Sprite.prototype.acts.SetY, cr.plugins_.Sprite.prototype.exps.Y, cr.plugins_.Sprite.prototype.acts.Destroy, cr.plugins_.SyncStorage.prototype.acts.AddValue, cr.behaviors.Sin.prototype.acts.SetPhase, cr.behaviors.Sin.prototype.acts.SetActive, cr.plugins_.NSG_WebAdsPro_Banner.prototype.acts.ShowBanner, cr.plugins_.TextBox.prototype.cnds.OnClicked, cr.plugins_.NSG_MobilePopup.prototype.cnds.OnClose, cr.plugins_.Browser.prototype.acts.GoToURLWindow, cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedSuccessful, cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedEmpty, cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnRewardedCanceled, cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupOpened, cr.plugins_.NSG_WebAdsPro.prototype.cnds.OnGDPRPopupClosed, cr.plugins_.Browser.prototype.exps.Domain, cr.plugins_.TR_CrossPromo.prototype.exps.MoreGamesURL, cr.plugins_.NSG_WebAdsPro.prototype.acts.ShowConsentToolSettings, cr.plugins_.Sprite.prototype.exps.PickedCount, cr.system_object.prototype.acts.CreateObject, cr.plugins_.Sprite.prototype.acts.SetInstanceVar, cr.plugins_.Sprite.prototype.acts.SetAngle, cr.plugins_.Sprite.prototype.acts.SetWidth, cr.plugins_.Sprite.prototype.acts.SetX, cr.plugins_.Function.prototype.exps.Param, cr.plugins_.Sprite.prototype.cnds.PickByUID, cr.plugins_.Sprite.prototype.exps.X, cr.plugins_.Sprite.prototype.exps.BBoxTop, cr.behaviors.Bullet.prototype.acts.SetAngleOfMotion, cr.system_object.prototype.exps.random, cr.behaviors.Bullet.prototype.acts.SetAcceleration, cr.plugins_.Text.prototype.acts.SetFontSize, cr.behaviors.TR_Level.prototype.exps.CurrentLevel, cr.plugins_.Text.prototype.acts.SetText, cr.behaviors.TR_Level.prototype.cnds.OnLevelChange, cr.plugins_.Text.prototype.cnds.CompareInstanceVar, cr.plugins_.Sprite.prototype.exps.UID, cr.system_object.prototype.exps.abs, cr.behaviors.TR_Level.prototype.exps.LevelChangeValue, cr.plugins_.Sprite.prototype.acts.AddInstanceVar, cr.plugins_.Arr.prototype.exps.At, cr.behaviors.TR_Scale.prototype.acts.SetScaleSelf, cr.behaviors.TR_Scale.prototype.exps.Self, cr.plugins_.Sprite.prototype.acts.SetScale, cr.behaviors.TR_Level.prototype.cnds.LevelCompare, cr.plugins_.Sprite.prototype.cnds.IsBoolInstanceVarSet, cr.behaviors.Bullet.prototype.acts.SetEnabled, cr.system_object.prototype.cnds.Repeat, cr.plugins_.Sprite.prototype.acts.SetAnim, cr.plugins_.Text.prototype.acts.SetSize, cr.plugins_.Text.prototype.exps.Width, cr.plugins_.Text.prototype.exps.Height, cr.behaviors.Rex_pinOffsetXY.prototype.acts.Pin, cr.plugins_.Text.prototype.acts.SetBoolInstanceVar, cr.system_object.prototype.cnds.Every, cr.plugins_.Text.prototype.cnds.IsBoolInstanceVarSet, cr.plugins_.Text.prototype.cnds.IsOnScreen, cr.plugins_.Text.prototype.exps.TextWidth, cr.plugins_.Text.prototype.exps.TextHeight, cr.behaviors.NSG_TrueTimer.prototype.cnds.OnTimer, cr.plugins_.Sprite.prototype.acts.SetOpacity, cr.behaviors.NSG_TrueTimer.prototype.cnds.IsActive, cr.behaviors.NSG_TrueTimer.prototype.exps.TimerAgePercent, cr.plugins_.Sprite.prototype.exps.Width, cr.behaviors.NSG_TrueTimer.prototype.acts.StartTimer, cr.plugins_.TR_ClockParser.prototype.exps.MMSS, cr.plugins_.Text.prototype.acts.SetFontColor, cr.system_object.prototype.exps.rgb, cr.system_object.prototype.acts.SetLayoutScale, cr.plugins_.MoMod.prototype.acts.SetSection, cr.system_object.prototype.exps.layoutscale, cr.system_object.prototype.exps.dt, cr.system_object.prototype.cnds.PickByEvaluate, cr.plugins_.Sprite.prototype.cnds.IsOverlapping, cr.system_object.prototype.acts.AddVar, cr.plugins_.Function.prototype.acts.SetReturnValue, cr.system_object.prototype.exps.loopindex, cr.plugins_.SpriteFontPlus.prototype.acts.Destroy, cr.behaviors.lunarray_LiteTween.prototype.cnds.IsActive, cr.plugins_.TR_HtmlText.prototype.exps.LayerName, cr.plugins_.SpriteFontPlus.prototype.exps.LayerName, cr.plugins_.Sprite.prototype.cnds.CompareOpacity, cr.system_object.prototype.acts.SubVar, cr.behaviors.lunarray_LiteTween.prototype.acts.SetTarget, cr.behaviors.lunarray_LiteTween.prototype.acts.Start, cr.system_object.prototype.cnds.PickAll, cr.behaviors.lunarray_LiteTween.prototype.acts.SetEasing, cr.behaviors.lunarray_LiteTween.prototype.acts.SetDuration, cr.behaviors.lunarray_LiteTween.prototype.acts.SetTweenedProperty, cr.system_object.prototype.exps.floor, cr.plugins_.Sprite.prototype.cnds.IsOnLayer, cr.plugins_.MoMod.prototype.acts.ShutdownModule, cr.plugins_.MoMod.prototype.exps.ThisModule, cr.plugins_.Arr.prototype.acts.Push, cr.plugins_.MoMod.prototype.acts.TriggerModuleEvent, cr.plugins_.TR_Leaderboard.prototype.acts.ClearLeaderboard, cr.plugins_.TR_Leaderboard.prototype.acts.SetPosition, cr.plugins_.Sprite.prototype.exps.BBoxLeft, cr.plugins_.TR_Leaderboard.prototype.acts.SetPositionColumn, cr.plugins_.TR_Leaderboard.prototype.acts.SetNameColumn, cr.plugins_.TR_Leaderboard.prototype.acts.SetScoreColumn, cr.plugins_.Text.prototype.cnds.OnCreated, cr.plugins_.TR_Leaderboard.prototype.cnds.HasNewData, cr.plugins_.TR_Leaderboard.prototype.acts.DrawLeaderboard, cr.behaviors.Pin.prototype.acts.Unpin, cr.plugins_.TR_Leaderboard.prototype.exps.GetX, cr.plugins_.TR_Leaderboard.prototype.exps.GetY, cr.plugins_.TR_Leaderboard.prototype.exps.GetIdByPosition, cr.plugins_.TR_Leaderboard.prototype.exps.GetScoreByPosition, cr.behaviors.TR_Level.prototype.acts.SetExperience, cr.plugins_.Sprite.prototype.exps.Height, cr.plugins_.TR_Leaderboard.prototype.exps.GetPosition, cr.plugins_.Sprite.prototype.acts.MoveToTop, cr.plugins_.Sprite.prototype.exps.Angle, cr.plugins_.Arr.prototype.acts.SetSize, cr.plugins_.rex_bbcodeText.prototype.cnds.IsOnLayer, cr.plugins_.rex_bbcodeText.prototype.acts.Destroy, cr.plugins_.Text.prototype.cnds.IsOnLayer, cr.plugins_.Text.prototype.acts.Destroy, cr.plugins_.NSG_PowerWS.prototype.cnds.OnEvent, cr.plugins_.NSG_ObjectJS.prototype.acts.Load, cr.plugins_.NSG_PowerWS.prototype.exps.DataAsJson, cr.plugins_.Arr.prototype.acts.SetXY, cr.plugins_.NSG_ObjectJS.prototype.exps.Get, cr.plugins_.TR_DateTime.prototype.cnds.OnTimer, cr.plugins_.TR_DateTime.prototype.acts.StopTimer, cr.plugins_.Arr.prototype.acts.Clear, cr.plugins_.Arr.prototype.cnds.CompareXY, cr.plugins_.Arr.prototype.acts.Sort, cr.plugins_.Arr.prototype.acts.Reverse, cr.plugins_.NSG_DataBag.prototype.acts.ClearAllBags, cr.system_object.prototype.exps.layoutname, cr.plugins_.NinePatch.prototype.exps.X, cr.plugins_.NinePatch.prototype.exps.Y, cr.plugins_.rex_bbcodeText.prototype.acts.SetFontFace, cr.plugins_.rex_bbcodeText.prototype.acts.SetText, cr.plugins_.NinePatch.prototype.exps.Width, cr.plugins_.Sprite.prototype.acts.SetSize, cr.plugins_.rex_bbcodeText.prototype.acts.SetFontColor, cr.plugins_.NSG_PowerWS.prototype.acts.SyncMovingObject, cr.plugins_.NSG_PowerWS.prototype.acts.SyncObjectInstanceVar, cr.plugins_.NSG_PowerWS.prototype.acts.SyncStaticObject, cr.plugins_.Sprite.prototype.exps.BBoxRight, cr.plugins_.SpriteFontPlus.prototype.acts.SetInstanceVar, cr.plugins_.NSG_PowerWS.prototype.exps.Ping, cr.plugins_.NSG_PowerWS.prototype.acts.SetMessage, cr.plugins_.NSG_PowerWS.prototype.acts.Send, cr.plugins_.NSG_ObjectJS.prototype.exps.DataAsJson, cr.plugins_.TR_Leaderboard.prototype.acts.RemoveEntry, cr.plugins_.Sprite.prototype.cnds.OnCreated, cr.plugins_.Sprite.prototype.acts.SetCollisions, cr.plugins_.Sprite.prototype.cnds.IsOnScreen, cr.plugins_.Particles.prototype.acts.SetSpraying, cr.plugins_.Particles.prototype.exps.UID, cr.plugins_.Text.prototype.acts.SetInstanceVar, cr.behaviors.TR_Level.prototype.acts.SetMaxLevel, cr.plugins_.Sprite.prototype.acts.ZMoveToObject, cr.plugins_.Audio.prototype.acts.SetListenerObject, cr.plugins_.Sprite.prototype.cnds.PickDistance, cr.system_object.prototype.exps.distance, cr.plugins_.Sprite.prototype.acts.SetBoolInstanceVar, cr.system_object.prototype.exps.angle, cr.plugins_.Mouse.prototype.exps.X, cr.plugins_.Mouse.prototype.exps.Y, cr.plugins_.NSG_PowerWS.prototype.acts.SendRaw, cr.plugins_.NSG_ObjectJS.prototype.cnds.HasData, cr.behaviors.TR_Level.prototype.cnds.OnExpChanged, cr.behaviors.TR_Level.prototype.exps.TotalExp, cr.behaviors.TR_Level.prototype.exps.LevelExpProgress, cr.behaviors.TR_Level.prototype.acts.AddExperience, cr.behaviors.TR_Level.prototype.exps.LevelExpPool, cr.behaviors.TR_Level.prototype.acts.SubtractExperience, cr.plugins_.NSG_PowerWS.prototype.cnds.OnInstanceVariableChanged, cr.plugins_.Sprite.prototype.acts.MoveAtAngle, cr.behaviors.lunarray_LiteTween.prototype.cnds.OnEnd, cr.behaviors.lunarray_LiteTween.prototype.acts.Stop, cr.plugins_.Audio.prototype.acts.PlayAtPosition, cr.behaviors.Rex_RotateTo.prototype.acts.SetActivated, cr.behaviors.Rex_RotateTo.prototype.acts.SetTargetAngle, cr.behaviors.Rex_RotateTo.prototype.cnds.OnHitTarget, cr.behaviors.Rex_RotateTo.prototype.acts.Stop, cr.plugins_.Particles.prototype.cnds.PickByUID, cr.plugins_.Sprite.prototype.exps.AnimationFrameCount, cr.plugins_.Sprite.prototype.cnds.OnAnimFinished, cr.plugins_.Sprite.prototype.cnds.OnDestroyed, cr.plugins_.Particles.prototype.acts.Destroy, cr.plugins_.TR_DateTime.prototype.exps.TimerAge, cr.system_object.prototype.exps.windowwidth, cr.system_object.prototype.exps.windowheight, cr.plugins_.Particles.prototype.acts.SetVisible, cr.plugins_.Text.prototype.acts.SetVisible, cr.plugins_.TR_Leaderboard.prototype.acts.SetEntry, cr.plugins_.TR_Leaderboard.prototype.acts.SetRequired, cr.plugins_.Sprite.prototype.cnds.CompareX, cr.plugins_.Sprite.prototype.cnds.CompareY, cr.plugins_.Touch.prototype.exps.TouchID, cr.plugins_.Touch.prototype.cnds.OnTouchEnd, cr.plugins_.Touch.prototype.exps.XForID, cr.plugins_.Touch.prototype.exps.YForID, cr.plugins_.Sprite.prototype.acts.SetPosToObject, cr.plugins_.Touch.prototype.cnds.IsTouchingObject, cr.plugins_.Mouse.prototype.cnds.OnClick, cr.plugins_.Mouse.prototype.cnds.OnRelease, cr.plugins_.Sprite.prototype.acts.SetTowardPosition, cr.plugins_.Mouse.prototype.cnds.IsOverObject, cr.system_object.prototype.cnds.While, cr.behaviors.Timer.prototype.acts.StartTimer, cr.plugins_.NSG_DataBag.prototype.cnds.IsBagEmpty, cr.plugins_.NSG_DataBag.prototype.exps.CutRandomData, cr.plugins_.NSG_NicknamesDB.prototype.exps.RandomNickname, cr.plugins_.Sprite.prototype.acts.MoveForward, cr.behaviors.Timer.prototype.cnds.OnTimer, cr.behaviors.Rex_RotateTo.prototype.acts.SetMaxSpeed, cr.plugins_.Sprite.prototype.cnds.OnCollision, cr.plugins_.MoMod.prototype.exps.Param, cr.system_object.prototype.cnds.PickRandom, cr.behaviors.Timer.prototype.acts.StopTimer, cr.plugins_.MoMod.prototype.acts.TriggerCustomModuleEvent, cr.plugins_.Rex_EventBalancer.prototype.cnds.IsProcessing, cr.plugins_.Sprite.prototype.exps.Count, cr.plugins_.Rex_EventBalancer.prototype.acts.Start, cr.plugins_.Rex_EventBalancer.prototype.cnds.OnProcessing, cr.plugins_.Rex_EventBalancer.prototype.acts.Stop, cr.plugins_.Keyboard.prototype.cnds.OnKey, cr.plugins_.Touch.prototype.cnds.OnTouchStart, cr.plugins_.Mouse.prototype.cnds.IsButtonDown, cr.plugins_.Sprite.prototype.acts.MoveToLayer, cr.plugins_.NSG_NicknamesDB.prototype.acts.Release, cr.plugins_.NSG_DataBag.prototype.acts.RemoveData, cr.system_object.prototype.exps.scrollx, cr.system_object.prototype.exps.scrolly, cr.plugins_.MoMod.prototype.cnds.OnModuleEvent, cr.system_object.prototype.exps["int"], cr.plugins_.NSG_PowerWS.prototype.acts.Close, cr.plugins_.TR_CrossPromo.prototype.acts.PickRandomBanner, cr.plugins_.TR_CrossPromo.prototype.cnds.OnBannerReady, cr.plugins_.Sprite.prototype.acts.LoadURL, cr.plugins_.TR_CrossPromo.prototype.exps.CurrentBannerIMG, cr.plugins_.TR_CrossPromo.prototype.acts.SmartRedirect, cr.plugins_.TR_CrossPromo.prototype.exps.CurrentBannerURL, cr.plugins_.Mouse.prototype.acts.SetCursor, cr.plugins_.NSG_PowerWS.prototype.cnds.IsOpen, cr.plugins_.Browser.prototype.exps.QueryParam, cr.plugins_.NSG_PowerWS.prototype.acts.Connect, cr.plugins_.NSG_PowerWS.prototype.cnds.OnOpened, cr.plugins_.NSG_PowerWS.prototype.acts.SendPing, cr.plugins_.NSG_PowerWS.prototype.cnds.OnPong, cr.system_object.prototype.cnds.CompareBetween, cr.plugins_.NSG_PowerWS.prototype.cnds.OnClosed, cr.plugins_.NSG_PowerWS.prototype.exps.CloseCode, cr.plugins_.NSG_PowerWS.prototype.exps.CloseReason, cr.plugins_.NSG_PowerWS.prototype.exps.ErrorMsg, cr.plugins_.NSG_PowerWS.prototype.cnds.OnError, cr.plugins_.TR_DateTime.prototype.exps.TriggersLeft ];};