42516 lines
1.2 MiB
Plaintext
42516 lines
1.2 MiB
Plaintext
// 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, "<default>");
|
|
;
|
|
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, "<point>");
|
|
;
|
|
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, "<earlyz>");
|
|
;
|
|
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, "<fill>");
|
|
;
|
|
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 === "<point>")
|
|
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 !== "<point>")
|
|
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 !== "<point>")
|
|
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("<p><a download='" + filename + "' href=\"data:application/json,"
|
|
+ encodeURIComponent(this.getAsJSON())
|
|
+ "\">Download link</a></p>");
|
|
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 !== "<preload>")
|
|
{
|
|
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, "<preload>", 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, "<preload>", 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;j<a.length;j++)g=a[j],g&&e(g.then)?g.then(d(j),c):f(j,g)})}var d=a.isArray,e=a.isFunction;b.all=c}),a("promise/asap",["exports"],function(a){"use strict";function b(){return function(){process.nextTick(e)}}function c(){var a=0,b=new i(e),c=document.createTextNode("");return b.observe(c,{characterData:!0}),function(){c.data=a=++a%2}}function d(){return function(){j.setTimeout(e,1)}}function e(){for(var a=0;a<k.length;a++){var b=k[a],c=b[0],d=b[1];c(d)}k=[]}function f(a,b){var c=k.push([a,b]);1===c&&g()}var g,h="undefined"!=typeof window?window:{},i=h.MutationObserver||h.WebKitMutationObserver,j="undefined"!=typeof global?global:void 0===this?window:this,k=[];g="undefined"!=typeof process&&"[object process]"==={}.toString.call(process)?b():i?c():d(),a.asap=f}),a("promise/config",["exports"],function(a){"use strict";function b(a,b){return 2!==arguments.length?c[a]:void(c[a]=b)}var c={instrument:!1};a.config=c,a.configure=b}),a("promise/polyfill",["./promise","./utils","exports"],function(a,b,c){"use strict";function d(){var a;a="undefined"!=typeof global?global:"undefined"!=typeof window&&window.document?window:self;var b="Promise"in a&&"resolve"in a.Promise&&"reject"in a.Promise&&"all"in a.Promise&&"race"in a.Promise&&function(){var b;return new a.Promise(function(a){b=a}),f(b)}();b||(a.Promise=e)}var e=a.Promise,f=b.isFunction;c.polyfill=d}),a("promise/promise",["./config","./utils","./all","./race","./resolve","./reject","./asap","exports"],function(a,b,c,d,e,f,g,h){"use strict";function i(a){if(!v(a))throw new TypeError("You must pass a resolver function as the first argument to the promise constructor");if(!(this instanceof i))throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this._subscribers=[],j(a,this)}function j(a,b){function c(a){o(b,a)}function d(a){q(b,a)}try{a(c,d)}catch(e){d(e)}}function k(a,b,c,d){var e,f,g,h,i=v(c);if(i)try{e=c(d),g=!0}catch(j){h=!0,f=j}else e=d,g=!0;n(b,e)||(i&&g?o(b,e):h?q(b,f):a===D?o(b,e):a===E&&q(b,e))}function l(a,b,c,d){var e=a._subscribers,f=e.length;e[f]=b,e[f+D]=c,e[f+E]=d}function m(a,b){for(var c,d,e=a._subscribers,f=a._detail,g=0;g<e.length;g+=3)c=e[g],d=e[g+b],k(b,c,d,f);a._subscribers=null}function n(a,b){var c,d=null;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(u(b)&&(d=b.then,v(d)))return d.call(b,function(d){return c?!0:(c=!0,void(b!==d?o(a,d):p(a,d)))},function(b){return c?!0:(c=!0,void q(a,b))}),!0}catch(e){return c?!0:(q(a,e),!0)}return!1}function o(a,b){a===b?p(a,b):n(a,b)||p(a,b)}function p(a,b){a._state===B&&(a._state=C,a._detail=b,t.async(r,a))}function q(a,b){a._state===B&&(a._state=C,a._detail=b,t.async(s,a))}function r(a){m(a,a._state=D)}function s(a){m(a,a._state=E)}var t=a.config,u=(a.configure,b.objectOrFunction),v=b.isFunction,w=(b.now,c.all),x=d.race,y=e.resolve,z=f.reject,A=g.asap;t.async=A;var B=void 0,C=0,D=1,E=2;i.prototype={constructor:i,_state:void 0,_detail:void 0,_subscribers:void 0,then:function(a,b){var c=this,d=new this.constructor(function(){});if(this._state){var e=arguments;t.async(function(){k(c._state,d,e[c._state-1],c._detail)})}else l(this,d,a,b);return d},"catch":function(a){return this.then(null,a)}},i.all=w,i.race=x,i.resolve=y,i.reject=z,h.Promise=i}),a("promise/race",["./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 race.");return new b(function(b,c){for(var d,e=0;e<a.length;e++)d=a[e],d&&"function"==typeof d.then?d.then(b,c):b(d)})}var d=a.isArray;b.race=c}),a("promise/reject",["exports"],function(a){"use strict";function b(a){var b=this;return new b(function(b,c){c(a)})}a.reject=b}),a("promise/resolve",["exports"],function(a){"use strict";function b(a){if(a&&"object"==typeof a&&a.constructor===this)return a;var b=this;return new b(function(b){b(a)})}a.resolve=b}),a("promise/utils",["exports"],function(a){"use strict";function b(a){return c(a)||"object"==typeof a&&null!==a}function c(a){return"function"==typeof a}function d(a){return"[object Array]"===Object.prototype.toString.call(a)}var e=Date.now||function(){return(new Date).getTime()};a.objectOrFunction=b,a.isFunction=c,a.isArray=d,a.now=e}),b("promise/polyfill").polyfill()}(),function(a,b){"object"==typeof exports&&"object"==typeof module?module.exports=b():"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?exports.localforage=b():a.localforage=b()}(this,function(){return function(a){function b(d){if(c[d])return c[d].exports;var e=c[d]={exports:{},id:d,loaded:!1};return a[d].call(e.exports,e,e.exports,b),e.loaded=!0,e.exports}var c={};return b.m=a,b.c=c,b.p="",b(0)}([function(a,b,c){"use strict";function d(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}b.__esModule=!0;var e=function(a){function b(a,b){a[b]=function(){var c=arguments;return a.ready().then(function(){return a[b].apply(a,c)})}}function e(){for(var a=1;a<arguments.length;a++){var b=arguments[a];if(b)for(var c in b)b.hasOwnProperty(c)&&(m(b[c])?arguments[0][c]=b[c].slice():arguments[0][c]=b[c])}return arguments[0]}function f(a){for(var b in h)if(h.hasOwnProperty(b)&&h[b]===a)return!0;return!1}var g={},h={INDEXEDDB:"asyncStorage",LOCALSTORAGE:"localStorageWrapper",WEBSQL:"webSQLStorage"},i=[h.INDEXEDDB,h.WEBSQL,h.LOCALSTORAGE],j=["clear","getItem","iterate","key","keys","length","removeItem","setItem"],k={description:"",driver:i.slice(),name:"localforage",size:4980736,storeName:"keyvaluepairs",version:1},l=function(a){var b={};return b[h.INDEXEDDB]=!!function(){try{var b=b||a.indexedDB||a.webkitIndexedDB||a.mozIndexedDB||a.OIndexedDB||a.msIndexedDB;return"undefined"!=typeof a.openDatabase&&a.navigator&&a.navigator.userAgent&&/Safari/.test(a.navigator.userAgent)&&!/Chrome/.test(a.navigator.userAgent)?!1:b&&"function"==typeof b.open&&"undefined"!=typeof a.IDBKeyRange}catch(c){return!1}}(),b[h.WEBSQL]=!!function(){try{return a.openDatabase}catch(b){return!1}}(),b[h.LOCALSTORAGE]=!!function(){try{return a.localStorage&&"setItem"in a.localStorage&&a.localStorage.setItem}catch(b){return!1}}(),b}(a),m=Array.isArray||function(a){return"[object Array]"===Object.prototype.toString.call(a)},n=function(){function a(b){d(this,a),this.INDEXEDDB=h.INDEXEDDB,this.LOCALSTORAGE=h.LOCALSTORAGE,this.WEBSQL=h.WEBSQL,this._defaultConfig=e({},k),this._config=e({},this._defaultConfig,b),this._driverSet=null,this._initDriver=null,this._ready=!1,this._dbInfo=null,this._wrapLibraryMethodsWithReady(),this.setDriver(this._config.driver)}return a.prototype.config=function(a){if("object"==typeof a){if(this._ready)return new Error("Can't call config() after localforage has been used.");for(var b in a)"storeName"===b&&(a[b]=a[b].replace(/\W/g,"_")),this._config[b]=a[b];return"driver"in a&&a.driver&&this.setDriver(this._config.driver),!0}return"string"==typeof a?this._config[a]:this._config},a.prototype.defineDriver=function(a,b,c){var d=new Promise(function(b,c){try{var d=a._driver,e=new Error("Custom driver not compliant; see https://mozilla.github.io/localForage/#definedriver"),h=new Error("Custom driver name already in use: "+a._driver);if(!a._driver)return void c(e);if(f(a._driver))return void c(h);for(var i=j.concat("_initStorage"),k=0;k<i.length;k++){var m=i[k];if(!m||!a[m]||"function"!=typeof a[m])return void c(e)}var n=Promise.resolve(!0);"_support"in a&&(n=a._support&&"function"==typeof a._support?a._support():Promise.resolve(!!a._support)),n.then(function(c){l[d]=c,g[d]=a,b()},c)}catch(o){c(o)}});return d.then(b,c),d},a.prototype.driver=function(){return this._driver||null},a.prototype.getDriver=function(a,b,d){var e=this,h=function(){if(f(a))switch(a){case e.INDEXEDDB:return new Promise(function(a,b){a(c(1))});case e.LOCALSTORAGE:return new Promise(function(a,b){a(c(2))});case e.WEBSQL:return new Promise(function(a,b){a(c(4))})}else if(g[a])return Promise.resolve(g[a]);return Promise.reject(new Error("Driver not found."))}();return h.then(b,d),h},a.prototype.getSerializer=function(a){var b=new Promise(function(a,b){a(c(3))});return a&&"function"==typeof a&&b.then(function(b){a(b)}),b},a.prototype.ready=function(a){var b=this,c=b._driverSet.then(function(){return null===b._ready&&(b._ready=b._initDriver()),b._ready});return c.then(a,a),c},a.prototype.setDriver=function(a,b,c){function d(){f._config.driver=f.driver()}function e(a){return function(){function b(){for(;c<a.length;){var e=a[c];return c++,f._dbInfo=null,f._ready=null,f.getDriver(e).then(function(a){return f._extend(a),d(),f._ready=f._initStorage(f._config),f._ready})["catch"](b)}d();var g=new Error("No available storage method found.");return f._driverSet=Promise.reject(g),f._driverSet}var c=0;return b()}}var f=this;m(a)||(a=[a]);var g=this._getSupportedDrivers(a),h=null!==this._driverSet?this._driverSet["catch"](function(){return Promise.resolve()}):Promise.resolve();return this._driverSet=h.then(function(){var a=g[0];return f._dbInfo=null,f._ready=null,f.getDriver(a).then(function(a){f._driver=a._driver,d(),f._wrapLibraryMethodsWithReady(),f._initDriver=e(g)})})["catch"](function(){d();var a=new Error("No available storage method found.");return f._driverSet=Promise.reject(a),f._driverSet}),this._driverSet.then(b,c),this._driverSet},a.prototype.supports=function(a){return!!l[a]},a.prototype._extend=function(a){e(this,a)},a.prototype._getSupportedDrivers=function(a){for(var b=[],c=0,d=a.length;d>c;c++){var e=a[c];this.supports(e)&&b.push(e)}return b},a.prototype._wrapLibraryMethodsWithReady=function(){for(var a=0;a<j.length;a++)b(this,j[a])},a.prototype.createInstance=function(b){return new a(b)},a}();return new n}("undefined"!=typeof window?window:self);b["default"]=e,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;g<b.length;g+=1)f.append(b[g]);return f.getBlob(c.type)}}function c(a){for(var b=a.length,c=new ArrayBuffer(b),d=new Uint8Array(c),e=0;b>e;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;h<f.forages.length;h++){var i=f.forages[h];i!==c&&g.push(i._initReady()["catch"](b))}var k=f.forages.slice(0);return Promise.all(g).then(function(){return d.db=f.db,n(d)}).then(function(a){return d.db=a,q(d,c._defaultConfig.version)?o(d):a}).then(function(a){d.db=f.db=a,c._dbInfo=d;for(var b=0;b<k.length;b++){var e=k[b];e!==c&&(e._dbInfo.db=d.db,e._dbInfo.version=d.version)}})}function n(a){return p(a,!1)}function o(a){return p(a,!0)}function p(b,c){return new Promise(function(d,e){if(b.db){if(!c)return d(b.db);k(b),b.db.close()}var f=[b.name];c&&f.push(b.version);var g=A.open.apply(A,f);c&&(g.onupgradeneeded=function(c){var d=g.result;try{d.createObjectStore(b.storeName),c.oldVersion<=1&&d.createObjectStore(D)}catch(e){if("ConstraintError"!==e.name)throw e;a.console.warn('The database "'+b.name+'" has been upgraded from version '+c.oldVersion+" to version "+c.newVersion+', but the storage "'+b.storeName+'" already exists.')}}),g.onerror=function(){e(g.error)},g.onsuccess=function(){d(g.result),l(b)}})}function q(b,c){if(!b.db)return!0;var d=!b.db.objectStoreNames.contains(b.storeName),e=b.version<b.db.version,f=b.version>b.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;g<b.length;g+=1)f.append(b[g]);return f.getBlob(c.type)}}function c(a,b){var c="";if(a&&(c=a.toString()),a&&("[object ArrayBuffer]"===a.toString()||a.buffer&&"[object ArrayBuffer]"===a.buffer.toString())){var d,e=j;a instanceof ArrayBuffer?(d=a,e+=l):(d=a.buffer,"[object Int8Array]"===c?e+=n:"[object Uint8Array]"===c?e+=o:"[object Uint8ClampedArray]"===c?e+=p:"[object Int16Array]"===c?e+=q:"[object Uint16Array]"===c?e+=s:"[object Int32Array]"===c?e+=r:"[object Uint32Array]"===c?e+=t:"[object Float32Array]"===c?e+=u:"[object Float64Array]"===c?e+=v:b(new Error("Failed to get type for BinaryArray"))),b(e+f(d))}else if("[object Blob]"===c){var g=new FileReader;g.onload=function(){var c=h+a.type+"~"+f(this.result);b(j+m+c)},g.readAsArrayBuffer(a)}else try{b(JSON.stringify(a))}catch(i){console.error("Couldn't convert value into a JSON string: ",a),b(null,i)}}function d(a){if(a.substring(0,k)!==j)return JSON.parse(a);var c,d=a.substring(w),f=a.substring(k,w);if(f===m&&i.test(d)){var g=d.match(i);c=g[1],d=d.substring(g[0].length)}var h=e(d);switch(f){case l:return h;case m:return b([h],{type:c});case n:return new Int8Array(h);case o:return new Uint8Array(h);case p:return new Uint8ClampedArray(h);case q:return new Int16Array(h);case s:return new Uint16Array(h);case r:return new Int32Array(h);case t:return new Uint32Array(h);case u:return new Float32Array(h);case v:return new Float64Array(h);default:throw new Error("Unkown type: "+f)}}function e(a){var b,c,d,e,f,h=.75*a.length,i=a.length,j=0;"="===a[a.length-1]&&(h--,"="===a[a.length-2]&&h--);var k=new ArrayBuffer(h),l=new Uint8Array(k);for(b=0;i>b;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<c.length;b+=3)d+=g[c[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<c.rows.length;e++)d.push(c.rows.item(e).key);a(d)},function(a,b){c(b)})})})["catch"](c)});return l(c,a),c}function l(a,b){b&&a.then(function(a){b(null,a)},function(a){b(a)})}var m=a.openDatabase;if(m){var n={_driver:"webSQLStorage",_initStorage:b,iterate:e,getItem:d,setItem:f,removeItem:g,clear:h,length:i,key:j,keys:k};return n}}("undefined"!=typeof window?window:self);b["default"]=d,a.exports=b["default"]}])});
|
|
}
|
|
catch (e)
|
|
{
|
|
localForageInitFailed = true;
|
|
}
|
|
cr.plugins_.LocalStorage = function(runtime)
|
|
{
|
|
this.runtime = runtime;
|
|
};
|
|
(function ()
|
|
{
|
|
var currentKey = "";
|
|
var lastValue = "";
|
|
var keyNamesList = [];
|
|
var errorMessage = "";
|
|
function getErrorString(err)
|
|
{
|
|
if (!err)
|
|
return "unknown error";
|
|
else if (typeof err === "string")
|
|
return err;
|
|
else if (typeof err.message === "string")
|
|
return err.message;
|
|
else if (typeof err.name === "string")
|
|
return err.name;
|
|
else if (typeof err.data === "string")
|
|
return err.data;
|
|
else
|
|
return "unknown error";
|
|
};
|
|
function TriggerStorageError(self, msg)
|
|
{
|
|
errorMessage = msg;
|
|
self.runtime.trigger(cr.plugins_.LocalStorage.prototype.cnds.OnError, self);
|
|
};
|
|
var prefix = "";
|
|
var is_arcade = (typeof window["is_scirra_arcade"] !== "undefined");
|
|
if (is_arcade)
|
|
prefix = "sa" + window["scirra_arcade_id"] + "_";
|
|
function hasRequiredPrefix(key)
|
|
{
|
|
if (!prefix)
|
|
return true;
|
|
return key.substr(0, prefix.length) === prefix;
|
|
};
|
|
function removePrefix(key)
|
|
{
|
|
if (!prefix)
|
|
return key;
|
|
if (hasRequiredPrefix(key))
|
|
return key.substr(prefix.length);
|
|
};
|
|
var pluginProto = cr.plugins_.LocalStorage.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.pendingSets = 0; // number of pending 'Set item' actions
|
|
this.pendingGets = 0; // number of pending 'Get item' actions
|
|
};
|
|
instanceProto.onDestroy = function ()
|
|
{
|
|
};
|
|
instanceProto.saveToJSON = function ()
|
|
{
|
|
return {
|
|
};
|
|
};
|
|
instanceProto.loadFromJSON = function (o)
|
|
{
|
|
};
|
|
var debugDataChanged = true;
|
|
function Cnds() {};
|
|
Cnds.prototype.OnItemSet = function (key)
|
|
{
|
|
return currentKey === key;
|
|
};
|
|
Cnds.prototype.OnAnyItemSet = function ()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnItemGet = function (key)
|
|
{
|
|
return currentKey === key;
|
|
};
|
|
Cnds.prototype.OnAnyItemGet = function ()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnItemRemoved = function (key)
|
|
{
|
|
return currentKey === key;
|
|
};
|
|
Cnds.prototype.OnAnyItemRemoved = function ()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnCleared = function ()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnAllKeyNamesLoaded = function ()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnError = function ()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnItemExists = function (key)
|
|
{
|
|
return currentKey === key;
|
|
};
|
|
Cnds.prototype.OnItemMissing = function (key)
|
|
{
|
|
return currentKey === key;
|
|
};
|
|
Cnds.prototype.CompareKey = function (cmp, key)
|
|
{
|
|
return cr.do_cmp(currentKey, cmp, key);
|
|
};
|
|
Cnds.prototype.CompareValue = function (cmp, v)
|
|
{
|
|
return cr.do_cmp(lastValue, cmp, v);
|
|
};
|
|
Cnds.prototype.IsProcessingSets = function ()
|
|
{
|
|
return this.pendingSets > 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<r.length;)a=(t=r.charCodeAt(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<r.length;)t=this._keyStr.indexOf(r.charAt(C++))<<2|(a=this._keyStr.indexOf(r.charAt(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;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&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;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&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<r.length;)a=(t=r.charCodeAt(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<r.length;)t=this._keyStr.indexOf(r.charAt(C++))<<2|(a=this._keyStr.indexOf(r.charAt(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;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&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;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&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.repeat_count; i++)
|
|
{
|
|
this.runtime.trigger(cr.plugins_.Rex_EventBalancer.prototype.cnds.OnProcessing, this);
|
|
if (!this.is_running)
|
|
break;
|
|
}
|
|
};
|
|
instanceProto.saveToJSON = function ()
|
|
{
|
|
return { "dm": this.is_dynamic_mode,
|
|
"pt": this.processing_time,
|
|
"rc": this.repeat_count,
|
|
"isrun": this.is_running,
|
|
};
|
|
};
|
|
instanceProto.loadFromJSON = function (o)
|
|
{
|
|
this.is_dynamic_mode = o["dm"];
|
|
this.processing_time = o["pt"];
|
|
this.repeat_count = o["rc"];
|
|
this.is_running = o["isrun"];
|
|
if (this.is_running)
|
|
this.runtime.tickMe(this);
|
|
};
|
|
function Cnds() {};
|
|
pluginProto.cnds = new Cnds();
|
|
Cnds.prototype.OnStart = function()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnProcessing = function()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.OnStop = function()
|
|
{
|
|
return true;
|
|
};
|
|
Cnds.prototype.IsProcessing = function()
|
|
{
|
|
return this.is_running;
|
|
};
|
|
Cnds.prototype.DynamicLoop = function()
|
|
{
|
|
var current_frame = this.runtime.getCurrentEventStack();
|
|
var current_event = current_frame.current_event;
|
|
var solModifierAfterCnds = current_frame.isModifierAfterCnds();
|
|
var start_time = Date.now();
|
|
this.is_looping = true;
|
|
if (solModifierAfterCnds)
|
|
{
|
|
while ((Date.now() - start_time) <= this.processing_time)
|
|
{
|
|
this.runtime.pushCopySol(current_event.solModifiers);
|
|
current_event.retrigger();
|
|
this.runtime.popSol(current_event.solModifiers);
|
|
if (!this.is_looping)
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while ((Date.now() - start_time) <= this.processing_time)
|
|
{
|
|
current_event.retrigger();
|
|
if (!this.is_looping)
|
|
break;
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
function Acts() {};
|
|
pluginProto.acts = new Acts();
|
|
Acts.prototype.Start = function()
|
|
{
|
|
if (!this.trigger_mode_init)
|
|
{
|
|
this.runtime.tickMe(this);
|
|
this.trigger_mode_init = true;
|
|
}
|
|
this.is_running = true;
|
|
this.elapsed_ticks = 0;
|
|
this.runtime.trigger(cr.plugins_.Rex_EventBalancer.prototype.cnds.OnStart, this);
|
|
};
|
|
Acts.prototype.Stop = function()
|
|
{
|
|
if (!this.is_running)
|
|
return;
|
|
this.is_running = false;
|
|
this.runtime.trigger(cr.plugins_.Rex_EventBalancer.prototype.cnds.OnStop, this);
|
|
};
|
|
Acts.prototype.SetProcessingTime = function(percentage)
|
|
{
|
|
this.processing_time = percentage2time(percentage);
|
|
};
|
|
Acts.prototype.SetRepeatCount = function(repeat_count)
|
|
{
|
|
if (repeat_count < 1)
|
|
repeat_count = 1;
|
|
this.repeat_count = repeat_count;
|
|
};
|
|
Acts.prototype.StopLoop = function()
|
|
{
|
|
this.is_running = false;
|
|
};
|
|
function Exps() {};
|
|
pluginProto.exps = new Exps();
|
|
Exps.prototype.ProcessingTime = function (ret)
|
|
{
|
|
ret.set_float(this.processing_time);
|
|
};
|
|
Exps.prototype.ElapsedTicks = function (ret)
|
|
{
|
|
ret.set_int(this.elapsed_ticks);
|
|
};
|
|
}());
|
|
;
|
|
;
|
|
cr.plugins_.Sprite = function(runtime)
|
|
{
|
|
this.runtime = runtime;
|
|
};
|
|
(function ()
|
|
{
|
|
var pluginProto = cr.plugins_.Sprite.prototype;
|
|
pluginProto.Type = function(plugin)
|
|
{
|
|
this.plugin = plugin;
|
|
this.runtime = plugin.runtime;
|
|
};
|
|
var typeProto = pluginProto.Type.prototype;
|
|
function frame_getDataUri()
|
|
{
|
|
if (this.datauri.length === 0)
|
|
{
|
|
var tmpcanvas = document.createElement("canvas");
|
|
tmpcanvas.width = this.width;
|
|
tmpcanvas.height = this.height;
|
|
var tmpctx = tmpcanvas.getContext("2d");
|
|
if (this.spritesheeted)
|
|
{
|
|
tmpctx.drawImage(this.texture_img, this.offx, this.offy, this.width, this.height,
|
|
0, 0, this.width, this.height);
|
|
}
|
|
else
|
|
{
|
|
tmpctx.drawImage(this.texture_img, 0, 0, this.width, this.height);
|
|
}
|
|
this.datauri = tmpcanvas.toDataURL("image/png");
|
|
}
|
|
return this.datauri;
|
|
};
|
|
typeProto.onCreate = function()
|
|
{
|
|
if (this.is_family)
|
|
return;
|
|
var i, leni, j, lenj;
|
|
var anim, frame, animobj, frameobj, wt, uv;
|
|
this.all_frames = [];
|
|
this.has_loaded_textures = false;
|
|
for (i = 0, leni = this.animations.length; i < leni; i++)
|
|
{
|
|
anim = this.animations[i];
|
|
animobj = {};
|
|
animobj.name = anim[0];
|
|
animobj.speed = anim[1];
|
|
animobj.loop = anim[2];
|
|
animobj.repeatcount = anim[3];
|
|
animobj.repeatto = anim[4];
|
|
animobj.pingpong = anim[5];
|
|
animobj.sid = anim[6];
|
|
animobj.frames = [];
|
|
for (j = 0, lenj = anim[7].length; j < lenj; j++)
|
|
{
|
|
frame = anim[7][j];
|
|
frameobj = {};
|
|
frameobj.texture_file = frame[0];
|
|
frameobj.texture_filesize = frame[1];
|
|
frameobj.offx = frame[2];
|
|
frameobj.offy = frame[3];
|
|
frameobj.width = frame[4];
|
|
frameobj.height = frame[5];
|
|
frameobj.duration = frame[6];
|
|
frameobj.hotspotX = frame[7];
|
|
frameobj.hotspotY = frame[8];
|
|
frameobj.image_points = frame[9];
|
|
frameobj.poly_pts = frame[10];
|
|
frameobj.pixelformat = frame[11];
|
|
frameobj.spritesheeted = (frameobj.width !== 0);
|
|
frameobj.datauri = ""; // generated on demand and cached
|
|
frameobj.getDataUri = frame_getDataUri;
|
|
uv = {};
|
|
uv.left = 0;
|
|
uv.top = 0;
|
|
uv.right = 1;
|
|
uv.bottom = 1;
|
|
frameobj.sheetTex = uv;
|
|
frameobj.webGL_texture = null;
|
|
wt = this.runtime.findWaitingTexture(frame[0]);
|
|
if (wt)
|
|
{
|
|
frameobj.texture_img = wt;
|
|
}
|
|
else
|
|
{
|
|
frameobj.texture_img = new Image();
|
|
frameobj.texture_img.cr_src = frame[0];
|
|
frameobj.texture_img.cr_filesize = frame[1];
|
|
frameobj.texture_img.c2webGL_texture = null;
|
|
this.runtime.waitForImageLoad(frameobj.texture_img, frame[0]);
|
|
}
|
|
cr.seal(frameobj);
|
|
animobj.frames.push(frameobj);
|
|
this.all_frames.push(frameobj);
|
|
}
|
|
cr.seal(animobj);
|
|
this.animations[i] = animobj; // swap array data for object
|
|
}
|
|
};
|
|
typeProto.updateAllCurrentTexture = function ()
|
|
{
|
|
var i, len, inst;
|
|
for (i = 0, len = this.instances.length; i < len; i++)
|
|
{
|
|
inst = this.instances[i];
|
|
inst.curWebGLTexture = inst.curFrame.webGL_texture;
|
|
}
|
|
};
|
|
typeProto.onLostWebGLContext = function ()
|
|
{
|
|
if (this.is_family)
|
|
return;
|
|
var i, len, frame;
|
|
for (i = 0, len = this.all_frames.length; i < len; ++i)
|
|
{
|
|
frame = this.all_frames[i];
|
|
frame.texture_img.c2webGL_texture = null;
|
|
frame.webGL_texture = null;
|
|
}
|
|
this.has_loaded_textures = false;
|
|
this.updateAllCurrentTexture();
|
|
};
|
|
typeProto.onRestoreWebGLContext = function ()
|
|
{
|
|
if (this.is_family || !this.instances.length)
|
|
return;
|
|
var i, len, frame;
|
|
for (i = 0, len = this.all_frames.length; i < len; ++i)
|
|
{
|
|
frame = this.all_frames[i];
|
|
frame.webGL_texture = this.runtime.glwrap.loadTexture(frame.texture_img, false, this.runtime.linearSampling, frame.pixelformat);
|
|
}
|
|
this.updateAllCurrentTexture();
|
|
};
|
|
typeProto.loadTextures = function ()
|
|
{
|
|
if (this.is_family || this.has_loaded_textures || !this.runtime.glwrap)
|
|
return;
|
|
var i, len, frame;
|
|
for (i = 0, len = this.all_frames.length; i < len; ++i)
|
|
{
|
|
frame = this.all_frames[i];
|
|
frame.webGL_texture = this.runtime.glwrap.loadTexture(frame.texture_img, false, this.runtime.linearSampling, frame.pixelformat);
|
|
}
|
|
this.has_loaded_textures = true;
|
|
};
|
|
typeProto.unloadTextures = function ()
|
|
{
|
|
if (this.is_family || this.instances.length || !this.has_loaded_textures)
|
|
return;
|
|
var i, len, frame;
|
|
for (i = 0, len = this.all_frames.length; i < len; ++i)
|
|
{
|
|
frame = this.all_frames[i];
|
|
this.runtime.glwrap.deleteTexture(frame.webGL_texture);
|
|
frame.webGL_texture = null;
|
|
}
|
|
this.has_loaded_textures = false;
|
|
};
|
|
var already_drawn_images = [];
|
|
typeProto.preloadCanvas2D = function (ctx)
|
|
{
|
|
var i, len, frameimg;
|
|
cr.clearArray(already_drawn_images);
|
|
for (i = 0, len = this.all_frames.length; i < len; ++i)
|
|
{
|
|
frameimg = this.all_frames[i].texture_img;
|
|
if (already_drawn_images.indexOf(frameimg) !== -1)
|
|
continue;
|
|
ctx.drawImage(frameimg, 0, 0);
|
|
already_drawn_images.push(frameimg);
|
|
}
|
|
};
|
|
pluginProto.Instance = function(type)
|
|
{
|
|
this.type = type;
|
|
this.runtime = type.runtime;
|
|
var poly_pts = this.type.animations[0].frames[0].poly_pts;
|
|
if (this.recycled)
|
|
this.collision_poly.set_pts(poly_pts);
|
|
else
|
|
this.collision_poly = new cr.CollisionPoly(poly_pts);
|
|
};
|
|
var instanceProto = pluginProto.Instance.prototype;
|
|
instanceProto.onCreate = function()
|
|
{
|
|
this.visible = (this.properties[0] === 0); // 0=visible, 1=invisible
|
|
this.isTicking = false;
|
|
this.inAnimTrigger = false;
|
|
this.collisionsEnabled = (this.properties[3] !== 0);
|
|
this.cur_animation = this.getAnimationByName(this.properties[1]) || this.type.animations[0];
|
|
this.cur_frame = this.properties[2];
|
|
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;
|
|
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<r.length;)a=(t=r.charCodeAt(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<r.length;)t=this._keyStr.indexOf(r.charAt(C++))<<2|(a=this._keyStr.indexOf(r.charAt(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;e<r.length;e++){var o=r.charCodeAt(e);o<128?t+=String.fromCharCode(o):o>127&&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;e<r.length;)(o=r.charCodeAt(e))<128?(t+=String.fromCharCode(o),e++):o>191&&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<l; i++ )
|
|
{
|
|
instance = instances[i];
|
|
if (!instance)
|
|
continue;
|
|
if(!instance.layer.visible || !instance.visible)
|
|
continue;
|
|
lx = instance.layer.canvasToLayer(touchX, touchY, true);
|
|
ly = instance.layer.canvasToLayer(touchX, touchY, false);
|
|
instance.update_bbox();
|
|
if (instance.contains_pt(lx, ly))
|
|
objectInstances.push(instance);
|
|
}
|
|
if (objectInstances.length == 0)
|
|
return;
|
|
var maxZInstance = objectInstances[0];
|
|
for (var i=1,l=objectInstances.length; i<l; i++)
|
|
{
|
|
if ( ( objectInstances[i].layer.index > 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<l; i++ )
|
|
{
|
|
instance = instances[i];
|
|
if (!instance)
|
|
continue;
|
|
if(!instance.layer.visible || !instance.visible)
|
|
continue;
|
|
lx = instance.layer.canvasToLayer(touchX, touchY, true);
|
|
ly = instance.layer.canvasToLayer(touchX, touchY, false);
|
|
instance.update_bbox();
|
|
instanceBehavior = getThisBehavior(instance,this);
|
|
if(instanceBehavior.OnAnyTouchStart){
|
|
instanceBehavior.OnAnyTouchStart();
|
|
}
|
|
if (instance.contains_pt(lx, ly)){
|
|
if(instanceBehavior.OnTouchStart){
|
|
instanceBehavior.OnTouchStart();
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var dispatchTouchEnd = function(touchX, touchY)
|
|
{
|
|
var instances = this.my_instances.valuesRef();
|
|
var instance;
|
|
var instanceBehavior;
|
|
var tx,ty;
|
|
for (var i=0,l=instances.length; i<l; i++ )
|
|
{
|
|
instance = instances[i];
|
|
if (!instance)
|
|
continue;
|
|
/*if(!instance.layer.visible || !instance.visible)
|
|
continue;*/
|
|
tx = instance.layer.canvasToLayer(touchX, touchY, true);
|
|
ty = instance.layer.canvasToLayer(touchX, touchY, false);
|
|
instanceBehavior = getThisBehavior(instance,this);
|
|
if(instanceBehavior.OnAnyTouchEnd){
|
|
instanceBehavior.OnAnyTouchEnd(tx, ty);
|
|
}
|
|
}
|
|
};
|
|
var dispatchWheel = function(triggerDir)
|
|
{
|
|
var instances = this.my_instances.valuesRef();
|
|
var instance;
|
|
var instanceBehavior;
|
|
for (var i=0,l=instances.length; i<l; i++ )
|
|
{
|
|
instance = instances[i];
|
|
if (!instance)
|
|
continue;
|
|
instanceBehavior = getThisBehavior(instance,this);
|
|
if(instanceBehavior.OnWheel){
|
|
instanceBehavior.OnWheel(triggerDir);
|
|
}
|
|
}
|
|
};
|
|
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;
|
|
for (var i=0,l=this._callbackObjs["wheel"].length; i<l; i++)
|
|
{
|
|
this.handled = true;
|
|
dispatchWheel.call(this._callbackObjs["wheel"][i],this.triggerDir);
|
|
}
|
|
this.runtime.isInUserInputEvent = false;
|
|
if (this.handled && cr.isCanvasInputEvent(info))
|
|
info.preventDefault();
|
|
};
|
|
instanceProto.onPointerMove = function (info)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
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);
|
|
var touchx = info.pageX - offset.left;
|
|
var touchy = info.pageY - offset.top;
|
|
/*var cnt=this._callbackObjs.length, hooki;
|
|
for (hooki=0; hooki<cnt; hooki++)
|
|
{
|
|
if (this._callbackObjs[hooki].OnTouchMove)
|
|
this._callbackObjs[hooki].OnTouchMove(t["identifier"], touchx, touchy);
|
|
} */
|
|
}
|
|
};
|
|
instanceProto.onPointerStart = function (info)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
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.curTouchX = touchx;
|
|
this.curTouchY = touchy;
|
|
var hooki, cnt=this._callbackObjs["touch"].length;
|
|
for (hooki=0; hooki<cnt; hooki++)
|
|
{
|
|
dispatchTouchStart.call(this._callbackObjs["touch"][hooki],this.curTouchX, this.curTouchY);
|
|
}
|
|
this.runtime.isInUserInputEvent = false;
|
|
};
|
|
instanceProto.onPointerEnd = function (info, isCancel)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
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;
|
|
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<cnt; hooki++)
|
|
{
|
|
dispatchTouchEnd.call(this._callbackObjs["touch"][hooki],this.lastTouchX,this.lastTouchY);
|
|
}
|
|
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 (!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<cnt; hooki++)
|
|
{
|
|
if (this._callbackObjs["touch"][hooki].OnTouchMove)
|
|
this._callbackObjs["touch"][hooki].OnTouchMove(t["identifier"], touchx, touchy);
|
|
}*/
|
|
}
|
|
}
|
|
};
|
|
instanceProto.onTouchStart = function (info)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
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;
|
|
var cnt=this._callbackObjs["touch"].length, hooki;
|
|
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.curTouchX = touchx;
|
|
this.curTouchY = touchy;
|
|
for (hooki=0; hooki<cnt; hooki++)
|
|
{
|
|
dispatchTouchStart.call(this._callbackObjs["touch"][hooki],this.curTouchX, this.curTouchY);
|
|
}
|
|
}
|
|
this.runtime.isInUserInputEvent = false;
|
|
};
|
|
instanceProto.onTouchEnd = function (info, isCancel)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
if (info.preventDefault && cr.isCanvasInputEvent(info))
|
|
info.preventDefault();
|
|
this.runtime.isInUserInputEvent = true;
|
|
var i, len, t, j;
|
|
var cnt=this._callbackObjs["touch"].length, hooki;
|
|
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.lastTouchX = this.touches[j].x;
|
|
this.lastTouchY = this.touches[j].y;
|
|
for (hooki=0; hooki<cnt; hooki++)
|
|
{
|
|
dispatchTouchEnd.call(this._callbackObjs["touch"][hooki],this.lastTouchX,this.lastTouchY);
|
|
}
|
|
if (!isCancel)
|
|
this.touches[j].maybeTriggerTap(this, j);
|
|
ReleaseTouchInfo(this.touches[j]);
|
|
this.touches.splice(j, 1);
|
|
}
|
|
}
|
|
this.runtime.isInUserInputEvent = false;
|
|
};
|
|
instanceProto.updateCursor = function(info)
|
|
{
|
|
var offset = this.runtime.isDomFree ? dummyoffset : jQuery(this.runtime.canvas).offset();
|
|
this.cursor.x = info.pageX - offset.left;
|
|
this.cursor.y = info.pageY - offset.top;
|
|
}
|
|
instanceProto.onMouseDown = function(info)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
this.updateCursor(info);
|
|
this.mouseDown = true;
|
|
if (info.preventDefault && this.runtime.had_a_click && !this.runtime.isMobile)
|
|
info.preventDefault();
|
|
var index = this.findTouch(0);
|
|
if (index !== -1)
|
|
{
|
|
ReleaseTouchInfo(this.touches[index]);
|
|
cr.arrayRemove( this.touches, index );
|
|
}
|
|
var t = { pageX: info.pageX, pageY: info.pageY, "identifier": 0 };
|
|
var fakeinfo = { changedTouches: [t] };
|
|
this.onTouchStart(fakeinfo);
|
|
};
|
|
instanceProto.onMouseMove = function(info)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
this.updateCursor(info);
|
|
if (!this.mouseDown)
|
|
return;
|
|
var t = { pageX: info.pageX, pageY: info.pageY, "identifier": 0 };
|
|
var fakeinfo = { changedTouches: [t] };
|
|
this.onTouchMove(fakeinfo);
|
|
};
|
|
instanceProto.onMouseUp = function(info)
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
this.updateCursor(info);
|
|
this.mouseDown = false;
|
|
if (info.preventDefault && this.runtime.had_a_click && !this.runtime.isMobile)
|
|
info.preventDefault();
|
|
this.runtime.had_a_click = true;
|
|
var t = { pageX: info.pageX, pageY: info.pageY, "identifier": 0 };
|
|
var fakeinfo = { changedTouches: [t] };
|
|
this.onTouchEnd(fakeinfo);
|
|
};
|
|
instanceProto.tick2 = function()
|
|
{
|
|
if (!this.enable)
|
|
return;
|
|
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;
|
|
}
|
|
this.lastTouchX = null;
|
|
this.lastTouchY = null;
|
|
/*if(this.firstFrame){
|
|
this.firstFrame = false;
|
|
}*/
|
|
};
|
|
function Cnds() {};
|
|
Cnds.IsDialogOpened = function ()
|
|
{
|
|
return this.currentDialogs.length;
|
|
};
|
|
pluginProto.cnds = new Cnds();
|
|
function Acts() {};
|
|
pluginProto.acts = new Acts();
|
|
Acts.prototype.SetEnable = function(en)
|
|
{
|
|
this.enable = (en==1);
|
|
};
|
|
function Exps() {};
|
|
pluginProto.exps = new Exps();
|
|
instanceProto.TouchCount = function (ret)
|
|
{
|
|
ret.set_int(this.touches.length);
|
|
};
|
|
instanceProto.X = function (layerparam)
|
|
{
|
|
var index = this.getTouchIndex;
|
|
var result;
|
|
if (index < 0 || index >= 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<lcnt; li++)
|
|
{
|
|
line_width = pensMgr.getLineWidth(li);
|
|
if (line_width === 0)
|
|
continue;
|
|
if (this.plugin.halign === 1) // center
|
|
offset_x = (boxWidth - line_width) / 2;
|
|
else if (this.plugin.halign === 2) // right
|
|
offset_x = boxWidth - line_width;
|
|
else
|
|
offset_x = 0;
|
|
offset_x += start_x;
|
|
pens = lines[li];
|
|
pcnt = pens.length;
|
|
for (pi=0; pi<pcnt; pi++)
|
|
{
|
|
pen = pens[pi];
|
|
if (pen.text === "")
|
|
continue;
|
|
this.draw_pen(pen, offset_x, offset_y);
|
|
}
|
|
}
|
|
};
|
|
CanvasTextProto.postProcess = function()
|
|
{
|
|
};
|
|
var RAWTEXTONLY_MODE = 1;
|
|
var __result=[];
|
|
var split_text = function(txt, mode)
|
|
{
|
|
var re = /\[b\]|\[\/b\]|\[i\]|\[\/i\]|\[size=(\d+)\]|\[\/size\]|\[color=([a-z]+|#[0-9abcdef]+)\]|\[\/color\]|\[u\]|\[u=([a-z]+|#[0-9abcdef]+)\]|\[\/u\]|\[shadow\]|\[\/shadow\]|\[stroke=([a-z]+|#[0-9abcdef]+)\]|\[\/stroke\]|\[img=([^\]]+)\]|\[\/img\]/ig;
|
|
__result.length = 0;
|
|
var arr, m, char_index=0, total_length=txt.length, match_start=total_length;
|
|
while(true)
|
|
{
|
|
arr = re.exec(txt);
|
|
if (!arr)
|
|
{
|
|
break;
|
|
}
|
|
m = arr[0];
|
|
match_start = re["lastIndex"] - m.length;
|
|
if (char_index < match_start)
|
|
{
|
|
__result.push(txt.substring(char_index,match_start));
|
|
}
|
|
if (mode == null)
|
|
__result.push(m);
|
|
char_index = re["lastIndex"];
|
|
}
|
|
if (char_index < total_length)
|
|
{
|
|
__result.push(txt.substring(char_index,total_length));
|
|
}
|
|
return __result;
|
|
};
|
|
var __re_bold_open = /\[b\]/i;
|
|
var __re_bold_close = /\[\/b\]/i;
|
|
var __re_italics_open = /\[i\]/i;
|
|
var __re_italics_close = /\[\/i\]/i;
|
|
var __re_size_open = /\[size=(\d+)\]/i;
|
|
var __re_size_close = /\[\/size\]/i;
|
|
var __re_color_open = /\[color=([a-z]+|#[0-9abcdef]+)\]/i;
|
|
var __re_color_close = /\[\/color\]/i;
|
|
var __re_underline_open = /\[u\]/i;
|
|
var __re_underline_openC = /\[u=([a-z]+|#[0-9abcdef]+)\]/i;
|
|
var __re_underline_close = /\[\/u\]/i;
|
|
var __re_shadow_open = /\[shadow\]/i;
|
|
var __re_shadow_close = /\[\/shadow\]/i;
|
|
var __re_stroke_open = /\[stroke=([a-z]+|#[0-9abcdef]+)\]/i;
|
|
var __re_stroke_close = /\[\/stroke\]/i;
|
|
var __re_image_open = /\[img=([^\]]+)\]/i;
|
|
var __re_image_close = /\[\/img\]/i;
|
|
var __curr_propScope = {};
|
|
var PROP_REMOVE = false;
|
|
var PROP_ADD = true;
|
|
CanvasTextProto.updatePens = function (pensMgr, textInfo, ignore_wrap)
|
|
{
|
|
if (textInfo == null)
|
|
textInfo = this.textInfo;
|
|
pensMgr.freePens();
|
|
var text=textInfo["text"], boxWidth=textInfo["boxWidth"], boxHeight=textInfo["boxHeight"];
|
|
if (text === "")
|
|
return;
|
|
var start_x = 0, start_y = 0;
|
|
var cursor_x=start_x, cursor_y=start_y;
|
|
var proText;
|
|
var m, match=split_text(text);
|
|
if (match.length === 0)
|
|
return;
|
|
var i, match_cnt = match.length;
|
|
var innerMatch = null;
|
|
for (i = 0; i < match_cnt; i++)
|
|
{
|
|
m = match[i];
|
|
if (__re_bold_open.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_ADD, "b", true);
|
|
continue;
|
|
}
|
|
else if (__re_bold_close.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_REMOVE, "b");
|
|
continue;
|
|
}
|
|
else if (__re_italics_open.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_ADD, "i", true);
|
|
continue;
|
|
}
|
|
else if (__re_italics_close.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_REMOVE, "i");
|
|
continue;
|
|
}
|
|
else if (__re_size_open.test(m))
|
|
{
|
|
innerMatch = m.match(__re_size_open);
|
|
update_propScope(__curr_propScope, PROP_ADD, "size", innerMatch[1]+"pt");
|
|
continue;
|
|
}
|
|
else if (__re_size_close.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_REMOVE, "size");
|
|
continue;
|
|
}
|
|
else if (__re_color_open.test(m))
|
|
{
|
|
innerMatch = m.match(__re_color_open);
|
|
update_propScope(__curr_propScope, PROP_ADD, "color", innerMatch[1]);
|
|
continue;
|
|
}
|
|
else if (__re_color_close.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_REMOVE, "color");
|
|
continue;
|
|
}
|
|
else if (__re_underline_open.test(m))
|
|
{
|
|
innerMatch = m.match(__re_underline_open);
|
|
update_propScope(__curr_propScope, PROP_ADD, "u", true);
|
|
continue;
|
|
}
|
|
else if (__re_underline_openC.test(m))
|
|
{
|
|
innerMatch = m.match(__re_underline_openC);
|
|
update_propScope(__curr_propScope, PROP_ADD, "u", innerMatch[1]);
|
|
continue;
|
|
}
|
|
else if (__re_underline_close.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_REMOVE, "u");
|
|
continue;
|
|
}
|
|
else if (__re_shadow_open.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_ADD, "shadow", true);
|
|
continue;
|
|
}
|
|
else if (__re_shadow_close.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_REMOVE, "shadow");
|
|
continue;
|
|
}
|
|
else if (__re_stroke_open.test(m))
|
|
{
|
|
innerMatch = m.match(__re_stroke_open);
|
|
update_propScope(__curr_propScope, PROP_ADD, "stroke", innerMatch[1]);
|
|
continue;
|
|
}
|
|
else if (__re_stroke_close.test(m))
|
|
{
|
|
update_propScope(__curr_propScope, PROP_REMOVE, "stroke");
|
|
continue;
|
|
}
|
|
else if (__re_image_open.test(m))
|
|
{
|
|
innerMatch = m.match(__re_image_open);
|
|
var key = innerMatch[1];
|
|
var img = window.RexImageBank.GetImage(key);
|
|
if (!img)
|
|
continue;
|
|
update_propScope(__curr_propScope, PROP_ADD, "img", key);
|
|
if (!ignore_wrap)
|
|
{
|
|
if ( img.width > 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<lcnt; n++)
|
|
{
|
|
wrap_line = wrap_lines[n];
|
|
pensMgr.addPen(wrap_line.text, // text
|
|
cursor_x, // x
|
|
cursor_y, // y
|
|
wrap_line.width, // width
|
|
__curr_propScope, // prop
|
|
wrap_line.newLineMode // new_line_mode
|
|
);
|
|
if (wrap_line.newLineMode !== NO_NEWLINE)
|
|
{
|
|
cursor_x = start_x;
|
|
cursor_y += this.lineHeight;
|
|
}
|
|
else
|
|
{
|
|
cursor_x += wrap_line.width;
|
|
}
|
|
}
|
|
this.context.restore();
|
|
}
|
|
else
|
|
{
|
|
pensMgr.addPen(proText, // text
|
|
null, // x
|
|
null, // y
|
|
null, // width
|
|
__curr_propScope, // prop
|
|
0 // new_line_mode
|
|
);
|
|
}
|
|
continue;
|
|
}
|
|
} // for (i = 0; i < match_cnt; i++)
|
|
for (var k in __curr_propScope)
|
|
delete __curr_propScope[k];
|
|
};
|
|
var update_propScope = function(propScope, op, prop, value)
|
|
{
|
|
if (op === PROP_ADD)
|
|
propScope[prop] = value;
|
|
else
|
|
remove_prop(propScope, prop);
|
|
return propScope;
|
|
};
|
|
var remove_prop = function (propScope, prop)
|
|
{
|
|
if (propScope.hasOwnProperty(prop))
|
|
delete propScope[prop];
|
|
};
|
|
CanvasTextProto.drawText = function ()
|
|
{
|
|
var textInfo = this.textInfo;
|
|
if (this.text_changed)
|
|
{
|
|
this.updatePens(this.pensMgr, textInfo);
|
|
this.text_changed = false;
|
|
}
|
|
if (!textInfo["ignore"])
|
|
{
|
|
this.context.textBaseline = this.textBaseline;
|
|
this.context.textAlign = this.textAlign;
|
|
this.preProcess();
|
|
this.drawPens(this.pensMgr, textInfo);
|
|
this.postProcess();
|
|
}
|
|
};
|
|
var __tempPensMgr = null;
|
|
CanvasTextProto.getSubText = function (start, end, text)
|
|
{
|
|
if (text == null)
|
|
return this.pensMgr.getSliceTagText(start, end);
|
|
if (__tempPensMgr === null)
|
|
__tempPensMgr = new PensMgrKlass();
|
|
var text_save = this.textInfo["text"];
|
|
this.textInfo["text"] = text;
|
|
this.updatePens(__tempPensMgr, this.textInfo, true);
|
|
this.textInfo["text"] = text_save;
|
|
return __tempPensMgr.getSliceTagText(start, end);
|
|
};
|
|
CanvasTextProto.getRawText = function (text)
|
|
{
|
|
if (text == null)
|
|
return this.pensMgr.getRawText();
|
|
var m, match=split_text(text, RAWTEXTONLY_MODE);
|
|
if (match.length === 0)
|
|
return "";
|
|
var i, match_cnt = match.length;
|
|
var innerMatch, rawTxt ="";
|
|
for (i=0; i<match_cnt; i++)
|
|
{
|
|
rawTxt += match[i];
|
|
} // for (i = 0; i < match_cnt; i++)
|
|
return rawTxt;
|
|
};
|
|
CanvasTextProto.copyPensMgr = function (pensMgr)
|
|
{
|
|
return this.pensMgr.copy(pensMgr);
|
|
}
|
|
CanvasTextProto.getTextWidth = function (pensMgr)
|
|
{
|
|
if (pensMgr == null)
|
|
pensMgr = this.pensMgr;
|
|
return pensMgr.getMaxLineWidth();
|
|
} ;
|
|
CanvasTextProto.getLastPen = function (pensMgr)
|
|
{
|
|
if (pensMgr == null)
|
|
pensMgr = this.pensMgr;
|
|
return pensMgr.getLastPen();
|
|
} ;
|
|
/**
|
|
* Save a new class definition.
|
|
*/
|
|
CanvasTextProto.defineClass = function (id, definition) {
|
|
this.savedClasses[id] = definition;
|
|
return true;
|
|
};
|
|
/**
|
|
* Returns a saved class.
|
|
*/
|
|
CanvasTextProto.getClass = function (id) {
|
|
return this.savedClasses[id];
|
|
};
|
|
/**
|
|
* A simple function to check if the given value is empty.
|
|
*/
|
|
var isEmpty = function (str) {
|
|
str = str.replace(/^\s+|\s+$/, '');
|
|
return str.length == 0;
|
|
};
|
|
/**
|
|
* A simple function clear whitespaces.
|
|
*/
|
|
CanvasTextProto.trim = function (str) {
|
|
var ws, i;
|
|
str = str.replace(/^\s\s*/, '');
|
|
ws = /\s/;
|
|
i = str.length;
|
|
while (ws.test(str.charAt(--i))) {
|
|
continue;
|
|
}
|
|
return str.slice(0, i + 1);
|
|
};
|
|
CanvasTextProto.saveToJSON = function ()
|
|
{
|
|
return {
|
|
"cls": this.savedClasses,
|
|
"stroke": [this.stroke.lineWidth, this.stroke.lineJoin],
|
|
"u": [this.underline.thickness, this.underline.offset],
|
|
"bgc": this.backgroundColor
|
|
};
|
|
};
|
|
CanvasTextProto.loadFromJSON = function (o)
|
|
{
|
|
this.savedClasses = o["cls"];
|
|
this.stroke.lineWidth = o["stroke"][0];
|
|
this.stroke.lineJoin = o["stroke"][1];
|
|
this.underline.thickness = o["u"][0];
|
|
this.underline.offset = o["u"][1];
|
|
this.backgroundColor = o["bgc"];
|
|
};
|
|
var NO_NEWLINE = 0;
|
|
var RAW_NEWLINE = 1;
|
|
var WRAPPED_NEWLINE = 2;
|
|
var lineCache = new ObjCacheKlass();
|
|
lineCache.newline = function(text, width, newLineMode)
|
|
{
|
|
var l = this.allocLine() || {};
|
|
l.text = text;
|
|
l.width = width;
|
|
l.newLineMode = newLineMode; // 0= no new line, 1=raw "\n", 2=wrapped "\n"
|
|
return l;
|
|
};
|
|
var __wrapped_lines=[];
|
|
var wordWrap = function (text, ctx, width, wrapbyword, offset_x)
|
|
{
|
|
var lines=__wrapped_lines;
|
|
lineCache.freeAllLines(lines);
|
|
if (!text || !text.length)
|
|
{
|
|
return lines;
|
|
}
|
|
if (width <= 2.0)
|
|
{
|
|
return lines;
|
|
}
|
|
if (text.length <= 100 && text.indexOf("\n") === -1)
|
|
{
|
|
var all_width = ctx.measureText(text).width;
|
|
if (all_width <= (width - offset_x))
|
|
{
|
|
lineCache.freeAllLines(lines);
|
|
lines.push(lineCache.newline(text, all_width, NO_NEWLINE));
|
|
return lines;
|
|
}
|
|
}
|
|
return WrapText(text, lines, ctx, width, wrapbyword, offset_x);
|
|
};
|
|
var WrapText = function (text, lines, ctx, width, wrapbyword, offset_x)
|
|
{
|
|
var wordArray = (wrapbyword)? TokeniseWords(text) : text;
|
|
var cur_line = "";
|
|
var prev_line;
|
|
var line_width;
|
|
var i, wcnt=wordArray.length;
|
|
var lineIndex = 0;
|
|
var line;
|
|
for (i = 0; i < wcnt; i++)
|
|
{
|
|
if (wordArray[i] === "\n")
|
|
{
|
|
if (lineIndex >= 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<lcnt; li++)
|
|
this.lines[li].length = 0; // unlink pens
|
|
__penMgr_penCache.freeAllLines(this.pens);
|
|
__penMgr_lineCache.freeAllLines(this.lines);
|
|
};
|
|
PensMgrKlassProto.addPen = function (txt, x, y, width, prop, new_line_mode)
|
|
{
|
|
var pen = __penMgr_penCache.allocLine();
|
|
if (pen === null)
|
|
{
|
|
pen = new PenKlass();
|
|
}
|
|
pen.setPen(txt, x, y, width, prop, new_line_mode);
|
|
var prev_pen = this.pens[this.pens.length -1];
|
|
if (prev_pen == null)
|
|
pen.startIndex = 0;
|
|
else
|
|
pen.startIndex = prev_pen.getNextStartIndex();
|
|
this.pens.push(pen);
|
|
var line = this.lines[this.lines.length-1];
|
|
if (line == null)
|
|
{
|
|
line = __penMgr_lineCache.allocLine() || [];
|
|
this.lines.push(line);
|
|
}
|
|
line.push(pen);
|
|
if (new_line_mode !== NO_NEWLINE)
|
|
{
|
|
line = __penMgr_lineCache.allocLine() || [];
|
|
this.lines.push(line);
|
|
}
|
|
};
|
|
PensMgrKlassProto.getPens = function ()
|
|
{
|
|
return this.pens;
|
|
};
|
|
PensMgrKlassProto.getLastPen = function ()
|
|
{
|
|
return this.pens[this.pens.length -1];
|
|
};
|
|
PensMgrKlassProto.getLines = function ()
|
|
{
|
|
return this.lines;
|
|
};
|
|
PensMgrKlassProto.getLineStartChartIndex = function (i)
|
|
{
|
|
var line = this.lines[i];
|
|
if (line == null)
|
|
return 0;
|
|
return line[0].startIndex;
|
|
};
|
|
PensMgrKlassProto.getLineEndChartIndex = function (i)
|
|
{
|
|
var li, has_last_pen=false, line;
|
|
for(li=i; 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<lcnt; li++ )
|
|
{
|
|
pens = this.lines[li];
|
|
pcnt = pens.length;
|
|
for (pi=0; pi<pcnt; pi++)
|
|
{
|
|
pen = pens[pi];
|
|
targetPensMgr.addPen(pen.text,
|
|
pen.x,
|
|
pen.y,
|
|
pen.width,
|
|
pen.prop,
|
|
pen.newLineMode);
|
|
}
|
|
}
|
|
return targetPensMgr;
|
|
};
|
|
PensMgrKlassProto.getLineWidth = function (i)
|
|
{
|
|
var line = this.lines[i];
|
|
if (!line)
|
|
return 0;
|
|
var last_pen = line[line.length -1];
|
|
if (!last_pen)
|
|
return 0;
|
|
var first_pen = line[0];
|
|
var line_width = last_pen.getLastX(); // start from 0
|
|
return line_width;
|
|
};
|
|
PensMgrKlassProto.getMaxLineWidth = function ()
|
|
{
|
|
var w, maxW=0, i, cnt=this.lines.length, line, last_pen;
|
|
for (i=0; i<cnt; i++)
|
|
{
|
|
w = this.getLineWidth(i);
|
|
if (w > maxW)
|
|
maxW = w;
|
|
}
|
|
return maxW;
|
|
};
|
|
PensMgrKlassProto.getRawText = function ()
|
|
{
|
|
var txt="", i, cnt=this.pens.length, pen;
|
|
for(i=0; i<cnt; i++)
|
|
txt += this.pens[i].getRawText();
|
|
return txt;
|
|
};
|
|
PensMgrKlassProto.getRawTextLength = function ()
|
|
{
|
|
var l=0, i, cnt=this.pens.length, pen;
|
|
for(i=0; i<cnt; i++)
|
|
l += this.pens[i].getRawText().length;
|
|
return l;
|
|
};
|
|
PensMgrKlassProto.getSliceTagText = function (start, end)
|
|
{
|
|
if (start == null)
|
|
start = 0;
|
|
if (end == null)
|
|
{
|
|
var last_pen = this.getLastPen();
|
|
if (last_pen == null)
|
|
return "";
|
|
end = last_pen.getEndIndex();
|
|
}
|
|
var txt="", i, cnt=this.pens.length, pen, pen_txt, pen_si, pen_ei, in_range;
|
|
var pre_prop;
|
|
var isFirstProp=true;
|
|
for(i=0; i<cnt; i++)
|
|
{
|
|
pen = this.pens[i];
|
|
pen_txt = pen.getRawText();
|
|
pen_si = pen.startIndex;
|
|
pen_ei = pen.getNextStartIndex();
|
|
if (pen_ei < start)
|
|
continue;
|
|
in_range = (pen_si >= 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
|
|
];};
|