mirror of
https://github.com/photonstorm/phaser
synced 2024-11-30 08:31:01 +00:00
60214 lines
No EOL
1.8 MiB
60214 lines
No EOL
1.8 MiB
window["SpinePlugin"] =
|
|
/******/ (function(modules) { // webpackBootstrap
|
|
/******/ // The module cache
|
|
/******/ var installedModules = {};
|
|
/******/
|
|
/******/ // The require function
|
|
/******/ function __webpack_require__(moduleId) {
|
|
/******/
|
|
/******/ // Check if module is in cache
|
|
/******/ if(installedModules[moduleId]) {
|
|
/******/ return installedModules[moduleId].exports;
|
|
/******/ }
|
|
/******/ // Create a new module (and put it into the cache)
|
|
/******/ var module = installedModules[moduleId] = {
|
|
/******/ i: moduleId,
|
|
/******/ l: false,
|
|
/******/ exports: {}
|
|
/******/ };
|
|
/******/
|
|
/******/ // Execute the module function
|
|
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
|
/******/
|
|
/******/ // Flag the module as loaded
|
|
/******/ module.l = true;
|
|
/******/
|
|
/******/ // Return the exports of the module
|
|
/******/ return module.exports;
|
|
/******/ }
|
|
/******/
|
|
/******/
|
|
/******/ // expose the modules object (__webpack_modules__)
|
|
/******/ __webpack_require__.m = modules;
|
|
/******/
|
|
/******/ // expose the module cache
|
|
/******/ __webpack_require__.c = installedModules;
|
|
/******/
|
|
/******/ // define getter function for harmony exports
|
|
/******/ __webpack_require__.d = function(exports, name, getter) {
|
|
/******/ if(!__webpack_require__.o(exports, name)) {
|
|
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
|
|
/******/ }
|
|
/******/ };
|
|
/******/
|
|
/******/ // define __esModule on exports
|
|
/******/ __webpack_require__.r = function(exports) {
|
|
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
|
|
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
/******/ }
|
|
/******/ Object.defineProperty(exports, '__esModule', { value: true });
|
|
/******/ };
|
|
/******/
|
|
/******/ // create a fake namespace object
|
|
/******/ // mode & 1: value is a module id, require it
|
|
/******/ // mode & 2: merge all properties of value into the ns
|
|
/******/ // mode & 4: return value when already ns object
|
|
/******/ // mode & 8|1: behave like require
|
|
/******/ __webpack_require__.t = function(value, mode) {
|
|
/******/ if(mode & 1) value = __webpack_require__(value);
|
|
/******/ if(mode & 8) return value;
|
|
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
|
|
/******/ var ns = Object.create(null);
|
|
/******/ __webpack_require__.r(ns);
|
|
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
|
|
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
|
|
/******/ return ns;
|
|
/******/ };
|
|
/******/
|
|
/******/ // getDefaultExport function for compatibility with non-harmony modules
|
|
/******/ __webpack_require__.n = function(module) {
|
|
/******/ var getter = module && module.__esModule ?
|
|
/******/ function getDefault() { return module['default']; } :
|
|
/******/ function getModuleExports() { return module; };
|
|
/******/ __webpack_require__.d(getter, 'a', getter);
|
|
/******/ return getter;
|
|
/******/ };
|
|
/******/
|
|
/******/ // Object.prototype.hasOwnProperty.call
|
|
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
|
|
/******/
|
|
/******/ // __webpack_public_path__
|
|
/******/ __webpack_require__.p = "";
|
|
/******/
|
|
/******/
|
|
/******/ // Load entry module and return exports
|
|
/******/ return __webpack_require__(__webpack_require__.s = 69);
|
|
/******/ })
|
|
/************************************************************************/
|
|
/******/ ([
|
|
/* 0 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Taken from klasse by mattdesl https://github.com/mattdesl/klasse
|
|
|
|
function hasGetterOrSetter (def)
|
|
{
|
|
return (!!def.get && typeof def.get === 'function') || (!!def.set && typeof def.set === 'function');
|
|
}
|
|
|
|
function getProperty (definition, k, isClassDescriptor)
|
|
{
|
|
// This may be a lightweight object, OR it might be a property that was defined previously.
|
|
|
|
// For simple class descriptors we can just assume its NOT previously defined.
|
|
var def = (isClassDescriptor) ? definition[k] : Object.getOwnPropertyDescriptor(definition, k);
|
|
|
|
if (!isClassDescriptor && def.value && typeof def.value === 'object')
|
|
{
|
|
def = def.value;
|
|
}
|
|
|
|
// This might be a regular property, or it may be a getter/setter the user defined in a class.
|
|
if (def && hasGetterOrSetter(def))
|
|
{
|
|
if (typeof def.enumerable === 'undefined')
|
|
{
|
|
def.enumerable = true;
|
|
}
|
|
|
|
if (typeof def.configurable === 'undefined')
|
|
{
|
|
def.configurable = true;
|
|
}
|
|
|
|
return def;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function hasNonConfigurable (obj, k)
|
|
{
|
|
var prop = Object.getOwnPropertyDescriptor(obj, k);
|
|
|
|
if (!prop)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (prop.value && typeof prop.value === 'object')
|
|
{
|
|
prop = prop.value;
|
|
}
|
|
|
|
if (prop.configurable === false)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Extends the given `myClass` object's prototype with the properties of `definition`.
|
|
*
|
|
* @function extend
|
|
* @ignore
|
|
* @param {Object} ctor The constructor object to mix into.
|
|
* @param {Object} definition A dictionary of functions for the class.
|
|
* @param {boolean} isClassDescriptor Is the definition a class descriptor?
|
|
* @param {Object} [extend] The parent constructor object.
|
|
*/
|
|
function extend (ctor, definition, isClassDescriptor, extend)
|
|
{
|
|
for (var k in definition)
|
|
{
|
|
if (!definition.hasOwnProperty(k))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var def = getProperty(definition, k, isClassDescriptor);
|
|
|
|
if (def !== false)
|
|
{
|
|
// If Extends is used, we will check its prototype to see if the final variable exists.
|
|
|
|
var parent = extend || ctor;
|
|
|
|
if (hasNonConfigurable(parent.prototype, k))
|
|
{
|
|
// Just skip the final property
|
|
if (Class.ignoreFinals)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// We cannot re-define a property that is configurable=false.
|
|
// So we will consider them final and throw an error. This is by
|
|
// default so it is clear to the developer what is happening.
|
|
// You can set ignoreFinals to true if you need to extend a class
|
|
// which has configurable=false; it will simply not re-define final properties.
|
|
throw new Error('cannot override final property \'' + k + '\', set Class.ignoreFinals = true to skip');
|
|
}
|
|
|
|
Object.defineProperty(ctor.prototype, k, def);
|
|
}
|
|
else
|
|
{
|
|
ctor.prototype[k] = definition[k];
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Applies the given `mixins` to the prototype of `myClass`.
|
|
*
|
|
* @function mixin
|
|
* @ignore
|
|
* @param {Object} myClass The constructor object to mix into.
|
|
* @param {Object|Array<Object>} mixins The mixins to apply to the constructor.
|
|
*/
|
|
function mixin (myClass, mixins)
|
|
{
|
|
if (!mixins)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!Array.isArray(mixins))
|
|
{
|
|
mixins = [ mixins ];
|
|
}
|
|
|
|
for (var i = 0; i < mixins.length; i++)
|
|
{
|
|
extend(myClass, mixins[i].prototype || mixins[i]);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates a new class with the given descriptor.
|
|
* The constructor, defined by the name `initialize`,
|
|
* is an optional function. If unspecified, an anonymous
|
|
* function will be used which calls the parent class (if
|
|
* one exists).
|
|
*
|
|
* You can also use `Extends` and `Mixins` to provide subclassing
|
|
* and inheritance.
|
|
*
|
|
* @class Phaser.Class
|
|
* @constructor
|
|
* @param {Object} definition a dictionary of functions for the class
|
|
* @example
|
|
*
|
|
* var MyClass = new Phaser.Class({
|
|
*
|
|
* initialize: function() {
|
|
* this.foo = 2.0;
|
|
* },
|
|
*
|
|
* bar: function() {
|
|
* return this.foo + 5;
|
|
* }
|
|
* });
|
|
*/
|
|
function Class (definition)
|
|
{
|
|
if (!definition)
|
|
{
|
|
definition = {};
|
|
}
|
|
|
|
// The variable name here dictates what we see in Chrome debugger
|
|
var initialize;
|
|
var Extends;
|
|
|
|
if (definition.initialize)
|
|
{
|
|
if (typeof definition.initialize !== 'function')
|
|
{
|
|
throw new Error('initialize must be a function');
|
|
}
|
|
|
|
initialize = definition.initialize;
|
|
|
|
// Usually we should avoid 'delete' in V8 at all costs.
|
|
// However, its unlikely to make any performance difference
|
|
// here since we only call this on class creation (i.e. not object creation).
|
|
delete definition.initialize;
|
|
}
|
|
else if (definition.Extends)
|
|
{
|
|
var base = definition.Extends;
|
|
|
|
initialize = function ()
|
|
{
|
|
base.apply(this, arguments);
|
|
};
|
|
}
|
|
else
|
|
{
|
|
initialize = function () {};
|
|
}
|
|
|
|
if (definition.Extends)
|
|
{
|
|
initialize.prototype = Object.create(definition.Extends.prototype);
|
|
initialize.prototype.constructor = initialize;
|
|
|
|
// For getOwnPropertyDescriptor to work, we need to act directly on the Extends (or Mixin)
|
|
|
|
Extends = definition.Extends;
|
|
|
|
delete definition.Extends;
|
|
}
|
|
else
|
|
{
|
|
initialize.prototype.constructor = initialize;
|
|
}
|
|
|
|
// Grab the mixins, if they are specified...
|
|
var mixins = null;
|
|
|
|
if (definition.Mixins)
|
|
{
|
|
mixins = definition.Mixins;
|
|
delete definition.Mixins;
|
|
}
|
|
|
|
// First, mixin if we can.
|
|
mixin(initialize, mixins);
|
|
|
|
// Now we grab the actual definition which defines the overrides.
|
|
extend(initialize, definition, true, Extends);
|
|
|
|
return initialize;
|
|
}
|
|
|
|
Class.extend = extend;
|
|
Class.mixin = mixin;
|
|
Class.ignoreFinals = false;
|
|
|
|
module.exports = Class;
|
|
|
|
|
|
/***/ }),
|
|
/* 1 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Force a value within the boundaries by clamping it to the range `min`, `max`.
|
|
*
|
|
* @function Phaser.Math.Clamp
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to be clamped.
|
|
* @param {number} min - The minimum bounds.
|
|
* @param {number} max - The maximum bounds.
|
|
*
|
|
* @return {number} The clamped value.
|
|
*/
|
|
var Clamp = function (value, min, max)
|
|
{
|
|
return Math.max(min, Math.min(max, value));
|
|
};
|
|
|
|
module.exports = Clamp;
|
|
|
|
|
|
/***/ }),
|
|
/* 2 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* A NOOP (No Operation) callback function.
|
|
*
|
|
* Used internally by Phaser when it's more expensive to determine if a callback exists
|
|
* than it is to just invoke an empty function.
|
|
*
|
|
* @function Phaser.Utils.NOOP
|
|
* @since 3.0.0
|
|
*/
|
|
var NOOP = function ()
|
|
{
|
|
// NOOP
|
|
};
|
|
|
|
module.exports = NOOP;
|
|
|
|
|
|
/***/ }),
|
|
/* 3 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji
|
|
// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl
|
|
|
|
var Class = __webpack_require__(0);
|
|
var FuzzyEqual = __webpack_require__(35);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A representation of a vector in 2D space.
|
|
*
|
|
* A two-component vector.
|
|
*
|
|
* @class Vector2
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number|Phaser.Types.Math.Vector2Like} [x=0] - The x component, or an object with `x` and `y` properties.
|
|
* @param {number} [y=x] - The y component.
|
|
*/
|
|
var Vector2 = new Class({
|
|
|
|
initialize:
|
|
|
|
function Vector2 (x, y)
|
|
{
|
|
/**
|
|
* The x component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector2#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.x = 0;
|
|
|
|
/**
|
|
* The y component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector2#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.y = 0;
|
|
|
|
if (typeof x === 'object')
|
|
{
|
|
this.x = x.x || 0;
|
|
this.y = x.y || 0;
|
|
}
|
|
else
|
|
{
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Make a clone of this Vector2.
|
|
*
|
|
* @method Phaser.Math.Vector2#clone
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector2} A clone of this Vector2.
|
|
*/
|
|
clone: function ()
|
|
{
|
|
return new Vector2(this.x, this.y);
|
|
},
|
|
|
|
/**
|
|
* Copy the components of a given Vector into this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#copy
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector to copy the components from.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
copy: function (src)
|
|
{
|
|
this.x = src.x || 0;
|
|
this.y = src.y || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the component values of this Vector from a given Vector2Like object.
|
|
*
|
|
* @method Phaser.Math.Vector2#setFromObject
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} obj - The object containing the component values to set for this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
setFromObject: function (obj)
|
|
{
|
|
this.x = obj.x || 0;
|
|
this.y = obj.y || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the `x` and `y` components of the this Vector to the given `x` and `y` values.
|
|
*
|
|
* @method Phaser.Math.Vector2#set
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The x value to set for this Vector.
|
|
* @param {number} [y=x] - The y value to set for this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
set: function (x, y)
|
|
{
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* This method is an alias for `Vector2.set`.
|
|
*
|
|
* @method Phaser.Math.Vector2#setTo
|
|
* @since 3.4.0
|
|
*
|
|
* @param {number} x - The x value to set for this Vector.
|
|
* @param {number} [y=x] - The y value to set for this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
setTo: function (x, y)
|
|
{
|
|
return this.set(x, y);
|
|
},
|
|
|
|
/**
|
|
* Sets the `x` and `y` values of this object from a given polar coordinate.
|
|
*
|
|
* @method Phaser.Math.Vector2#setToPolar
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} azimuth - The angular coordinate, in radians.
|
|
* @param {number} [radius=1] - The radial coordinate (length).
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
setToPolar: function (azimuth, radius)
|
|
{
|
|
if (radius == null) { radius = 1; }
|
|
|
|
this.x = Math.cos(azimuth) * radius;
|
|
this.y = Math.sin(azimuth) * radius;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Check whether this Vector is equal to a given Vector.
|
|
*
|
|
* Performs a strict equality check against each Vector's components.
|
|
*
|
|
* @method Phaser.Math.Vector2#equals
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} v - The vector to compare with this Vector.
|
|
*
|
|
* @return {boolean} Whether the given Vector is equal to this Vector.
|
|
*/
|
|
equals: function (v)
|
|
{
|
|
return ((this.x === v.x) && (this.y === v.y));
|
|
},
|
|
|
|
/**
|
|
* Check whether this Vector is approximately equal to a given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#fuzzyEquals
|
|
* @since 3.23.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} v - The vector to compare with this Vector.
|
|
* @param {number} [epsilon=0.0001] - The tolerance value.
|
|
*
|
|
* @return {boolean} Whether both absolute differences of the x and y components are smaller than `epsilon`.
|
|
*/
|
|
fuzzyEquals: function (v, epsilon)
|
|
{
|
|
return (FuzzyEqual(this.x, v.x, epsilon) && FuzzyEqual(this.y, v.y, epsilon));
|
|
},
|
|
|
|
/**
|
|
* Calculate the angle between this Vector and the positive x-axis, in radians.
|
|
*
|
|
* @method Phaser.Math.Vector2#angle
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The angle between this Vector, and the positive x-axis, given in radians.
|
|
*/
|
|
angle: function ()
|
|
{
|
|
// computes the angle in radians with respect to the positive x-axis
|
|
|
|
var angle = Math.atan2(this.y, this.x);
|
|
|
|
if (angle < 0)
|
|
{
|
|
angle += 2 * Math.PI;
|
|
}
|
|
|
|
return angle;
|
|
},
|
|
|
|
/**
|
|
* Set the angle of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#setAngle
|
|
* @since 3.23.0
|
|
*
|
|
* @param {number} angle - The angle, in radians.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
setAngle: function (angle)
|
|
{
|
|
return this.setToPolar(angle, this.length());
|
|
},
|
|
|
|
/**
|
|
* Add a given Vector to this Vector. Addition is component-wise.
|
|
*
|
|
* @method Phaser.Math.Vector2#add
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector to add to this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
add: function (src)
|
|
{
|
|
this.x += src.x;
|
|
this.y += src.y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Subtract the given Vector from this Vector. Subtraction is component-wise.
|
|
*
|
|
* @method Phaser.Math.Vector2#subtract
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector to subtract from this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
subtract: function (src)
|
|
{
|
|
this.x -= src.x;
|
|
this.y -= src.y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Perform a component-wise multiplication between this Vector and the given Vector.
|
|
*
|
|
* Multiplies this Vector by the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#multiply
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector to multiply this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
multiply: function (src)
|
|
{
|
|
this.x *= src.x;
|
|
this.y *= src.y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Scale this Vector by the given value.
|
|
*
|
|
* @method Phaser.Math.Vector2#scale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to scale this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
scale: function (value)
|
|
{
|
|
if (isFinite(value))
|
|
{
|
|
this.x *= value;
|
|
this.y *= value;
|
|
}
|
|
else
|
|
{
|
|
this.x = 0;
|
|
this.y = 0;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Perform a component-wise division between this Vector and the given Vector.
|
|
*
|
|
* Divides this Vector by the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#divide
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector to divide this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
divide: function (src)
|
|
{
|
|
this.x /= src.x;
|
|
this.y /= src.y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Negate the `x` and `y` components of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#negate
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
negate: function ()
|
|
{
|
|
this.x = -this.x;
|
|
this.y = -this.y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance between this Vector and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#distance
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector to calculate the distance to.
|
|
*
|
|
* @return {number} The distance from this Vector to the given Vector.
|
|
*/
|
|
distance: function (src)
|
|
{
|
|
var dx = src.x - this.x;
|
|
var dy = src.y - this.y;
|
|
|
|
return Math.sqrt(dx * dx + dy * dy);
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance between this Vector and the given Vector, squared.
|
|
*
|
|
* @method Phaser.Math.Vector2#distanceSq
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector to calculate the distance to.
|
|
*
|
|
* @return {number} The distance from this Vector to the given Vector, squared.
|
|
*/
|
|
distanceSq: function (src)
|
|
{
|
|
var dx = src.x - this.x;
|
|
var dy = src.y - this.y;
|
|
|
|
return dx * dx + dy * dy;
|
|
},
|
|
|
|
/**
|
|
* Calculate the length (or magnitude) of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#length
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Vector.
|
|
*/
|
|
length: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
|
|
return Math.sqrt(x * x + y * y);
|
|
},
|
|
|
|
/**
|
|
* Set the length (or magnitude) of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#setLength
|
|
* @since 3.23.0
|
|
*
|
|
* @param {number} length
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
setLength: function (length)
|
|
{
|
|
return this.normalize().scale(length);
|
|
},
|
|
|
|
/**
|
|
* Calculate the length of this Vector squared.
|
|
*
|
|
* @method Phaser.Math.Vector2#lengthSq
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Vector, squared.
|
|
*/
|
|
lengthSq: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
|
|
return x * x + y * y;
|
|
},
|
|
|
|
/**
|
|
* Normalize this Vector.
|
|
*
|
|
* Makes the vector a unit length vector (magnitude of 1) in the same direction.
|
|
*
|
|
* @method Phaser.Math.Vector2#normalize
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
normalize: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var len = x * x + y * y;
|
|
|
|
if (len > 0)
|
|
{
|
|
len = 1 / Math.sqrt(len);
|
|
|
|
this.x = x * len;
|
|
this.y = y * len;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Rotate this Vector to its perpendicular, in the positive direction.
|
|
*
|
|
* @method Phaser.Math.Vector2#normalizeRightHand
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
normalizeRightHand: function ()
|
|
{
|
|
var x = this.x;
|
|
|
|
this.x = this.y * -1;
|
|
this.y = x;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Rotate this Vector to its perpendicular, in the negative direction.
|
|
*
|
|
* @method Phaser.Math.Vector2#normalizeLeftHand
|
|
* @since 3.23.0
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
normalizeLeftHand: function ()
|
|
{
|
|
var x = this.x;
|
|
|
|
this.x = this.y;
|
|
this.y = x * -1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the dot product of this Vector and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#dot
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector2 to dot product with this Vector2.
|
|
*
|
|
* @return {number} The dot product of this Vector and the given Vector.
|
|
*/
|
|
dot: function (src)
|
|
{
|
|
return this.x * src.x + this.y * src.y;
|
|
},
|
|
|
|
/**
|
|
* Calculate the cross product of this Vector and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#cross
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector2 to cross with this Vector2.
|
|
*
|
|
* @return {number} The cross product of this Vector and the given Vector.
|
|
*/
|
|
cross: function (src)
|
|
{
|
|
return this.x * src.y - this.y * src.x;
|
|
},
|
|
|
|
/**
|
|
* Linearly interpolate between this Vector and the given Vector.
|
|
*
|
|
* Interpolates this Vector towards the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#lerp
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} src - The Vector2 to interpolate towards.
|
|
* @param {number} [t=0] - The interpolation percentage, between 0 and 1.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
lerp: function (src, t)
|
|
{
|
|
if (t === undefined) { t = 0; }
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
|
|
this.x = ax + t * (src.x - ax);
|
|
this.y = ay + t * (src.y - ay);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform this Vector with the given Matrix.
|
|
*
|
|
* @method Phaser.Math.Vector2#transformMat3
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} mat - The Matrix3 to transform this Vector2 with.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
transformMat3: function (mat)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var m = mat.val;
|
|
|
|
this.x = m[0] * x + m[3] * y + m[6];
|
|
this.y = m[1] * x + m[4] * y + m[7];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform this Vector with the given Matrix.
|
|
*
|
|
* @method Phaser.Math.Vector2#transformMat4
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector2 with.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
transformMat4: function (mat)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var m = mat.val;
|
|
|
|
this.x = m[0] * x + m[4] * y + m[12];
|
|
this.y = m[1] * x + m[5] * y + m[13];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Make this Vector the zero vector (0, 0).
|
|
*
|
|
* @method Phaser.Math.Vector2#reset
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
reset: function ()
|
|
{
|
|
this.x = 0;
|
|
this.y = 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Limit the length (or magnitude) of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector2#limit
|
|
* @since 3.23.0
|
|
*
|
|
* @param {number} max - The maximum length.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
limit: function (max)
|
|
{
|
|
var len = this.length();
|
|
|
|
if (len && len > max)
|
|
{
|
|
this.scale(max / len);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Reflect this Vector off a line defined by a normal.
|
|
*
|
|
* @method Phaser.Math.Vector2#reflect
|
|
* @since 3.23.0
|
|
*
|
|
* @param {Phaser.Math.Vector2} normal - A vector perpendicular to the line.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
reflect: function (normal)
|
|
{
|
|
normal = normal.clone().normalize();
|
|
|
|
return this.subtract(normal.scale(2 * this.dot(normal)));
|
|
},
|
|
|
|
/**
|
|
* Reflect this Vector across another.
|
|
*
|
|
* @method Phaser.Math.Vector2#mirror
|
|
* @since 3.23.0
|
|
*
|
|
* @param {Phaser.Math.Vector2} axis - A vector to reflect across.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
mirror: function (axis)
|
|
{
|
|
return this.reflect(axis).negate();
|
|
},
|
|
|
|
/**
|
|
* Rotate this Vector by an angle amount.
|
|
*
|
|
* @method Phaser.Math.Vector2#rotate
|
|
* @since 3.23.0
|
|
*
|
|
* @param {number} delta - The angle to rotate by, in radians.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
rotate: function (delta)
|
|
{
|
|
var cos = Math.cos(delta);
|
|
var sin = Math.sin(delta);
|
|
|
|
return this.set(cos * this.x - sin * this.y, sin * this.x + cos * this.y);
|
|
},
|
|
|
|
/**
|
|
* Project this Vector onto another.
|
|
*
|
|
* @method Phaser.Math.Vector2#project
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Math.Vector2} src - The vector to project onto.
|
|
*
|
|
* @return {Phaser.Math.Vector2} This Vector2.
|
|
*/
|
|
project: function (src)
|
|
{
|
|
var scalar = this.dot(src) / src.dot(src);
|
|
|
|
return this.copy(src).scale(scalar);
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* A static zero Vector2 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector2.ZERO
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.1.0
|
|
*/
|
|
Vector2.ZERO = new Vector2();
|
|
|
|
/**
|
|
* A static right Vector2 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector2.RIGHT
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector2.RIGHT = new Vector2(1, 0);
|
|
|
|
/**
|
|
* A static left Vector2 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector2.LEFT
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector2.LEFT = new Vector2(-1, 0);
|
|
|
|
/**
|
|
* A static up Vector2 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector2.UP
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector2.UP = new Vector2(0, -1);
|
|
|
|
/**
|
|
* A static down Vector2 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector2.DOWN
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector2.DOWN = new Vector2(0, 1);
|
|
|
|
/**
|
|
* A static one Vector2 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector2.ONE
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector2.ONE = new Vector2(1, 1);
|
|
|
|
module.exports = Vector2;
|
|
|
|
|
|
/***/ }),
|
|
/* 4 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var MATH_CONST = {
|
|
|
|
/**
|
|
* The value of PI * 2.
|
|
*
|
|
* @name Phaser.Math.PI2
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
PI2: Math.PI * 2,
|
|
|
|
/**
|
|
* The value of PI * 0.5.
|
|
*
|
|
* @name Phaser.Math.TAU
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
TAU: Math.PI * 0.5,
|
|
|
|
/**
|
|
* An epsilon value (1.0e-6)
|
|
*
|
|
* @name Phaser.Math.EPSILON
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
EPSILON: 1.0e-6,
|
|
|
|
/**
|
|
* For converting degrees to radians (PI / 180)
|
|
*
|
|
* @name Phaser.Math.DEG_TO_RAD
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
DEG_TO_RAD: Math.PI / 180,
|
|
|
|
/**
|
|
* For converting radians to degrees (180 / PI)
|
|
*
|
|
* @name Phaser.Math.RAD_TO_DEG
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
RAD_TO_DEG: 180 / Math.PI,
|
|
|
|
/**
|
|
* An instance of the Random Number Generator.
|
|
* This is not set until the Game boots.
|
|
*
|
|
* @name Phaser.Math.RND
|
|
* @type {Phaser.Math.RandomDataGenerator}
|
|
* @since 3.0.0
|
|
*/
|
|
RND: null,
|
|
|
|
/**
|
|
* The minimum safe integer this browser supports.
|
|
* We use a const for backward compatibility with Internet Explorer.
|
|
*
|
|
* @name Phaser.Math.MIN_SAFE_INTEGER
|
|
* @type {number}
|
|
* @since 3.21.0
|
|
*/
|
|
MIN_SAFE_INTEGER: Number.MIN_SAFE_INTEGER || -9007199254740991,
|
|
|
|
/**
|
|
* The maximum safe integer this browser supports.
|
|
* We use a const for backward compatibility with Internet Explorer.
|
|
*
|
|
* @name Phaser.Math.MAX_SAFE_INTEGER
|
|
* @type {number}
|
|
* @since 3.21.0
|
|
*/
|
|
MAX_SAFE_INTEGER: Number.MAX_SAFE_INTEGER || 9007199254740991
|
|
|
|
};
|
|
|
|
module.exports = MATH_CONST;
|
|
|
|
|
|
/***/ }),
|
|
/* 5 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Tests if the start and end indexes are a safe range for the given array.
|
|
*
|
|
* @function Phaser.Utils.Array.SafeRange
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to check.
|
|
* @param {number} startIndex - The start index.
|
|
* @param {number} endIndex - The end index.
|
|
* @param {boolean} [throwError=true] - Throw an error if the range is out of bounds.
|
|
*
|
|
* @return {boolean} True if the range is safe, otherwise false.
|
|
*/
|
|
var SafeRange = function (array, startIndex, endIndex, throwError)
|
|
{
|
|
var len = array.length;
|
|
|
|
if (startIndex < 0 ||
|
|
startIndex > len ||
|
|
startIndex >= endIndex ||
|
|
endIndex > len)
|
|
{
|
|
if (throwError)
|
|
{
|
|
throw new Error('Range Error: Values outside acceptable range');
|
|
}
|
|
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
return true;
|
|
}
|
|
};
|
|
|
|
module.exports = SafeRange;
|
|
|
|
|
|
/***/ }),
|
|
/* 6 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Wrap the given `value` between `min` and `max`.
|
|
*
|
|
* @function Phaser.Math.Wrap
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to wrap.
|
|
* @param {number} min - The minimum value.
|
|
* @param {number} max - The maximum value.
|
|
*
|
|
* @return {number} The wrapped value.
|
|
*/
|
|
var Wrap = function (value, min, max)
|
|
{
|
|
var range = max - min;
|
|
|
|
return (min + ((((value - min) % range) + range) % range));
|
|
};
|
|
|
|
module.exports = Wrap;
|
|
|
|
|
|
/***/ }),
|
|
/* 7 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* This is a slightly modified version of jQuery.isPlainObject.
|
|
* A plain object is an object whose internal class property is [object Object].
|
|
*
|
|
* @function Phaser.Utils.Objects.IsPlainObject
|
|
* @since 3.0.0
|
|
*
|
|
* @param {object} obj - The object to inspect.
|
|
*
|
|
* @return {boolean} `true` if the object is plain, otherwise `false`.
|
|
*/
|
|
var IsPlainObject = function (obj)
|
|
{
|
|
// Not plain objects:
|
|
// - Any object or value whose internal [[Class]] property is not "[object Object]"
|
|
// - DOM nodes
|
|
// - window
|
|
if (!obj || typeof(obj) !== 'object' || obj.nodeType || obj === obj.window)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Support: Firefox <20
|
|
// The try/catch suppresses exceptions thrown when attempting to access
|
|
// the "constructor" property of certain host objects, ie. |window.location|
|
|
// https://bugzilla.mozilla.org/show_bug.cgi?id=814622
|
|
try
|
|
{
|
|
if (obj.constructor && !({}).hasOwnProperty.call(obj.constructor.prototype, 'isPrototypeOf'))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// If the function hasn't returned already, we're confident that
|
|
// |obj| is a plain object, created by {} or constructed with new Object
|
|
return true;
|
|
};
|
|
|
|
module.exports = IsPlainObject;
|
|
|
|
|
|
/***/ }),
|
|
/* 8 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CONST = __webpack_require__(4);
|
|
|
|
/**
|
|
* Takes an angle in Phasers default clockwise format and converts it so that
|
|
* 0 is North, 90 is West, 180 is South and 270 is East,
|
|
* therefore running counter-clockwise instead of clockwise.
|
|
*
|
|
* You can pass in the angle from a Game Object using:
|
|
*
|
|
* ```javascript
|
|
* var converted = CounterClockwise(gameobject.rotation);
|
|
* ```
|
|
*
|
|
* All values for this function are in radians.
|
|
*
|
|
* @function Phaser.Math.Angle.CounterClockwise
|
|
* @since 3.16.0
|
|
*
|
|
* @param {number} angle - The angle to convert, in radians.
|
|
*
|
|
* @return {number} The converted angle, in radians.
|
|
*/
|
|
var CounterClockwise = function (angle)
|
|
{
|
|
if (angle > Math.PI)
|
|
{
|
|
angle -= CONST.PI2;
|
|
}
|
|
|
|
return Math.abs((((angle + CONST.TAU) % CONST.PI2) - CONST.PI2) % CONST.PI2);
|
|
};
|
|
|
|
module.exports = CounterClockwise;
|
|
|
|
|
|
/***/ }),
|
|
/* 9 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CONST = __webpack_require__(4);
|
|
|
|
/**
|
|
* Convert the given angle in radians, to the equivalent angle in degrees.
|
|
*
|
|
* @function Phaser.Math.RadToDeg
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} radians - The angle in radians to convert ot degrees.
|
|
*
|
|
* @return {number} The given angle converted to degrees.
|
|
*/
|
|
var RadToDeg = function (radians)
|
|
{
|
|
return radians * CONST.RAD_TO_DEG;
|
|
};
|
|
|
|
module.exports = RadToDeg;
|
|
|
|
|
|
/***/ }),
|
|
/* 10 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Retrieves a value from an object, or an alternative object, falling to a back-up default value if not found.
|
|
*
|
|
* The key is a string, which can be split based on the use of the period character.
|
|
*
|
|
* For example:
|
|
*
|
|
* ```javascript
|
|
* const source = {
|
|
* lives: 3,
|
|
* render: {
|
|
* screen: {
|
|
* width: 1024
|
|
* }
|
|
* }
|
|
* }
|
|
*
|
|
* const lives = GetValue(source, 'lives', 1);
|
|
* const width = GetValue(source, 'render.screen.width', 800);
|
|
* const height = GetValue(source, 'render.screen.height', 600);
|
|
* ```
|
|
*
|
|
* In the code above, `lives` will be 3 because it's defined at the top level of `source`.
|
|
* The `width` value will be 1024 because it can be found inside the `render.screen` object.
|
|
* The `height` value will be 600, the default value, because it is missing from the `render.screen` object.
|
|
*
|
|
* @function Phaser.Utils.Objects.GetValue
|
|
* @since 3.0.0
|
|
*
|
|
* @param {object} source - The primary object to try to retrieve the value from. If not found in here, `altSource` is checked.
|
|
* @param {string} key - The name of the property to retrieve from the object. If a property is nested, the names of its preceding properties should be separated by a dot (`.`) - `banner.hideBanner` would return the value of the `hideBanner` property from the object stored in the `banner` property of the `source` object.
|
|
* @param {*} defaultValue - The value to return if the `key` isn't found in the `source` object.
|
|
* @param {object} [altSource] - An alternative object to retrieve the value from. If the property exists in `source` then `altSource` will not be used.
|
|
*
|
|
* @return {*} The value of the requested key.
|
|
*/
|
|
var GetValue = function (source, key, defaultValue, altSource)
|
|
{
|
|
if ((!source && !altSource) || typeof source === 'number')
|
|
{
|
|
return defaultValue;
|
|
}
|
|
else if (source && source.hasOwnProperty(key))
|
|
{
|
|
return source[key];
|
|
}
|
|
else if (altSource && altSource.hasOwnProperty(key))
|
|
{
|
|
return altSource[key];
|
|
}
|
|
else if (key.indexOf('.') !== -1)
|
|
{
|
|
var keys = key.split('.');
|
|
var parentA = source;
|
|
var parentB = altSource;
|
|
var valueA = defaultValue;
|
|
var valueB = defaultValue;
|
|
var valueAFound = true;
|
|
var valueBFound = true;
|
|
|
|
// Use for loop here so we can break early
|
|
for (var i = 0; i < keys.length; i++)
|
|
{
|
|
if (parentA && parentA.hasOwnProperty(keys[i]))
|
|
{
|
|
// Yes parentA has a key property, let's carry on down
|
|
valueA = parentA[keys[i]];
|
|
parentA = parentA[keys[i]];
|
|
}
|
|
else
|
|
{
|
|
valueAFound = false;
|
|
}
|
|
|
|
if (parentB && parentB.hasOwnProperty(keys[i]))
|
|
{
|
|
// Yes parentB has a key property, let's carry on down
|
|
valueB = parentB[keys[i]];
|
|
parentB = parentB[keys[i]];
|
|
}
|
|
else
|
|
{
|
|
valueBFound = false;
|
|
}
|
|
}
|
|
|
|
if (valueAFound)
|
|
{
|
|
return valueA;
|
|
}
|
|
else if (valueBFound)
|
|
{
|
|
return valueB;
|
|
}
|
|
else
|
|
{
|
|
return defaultValue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return defaultValue;
|
|
}
|
|
};
|
|
|
|
module.exports = GetValue;
|
|
|
|
|
|
/***/ }),
|
|
/* 11 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Finds the key within the top level of the {@link source} object, or returns {@link defaultValue}
|
|
*
|
|
* @function Phaser.Utils.Objects.GetFastValue
|
|
* @since 3.0.0
|
|
*
|
|
* @param {object} source - The object to search
|
|
* @param {string} key - The key for the property on source. Must exist at the top level of the source object (no periods)
|
|
* @param {*} [defaultValue] - The default value to use if the key does not exist.
|
|
*
|
|
* @return {*} The value if found; otherwise, defaultValue (null if none provided)
|
|
*/
|
|
var GetFastValue = function (source, key, defaultValue)
|
|
{
|
|
var t = typeof(source);
|
|
|
|
if (!source || t === 'number' || t === 'string')
|
|
{
|
|
return defaultValue;
|
|
}
|
|
else if (source.hasOwnProperty(key) && source[key] !== undefined)
|
|
{
|
|
return source[key];
|
|
}
|
|
else
|
|
{
|
|
return defaultValue;
|
|
}
|
|
};
|
|
|
|
module.exports = GetFastValue;
|
|
|
|
|
|
/***/ }),
|
|
/* 12 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var FILE_CONST = {
|
|
|
|
/**
|
|
* The Loader is idle.
|
|
*
|
|
* @name Phaser.Loader.LOADER_IDLE
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
LOADER_IDLE: 0,
|
|
|
|
/**
|
|
* The Loader is actively loading.
|
|
*
|
|
* @name Phaser.Loader.LOADER_LOADING
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
LOADER_LOADING: 1,
|
|
|
|
/**
|
|
* The Loader is processing files is has loaded.
|
|
*
|
|
* @name Phaser.Loader.LOADER_PROCESSING
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
LOADER_PROCESSING: 2,
|
|
|
|
/**
|
|
* The Loader has completed loading and processing.
|
|
*
|
|
* @name Phaser.Loader.LOADER_COMPLETE
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
LOADER_COMPLETE: 3,
|
|
|
|
/**
|
|
* The Loader is shutting down.
|
|
*
|
|
* @name Phaser.Loader.LOADER_SHUTDOWN
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
LOADER_SHUTDOWN: 4,
|
|
|
|
/**
|
|
* The Loader has been destroyed.
|
|
*
|
|
* @name Phaser.Loader.LOADER_DESTROYED
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
LOADER_DESTROYED: 5,
|
|
|
|
/**
|
|
* File is in the load queue but not yet started.
|
|
*
|
|
* @name Phaser.Loader.FILE_PENDING
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_PENDING: 10,
|
|
|
|
/**
|
|
* File has been started to load by the loader (onLoad called)
|
|
*
|
|
* @name Phaser.Loader.FILE_LOADING
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_LOADING: 11,
|
|
|
|
/**
|
|
* File has loaded successfully, awaiting processing.
|
|
*
|
|
* @name Phaser.Loader.FILE_LOADED
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_LOADED: 12,
|
|
|
|
/**
|
|
* File failed to load.
|
|
*
|
|
* @name Phaser.Loader.FILE_FAILED
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_FAILED: 13,
|
|
|
|
/**
|
|
* File is being processed (onProcess callback)
|
|
*
|
|
* @name Phaser.Loader.FILE_PROCESSING
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_PROCESSING: 14,
|
|
|
|
/**
|
|
* The File has errored somehow during processing.
|
|
*
|
|
* @name Phaser.Loader.FILE_ERRORED
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_ERRORED: 16,
|
|
|
|
/**
|
|
* File has finished processing.
|
|
*
|
|
* @name Phaser.Loader.FILE_COMPLETE
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_COMPLETE: 17,
|
|
|
|
/**
|
|
* File has been destroyed.
|
|
*
|
|
* @name Phaser.Loader.FILE_DESTROYED
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_DESTROYED: 18,
|
|
|
|
/**
|
|
* File was populated from local data and doesn't need an HTTP request.
|
|
*
|
|
* @name Phaser.Loader.FILE_POPULATED
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FILE_POPULATED: 19,
|
|
|
|
/**
|
|
* File is pending being destroyed.
|
|
*
|
|
* @name Phaser.Loader.FILE_PENDING_DESTROY
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
FILE_PENDING_DESTROY: 20
|
|
|
|
};
|
|
|
|
module.exports = FILE_CONST;
|
|
|
|
|
|
/***/ }),
|
|
/* 13 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Removes a single item from an array and returns it without creating gc, like the native splice does.
|
|
* Based on code by Mike Reinstein.
|
|
*
|
|
* @function Phaser.Utils.Array.SpliceOne
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} array - The array to splice from.
|
|
* @param {number} index - The index of the item which should be spliced.
|
|
*
|
|
* @return {*} The item which was spliced (removed).
|
|
*/
|
|
var SpliceOne = function (array, index)
|
|
{
|
|
if (index >= array.length)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var len = array.length - 1;
|
|
|
|
var item = array[index];
|
|
|
|
for (var i = index; i < len; i++)
|
|
{
|
|
array[i] = array[i + 1];
|
|
}
|
|
|
|
array.length = len;
|
|
|
|
return item;
|
|
};
|
|
|
|
module.exports = SpliceOne;
|
|
|
|
|
|
/***/ }),
|
|
/* 14 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var GEOM_CONST = __webpack_require__(30);
|
|
|
|
/**
|
|
* @classdesc
|
|
* Defines a Point in 2D space, with an x and y component.
|
|
*
|
|
* @class Point
|
|
* @memberof Phaser.Geom
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=0] - The x coordinate of this Point.
|
|
* @param {number} [y=x] - The y coordinate of this Point.
|
|
*/
|
|
var Point = new Class({
|
|
|
|
initialize:
|
|
|
|
function Point (x, y)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = x; }
|
|
|
|
/**
|
|
* The geometry constant type of this object: `GEOM_CONST.POINT`.
|
|
* Used for fast type comparisons.
|
|
*
|
|
* @name Phaser.Geom.Point#type
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.19.0
|
|
*/
|
|
this.type = GEOM_CONST.POINT;
|
|
|
|
/**
|
|
* The x coordinate of this Point.
|
|
*
|
|
* @name Phaser.Geom.Point#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.x = x;
|
|
|
|
/**
|
|
* The y coordinate of this Point.
|
|
*
|
|
* @name Phaser.Geom.Point#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.y = y;
|
|
},
|
|
|
|
/**
|
|
* Set the x and y coordinates of the point to the given values.
|
|
*
|
|
* @method Phaser.Geom.Point#setTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=0] - The x coordinate of this Point.
|
|
* @param {number} [y=x] - The y coordinate of this Point.
|
|
*
|
|
* @return {this} This Point object.
|
|
*/
|
|
setTo: function (x, y)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
|
|
return this;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = Point;
|
|
|
|
|
|
/***/ }),
|
|
/* 15 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Phaser Blend Modes.
|
|
*
|
|
* @namespace Phaser.BlendModes
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
/**
|
|
* Skips the Blend Mode check in the renderer.
|
|
*
|
|
* @name Phaser.BlendModes.SKIP_CHECK
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
SKIP_CHECK: -1,
|
|
|
|
/**
|
|
* Normal blend mode. For Canvas and WebGL.
|
|
* This is the default setting and draws new shapes on top of the existing canvas content.
|
|
*
|
|
* @name Phaser.BlendModes.NORMAL
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
NORMAL: 0,
|
|
|
|
/**
|
|
* Add blend mode. For Canvas and WebGL.
|
|
* Where both shapes overlap the color is determined by adding color values.
|
|
*
|
|
* @name Phaser.BlendModes.ADD
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
ADD: 1,
|
|
|
|
/**
|
|
* Multiply blend mode. For Canvas and WebGL.
|
|
* The pixels are of the top layer are multiplied with the corresponding pixel of the bottom layer. A darker picture is the result.
|
|
*
|
|
* @name Phaser.BlendModes.MULTIPLY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
MULTIPLY: 2,
|
|
|
|
/**
|
|
* Screen blend mode. For Canvas and WebGL.
|
|
* The pixels are inverted, multiplied, and inverted again. A lighter picture is the result (opposite of multiply)
|
|
*
|
|
* @name Phaser.BlendModes.SCREEN
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
SCREEN: 3,
|
|
|
|
/**
|
|
* Overlay blend mode. For Canvas only.
|
|
* A combination of multiply and screen. Dark parts on the base layer become darker, and light parts become lighter.
|
|
*
|
|
* @name Phaser.BlendModes.OVERLAY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
OVERLAY: 4,
|
|
|
|
/**
|
|
* Darken blend mode. For Canvas only.
|
|
* Retains the darkest pixels of both layers.
|
|
*
|
|
* @name Phaser.BlendModes.DARKEN
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
DARKEN: 5,
|
|
|
|
/**
|
|
* Lighten blend mode. For Canvas only.
|
|
* Retains the lightest pixels of both layers.
|
|
*
|
|
* @name Phaser.BlendModes.LIGHTEN
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
LIGHTEN: 6,
|
|
|
|
/**
|
|
* Color Dodge blend mode. For Canvas only.
|
|
* Divides the bottom layer by the inverted top layer.
|
|
*
|
|
* @name Phaser.BlendModes.COLOR_DODGE
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
COLOR_DODGE: 7,
|
|
|
|
/**
|
|
* Color Burn blend mode. For Canvas only.
|
|
* Divides the inverted bottom layer by the top layer, and then inverts the result.
|
|
*
|
|
* @name Phaser.BlendModes.COLOR_BURN
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
COLOR_BURN: 8,
|
|
|
|
/**
|
|
* Hard Light blend mode. For Canvas only.
|
|
* A combination of multiply and screen like overlay, but with top and bottom layer swapped.
|
|
*
|
|
* @name Phaser.BlendModes.HARD_LIGHT
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
HARD_LIGHT: 9,
|
|
|
|
/**
|
|
* Soft Light blend mode. For Canvas only.
|
|
* A softer version of hard-light. Pure black or white does not result in pure black or white.
|
|
*
|
|
* @name Phaser.BlendModes.SOFT_LIGHT
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
SOFT_LIGHT: 10,
|
|
|
|
/**
|
|
* Difference blend mode. For Canvas only.
|
|
* Subtracts the bottom layer from the top layer or the other way round to always get a positive value.
|
|
*
|
|
* @name Phaser.BlendModes.DIFFERENCE
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
DIFFERENCE: 11,
|
|
|
|
/**
|
|
* Exclusion blend mode. For Canvas only.
|
|
* Like difference, but with lower contrast.
|
|
*
|
|
* @name Phaser.BlendModes.EXCLUSION
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
EXCLUSION: 12,
|
|
|
|
/**
|
|
* Hue blend mode. For Canvas only.
|
|
* Preserves the luma and chroma of the bottom layer, while adopting the hue of the top layer.
|
|
*
|
|
* @name Phaser.BlendModes.HUE
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
HUE: 13,
|
|
|
|
/**
|
|
* Saturation blend mode. For Canvas only.
|
|
* Preserves the luma and hue of the bottom layer, while adopting the chroma of the top layer.
|
|
*
|
|
* @name Phaser.BlendModes.SATURATION
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
SATURATION: 14,
|
|
|
|
/**
|
|
* Color blend mode. For Canvas only.
|
|
* Preserves the luma of the bottom layer, while adopting the hue and chroma of the top layer.
|
|
*
|
|
* @name Phaser.BlendModes.COLOR
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
COLOR: 15,
|
|
|
|
/**
|
|
* Luminosity blend mode. For Canvas only.
|
|
* Preserves the hue and chroma of the bottom layer, while adopting the luma of the top layer.
|
|
*
|
|
* @name Phaser.BlendModes.LUMINOSITY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
LUMINOSITY: 16,
|
|
|
|
/**
|
|
* Alpha erase blend mode. For Canvas and WebGL.
|
|
*
|
|
* @name Phaser.BlendModes.ERASE
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
ERASE: 17,
|
|
|
|
/**
|
|
* Source-in blend mode. For Canvas only.
|
|
* The new shape is drawn only where both the new shape and the destination canvas overlap. Everything else is made transparent.
|
|
*
|
|
* @name Phaser.BlendModes.SOURCE_IN
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
SOURCE_IN: 18,
|
|
|
|
/**
|
|
* Source-out blend mode. For Canvas only.
|
|
* The new shape is drawn where it doesn't overlap the existing canvas content.
|
|
*
|
|
* @name Phaser.BlendModes.SOURCE_OUT
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
SOURCE_OUT: 19,
|
|
|
|
/**
|
|
* Source-out blend mode. For Canvas only.
|
|
* The new shape is only drawn where it overlaps the existing canvas content.
|
|
*
|
|
* @name Phaser.BlendModes.SOURCE_ATOP
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
SOURCE_ATOP: 20,
|
|
|
|
/**
|
|
* Destination-over blend mode. For Canvas only.
|
|
* New shapes are drawn behind the existing canvas content.
|
|
*
|
|
* @name Phaser.BlendModes.DESTINATION_OVER
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
DESTINATION_OVER: 21,
|
|
|
|
/**
|
|
* Destination-in blend mode. For Canvas only.
|
|
* The existing canvas content is kept where both the new shape and existing canvas content overlap. Everything else is made transparent.
|
|
*
|
|
* @name Phaser.BlendModes.DESTINATION_IN
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
DESTINATION_IN: 22,
|
|
|
|
/**
|
|
* Destination-out blend mode. For Canvas only.
|
|
* The existing content is kept where it doesn't overlap the new shape.
|
|
*
|
|
* @name Phaser.BlendModes.DESTINATION_OUT
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
DESTINATION_OUT: 23,
|
|
|
|
/**
|
|
* Destination-out blend mode. For Canvas only.
|
|
* The existing canvas is only kept where it overlaps the new shape. The new shape is drawn behind the canvas content.
|
|
*
|
|
* @name Phaser.BlendModes.DESTINATION_ATOP
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
DESTINATION_ATOP: 24,
|
|
|
|
/**
|
|
* Lighten blend mode. For Canvas only.
|
|
* Where both shapes overlap the color is determined by adding color values.
|
|
*
|
|
* @name Phaser.BlendModes.LIGHTER
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
LIGHTER: 25,
|
|
|
|
/**
|
|
* Copy blend mode. For Canvas only.
|
|
* Only the new shape is shown.
|
|
*
|
|
* @name Phaser.BlendModes.COPY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
COPY: 26,
|
|
|
|
/**
|
|
* Xor blend mode. For Canvas only.
|
|
* Shapes are made transparent where both overlap and drawn normal everywhere else.
|
|
*
|
|
* @name Phaser.BlendModes.XOR
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
XOR: 27
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 16 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji
|
|
// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl
|
|
|
|
var Class = __webpack_require__(0);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A representation of a vector in 3D space.
|
|
*
|
|
* A three-component vector.
|
|
*
|
|
* @class Vector3
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x] - The x component.
|
|
* @param {number} [y] - The y component.
|
|
* @param {number} [z] - The z component.
|
|
*/
|
|
var Vector3 = new Class({
|
|
|
|
initialize:
|
|
|
|
function Vector3 (x, y, z)
|
|
{
|
|
/**
|
|
* The x component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector3#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.x = 0;
|
|
|
|
/**
|
|
* The y component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector3#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.y = 0;
|
|
|
|
/**
|
|
* The z component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector3#z
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.z = 0;
|
|
|
|
if (typeof x === 'object')
|
|
{
|
|
this.x = x.x || 0;
|
|
this.y = x.y || 0;
|
|
this.z = x.z || 0;
|
|
}
|
|
else
|
|
{
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
this.z = z || 0;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Set this Vector to point up.
|
|
*
|
|
* Sets the y component of the vector to 1, and the others to 0.
|
|
*
|
|
* @method Phaser.Math.Vector3#up
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
up: function ()
|
|
{
|
|
this.x = 0;
|
|
this.y = 1;
|
|
this.z = 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the components of this Vector to be the `Math.min` result from the given vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#min
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} v - The Vector3 to check the minimum values against.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
min: function (v)
|
|
{
|
|
this.x = Math.min(this.x, v.x);
|
|
this.y = Math.min(this.y, v.y);
|
|
this.z = Math.min(this.z, v.z);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the components of this Vector to be the `Math.max` result from the given vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#max
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} v - The Vector3 to check the maximum values against.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
max: function (v)
|
|
{
|
|
this.x = Math.max(this.x, v.x);
|
|
this.y = Math.max(this.y, v.y);
|
|
this.z = Math.max(this.z, v.z);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Make a clone of this Vector3.
|
|
*
|
|
* @method Phaser.Math.Vector3#clone
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector3} A new Vector3 object containing this Vectors values.
|
|
*/
|
|
clone: function ()
|
|
{
|
|
return new Vector3(this.x, this.y, this.z);
|
|
},
|
|
|
|
/**
|
|
* Adds the two given Vector3s and sets the results into this Vector3.
|
|
*
|
|
* @method Phaser.Math.Vector3#addVectors
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} a - The first Vector to add.
|
|
* @param {Phaser.Math.Vector3} b - The second Vector to add.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
addVectors: function (a, b)
|
|
{
|
|
this.x = a.x + b.x;
|
|
this.y = a.y + b.y;
|
|
this.z = a.z + b.z;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the cross (vector) product of two given Vectors.
|
|
*
|
|
* @method Phaser.Math.Vector3#crossVectors
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} a - The first Vector to multiply.
|
|
* @param {Phaser.Math.Vector3} b - The second Vector to multiply.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
crossVectors: function (a, b)
|
|
{
|
|
var ax = a.x;
|
|
var ay = a.y;
|
|
var az = a.z;
|
|
var bx = b.x;
|
|
var by = b.y;
|
|
var bz = b.z;
|
|
|
|
this.x = ay * bz - az * by;
|
|
this.y = az * bx - ax * bz;
|
|
this.z = ax * by - ay * bx;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Check whether this Vector is equal to a given Vector.
|
|
*
|
|
* Performs a strict equality check against each Vector's components.
|
|
*
|
|
* @method Phaser.Math.Vector3#equals
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} v - The Vector3 to compare against.
|
|
*
|
|
* @return {boolean} True if the two vectors strictly match, otherwise false.
|
|
*/
|
|
equals: function (v)
|
|
{
|
|
return ((this.x === v.x) && (this.y === v.y) && (this.z === v.z));
|
|
},
|
|
|
|
/**
|
|
* Copy the components of a given Vector into this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#copy
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} src - The Vector to copy the components from.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
copy: function (src)
|
|
{
|
|
this.x = src.x;
|
|
this.y = src.y;
|
|
this.z = src.z || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the `x`, `y`, and `z` components of this Vector to the given `x`, `y`, and `z` values.
|
|
*
|
|
* @method Phaser.Math.Vector3#set
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(number|object)} x - The x value to set for this Vector, or an object containing x, y and z components.
|
|
* @param {number} [y] - The y value to set for this Vector.
|
|
* @param {number} [z] - The z value to set for this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
set: function (x, y, z)
|
|
{
|
|
if (typeof x === 'object')
|
|
{
|
|
this.x = x.x || 0;
|
|
this.y = x.y || 0;
|
|
this.z = x.z || 0;
|
|
}
|
|
else
|
|
{
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
this.z = z || 0;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the components of this Vector3 from the position of the given Matrix4.
|
|
*
|
|
* @method Phaser.Math.Vector3#setFromMatrixPosition
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to get the position from.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
setFromMatrixPosition: function (m)
|
|
{
|
|
return this.fromArray(m.val, 12);
|
|
},
|
|
|
|
/**
|
|
* Sets the components of this Vector3 from the Matrix4 column specified.
|
|
*
|
|
* @method Phaser.Math.Vector3#setFromMatrixColumn
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to get the column from.
|
|
* @param {number} index - The column index.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
setFromMatrixColumn: function (mat4, index)
|
|
{
|
|
return this.fromArray(mat4.val, index * 4);
|
|
},
|
|
|
|
/**
|
|
* Sets the components of this Vector3 from the given array, based on the offset.
|
|
*
|
|
* Vector3.x = array[offset]
|
|
* Vector3.y = array[offset + 1]
|
|
* Vector3.z = array[offset + 2]
|
|
*
|
|
* @method Phaser.Math.Vector3#fromArray
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number[]} array - The array of values to get this Vector from.
|
|
* @param {number} [offset=0] - The offset index into the array.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
fromArray: function (array, offset)
|
|
{
|
|
if (offset === undefined) { offset = 0; }
|
|
|
|
this.x = array[offset];
|
|
this.y = array[offset + 1];
|
|
this.z = array[offset + 2];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Add a given Vector to this Vector. Addition is component-wise.
|
|
*
|
|
* @method Phaser.Math.Vector3#add
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to add to this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
add: function (v)
|
|
{
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
this.z += v.z || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Add the given value to each component of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#addScalar
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number} s - The amount to add to this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
addScalar: function (s)
|
|
{
|
|
this.x += s;
|
|
this.y += s;
|
|
this.z += s;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Add and scale a given Vector to this Vector. Addition is component-wise.
|
|
*
|
|
* @method Phaser.Math.Vector3#addScale
|
|
* @since 3.50.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to add to this Vector.
|
|
* @param {number} scale - The amount to scale `v` by.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
addScale: function (v, scale)
|
|
{
|
|
this.x += v.x * scale;
|
|
this.y += v.y * scale;
|
|
this.z += v.z * scale || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Subtract the given Vector from this Vector. Subtraction is component-wise.
|
|
*
|
|
* @method Phaser.Math.Vector3#subtract
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to subtract from this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
subtract: function (v)
|
|
{
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
this.z -= v.z || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Perform a component-wise multiplication between this Vector and the given Vector.
|
|
*
|
|
* Multiplies this Vector by the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#multiply
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to multiply this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
multiply: function (v)
|
|
{
|
|
this.x *= v.x;
|
|
this.y *= v.y;
|
|
this.z *= v.z || 1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Scale this Vector by the given value.
|
|
*
|
|
* @method Phaser.Math.Vector3#scale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} scale - The value to scale this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
scale: function (scale)
|
|
{
|
|
if (isFinite(scale))
|
|
{
|
|
this.x *= scale;
|
|
this.y *= scale;
|
|
this.z *= scale;
|
|
}
|
|
else
|
|
{
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Perform a component-wise division between this Vector and the given Vector.
|
|
*
|
|
* Divides this Vector by the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#divide
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to divide this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
divide: function (v)
|
|
{
|
|
this.x /= v.x;
|
|
this.y /= v.y;
|
|
this.z /= v.z || 1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Negate the `x`, `y` and `z` components of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#negate
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
negate: function ()
|
|
{
|
|
this.x = -this.x;
|
|
this.y = -this.y;
|
|
this.z = -this.z;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance between this Vector and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#distance
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to calculate the distance to.
|
|
*
|
|
* @return {number} The distance from this Vector to the given Vector.
|
|
*/
|
|
distance: function (v)
|
|
{
|
|
var dx = v.x - this.x;
|
|
var dy = v.y - this.y;
|
|
var dz = v.z - this.z || 0;
|
|
|
|
return Math.sqrt(dx * dx + dy * dy + dz * dz);
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance between this Vector and the given Vector, squared.
|
|
*
|
|
* @method Phaser.Math.Vector3#distanceSq
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3)} v - The Vector to calculate the distance to.
|
|
*
|
|
* @return {number} The distance from this Vector to the given Vector, squared.
|
|
*/
|
|
distanceSq: function (v)
|
|
{
|
|
var dx = v.x - this.x;
|
|
var dy = v.y - this.y;
|
|
var dz = v.z - this.z || 0;
|
|
|
|
return dx * dx + dy * dy + dz * dz;
|
|
},
|
|
|
|
/**
|
|
* Calculate the length (or magnitude) of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#length
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Vector.
|
|
*/
|
|
length: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
|
|
return Math.sqrt(x * x + y * y + z * z);
|
|
},
|
|
|
|
/**
|
|
* Calculate the length of this Vector squared.
|
|
*
|
|
* @method Phaser.Math.Vector3#lengthSq
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Vector, squared.
|
|
*/
|
|
lengthSq: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
|
|
return x * x + y * y + z * z;
|
|
},
|
|
|
|
/**
|
|
* Normalize this Vector.
|
|
*
|
|
* Makes the vector a unit length vector (magnitude of 1) in the same direction.
|
|
*
|
|
* @method Phaser.Math.Vector3#normalize
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
normalize: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var len = x * x + y * y + z * z;
|
|
|
|
if (len > 0)
|
|
{
|
|
len = 1 / Math.sqrt(len);
|
|
|
|
this.x = x * len;
|
|
this.y = y * len;
|
|
this.z = z * len;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the dot product of this Vector and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#dot
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} v - The Vector3 to dot product with this Vector3.
|
|
*
|
|
* @return {number} The dot product of this Vector and `v`.
|
|
*/
|
|
dot: function (v)
|
|
{
|
|
return this.x * v.x + this.y * v.y + this.z * v.z;
|
|
},
|
|
|
|
/**
|
|
* Calculate the cross (vector) product of this Vector (which will be modified) and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#cross
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} v - The Vector to cross product with.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
cross: function (v)
|
|
{
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var bx = v.x;
|
|
var by = v.y;
|
|
var bz = v.z;
|
|
|
|
this.x = ay * bz - az * by;
|
|
this.y = az * bx - ax * bz;
|
|
this.z = ax * by - ay * bx;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Linearly interpolate between this Vector and the given Vector.
|
|
*
|
|
* Interpolates this Vector towards the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector3#lerp
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} v - The Vector3 to interpolate towards.
|
|
* @param {number} [t=0] - The interpolation percentage, between 0 and 1.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
lerp: function (v, t)
|
|
{
|
|
if (t === undefined) { t = 0; }
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
|
|
this.x = ax + t * (v.x - ax);
|
|
this.y = ay + t * (v.y - ay);
|
|
this.z = az + t * (v.z - az);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Takes a Matrix3 and applies it to this Vector3.
|
|
*
|
|
* @method Phaser.Math.Vector3#applyMatrix3
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} mat3 - The Matrix3 to apply to this Vector3.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
applyMatrix3: function (mat3)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var m = mat3.val;
|
|
|
|
this.x = m[0] * x + m[3] * y + m[6] * z;
|
|
this.y = m[1] * x + m[4] * y + m[7] * z;
|
|
this.z = m[2] * x + m[5] * y + m[8] * z;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Takes a Matrix4 and applies it to this Vector3.
|
|
*
|
|
* @method Phaser.Math.Vector3#applyMatrix4
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to apply to this Vector3.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
applyMatrix4: function (mat4)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var m = mat4.val;
|
|
|
|
var w = 1 / (m[3] * x + m[7] * y + m[11] * z + m[15]);
|
|
|
|
this.x = (m[0] * x + m[4] * y + m[8] * z + m[12]) * w;
|
|
this.y = (m[1] * x + m[5] * y + m[9] * z + m[13]) * w;
|
|
this.z = (m[2] * x + m[6] * y + m[10] * z + m[14]) * w;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform this Vector with the given Matrix.
|
|
*
|
|
* @method Phaser.Math.Vector3#transformMat3
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} mat - The Matrix3 to transform this Vector3 with.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
transformMat3: function (mat)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var m = mat.val;
|
|
|
|
this.x = x * m[0] + y * m[3] + z * m[6];
|
|
this.y = x * m[1] + y * m[4] + z * m[7];
|
|
this.z = x * m[2] + y * m[5] + z * m[8];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform this Vector with the given Matrix4.
|
|
*
|
|
* @method Phaser.Math.Vector3#transformMat4
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector3 with.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
transformMat4: function (mat)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var m = mat.val;
|
|
|
|
this.x = m[0] * x + m[4] * y + m[8] * z + m[12];
|
|
this.y = m[1] * x + m[5] * y + m[9] * z + m[13];
|
|
this.z = m[2] * x + m[6] * y + m[10] * z + m[14];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transforms the coordinates of this Vector3 with the given Matrix4.
|
|
*
|
|
* @method Phaser.Math.Vector3#transformCoordinates
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector3 with.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
transformCoordinates: function (mat)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var m = mat.val;
|
|
|
|
var tx = (x * m[0]) + (y * m[4]) + (z * m[8]) + m[12];
|
|
var ty = (x * m[1]) + (y * m[5]) + (z * m[9]) + m[13];
|
|
var tz = (x * m[2]) + (y * m[6]) + (z * m[10]) + m[14];
|
|
var tw = (x * m[3]) + (y * m[7]) + (z * m[11]) + m[15];
|
|
|
|
this.x = tx / tw;
|
|
this.y = ty / tw;
|
|
this.z = tz / tw;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform this Vector with the given Quaternion.
|
|
*
|
|
* @method Phaser.Math.Vector3#transformQuat
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Quaternion} q - The Quaternion to transform this Vector with.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
transformQuat: function (q)
|
|
{
|
|
// benchmarks: http://jsperf.com/quaternion-transform-vec3-implementations
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var qx = q.x;
|
|
var qy = q.y;
|
|
var qz = q.z;
|
|
var qw = q.w;
|
|
|
|
// calculate quat * vec
|
|
var ix = qw * x + qy * z - qz * y;
|
|
var iy = qw * y + qz * x - qx * z;
|
|
var iz = qw * z + qx * y - qy * x;
|
|
var iw = -qx * x - qy * y - qz * z;
|
|
|
|
// calculate result * inverse quat
|
|
this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
|
this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
|
this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Multiplies this Vector3 by the specified matrix, applying a W divide. This is useful for projection,
|
|
* e.g. unprojecting a 2D point into 3D space.
|
|
*
|
|
* @method Phaser.Math.Vector3#project
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat - The Matrix4 to multiply this Vector3 with.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
project: function (mat)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var m = mat.val;
|
|
|
|
var a00 = m[0];
|
|
var a01 = m[1];
|
|
var a02 = m[2];
|
|
var a03 = m[3];
|
|
var a10 = m[4];
|
|
var a11 = m[5];
|
|
var a12 = m[6];
|
|
var a13 = m[7];
|
|
var a20 = m[8];
|
|
var a21 = m[9];
|
|
var a22 = m[10];
|
|
var a23 = m[11];
|
|
var a30 = m[12];
|
|
var a31 = m[13];
|
|
var a32 = m[14];
|
|
var a33 = m[15];
|
|
|
|
var lw = 1 / (x * a03 + y * a13 + z * a23 + a33);
|
|
|
|
this.x = (x * a00 + y * a10 + z * a20 + a30) * lw;
|
|
this.y = (x * a01 + y * a11 + z * a21 + a31) * lw;
|
|
this.z = (x * a02 + y * a12 + z * a22 + a32) * lw;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Multiplies this Vector3 by the given view and projection matrices.
|
|
*
|
|
* @method Phaser.Math.Vector3#projectViewMatrix
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} viewMatrix - A View Matrix.
|
|
* @param {Phaser.Math.Matrix4} projectionMatrix - A Projection Matrix.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
projectViewMatrix: function (viewMatrix, projectionMatrix)
|
|
{
|
|
return this.applyMatrix4(viewMatrix).applyMatrix4(projectionMatrix);
|
|
},
|
|
|
|
/**
|
|
* Multiplies this Vector3 by the given inversed projection matrix and world matrix.
|
|
*
|
|
* @method Phaser.Math.Vector3#unprojectViewMatrix
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} projectionMatrix - An inversed Projection Matrix.
|
|
* @param {Phaser.Math.Matrix4} worldMatrix - A World View Matrix.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
unprojectViewMatrix: function (projectionMatrix, worldMatrix)
|
|
{
|
|
return this.applyMatrix4(projectionMatrix).applyMatrix4(worldMatrix);
|
|
},
|
|
|
|
/**
|
|
* Unproject this point from 2D space to 3D space.
|
|
* The point should have its x and y properties set to
|
|
* 2D screen space, and the z either at 0 (near plane)
|
|
* or 1 (far plane). The provided matrix is assumed to already
|
|
* be combined, i.e. projection * view * model.
|
|
*
|
|
* After this operation, this vector's (x, y, z) components will
|
|
* represent the unprojected 3D coordinate.
|
|
*
|
|
* @method Phaser.Math.Vector3#unproject
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector4} viewport - Screen x, y, width and height in pixels.
|
|
* @param {Phaser.Math.Matrix4} invProjectionView - Combined projection and view matrix.
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
unproject: function (viewport, invProjectionView)
|
|
{
|
|
var viewX = viewport.x;
|
|
var viewY = viewport.y;
|
|
var viewWidth = viewport.z;
|
|
var viewHeight = viewport.w;
|
|
|
|
var x = this.x - viewX;
|
|
var y = (viewHeight - this.y - 1) - viewY;
|
|
var z = this.z;
|
|
|
|
this.x = (2 * x) / viewWidth - 1;
|
|
this.y = (2 * y) / viewHeight - 1;
|
|
this.z = 2 * z - 1;
|
|
|
|
return this.project(invProjectionView);
|
|
},
|
|
|
|
/**
|
|
* Make this Vector the zero vector (0, 0, 0).
|
|
*
|
|
* @method Phaser.Math.Vector3#reset
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector3} This Vector3.
|
|
*/
|
|
reset: function ()
|
|
{
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
|
|
return this;
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* A static zero Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.ZERO
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.ZERO = new Vector3();
|
|
|
|
/**
|
|
* A static right Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.RIGHT
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.RIGHT = new Vector3(1, 0, 0);
|
|
|
|
/**
|
|
* A static left Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.LEFT
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.LEFT = new Vector3(-1, 0, 0);
|
|
|
|
/**
|
|
* A static up Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.UP
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.UP = new Vector3(0, -1, 0);
|
|
|
|
/**
|
|
* A static down Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.DOWN
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.DOWN = new Vector3(0, 1, 0);
|
|
|
|
/**
|
|
* A static forward Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.FORWARD
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.FORWARD = new Vector3(0, 0, 1);
|
|
|
|
/**
|
|
* A static back Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.BACK
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.BACK = new Vector3(0, 0, -1);
|
|
|
|
/**
|
|
* A static one Vector3 for use by reference.
|
|
*
|
|
* This constant is meant for comparison operations and should not be modified directly.
|
|
*
|
|
* @constant
|
|
* @name Phaser.Math.Vector3.ONE
|
|
* @type {Phaser.Math.Vector3}
|
|
* @since 3.16.0
|
|
*/
|
|
Vector3.ONE = new Vector3(1, 1, 1);
|
|
|
|
module.exports = Vector3;
|
|
|
|
|
|
/***/ }),
|
|
/* 17 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CheckMatrix = __webpack_require__(27);
|
|
var TransposeMatrix = __webpack_require__(61);
|
|
|
|
/**
|
|
* Rotates the array matrix based on the given rotation value.
|
|
*
|
|
* The value can be given in degrees: 90, -90, 270, -270 or 180,
|
|
* or a string command: `rotateLeft`, `rotateRight` or `rotate180`.
|
|
*
|
|
* Based on the routine from {@link http://jsfiddle.net/MrPolywhirl/NH42z/}.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.RotateMatrix
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix,$return]
|
|
*
|
|
* @param {T[][]} [matrix] - The array to rotate.
|
|
* @param {(number|string)} [direction=90] - The amount to rotate the matrix by.
|
|
*
|
|
* @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix.
|
|
*/
|
|
var RotateMatrix = function (matrix, direction)
|
|
{
|
|
if (direction === undefined) { direction = 90; }
|
|
|
|
if (!CheckMatrix(matrix))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (typeof direction !== 'string')
|
|
{
|
|
direction = ((direction % 360) + 360) % 360;
|
|
}
|
|
|
|
if (direction === 90 || direction === -270 || direction === 'rotateLeft')
|
|
{
|
|
matrix = TransposeMatrix(matrix);
|
|
matrix.reverse();
|
|
}
|
|
else if (direction === -90 || direction === 270 || direction === 'rotateRight')
|
|
{
|
|
matrix.reverse();
|
|
matrix = TransposeMatrix(matrix);
|
|
}
|
|
else if (Math.abs(direction) === 180 || direction === 'rotate180')
|
|
{
|
|
for (var i = 0; i < matrix.length; i++)
|
|
{
|
|
matrix[i].reverse();
|
|
}
|
|
|
|
matrix.reverse();
|
|
}
|
|
|
|
return matrix;
|
|
};
|
|
|
|
module.exports = RotateMatrix;
|
|
|
|
|
|
/***/ }),
|
|
/* 18 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var OS = __webpack_require__(28);
|
|
|
|
/**
|
|
* Determines the browser type and version running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.browser` from within any Scene.
|
|
*
|
|
* @typedef {object} Phaser.Device.Browser
|
|
* @since 3.0.0
|
|
*
|
|
* @property {boolean} chrome - Set to true if running in Chrome.
|
|
* @property {boolean} edge - Set to true if running in Microsoft Edge browser.
|
|
* @property {boolean} firefox - Set to true if running in Firefox.
|
|
* @property {boolean} ie - Set to true if running in Internet Explorer 11 or less (not Edge).
|
|
* @property {boolean} mobileSafari - Set to true if running in Mobile Safari.
|
|
* @property {boolean} opera - Set to true if running in Opera.
|
|
* @property {boolean} safari - Set to true if running in Safari.
|
|
* @property {boolean} silk - Set to true if running in the Silk browser (as used on the Amazon Kindle)
|
|
* @property {boolean} trident - Set to true if running a Trident version of Internet Explorer (IE11+)
|
|
* @property {number} chromeVersion - If running in Chrome this will contain the major version number.
|
|
* @property {number} firefoxVersion - If running in Firefox this will contain the major version number.
|
|
* @property {number} ieVersion - If running in Internet Explorer this will contain the major version number. Beyond IE10 you should use Browser.trident and Browser.tridentVersion.
|
|
* @property {number} safariVersion - If running in Safari this will contain the major version number.
|
|
* @property {number} tridentVersion - If running in Internet Explorer 11 this will contain the major version number. See {@link http://msdn.microsoft.com/en-us/library/ie/ms537503(v=vs.85).aspx}
|
|
*/
|
|
var Browser = {
|
|
|
|
chrome: false,
|
|
chromeVersion: 0,
|
|
edge: false,
|
|
firefox: false,
|
|
firefoxVersion: 0,
|
|
ie: false,
|
|
ieVersion: 0,
|
|
mobileSafari: false,
|
|
opera: false,
|
|
safari: false,
|
|
safariVersion: 0,
|
|
silk: false,
|
|
trident: false,
|
|
tridentVersion: 0,
|
|
es2019: false
|
|
|
|
};
|
|
|
|
function init ()
|
|
{
|
|
var ua = navigator.userAgent;
|
|
|
|
if ((/Edg\/\d+/).test(ua))
|
|
{
|
|
Browser.edge = true;
|
|
Browser.es2019 = true;
|
|
}
|
|
else if ((/OPR/).test(ua)) {
|
|
Browser.opera = true;
|
|
Browser.es2019 = true;
|
|
}
|
|
else if ((/Chrome\/(\d+)/).test(ua) && !OS.windowsPhone)
|
|
{
|
|
Browser.chrome = true;
|
|
Browser.chromeVersion = parseInt(RegExp.$1, 10);
|
|
Browser.es2019 = (Browser.chromeVersion > 69);
|
|
}
|
|
else if ((/Firefox\D+(\d+)/).test(ua))
|
|
{
|
|
Browser.firefox = true;
|
|
Browser.firefoxVersion = parseInt(RegExp.$1, 10);
|
|
Browser.es2019 = (Browser.firefoxVersion > 10);
|
|
}
|
|
else if ((/AppleWebKit/).test(ua) && OS.iOS)
|
|
{
|
|
Browser.mobileSafari = true;
|
|
}
|
|
else if ((/MSIE (\d+\.\d+);/).test(ua))
|
|
{
|
|
Browser.ie = true;
|
|
Browser.ieVersion = parseInt(RegExp.$1, 10);
|
|
}
|
|
else if ((/Version\/(\d+\.\d+) Safari/).test(ua) && !OS.windowsPhone)
|
|
{
|
|
Browser.safari = true;
|
|
Browser.safariVersion = parseInt(RegExp.$1, 10);
|
|
Browser.es2019 = (Browser.safariVersion > 10);
|
|
}
|
|
else if ((/Trident\/(\d+\.\d+)(.*)rv:(\d+\.\d+)/).test(ua))
|
|
{
|
|
Browser.ie = true;
|
|
Browser.trident = true;
|
|
Browser.tridentVersion = parseInt(RegExp.$1, 10);
|
|
Browser.ieVersion = parseInt(RegExp.$3, 10);
|
|
}
|
|
|
|
// Silk gets its own if clause because its ua also contains 'Safari'
|
|
if ((/Silk/).test(ua))
|
|
{
|
|
Browser.silk = true;
|
|
}
|
|
|
|
return Browser;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
|
|
/***/ }),
|
|
/* 19 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var IsPlainObject = __webpack_require__(7);
|
|
|
|
// @param {boolean} deep - Perform a deep copy?
|
|
// @param {object} target - The target object to copy to.
|
|
// @return {object} The extended object.
|
|
|
|
/**
|
|
* This is a slightly modified version of http://api.jquery.com/jQuery.extend/
|
|
*
|
|
* @function Phaser.Utils.Objects.Extend
|
|
* @since 3.0.0
|
|
*
|
|
* @param {...*} [args] - The objects that will be mixed.
|
|
*
|
|
* @return {object} The extended object.
|
|
*/
|
|
var Extend = function ()
|
|
{
|
|
var options, name, src, copy, copyIsArray, clone,
|
|
target = arguments[0] || {},
|
|
i = 1,
|
|
length = arguments.length,
|
|
deep = false;
|
|
|
|
// Handle a deep copy situation
|
|
if (typeof target === 'boolean')
|
|
{
|
|
deep = target;
|
|
target = arguments[1] || {};
|
|
|
|
// skip the boolean and the target
|
|
i = 2;
|
|
}
|
|
|
|
// extend Phaser if only one argument is passed
|
|
if (length === i)
|
|
{
|
|
target = this;
|
|
--i;
|
|
}
|
|
|
|
for (; i < length; i++)
|
|
{
|
|
// Only deal with non-null/undefined values
|
|
if ((options = arguments[i]) != null)
|
|
{
|
|
// Extend the base object
|
|
for (name in options)
|
|
{
|
|
src = target[name];
|
|
copy = options[name];
|
|
|
|
// Prevent never-ending loop
|
|
if (target === copy)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
// Recurse if we're merging plain objects or arrays
|
|
if (deep && copy && (IsPlainObject(copy) || (copyIsArray = Array.isArray(copy))))
|
|
{
|
|
if (copyIsArray)
|
|
{
|
|
copyIsArray = false;
|
|
clone = src && Array.isArray(src) ? src : [];
|
|
}
|
|
else
|
|
{
|
|
clone = src && IsPlainObject(src) ? src : {};
|
|
}
|
|
|
|
// Never move original objects, clone them
|
|
target[name] = Extend(deep, clone, copy);
|
|
|
|
// Don't bring in undefined values
|
|
}
|
|
else if (copy !== undefined)
|
|
{
|
|
target[name] = copy;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return the modified object
|
|
return target;
|
|
};
|
|
|
|
module.exports = Extend;
|
|
|
|
|
|
/***/ }),
|
|
/* 20 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Generate a random floating point number between the two given bounds, minimum inclusive, maximum exclusive.
|
|
*
|
|
* @function Phaser.Math.FloatBetween
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} min - The lower bound for the float, inclusive.
|
|
* @param {number} max - The upper bound for the float exclusive.
|
|
*
|
|
* @return {number} A random float within the given range.
|
|
*/
|
|
var FloatBetween = function (min, max)
|
|
{
|
|
return Math.random() * (max - min) + min;
|
|
};
|
|
|
|
module.exports = FloatBetween;
|
|
|
|
|
|
/***/ }),
|
|
/* 21 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CONST = __webpack_require__(4);
|
|
|
|
/**
|
|
* Convert the given angle from degrees, to the equivalent angle in radians.
|
|
*
|
|
* @function Phaser.Math.DegToRad
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} degrees - The angle (in degrees) to convert to radians.
|
|
*
|
|
* @return {number} The given angle converted to radians.
|
|
*/
|
|
var DegToRad = function (degrees)
|
|
{
|
|
return degrees * CONST.DEG_TO_RAD;
|
|
};
|
|
|
|
module.exports = DegToRad;
|
|
|
|
|
|
/***/ }),
|
|
/* 22 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var Vector3 = __webpack_require__(16);
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
var EPSILON = 0.000001;
|
|
|
|
/**
|
|
* @classdesc
|
|
* A four-dimensional matrix.
|
|
*
|
|
* Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji
|
|
* and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl
|
|
*
|
|
* @class Matrix4
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} [m] - Optional Matrix4 to copy values from.
|
|
*/
|
|
var Matrix4 = new Class({
|
|
|
|
initialize:
|
|
|
|
function Matrix4 (m)
|
|
{
|
|
/**
|
|
* The matrix values.
|
|
*
|
|
* @name Phaser.Math.Matrix4#val
|
|
* @type {Float32Array}
|
|
* @since 3.0.0
|
|
*/
|
|
this.val = new Float32Array(16);
|
|
|
|
if (m)
|
|
{
|
|
// Assume Matrix4 with val:
|
|
this.copy(m);
|
|
}
|
|
else
|
|
{
|
|
// Default to identity
|
|
this.identity();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Make a clone of this Matrix4.
|
|
*
|
|
* @method Phaser.Math.Matrix4#clone
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Matrix4} A clone of this Matrix4.
|
|
*/
|
|
clone: function ()
|
|
{
|
|
return new Matrix4(this);
|
|
},
|
|
|
|
/**
|
|
* This method is an alias for `Matrix4.copy`.
|
|
*
|
|
* @method Phaser.Math.Matrix4#set
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} src - The Matrix to set the values of this Matrix's from.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
set: function (src)
|
|
{
|
|
return this.copy(src);
|
|
},
|
|
|
|
/**
|
|
* Sets all values of this Matrix4.
|
|
*
|
|
* @method Phaser.Math.Matrix4#setValues
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number} m00 - The m00 value.
|
|
* @param {number} m01 - The m01 value.
|
|
* @param {number} m02 - The m02 value.
|
|
* @param {number} m03 - The m03 value.
|
|
* @param {number} m10 - The m10 value.
|
|
* @param {number} m11 - The m11 value.
|
|
* @param {number} m12 - The m12 value.
|
|
* @param {number} m13 - The m13 value.
|
|
* @param {number} m20 - The m20 value.
|
|
* @param {number} m21 - The m21 value.
|
|
* @param {number} m22 - The m22 value.
|
|
* @param {number} m23 - The m23 value.
|
|
* @param {number} m30 - The m30 value.
|
|
* @param {number} m31 - The m31 value.
|
|
* @param {number} m32 - The m32 value.
|
|
* @param {number} m33 - The m33 value.
|
|
*
|
|
* @return {this} This Matrix4 instance.
|
|
*/
|
|
setValues: function (m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23, m30, m31, m32, m33)
|
|
{
|
|
var out = this.val;
|
|
|
|
out[0] = m00;
|
|
out[1] = m01;
|
|
out[2] = m02;
|
|
out[3] = m03;
|
|
out[4] = m10;
|
|
out[5] = m11;
|
|
out[6] = m12;
|
|
out[7] = m13;
|
|
out[8] = m20;
|
|
out[9] = m21;
|
|
out[10] = m22;
|
|
out[11] = m23;
|
|
out[12] = m30;
|
|
out[13] = m31;
|
|
out[14] = m32;
|
|
out[15] = m33;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Copy the values of a given Matrix into this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#copy
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} src - The Matrix to copy the values from.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
copy: function (src)
|
|
{
|
|
var a = src.val;
|
|
|
|
return this.setValues(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]);
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix from the given array.
|
|
*
|
|
* @method Phaser.Math.Matrix4#fromArray
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number[]} a - The array to copy the values from. Must have at least 16 elements.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
fromArray: function (a)
|
|
{
|
|
return this.setValues(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]);
|
|
},
|
|
|
|
/**
|
|
* Reset this Matrix.
|
|
*
|
|
* Sets all values to `0`.
|
|
*
|
|
* @method Phaser.Math.Matrix4#zero
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Matrix4} This Matrix4.
|
|
*/
|
|
zero: function ()
|
|
{
|
|
return this.setValues(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
|
},
|
|
|
|
/**
|
|
* Generates a transform matrix based on the given position, scale and rotation.
|
|
*
|
|
* @method Phaser.Math.Matrix4#transform
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} position - The position vector.
|
|
* @param {Phaser.Math.Vector3} scale - The scale vector.
|
|
* @param {Phaser.Math.Quaternion} rotation - The rotation quaternion.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
transform: function (position, scale, rotation)
|
|
{
|
|
var rotMatrix = _tempMat1.fromQuat(rotation);
|
|
|
|
var rm = rotMatrix.val;
|
|
|
|
var sx = scale.x;
|
|
var sy = scale.y;
|
|
var sz = scale.z;
|
|
|
|
return this.setValues(
|
|
rm[0] * sx,
|
|
rm[1] * sx,
|
|
rm[2] * sx,
|
|
0,
|
|
|
|
rm[4] * sy,
|
|
rm[5] * sy,
|
|
rm[6] * sy,
|
|
0,
|
|
|
|
rm[8] * sz,
|
|
rm[9] * sz,
|
|
rm[10] * sz,
|
|
0,
|
|
|
|
position.x,
|
|
position.y,
|
|
position.z,
|
|
1
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Set the `x`, `y` and `z` values of this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#xyz
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The x value.
|
|
* @param {number} y - The y value.
|
|
* @param {number} z - The z value.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
xyz: function (x, y, z)
|
|
{
|
|
this.identity();
|
|
|
|
var out = this.val;
|
|
|
|
out[12] = x;
|
|
out[13] = y;
|
|
out[14] = z;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the scaling values of this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#scaling
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The x scaling value.
|
|
* @param {number} y - The y scaling value.
|
|
* @param {number} z - The z scaling value.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
scaling: function (x, y, z)
|
|
{
|
|
this.zero();
|
|
|
|
var out = this.val;
|
|
|
|
out[0] = x;
|
|
out[5] = y;
|
|
out[10] = z;
|
|
out[15] = 1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Reset this Matrix to an identity (default) matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#identity
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
identity: function ()
|
|
{
|
|
return this.setValues(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
},
|
|
|
|
/**
|
|
* Transpose this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#transpose
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
transpose: function ()
|
|
{
|
|
var a = this.val;
|
|
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
var a23 = a[11];
|
|
|
|
a[1] = a[4];
|
|
a[2] = a[8];
|
|
a[3] = a[12];
|
|
a[4] = a01;
|
|
a[6] = a[9];
|
|
a[7] = a[13];
|
|
a[8] = a02;
|
|
a[9] = a12;
|
|
a[11] = a[14];
|
|
a[12] = a03;
|
|
a[13] = a13;
|
|
a[14] = a23;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Copies the given Matrix4 into this Matrix and then inverses it.
|
|
*
|
|
* @method Phaser.Math.Matrix4#getInverse
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} m - The Matrix4 to invert into this Matrix4.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
getInverse: function (m)
|
|
{
|
|
this.copy(m);
|
|
|
|
return this.invert();
|
|
},
|
|
|
|
/**
|
|
* Invert this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#invert
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
invert: function ()
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
var a30 = a[12];
|
|
var a31 = a[13];
|
|
var a32 = a[14];
|
|
var a33 = a[15];
|
|
|
|
var b00 = a00 * a11 - a01 * a10;
|
|
var b01 = a00 * a12 - a02 * a10;
|
|
var b02 = a00 * a13 - a03 * a10;
|
|
var b03 = a01 * a12 - a02 * a11;
|
|
|
|
var b04 = a01 * a13 - a03 * a11;
|
|
var b05 = a02 * a13 - a03 * a12;
|
|
var b06 = a20 * a31 - a21 * a30;
|
|
var b07 = a20 * a32 - a22 * a30;
|
|
|
|
var b08 = a20 * a33 - a23 * a30;
|
|
var b09 = a21 * a32 - a22 * a31;
|
|
var b10 = a21 * a33 - a23 * a31;
|
|
var b11 = a22 * a33 - a23 * a32;
|
|
|
|
// Calculate the determinant
|
|
var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
|
|
|
if (!det)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
det = 1 / det;
|
|
|
|
return this.setValues(
|
|
(a11 * b11 - a12 * b10 + a13 * b09) * det,
|
|
(a02 * b10 - a01 * b11 - a03 * b09) * det,
|
|
(a31 * b05 - a32 * b04 + a33 * b03) * det,
|
|
(a22 * b04 - a21 * b05 - a23 * b03) * det,
|
|
(a12 * b08 - a10 * b11 - a13 * b07) * det,
|
|
(a00 * b11 - a02 * b08 + a03 * b07) * det,
|
|
(a32 * b02 - a30 * b05 - a33 * b01) * det,
|
|
(a20 * b05 - a22 * b02 + a23 * b01) * det,
|
|
(a10 * b10 - a11 * b08 + a13 * b06) * det,
|
|
(a01 * b08 - a00 * b10 - a03 * b06) * det,
|
|
(a30 * b04 - a31 * b02 + a33 * b00) * det,
|
|
(a21 * b02 - a20 * b04 - a23 * b00) * det,
|
|
(a11 * b07 - a10 * b09 - a12 * b06) * det,
|
|
(a00 * b09 - a01 * b07 + a02 * b06) * det,
|
|
(a31 * b01 - a30 * b03 - a32 * b00) * det,
|
|
(a20 * b03 - a21 * b01 + a22 * b00) * det
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Calculate the adjoint, or adjugate, of this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#adjoint
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
adjoint: function ()
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
var a30 = a[12];
|
|
var a31 = a[13];
|
|
var a32 = a[14];
|
|
var a33 = a[15];
|
|
|
|
return this.setValues(
|
|
(a11 * (a22 * a33 - a23 * a32) - a21 * (a12 * a33 - a13 * a32) + a31 * (a12 * a23 - a13 * a22)),
|
|
-(a01 * (a22 * a33 - a23 * a32) - a21 * (a02 * a33 - a03 * a32) + a31 * (a02 * a23 - a03 * a22)),
|
|
(a01 * (a12 * a33 - a13 * a32) - a11 * (a02 * a33 - a03 * a32) + a31 * (a02 * a13 - a03 * a12)),
|
|
-(a01 * (a12 * a23 - a13 * a22) - a11 * (a02 * a23 - a03 * a22) + a21 * (a02 * a13 - a03 * a12)),
|
|
-(a10 * (a22 * a33 - a23 * a32) - a20 * (a12 * a33 - a13 * a32) + a30 * (a12 * a23 - a13 * a22)),
|
|
(a00 * (a22 * a33 - a23 * a32) - a20 * (a02 * a33 - a03 * a32) + a30 * (a02 * a23 - a03 * a22)),
|
|
-(a00 * (a12 * a33 - a13 * a32) - a10 * (a02 * a33 - a03 * a32) + a30 * (a02 * a13 - a03 * a12)),
|
|
(a00 * (a12 * a23 - a13 * a22) - a10 * (a02 * a23 - a03 * a22) + a20 * (a02 * a13 - a03 * a12)),
|
|
(a10 * (a21 * a33 - a23 * a31) - a20 * (a11 * a33 - a13 * a31) + a30 * (a11 * a23 - a13 * a21)),
|
|
-(a00 * (a21 * a33 - a23 * a31) - a20 * (a01 * a33 - a03 * a31) + a30 * (a01 * a23 - a03 * a21)),
|
|
(a00 * (a11 * a33 - a13 * a31) - a10 * (a01 * a33 - a03 * a31) + a30 * (a01 * a13 - a03 * a11)),
|
|
-(a00 * (a11 * a23 - a13 * a21) - a10 * (a01 * a23 - a03 * a21) + a20 * (a01 * a13 - a03 * a11)),
|
|
-(a10 * (a21 * a32 - a22 * a31) - a20 * (a11 * a32 - a12 * a31) + a30 * (a11 * a22 - a12 * a21)),
|
|
(a00 * (a21 * a32 - a22 * a31) - a20 * (a01 * a32 - a02 * a31) + a30 * (a01 * a22 - a02 * a21)),
|
|
-(a00 * (a11 * a32 - a12 * a31) - a10 * (a01 * a32 - a02 * a31) + a30 * (a01 * a12 - a02 * a11)),
|
|
(a00 * (a11 * a22 - a12 * a21) - a10 * (a01 * a22 - a02 * a21) + a20 * (a01 * a12 - a02 * a11))
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Calculate the determinant of this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#determinant
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The determinant of this Matrix.
|
|
*/
|
|
determinant: function ()
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
var a30 = a[12];
|
|
var a31 = a[13];
|
|
var a32 = a[14];
|
|
var a33 = a[15];
|
|
|
|
var b00 = a00 * a11 - a01 * a10;
|
|
var b01 = a00 * a12 - a02 * a10;
|
|
var b02 = a00 * a13 - a03 * a10;
|
|
var b03 = a01 * a12 - a02 * a11;
|
|
var b04 = a01 * a13 - a03 * a11;
|
|
var b05 = a02 * a13 - a03 * a12;
|
|
var b06 = a20 * a31 - a21 * a30;
|
|
var b07 = a20 * a32 - a22 * a30;
|
|
var b08 = a20 * a33 - a23 * a30;
|
|
var b09 = a21 * a32 - a22 * a31;
|
|
var b10 = a21 * a33 - a23 * a31;
|
|
var b11 = a22 * a33 - a23 * a32;
|
|
|
|
// Calculate the determinant
|
|
return b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
|
},
|
|
|
|
/**
|
|
* Multiply this Matrix by the given Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#multiply
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} src - The Matrix to multiply this Matrix by.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
multiply: function (src)
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
var a30 = a[12];
|
|
var a31 = a[13];
|
|
var a32 = a[14];
|
|
var a33 = a[15];
|
|
|
|
var b = src.val;
|
|
|
|
// Cache only the current line of the second matrix
|
|
var b0 = b[0];
|
|
var b1 = b[1];
|
|
var b2 = b[2];
|
|
var b3 = b[3];
|
|
|
|
a[0] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
|
a[1] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
|
a[2] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
|
a[3] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
|
|
|
b0 = b[4];
|
|
b1 = b[5];
|
|
b2 = b[6];
|
|
b3 = b[7];
|
|
|
|
a[4] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
|
a[5] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
|
a[6] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
|
a[7] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
|
|
|
b0 = b[8];
|
|
b1 = b[9];
|
|
b2 = b[10];
|
|
b3 = b[11];
|
|
|
|
a[8] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
|
a[9] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
|
a[10] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
|
a[11] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
|
|
|
b0 = b[12];
|
|
b1 = b[13];
|
|
b2 = b[14];
|
|
b3 = b[15];
|
|
|
|
a[12] = b0 * a00 + b1 * a10 + b2 * a20 + b3 * a30;
|
|
a[13] = b0 * a01 + b1 * a11 + b2 * a21 + b3 * a31;
|
|
a[14] = b0 * a02 + b1 * a12 + b2 * a22 + b3 * a32;
|
|
a[15] = b0 * a03 + b1 * a13 + b2 * a23 + b3 * a33;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Multiply the values of this Matrix4 by those given in the `src` argument.
|
|
*
|
|
* @method Phaser.Math.Matrix4#multiplyLocal
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} src - The source Matrix4 that this Matrix4 is multiplied by.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
multiplyLocal: function (src)
|
|
{
|
|
var a = this.val;
|
|
var b = src.val;
|
|
|
|
return this.setValues(
|
|
a[0] * b[0] + a[1] * b[4] + a[2] * b[8] + a[3] * b[12],
|
|
a[0] * b[1] + a[1] * b[5] + a[2] * b[9] + a[3] * b[13],
|
|
a[0] * b[2] + a[1] * b[6] + a[2] * b[10] + a[3] * b[14],
|
|
a[0] * b[3] + a[1] * b[7] + a[2] * b[11] + a[3] * b[15],
|
|
|
|
a[4] * b[0] + a[5] * b[4] + a[6] * b[8] + a[7] * b[12],
|
|
a[4] * b[1] + a[5] * b[5] + a[6] * b[9] + a[7] * b[13],
|
|
a[4] * b[2] + a[5] * b[6] + a[6] * b[10] + a[7] * b[14],
|
|
a[4] * b[3] + a[5] * b[7] + a[6] * b[11] + a[7] * b[15],
|
|
|
|
a[8] * b[0] + a[9] * b[4] + a[10] * b[8] + a[11] * b[12],
|
|
a[8] * b[1] + a[9] * b[5] + a[10] * b[9] + a[11] * b[13],
|
|
a[8] * b[2] + a[9] * b[6] + a[10] * b[10] + a[11] * b[14],
|
|
a[8] * b[3] + a[9] * b[7] + a[10] * b[11] + a[11] * b[15],
|
|
|
|
a[12] * b[0] + a[13] * b[4] + a[14] * b[8] + a[15] * b[12],
|
|
a[12] * b[1] + a[13] * b[5] + a[14] * b[9] + a[15] * b[13],
|
|
a[12] * b[2] + a[13] * b[6] + a[14] * b[10] + a[15] * b[14],
|
|
a[12] * b[3] + a[13] * b[7] + a[14] * b[11] + a[15] * b[15]
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Multiplies the given Matrix4 object with this Matrix.
|
|
*
|
|
* This is the same as calling `multiplyMatrices(m, this)`.
|
|
*
|
|
* @method Phaser.Math.Matrix4#premultiply
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} m - The Matrix4 to multiply with this one.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
premultiply: function (m)
|
|
{
|
|
return this.multiplyMatrices(m, this);
|
|
},
|
|
|
|
/**
|
|
* Multiplies the two given Matrix4 objects and stores the results in this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#multiplyMatrices
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} a - The first Matrix4 to multiply.
|
|
* @param {Phaser.Math.Matrix4} b - The second Matrix4 to multiply.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
multiplyMatrices: function (a, b)
|
|
{
|
|
var am = a.val;
|
|
var bm = b.val;
|
|
|
|
var a11 = am[0];
|
|
var a12 = am[4];
|
|
var a13 = am[8];
|
|
var a14 = am[12];
|
|
var a21 = am[1];
|
|
var a22 = am[5];
|
|
var a23 = am[9];
|
|
var a24 = am[13];
|
|
var a31 = am[2];
|
|
var a32 = am[6];
|
|
var a33 = am[10];
|
|
var a34 = am[14];
|
|
var a41 = am[3];
|
|
var a42 = am[7];
|
|
var a43 = am[11];
|
|
var a44 = am[15];
|
|
|
|
var b11 = bm[0];
|
|
var b12 = bm[4];
|
|
var b13 = bm[8];
|
|
var b14 = bm[12];
|
|
var b21 = bm[1];
|
|
var b22 = bm[5];
|
|
var b23 = bm[9];
|
|
var b24 = bm[13];
|
|
var b31 = bm[2];
|
|
var b32 = bm[6];
|
|
var b33 = bm[10];
|
|
var b34 = bm[14];
|
|
var b41 = bm[3];
|
|
var b42 = bm[7];
|
|
var b43 = bm[11];
|
|
var b44 = bm[15];
|
|
|
|
return this.setValues(
|
|
a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41,
|
|
a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41,
|
|
a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41,
|
|
a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41,
|
|
a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42,
|
|
a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42,
|
|
a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42,
|
|
a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42,
|
|
a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43,
|
|
a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43,
|
|
a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43,
|
|
a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43,
|
|
a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44,
|
|
a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44,
|
|
a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44,
|
|
a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Translate this Matrix using the given Vector.
|
|
*
|
|
* @method Phaser.Math.Matrix4#translate
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to translate this Matrix with.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
translate: function (v)
|
|
{
|
|
return this.translateXYZ(v.x, v.y, v.z);
|
|
},
|
|
|
|
/**
|
|
* Translate this Matrix using the given values.
|
|
*
|
|
* @method Phaser.Math.Matrix4#translateXYZ
|
|
* @since 3.16.0
|
|
*
|
|
* @param {number} x - The x component.
|
|
* @param {number} y - The y component.
|
|
* @param {number} z - The z component.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
translateXYZ: function (x, y, z)
|
|
{
|
|
var a = this.val;
|
|
|
|
a[12] = a[0] * x + a[4] * y + a[8] * z + a[12];
|
|
a[13] = a[1] * x + a[5] * y + a[9] * z + a[13];
|
|
a[14] = a[2] * x + a[6] * y + a[10] * z + a[14];
|
|
a[15] = a[3] * x + a[7] * y + a[11] * z + a[15];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Apply a scale transformation to this Matrix.
|
|
*
|
|
* Uses the `x`, `y` and `z` components of the given Vector to scale the Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#scale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to scale this Matrix with.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
scale: function (v)
|
|
{
|
|
return this.scaleXYZ(v.x, v.y, v.z);
|
|
},
|
|
|
|
/**
|
|
* Apply a scale transformation to this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#scaleXYZ
|
|
* @since 3.16.0
|
|
*
|
|
* @param {number} x - The x component.
|
|
* @param {number} y - The y component.
|
|
* @param {number} z - The z component.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
scaleXYZ: function (x, y, z)
|
|
{
|
|
var a = this.val;
|
|
|
|
a[0] = a[0] * x;
|
|
a[1] = a[1] * x;
|
|
a[2] = a[2] * x;
|
|
a[3] = a[3] * x;
|
|
|
|
a[4] = a[4] * y;
|
|
a[5] = a[5] * y;
|
|
a[6] = a[6] * y;
|
|
a[7] = a[7] * y;
|
|
|
|
a[8] = a[8] * z;
|
|
a[9] = a[9] * z;
|
|
a[10] = a[10] * z;
|
|
a[11] = a[11] * z;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Derive a rotation matrix around the given axis.
|
|
*
|
|
* @method Phaser.Math.Matrix4#makeRotationAxis
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector3|Phaser.Math.Vector4)} axis - The rotation axis.
|
|
* @param {number} angle - The rotation angle in radians.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
makeRotationAxis: function (axis, angle)
|
|
{
|
|
// Based on http://www.gamedev.net/reference/articles/article1199.asp
|
|
|
|
var c = Math.cos(angle);
|
|
var s = Math.sin(angle);
|
|
var t = 1 - c;
|
|
var x = axis.x;
|
|
var y = axis.y;
|
|
var z = axis.z;
|
|
var tx = t * x;
|
|
var ty = t * y;
|
|
|
|
return this.setValues(
|
|
tx * x + c, tx * y - s * z, tx * z + s * y, 0,
|
|
tx * y + s * z, ty * y + c, ty * z - s * x, 0,
|
|
tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
|
|
0, 0, 0, 1
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Apply a rotation transformation to this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#rotate
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The angle in radians to rotate by.
|
|
* @param {Phaser.Math.Vector3} axis - The axis to rotate upon.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
rotate: function (rad, axis)
|
|
{
|
|
var a = this.val;
|
|
var x = axis.x;
|
|
var y = axis.y;
|
|
var z = axis.z;
|
|
var len = Math.sqrt(x * x + y * y + z * z);
|
|
|
|
if (Math.abs(len) < EPSILON)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
len = 1 / len;
|
|
x *= len;
|
|
y *= len;
|
|
z *= len;
|
|
|
|
var s = Math.sin(rad);
|
|
var c = Math.cos(rad);
|
|
var t = 1 - c;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
var a30 = a[12];
|
|
var a31 = a[13];
|
|
var a32 = a[14];
|
|
var a33 = a[15];
|
|
|
|
// Construct the elements of the rotation matrix
|
|
var b00 = x * x * t + c;
|
|
var b01 = y * x * t + z * s;
|
|
var b02 = z * x * t - y * s;
|
|
|
|
var b10 = x * y * t - z * s;
|
|
var b11 = y * y * t + c;
|
|
var b12 = z * y * t + x * s;
|
|
|
|
var b20 = x * z * t + y * s;
|
|
var b21 = y * z * t - x * s;
|
|
var b22 = z * z * t + c;
|
|
|
|
// Perform rotation-specific matrix multiplication
|
|
return this.setValues(
|
|
a00 * b00 + a10 * b01 + a20 * b02,
|
|
a01 * b00 + a11 * b01 + a21 * b02,
|
|
a02 * b00 + a12 * b01 + a22 * b02,
|
|
a03 * b00 + a13 * b01 + a23 * b02,
|
|
a00 * b10 + a10 * b11 + a20 * b12,
|
|
a01 * b10 + a11 * b11 + a21 * b12,
|
|
a02 * b10 + a12 * b11 + a22 * b12,
|
|
a03 * b10 + a13 * b11 + a23 * b12,
|
|
a00 * b20 + a10 * b21 + a20 * b22,
|
|
a01 * b20 + a11 * b21 + a21 * b22,
|
|
a02 * b20 + a12 * b21 + a22 * b22,
|
|
a03 * b20 + a13 * b21 + a23 * b22,
|
|
a30, a31, a32, a33
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Rotate this matrix on its X axis.
|
|
*
|
|
* @method Phaser.Math.Matrix4#rotateX
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The angle in radians to rotate by.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
rotateX: function (rad)
|
|
{
|
|
var a = this.val;
|
|
var s = Math.sin(rad);
|
|
var c = Math.cos(rad);
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
// Perform axis-specific matrix multiplication
|
|
a[4] = a10 * c + a20 * s;
|
|
a[5] = a11 * c + a21 * s;
|
|
a[6] = a12 * c + a22 * s;
|
|
a[7] = a13 * c + a23 * s;
|
|
a[8] = a20 * c - a10 * s;
|
|
a[9] = a21 * c - a11 * s;
|
|
a[10] = a22 * c - a12 * s;
|
|
a[11] = a23 * c - a13 * s;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Rotate this matrix on its Y axis.
|
|
*
|
|
* @method Phaser.Math.Matrix4#rotateY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The angle to rotate by, in radians.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
rotateY: function (rad)
|
|
{
|
|
var a = this.val;
|
|
var s = Math.sin(rad);
|
|
var c = Math.cos(rad);
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
// Perform axis-specific matrix multiplication
|
|
a[0] = a00 * c - a20 * s;
|
|
a[1] = a01 * c - a21 * s;
|
|
a[2] = a02 * c - a22 * s;
|
|
a[3] = a03 * c - a23 * s;
|
|
a[8] = a00 * s + a20 * c;
|
|
a[9] = a01 * s + a21 * c;
|
|
a[10] = a02 * s + a22 * c;
|
|
a[11] = a03 * s + a23 * c;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Rotate this matrix on its Z axis.
|
|
*
|
|
* @method Phaser.Math.Matrix4#rotateZ
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The angle to rotate by, in radians.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
rotateZ: function (rad)
|
|
{
|
|
var a = this.val;
|
|
var s = Math.sin(rad);
|
|
var c = Math.cos(rad);
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
// Perform axis-specific matrix multiplication
|
|
a[0] = a00 * c + a10 * s;
|
|
a[1] = a01 * c + a11 * s;
|
|
a[2] = a02 * c + a12 * s;
|
|
a[3] = a03 * c + a13 * s;
|
|
a[4] = a10 * c - a00 * s;
|
|
a[5] = a11 * c - a01 * s;
|
|
a[6] = a12 * c - a02 * s;
|
|
a[7] = a13 * c - a03 * s;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix from the given rotation Quaternion and translation Vector.
|
|
*
|
|
* @method Phaser.Math.Matrix4#fromRotationTranslation
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Quaternion} q - The Quaternion to set rotation from.
|
|
* @param {Phaser.Math.Vector3} v - The Vector to set translation from.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
fromRotationTranslation: function (q, v)
|
|
{
|
|
// Quaternion math
|
|
var x = q.x;
|
|
var y = q.y;
|
|
var z = q.z;
|
|
var w = q.w;
|
|
|
|
var x2 = x + x;
|
|
var y2 = y + y;
|
|
var z2 = z + z;
|
|
|
|
var xx = x * x2;
|
|
var xy = x * y2;
|
|
var xz = x * z2;
|
|
|
|
var yy = y * y2;
|
|
var yz = y * z2;
|
|
var zz = z * z2;
|
|
|
|
var wx = w * x2;
|
|
var wy = w * y2;
|
|
var wz = w * z2;
|
|
|
|
return this.setValues(
|
|
1 - (yy + zz),
|
|
xy + wz,
|
|
xz - wy,
|
|
0,
|
|
|
|
xy - wz,
|
|
1 - (xx + zz),
|
|
yz + wx,
|
|
0,
|
|
|
|
xz + wy,
|
|
yz - wx,
|
|
1 - (xx + yy),
|
|
0,
|
|
|
|
v.x,
|
|
v.y,
|
|
v.z,
|
|
1
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix from the given Quaternion.
|
|
*
|
|
* @method Phaser.Math.Matrix4#fromQuat
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Quaternion} q - The Quaternion to set the values of this Matrix from.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
fromQuat: function (q)
|
|
{
|
|
var x = q.x;
|
|
var y = q.y;
|
|
var z = q.z;
|
|
var w = q.w;
|
|
|
|
var x2 = x + x;
|
|
var y2 = y + y;
|
|
var z2 = z + z;
|
|
|
|
var xx = x * x2;
|
|
var xy = x * y2;
|
|
var xz = x * z2;
|
|
|
|
var yy = y * y2;
|
|
var yz = y * z2;
|
|
var zz = z * z2;
|
|
|
|
var wx = w * x2;
|
|
var wy = w * y2;
|
|
var wz = w * z2;
|
|
|
|
return this.setValues(
|
|
1 - (yy + zz),
|
|
xy + wz,
|
|
xz - wy,
|
|
0,
|
|
|
|
xy - wz,
|
|
1 - (xx + zz),
|
|
yz + wx,
|
|
0,
|
|
|
|
xz + wy,
|
|
yz - wx,
|
|
1 - (xx + yy),
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
0,
|
|
1
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Generate a frustum matrix with the given bounds.
|
|
*
|
|
* @method Phaser.Math.Matrix4#frustum
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} left - The left bound of the frustum.
|
|
* @param {number} right - The right bound of the frustum.
|
|
* @param {number} bottom - The bottom bound of the frustum.
|
|
* @param {number} top - The top bound of the frustum.
|
|
* @param {number} near - The near bound of the frustum.
|
|
* @param {number} far - The far bound of the frustum.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
frustum: function (left, right, bottom, top, near, far)
|
|
{
|
|
var rl = 1 / (right - left);
|
|
var tb = 1 / (top - bottom);
|
|
var nf = 1 / (near - far);
|
|
|
|
return this.setValues(
|
|
(near * 2) * rl,
|
|
0,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
(near * 2) * tb,
|
|
0,
|
|
0,
|
|
|
|
(right + left) * rl,
|
|
(top + bottom) * tb,
|
|
(far + near) * nf,
|
|
-1,
|
|
|
|
0,
|
|
0,
|
|
(far * near * 2) * nf,
|
|
0
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Generate a perspective projection matrix with the given bounds.
|
|
*
|
|
* @method Phaser.Math.Matrix4#perspective
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} fovy - Vertical field of view in radians
|
|
* @param {number} aspect - Aspect ratio. Typically viewport width /height.
|
|
* @param {number} near - Near bound of the frustum.
|
|
* @param {number} far - Far bound of the frustum.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
perspective: function (fovy, aspect, near, far)
|
|
{
|
|
var f = 1.0 / Math.tan(fovy / 2);
|
|
var nf = 1 / (near - far);
|
|
|
|
return this.setValues(
|
|
f / aspect,
|
|
0,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
f,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
(far + near) * nf,
|
|
-1,
|
|
|
|
0,
|
|
0,
|
|
(2 * far * near) * nf,
|
|
0
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Generate a perspective projection matrix with the given bounds.
|
|
*
|
|
* @method Phaser.Math.Matrix4#perspectiveLH
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} width - The width of the frustum.
|
|
* @param {number} height - The height of the frustum.
|
|
* @param {number} near - Near bound of the frustum.
|
|
* @param {number} far - Far bound of the frustum.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
perspectiveLH: function (width, height, near, far)
|
|
{
|
|
return this.setValues(
|
|
(2 * near) / width,
|
|
0,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
(2 * near) / height,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
-far / (near - far),
|
|
1,
|
|
|
|
0,
|
|
0,
|
|
(near * far) / (near - far),
|
|
0
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Generate an orthogonal projection matrix with the given bounds.
|
|
*
|
|
* @method Phaser.Math.Matrix4#ortho
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} left - The left bound of the frustum.
|
|
* @param {number} right - The right bound of the frustum.
|
|
* @param {number} bottom - The bottom bound of the frustum.
|
|
* @param {number} top - The top bound of the frustum.
|
|
* @param {number} near - The near bound of the frustum.
|
|
* @param {number} far - The far bound of the frustum.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
ortho: function (left, right, bottom, top, near, far)
|
|
{
|
|
var lr = left - right;
|
|
var bt = bottom - top;
|
|
var nf = near - far;
|
|
|
|
// Avoid division by zero
|
|
lr = (lr === 0) ? lr : 1 / lr;
|
|
bt = (bt === 0) ? bt : 1 / bt;
|
|
nf = (nf === 0) ? nf : 1 / nf;
|
|
|
|
return this.setValues(
|
|
-2 * lr,
|
|
0,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
-2 * bt,
|
|
0,
|
|
0,
|
|
|
|
0,
|
|
0,
|
|
2 * nf,
|
|
0,
|
|
|
|
(left + right) * lr,
|
|
(top + bottom) * bt,
|
|
(far + near) * nf,
|
|
1
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Generate a right-handed look-at matrix with the given eye position, target and up axis.
|
|
*
|
|
* @method Phaser.Math.Matrix4#lookAtRH
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} eye - Position of the viewer.
|
|
* @param {Phaser.Math.Vector3} target - Point the viewer is looking at.
|
|
* @param {Phaser.Math.Vector3} up - vec3 pointing up.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
lookAtRH: function (eye, target, up)
|
|
{
|
|
var m = this.val;
|
|
|
|
_z.subVectors(eye, target);
|
|
|
|
if (_z.getLengthSquared() === 0)
|
|
{
|
|
// eye and target are in the same position
|
|
_z.z = 1;
|
|
}
|
|
|
|
_z.normalize();
|
|
_x.crossVectors(up, _z);
|
|
|
|
if (_x.getLengthSquared() === 0)
|
|
{
|
|
// up and z are parallel
|
|
|
|
if (Math.abs(up.z) === 1)
|
|
{
|
|
_z.x += 0.0001;
|
|
}
|
|
else
|
|
{
|
|
_z.z += 0.0001;
|
|
}
|
|
|
|
_z.normalize();
|
|
_x.crossVectors(up, _z);
|
|
}
|
|
|
|
_x.normalize();
|
|
_y.crossVectors(_z, _x);
|
|
|
|
m[0] = _x.x;
|
|
m[1] = _x.y;
|
|
m[2] = _x.z;
|
|
m[4] = _y.x;
|
|
m[5] = _y.y;
|
|
m[6] = _y.z;
|
|
m[8] = _z.x;
|
|
m[9] = _z.y;
|
|
m[10] = _z.z;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Generate a look-at matrix with the given eye position, focal point, and up axis.
|
|
*
|
|
* @method Phaser.Math.Matrix4#lookAt
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} eye - Position of the viewer
|
|
* @param {Phaser.Math.Vector3} center - Point the viewer is looking at
|
|
* @param {Phaser.Math.Vector3} up - vec3 pointing up.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
lookAt: function (eye, center, up)
|
|
{
|
|
var eyex = eye.x;
|
|
var eyey = eye.y;
|
|
var eyez = eye.z;
|
|
|
|
var upx = up.x;
|
|
var upy = up.y;
|
|
var upz = up.z;
|
|
|
|
var centerx = center.x;
|
|
var centery = center.y;
|
|
var centerz = center.z;
|
|
|
|
if (Math.abs(eyex - centerx) < EPSILON &&
|
|
Math.abs(eyey - centery) < EPSILON &&
|
|
Math.abs(eyez - centerz) < EPSILON)
|
|
{
|
|
return this.identity();
|
|
}
|
|
|
|
var z0 = eyex - centerx;
|
|
var z1 = eyey - centery;
|
|
var z2 = eyez - centerz;
|
|
|
|
var len = 1 / Math.sqrt(z0 * z0 + z1 * z1 + z2 * z2);
|
|
|
|
z0 *= len;
|
|
z1 *= len;
|
|
z2 *= len;
|
|
|
|
var x0 = upy * z2 - upz * z1;
|
|
var x1 = upz * z0 - upx * z2;
|
|
var x2 = upx * z1 - upy * z0;
|
|
|
|
len = Math.sqrt(x0 * x0 + x1 * x1 + x2 * x2);
|
|
|
|
if (!len)
|
|
{
|
|
x0 = 0;
|
|
x1 = 0;
|
|
x2 = 0;
|
|
}
|
|
else
|
|
{
|
|
len = 1 / len;
|
|
x0 *= len;
|
|
x1 *= len;
|
|
x2 *= len;
|
|
}
|
|
|
|
var y0 = z1 * x2 - z2 * x1;
|
|
var y1 = z2 * x0 - z0 * x2;
|
|
var y2 = z0 * x1 - z1 * x0;
|
|
|
|
len = Math.sqrt(y0 * y0 + y1 * y1 + y2 * y2);
|
|
|
|
if (!len)
|
|
{
|
|
y0 = 0;
|
|
y1 = 0;
|
|
y2 = 0;
|
|
}
|
|
else
|
|
{
|
|
len = 1 / len;
|
|
y0 *= len;
|
|
y1 *= len;
|
|
y2 *= len;
|
|
}
|
|
|
|
return this.setValues(
|
|
x0,
|
|
y0,
|
|
z0,
|
|
0,
|
|
|
|
x1,
|
|
y1,
|
|
z1,
|
|
0,
|
|
|
|
x2,
|
|
y2,
|
|
z2,
|
|
0,
|
|
|
|
-(x0 * eyex + x1 * eyey + x2 * eyez),
|
|
-(y0 * eyex + y1 * eyey + y2 * eyez),
|
|
-(z0 * eyex + z1 * eyey + z2 * eyez),
|
|
1
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Set the values of this matrix from the given `yaw`, `pitch` and `roll` values.
|
|
*
|
|
* @method Phaser.Math.Matrix4#yawPitchRoll
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} yaw - The yaw value.
|
|
* @param {number} pitch - The pitch value.
|
|
* @param {number} roll - The roll value.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
yawPitchRoll: function (yaw, pitch, roll)
|
|
{
|
|
this.zero();
|
|
_tempMat1.zero();
|
|
_tempMat2.zero();
|
|
|
|
var m0 = this.val;
|
|
var m1 = _tempMat1.val;
|
|
var m2 = _tempMat2.val;
|
|
|
|
// Rotate Z
|
|
var s = Math.sin(roll);
|
|
var c = Math.cos(roll);
|
|
|
|
m0[10] = 1;
|
|
m0[15] = 1;
|
|
m0[0] = c;
|
|
m0[1] = s;
|
|
m0[4] = -s;
|
|
m0[5] = c;
|
|
|
|
// Rotate X
|
|
s = Math.sin(pitch);
|
|
c = Math.cos(pitch);
|
|
|
|
m1[0] = 1;
|
|
m1[15] = 1;
|
|
m1[5] = c;
|
|
m1[10] = c;
|
|
m1[9] = -s;
|
|
m1[6] = s;
|
|
|
|
// Rotate Y
|
|
s = Math.sin(yaw);
|
|
c = Math.cos(yaw);
|
|
|
|
m2[5] = 1;
|
|
m2[15] = 1;
|
|
m2[0] = c;
|
|
m2[2] = -s;
|
|
m2[8] = s;
|
|
m2[10] = c;
|
|
|
|
this.multiplyLocal(_tempMat1);
|
|
this.multiplyLocal(_tempMat2);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Generate a world matrix from the given rotation, position, scale, view matrix and projection matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix4#setWorldMatrix
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} rotation - The rotation of the world matrix.
|
|
* @param {Phaser.Math.Vector3} position - The position of the world matrix.
|
|
* @param {Phaser.Math.Vector3} scale - The scale of the world matrix.
|
|
* @param {Phaser.Math.Matrix4} [viewMatrix] - The view matrix.
|
|
* @param {Phaser.Math.Matrix4} [projectionMatrix] - The projection matrix.
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
setWorldMatrix: function (rotation, position, scale, viewMatrix, projectionMatrix)
|
|
{
|
|
this.yawPitchRoll(rotation.y, rotation.x, rotation.z);
|
|
|
|
_tempMat1.scaling(scale.x, scale.y, scale.z);
|
|
_tempMat2.xyz(position.x, position.y, position.z);
|
|
|
|
this.multiplyLocal(_tempMat1);
|
|
this.multiplyLocal(_tempMat2);
|
|
|
|
if (viewMatrix)
|
|
{
|
|
this.multiplyLocal(viewMatrix);
|
|
}
|
|
|
|
if (projectionMatrix)
|
|
{
|
|
this.multiplyLocal(projectionMatrix);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Multiplies this Matrix4 by the given `src` Matrix4 and stores the results in the `out` Matrix4.
|
|
*
|
|
* @method Phaser.Math.Matrix4#multiplyToMat4
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} src - The Matrix4 to multiply with this one.
|
|
* @param {Phaser.Math.Matrix4} out - The receiving Matrix.
|
|
*
|
|
* @return {Phaser.Math.Matrix4} This `out` Matrix4.
|
|
*/
|
|
multiplyToMat4: function (src, out)
|
|
{
|
|
var a = this.val;
|
|
var b = src.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
var a30 = a[12];
|
|
var a31 = a[13];
|
|
var a32 = a[14];
|
|
var a33 = a[15];
|
|
|
|
var b00 = b[0];
|
|
var b01 = b[1];
|
|
var b02 = b[2];
|
|
var b03 = b[3];
|
|
var b10 = b[4];
|
|
var b11 = b[5];
|
|
var b12 = b[6];
|
|
var b13 = b[7];
|
|
var b20 = b[8];
|
|
var b21 = b[9];
|
|
var b22 = b[10];
|
|
var b23 = b[11];
|
|
var b30 = b[12];
|
|
var b31 = b[13];
|
|
var b32 = b[14];
|
|
var b33 = b[15];
|
|
|
|
return out.setValues(
|
|
b00 * a00 + b01 * a10 + b02 * a20 + b03 * a30,
|
|
b01 * a01 + b01 * a11 + b02 * a21 + b03 * a31,
|
|
b02 * a02 + b01 * a12 + b02 * a22 + b03 * a32,
|
|
b03 * a03 + b01 * a13 + b02 * a23 + b03 * a33,
|
|
|
|
b10 * a00 + b11 * a10 + b12 * a20 + b13 * a30,
|
|
b10 * a01 + b11 * a11 + b12 * a21 + b13 * a31,
|
|
b10 * a02 + b11 * a12 + b12 * a22 + b13 * a32,
|
|
b10 * a03 + b11 * a13 + b12 * a23 + b13 * a33,
|
|
|
|
b20 * a00 + b21 * a10 + b22 * a20 + b23 * a30,
|
|
b20 * a01 + b21 * a11 + b22 * a21 + b23 * a31,
|
|
b20 * a02 + b21 * a12 + b22 * a22 + b23 * a32,
|
|
b20 * a03 + b21 * a13 + b22 * a23 + b23 * a33,
|
|
|
|
b30 * a00 + b31 * a10 + b32 * a20 + b33 * a30,
|
|
b30 * a01 + b31 * a11 + b32 * a21 + b33 * a31,
|
|
b30 * a02 + b31 * a12 + b32 * a22 + b33 * a32,
|
|
b30 * a03 + b31 * a13 + b32 * a23 + b33 * a33
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Takes the rotation and position vectors and builds this Matrix4 from them.
|
|
*
|
|
* @method Phaser.Math.Matrix4#fromRotationXYTranslation
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} rotation - The rotation vector.
|
|
* @param {Phaser.Math.Vector3} position - The position vector.
|
|
* @param {boolean} translateFirst - Should the operation translate then rotate (`true`), or rotate then translate? (`false`)
|
|
*
|
|
* @return {this} This Matrix4.
|
|
*/
|
|
fromRotationXYTranslation: function (rotation, position, translateFirst)
|
|
{
|
|
var x = position.x;
|
|
var y = position.y;
|
|
var z = position.z;
|
|
|
|
var sx = Math.sin(rotation.x);
|
|
var cx = Math.cos(rotation.x);
|
|
|
|
var sy = Math.sin(rotation.y);
|
|
var cy = Math.cos(rotation.y);
|
|
|
|
var a30 = x;
|
|
var a31 = y;
|
|
var a32 = z;
|
|
|
|
// Rotate X
|
|
|
|
var b21 = -sx;
|
|
|
|
// Rotate Y
|
|
|
|
var c01 = 0 - b21 * sy;
|
|
|
|
var c02 = 0 - cx * sy;
|
|
|
|
var c21 = b21 * cy;
|
|
|
|
var c22 = cx * cy;
|
|
|
|
// Translate
|
|
if (!translateFirst)
|
|
{
|
|
// a30 = cy * x + 0 * y + sy * z;
|
|
a30 = cy * x + sy * z;
|
|
a31 = c01 * x + cx * y + c21 * z;
|
|
a32 = c02 * x + sx * y + c22 * z;
|
|
}
|
|
|
|
return this.setValues(
|
|
cy,
|
|
c01,
|
|
c02,
|
|
0,
|
|
0,
|
|
cx,
|
|
sx,
|
|
0,
|
|
sy,
|
|
c21,
|
|
c22,
|
|
0,
|
|
a30,
|
|
a31,
|
|
a32,
|
|
1
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Returns the maximum axis scale from this Matrix4.
|
|
*
|
|
* @method Phaser.Math.Matrix4#getMaxScaleOnAxis
|
|
* @since 3.50.0
|
|
*
|
|
* @return {number} The maximum axis scale.
|
|
*/
|
|
getMaxScaleOnAxis: function ()
|
|
{
|
|
var m = this.val;
|
|
|
|
var scaleXSq = m[0] * m[0] + m[1] * m[1] + m[2] * m[2];
|
|
var scaleYSq = m[4] * m[4] + m[5] * m[5] + m[6] * m[6];
|
|
var scaleZSq = m[8] * m[8] + m[9] * m[9] + m[10] * m[10];
|
|
|
|
return Math.sqrt(Math.max(scaleXSq, scaleYSq, scaleZSq));
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
var _tempMat1 = new Matrix4();
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
var _tempMat2 = new Matrix4();
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
var _x = new Vector3();
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
var _y = new Vector3();
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
var _z = new Vector3();
|
|
|
|
module.exports = Matrix4;
|
|
|
|
|
|
/***/ }),
|
|
/* 23 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Scenes.Events
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
ADDED_TO_SCENE: __webpack_require__(187),
|
|
BOOT: __webpack_require__(188),
|
|
CREATE: __webpack_require__(189),
|
|
DESTROY: __webpack_require__(190),
|
|
PAUSE: __webpack_require__(191),
|
|
POST_UPDATE: __webpack_require__(192),
|
|
PRE_RENDER: __webpack_require__(193),
|
|
PRE_UPDATE: __webpack_require__(194),
|
|
READY: __webpack_require__(195),
|
|
REMOVED_FROM_SCENE: __webpack_require__(196),
|
|
RENDER: __webpack_require__(197),
|
|
RESUME: __webpack_require__(198),
|
|
SHUTDOWN: __webpack_require__(199),
|
|
SLEEP: __webpack_require__(200),
|
|
START: __webpack_require__(201),
|
|
TRANSITION_COMPLETE: __webpack_require__(202),
|
|
TRANSITION_INIT: __webpack_require__(203),
|
|
TRANSITION_OUT: __webpack_require__(204),
|
|
TRANSITION_START: __webpack_require__(205),
|
|
TRANSITION_WAKE: __webpack_require__(206),
|
|
UPDATE: __webpack_require__(207),
|
|
WAKE: __webpack_require__(208)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 24 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var CONST = __webpack_require__(12);
|
|
var Events = __webpack_require__(47);
|
|
var GetFastValue = __webpack_require__(11);
|
|
var GetURL = __webpack_require__(48);
|
|
var MergeXHRSettings = __webpack_require__(49);
|
|
var XHRLoader = __webpack_require__(223);
|
|
var XHRSettings = __webpack_require__(50);
|
|
|
|
/**
|
|
* @classdesc
|
|
* The base File class used by all File Types that the Loader can support.
|
|
* You shouldn't create an instance of a File directly, but should extend it with your own class, setting a custom type and processing methods.
|
|
*
|
|
* @class File
|
|
* @memberof Phaser.Loader
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - The Loader that is going to load this File.
|
|
* @param {Phaser.Types.Loader.FileConfig} fileConfig - The file configuration object, as created by the file type.
|
|
*/
|
|
var File = new Class({
|
|
|
|
initialize:
|
|
|
|
function File (loader, fileConfig)
|
|
{
|
|
/**
|
|
* A reference to the Loader that is going to load this file.
|
|
*
|
|
* @name Phaser.Loader.File#loader
|
|
* @type {Phaser.Loader.LoaderPlugin}
|
|
* @since 3.0.0
|
|
*/
|
|
this.loader = loader;
|
|
|
|
/**
|
|
* A reference to the Cache, or Texture Manager, that is going to store this file if it loads.
|
|
*
|
|
* @name Phaser.Loader.File#cache
|
|
* @type {(Phaser.Cache.BaseCache|Phaser.Textures.TextureManager)}
|
|
* @since 3.7.0
|
|
*/
|
|
this.cache = GetFastValue(fileConfig, 'cache', false);
|
|
|
|
/**
|
|
* The file type string (image, json, etc) for sorting within the Loader.
|
|
*
|
|
* @name Phaser.Loader.File#type
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*/
|
|
this.type = GetFastValue(fileConfig, 'type', false);
|
|
|
|
if (!this.type)
|
|
{
|
|
throw new Error('Invalid File type: ' + this.type);
|
|
}
|
|
|
|
/**
|
|
* Unique cache key (unique within its file type)
|
|
*
|
|
* @name Phaser.Loader.File#key
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*/
|
|
this.key = GetFastValue(fileConfig, 'key', false);
|
|
|
|
var loadKey = this.key;
|
|
|
|
if (loader.prefix && loader.prefix !== '')
|
|
{
|
|
this.key = loader.prefix + loadKey;
|
|
}
|
|
|
|
if (!this.key)
|
|
{
|
|
throw new Error('Invalid File key: ' + this.key);
|
|
}
|
|
|
|
var url = GetFastValue(fileConfig, 'url');
|
|
|
|
if (url === undefined)
|
|
{
|
|
url = loader.path + loadKey + '.' + GetFastValue(fileConfig, 'extension', '');
|
|
}
|
|
else if (typeof url === 'string' && !url.match(/^(?:blob:|data:|capacitor:\/\/|http:\/\/|https:\/\/|\/\/)/))
|
|
{
|
|
url = loader.path + url;
|
|
}
|
|
|
|
/**
|
|
* The URL of the file, not including baseURL.
|
|
*
|
|
* Automatically has Loader.path prepended to it if a string.
|
|
*
|
|
* Can also be a JavaScript Object, such as the results of parsing JSON data.
|
|
*
|
|
* @name Phaser.Loader.File#url
|
|
* @type {object|string}
|
|
* @since 3.0.0
|
|
*/
|
|
this.url = url;
|
|
|
|
/**
|
|
* The final URL this file will load from, including baseURL and path.
|
|
* Set automatically when the Loader calls 'load' on this file.
|
|
*
|
|
* @name Phaser.Loader.File#src
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*/
|
|
this.src = '';
|
|
|
|
/**
|
|
* The merged XHRSettings for this file.
|
|
*
|
|
* @name Phaser.Loader.File#xhrSettings
|
|
* @type {Phaser.Types.Loader.XHRSettingsObject}
|
|
* @since 3.0.0
|
|
*/
|
|
this.xhrSettings = XHRSettings(GetFastValue(fileConfig, 'responseType', undefined));
|
|
|
|
if (GetFastValue(fileConfig, 'xhrSettings', false))
|
|
{
|
|
this.xhrSettings = MergeXHRSettings(this.xhrSettings, GetFastValue(fileConfig, 'xhrSettings', {}));
|
|
}
|
|
|
|
/**
|
|
* The XMLHttpRequest instance (as created by XHR Loader) that is loading this File.
|
|
*
|
|
* @name Phaser.Loader.File#xhrLoader
|
|
* @type {?XMLHttpRequest}
|
|
* @since 3.0.0
|
|
*/
|
|
this.xhrLoader = null;
|
|
|
|
/**
|
|
* The current state of the file. One of the FILE_CONST values.
|
|
*
|
|
* @name Phaser.Loader.File#state
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.state = (typeof(this.url) === 'function') ? CONST.FILE_POPULATED : CONST.FILE_PENDING;
|
|
|
|
/**
|
|
* The total size of this file.
|
|
* Set by onProgress and only if loading via XHR.
|
|
*
|
|
* @name Phaser.Loader.File#bytesTotal
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.bytesTotal = 0;
|
|
|
|
/**
|
|
* Updated as the file loads.
|
|
* Only set if loading via XHR.
|
|
*
|
|
* @name Phaser.Loader.File#bytesLoaded
|
|
* @type {number}
|
|
* @default -1
|
|
* @since 3.0.0
|
|
*/
|
|
this.bytesLoaded = -1;
|
|
|
|
/**
|
|
* A percentage value between 0 and 1 indicating how much of this file has loaded.
|
|
* Only set if loading via XHR.
|
|
*
|
|
* @name Phaser.Loader.File#percentComplete
|
|
* @type {number}
|
|
* @default -1
|
|
* @since 3.0.0
|
|
*/
|
|
this.percentComplete = -1;
|
|
|
|
/**
|
|
* For CORs based loading.
|
|
* If this is undefined then the File will check BaseLoader.crossOrigin and use that (if set)
|
|
*
|
|
* @name Phaser.Loader.File#crossOrigin
|
|
* @type {(string|undefined)}
|
|
* @since 3.0.0
|
|
*/
|
|
this.crossOrigin = undefined;
|
|
|
|
/**
|
|
* The processed file data, stored here after the file has loaded.
|
|
*
|
|
* @name Phaser.Loader.File#data
|
|
* @type {*}
|
|
* @since 3.0.0
|
|
*/
|
|
this.data = undefined;
|
|
|
|
/**
|
|
* A config object that can be used by file types to store transitional data.
|
|
*
|
|
* @name Phaser.Loader.File#config
|
|
* @type {*}
|
|
* @since 3.0.0
|
|
*/
|
|
this.config = GetFastValue(fileConfig, 'config', {});
|
|
|
|
/**
|
|
* If this is a multipart file, i.e. an atlas and its json together, then this is a reference
|
|
* to the parent MultiFile. Set and used internally by the Loader or specific file types.
|
|
*
|
|
* @name Phaser.Loader.File#multiFile
|
|
* @type {?Phaser.Loader.MultiFile}
|
|
* @since 3.7.0
|
|
*/
|
|
this.multiFile;
|
|
|
|
/**
|
|
* Does this file have an associated linked file? Such as an image and a normal map.
|
|
* Atlases and Bitmap Fonts use the multiFile, because those files need loading together but aren't
|
|
* actually bound by data, where-as a linkFile is.
|
|
*
|
|
* @name Phaser.Loader.File#linkFile
|
|
* @type {?Phaser.Loader.File}
|
|
* @since 3.7.0
|
|
*/
|
|
this.linkFile;
|
|
},
|
|
|
|
/**
|
|
* Links this File with another, so they depend upon each other for loading and processing.
|
|
*
|
|
* @method Phaser.Loader.File#setLink
|
|
* @since 3.7.0
|
|
*
|
|
* @param {Phaser.Loader.File} fileB - The file to link to this one.
|
|
*/
|
|
setLink: function (fileB)
|
|
{
|
|
this.linkFile = fileB;
|
|
|
|
fileB.linkFile = this;
|
|
},
|
|
|
|
/**
|
|
* Resets the XHRLoader instance this file is using.
|
|
*
|
|
* @method Phaser.Loader.File#resetXHR
|
|
* @since 3.0.0
|
|
*/
|
|
resetXHR: function ()
|
|
{
|
|
if (this.xhrLoader)
|
|
{
|
|
this.xhrLoader.onload = undefined;
|
|
this.xhrLoader.onerror = undefined;
|
|
this.xhrLoader.onprogress = undefined;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called by the Loader, starts the actual file downloading.
|
|
* During the load the methods onLoad, onError and onProgress are called, based on the XHR events.
|
|
* You shouldn't normally call this method directly, it's meant to be invoked by the Loader.
|
|
*
|
|
* @method Phaser.Loader.File#load
|
|
* @since 3.0.0
|
|
*/
|
|
load: function ()
|
|
{
|
|
if (this.state === CONST.FILE_POPULATED)
|
|
{
|
|
// Can happen for example in a JSONFile if they've provided a JSON object instead of a URL
|
|
this.loader.nextFile(this, true);
|
|
}
|
|
else
|
|
{
|
|
this.state = CONST.FILE_LOADING;
|
|
|
|
this.src = GetURL(this, this.loader.baseURL);
|
|
|
|
if (this.src.indexOf('data:') === 0)
|
|
{
|
|
console.warn('Local data URIs are not supported: ' + this.key);
|
|
}
|
|
else
|
|
{
|
|
// The creation of this XHRLoader starts the load process going.
|
|
// It will automatically call the following, based on the load outcome:
|
|
//
|
|
// xhr.onload = this.onLoad
|
|
// xhr.onerror = this.onError
|
|
// xhr.onprogress = this.onProgress
|
|
|
|
this.xhrLoader = XHRLoader(this, this.loader.xhr);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called when the file finishes loading, is sent a DOM ProgressEvent.
|
|
*
|
|
* @method Phaser.Loader.File#onLoad
|
|
* @since 3.0.0
|
|
*
|
|
* @param {XMLHttpRequest} xhr - The XMLHttpRequest that caused this onload event.
|
|
* @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this load.
|
|
*/
|
|
onLoad: function (xhr, event)
|
|
{
|
|
var isLocalFile = xhr.responseURL && this.loader.localSchemes.some(function (scheme)
|
|
{
|
|
return xhr.responseURL.indexOf(scheme) === 0;
|
|
});
|
|
|
|
var localFileOk = (isLocalFile && event.target.status === 0);
|
|
|
|
var success = !(event.target && event.target.status !== 200) || localFileOk;
|
|
|
|
// Handle HTTP status codes of 4xx and 5xx as errors, even if xhr.onerror was not called.
|
|
if (xhr.readyState === 4 && xhr.status >= 400 && xhr.status <= 599)
|
|
{
|
|
success = false;
|
|
}
|
|
|
|
this.state = CONST.FILE_LOADED;
|
|
|
|
this.resetXHR();
|
|
|
|
this.loader.nextFile(this, success);
|
|
},
|
|
|
|
/**
|
|
* Called if the file errors while loading, is sent a DOM ProgressEvent.
|
|
*
|
|
* @method Phaser.Loader.File#onError
|
|
* @since 3.0.0
|
|
*
|
|
* @param {XMLHttpRequest} xhr - The XMLHttpRequest that caused this onload event.
|
|
* @param {ProgressEvent} event - The DOM ProgressEvent that resulted from this error.
|
|
*/
|
|
onError: function ()
|
|
{
|
|
this.resetXHR();
|
|
|
|
this.loader.nextFile(this, false);
|
|
},
|
|
|
|
/**
|
|
* Called during the file load progress. Is sent a DOM ProgressEvent.
|
|
*
|
|
* @method Phaser.Loader.File#onProgress
|
|
* @fires Phaser.Loader.Events#FILE_PROGRESS
|
|
* @since 3.0.0
|
|
*
|
|
* @param {ProgressEvent} event - The DOM ProgressEvent.
|
|
*/
|
|
onProgress: function (event)
|
|
{
|
|
if (event.lengthComputable)
|
|
{
|
|
this.bytesLoaded = event.loaded;
|
|
this.bytesTotal = event.total;
|
|
|
|
this.percentComplete = Math.min((this.bytesLoaded / this.bytesTotal), 1);
|
|
|
|
this.loader.emit(Events.FILE_PROGRESS, this, this.percentComplete);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Usually overridden by the FileTypes and is called by Loader.nextFile.
|
|
* This method controls what extra work this File does with its loaded data, for example a JSON file will parse itself during this stage.
|
|
*
|
|
* @method Phaser.Loader.File#onProcess
|
|
* @since 3.0.0
|
|
*/
|
|
onProcess: function ()
|
|
{
|
|
this.state = CONST.FILE_PROCESSING;
|
|
|
|
this.onProcessComplete();
|
|
},
|
|
|
|
/**
|
|
* Called when the File has completed processing.
|
|
* Checks on the state of its multifile, if set.
|
|
*
|
|
* @method Phaser.Loader.File#onProcessComplete
|
|
* @since 3.7.0
|
|
*/
|
|
onProcessComplete: function ()
|
|
{
|
|
this.state = CONST.FILE_COMPLETE;
|
|
|
|
if (this.multiFile)
|
|
{
|
|
this.multiFile.onFileComplete(this);
|
|
}
|
|
|
|
this.loader.fileProcessComplete(this);
|
|
},
|
|
|
|
/**
|
|
* Called when the File has completed processing but it generated an error.
|
|
* Checks on the state of its multifile, if set.
|
|
*
|
|
* @method Phaser.Loader.File#onProcessError
|
|
* @since 3.7.0
|
|
*/
|
|
onProcessError: function ()
|
|
{
|
|
// eslint-disable-next-line no-console
|
|
console.error('Failed to process file: %s "%s"', this.type, this.key);
|
|
|
|
this.state = CONST.FILE_ERRORED;
|
|
|
|
if (this.multiFile)
|
|
{
|
|
this.multiFile.onFileFailed(this);
|
|
}
|
|
|
|
this.loader.fileProcessComplete(this);
|
|
},
|
|
|
|
/**
|
|
* Checks if a key matching the one used by this file exists in the target Cache or not.
|
|
* This is called automatically by the LoaderPlugin to decide if the file can be safely
|
|
* loaded or will conflict.
|
|
*
|
|
* @method Phaser.Loader.File#hasCacheConflict
|
|
* @since 3.7.0
|
|
*
|
|
* @return {boolean} `true` if adding this file will cause a conflict, otherwise `false`.
|
|
*/
|
|
hasCacheConflict: function ()
|
|
{
|
|
return (this.cache && this.cache.exists(this.key));
|
|
},
|
|
|
|
/**
|
|
* Adds this file to its target cache upon successful loading and processing.
|
|
* This method is often overridden by specific file types.
|
|
*
|
|
* @method Phaser.Loader.File#addToCache
|
|
* @since 3.7.0
|
|
*/
|
|
addToCache: function ()
|
|
{
|
|
if (this.cache && this.data)
|
|
{
|
|
this.cache.add(this.key, this.data);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called once the file has been added to its cache and is now ready for deletion from the Loader.
|
|
* It will emit a `filecomplete` event from the LoaderPlugin.
|
|
*
|
|
* @method Phaser.Loader.File#pendingDestroy
|
|
* @fires Phaser.Loader.Events#FILE_COMPLETE
|
|
* @fires Phaser.Loader.Events#FILE_KEY_COMPLETE
|
|
* @since 3.7.0
|
|
*/
|
|
pendingDestroy: function (data)
|
|
{
|
|
if (this.state === CONST.FILE_PENDING_DESTROY)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (data === undefined) { data = this.data; }
|
|
|
|
var key = this.key;
|
|
var type = this.type;
|
|
|
|
this.loader.emit(Events.FILE_COMPLETE, key, type, data);
|
|
this.loader.emit(Events.FILE_KEY_COMPLETE + type + '-' + key, key, type, data);
|
|
|
|
this.loader.flagForRemoval(this);
|
|
|
|
this.state = CONST.FILE_PENDING_DESTROY;
|
|
},
|
|
|
|
/**
|
|
* Destroy this File and any references it holds.
|
|
*
|
|
* @method Phaser.Loader.File#destroy
|
|
* @since 3.7.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.loader = null;
|
|
this.cache = null;
|
|
this.xhrSettings = null;
|
|
this.multiFile = null;
|
|
this.linkFile = null;
|
|
this.data = null;
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* Static method for creating object URL using URL API and setting it as image 'src' attribute.
|
|
* If URL API is not supported (usually on old browsers) it falls back to creating Base64 encoded url using FileReader.
|
|
*
|
|
* @method Phaser.Loader.File.createObjectURL
|
|
* @static
|
|
* @since 3.7.0
|
|
*
|
|
* @param {HTMLImageElement} image - Image object which 'src' attribute should be set to object URL.
|
|
* @param {Blob} blob - A Blob object to create an object URL for.
|
|
* @param {string} defaultType - Default mime type used if blob type is not available.
|
|
*/
|
|
File.createObjectURL = function (image, blob, defaultType)
|
|
{
|
|
if (typeof URL === 'function')
|
|
{
|
|
image.src = URL.createObjectURL(blob);
|
|
}
|
|
else
|
|
{
|
|
var reader = new FileReader();
|
|
|
|
reader.onload = function ()
|
|
{
|
|
image.removeAttribute('crossOrigin');
|
|
image.src = 'data:' + (blob.type || defaultType) + ';base64,' + reader.result.split(',')[1];
|
|
};
|
|
|
|
reader.onerror = image.onerror;
|
|
|
|
reader.readAsDataURL(blob);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Static method for releasing an existing object URL which was previously created
|
|
* by calling {@link File#createObjectURL} method.
|
|
*
|
|
* @method Phaser.Loader.File.revokeObjectURL
|
|
* @static
|
|
* @since 3.7.0
|
|
*
|
|
* @param {HTMLImageElement} image - Image object which 'src' attribute should be revoked.
|
|
*/
|
|
File.revokeObjectURL = function (image)
|
|
{
|
|
if (typeof URL === 'function')
|
|
{
|
|
URL.revokeObjectURL(image.src);
|
|
}
|
|
};
|
|
|
|
module.exports = File;
|
|
|
|
|
|
/***/ }),
|
|
/* 25 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var types = {};
|
|
|
|
/**
|
|
* @namespace Phaser.Loader.FileTypesManager
|
|
*/
|
|
|
|
var FileTypesManager = {
|
|
|
|
/**
|
|
* Static method called when a LoaderPlugin is created.
|
|
*
|
|
* Loops through the local types object and injects all of them as
|
|
* properties into the LoaderPlugin instance.
|
|
*
|
|
* @method Phaser.Loader.FileTypesManager.install
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - The LoaderPlugin to install the types into.
|
|
*/
|
|
install: function (loader)
|
|
{
|
|
for (var key in types)
|
|
{
|
|
loader[key] = types[key];
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Static method called directly by the File Types.
|
|
*
|
|
* The key is a reference to the function used to load the files via the Loader, i.e. `image`.
|
|
*
|
|
* @method Phaser.Loader.FileTypesManager.register
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} key - The key that will be used as the method name in the LoaderPlugin.
|
|
* @param {function} factoryFunction - The function that will be called when LoaderPlugin.key is invoked.
|
|
*/
|
|
register: function (key, factoryFunction)
|
|
{
|
|
types[key] = factoryFunction;
|
|
},
|
|
|
|
/**
|
|
* Removed all associated file types.
|
|
*
|
|
* @method Phaser.Loader.FileTypesManager.destroy
|
|
* @since 3.0.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
types = {};
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = FileTypesManager;
|
|
|
|
|
|
/***/ }),
|
|
/* 26 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var MATH_CONST = __webpack_require__(4);
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Matrix used for display transformations for rendering.
|
|
*
|
|
* It is represented like so:
|
|
*
|
|
* ```
|
|
* | a | c | tx |
|
|
* | b | d | ty |
|
|
* | 0 | 0 | 1 |
|
|
* ```
|
|
*
|
|
* @class TransformMatrix
|
|
* @memberof Phaser.GameObjects.Components
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [a=1] - The Scale X value.
|
|
* @param {number} [b=0] - The Skew Y value.
|
|
* @param {number} [c=0] - The Skew X value.
|
|
* @param {number} [d=1] - The Scale Y value.
|
|
* @param {number} [tx=0] - The Translate X value.
|
|
* @param {number} [ty=0] - The Translate Y value.
|
|
*/
|
|
var TransformMatrix = new Class({
|
|
|
|
initialize:
|
|
|
|
function TransformMatrix (a, b, c, d, tx, ty)
|
|
{
|
|
if (a === undefined) { a = 1; }
|
|
if (b === undefined) { b = 0; }
|
|
if (c === undefined) { c = 0; }
|
|
if (d === undefined) { d = 1; }
|
|
if (tx === undefined) { tx = 0; }
|
|
if (ty === undefined) { ty = 0; }
|
|
|
|
/**
|
|
* The matrix values.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#matrix
|
|
* @type {Float32Array}
|
|
* @since 3.0.0
|
|
*/
|
|
this.matrix = new Float32Array([ a, b, c, d, tx, ty, 0, 0, 1 ]);
|
|
|
|
/**
|
|
* The decomposed matrix.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#decomposedMatrix
|
|
* @type {object}
|
|
* @since 3.0.0
|
|
*/
|
|
this.decomposedMatrix = {
|
|
translateX: 0,
|
|
translateY: 0,
|
|
scaleX: 1,
|
|
scaleY: 1,
|
|
rotation: 0
|
|
};
|
|
|
|
/**
|
|
* The temporary quad value cache.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#quad
|
|
* @type {Float32Array}
|
|
* @since 3.60.0
|
|
*/
|
|
this.quad = new Float32Array(8);
|
|
},
|
|
|
|
/**
|
|
* The Scale X value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#a
|
|
* @type {number}
|
|
* @since 3.4.0
|
|
*/
|
|
a: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[0];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[0] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Skew Y value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#b
|
|
* @type {number}
|
|
* @since 3.4.0
|
|
*/
|
|
b: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[1];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[1] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Skew X value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#c
|
|
* @type {number}
|
|
* @since 3.4.0
|
|
*/
|
|
c: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[2];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[2] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Scale Y value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#d
|
|
* @type {number}
|
|
* @since 3.4.0
|
|
*/
|
|
d: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[3];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[3] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Translate X value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#e
|
|
* @type {number}
|
|
* @since 3.11.0
|
|
*/
|
|
e: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[4];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[4] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Translate Y value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#f
|
|
* @type {number}
|
|
* @since 3.11.0
|
|
*/
|
|
f: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[5];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[5] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Translate X value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#tx
|
|
* @type {number}
|
|
* @since 3.4.0
|
|
*/
|
|
tx: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[4];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[4] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Translate Y value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#ty
|
|
* @type {number}
|
|
* @since 3.4.0
|
|
*/
|
|
ty: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.matrix[5];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.matrix[5] = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The rotation of the Matrix. Value is in radians.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#rotation
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
rotation: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.acos(this.a / this.scaleX) * ((Math.atan(-this.c / this.a) < 0) ? -1 : 1);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The rotation of the Matrix, normalized to be within the Phaser right-handed
|
|
* clockwise rotation space. Value is in radians.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#rotationNormalized
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.19.0
|
|
*/
|
|
rotationNormalized: {
|
|
|
|
get: function ()
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
var a = matrix[0];
|
|
var b = matrix[1];
|
|
var c = matrix[2];
|
|
var d = matrix[3];
|
|
|
|
if (a || b)
|
|
{
|
|
// var r = Math.sqrt(a * a + b * b);
|
|
|
|
return (b > 0) ? Math.acos(a / this.scaleX) : -Math.acos(a / this.scaleX);
|
|
}
|
|
else if (c || d)
|
|
{
|
|
// var s = Math.sqrt(c * c + d * d);
|
|
|
|
return MATH_CONST.TAU - ((d > 0) ? Math.acos(-c / this.scaleY) : -Math.acos(c / this.scaleY));
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The decomposed horizontal scale of the Matrix. This value is always positive.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#scaleX
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
scaleX: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.sqrt((this.a * this.a) + (this.b * this.b));
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The decomposed vertical scale of the Matrix. This value is always positive.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TransformMatrix#scaleY
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
scaleY: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.sqrt((this.c * this.c) + (this.d * this.d));
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Reset the Matrix to an identity matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#loadIdentity
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
loadIdentity: function ()
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
matrix[0] = 1;
|
|
matrix[1] = 0;
|
|
matrix[2] = 0;
|
|
matrix[3] = 1;
|
|
matrix[4] = 0;
|
|
matrix[5] = 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Translate the Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#translate
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The horizontal translation value.
|
|
* @param {number} y - The vertical translation value.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
translate: function (x, y)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
matrix[4] = matrix[0] * x + matrix[2] * y + matrix[4];
|
|
matrix[5] = matrix[1] * x + matrix[3] * y + matrix[5];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Scale the Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#scale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The horizontal scale value.
|
|
* @param {number} y - The vertical scale value.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
scale: function (x, y)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
matrix[0] *= x;
|
|
matrix[1] *= x;
|
|
matrix[2] *= y;
|
|
matrix[3] *= y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Rotate the Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#rotate
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} angle - The angle of rotation in radians.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
rotate: function (angle)
|
|
{
|
|
var sin = Math.sin(angle);
|
|
var cos = Math.cos(angle);
|
|
|
|
var matrix = this.matrix;
|
|
|
|
var a = matrix[0];
|
|
var b = matrix[1];
|
|
var c = matrix[2];
|
|
var d = matrix[3];
|
|
|
|
matrix[0] = a * cos + c * sin;
|
|
matrix[1] = b * cos + d * sin;
|
|
matrix[2] = a * -sin + c * cos;
|
|
matrix[3] = b * -sin + d * cos;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Multiply this Matrix by the given Matrix.
|
|
*
|
|
* If an `out` Matrix is given then the results will be stored in it.
|
|
* If it is not given, this matrix will be updated in place instead.
|
|
* Use an `out` Matrix if you do not wish to mutate this matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#multiply
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} rhs - The Matrix to multiply by.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} [out] - An optional Matrix to store the results in.
|
|
*
|
|
* @return {(this|Phaser.GameObjects.Components.TransformMatrix)} Either this TransformMatrix, or the `out` Matrix, if given in the arguments.
|
|
*/
|
|
multiply: function (rhs, out)
|
|
{
|
|
var matrix = this.matrix;
|
|
var source = rhs.matrix;
|
|
|
|
var localA = matrix[0];
|
|
var localB = matrix[1];
|
|
var localC = matrix[2];
|
|
var localD = matrix[3];
|
|
var localE = matrix[4];
|
|
var localF = matrix[5];
|
|
|
|
var sourceA = source[0];
|
|
var sourceB = source[1];
|
|
var sourceC = source[2];
|
|
var sourceD = source[3];
|
|
var sourceE = source[4];
|
|
var sourceF = source[5];
|
|
|
|
var destinationMatrix = (out === undefined) ? matrix : out.matrix;
|
|
|
|
destinationMatrix[0] = (sourceA * localA) + (sourceB * localC);
|
|
destinationMatrix[1] = (sourceA * localB) + (sourceB * localD);
|
|
destinationMatrix[2] = (sourceC * localA) + (sourceD * localC);
|
|
destinationMatrix[3] = (sourceC * localB) + (sourceD * localD);
|
|
destinationMatrix[4] = (sourceE * localA) + (sourceF * localC) + localE;
|
|
destinationMatrix[5] = (sourceE * localB) + (sourceF * localD) + localF;
|
|
|
|
return destinationMatrix;
|
|
},
|
|
|
|
/**
|
|
* Multiply this Matrix by the matrix given, including the offset.
|
|
*
|
|
* The offsetX is added to the tx value: `offsetX * a + offsetY * c + tx`.
|
|
* The offsetY is added to the ty value: `offsetY * b + offsetY * d + ty`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#multiplyWithOffset
|
|
* @since 3.11.0
|
|
*
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} src - The source Matrix to copy from.
|
|
* @param {number} offsetX - Horizontal offset to factor in to the multiplication.
|
|
* @param {number} offsetY - Vertical offset to factor in to the multiplication.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
multiplyWithOffset: function (src, offsetX, offsetY)
|
|
{
|
|
var matrix = this.matrix;
|
|
var otherMatrix = src.matrix;
|
|
|
|
var a0 = matrix[0];
|
|
var b0 = matrix[1];
|
|
var c0 = matrix[2];
|
|
var d0 = matrix[3];
|
|
var tx0 = matrix[4];
|
|
var ty0 = matrix[5];
|
|
|
|
var pse = offsetX * a0 + offsetY * c0 + tx0;
|
|
var psf = offsetX * b0 + offsetY * d0 + ty0;
|
|
|
|
var a1 = otherMatrix[0];
|
|
var b1 = otherMatrix[1];
|
|
var c1 = otherMatrix[2];
|
|
var d1 = otherMatrix[3];
|
|
var tx1 = otherMatrix[4];
|
|
var ty1 = otherMatrix[5];
|
|
|
|
matrix[0] = a1 * a0 + b1 * c0;
|
|
matrix[1] = a1 * b0 + b1 * d0;
|
|
matrix[2] = c1 * a0 + d1 * c0;
|
|
matrix[3] = c1 * b0 + d1 * d0;
|
|
matrix[4] = tx1 * a0 + ty1 * c0 + pse;
|
|
matrix[5] = tx1 * b0 + ty1 * d0 + psf;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform the Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#transform
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} a - The Scale X value.
|
|
* @param {number} b - The Shear Y value.
|
|
* @param {number} c - The Shear X value.
|
|
* @param {number} d - The Scale Y value.
|
|
* @param {number} tx - The Translate X value.
|
|
* @param {number} ty - The Translate Y value.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
transform: function (a, b, c, d, tx, ty)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
var a0 = matrix[0];
|
|
var b0 = matrix[1];
|
|
var c0 = matrix[2];
|
|
var d0 = matrix[3];
|
|
var tx0 = matrix[4];
|
|
var ty0 = matrix[5];
|
|
|
|
matrix[0] = a * a0 + b * c0;
|
|
matrix[1] = a * b0 + b * d0;
|
|
matrix[2] = c * a0 + d * c0;
|
|
matrix[3] = c * b0 + d * d0;
|
|
matrix[4] = tx * a0 + ty * c0 + tx0;
|
|
matrix[5] = tx * b0 + ty * d0 + ty0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform a point in to the local space of this Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#transformPoint
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The x coordinate of the point to transform.
|
|
* @param {number} y - The y coordinate of the point to transform.
|
|
* @param {Phaser.Types.Math.Vector2Like} [point] - Optional Point object to store the transformed coordinates in.
|
|
*
|
|
* @return {Phaser.Types.Math.Vector2Like} The Point containing the transformed coordinates.
|
|
*/
|
|
transformPoint: function (x, y, point)
|
|
{
|
|
if (point === undefined) { point = { x: 0, y: 0 }; }
|
|
|
|
var matrix = this.matrix;
|
|
|
|
var a = matrix[0];
|
|
var b = matrix[1];
|
|
var c = matrix[2];
|
|
var d = matrix[3];
|
|
var tx = matrix[4];
|
|
var ty = matrix[5];
|
|
|
|
point.x = x * a + y * c + tx;
|
|
point.y = x * b + y * d + ty;
|
|
|
|
return point;
|
|
},
|
|
|
|
/**
|
|
* Invert the Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#invert
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
invert: function ()
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
var a = matrix[0];
|
|
var b = matrix[1];
|
|
var c = matrix[2];
|
|
var d = matrix[3];
|
|
var tx = matrix[4];
|
|
var ty = matrix[5];
|
|
|
|
var n = a * d - b * c;
|
|
|
|
matrix[0] = d / n;
|
|
matrix[1] = -b / n;
|
|
matrix[2] = -c / n;
|
|
matrix[3] = a / n;
|
|
matrix[4] = (c * ty - d * tx) / n;
|
|
matrix[5] = -(a * ty - b * tx) / n;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix to copy those of the matrix given.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#copyFrom
|
|
* @since 3.11.0
|
|
*
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} src - The source Matrix to copy from.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
copyFrom: function (src)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
matrix[0] = src.a;
|
|
matrix[1] = src.b;
|
|
matrix[2] = src.c;
|
|
matrix[3] = src.d;
|
|
matrix[4] = src.e;
|
|
matrix[5] = src.f;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix to copy those of the array given.
|
|
* Where array indexes 0, 1, 2, 3, 4 and 5 are mapped to a, b, c, d, e and f.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#copyFromArray
|
|
* @since 3.11.0
|
|
*
|
|
* @param {array} src - The array of values to set into this matrix.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
copyFromArray: function (src)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
matrix[0] = src[0];
|
|
matrix[1] = src[1];
|
|
matrix[2] = src[2];
|
|
matrix[3] = src[3];
|
|
matrix[4] = src[4];
|
|
matrix[5] = src[5];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Copy the values from this Matrix to the given Canvas Rendering Context.
|
|
* This will use the Context.transform method.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#copyToContext
|
|
* @since 3.12.0
|
|
*
|
|
* @param {CanvasRenderingContext2D} ctx - The Canvas Rendering Context to copy the matrix values to.
|
|
*
|
|
* @return {CanvasRenderingContext2D} The Canvas Rendering Context.
|
|
*/
|
|
copyToContext: function (ctx)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
ctx.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
|
|
|
|
return ctx;
|
|
},
|
|
|
|
/**
|
|
* Copy the values from this Matrix to the given Canvas Rendering Context.
|
|
* This will use the Context.setTransform method.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#setToContext
|
|
* @since 3.12.0
|
|
*
|
|
* @param {CanvasRenderingContext2D} ctx - The Canvas Rendering Context to copy the matrix values to.
|
|
*
|
|
* @return {CanvasRenderingContext2D} The Canvas Rendering Context.
|
|
*/
|
|
setToContext: function (ctx)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
ctx.setTransform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
|
|
|
|
return ctx;
|
|
},
|
|
|
|
/**
|
|
* Copy the values in this Matrix to the array given.
|
|
*
|
|
* Where array indexes 0, 1, 2, 3, 4 and 5 are mapped to a, b, c, d, e and f.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#copyToArray
|
|
* @since 3.12.0
|
|
*
|
|
* @param {array} [out] - The array to copy the matrix values in to.
|
|
*
|
|
* @return {array} An array where elements 0 to 5 contain the values from this matrix.
|
|
*/
|
|
copyToArray: function (out)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
if (out === undefined)
|
|
{
|
|
out = [ matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5] ];
|
|
}
|
|
else
|
|
{
|
|
out[0] = matrix[0];
|
|
out[1] = matrix[1];
|
|
out[2] = matrix[2];
|
|
out[3] = matrix[3];
|
|
out[4] = matrix[4];
|
|
out[5] = matrix[5];
|
|
}
|
|
|
|
return out;
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#setTransform
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} a - The Scale X value.
|
|
* @param {number} b - The Shear Y value.
|
|
* @param {number} c - The Shear X value.
|
|
* @param {number} d - The Scale Y value.
|
|
* @param {number} tx - The Translate X value.
|
|
* @param {number} ty - The Translate Y value.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
setTransform: function (a, b, c, d, tx, ty)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
matrix[0] = a;
|
|
matrix[1] = b;
|
|
matrix[2] = c;
|
|
matrix[3] = d;
|
|
matrix[4] = tx;
|
|
matrix[5] = ty;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Decompose this Matrix into its translation, scale and rotation values using QR decomposition.
|
|
*
|
|
* The result must be applied in the following order to reproduce the current matrix:
|
|
*
|
|
* translate -> rotate -> scale
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#decomposeMatrix
|
|
* @since 3.0.0
|
|
*
|
|
* @return {object} The decomposed Matrix.
|
|
*/
|
|
decomposeMatrix: function ()
|
|
{
|
|
var decomposedMatrix = this.decomposedMatrix;
|
|
|
|
var matrix = this.matrix;
|
|
|
|
// a = scale X (1)
|
|
// b = shear Y (0)
|
|
// c = shear X (0)
|
|
// d = scale Y (1)
|
|
|
|
var a = matrix[0];
|
|
var b = matrix[1];
|
|
var c = matrix[2];
|
|
var d = matrix[3];
|
|
|
|
var determ = a * d - b * c;
|
|
|
|
decomposedMatrix.translateX = matrix[4];
|
|
decomposedMatrix.translateY = matrix[5];
|
|
|
|
if (a || b)
|
|
{
|
|
var r = Math.sqrt(a * a + b * b);
|
|
|
|
decomposedMatrix.rotation = (b > 0) ? Math.acos(a / r) : -Math.acos(a / r);
|
|
decomposedMatrix.scaleX = r;
|
|
decomposedMatrix.scaleY = determ / r;
|
|
}
|
|
else if (c || d)
|
|
{
|
|
var s = Math.sqrt(c * c + d * d);
|
|
|
|
decomposedMatrix.rotation = Math.PI * 0.5 - (d > 0 ? Math.acos(-c / s) : -Math.acos(c / s));
|
|
decomposedMatrix.scaleX = determ / s;
|
|
decomposedMatrix.scaleY = s;
|
|
}
|
|
else
|
|
{
|
|
decomposedMatrix.rotation = 0;
|
|
decomposedMatrix.scaleX = 0;
|
|
decomposedMatrix.scaleY = 0;
|
|
}
|
|
|
|
return decomposedMatrix;
|
|
},
|
|
|
|
/**
|
|
* Apply the identity, translate, rotate and scale operations on the Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#applyITRS
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The horizontal translation.
|
|
* @param {number} y - The vertical translation.
|
|
* @param {number} rotation - The angle of rotation in radians.
|
|
* @param {number} scaleX - The horizontal scale.
|
|
* @param {number} scaleY - The vertical scale.
|
|
*
|
|
* @return {this} This TransformMatrix.
|
|
*/
|
|
applyITRS: function (x, y, rotation, scaleX, scaleY)
|
|
{
|
|
var matrix = this.matrix;
|
|
|
|
var radianSin = Math.sin(rotation);
|
|
var radianCos = Math.cos(rotation);
|
|
|
|
// Translate
|
|
matrix[4] = x;
|
|
matrix[5] = y;
|
|
|
|
// Rotate and Scale
|
|
matrix[0] = radianCos * scaleX;
|
|
matrix[1] = radianSin * scaleX;
|
|
matrix[2] = -radianSin * scaleY;
|
|
matrix[3] = radianCos * scaleY;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Takes the `x` and `y` values and returns a new position in the `output` vector that is the inverse of
|
|
* the current matrix with its transformation applied.
|
|
*
|
|
* Can be used to translate points from world to local space.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#applyInverse
|
|
* @since 3.12.0
|
|
*
|
|
* @param {number} x - The x position to translate.
|
|
* @param {number} y - The y position to translate.
|
|
* @param {Phaser.Math.Vector2} [output] - A Vector2, or point-like object, to store the results in.
|
|
*
|
|
* @return {Phaser.Math.Vector2} The coordinates, inverse-transformed through this matrix.
|
|
*/
|
|
applyInverse: function (x, y, output)
|
|
{
|
|
if (output === undefined) { output = new Vector2(); }
|
|
|
|
var matrix = this.matrix;
|
|
|
|
var a = matrix[0];
|
|
var b = matrix[1];
|
|
var c = matrix[2];
|
|
var d = matrix[3];
|
|
var tx = matrix[4];
|
|
var ty = matrix[5];
|
|
|
|
var id = 1 / ((a * d) + (c * -b));
|
|
|
|
output.x = (d * id * x) + (-c * id * y) + (((ty * c) - (tx * d)) * id);
|
|
output.y = (a * id * y) + (-b * id * x) + (((-ty * a) + (tx * b)) * id);
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Performs the 8 calculations required to create the vertices of
|
|
* a quad based on this matrix and the given x/y/xw/yh values.
|
|
*
|
|
* The result is stored in `TransformMatrix.quad`, which is returned
|
|
* from this method.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#setQuad
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} x - The x value.
|
|
* @param {number} y - The y value.
|
|
* @param {number} xw - The xw value.
|
|
* @param {number} yh - The yh value.
|
|
* @param {boolean} roundPixels - Pass the results via Math.round?
|
|
* @param {Float32Array} [quad] - Optional Float32Array to store the results in. Otherwises uses the local quad array.
|
|
*
|
|
* @return {Float32Array} The quad Float32Array.
|
|
*/
|
|
setQuad: function (x, y, xw, yh, roundPixels, quad)
|
|
{
|
|
if (quad === undefined) { quad = this.quad; }
|
|
|
|
var matrix = this.matrix;
|
|
|
|
var a = matrix[0];
|
|
var b = matrix[1];
|
|
var c = matrix[2];
|
|
var d = matrix[3];
|
|
var e = matrix[4];
|
|
var f = matrix[5];
|
|
|
|
quad[0] = x * a + y * c + e;
|
|
quad[1] = x * b + y * d + f;
|
|
|
|
quad[2] = x * a + yh * c + e;
|
|
quad[3] = x * b + yh * d + f;
|
|
|
|
quad[4] = xw * a + yh * c + e;
|
|
quad[5] = xw * b + yh * d + f;
|
|
|
|
quad[6] = xw * a + y * c + e;
|
|
quad[7] = xw * b + y * d + f;
|
|
|
|
if (roundPixels)
|
|
{
|
|
quad.forEach(function (value, index)
|
|
{
|
|
quad[index] = Math.round(value);
|
|
});
|
|
}
|
|
|
|
return quad;
|
|
},
|
|
|
|
/**
|
|
* Returns the X component of this matrix multiplied by the given values.
|
|
* This is the same as `x * a + y * c + e`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#getX
|
|
* @since 3.12.0
|
|
*
|
|
* @param {number} x - The x value.
|
|
* @param {number} y - The y value.
|
|
*
|
|
* @return {number} The calculated x value.
|
|
*/
|
|
getX: function (x, y)
|
|
{
|
|
return x * this.a + y * this.c + this.e;
|
|
},
|
|
|
|
/**
|
|
* Returns the Y component of this matrix multiplied by the given values.
|
|
* This is the same as `x * b + y * d + f`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#getY
|
|
* @since 3.12.0
|
|
*
|
|
* @param {number} x - The x value.
|
|
* @param {number} y - The y value.
|
|
*
|
|
* @return {number} The calculated y value.
|
|
*/
|
|
getY: function (x, y)
|
|
{
|
|
return x * this.b + y * this.d + this.f;
|
|
},
|
|
|
|
/**
|
|
* Returns the X component of this matrix multiplied by the given values.
|
|
*
|
|
* This is the same as `x * a + y * c + e`, optionally passing via `Math.round`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#getXRound
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number} x - The x value.
|
|
* @param {number} y - The y value.
|
|
* @param {boolean} [round=false] - Math.round the resulting value?
|
|
*
|
|
* @return {number} The calculated x value.
|
|
*/
|
|
getXRound: function (x, y, round)
|
|
{
|
|
var v = this.getX(x, y);
|
|
|
|
if (round)
|
|
{
|
|
v = Math.round(v);
|
|
}
|
|
|
|
return v;
|
|
},
|
|
|
|
/**
|
|
* Returns the Y component of this matrix multiplied by the given values.
|
|
*
|
|
* This is the same as `x * b + y * d + f`, optionally passing via `Math.round`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#getYRound
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number} x - The x value.
|
|
* @param {number} y - The y value.
|
|
* @param {boolean} [round=false] - Math.round the resulting value?
|
|
*
|
|
* @return {number} The calculated y value.
|
|
*/
|
|
getYRound: function (x, y, round)
|
|
{
|
|
var v = this.getY(x, y);
|
|
|
|
if (round)
|
|
{
|
|
v = Math.round(v);
|
|
}
|
|
|
|
return v;
|
|
},
|
|
|
|
/**
|
|
* Returns a string that can be used in a CSS Transform call as a `matrix` property.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#getCSSMatrix
|
|
* @since 3.12.0
|
|
*
|
|
* @return {string} A string containing the CSS Transform matrix values.
|
|
*/
|
|
getCSSMatrix: function ()
|
|
{
|
|
var m = this.matrix;
|
|
|
|
return 'matrix(' + m[0] + ',' + m[1] + ',' + m[2] + ',' + m[3] + ',' + m[4] + ',' + m[5] + ')';
|
|
},
|
|
|
|
/**
|
|
* Destroys this Transform Matrix.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TransformMatrix#destroy
|
|
* @since 3.4.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.matrix = null;
|
|
this.quad = null;
|
|
this.decomposedMatrix = null;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = TransformMatrix;
|
|
|
|
|
|
/***/ }),
|
|
/* 27 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Checks if an array can be used as a matrix.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.CheckMatrix
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix]
|
|
*
|
|
* @param {T[][]} [matrix] - The array to check.
|
|
*
|
|
* @return {boolean} `true` if the given `matrix` array is a valid matrix.
|
|
*/
|
|
var CheckMatrix = function (matrix)
|
|
{
|
|
if (!Array.isArray(matrix) || !Array.isArray(matrix[0]))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// How long is the first row?
|
|
var size = matrix[0].length;
|
|
|
|
// Validate the rest of the rows are the same length
|
|
for (var i = 1; i < matrix.length; i++)
|
|
{
|
|
if (matrix[i].length !== size)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
module.exports = CheckMatrix;
|
|
|
|
|
|
/***/ }),
|
|
/* 28 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/* WEBPACK VAR INJECTION */(function(process) {/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Determines the operating system of the device running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.os` from within any Scene.
|
|
*
|
|
* @typedef {object} Phaser.Device.OS
|
|
* @since 3.0.0
|
|
*
|
|
* @property {boolean} android - Is running on android?
|
|
* @property {boolean} chromeOS - Is running on chromeOS?
|
|
* @property {boolean} cordova - Is the game running under Apache Cordova?
|
|
* @property {boolean} crosswalk - Is the game running under the Intel Crosswalk XDK?
|
|
* @property {boolean} desktop - Is running on a desktop?
|
|
* @property {boolean} ejecta - Is the game running under Ejecta?
|
|
* @property {boolean} electron - Is the game running under GitHub Electron?
|
|
* @property {boolean} iOS - Is running on iOS?
|
|
* @property {boolean} iPad - Is running on iPad?
|
|
* @property {boolean} iPhone - Is running on iPhone?
|
|
* @property {boolean} kindle - Is running on an Amazon Kindle?
|
|
* @property {boolean} linux - Is running on linux?
|
|
* @property {boolean} macOS - Is running on macOS?
|
|
* @property {boolean} node - Is the game running under Node.js?
|
|
* @property {boolean} nodeWebkit - Is the game running under Node-Webkit?
|
|
* @property {boolean} webApp - Set to true if running as a WebApp, i.e. within a WebView
|
|
* @property {boolean} windows - Is running on windows?
|
|
* @property {boolean} windowsPhone - Is running on a Windows Phone?
|
|
* @property {number} iOSVersion - If running in iOS this will contain the major version number.
|
|
* @property {number} pixelRatio - PixelRatio of the host device?
|
|
*/
|
|
var OS = {
|
|
|
|
android: false,
|
|
chromeOS: false,
|
|
cordova: false,
|
|
crosswalk: false,
|
|
desktop: false,
|
|
ejecta: false,
|
|
electron: false,
|
|
iOS: false,
|
|
iOSVersion: 0,
|
|
iPad: false,
|
|
iPhone: false,
|
|
kindle: false,
|
|
linux: false,
|
|
macOS: false,
|
|
node: false,
|
|
nodeWebkit: false,
|
|
pixelRatio: 1,
|
|
webApp: false,
|
|
windows: false,
|
|
windowsPhone: false
|
|
|
|
};
|
|
|
|
function init ()
|
|
{
|
|
if (typeof importScripts === 'function')
|
|
{
|
|
return OS;
|
|
}
|
|
|
|
var ua = navigator.userAgent;
|
|
|
|
if ((/Windows/).test(ua))
|
|
{
|
|
OS.windows = true;
|
|
}
|
|
else if ((/Mac OS/).test(ua) && !((/like Mac OS/).test(ua)))
|
|
{
|
|
// Because iOS 13 identifies as Mac OS:
|
|
if (navigator.maxTouchPoints && navigator.maxTouchPoints > 2)
|
|
{
|
|
OS.iOS = true;
|
|
OS.iPad = true;
|
|
|
|
(navigator.appVersion).match(/Version\/(\d+)/);
|
|
|
|
OS.iOSVersion = parseInt(RegExp.$1, 10);
|
|
}
|
|
else
|
|
{
|
|
OS.macOS = true;
|
|
}
|
|
}
|
|
else if ((/Android/).test(ua))
|
|
{
|
|
OS.android = true;
|
|
}
|
|
else if ((/Linux/).test(ua))
|
|
{
|
|
OS.linux = true;
|
|
}
|
|
else if ((/iP[ao]d|iPhone/i).test(ua))
|
|
{
|
|
OS.iOS = true;
|
|
|
|
(navigator.appVersion).match(/OS (\d+)/);
|
|
|
|
OS.iOSVersion = parseInt(RegExp.$1, 10);
|
|
|
|
OS.iPhone = ua.toLowerCase().indexOf('iphone') !== -1;
|
|
OS.iPad = ua.toLowerCase().indexOf('ipad') !== -1;
|
|
}
|
|
else if ((/Kindle/).test(ua) || (/\bKF[A-Z][A-Z]+/).test(ua) || (/Silk.*Mobile Safari/).test(ua))
|
|
{
|
|
OS.kindle = true;
|
|
|
|
// This will NOT detect early generations of Kindle Fire, I think there is no reliable way...
|
|
// E.g. "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_3; en-us; Silk/1.1.0-80) AppleWebKit/533.16 (KHTML, like Gecko) Version/5.0 Safari/533.16 Silk-Accelerated=true"
|
|
}
|
|
else if ((/CrOS/).test(ua))
|
|
{
|
|
OS.chromeOS = true;
|
|
}
|
|
|
|
if ((/Windows Phone/i).test(ua) || (/IEMobile/i).test(ua))
|
|
{
|
|
OS.android = false;
|
|
OS.iOS = false;
|
|
OS.macOS = false;
|
|
OS.windows = true;
|
|
OS.windowsPhone = true;
|
|
}
|
|
|
|
var silk = (/Silk/).test(ua);
|
|
|
|
if (OS.windows || OS.macOS || (OS.linux && !silk) || OS.chromeOS)
|
|
{
|
|
OS.desktop = true;
|
|
}
|
|
|
|
// Windows Phone / Table reset
|
|
if (OS.windowsPhone || (((/Windows NT/i).test(ua)) && ((/Touch/i).test(ua))))
|
|
{
|
|
OS.desktop = false;
|
|
}
|
|
|
|
// WebApp mode in iOS
|
|
if (navigator.standalone)
|
|
{
|
|
OS.webApp = true;
|
|
}
|
|
|
|
if (typeof importScripts !== 'function')
|
|
{
|
|
if (window.cordova !== undefined)
|
|
{
|
|
OS.cordova = true;
|
|
}
|
|
|
|
if (window.ejecta !== undefined)
|
|
{
|
|
OS.ejecta = true;
|
|
}
|
|
}
|
|
|
|
if (typeof process !== 'undefined' && process.versions && process.versions.node)
|
|
{
|
|
OS.node = true;
|
|
}
|
|
|
|
if (OS.node && typeof process.versions === 'object')
|
|
{
|
|
OS.nodeWebkit = !!process.versions['node-webkit'];
|
|
|
|
OS.electron = !!process.versions.electron;
|
|
}
|
|
|
|
if ((/Crosswalk/).test(ua))
|
|
{
|
|
OS.crosswalk = true;
|
|
}
|
|
|
|
OS.pixelRatio = window['devicePixelRatio'] || 1;
|
|
|
|
return OS;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(302)))
|
|
|
|
/***/ }),
|
|
/* 29 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var Contains = __webpack_require__(320);
|
|
var GetPoint = __webpack_require__(66);
|
|
var GetPoints = __webpack_require__(321);
|
|
var GEOM_CONST = __webpack_require__(30);
|
|
var Line = __webpack_require__(322);
|
|
var Random = __webpack_require__(327);
|
|
|
|
/**
|
|
* @classdesc
|
|
* Encapsulates a 2D rectangle defined by its corner point in the top-left and its extends in x (width) and y (height)
|
|
*
|
|
* @class Rectangle
|
|
* @memberof Phaser.Geom
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=0] - The X coordinate of the top left corner of the Rectangle.
|
|
* @param {number} [y=0] - The Y coordinate of the top left corner of the Rectangle.
|
|
* @param {number} [width=0] - The width of the Rectangle.
|
|
* @param {number} [height=0] - The height of the Rectangle.
|
|
*/
|
|
var Rectangle = new Class({
|
|
|
|
initialize:
|
|
|
|
function Rectangle (x, y, width, height)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = 0; }
|
|
if (width === undefined) { width = 0; }
|
|
if (height === undefined) { height = 0; }
|
|
|
|
/**
|
|
* The geometry constant type of this object: `GEOM_CONST.RECTANGLE`.
|
|
* Used for fast type comparisons.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#type
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.19.0
|
|
*/
|
|
this.type = GEOM_CONST.RECTANGLE;
|
|
|
|
/**
|
|
* The X coordinate of the top left corner of the Rectangle.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.x = x;
|
|
|
|
/**
|
|
* The Y coordinate of the top left corner of the Rectangle.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.y = y;
|
|
|
|
/**
|
|
* The width of the Rectangle, i.e. the distance between its left side (defined by `x`) and its right side.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#width
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.width = width;
|
|
|
|
/**
|
|
* The height of the Rectangle, i.e. the distance between its top side (defined by `y`) and its bottom side.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#height
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.height = height;
|
|
},
|
|
|
|
/**
|
|
* Checks if the given point is inside the Rectangle's bounds.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#contains
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The X coordinate of the point to check.
|
|
* @param {number} y - The Y coordinate of the point to check.
|
|
*
|
|
* @return {boolean} `true` if the point is within the Rectangle's bounds, otherwise `false`.
|
|
*/
|
|
contains: function (x, y)
|
|
{
|
|
return Contains(this, x, y);
|
|
},
|
|
|
|
/**
|
|
* Calculates the coordinates of a point at a certain `position` on the Rectangle's perimeter.
|
|
*
|
|
* The `position` is a fraction between 0 and 1 which defines how far into the perimeter the point is.
|
|
*
|
|
* A value of 0 or 1 returns the point at the top left corner of the rectangle, while a value of 0.5 returns the point at the bottom right corner of the rectangle. Values between 0 and 0.5 are on the top or the right side and values between 0.5 and 1 are on the bottom or the left side.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#getPoint
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [output,$return]
|
|
*
|
|
* @param {number} position - The normalized distance into the Rectangle's perimeter to return.
|
|
* @param {(Phaser.Geom.Point|object)} [output] - An object to update with the `x` and `y` coordinates of the point.
|
|
*
|
|
* @return {(Phaser.Geom.Point|object)} The updated `output` object, or a new Point if no `output` object was given.
|
|
*/
|
|
getPoint: function (position, output)
|
|
{
|
|
return GetPoint(this, position, output);
|
|
},
|
|
|
|
/**
|
|
* Returns an array of points from the perimeter of the Rectangle, each spaced out based on the quantity or step required.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#getPoints
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point[]} O - [output,$return]
|
|
*
|
|
* @param {number} quantity - The number of points to return. Set to `false` or 0 to return an arbitrary number of points (`perimeter / stepRate`) evenly spaced around the Rectangle based on the `stepRate`.
|
|
* @param {number} [stepRate] - If `quantity` is 0, determines the normalized distance between each returned point.
|
|
* @param {(array|Phaser.Geom.Point[])} [output] - An array to which to append the points.
|
|
*
|
|
* @return {(array|Phaser.Geom.Point[])} The modified `output` array, or a new array if none was provided.
|
|
*/
|
|
getPoints: function (quantity, stepRate, output)
|
|
{
|
|
return GetPoints(this, quantity, stepRate, output);
|
|
},
|
|
|
|
/**
|
|
* Returns a random point within the Rectangle's bounds.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#getRandomPoint
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [point,$return]
|
|
*
|
|
* @param {Phaser.Geom.Point} [point] - The object in which to store the `x` and `y` coordinates of the point.
|
|
*
|
|
* @return {Phaser.Geom.Point} The updated `point`, or a new Point if none was provided.
|
|
*/
|
|
getRandomPoint: function (point)
|
|
{
|
|
return Random(this, point);
|
|
},
|
|
|
|
/**
|
|
* Sets the position, width, and height of the Rectangle.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#setTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The X coordinate of the top left corner of the Rectangle.
|
|
* @param {number} y - The Y coordinate of the top left corner of the Rectangle.
|
|
* @param {number} width - The width of the Rectangle.
|
|
* @param {number} height - The height of the Rectangle.
|
|
*
|
|
* @return {this} This Rectangle object.
|
|
*/
|
|
setTo: function (x, y, width, height)
|
|
{
|
|
this.x = x;
|
|
this.y = y;
|
|
this.width = width;
|
|
this.height = height;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Resets the position, width, and height of the Rectangle to 0.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#setEmpty
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Rectangle object.
|
|
*/
|
|
setEmpty: function ()
|
|
{
|
|
return this.setTo(0, 0, 0, 0);
|
|
},
|
|
|
|
/**
|
|
* Sets the position of the Rectangle.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#setPosition
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The X coordinate of the top left corner of the Rectangle.
|
|
* @param {number} [y=x] - The Y coordinate of the top left corner of the Rectangle.
|
|
*
|
|
* @return {this} This Rectangle object.
|
|
*/
|
|
setPosition: function (x, y)
|
|
{
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the width and height of the Rectangle.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#setSize
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} width - The width to set the Rectangle to.
|
|
* @param {number} [height=width] - The height to set the Rectangle to.
|
|
*
|
|
* @return {this} This Rectangle object.
|
|
*/
|
|
setSize: function (width, height)
|
|
{
|
|
if (height === undefined) { height = width; }
|
|
|
|
this.width = width;
|
|
this.height = height;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Determines if the Rectangle is empty. A Rectangle is empty if its width or height is less than or equal to 0.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#isEmpty
|
|
* @since 3.0.0
|
|
*
|
|
* @return {boolean} `true` if the Rectangle is empty. A Rectangle object is empty if its width or height is less than or equal to 0.
|
|
*/
|
|
isEmpty: function ()
|
|
{
|
|
return (this.width <= 0 || this.height <= 0);
|
|
},
|
|
|
|
/**
|
|
* Returns a Line object that corresponds to the top of this Rectangle.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#getLineA
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Line} O - [line,$return]
|
|
*
|
|
* @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created.
|
|
*
|
|
* @return {Phaser.Geom.Line} A Line object that corresponds to the top of this Rectangle.
|
|
*/
|
|
getLineA: function (line)
|
|
{
|
|
if (line === undefined) { line = new Line(); }
|
|
|
|
line.setTo(this.x, this.y, this.right, this.y);
|
|
|
|
return line;
|
|
},
|
|
|
|
/**
|
|
* Returns a Line object that corresponds to the right of this Rectangle.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#getLineB
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Line} O - [line,$return]
|
|
*
|
|
* @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created.
|
|
*
|
|
* @return {Phaser.Geom.Line} A Line object that corresponds to the right of this Rectangle.
|
|
*/
|
|
getLineB: function (line)
|
|
{
|
|
if (line === undefined) { line = new Line(); }
|
|
|
|
line.setTo(this.right, this.y, this.right, this.bottom);
|
|
|
|
return line;
|
|
},
|
|
|
|
/**
|
|
* Returns a Line object that corresponds to the bottom of this Rectangle.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#getLineC
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Line} O - [line,$return]
|
|
*
|
|
* @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created.
|
|
*
|
|
* @return {Phaser.Geom.Line} A Line object that corresponds to the bottom of this Rectangle.
|
|
*/
|
|
getLineC: function (line)
|
|
{
|
|
if (line === undefined) { line = new Line(); }
|
|
|
|
line.setTo(this.right, this.bottom, this.x, this.bottom);
|
|
|
|
return line;
|
|
},
|
|
|
|
/**
|
|
* Returns a Line object that corresponds to the left of this Rectangle.
|
|
*
|
|
* @method Phaser.Geom.Rectangle#getLineD
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Line} O - [line,$return]
|
|
*
|
|
* @param {Phaser.Geom.Line} [line] - A Line object to set the results in. If `undefined` a new Line will be created.
|
|
*
|
|
* @return {Phaser.Geom.Line} A Line object that corresponds to the left of this Rectangle.
|
|
*/
|
|
getLineD: function (line)
|
|
{
|
|
if (line === undefined) { line = new Line(); }
|
|
|
|
line.setTo(this.x, this.bottom, this.x, this.y);
|
|
|
|
return line;
|
|
},
|
|
|
|
/**
|
|
* The x coordinate of the left of the Rectangle.
|
|
* Changing the left property of a Rectangle object has no effect on the y and height properties. However it does affect the width property, whereas changing the x value does not affect the width property.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#left
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
left: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.x;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (value >= this.right)
|
|
{
|
|
this.width = 0;
|
|
}
|
|
else
|
|
{
|
|
this.width = this.right - value;
|
|
}
|
|
|
|
this.x = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The sum of the x and width properties.
|
|
* Changing the right property of a Rectangle object has no effect on the x, y and height properties, however it does affect the width property.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#right
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
right: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.x + this.width;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (value <= this.x)
|
|
{
|
|
this.width = 0;
|
|
}
|
|
else
|
|
{
|
|
this.width = value - this.x;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The y coordinate of the top of the Rectangle. Changing the top property of a Rectangle object has no effect on the x and width properties.
|
|
* However it does affect the height property, whereas changing the y value does not affect the height property.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#top
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
top: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.y;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (value >= this.bottom)
|
|
{
|
|
this.height = 0;
|
|
}
|
|
else
|
|
{
|
|
this.height = (this.bottom - value);
|
|
}
|
|
|
|
this.y = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The sum of the y and height properties.
|
|
* Changing the bottom property of a Rectangle object has no effect on the x, y and width properties, but does change the height property.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#bottom
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
bottom: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.y + this.height;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (value <= this.y)
|
|
{
|
|
this.height = 0;
|
|
}
|
|
else
|
|
{
|
|
this.height = value - this.y;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The x coordinate of the center of the Rectangle.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#centerX
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
centerX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.x + (this.width / 2);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.x = value - (this.width / 2);
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The y coordinate of the center of the Rectangle.
|
|
*
|
|
* @name Phaser.Geom.Rectangle#centerY
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
centerY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.y + (this.height / 2);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.y = value - (this.height / 2);
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = Rectangle;
|
|
|
|
|
|
/***/ }),
|
|
/* 30 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var GEOM_CONST = {
|
|
|
|
/**
|
|
* A Circle Geometry object type.
|
|
*
|
|
* @name Phaser.Geom.CIRCLE
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
CIRCLE: 0,
|
|
|
|
/**
|
|
* An Ellipse Geometry object type.
|
|
*
|
|
* @name Phaser.Geom.ELLIPSE
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
ELLIPSE: 1,
|
|
|
|
/**
|
|
* A Line Geometry object type.
|
|
*
|
|
* @name Phaser.Geom.LINE
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
LINE: 2,
|
|
|
|
/**
|
|
* A Point Geometry object type.
|
|
*
|
|
* @name Phaser.Geom.POINT
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
POINT: 3,
|
|
|
|
/**
|
|
* A Polygon Geometry object type.
|
|
*
|
|
* @name Phaser.Geom.POLYGON
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
POLYGON: 4,
|
|
|
|
/**
|
|
* A Rectangle Geometry object type.
|
|
*
|
|
* @name Phaser.Geom.RECTANGLE
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
RECTANGLE: 5,
|
|
|
|
/**
|
|
* A Triangle Geometry object type.
|
|
*
|
|
* @name Phaser.Geom.TRIANGLE
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
TRIANGLE: 6
|
|
|
|
};
|
|
|
|
module.exports = GEOM_CONST;
|
|
|
|
|
|
/***/ }),
|
|
/* 31 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Find the angle of a segment from (x1, y1) -> (x2, y2).
|
|
*
|
|
* @function Phaser.Math.Angle.Between
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x1 - The x coordinate of the first point.
|
|
* @param {number} y1 - The y coordinate of the first point.
|
|
* @param {number} x2 - The x coordinate of the second point.
|
|
* @param {number} y2 - The y coordinate of the second point.
|
|
*
|
|
* @return {number} The angle in radians.
|
|
*/
|
|
var Between = function (x1, y1, x2, y2)
|
|
{
|
|
return Math.atan2(y2 - y1, x2 - x1);
|
|
};
|
|
|
|
module.exports = Between;
|
|
|
|
|
|
/***/ }),
|
|
/* 32 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Normalize an angle to the [0, 2pi] range.
|
|
*
|
|
* @function Phaser.Math.Angle.Normalize
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} angle - The angle to normalize, in radians.
|
|
*
|
|
* @return {number} The normalized angle, in radians.
|
|
*/
|
|
var Normalize = function (angle)
|
|
{
|
|
angle = angle % (2 * Math.PI);
|
|
|
|
if (angle >= 0)
|
|
{
|
|
return angle;
|
|
}
|
|
else
|
|
{
|
|
return angle + 2 * Math.PI;
|
|
}
|
|
};
|
|
|
|
module.exports = Normalize;
|
|
|
|
|
|
/***/ }),
|
|
/* 33 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var MathWrap = __webpack_require__(6);
|
|
|
|
/**
|
|
* Wrap an angle.
|
|
*
|
|
* Wraps the angle to a value in the range of -PI to PI.
|
|
*
|
|
* @function Phaser.Math.Angle.Wrap
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} angle - The angle to wrap, in radians.
|
|
*
|
|
* @return {number} The wrapped angle, in radians.
|
|
*/
|
|
var Wrap = function (angle)
|
|
{
|
|
return MathWrap(angle, -Math.PI, Math.PI);
|
|
};
|
|
|
|
module.exports = Wrap;
|
|
|
|
|
|
/***/ }),
|
|
/* 34 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Wrap = __webpack_require__(6);
|
|
|
|
/**
|
|
* Wrap an angle in degrees.
|
|
*
|
|
* Wraps the angle to a value in the range of -180 to 180.
|
|
*
|
|
* @function Phaser.Math.Angle.WrapDegrees
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} angle - The angle to wrap, in degrees.
|
|
*
|
|
* @return {number} The wrapped angle, in degrees.
|
|
*/
|
|
var WrapDegrees = function (angle)
|
|
{
|
|
return Wrap(angle, -180, 180);
|
|
};
|
|
|
|
module.exports = WrapDegrees;
|
|
|
|
|
|
/***/ }),
|
|
/* 35 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Check whether the given values are fuzzily equal.
|
|
*
|
|
* Two numbers are fuzzily equal if their difference is less than `epsilon`.
|
|
*
|
|
* @function Phaser.Math.Fuzzy.Equal
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} a - The first value.
|
|
* @param {number} b - The second value.
|
|
* @param {number} [epsilon=0.0001] - The epsilon.
|
|
*
|
|
* @return {boolean} `true` if the values are fuzzily equal, otherwise `false`.
|
|
*/
|
|
var Equal = function (a, b, epsilon)
|
|
{
|
|
if (epsilon === undefined) { epsilon = 0.0001; }
|
|
|
|
return Math.abs(a - b) < epsilon;
|
|
};
|
|
|
|
module.exports = Equal;
|
|
|
|
|
|
/***/ }),
|
|
/* 36 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Factorial = __webpack_require__(37);
|
|
|
|
/**
|
|
* Calculates the Bernstein basis from the three factorial coefficients.
|
|
*
|
|
* @function Phaser.Math.Bernstein
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} n - The first value.
|
|
* @param {number} i - The second value.
|
|
*
|
|
* @return {number} The Bernstein basis of Factorial(n) / Factorial(i) / Factorial(n - i)
|
|
*/
|
|
var Bernstein = function (n, i)
|
|
{
|
|
return Factorial(n) / Factorial(i) / Factorial(n - i);
|
|
};
|
|
|
|
module.exports = Bernstein;
|
|
|
|
|
|
/***/ }),
|
|
/* 37 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculates the factorial of a given number for integer values greater than 0.
|
|
*
|
|
* @function Phaser.Math.Factorial
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - A positive integer to calculate the factorial of.
|
|
*
|
|
* @return {number} The factorial of the given number.
|
|
*/
|
|
var Factorial = function (value)
|
|
{
|
|
if (value === 0)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
var res = value;
|
|
|
|
while (--value)
|
|
{
|
|
res *= value;
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
module.exports = Factorial;
|
|
|
|
|
|
/***/ }),
|
|
/* 38 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculates a Catmull-Rom value from the given points, based on an alpha of 0.5.
|
|
*
|
|
* @function Phaser.Math.CatmullRom
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} t - The amount to interpolate by.
|
|
* @param {number} p0 - The first control point.
|
|
* @param {number} p1 - The second control point.
|
|
* @param {number} p2 - The third control point.
|
|
* @param {number} p3 - The fourth control point.
|
|
*
|
|
* @return {number} The Catmull-Rom value.
|
|
*/
|
|
var CatmullRom = function (t, p0, p1, p2, p3)
|
|
{
|
|
var v0 = (p2 - p0) * 0.5;
|
|
var v1 = (p3 - p1) * 0.5;
|
|
var t2 = t * t;
|
|
var t3 = t * t2;
|
|
|
|
return (2 * p1 - 2 * p2 + v0 + v1) * t3 + (-3 * p1 + 3 * p2 - 2 * v0 - v1) * t2 + v0 * t + p1;
|
|
};
|
|
|
|
module.exports = CatmullRom;
|
|
|
|
|
|
/***/ }),
|
|
/* 39 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculates a linear (interpolation) value over t.
|
|
*
|
|
* @function Phaser.Math.Linear
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} p0 - The first point.
|
|
* @param {number} p1 - The second point.
|
|
* @param {number} t - The percentage between p0 and p1 to return, represented as a number between 0 and 1.
|
|
*
|
|
* @return {number} The step t% of the way between p0 and p1.
|
|
*/
|
|
var Linear = function (p0, p1, t)
|
|
{
|
|
return (p1 - p0) * t + p0;
|
|
};
|
|
|
|
module.exports = Linear;
|
|
|
|
|
|
/***/ }),
|
|
/* 40 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate a smooth interpolation percentage of `x` between `min` and `max`.
|
|
*
|
|
* The function receives the number `x` as an argument and returns 0 if `x` is less than or equal to the left edge,
|
|
* 1 if `x` is greater than or equal to the right edge, and smoothly interpolates, using a Hermite polynomial,
|
|
* between 0 and 1 otherwise.
|
|
*
|
|
* @function Phaser.Math.SmoothStep
|
|
* @since 3.0.0
|
|
* @see {@link https://en.wikipedia.org/wiki/Smoothstep}
|
|
*
|
|
* @param {number} x - The input value.
|
|
* @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'.
|
|
* @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'.
|
|
*
|
|
* @return {number} The percentage of interpolation, between 0 and 1.
|
|
*/
|
|
var SmoothStep = function (x, min, max)
|
|
{
|
|
if (x <= min)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
if (x >= max)
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
x = (x - min) / (max - min);
|
|
|
|
return x * x * (3 - 2 * x);
|
|
};
|
|
|
|
module.exports = SmoothStep;
|
|
|
|
|
|
/***/ }),
|
|
/* 41 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate a smoother interpolation percentage of `x` between `min` and `max`.
|
|
*
|
|
* The function receives the number `x` as an argument and returns 0 if `x` is less than or equal to the left edge,
|
|
* 1 if `x` is greater than or equal to the right edge, and smoothly interpolates, using a Hermite polynomial,
|
|
* between 0 and 1 otherwise.
|
|
*
|
|
* Produces an even smoother interpolation than {@link Phaser.Math.SmoothStep}.
|
|
*
|
|
* @function Phaser.Math.SmootherStep
|
|
* @since 3.0.0
|
|
* @see {@link https://en.wikipedia.org/wiki/Smoothstep#Variations}
|
|
*
|
|
* @param {number} x - The input value.
|
|
* @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'.
|
|
* @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'.
|
|
*
|
|
* @return {number} The percentage of interpolation, between 0 and 1.
|
|
*/
|
|
var SmootherStep = function (x, min, max)
|
|
{
|
|
x = Math.max(0, Math.min(1, (x - min) / (max - min)));
|
|
|
|
return x * x * x * (x * (x * 6 - 15) + 10);
|
|
};
|
|
|
|
module.exports = SmootherStep;
|
|
|
|
|
|
/***/ }),
|
|
/* 42 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Rotate a `point` around `x` and `y` to the given `angle`, at the same distance.
|
|
*
|
|
* In polar notation, this maps a point from (r, t) to (r, angle), vs. the origin (x, y).
|
|
*
|
|
* @function Phaser.Math.RotateAround
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Types.Math.Vector2Like} T - [point,$return]
|
|
*
|
|
* @param {(Phaser.Geom.Point|object)} point - The point to be rotated.
|
|
* @param {number} x - The horizontal coordinate to rotate around.
|
|
* @param {number} y - The vertical coordinate to rotate around.
|
|
* @param {number} angle - The angle of rotation in radians.
|
|
*
|
|
* @return {Phaser.Types.Math.Vector2Like} The given point.
|
|
*/
|
|
var RotateAround = function (point, x, y, angle)
|
|
{
|
|
var c = Math.cos(angle);
|
|
var s = Math.sin(angle);
|
|
|
|
var tx = point.x - x;
|
|
var ty = point.y - y;
|
|
|
|
point.x = tx * c - ty * s + x;
|
|
point.y = tx * s + ty * c + y;
|
|
|
|
return point;
|
|
};
|
|
|
|
module.exports = RotateAround;
|
|
|
|
|
|
/***/ }),
|
|
/* 43 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Round a given number so it is further away from zero. That is, positive numbers are rounded up, and negative numbers are rounded down.
|
|
*
|
|
* @function Phaser.Math.RoundAwayFromZero
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The number to round.
|
|
*
|
|
* @return {number} The rounded number, rounded away from zero.
|
|
*/
|
|
var RoundAwayFromZero = function (value)
|
|
{
|
|
// "Opposite" of truncate.
|
|
return (value > 0) ? Math.ceil(value) : Math.floor(value);
|
|
};
|
|
|
|
module.exports = RoundAwayFromZero;
|
|
|
|
|
|
/***/ }),
|
|
/* 44 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
/**
|
|
* Takes the `x` and `y` coordinates and transforms them into the same space as
|
|
* defined by the position, rotation and scale values.
|
|
*
|
|
* @function Phaser.Math.TransformXY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The x coordinate to be transformed.
|
|
* @param {number} y - The y coordinate to be transformed.
|
|
* @param {number} positionX - Horizontal position of the transform point.
|
|
* @param {number} positionY - Vertical position of the transform point.
|
|
* @param {number} rotation - Rotation of the transform point, in radians.
|
|
* @param {number} scaleX - Horizontal scale of the transform point.
|
|
* @param {number} scaleY - Vertical scale of the transform point.
|
|
* @param {(Phaser.Math.Vector2|Phaser.Geom.Point|object)} [output] - The output vector, point or object for the translated coordinates.
|
|
*
|
|
* @return {(Phaser.Math.Vector2|Phaser.Geom.Point|object)} The translated point.
|
|
*/
|
|
var TransformXY = function (x, y, positionX, positionY, rotation, scaleX, scaleY, output)
|
|
{
|
|
if (output === undefined) { output = new Vector2(); }
|
|
|
|
var radianSin = Math.sin(rotation);
|
|
var radianCos = Math.cos(rotation);
|
|
|
|
// Rotate and Scale
|
|
var a = radianCos * scaleX;
|
|
var b = radianSin * scaleX;
|
|
var c = -radianSin * scaleY;
|
|
var d = radianCos * scaleY;
|
|
|
|
// Invert
|
|
var id = 1 / ((a * d) + (c * -b));
|
|
|
|
output.x = (d * id * x) + (-c * id * y) + (((positionY * c) - (positionX * d)) * id);
|
|
output.y = (a * id * y) + (-b * id * x) + (((-positionY * a) + (positionX * b)) * id);
|
|
|
|
return output;
|
|
};
|
|
|
|
module.exports = TransformXY;
|
|
|
|
|
|
/***/ }),
|
|
/* 45 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji
|
|
// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl
|
|
|
|
var Class = __webpack_require__(0);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A three-dimensional matrix.
|
|
*
|
|
* Defaults to the identity matrix when instantiated.
|
|
*
|
|
* @class Matrix3
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} [m] - Optional Matrix3 to copy values from.
|
|
*/
|
|
var Matrix3 = new Class({
|
|
|
|
initialize:
|
|
|
|
function Matrix3 (m)
|
|
{
|
|
/**
|
|
* The matrix values.
|
|
*
|
|
* @name Phaser.Math.Matrix3#val
|
|
* @type {Float32Array}
|
|
* @since 3.0.0
|
|
*/
|
|
this.val = new Float32Array(9);
|
|
|
|
if (m)
|
|
{
|
|
// Assume Matrix3 with val:
|
|
this.copy(m);
|
|
}
|
|
else
|
|
{
|
|
// Default to identity
|
|
this.identity();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Make a clone of this Matrix3.
|
|
*
|
|
* @method Phaser.Math.Matrix3#clone
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Matrix3} A clone of this Matrix3.
|
|
*/
|
|
clone: function ()
|
|
{
|
|
return new Matrix3(this);
|
|
},
|
|
|
|
/**
|
|
* This method is an alias for `Matrix3.copy`.
|
|
*
|
|
* @method Phaser.Math.Matrix3#set
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} src - The Matrix to set the values of this Matrix's from.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
set: function (src)
|
|
{
|
|
return this.copy(src);
|
|
},
|
|
|
|
/**
|
|
* Copy the values of a given Matrix into this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#copy
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} src - The Matrix to copy the values from.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
copy: function (src)
|
|
{
|
|
var out = this.val;
|
|
var a = src.val;
|
|
|
|
out[0] = a[0];
|
|
out[1] = a[1];
|
|
out[2] = a[2];
|
|
out[3] = a[3];
|
|
out[4] = a[4];
|
|
out[5] = a[5];
|
|
out[6] = a[6];
|
|
out[7] = a[7];
|
|
out[8] = a[8];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Copy the values of a given Matrix4 into this Matrix3.
|
|
*
|
|
* @method Phaser.Math.Matrix3#fromMat4
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} m - The Matrix4 to copy the values from.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
fromMat4: function (m)
|
|
{
|
|
var a = m.val;
|
|
var out = this.val;
|
|
|
|
out[0] = a[0];
|
|
out[1] = a[1];
|
|
out[2] = a[2];
|
|
out[3] = a[4];
|
|
out[4] = a[5];
|
|
out[5] = a[6];
|
|
out[6] = a[8];
|
|
out[7] = a[9];
|
|
out[8] = a[10];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix from the given array.
|
|
*
|
|
* @method Phaser.Math.Matrix3#fromArray
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} a - The array to copy the values from.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
fromArray: function (a)
|
|
{
|
|
var out = this.val;
|
|
|
|
out[0] = a[0];
|
|
out[1] = a[1];
|
|
out[2] = a[2];
|
|
out[3] = a[3];
|
|
out[4] = a[4];
|
|
out[5] = a[5];
|
|
out[6] = a[6];
|
|
out[7] = a[7];
|
|
out[8] = a[8];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Reset this Matrix to an identity (default) matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#identity
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
identity: function ()
|
|
{
|
|
var out = this.val;
|
|
|
|
out[0] = 1;
|
|
out[1] = 0;
|
|
out[2] = 0;
|
|
out[3] = 0;
|
|
out[4] = 1;
|
|
out[5] = 0;
|
|
out[6] = 0;
|
|
out[7] = 0;
|
|
out[8] = 1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transpose this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#transpose
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
transpose: function ()
|
|
{
|
|
var a = this.val;
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a12 = a[5];
|
|
|
|
a[1] = a[3];
|
|
a[2] = a[6];
|
|
a[3] = a01;
|
|
a[5] = a[7];
|
|
a[6] = a02;
|
|
a[7] = a12;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Invert this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#invert
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
invert: function ()
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a10 = a[3];
|
|
var a11 = a[4];
|
|
var a12 = a[5];
|
|
var a20 = a[6];
|
|
var a21 = a[7];
|
|
var a22 = a[8];
|
|
|
|
var b01 = a22 * a11 - a12 * a21;
|
|
var b11 = -a22 * a10 + a12 * a20;
|
|
var b21 = a21 * a10 - a11 * a20;
|
|
|
|
// Calculate the determinant
|
|
var det = a00 * b01 + a01 * b11 + a02 * b21;
|
|
|
|
if (!det)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
det = 1 / det;
|
|
|
|
a[0] = b01 * det;
|
|
a[1] = (-a22 * a01 + a02 * a21) * det;
|
|
a[2] = (a12 * a01 - a02 * a11) * det;
|
|
a[3] = b11 * det;
|
|
a[4] = (a22 * a00 - a02 * a20) * det;
|
|
a[5] = (-a12 * a00 + a02 * a10) * det;
|
|
a[6] = b21 * det;
|
|
a[7] = (-a21 * a00 + a01 * a20) * det;
|
|
a[8] = (a11 * a00 - a01 * a10) * det;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the adjoint, or adjugate, of this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#adjoint
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
adjoint: function ()
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a10 = a[3];
|
|
var a11 = a[4];
|
|
var a12 = a[5];
|
|
var a20 = a[6];
|
|
var a21 = a[7];
|
|
var a22 = a[8];
|
|
|
|
a[0] = (a11 * a22 - a12 * a21);
|
|
a[1] = (a02 * a21 - a01 * a22);
|
|
a[2] = (a01 * a12 - a02 * a11);
|
|
a[3] = (a12 * a20 - a10 * a22);
|
|
a[4] = (a00 * a22 - a02 * a20);
|
|
a[5] = (a02 * a10 - a00 * a12);
|
|
a[6] = (a10 * a21 - a11 * a20);
|
|
a[7] = (a01 * a20 - a00 * a21);
|
|
a[8] = (a00 * a11 - a01 * a10);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the determinant of this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#determinant
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The determinant of this Matrix.
|
|
*/
|
|
determinant: function ()
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a10 = a[3];
|
|
var a11 = a[4];
|
|
var a12 = a[5];
|
|
var a20 = a[6];
|
|
var a21 = a[7];
|
|
var a22 = a[8];
|
|
|
|
return a00 * (a22 * a11 - a12 * a21) + a01 * (-a22 * a10 + a12 * a20) + a02 * (a21 * a10 - a11 * a20);
|
|
},
|
|
|
|
/**
|
|
* Multiply this Matrix by the given Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#multiply
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} src - The Matrix to multiply this Matrix by.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
multiply: function (src)
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a10 = a[3];
|
|
var a11 = a[4];
|
|
var a12 = a[5];
|
|
var a20 = a[6];
|
|
var a21 = a[7];
|
|
var a22 = a[8];
|
|
|
|
var b = src.val;
|
|
|
|
var b00 = b[0];
|
|
var b01 = b[1];
|
|
var b02 = b[2];
|
|
var b10 = b[3];
|
|
var b11 = b[4];
|
|
var b12 = b[5];
|
|
var b20 = b[6];
|
|
var b21 = b[7];
|
|
var b22 = b[8];
|
|
|
|
a[0] = b00 * a00 + b01 * a10 + b02 * a20;
|
|
a[1] = b00 * a01 + b01 * a11 + b02 * a21;
|
|
a[2] = b00 * a02 + b01 * a12 + b02 * a22;
|
|
|
|
a[3] = b10 * a00 + b11 * a10 + b12 * a20;
|
|
a[4] = b10 * a01 + b11 * a11 + b12 * a21;
|
|
a[5] = b10 * a02 + b11 * a12 + b12 * a22;
|
|
|
|
a[6] = b20 * a00 + b21 * a10 + b22 * a20;
|
|
a[7] = b20 * a01 + b21 * a11 + b22 * a21;
|
|
a[8] = b20 * a02 + b21 * a12 + b22 * a22;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Translate this Matrix using the given Vector.
|
|
*
|
|
* @method Phaser.Math.Matrix3#translate
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to translate this Matrix with.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
translate: function (v)
|
|
{
|
|
var a = this.val;
|
|
var x = v.x;
|
|
var y = v.y;
|
|
|
|
a[6] = x * a[0] + y * a[3] + a[6];
|
|
a[7] = x * a[1] + y * a[4] + a[7];
|
|
a[8] = x * a[2] + y * a[5] + a[8];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Apply a rotation transformation to this Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#rotate
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The angle in radians to rotate by.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
rotate: function (rad)
|
|
{
|
|
var a = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a10 = a[3];
|
|
var a11 = a[4];
|
|
var a12 = a[5];
|
|
|
|
var s = Math.sin(rad);
|
|
var c = Math.cos(rad);
|
|
|
|
a[0] = c * a00 + s * a10;
|
|
a[1] = c * a01 + s * a11;
|
|
a[2] = c * a02 + s * a12;
|
|
|
|
a[3] = c * a10 - s * a00;
|
|
a[4] = c * a11 - s * a01;
|
|
a[5] = c * a12 - s * a02;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Apply a scale transformation to this Matrix.
|
|
*
|
|
* Uses the `x` and `y` components of the given Vector to scale the Matrix.
|
|
*
|
|
* @method Phaser.Math.Matrix3#scale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to scale this Matrix with.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
scale: function (v)
|
|
{
|
|
var a = this.val;
|
|
var x = v.x;
|
|
var y = v.y;
|
|
|
|
a[0] = x * a[0];
|
|
a[1] = x * a[1];
|
|
a[2] = x * a[2];
|
|
|
|
a[3] = y * a[3];
|
|
a[4] = y * a[4];
|
|
a[5] = y * a[5];
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix from the given Quaternion.
|
|
*
|
|
* @method Phaser.Math.Matrix3#fromQuat
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Quaternion} q - The Quaternion to set the values of this Matrix from.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
fromQuat: function (q)
|
|
{
|
|
var x = q.x;
|
|
var y = q.y;
|
|
var z = q.z;
|
|
var w = q.w;
|
|
|
|
var x2 = x + x;
|
|
var y2 = y + y;
|
|
var z2 = z + z;
|
|
|
|
var xx = x * x2;
|
|
var xy = x * y2;
|
|
var xz = x * z2;
|
|
|
|
var yy = y * y2;
|
|
var yz = y * z2;
|
|
var zz = z * z2;
|
|
|
|
var wx = w * x2;
|
|
var wy = w * y2;
|
|
var wz = w * z2;
|
|
|
|
var out = this.val;
|
|
|
|
out[0] = 1 - (yy + zz);
|
|
out[3] = xy + wz;
|
|
out[6] = xz - wy;
|
|
|
|
out[1] = xy - wz;
|
|
out[4] = 1 - (xx + zz);
|
|
out[7] = yz + wx;
|
|
|
|
out[2] = xz + wy;
|
|
out[5] = yz - wx;
|
|
out[8] = 1 - (xx + yy);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set the values of this Matrix3 to be normalized from the given Matrix4.
|
|
*
|
|
* @method Phaser.Math.Matrix3#normalFromMat4
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} m - The Matrix4 to normalize the values from.
|
|
*
|
|
* @return {Phaser.Math.Matrix3} This Matrix3.
|
|
*/
|
|
normalFromMat4: function (m)
|
|
{
|
|
var a = m.val;
|
|
var out = this.val;
|
|
|
|
var a00 = a[0];
|
|
var a01 = a[1];
|
|
var a02 = a[2];
|
|
var a03 = a[3];
|
|
|
|
var a10 = a[4];
|
|
var a11 = a[5];
|
|
var a12 = a[6];
|
|
var a13 = a[7];
|
|
|
|
var a20 = a[8];
|
|
var a21 = a[9];
|
|
var a22 = a[10];
|
|
var a23 = a[11];
|
|
|
|
var a30 = a[12];
|
|
var a31 = a[13];
|
|
var a32 = a[14];
|
|
var a33 = a[15];
|
|
|
|
var b00 = a00 * a11 - a01 * a10;
|
|
var b01 = a00 * a12 - a02 * a10;
|
|
var b02 = a00 * a13 - a03 * a10;
|
|
var b03 = a01 * a12 - a02 * a11;
|
|
|
|
var b04 = a01 * a13 - a03 * a11;
|
|
var b05 = a02 * a13 - a03 * a12;
|
|
var b06 = a20 * a31 - a21 * a30;
|
|
var b07 = a20 * a32 - a22 * a30;
|
|
|
|
var b08 = a20 * a33 - a23 * a30;
|
|
var b09 = a21 * a32 - a22 * a31;
|
|
var b10 = a21 * a33 - a23 * a31;
|
|
var b11 = a22 * a33 - a23 * a32;
|
|
|
|
// Calculate the determinant
|
|
var det = b00 * b11 - b01 * b10 + b02 * b09 + b03 * b08 - b04 * b07 + b05 * b06;
|
|
|
|
if (!det)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
det = 1 / det;
|
|
|
|
out[0] = (a11 * b11 - a12 * b10 + a13 * b09) * det;
|
|
out[1] = (a12 * b08 - a10 * b11 - a13 * b07) * det;
|
|
out[2] = (a10 * b10 - a11 * b08 + a13 * b06) * det;
|
|
|
|
out[3] = (a02 * b10 - a01 * b11 - a03 * b09) * det;
|
|
out[4] = (a00 * b11 - a02 * b08 + a03 * b07) * det;
|
|
out[5] = (a01 * b08 - a00 * b10 - a03 * b06) * det;
|
|
|
|
out[6] = (a31 * b05 - a32 * b04 + a33 * b03) * det;
|
|
out[7] = (a32 * b02 - a30 * b05 - a33 * b01) * det;
|
|
out[8] = (a30 * b04 - a31 * b02 + a33 * b00) * det;
|
|
|
|
return this;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = Matrix3;
|
|
|
|
|
|
/***/ }),
|
|
/* 46 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji
|
|
// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl
|
|
|
|
var Class = __webpack_require__(0);
|
|
var Matrix3 = __webpack_require__(45);
|
|
var NOOP = __webpack_require__(2);
|
|
var Vector3 = __webpack_require__(16);
|
|
|
|
var EPSILON = 0.000001;
|
|
|
|
// Some shared 'private' arrays
|
|
var siNext = new Int8Array([ 1, 2, 0 ]);
|
|
var tmp = new Float32Array([ 0, 0, 0 ]);
|
|
|
|
var xUnitVec3 = new Vector3(1, 0, 0);
|
|
var yUnitVec3 = new Vector3(0, 1, 0);
|
|
|
|
var tmpvec = new Vector3();
|
|
var tmpMat3 = new Matrix3();
|
|
|
|
/**
|
|
* @classdesc
|
|
* A quaternion.
|
|
*
|
|
* @class Quaternion
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=0] - The x component.
|
|
* @param {number} [y=0] - The y component.
|
|
* @param {number} [z=0] - The z component.
|
|
* @param {number} [w=1] - The w component.
|
|
*/
|
|
var Quaternion = new Class({
|
|
|
|
initialize:
|
|
|
|
function Quaternion (x, y, z, w)
|
|
{
|
|
/**
|
|
* The x component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#_x
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.50.0
|
|
*/
|
|
|
|
/**
|
|
* The y component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#_y
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.50.0
|
|
*/
|
|
|
|
/**
|
|
* The z component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#_z
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.50.0
|
|
*/
|
|
|
|
/**
|
|
* The w component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#_w
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.50.0
|
|
*/
|
|
|
|
/**
|
|
* This callback is invoked, if set, each time a value in this quaternion is changed.
|
|
* The callback is passed one argument, a reference to this quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#onChangeCallback
|
|
* @type {function}
|
|
* @since 3.50.0
|
|
*/
|
|
this.onChangeCallback = NOOP;
|
|
|
|
this.set(x, y, z, w);
|
|
},
|
|
|
|
/**
|
|
* The x component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
x: {
|
|
get: function ()
|
|
{
|
|
return this._x;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._x = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The y component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
y: {
|
|
get: function ()
|
|
{
|
|
return this._y;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._y = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The z component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#z
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
z: {
|
|
get: function ()
|
|
{
|
|
return this._z;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._z = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The w component of this Quaternion.
|
|
*
|
|
* @name Phaser.Math.Quaternion#w
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
w: {
|
|
get: function ()
|
|
{
|
|
return this._w;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._w = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Copy the components of a given Quaternion or Vector into this Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#copy
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} src - The Quaternion or Vector to copy the components from.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
copy: function (src)
|
|
{
|
|
return this.set(src);
|
|
},
|
|
|
|
/**
|
|
* Set the components of this Quaternion and optionally call the `onChangeCallback`.
|
|
*
|
|
* @method Phaser.Math.Quaternion#set
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(number|object)} [x=0] - The x component, or an object containing x, y, z, and w components.
|
|
* @param {number} [y=0] - The y component.
|
|
* @param {number} [z=0] - The z component.
|
|
* @param {number} [w=0] - The w component.
|
|
* @param {boolean} [update=true] - Call the `onChangeCallback`?
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
set: function (x, y, z, w, update)
|
|
{
|
|
if (update === undefined) { update = true; }
|
|
|
|
if (typeof x === 'object')
|
|
{
|
|
this._x = x.x || 0;
|
|
this._y = x.y || 0;
|
|
this._z = x.z || 0;
|
|
this._w = x.w || 0;
|
|
}
|
|
else
|
|
{
|
|
this._x = x || 0;
|
|
this._y = y || 0;
|
|
this._z = z || 0;
|
|
this._w = w || 0;
|
|
}
|
|
|
|
if (update)
|
|
{
|
|
this.onChangeCallback(this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Add a given Quaternion or Vector to this Quaternion. Addition is component-wise.
|
|
*
|
|
* @method Phaser.Math.Quaternion#add
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to add to this Quaternion.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
add: function (v)
|
|
{
|
|
this._x += v.x;
|
|
this._y += v.y;
|
|
this._z += v.z;
|
|
this._w += v.w;
|
|
|
|
this.onChangeCallback(this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Subtract a given Quaternion or Vector from this Quaternion. Subtraction is component-wise.
|
|
*
|
|
* @method Phaser.Math.Quaternion#subtract
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to subtract from this Quaternion.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
subtract: function (v)
|
|
{
|
|
this._x -= v.x;
|
|
this._y -= v.y;
|
|
this._z -= v.z;
|
|
this._w -= v.w;
|
|
|
|
this.onChangeCallback(this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Scale this Quaternion by the given value.
|
|
*
|
|
* @method Phaser.Math.Quaternion#scale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} scale - The value to scale this Quaternion by.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
scale: function (scale)
|
|
{
|
|
this._x *= scale;
|
|
this._y *= scale;
|
|
this._z *= scale;
|
|
this._w *= scale;
|
|
|
|
this.onChangeCallback(this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the length of this Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#length
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Quaternion.
|
|
*/
|
|
length: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var w = this.w;
|
|
|
|
return Math.sqrt(x * x + y * y + z * z + w * w);
|
|
},
|
|
|
|
/**
|
|
* Calculate the length of this Quaternion squared.
|
|
*
|
|
* @method Phaser.Math.Quaternion#lengthSq
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Quaternion, squared.
|
|
*/
|
|
lengthSq: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var w = this.w;
|
|
|
|
return x * x + y * y + z * z + w * w;
|
|
},
|
|
|
|
/**
|
|
* Normalize this Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#normalize
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
normalize: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var w = this.w;
|
|
var len = x * x + y * y + z * z + w * w;
|
|
|
|
if (len > 0)
|
|
{
|
|
len = 1 / Math.sqrt(len);
|
|
|
|
this._x = x * len;
|
|
this._y = y * len;
|
|
this._z = z * len;
|
|
this._w = w * len;
|
|
}
|
|
|
|
this.onChangeCallback(this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the dot product of this Quaternion and the given Quaternion or Vector.
|
|
*
|
|
* @method Phaser.Math.Quaternion#dot
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to dot product with this Quaternion.
|
|
*
|
|
* @return {number} The dot product of this Quaternion and the given Quaternion or Vector.
|
|
*/
|
|
dot: function (v)
|
|
{
|
|
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
|
|
},
|
|
|
|
/**
|
|
* Linearly interpolate this Quaternion towards the given Quaternion or Vector.
|
|
*
|
|
* @method Phaser.Math.Quaternion#lerp
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} v - The Quaternion or Vector to interpolate towards.
|
|
* @param {number} [t=0] - The percentage of interpolation.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
lerp: function (v, t)
|
|
{
|
|
if (t === undefined) { t = 0; }
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var aw = this.w;
|
|
|
|
return this.set(
|
|
ax + t * (v.x - ax),
|
|
ay + t * (v.y - ay),
|
|
az + t * (v.z - az),
|
|
aw + t * (v.w - aw)
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Rotates this Quaternion based on the two given vectors.
|
|
*
|
|
* @method Phaser.Math.Quaternion#rotationTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} a - The transform rotation vector.
|
|
* @param {Phaser.Math.Vector3} b - The target rotation vector.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
rotationTo: function (a, b)
|
|
{
|
|
var dot = a.x * b.x + a.y * b.y + a.z * b.z;
|
|
|
|
if (dot < -0.999999)
|
|
{
|
|
if (tmpvec.copy(xUnitVec3).cross(a).length() < EPSILON)
|
|
{
|
|
tmpvec.copy(yUnitVec3).cross(a);
|
|
}
|
|
|
|
tmpvec.normalize();
|
|
|
|
return this.setAxisAngle(tmpvec, Math.PI);
|
|
|
|
}
|
|
else if (dot > 0.999999)
|
|
{
|
|
return this.set(0, 0, 0, 1);
|
|
}
|
|
else
|
|
{
|
|
tmpvec.copy(a).cross(b);
|
|
|
|
this._x = tmpvec.x;
|
|
this._y = tmpvec.y;
|
|
this._z = tmpvec.z;
|
|
this._w = 1 + dot;
|
|
|
|
return this.normalize();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Set the axes of this Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#setAxes
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} view - The view axis.
|
|
* @param {Phaser.Math.Vector3} right - The right axis.
|
|
* @param {Phaser.Math.Vector3} up - The upwards axis.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
setAxes: function (view, right, up)
|
|
{
|
|
var m = tmpMat3.val;
|
|
|
|
m[0] = right.x;
|
|
m[3] = right.y;
|
|
m[6] = right.z;
|
|
|
|
m[1] = up.x;
|
|
m[4] = up.y;
|
|
m[7] = up.z;
|
|
|
|
m[2] = -view.x;
|
|
m[5] = -view.y;
|
|
m[8] = -view.z;
|
|
|
|
return this.fromMat3(tmpMat3).normalize();
|
|
},
|
|
|
|
/**
|
|
* Reset this Matrix to an identity (default) Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#identity
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
identity: function ()
|
|
{
|
|
return this.set(0, 0, 0, 1);
|
|
},
|
|
|
|
/**
|
|
* Set the axis angle of this Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#setAxisAngle
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} axis - The axis.
|
|
* @param {number} rad - The angle in radians.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
setAxisAngle: function (axis, rad)
|
|
{
|
|
rad = rad * 0.5;
|
|
|
|
var s = Math.sin(rad);
|
|
|
|
return this.set(
|
|
s * axis.x,
|
|
s * axis.y,
|
|
s * axis.z,
|
|
Math.cos(rad)
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Multiply this Quaternion by the given Quaternion or Vector.
|
|
*
|
|
* @method Phaser.Math.Quaternion#multiply
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} b - The Quaternion or Vector to multiply this Quaternion by.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
multiply: function (b)
|
|
{
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var aw = this.w;
|
|
|
|
var bx = b.x;
|
|
var by = b.y;
|
|
var bz = b.z;
|
|
var bw = b.w;
|
|
|
|
return this.set(
|
|
ax * bw + aw * bx + ay * bz - az * by,
|
|
ay * bw + aw * by + az * bx - ax * bz,
|
|
az * bw + aw * bz + ax * by - ay * bx,
|
|
aw * bw - ax * bx - ay * by - az * bz
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Smoothly linearly interpolate this Quaternion towards the given Quaternion or Vector.
|
|
*
|
|
* @method Phaser.Math.Quaternion#slerp
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Quaternion|Phaser.Math.Vector4)} b - The Quaternion or Vector to interpolate towards.
|
|
* @param {number} t - The percentage of interpolation.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
slerp: function (b, t)
|
|
{
|
|
// benchmarks: http://jsperf.com/quaternion-slerp-implementations
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var aw = this.w;
|
|
|
|
var bx = b.x;
|
|
var by = b.y;
|
|
var bz = b.z;
|
|
var bw = b.w;
|
|
|
|
// calc cosine
|
|
var cosom = ax * bx + ay * by + az * bz + aw * bw;
|
|
|
|
// adjust signs (if necessary)
|
|
if (cosom < 0)
|
|
{
|
|
cosom = -cosom;
|
|
bx = - bx;
|
|
by = - by;
|
|
bz = - bz;
|
|
bw = - bw;
|
|
}
|
|
|
|
// "from" and "to" quaternions are very close
|
|
// ... so we can do a linear interpolation
|
|
var scale0 = 1 - t;
|
|
var scale1 = t;
|
|
|
|
// calculate coefficients
|
|
if ((1 - cosom) > EPSILON)
|
|
{
|
|
// standard case (slerp)
|
|
var omega = Math.acos(cosom);
|
|
var sinom = Math.sin(omega);
|
|
|
|
scale0 = Math.sin((1.0 - t) * omega) / sinom;
|
|
scale1 = Math.sin(t * omega) / sinom;
|
|
}
|
|
|
|
// calculate final values
|
|
return this.set(
|
|
scale0 * ax + scale1 * bx,
|
|
scale0 * ay + scale1 * by,
|
|
scale0 * az + scale1 * bz,
|
|
scale0 * aw + scale1 * bw
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Invert this Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#invert
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
invert: function ()
|
|
{
|
|
var a0 = this.x;
|
|
var a1 = this.y;
|
|
var a2 = this.z;
|
|
var a3 = this.w;
|
|
|
|
var dot = a0 * a0 + a1 * a1 + a2 * a2 + a3 * a3;
|
|
var invDot = (dot) ? 1 / dot : 0;
|
|
|
|
return this.set(
|
|
-a0 * invDot,
|
|
-a1 * invDot,
|
|
-a2 * invDot,
|
|
a3 * invDot
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Convert this Quaternion into its conjugate.
|
|
*
|
|
* Sets the x, y and z components.
|
|
*
|
|
* @method Phaser.Math.Quaternion#conjugate
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
conjugate: function ()
|
|
{
|
|
this._x = -this.x;
|
|
this._y = -this.y;
|
|
this._z = -this.z;
|
|
|
|
this.onChangeCallback(this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Rotate this Quaternion on the X axis.
|
|
*
|
|
* @method Phaser.Math.Quaternion#rotateX
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The rotation angle in radians.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
rotateX: function (rad)
|
|
{
|
|
rad *= 0.5;
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var aw = this.w;
|
|
|
|
var bx = Math.sin(rad);
|
|
var bw = Math.cos(rad);
|
|
|
|
return this.set(
|
|
ax * bw + aw * bx,
|
|
ay * bw + az * bx,
|
|
az * bw - ay * bx,
|
|
aw * bw - ax * bx
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Rotate this Quaternion on the Y axis.
|
|
*
|
|
* @method Phaser.Math.Quaternion#rotateY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The rotation angle in radians.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
rotateY: function (rad)
|
|
{
|
|
rad *= 0.5;
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var aw = this.w;
|
|
|
|
var by = Math.sin(rad);
|
|
var bw = Math.cos(rad);
|
|
|
|
return this.set(
|
|
ax * bw - az * by,
|
|
ay * bw + aw * by,
|
|
az * bw + ax * by,
|
|
aw * bw - ay * by
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Rotate this Quaternion on the Z axis.
|
|
*
|
|
* @method Phaser.Math.Quaternion#rotateZ
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} rad - The rotation angle in radians.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
rotateZ: function (rad)
|
|
{
|
|
rad *= 0.5;
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var aw = this.w;
|
|
|
|
var bz = Math.sin(rad);
|
|
var bw = Math.cos(rad);
|
|
|
|
return this.set(
|
|
ax * bw + ay * bz,
|
|
ay * bw - ax * bz,
|
|
az * bw + aw * bz,
|
|
aw * bw - az * bz
|
|
);
|
|
},
|
|
|
|
/**
|
|
* Create a unit (or rotation) Quaternion from its x, y, and z components.
|
|
*
|
|
* Sets the w component.
|
|
*
|
|
* @method Phaser.Math.Quaternion#calculateW
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
calculateW: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
|
|
this.w = -Math.sqrt(1.0 - x * x - y * y - z * z);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set this Quaternion from the given Euler, based on Euler order.
|
|
*
|
|
* @method Phaser.Math.Quaternion#setFromEuler
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Euler} euler - The Euler to convert from.
|
|
* @param {boolean} [update=true] - Run the `onChangeCallback`?
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
setFromEuler: function (euler, update)
|
|
{
|
|
var x = euler.x / 2;
|
|
var y = euler.y / 2;
|
|
var z = euler.z / 2;
|
|
|
|
var c1 = Math.cos(x);
|
|
var c2 = Math.cos(y);
|
|
var c3 = Math.cos(z);
|
|
|
|
var s1 = Math.sin(x);
|
|
var s2 = Math.sin(y);
|
|
var s3 = Math.sin(z);
|
|
|
|
switch (euler.order)
|
|
{
|
|
case 'XYZ':
|
|
{
|
|
this.set(
|
|
s1 * c2 * c3 + c1 * s2 * s3,
|
|
c1 * s2 * c3 - s1 * c2 * s3,
|
|
c1 * c2 * s3 + s1 * s2 * c3,
|
|
c1 * c2 * c3 - s1 * s2 * s3,
|
|
update
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case 'YXZ':
|
|
{
|
|
this.set(
|
|
s1 * c2 * c3 + c1 * s2 * s3,
|
|
c1 * s2 * c3 - s1 * c2 * s3,
|
|
c1 * c2 * s3 - s1 * s2 * c3,
|
|
c1 * c2 * c3 + s1 * s2 * s3,
|
|
update
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case 'ZXY':
|
|
{
|
|
this.set(
|
|
s1 * c2 * c3 - c1 * s2 * s3,
|
|
c1 * s2 * c3 + s1 * c2 * s3,
|
|
c1 * c2 * s3 + s1 * s2 * c3,
|
|
c1 * c2 * c3 - s1 * s2 * s3,
|
|
update
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case 'ZYX':
|
|
{
|
|
this.set(
|
|
s1 * c2 * c3 - c1 * s2 * s3,
|
|
c1 * s2 * c3 + s1 * c2 * s3,
|
|
c1 * c2 * s3 - s1 * s2 * c3,
|
|
c1 * c2 * c3 + s1 * s2 * s3,
|
|
update
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case 'YZX':
|
|
{
|
|
this.set(
|
|
s1 * c2 * c3 + c1 * s2 * s3,
|
|
c1 * s2 * c3 + s1 * c2 * s3,
|
|
c1 * c2 * s3 - s1 * s2 * c3,
|
|
c1 * c2 * c3 - s1 * s2 * s3,
|
|
update
|
|
);
|
|
|
|
break;
|
|
}
|
|
|
|
case 'XZY':
|
|
{
|
|
this.set(
|
|
s1 * c2 * c3 - c1 * s2 * s3,
|
|
c1 * s2 * c3 - s1 * c2 * s3,
|
|
c1 * c2 * s3 + s1 * s2 * c3,
|
|
c1 * c2 * c3 + s1 * s2 * s3,
|
|
update
|
|
);
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the rotation of this Quaternion from the given Matrix4.
|
|
*
|
|
* @method Phaser.Math.Quaternion#setFromRotationMatrix
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat4 - The Matrix4 to set the rotation from.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
setFromRotationMatrix: function (mat4)
|
|
{
|
|
var m = mat4.val;
|
|
|
|
var m11 = m[0];
|
|
var m12 = m[4];
|
|
var m13 = m[8];
|
|
var m21 = m[1];
|
|
var m22 = m[5];
|
|
var m23 = m[9];
|
|
var m31 = m[2];
|
|
var m32 = m[6];
|
|
var m33 = m[10];
|
|
|
|
var trace = m11 + m22 + m33;
|
|
var s;
|
|
|
|
if (trace > 0)
|
|
{
|
|
s = 0.5 / Math.sqrt(trace + 1.0);
|
|
|
|
this.set(
|
|
(m32 - m23) * s,
|
|
(m13 - m31) * s,
|
|
(m21 - m12) * s,
|
|
0.25 / s
|
|
);
|
|
}
|
|
else if (m11 > m22 && m11 > m33)
|
|
{
|
|
s = 2.0 * Math.sqrt(1.0 + m11 - m22 - m33);
|
|
|
|
this.set(
|
|
0.25 * s,
|
|
(m12 + m21) / s,
|
|
(m13 + m31) / s,
|
|
(m32 - m23) / s
|
|
);
|
|
}
|
|
else if (m22 > m33)
|
|
{
|
|
s = 2.0 * Math.sqrt(1.0 + m22 - m11 - m33);
|
|
|
|
this.set(
|
|
(m12 + m21) / s,
|
|
0.25 * s,
|
|
(m23 + m32) / s,
|
|
(m13 - m31) / s
|
|
);
|
|
}
|
|
else
|
|
{
|
|
s = 2.0 * Math.sqrt(1.0 + m33 - m11 - m22);
|
|
|
|
this.set(
|
|
(m13 + m31) / s,
|
|
(m23 + m32) / s,
|
|
0.25 * s,
|
|
(m21 - m12) / s
|
|
);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Convert the given Matrix into this Quaternion.
|
|
*
|
|
* @method Phaser.Math.Quaternion#fromMat3
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix3} mat - The Matrix to convert from.
|
|
*
|
|
* @return {Phaser.Math.Quaternion} This Quaternion.
|
|
*/
|
|
fromMat3: function (mat)
|
|
{
|
|
// benchmarks:
|
|
// http://jsperf.com/typed-array-access-speed
|
|
// http://jsperf.com/conversion-of-3x3-matrix-to-quaternion
|
|
|
|
// Algorithm in Ken Shoemake's article in 1987 SIGGRAPH course notes
|
|
// article "Quaternion Calculus and Fast Animation".
|
|
var m = mat.val;
|
|
var fTrace = m[0] + m[4] + m[8];
|
|
var fRoot;
|
|
|
|
if (fTrace > 0)
|
|
{
|
|
// |w| > 1/2, may as well choose w > 1/2
|
|
fRoot = Math.sqrt(fTrace + 1.0); // 2w
|
|
|
|
this.w = 0.5 * fRoot;
|
|
|
|
fRoot = 0.5 / fRoot; // 1/(4w)
|
|
|
|
this._x = (m[7] - m[5]) * fRoot;
|
|
this._y = (m[2] - m[6]) * fRoot;
|
|
this._z = (m[3] - m[1]) * fRoot;
|
|
}
|
|
else
|
|
{
|
|
// |w| <= 1/2
|
|
var i = 0;
|
|
|
|
if (m[4] > m[0])
|
|
{
|
|
i = 1;
|
|
}
|
|
|
|
if (m[8] > m[i * 3 + i])
|
|
{
|
|
i = 2;
|
|
}
|
|
|
|
var j = siNext[i];
|
|
var k = siNext[j];
|
|
|
|
// This isn't quite as clean without array access
|
|
fRoot = Math.sqrt(m[i * 3 + i] - m[j * 3 + j] - m[k * 3 + k] + 1);
|
|
tmp[i] = 0.5 * fRoot;
|
|
|
|
fRoot = 0.5 / fRoot;
|
|
|
|
tmp[j] = (m[j * 3 + i] + m[i * 3 + j]) * fRoot;
|
|
tmp[k] = (m[k * 3 + i] + m[i * 3 + k]) * fRoot;
|
|
|
|
this._x = tmp[0];
|
|
this._y = tmp[1];
|
|
this._z = tmp[2];
|
|
this._w = (m[k * 3 + j] - m[j * 3 + k]) * fRoot;
|
|
}
|
|
|
|
this.onChangeCallback(this);
|
|
|
|
return this;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = Quaternion;
|
|
|
|
|
|
/***/ }),
|
|
/* 47 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Loader.Events
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
ADD: __webpack_require__(213),
|
|
COMPLETE: __webpack_require__(214),
|
|
FILE_COMPLETE: __webpack_require__(215),
|
|
FILE_KEY_COMPLETE: __webpack_require__(216),
|
|
FILE_LOAD_ERROR: __webpack_require__(217),
|
|
FILE_LOAD: __webpack_require__(218),
|
|
FILE_PROGRESS: __webpack_require__(219),
|
|
POST_PROCESS: __webpack_require__(220),
|
|
PROGRESS: __webpack_require__(221),
|
|
START: __webpack_require__(222)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 48 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Given a File and a baseURL value this returns the URL the File will use to download from.
|
|
*
|
|
* @function Phaser.Loader.GetURL
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - The File object.
|
|
* @param {string} baseURL - A default base URL.
|
|
*
|
|
* @return {string} The URL the File will use.
|
|
*/
|
|
var GetURL = function (file, baseURL)
|
|
{
|
|
if (!file.url)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (file.url.match(/^(?:blob:|data:|capacitor:\/\/|http:\/\/|https:\/\/|\/\/)/))
|
|
{
|
|
return file.url;
|
|
}
|
|
else
|
|
{
|
|
return baseURL + file.url;
|
|
}
|
|
};
|
|
|
|
module.exports = GetURL;
|
|
|
|
|
|
/***/ }),
|
|
/* 49 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Extend = __webpack_require__(19);
|
|
var XHRSettings = __webpack_require__(50);
|
|
|
|
/**
|
|
* Takes two XHRSettings Objects and creates a new XHRSettings object from them.
|
|
*
|
|
* The new object is seeded by the values given in the global settings, but any setting in
|
|
* the local object overrides the global ones.
|
|
*
|
|
* @function Phaser.Loader.MergeXHRSettings
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} global - The global XHRSettings object.
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} local - The local XHRSettings object.
|
|
*
|
|
* @return {Phaser.Types.Loader.XHRSettingsObject} A newly formed XHRSettings object.
|
|
*/
|
|
var MergeXHRSettings = function (global, local)
|
|
{
|
|
var output = (global === undefined) ? XHRSettings() : Extend({}, global);
|
|
|
|
if (local)
|
|
{
|
|
for (var setting in local)
|
|
{
|
|
if (local[setting] !== undefined)
|
|
{
|
|
output[setting] = local[setting];
|
|
}
|
|
}
|
|
}
|
|
|
|
return output;
|
|
};
|
|
|
|
module.exports = MergeXHRSettings;
|
|
|
|
|
|
/***/ }),
|
|
/* 50 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Creates an XHRSettings Object with default values.
|
|
*
|
|
* @function Phaser.Loader.XHRSettings
|
|
* @since 3.0.0
|
|
*
|
|
* @param {XMLHttpRequestResponseType} [responseType=''] - The responseType, such as 'text'.
|
|
* @param {boolean} [async=true] - Should the XHR request use async or not?
|
|
* @param {string} [user=''] - Optional username for the XHR request.
|
|
* @param {string} [password=''] - Optional password for the XHR request.
|
|
* @param {number} [timeout=0] - Optional XHR timeout value.
|
|
* @param {boolean} [withCredentials=false] - Optional XHR withCredentials value.
|
|
*
|
|
* @return {Phaser.Types.Loader.XHRSettingsObject} The XHRSettings object as used by the Loader.
|
|
*/
|
|
var XHRSettings = function (responseType, async, user, password, timeout, withCredentials)
|
|
{
|
|
if (responseType === undefined) { responseType = ''; }
|
|
if (async === undefined) { async = true; }
|
|
if (user === undefined) { user = ''; }
|
|
if (password === undefined) { password = ''; }
|
|
if (timeout === undefined) { timeout = 0; }
|
|
if (withCredentials === undefined) { withCredentials = false; }
|
|
|
|
// Before sending a request, set the xhr.responseType to "text",
|
|
// "arraybuffer", "blob", or "document", depending on your data needs.
|
|
// Note, setting xhr.responseType = '' (or omitting) will default the response to "text".
|
|
|
|
return {
|
|
|
|
// Ignored by the Loader, only used by File.
|
|
responseType: responseType,
|
|
|
|
async: async,
|
|
|
|
// credentials
|
|
user: user,
|
|
password: password,
|
|
|
|
// timeout in ms (0 = no timeout)
|
|
timeout: timeout,
|
|
|
|
// setRequestHeader
|
|
headers: undefined,
|
|
header: undefined,
|
|
headerValue: undefined,
|
|
requestedWith: false,
|
|
|
|
// overrideMimeType
|
|
overrideMimeType: undefined,
|
|
|
|
// withCredentials
|
|
withCredentials: withCredentials
|
|
|
|
};
|
|
};
|
|
|
|
module.exports = XHRSettings;
|
|
|
|
|
|
/***/ }),
|
|
/* 51 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for calculating and setting the size of a non-Frame based Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.ComputedSize
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var ComputedSize = {
|
|
|
|
/**
|
|
* The native (un-scaled) width of this Game Object.
|
|
*
|
|
* Changing this value will not change the size that the Game Object is rendered in-game.
|
|
* For that you need to either set the scale of the Game Object (`setScale`) or use
|
|
* the `displayWidth` property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.ComputedSize#width
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
width: 0,
|
|
|
|
/**
|
|
* The native (un-scaled) height of this Game Object.
|
|
*
|
|
* Changing this value will not change the size that the Game Object is rendered in-game.
|
|
* For that you need to either set the scale of the Game Object (`setScale`) or use
|
|
* the `displayHeight` property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.ComputedSize#height
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
height: 0,
|
|
|
|
/**
|
|
* The displayed width of this Game Object.
|
|
*
|
|
* This value takes into account the scale factor.
|
|
*
|
|
* Setting this value will adjust the Game Object's scale property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.ComputedSize#displayWidth
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
displayWidth: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.scaleX * this.width;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.scaleX = value / this.width;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The displayed height of this Game Object.
|
|
*
|
|
* This value takes into account the scale factor.
|
|
*
|
|
* Setting this value will adjust the Game Object's scale property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.ComputedSize#displayHeight
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
displayHeight: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.scaleY * this.height;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.scaleY = value / this.height;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Sets the internal size of this Game Object, as used for frame or physics body creation.
|
|
*
|
|
* This will not change the size that the Game Object is rendered in-game.
|
|
* For that you need to either set the scale of the Game Object (`setScale`) or call the
|
|
* `setDisplaySize` method, which is the same thing as changing the scale but allows you
|
|
* to do so by giving pixel values.
|
|
*
|
|
* If you have enabled this Game Object for input, changing the size will _not_ change the
|
|
* size of the hit area. To do this you should adjust the `input.hitArea` object directly.
|
|
*
|
|
* @method Phaser.GameObjects.Components.ComputedSize#setSize
|
|
* @since 3.4.0
|
|
*
|
|
* @param {number} width - The width of this Game Object.
|
|
* @param {number} height - The height of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setSize: function (width, height)
|
|
{
|
|
this.width = width;
|
|
this.height = height;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the display size of this Game Object.
|
|
*
|
|
* Calling this will adjust the scale.
|
|
*
|
|
* @method Phaser.GameObjects.Components.ComputedSize#setDisplaySize
|
|
* @since 3.4.0
|
|
*
|
|
* @param {number} width - The width of this Game Object.
|
|
* @param {number} height - The height of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setDisplaySize: function (width, height)
|
|
{
|
|
this.displayWidth = width;
|
|
this.displayHeight = height;
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = ComputedSize;
|
|
|
|
|
|
/***/ }),
|
|
/* 52 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for setting the depth of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Depth
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Depth = {
|
|
|
|
/**
|
|
* Private internal value. Holds the depth of the Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Depth#_depth
|
|
* @type {number}
|
|
* @private
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
_depth: 0,
|
|
|
|
/**
|
|
* The depth of this Game Object within the Scene. Ensure this value is only ever set to a number data-type.
|
|
*
|
|
* The depth is also known as the 'z-index' in some environments, and allows you to change the rendering order
|
|
* of Game Objects, without actually moving their position in the display list.
|
|
*
|
|
* The default depth is zero. A Game Object with a higher depth
|
|
* value will always render in front of one with a lower value.
|
|
*
|
|
* Setting the depth will queue a depth sort event within the Scene.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Depth#depth
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
depth: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._depth;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (this.displayList)
|
|
{
|
|
this.displayList.queueDepthSort();
|
|
}
|
|
|
|
this._depth = value;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The depth of this Game Object within the Scene.
|
|
*
|
|
* The depth is also known as the 'z-index' in some environments, and allows you to change the rendering order
|
|
* of Game Objects, without actually moving their position in the display list.
|
|
*
|
|
* The default depth is zero. A Game Object with a higher depth
|
|
* value will always render in front of one with a lower value.
|
|
*
|
|
* Setting the depth will queue a depth sort event within the Scene.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Depth#setDepth
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The depth of this Game Object. Ensure this value is only ever a number data-type.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setDepth: function (value)
|
|
{
|
|
if (value === undefined) { value = 0; }
|
|
|
|
this.depth = value;
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Depth;
|
|
|
|
|
|
/***/ }),
|
|
/* 53 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for visually flipping a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Flip
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Flip = {
|
|
|
|
/**
|
|
* The horizontally flipped state of the Game Object.
|
|
*
|
|
* A Game Object that is flipped horizontally will render inversed on the horizontal axis.
|
|
* Flipping always takes place from the middle of the texture and does not impact the scale value.
|
|
* If this Game Object has a physics body, it will not change the body. This is a rendering toggle only.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Flip#flipX
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
flipX: false,
|
|
|
|
/**
|
|
* The vertically flipped state of the Game Object.
|
|
*
|
|
* A Game Object that is flipped vertically will render inversed on the vertical axis (i.e. upside down)
|
|
* Flipping always takes place from the middle of the texture and does not impact the scale value.
|
|
* If this Game Object has a physics body, it will not change the body. This is a rendering toggle only.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Flip#flipY
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
flipY: false,
|
|
|
|
/**
|
|
* Toggles the horizontal flipped state of this Game Object.
|
|
*
|
|
* A Game Object that is flipped horizontally will render inversed on the horizontal axis.
|
|
* Flipping always takes place from the middle of the texture and does not impact the scale value.
|
|
* If this Game Object has a physics body, it will not change the body. This is a rendering toggle only.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Flip#toggleFlipX
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
toggleFlipX: function ()
|
|
{
|
|
this.flipX = !this.flipX;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Toggles the vertical flipped state of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Flip#toggleFlipY
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
toggleFlipY: function ()
|
|
{
|
|
this.flipY = !this.flipY;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the horizontal flipped state of this Game Object.
|
|
*
|
|
* A Game Object that is flipped horizontally will render inversed on the horizontal axis.
|
|
* Flipping always takes place from the middle of the texture and does not impact the scale value.
|
|
* If this Game Object has a physics body, it will not change the body. This is a rendering toggle only.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Flip#setFlipX
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setFlipX: function (value)
|
|
{
|
|
this.flipX = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the vertical flipped state of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Flip#setFlipY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} value - The flipped state. `false` for no flip, or `true` to be flipped.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setFlipY: function (value)
|
|
{
|
|
this.flipY = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the horizontal and vertical flipped state of this Game Object.
|
|
*
|
|
* A Game Object that is flipped will render inversed on the flipped axis.
|
|
* Flipping always takes place from the middle of the texture and does not impact the scale value.
|
|
* If this Game Object has a physics body, it will not change the body. This is a rendering toggle only.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Flip#setFlip
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} x - The horizontal flipped state. `false` for no flip, or `true` to be flipped.
|
|
* @param {boolean} y - The horizontal flipped state. `false` for no flip, or `true` to be flipped.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setFlip: function (x, y)
|
|
{
|
|
this.flipX = x;
|
|
this.flipY = y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Resets the horizontal and vertical flipped state of this Game Object back to their default un-flipped state.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Flip#resetFlip
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
resetFlip: function ()
|
|
{
|
|
this.flipX = false;
|
|
this.flipY = false;
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Flip;
|
|
|
|
|
|
/***/ }),
|
|
/* 54 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the Scroll Factor of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.ScrollFactor
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var ScrollFactor = {
|
|
|
|
/**
|
|
* The horizontal scroll factor of this Game Object.
|
|
*
|
|
* The scroll factor controls the influence of the movement of a Camera upon this Game Object.
|
|
*
|
|
* When a camera scrolls it will change the location at which this Game Object is rendered on-screen.
|
|
* It does not change the Game Objects actual position values.
|
|
*
|
|
* A value of 1 means it will move exactly in sync with a camera.
|
|
* A value of 0 means it will not move at all, even if the camera moves.
|
|
* Other values control the degree to which the camera movement is mapped to this Game Object.
|
|
*
|
|
* Please be aware that scroll factor values other than 1 are not taken in to consideration when
|
|
* calculating physics collisions. Bodies always collide based on their world position, but changing
|
|
* the scroll factor is a visual adjustment to where the textures are rendered, which can offset
|
|
* them from physics bodies if not accounted for in your code.
|
|
*
|
|
* @name Phaser.GameObjects.Components.ScrollFactor#scrollFactorX
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
scrollFactorX: 1,
|
|
|
|
/**
|
|
* The vertical scroll factor of this Game Object.
|
|
*
|
|
* The scroll factor controls the influence of the movement of a Camera upon this Game Object.
|
|
*
|
|
* When a camera scrolls it will change the location at which this Game Object is rendered on-screen.
|
|
* It does not change the Game Objects actual position values.
|
|
*
|
|
* A value of 1 means it will move exactly in sync with a camera.
|
|
* A value of 0 means it will not move at all, even if the camera moves.
|
|
* Other values control the degree to which the camera movement is mapped to this Game Object.
|
|
*
|
|
* Please be aware that scroll factor values other than 1 are not taken in to consideration when
|
|
* calculating physics collisions. Bodies always collide based on their world position, but changing
|
|
* the scroll factor is a visual adjustment to where the textures are rendered, which can offset
|
|
* them from physics bodies if not accounted for in your code.
|
|
*
|
|
* @name Phaser.GameObjects.Components.ScrollFactor#scrollFactorY
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
scrollFactorY: 1,
|
|
|
|
/**
|
|
* Sets the scroll factor of this Game Object.
|
|
*
|
|
* The scroll factor controls the influence of the movement of a Camera upon this Game Object.
|
|
*
|
|
* When a camera scrolls it will change the location at which this Game Object is rendered on-screen.
|
|
* It does not change the Game Objects actual position values.
|
|
*
|
|
* A value of 1 means it will move exactly in sync with a camera.
|
|
* A value of 0 means it will not move at all, even if the camera moves.
|
|
* Other values control the degree to which the camera movement is mapped to this Game Object.
|
|
*
|
|
* Please be aware that scroll factor values other than 1 are not taken in to consideration when
|
|
* calculating physics collisions. Bodies always collide based on their world position, but changing
|
|
* the scroll factor is a visual adjustment to where the textures are rendered, which can offset
|
|
* them from physics bodies if not accounted for in your code.
|
|
*
|
|
* @method Phaser.GameObjects.Components.ScrollFactor#setScrollFactor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The horizontal scroll factor of this Game Object.
|
|
* @param {number} [y=x] - The vertical scroll factor of this Game Object. If not set it will use the `x` value.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setScrollFactor: function (x, y)
|
|
{
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.scrollFactorX = x;
|
|
this.scrollFactorY = y;
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = ScrollFactor;
|
|
|
|
|
|
/***/ }),
|
|
/* 55 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var MATH_CONST = __webpack_require__(4);
|
|
var TransformMatrix = __webpack_require__(26);
|
|
var TransformXY = __webpack_require__(44);
|
|
var WrapAngle = __webpack_require__(33);
|
|
var WrapAngleDegrees = __webpack_require__(34);
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
// global bitmask flag for GameObject.renderMask (used by Scale)
|
|
var _FLAG = 4; // 0100
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the position, scale and rotation of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Transform
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Transform = {
|
|
|
|
/**
|
|
* A property indicating that a Game Object has this component.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#hasTransformComponent
|
|
* @type {boolean}
|
|
* @readonly
|
|
* @default true
|
|
* @since 3.60.0
|
|
*/
|
|
hasTransformComponent: true,
|
|
|
|
/**
|
|
* Private internal value. Holds the horizontal scale value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#_scaleX
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_scaleX: 1,
|
|
|
|
/**
|
|
* Private internal value. Holds the vertical scale value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#_scaleY
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_scaleY: 1,
|
|
|
|
/**
|
|
* Private internal value. Holds the rotation value in radians.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#_rotation
|
|
* @type {number}
|
|
* @private
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
_rotation: 0,
|
|
|
|
/**
|
|
* The x position of this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
x: 0,
|
|
|
|
/**
|
|
* The y position of this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
y: 0,
|
|
|
|
/**
|
|
* The z position of this Game Object.
|
|
*
|
|
* Note: The z position does not control the rendering order of 2D Game Objects. Use
|
|
* {@link Phaser.GameObjects.Components.Depth#depth} instead.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#z
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
z: 0,
|
|
|
|
/**
|
|
* The w position of this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#w
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
w: 0,
|
|
|
|
/**
|
|
* This is a special setter that allows you to set both the horizontal and vertical scale of this Game Object
|
|
* to the same value, at the same time. When reading this value the result returned is `(scaleX + scaleY) / 2`.
|
|
*
|
|
* Use of this property implies you wish the horizontal and vertical scales to be equal to each other. If this
|
|
* isn't the case, use the `scaleX` or `scaleY` properties instead.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#scale
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.18.0
|
|
*/
|
|
scale: {
|
|
|
|
get: function ()
|
|
{
|
|
return (this._scaleX + this._scaleY) / 2;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._scaleX = value;
|
|
this._scaleY = value;
|
|
|
|
if (value === 0)
|
|
{
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The horizontal scale of this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#scaleX
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
scaleX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._scaleX;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._scaleX = value;
|
|
|
|
if (value === 0)
|
|
{
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The vertical scale of this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#scaleY
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
scaleY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._scaleY;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._scaleY = value;
|
|
|
|
if (value === 0)
|
|
{
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The angle of this Game Object as expressed in degrees.
|
|
*
|
|
* Phaser uses a right-hand clockwise rotation system, where 0 is right, 90 is down, 180/-180 is left
|
|
* and -90 is up.
|
|
*
|
|
* If you prefer to work in radians, see the `rotation` property instead.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#angle
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
angle: {
|
|
|
|
get: function ()
|
|
{
|
|
return WrapAngleDegrees(this._rotation * MATH_CONST.RAD_TO_DEG);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
// value is in degrees
|
|
this.rotation = WrapAngleDegrees(value) * MATH_CONST.DEG_TO_RAD;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The angle of this Game Object in radians.
|
|
*
|
|
* Phaser uses a right-hand clockwise rotation system, where 0 is right, PI/2 is down, +-PI is left
|
|
* and -PI/2 is up.
|
|
*
|
|
* If you prefer to work in degrees, see the `angle` property instead.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Transform#rotation
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
rotation: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._rotation;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
// value is in radians
|
|
this._rotation = WrapAngle(value);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sets the position of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setPosition
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=0] - The x position of this Game Object.
|
|
* @param {number} [y=x] - The y position of this Game Object. If not set it will use the `x` value.
|
|
* @param {number} [z=0] - The z position of this Game Object.
|
|
* @param {number} [w=0] - The w position of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setPosition: function (x, y, z, w)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = x; }
|
|
if (z === undefined) { z = 0; }
|
|
if (w === undefined) { w = 0; }
|
|
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
this.w = w;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Copies an object's coordinates to this Game Object's position.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#copyPosition
|
|
* @since 3.50.0
|
|
*
|
|
* @param {(Phaser.Types.Math.Vector2Like|Phaser.Types.Math.Vector3Like|Phaser.Types.Math.Vector4Like)} source - An object with numeric 'x', 'y', 'z', or 'w' properties. Undefined values are not copied.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
copyPosition: function (source)
|
|
{
|
|
if (source.x !== undefined) { this.x = source.x; }
|
|
if (source.y !== undefined) { this.y = source.y; }
|
|
if (source.z !== undefined) { this.z = source.z; }
|
|
if (source.w !== undefined) { this.w = source.w; }
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the position of this Game Object to be a random position within the confines of
|
|
* the given area.
|
|
*
|
|
* If no area is specified a random position between 0 x 0 and the game width x height is used instead.
|
|
*
|
|
* The position does not factor in the size of this Game Object, meaning that only the origin is
|
|
* guaranteed to be within the area.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setRandomPosition
|
|
* @since 3.8.0
|
|
*
|
|
* @param {number} [x=0] - The x position of the top-left of the random area.
|
|
* @param {number} [y=0] - The y position of the top-left of the random area.
|
|
* @param {number} [width] - The width of the random area.
|
|
* @param {number} [height] - The height of the random area.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setRandomPosition: function (x, y, width, height)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = 0; }
|
|
if (width === undefined) { width = this.scene.sys.scale.width; }
|
|
if (height === undefined) { height = this.scene.sys.scale.height; }
|
|
|
|
this.x = x + (Math.random() * width);
|
|
this.y = y + (Math.random() * height);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the rotation of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setRotation
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [radians=0] - The rotation of this Game Object, in radians.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setRotation: function (radians)
|
|
{
|
|
if (radians === undefined) { radians = 0; }
|
|
|
|
this.rotation = radians;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the angle of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setAngle
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [degrees=0] - The rotation of this Game Object, in degrees.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setAngle: function (degrees)
|
|
{
|
|
if (degrees === undefined) { degrees = 0; }
|
|
|
|
this.angle = degrees;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the scale of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setScale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x - The horizontal scale of this Game Object.
|
|
* @param {number} [y=x] - The vertical scale of this Game Object. If not set it will use the `x` value.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setScale: function (x, y)
|
|
{
|
|
if (x === undefined) { x = 1; }
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.scaleX = x;
|
|
this.scaleY = y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the x position of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setX
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [value=0] - The x position of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setX: function (value)
|
|
{
|
|
if (value === undefined) { value = 0; }
|
|
|
|
this.x = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the y position of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [value=0] - The y position of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setY: function (value)
|
|
{
|
|
if (value === undefined) { value = 0; }
|
|
|
|
this.y = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the z position of this Game Object.
|
|
*
|
|
* Note: The z position does not control the rendering order of 2D Game Objects. Use
|
|
* {@link Phaser.GameObjects.Components.Depth#setDepth} instead.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setZ
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [value=0] - The z position of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setZ: function (value)
|
|
{
|
|
if (value === undefined) { value = 0; }
|
|
|
|
this.z = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the w position of this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#setW
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [value=0] - The w position of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setW: function (value)
|
|
{
|
|
if (value === undefined) { value = 0; }
|
|
|
|
this.w = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Gets the local transform matrix for this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#getLocalTransformMatrix
|
|
* @since 3.4.0
|
|
*
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object.
|
|
*
|
|
* @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix.
|
|
*/
|
|
getLocalTransformMatrix: function (tempMatrix)
|
|
{
|
|
if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); }
|
|
|
|
return tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY);
|
|
},
|
|
|
|
/**
|
|
* Gets the world transform matrix for this Game Object, factoring in any parent Containers.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#getWorldTransformMatrix
|
|
* @since 3.4.0
|
|
*
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} [tempMatrix] - The matrix to populate with the values from this Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - A temporary matrix to hold parent values during the calculations.
|
|
*
|
|
* @return {Phaser.GameObjects.Components.TransformMatrix} The populated Transform Matrix.
|
|
*/
|
|
getWorldTransformMatrix: function (tempMatrix, parentMatrix)
|
|
{
|
|
if (tempMatrix === undefined) { tempMatrix = new TransformMatrix(); }
|
|
if (parentMatrix === undefined) { parentMatrix = new TransformMatrix(); }
|
|
|
|
var parent = this.parentContainer;
|
|
|
|
if (!parent)
|
|
{
|
|
return this.getLocalTransformMatrix(tempMatrix);
|
|
}
|
|
|
|
tempMatrix.applyITRS(this.x, this.y, this._rotation, this._scaleX, this._scaleY);
|
|
|
|
while (parent)
|
|
{
|
|
parentMatrix.applyITRS(parent.x, parent.y, parent._rotation, parent._scaleX, parent._scaleY);
|
|
|
|
parentMatrix.multiply(tempMatrix, tempMatrix);
|
|
|
|
parent = parent.parentContainer;
|
|
}
|
|
|
|
return tempMatrix;
|
|
},
|
|
|
|
/**
|
|
* Takes the given `x` and `y` coordinates and converts them into local space for this
|
|
* Game Object, taking into account parent and local transforms, and the Display Origin.
|
|
*
|
|
* The returned Vector2 contains the translated point in its properties.
|
|
*
|
|
* A Camera needs to be provided in order to handle modified scroll factors. If no
|
|
* camera is specified, it will use the `main` camera from the Scene to which this
|
|
* Game Object belongs.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#getLocalPoint
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number} x - The x position to translate.
|
|
* @param {number} y - The y position to translate.
|
|
* @param {Phaser.Math.Vector2} [point] - A Vector2, or point-like object, to store the results in.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} [camera] - The Camera which is being tested against. If not given will use the Scene default camera.
|
|
*
|
|
* @return {Phaser.Math.Vector2} The translated point.
|
|
*/
|
|
getLocalPoint: function (x, y, point, camera)
|
|
{
|
|
if (!point) { point = new Vector2(); }
|
|
if (!camera) { camera = this.scene.sys.cameras.main; }
|
|
|
|
var csx = camera.scrollX;
|
|
var csy = camera.scrollY;
|
|
|
|
var px = x + (csx * this.scrollFactorX) - csx;
|
|
var py = y + (csy * this.scrollFactorY) - csy;
|
|
|
|
if (this.parentContainer)
|
|
{
|
|
this.getWorldTransformMatrix().applyInverse(px, py, point);
|
|
}
|
|
else
|
|
{
|
|
TransformXY(px, py, this.x, this.y, this.rotation, this.scaleX, this.scaleY, point);
|
|
}
|
|
|
|
// Normalize origin
|
|
if (this._originComponent)
|
|
{
|
|
point.x += this._displayOriginX;
|
|
point.y += this._displayOriginY;
|
|
}
|
|
|
|
return point;
|
|
},
|
|
|
|
/**
|
|
* Gets the sum total rotation of all of this Game Objects parent Containers.
|
|
*
|
|
* The returned value is in radians and will be zero if this Game Object has no parent container.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Transform#getParentRotation
|
|
* @since 3.18.0
|
|
*
|
|
* @return {number} The sum total rotation, in radians, of all parent containers of this Game Object.
|
|
*/
|
|
getParentRotation: function ()
|
|
{
|
|
var rotation = 0;
|
|
|
|
var parent = this.parentContainer;
|
|
|
|
while (parent)
|
|
{
|
|
rotation += parent.rotation;
|
|
|
|
parent = parent.parentContainer;
|
|
}
|
|
|
|
return rotation;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Transform;
|
|
|
|
|
|
/***/ }),
|
|
/* 56 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// bitmask flag for GameObject.renderMask
|
|
var _FLAG = 1; // 0001
|
|
|
|
/**
|
|
* Provides methods used for setting the visibility of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Visible
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Visible = {
|
|
|
|
/**
|
|
* Private internal value. Holds the visible value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Visible#_visible
|
|
* @type {boolean}
|
|
* @private
|
|
* @default true
|
|
* @since 3.0.0
|
|
*/
|
|
_visible: true,
|
|
|
|
/**
|
|
* The visible state of the Game Object.
|
|
*
|
|
* An invisible Game Object will skip rendering, but will still process update logic.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Visible#visible
|
|
* @type {boolean}
|
|
* @since 3.0.0
|
|
*/
|
|
visible: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._visible;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (value)
|
|
{
|
|
this._visible = true;
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
else
|
|
{
|
|
this._visible = false;
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Sets the visibility of this Game Object.
|
|
*
|
|
* An invisible Game Object will skip rendering, but will still process update logic.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Visible#setVisible
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} value - The visible state of the Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setVisible: function (value)
|
|
{
|
|
this.visible = value;
|
|
|
|
return this;
|
|
}
|
|
};
|
|
|
|
module.exports = Visible;
|
|
|
|
|
|
/***/ }),
|
|
/* 57 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var ComponentsToJSON = __webpack_require__(58);
|
|
var DataManager = __webpack_require__(228);
|
|
var EventEmitter = __webpack_require__(235);
|
|
var Events = __webpack_require__(59);
|
|
var SceneEvents = __webpack_require__(23);
|
|
|
|
/**
|
|
* @classdesc
|
|
* The base class that all Game Objects extend.
|
|
* You don't create GameObjects directly and they cannot be added to the display list.
|
|
* Instead, use them as the base for your own custom classes.
|
|
*
|
|
* @class GameObject
|
|
* @memberof Phaser.GameObjects
|
|
* @extends Phaser.Events.EventEmitter
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs.
|
|
* @param {string} type - A textual representation of the type of Game Object, i.e. `sprite`.
|
|
*/
|
|
var GameObject = new Class({
|
|
|
|
Extends: EventEmitter,
|
|
|
|
initialize:
|
|
|
|
function GameObject (scene, type)
|
|
{
|
|
EventEmitter.call(this);
|
|
|
|
/**
|
|
* A reference to the Scene to which this Game Object belongs.
|
|
*
|
|
* Game Objects can only belong to one Scene.
|
|
*
|
|
* You should consider this property as being read-only. You cannot move a
|
|
* Game Object to another Scene by simply changing it.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#scene
|
|
* @type {Phaser.Scene}
|
|
* @since 3.0.0
|
|
*/
|
|
this.scene = scene;
|
|
|
|
/**
|
|
* Holds a reference to the Display List that contains this Game Object.
|
|
*
|
|
* This is set automatically when this Game Object is added to a Scene or Layer.
|
|
*
|
|
* You should treat this property as being read-only.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#displayList
|
|
* @type {(Phaser.GameObjects.DisplayList|Phaser.GameObjects.Layer)}
|
|
* @default null
|
|
* @since 3.50.0
|
|
*/
|
|
this.displayList = null;
|
|
|
|
/**
|
|
* A textual representation of this Game Object, i.e. `sprite`.
|
|
* Used internally by Phaser but is available for your own custom classes to populate.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#type
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*/
|
|
this.type = type;
|
|
|
|
/**
|
|
* The current state of this Game Object.
|
|
*
|
|
* Phaser itself will never modify this value, although plugins may do so.
|
|
*
|
|
* Use this property to track the state of a Game Object during its lifetime. For example, it could change from
|
|
* a state of 'moving', to 'attacking', to 'dead'. The state value should be an integer (ideally mapped to a constant
|
|
* in your game code), or a string. These are recommended to keep it light and simple, with fast comparisons.
|
|
* If you need to store complex data about your Game Object, look at using the Data Component instead.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#state
|
|
* @type {(number|string)}
|
|
* @since 3.16.0
|
|
*/
|
|
this.state = 0;
|
|
|
|
/**
|
|
* The parent Container of this Game Object, if it has one.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#parentContainer
|
|
* @type {Phaser.GameObjects.Container}
|
|
* @since 3.4.0
|
|
*/
|
|
this.parentContainer = null;
|
|
|
|
/**
|
|
* The name of this Game Object.
|
|
* Empty by default and never populated by Phaser, this is left for developers to use.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#name
|
|
* @type {string}
|
|
* @default ''
|
|
* @since 3.0.0
|
|
*/
|
|
this.name = '';
|
|
|
|
/**
|
|
* The active state of this Game Object.
|
|
* A Game Object with an active state of `true` is processed by the Scenes UpdateList, if added to it.
|
|
* An active object is one which is having its logic and internal systems updated.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#active
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.0.0
|
|
*/
|
|
this.active = true;
|
|
|
|
/**
|
|
* The Tab Index of the Game Object.
|
|
* Reserved for future use by plugins and the Input Manager.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#tabIndex
|
|
* @type {number}
|
|
* @default -1
|
|
* @since 3.0.0
|
|
*/
|
|
this.tabIndex = -1;
|
|
|
|
/**
|
|
* A Data Manager.
|
|
* It allows you to store, query and get key/value paired information specific to this Game Object.
|
|
* `null` by default. Automatically created if you use `getData` or `setData` or `setDataEnabled`.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#data
|
|
* @type {Phaser.Data.DataManager}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
this.data = null;
|
|
|
|
/**
|
|
* The flags that are compared against `RENDER_MASK` to determine if this Game Object will render or not.
|
|
* The bits are 0001 | 0010 | 0100 | 1000 set by the components Visible, Alpha, Transform and Texture respectively.
|
|
* If those components are not used by your custom class then you can use this bitmask as you wish.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#renderFlags
|
|
* @type {number}
|
|
* @default 15
|
|
* @since 3.0.0
|
|
*/
|
|
this.renderFlags = 15;
|
|
|
|
/**
|
|
* A bitmask that controls if this Game Object is drawn by a Camera or not.
|
|
* Not usually set directly, instead call `Camera.ignore`, however you can
|
|
* set this property directly using the Camera.id property:
|
|
*
|
|
* @example
|
|
* this.cameraFilter |= camera.id
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#cameraFilter
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.cameraFilter = 0;
|
|
|
|
/**
|
|
* If this Game Object is enabled for input then this property will contain an InteractiveObject instance.
|
|
* Not usually set directly. Instead call `GameObject.setInteractive()`.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#input
|
|
* @type {?Phaser.Types.Input.InteractiveObject}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
this.input = null;
|
|
|
|
/**
|
|
* If this Game Object is enabled for Arcade or Matter Physics then this property will contain a reference to a Physics Body.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#body
|
|
* @type {?(Phaser.Physics.Arcade.Body|Phaser.Physics.Arcade.StaticBody|MatterJS.BodyType)}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
this.body = null;
|
|
|
|
/**
|
|
* This Game Object will ignore all calls made to its destroy method if this flag is set to `true`.
|
|
* This includes calls that may come from a Group, Container or the Scene itself.
|
|
* While it allows you to persist a Game Object across Scenes, please understand you are entirely
|
|
* responsible for managing references to and from this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.GameObject#ignoreDestroy
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.5.0
|
|
*/
|
|
this.ignoreDestroy = false;
|
|
|
|
this.on(Events.ADDED_TO_SCENE, this.addedToScene, this);
|
|
this.on(Events.REMOVED_FROM_SCENE, this.removedFromScene, this);
|
|
|
|
// Tell the Scene to re-sort the children
|
|
scene.sys.queueDepthSort();
|
|
},
|
|
|
|
/**
|
|
* Sets the `active` property of this Game Object and returns this Game Object for further chaining.
|
|
* A Game Object with its `active` property set to `true` will be updated by the Scenes UpdateList.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#setActive
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} value - True if this Game Object should be set as active, false if not.
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
setActive: function (value)
|
|
{
|
|
this.active = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the `name` property of this Game Object and returns this Game Object for further chaining.
|
|
* The `name` property is not populated by Phaser and is presented for your own use.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#setName
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} value - The name to be given to this Game Object.
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
setName: function (value)
|
|
{
|
|
this.name = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the current state of this Game Object.
|
|
*
|
|
* Phaser itself will never modify the State of a Game Object, although plugins may do so.
|
|
*
|
|
* For example, a Game Object could change from a state of 'moving', to 'attacking', to 'dead'.
|
|
* The state value should typically be an integer (ideally mapped to a constant
|
|
* in your game code), but could also be a string. It is recommended to keep it light and simple.
|
|
* If you need to store complex data about your Game Object, look at using the Data Component instead.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#setState
|
|
* @since 3.16.0
|
|
*
|
|
* @param {(number|string)} value - The state of the Game Object.
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
setState: function (value)
|
|
{
|
|
this.state = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds a Data Manager component to this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#setDataEnabled
|
|
* @since 3.0.0
|
|
* @see Phaser.Data.DataManager
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
setDataEnabled: function ()
|
|
{
|
|
if (!this.data)
|
|
{
|
|
this.data = new DataManager(this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Allows you to store a key value pair within this Game Objects Data Manager.
|
|
*
|
|
* If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled
|
|
* before setting the value.
|
|
*
|
|
* If the key doesn't already exist in the Data Manager then it is created.
|
|
*
|
|
* ```javascript
|
|
* sprite.setData('name', 'Red Gem Stone');
|
|
* ```
|
|
*
|
|
* You can also pass in an object of key value pairs as the first argument:
|
|
*
|
|
* ```javascript
|
|
* sprite.setData({ name: 'Red Gem Stone', level: 2, owner: 'Link', gold: 50 });
|
|
* ```
|
|
*
|
|
* To get a value back again you can call `getData`:
|
|
*
|
|
* ```javascript
|
|
* sprite.getData('gold');
|
|
* ```
|
|
*
|
|
* Or you can access the value directly via the `values` property, where it works like any other variable:
|
|
*
|
|
* ```javascript
|
|
* sprite.data.values.gold += 50;
|
|
* ```
|
|
*
|
|
* When the value is first set, a `setdata` event is emitted from this Game Object.
|
|
*
|
|
* If the key already exists, a `changedata` event is emitted instead, along an event named after the key.
|
|
* For example, if you updated an existing key called `PlayerLives` then it would emit the event `changedata-PlayerLives`.
|
|
* These events will be emitted regardless if you use this method to set the value, or the direct `values` setter.
|
|
*
|
|
* Please note that the data keys are case-sensitive and must be valid JavaScript Object property strings.
|
|
* This means the keys `gold` and `Gold` are treated as two unique values within the Data Manager.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#setData
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {any} T
|
|
* @genericUse {(string|T)} - [key]
|
|
*
|
|
* @param {(string|object)} key - The key to set the value for. Or an object of key value pairs. If an object the `data` argument is ignored.
|
|
* @param {*} [data] - The value to set for the given key. If an object is provided as the key this argument is ignored.
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
setData: function (key, value)
|
|
{
|
|
if (!this.data)
|
|
{
|
|
this.data = new DataManager(this);
|
|
}
|
|
|
|
this.data.set(key, value);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Increase a value for the given key within this Game Objects Data Manager. If the key doesn't already exist in the Data Manager then it is increased from 0.
|
|
*
|
|
* If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled
|
|
* before setting the value.
|
|
*
|
|
* If the key doesn't already exist in the Data Manager then it is created.
|
|
*
|
|
* When the value is first set, a `setdata` event is emitted from this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#incData
|
|
* @since 3.23.0
|
|
*
|
|
* @generic {any} T
|
|
* @genericUse {(string|T)} - [key]
|
|
*
|
|
* @param {(string|object)} key - The key to increase the value for.
|
|
* @param {*} [data] - The value to increase for the given key.
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
incData: function (key, value)
|
|
{
|
|
if (!this.data)
|
|
{
|
|
this.data = new DataManager(this);
|
|
}
|
|
|
|
this.data.inc(key, value);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Toggle a boolean value for the given key within this Game Objects Data Manager. If the key doesn't already exist in the Data Manager then it is toggled from false.
|
|
*
|
|
* If the Game Object has not been enabled for data (via `setDataEnabled`) then it will be enabled
|
|
* before setting the value.
|
|
*
|
|
* If the key doesn't already exist in the Data Manager then it is created.
|
|
*
|
|
* When the value is first set, a `setdata` event is emitted from this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#toggleData
|
|
* @since 3.23.0
|
|
*
|
|
* @generic {any} T
|
|
* @genericUse {(string|T)} - [key]
|
|
*
|
|
* @param {(string|object)} key - The key to toggle the value for.
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
toggleData: function (key)
|
|
{
|
|
if (!this.data)
|
|
{
|
|
this.data = new DataManager(this);
|
|
}
|
|
|
|
this.data.toggle(key);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Retrieves the value for the given key in this Game Objects Data Manager, or undefined if it doesn't exist.
|
|
*
|
|
* You can also access values via the `values` object. For example, if you had a key called `gold` you can do either:
|
|
*
|
|
* ```javascript
|
|
* sprite.getData('gold');
|
|
* ```
|
|
*
|
|
* Or access the value directly:
|
|
*
|
|
* ```javascript
|
|
* sprite.data.values.gold;
|
|
* ```
|
|
*
|
|
* You can also pass in an array of keys, in which case an array of values will be returned:
|
|
*
|
|
* ```javascript
|
|
* sprite.getData([ 'gold', 'armor', 'health' ]);
|
|
* ```
|
|
*
|
|
* This approach is useful for destructuring arrays in ES6.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#getData
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|string[])} key - The key of the value to retrieve, or an array of keys.
|
|
*
|
|
* @return {*} The value belonging to the given key, or an array of values, the order of which will match the input array.
|
|
*/
|
|
getData: function (key)
|
|
{
|
|
if (!this.data)
|
|
{
|
|
this.data = new DataManager(this);
|
|
}
|
|
|
|
return this.data.get(key);
|
|
},
|
|
|
|
/**
|
|
* Pass this Game Object to the Input Manager to enable it for Input.
|
|
*
|
|
* Input works by using hit areas, these are nearly always geometric shapes, such as rectangles or circles, that act as the hit area
|
|
* for the Game Object. However, you can provide your own hit area shape and callback, should you wish to handle some more advanced
|
|
* input detection.
|
|
*
|
|
* If no arguments are provided it will try and create a rectangle hit area based on the texture frame the Game Object is using. If
|
|
* this isn't a texture-bound object, such as a Graphics or BitmapText object, this will fail, and you'll need to provide a specific
|
|
* shape for it to use.
|
|
*
|
|
* You can also provide an Input Configuration Object as the only argument to this method.
|
|
*
|
|
* @example
|
|
* sprite.setInteractive();
|
|
*
|
|
* @example
|
|
* sprite.setInteractive(new Phaser.Geom.Circle(45, 46, 45), Phaser.Geom.Circle.Contains);
|
|
*
|
|
* @example
|
|
* graphics.setInteractive(new Phaser.Geom.Rectangle(0, 0, 128, 128), Phaser.Geom.Rectangle.Contains);
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#setInteractive
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Types.Input.InputConfiguration|any)} [hitArea] - Either an input configuration object, or a geometric shape that defines the hit area for the Game Object. If not given it will try to create a Rectangle based on the texture frame.
|
|
* @param {Phaser.Types.Input.HitAreaCallback} [callback] - The callback that determines if the pointer is within the Hit Area shape or not. If you provide a shape you must also provide a callback.
|
|
* @param {boolean} [dropZone=false] - Should this Game Object be treated as a drop zone target?
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
setInteractive: function (hitArea, hitAreaCallback, dropZone)
|
|
{
|
|
this.scene.sys.input.enable(this, hitArea, hitAreaCallback, dropZone);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* If this Game Object has previously been enabled for input, this will disable it.
|
|
*
|
|
* An object that is disabled for input stops processing or being considered for
|
|
* input events, but can be turned back on again at any time by simply calling
|
|
* `setInteractive()` with no arguments provided.
|
|
*
|
|
* If want to completely remove interaction from this Game Object then use `removeInteractive` instead.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#disableInteractive
|
|
* @since 3.7.0
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
disableInteractive: function ()
|
|
{
|
|
this.scene.sys.input.disable(this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* If this Game Object has previously been enabled for input, this will queue it
|
|
* for removal, causing it to no longer be interactive. The removal happens on
|
|
* the next game step, it is not immediate.
|
|
*
|
|
* The Interactive Object that was assigned to this Game Object will be destroyed,
|
|
* removed from the Input Manager and cleared from this Game Object.
|
|
*
|
|
* If you wish to re-enable this Game Object at a later date you will need to
|
|
* re-create its InteractiveObject by calling `setInteractive` again.
|
|
*
|
|
* If you wish to only temporarily stop an object from receiving input then use
|
|
* `disableInteractive` instead, as that toggles the interactive state, where-as
|
|
* this erases it completely.
|
|
*
|
|
* If you wish to resize a hit area, don't remove and then set it as being
|
|
* interactive. Instead, access the hitarea object directly and resize the shape
|
|
* being used. I.e.: `sprite.input.hitArea.setSize(width, height)` (assuming the
|
|
* shape is a Rectangle, which it is by default.)
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#removeInteractive
|
|
* @since 3.7.0
|
|
*
|
|
* @return {this} This GameObject.
|
|
*/
|
|
removeInteractive: function ()
|
|
{
|
|
this.scene.sys.input.clear(this);
|
|
|
|
this.input = undefined;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* This callback is invoked when this Game Object is added to a Scene.
|
|
*
|
|
* Can be overriden by custom Game Objects, but be aware of some Game Objects that
|
|
* will use this, such as Sprites, to add themselves into the Update List.
|
|
*
|
|
* You can also listen for the `ADDED_TO_SCENE` event from this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#addedToScene
|
|
* @since 3.50.0
|
|
*/
|
|
addedToScene: function ()
|
|
{
|
|
},
|
|
|
|
/**
|
|
* This callback is invoked when this Game Object is removed from a Scene.
|
|
*
|
|
* Can be overriden by custom Game Objects, but be aware of some Game Objects that
|
|
* will use this, such as Sprites, to removed themselves from the Update List.
|
|
*
|
|
* You can also listen for the `REMOVED_FROM_SCENE` event from this Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#removedFromScene
|
|
* @since 3.50.0
|
|
*/
|
|
removedFromScene: function ()
|
|
{
|
|
},
|
|
|
|
/**
|
|
* To be overridden by custom GameObjects. Allows base objects to be used in a Pool.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#update
|
|
* @since 3.0.0
|
|
*
|
|
* @param {...*} [args] - args
|
|
*/
|
|
update: function ()
|
|
{
|
|
},
|
|
|
|
/**
|
|
* Returns a JSON representation of the Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#toJSON
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object.
|
|
*/
|
|
toJSON: function ()
|
|
{
|
|
return ComponentsToJSON(this);
|
|
},
|
|
|
|
/**
|
|
* Compares the renderMask with the renderFlags to see if this Game Object will render or not.
|
|
* Also checks the Game Object against the given Cameras exclusion list.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#willRender
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to check against this Game Object.
|
|
*
|
|
* @return {boolean} True if the Game Object should be rendered, otherwise false.
|
|
*/
|
|
willRender: function (camera)
|
|
{
|
|
var listWillRender = (this.displayList && this.displayList.active) ? this.displayList.willRender(camera) : true;
|
|
|
|
return !(!listWillRender || GameObject.RENDER_MASK !== this.renderFlags || (this.cameraFilter !== 0 && (this.cameraFilter & camera.id)));
|
|
},
|
|
|
|
/**
|
|
* Returns an array containing the display list index of either this Game Object, or if it has one,
|
|
* its parent Container. It then iterates up through all of the parent containers until it hits the
|
|
* root of the display list (which is index 0 in the returned array).
|
|
*
|
|
* Used internally by the InputPlugin but also useful if you wish to find out the display depth of
|
|
* this Game Object and all of its ancestors.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#getIndexList
|
|
* @since 3.4.0
|
|
*
|
|
* @return {number[]} An array of display list position indexes.
|
|
*/
|
|
getIndexList: function ()
|
|
{
|
|
// eslint-disable-next-line consistent-this
|
|
var child = this;
|
|
var parent = this.parentContainer;
|
|
|
|
var indexes = [];
|
|
|
|
while (parent)
|
|
{
|
|
indexes.unshift(parent.getIndex(child));
|
|
|
|
child = parent;
|
|
|
|
if (!parent.parentContainer)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
parent = parent.parentContainer;
|
|
}
|
|
}
|
|
|
|
if (this.displayList)
|
|
{
|
|
indexes.unshift(this.displayList.getIndex(child));
|
|
}
|
|
else
|
|
{
|
|
indexes.unshift(this.scene.sys.displayList.getIndex(child));
|
|
}
|
|
|
|
return indexes;
|
|
},
|
|
|
|
/**
|
|
* Adds this Game Object to the given Display List.
|
|
*
|
|
* If no Display List is specified, it will default to the Display List owned by the Scene to which
|
|
* this Game Object belongs.
|
|
*
|
|
* A Game Object can only exist on one Display List at any given time, but may move freely between them.
|
|
*
|
|
* If this Game Object is already on another Display List when this method is called, it will first
|
|
* be removed from it, before being added to the new list.
|
|
*
|
|
* You can query which list it is on by looking at the `Phaser.GameObjects.GameObject#displayList` property.
|
|
*
|
|
* If a Game Object isn't on any display list, it will not be rendered. If you just wish to temporarly
|
|
* disable it from rendering, consider using the `setVisible` method, instead.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#addToDisplayList
|
|
* @fires Phaser.Scenes.Events#ADDED_TO_SCENE
|
|
* @fires Phaser.GameObjects.Events#ADDED_TO_SCENE
|
|
* @since 3.53.0
|
|
*
|
|
* @param {(Phaser.GameObjects.DisplayList|Phaser.GameObjects.Layer)} [displayList] - The Display List to add to. Defaults to the Scene Display List.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
addToDisplayList: function (displayList)
|
|
{
|
|
if (displayList === undefined) { displayList = this.scene.sys.displayList; }
|
|
|
|
if (this.displayList && this.displayList !== displayList)
|
|
{
|
|
this.removeFromDisplayList();
|
|
}
|
|
|
|
// Don't repeat if it's already on this list
|
|
if (!displayList.exists(this))
|
|
{
|
|
this.displayList = displayList;
|
|
|
|
displayList.add(this, true);
|
|
|
|
displayList.queueDepthSort();
|
|
|
|
this.emit(Events.ADDED_TO_SCENE, this, this.scene);
|
|
|
|
displayList.events.emit(SceneEvents.ADDED_TO_SCENE, this, this.scene);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds this Game Object to the Update List belonging to the Scene.
|
|
*
|
|
* When a Game Object is added to the Update List it will have its `preUpdate` method called
|
|
* every game frame. This method is passed two parameters: `delta` and `time`.
|
|
*
|
|
* If you wish to run your own logic within `preUpdate` then you should always call
|
|
* `preUpdate.super(delta, time)` within it, or it may fail to process required operations,
|
|
* such as Sprite animations.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#addToUpdateList
|
|
* @since 3.53.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
addToUpdateList: function ()
|
|
{
|
|
if (this.scene && this.preUpdate)
|
|
{
|
|
this.scene.sys.updateList.add(this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes this Game Object from the Display List it is currently on.
|
|
*
|
|
* A Game Object can only exist on one Display List at any given time, but may move freely removed
|
|
* and added back at a later stage.
|
|
*
|
|
* You can query which list it is on by looking at the `Phaser.GameObjects.GameObject#displayList` property.
|
|
*
|
|
* If a Game Object isn't on any Display List, it will not be rendered. If you just wish to temporarly
|
|
* disable it from rendering, consider using the `setVisible` method, instead.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#removeFromDisplayList
|
|
* @fires Phaser.Scenes.Events#REMOVED_FROM_SCENE
|
|
* @fires Phaser.GameObjects.Events#REMOVED_FROM_SCENE
|
|
* @since 3.53.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
removeFromDisplayList: function ()
|
|
{
|
|
var displayList = this.displayList || this.scene.sys.displayList;
|
|
|
|
if (displayList && displayList.exists(this))
|
|
{
|
|
displayList.remove(this, true);
|
|
|
|
displayList.queueDepthSort();
|
|
|
|
this.displayList = null;
|
|
|
|
this.emit(Events.REMOVED_FROM_SCENE, this, this.scene);
|
|
|
|
displayList.events.emit(SceneEvents.REMOVED_FROM_SCENE, this, this.scene);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes this Game Object from the Scene's Update List.
|
|
*
|
|
* When a Game Object is on the Update List, it will have its `preUpdate` method called
|
|
* every game frame. Calling this method will remove it from the list, preventing this.
|
|
*
|
|
* Removing a Game Object from the Update List will stop most internal functions working.
|
|
* For example, removing a Sprite from the Update List will prevent it from being able to
|
|
* run animations.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#removeFromUpdateList
|
|
* @since 3.53.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
removeFromUpdateList: function ()
|
|
{
|
|
if (this.scene && this.preUpdate)
|
|
{
|
|
this.scene.sys.updateList.remove(this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Destroys this Game Object removing it from the Display List and Update List and
|
|
* severing all ties to parent resources.
|
|
*
|
|
* Also removes itself from the Input Manager and Physics Manager if previously enabled.
|
|
*
|
|
* Use this to remove a Game Object from your game if you don't ever plan to use it again.
|
|
* As long as no reference to it exists within your own code it should become free for
|
|
* garbage collection by the browser.
|
|
*
|
|
* If you just want to temporarily disable an object then look at using the
|
|
* Game Object Pool instead of destroying it, as destroyed objects cannot be resurrected.
|
|
*
|
|
* @method Phaser.GameObjects.GameObject#destroy
|
|
* @fires Phaser.GameObjects.Events#DESTROY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} [fromScene=false] - `True` if this Game Object is being destroyed by the Scene, `false` if not.
|
|
*/
|
|
destroy: function (fromScene)
|
|
{
|
|
// This Game Object has already been destroyed
|
|
if (!this.scene || this.ignoreDestroy)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (fromScene === undefined) { fromScene = false; }
|
|
|
|
if (this.preDestroy)
|
|
{
|
|
this.preDestroy.call(this);
|
|
}
|
|
|
|
this.emit(Events.DESTROY, this, fromScene);
|
|
|
|
this.removeAllListeners();
|
|
|
|
if (this.postPipelines)
|
|
{
|
|
this.resetPostPipeline(true);
|
|
}
|
|
|
|
this.removeFromDisplayList();
|
|
this.removeFromUpdateList();
|
|
|
|
if (this.input)
|
|
{
|
|
this.scene.sys.input.clear(this);
|
|
|
|
this.input = undefined;
|
|
}
|
|
|
|
if (this.data)
|
|
{
|
|
this.data.destroy();
|
|
|
|
this.data = undefined;
|
|
}
|
|
|
|
if (this.body)
|
|
{
|
|
this.body.destroy();
|
|
|
|
this.body = undefined;
|
|
}
|
|
|
|
this.active = false;
|
|
this.visible = false;
|
|
|
|
this.scene = undefined;
|
|
this.parentContainer = undefined;
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* The bitmask that `GameObject.renderFlags` is compared against to determine if the Game Object will render or not.
|
|
*
|
|
* @constant {number} RENDER_MASK
|
|
* @memberof Phaser.GameObjects.GameObject
|
|
* @default
|
|
*/
|
|
GameObject.RENDER_MASK = 15;
|
|
|
|
module.exports = GameObject;
|
|
|
|
|
|
/***/ }),
|
|
/* 58 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Build a JSON representation of the given Game Object.
|
|
*
|
|
* This is typically extended further by Game Object specific implementations.
|
|
*
|
|
* @method Phaser.GameObjects.Components.ToJSON
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object to export as JSON.
|
|
*
|
|
* @return {Phaser.Types.GameObjects.JSONGameObject} A JSON representation of the Game Object.
|
|
*/
|
|
var ToJSON = function (gameObject)
|
|
{
|
|
var out = {
|
|
name: gameObject.name,
|
|
type: gameObject.type,
|
|
x: gameObject.x,
|
|
y: gameObject.y,
|
|
depth: gameObject.depth,
|
|
scale: {
|
|
x: gameObject.scaleX,
|
|
y: gameObject.scaleY
|
|
},
|
|
origin: {
|
|
x: gameObject.originX,
|
|
y: gameObject.originY
|
|
},
|
|
flipX: gameObject.flipX,
|
|
flipY: gameObject.flipY,
|
|
rotation: gameObject.rotation,
|
|
alpha: gameObject.alpha,
|
|
visible: gameObject.visible,
|
|
blendMode: gameObject.blendMode,
|
|
textureKey: '',
|
|
frameKey: '',
|
|
data: {}
|
|
};
|
|
|
|
if (gameObject.texture)
|
|
{
|
|
out.textureKey = gameObject.texture.key;
|
|
out.frameKey = gameObject.frame.name;
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = ToJSON;
|
|
|
|
|
|
/***/ }),
|
|
/* 59 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.GameObjects.Events
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
ADDED_TO_SCENE: __webpack_require__(236),
|
|
DESTROY: __webpack_require__(237),
|
|
REMOVED_FROM_SCENE: __webpack_require__(238),
|
|
VIDEO_COMPLETE: __webpack_require__(239),
|
|
VIDEO_CREATED: __webpack_require__(240),
|
|
VIDEO_ERROR: __webpack_require__(241),
|
|
VIDEO_LOOP: __webpack_require__(242),
|
|
VIDEO_PLAY: __webpack_require__(243),
|
|
VIDEO_SEEKED: __webpack_require__(244),
|
|
VIDEO_SEEKING: __webpack_require__(245),
|
|
VIDEO_STOP: __webpack_require__(246),
|
|
VIDEO_TIMEOUT: __webpack_require__(247),
|
|
VIDEO_UNLOCKED: __webpack_require__(248)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 60 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var TransformMatrix = __webpack_require__(26);
|
|
|
|
var tempMatrix1 = new TransformMatrix();
|
|
var tempMatrix2 = new TransformMatrix();
|
|
var tempMatrix3 = new TransformMatrix();
|
|
|
|
var result = { camera: tempMatrix1, sprite: tempMatrix2, calc: tempMatrix3 };
|
|
|
|
/**
|
|
* Calculates the Transform Matrix of the given Game Object and Camera, factoring in
|
|
* the parent matrix if provided.
|
|
*
|
|
* Note that the object this results contains _references_ to the Transform Matrices,
|
|
* not new instances of them. Therefore, you should use their values immediately, or
|
|
* copy them to your own matrix, as they will be replaced as soon as another Game
|
|
* Object is rendered.
|
|
*
|
|
* @function Phaser.GameObjects.GetCalcMatrix
|
|
* @memberof Phaser.GameObjects
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} src - The Game Object to calculate the transform matrix for.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera being used to render the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} [parentMatrix] - The transform matrix of the parent container, if any.
|
|
*
|
|
* @return {Phaser.Types.GameObjects.GetCalcMatrixResults} The results object containing the updated transform matrices.
|
|
*/
|
|
var GetCalcMatrix = function (src, camera, parentMatrix)
|
|
{
|
|
var camMatrix = tempMatrix1;
|
|
var spriteMatrix = tempMatrix2;
|
|
var calcMatrix = tempMatrix3;
|
|
|
|
spriteMatrix.applyITRS(src.x, src.y, src.rotation, src.scaleX, src.scaleY);
|
|
|
|
camMatrix.copyFrom(camera.matrix);
|
|
|
|
if (parentMatrix)
|
|
{
|
|
// Multiply the camera by the parent matrix
|
|
camMatrix.multiplyWithOffset(parentMatrix, -camera.scrollX * src.scrollFactorX, -camera.scrollY * src.scrollFactorY);
|
|
|
|
// Undo the camera scroll
|
|
spriteMatrix.e = src.x;
|
|
spriteMatrix.f = src.y;
|
|
}
|
|
else
|
|
{
|
|
spriteMatrix.e -= camera.scrollX * src.scrollFactorX;
|
|
spriteMatrix.f -= camera.scrollY * src.scrollFactorY;
|
|
}
|
|
|
|
// Multiply by the Sprite matrix, store result in calcMatrix
|
|
camMatrix.multiply(spriteMatrix, calcMatrix);
|
|
|
|
return result;
|
|
};
|
|
|
|
module.exports = GetCalcMatrix;
|
|
|
|
|
|
/***/ }),
|
|
/* 61 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Transposes the elements of the given matrix (array of arrays).
|
|
*
|
|
* The transpose of a matrix is a new matrix whose rows are the columns of the original.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.TransposeMatrix
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [array,$return]
|
|
*
|
|
* @param {T[][]} [array] - The array matrix to transpose.
|
|
*
|
|
* @return {T[][]} A new array matrix which is a transposed version of the given array.
|
|
*/
|
|
var TransposeMatrix = function (array)
|
|
{
|
|
var sourceRowCount = array.length;
|
|
var sourceColCount = array[0].length;
|
|
|
|
var result = new Array(sourceColCount);
|
|
|
|
for (var i = 0; i < sourceColCount; i++)
|
|
{
|
|
result[i] = new Array(sourceRowCount);
|
|
|
|
for (var j = sourceRowCount - 1; j > -1; j--)
|
|
{
|
|
result[i][j] = array[j][i];
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
module.exports = TransposeMatrix;
|
|
|
|
|
|
/***/ }),
|
|
/* 62 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the element at the start of the array to the end, shifting all items in the process.
|
|
* The "rotation" happens to the left.
|
|
*
|
|
* @function Phaser.Utils.Array.RotateLeft
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} array - The array to shift to the left. This array is modified in place.
|
|
* @param {number} [total=1] - The number of times to shift the array.
|
|
*
|
|
* @return {*} The most recently shifted element.
|
|
*/
|
|
var RotateLeft = function (array, total)
|
|
{
|
|
if (total === undefined) { total = 1; }
|
|
|
|
var element = null;
|
|
|
|
for (var i = 0; i < total; i++)
|
|
{
|
|
element = array.shift();
|
|
array.push(element);
|
|
}
|
|
|
|
return element;
|
|
};
|
|
|
|
module.exports = RotateLeft;
|
|
|
|
|
|
/***/ }),
|
|
/* 63 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the element at the end of the array to the start, shifting all items in the process.
|
|
* The "rotation" happens to the right.
|
|
*
|
|
* @function Phaser.Utils.Array.RotateRight
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} array - The array to shift to the right. This array is modified in place.
|
|
* @param {number} [total=1] - The number of times to shift the array.
|
|
*
|
|
* @return {*} The most recently shifted element.
|
|
*/
|
|
var RotateRight = function (array, total)
|
|
{
|
|
if (total === undefined) { total = 1; }
|
|
|
|
var element = null;
|
|
|
|
for (var i = 0; i < total; i++)
|
|
{
|
|
element = array.pop();
|
|
array.unshift(element);
|
|
}
|
|
|
|
return element;
|
|
};
|
|
|
|
module.exports = RotateRight;
|
|
|
|
|
|
/***/ }),
|
|
/* 64 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Shuffles the contents of the given array using the Fisher-Yates implementation.
|
|
*
|
|
* The original array is modified directly and returned.
|
|
*
|
|
* @function Phaser.Utils.Array.Shuffle
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[]} - [array,$return]
|
|
*
|
|
* @param {T[]} array - The array to shuffle. This array is modified in place.
|
|
*
|
|
* @return {T[]} The shuffled array.
|
|
*/
|
|
var Shuffle = function (array)
|
|
{
|
|
for (var i = array.length - 1; i > 0; i--)
|
|
{
|
|
var j = Math.floor(Math.random() * (i + 1));
|
|
var temp = array[i];
|
|
array[i] = array[j];
|
|
array[j] = temp;
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = Shuffle;
|
|
|
|
|
|
/***/ }),
|
|
/* 65 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CONST = __webpack_require__(304);
|
|
var Smoothing = __webpack_require__(306);
|
|
|
|
// The pool into which the canvas elements are placed.
|
|
var pool = [];
|
|
|
|
// Automatically apply smoothing(false) to created Canvas elements
|
|
var _disableContextSmoothing = false;
|
|
|
|
/**
|
|
* The CanvasPool is a global static object, that allows Phaser to recycle and pool 2D Context Canvas DOM elements.
|
|
* It does not pool WebGL Contexts, because once the context options are set they cannot be modified again,
|
|
* which is useless for some of the Phaser pipelines / renderer.
|
|
*
|
|
* This singleton is instantiated as soon as Phaser loads, before a Phaser.Game instance has even been created.
|
|
* Which means all instances of Phaser Games on the same page can share the one single pool.
|
|
*
|
|
* @namespace Phaser.Display.Canvas.CanvasPool
|
|
* @since 3.0.0
|
|
*/
|
|
var CanvasPool = function ()
|
|
{
|
|
/**
|
|
* Creates a new Canvas DOM element, or pulls one from the pool if free.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.create
|
|
* @since 3.0.0
|
|
*
|
|
* @param {*} parent - The parent of the Canvas object.
|
|
* @param {number} [width=1] - The width of the Canvas.
|
|
* @param {number} [height=1] - The height of the Canvas.
|
|
* @param {number} [canvasType=Phaser.CANVAS] - The type of the Canvas. Either `Phaser.CANVAS` or `Phaser.WEBGL`.
|
|
* @param {boolean} [selfParent=false] - Use the generated Canvas element as the parent?
|
|
*
|
|
* @return {HTMLCanvasElement} The canvas element that was created or pulled from the pool
|
|
*/
|
|
var create = function (parent, width, height, canvasType, selfParent)
|
|
{
|
|
if (width === undefined) { width = 1; }
|
|
if (height === undefined) { height = 1; }
|
|
if (canvasType === undefined) { canvasType = CONST.CANVAS; }
|
|
if (selfParent === undefined) { selfParent = false; }
|
|
|
|
var canvas;
|
|
var container = first(canvasType);
|
|
|
|
if (container === null)
|
|
{
|
|
container = {
|
|
parent: parent,
|
|
canvas: document.createElement('canvas'),
|
|
type: canvasType
|
|
};
|
|
|
|
if (canvasType === CONST.CANVAS)
|
|
{
|
|
pool.push(container);
|
|
}
|
|
|
|
canvas = container.canvas;
|
|
}
|
|
else
|
|
{
|
|
container.parent = parent;
|
|
|
|
canvas = container.canvas;
|
|
}
|
|
|
|
if (selfParent)
|
|
{
|
|
container.parent = canvas;
|
|
}
|
|
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
|
|
if (_disableContextSmoothing && canvasType === CONST.CANVAS)
|
|
{
|
|
Smoothing.disable(canvas.getContext('2d'));
|
|
}
|
|
|
|
return canvas;
|
|
};
|
|
|
|
/**
|
|
* Creates a new Canvas DOM element, or pulls one from the pool if free.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.create2D
|
|
* @since 3.0.0
|
|
*
|
|
* @param {*} parent - The parent of the Canvas object.
|
|
* @param {number} [width=1] - The width of the Canvas.
|
|
* @param {number} [height=1] - The height of the Canvas.
|
|
*
|
|
* @return {HTMLCanvasElement} The created canvas.
|
|
*/
|
|
var create2D = function (parent, width, height)
|
|
{
|
|
return create(parent, width, height, CONST.CANVAS);
|
|
};
|
|
|
|
/**
|
|
* Creates a new Canvas DOM element, or pulls one from the pool if free.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.createWebGL
|
|
* @since 3.0.0
|
|
*
|
|
* @param {*} parent - The parent of the Canvas object.
|
|
* @param {number} [width=1] - The width of the Canvas.
|
|
* @param {number} [height=1] - The height of the Canvas.
|
|
*
|
|
* @return {HTMLCanvasElement} The created WebGL canvas.
|
|
*/
|
|
var createWebGL = function (parent, width, height)
|
|
{
|
|
return create(parent, width, height, CONST.WEBGL);
|
|
};
|
|
|
|
/**
|
|
* Gets the first free canvas index from the pool.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.first
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [canvasType=Phaser.CANVAS] - The type of the Canvas. Either `Phaser.CANVAS` or `Phaser.WEBGL`.
|
|
*
|
|
* @return {HTMLCanvasElement} The first free canvas, or `null` if a WebGL canvas was requested or if the pool doesn't have free canvases.
|
|
*/
|
|
var first = function (canvasType)
|
|
{
|
|
if (canvasType === undefined) { canvasType = CONST.CANVAS; }
|
|
|
|
if (canvasType === CONST.WEBGL)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
for (var i = 0; i < pool.length; i++)
|
|
{
|
|
var container = pool[i];
|
|
|
|
if (!container.parent && container.type === canvasType)
|
|
{
|
|
return container;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Looks up a canvas based on its parent, and if found puts it back in the pool, freeing it up for re-use.
|
|
* The canvas has its width and height set to 1, and its parent attribute nulled.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.remove
|
|
* @since 3.0.0
|
|
*
|
|
* @param {*} parent - The canvas or the parent of the canvas to free.
|
|
*/
|
|
var remove = function (parent)
|
|
{
|
|
// Check to see if the parent is a canvas object
|
|
var isCanvas = parent instanceof HTMLCanvasElement;
|
|
|
|
pool.forEach(function (container)
|
|
{
|
|
if ((isCanvas && container.canvas === parent) || (!isCanvas && container.parent === parent))
|
|
{
|
|
container.parent = null;
|
|
container.canvas.width = 1;
|
|
container.canvas.height = 1;
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Gets the total number of used canvas elements in the pool.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.total
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The number of used canvases.
|
|
*/
|
|
var total = function ()
|
|
{
|
|
var c = 0;
|
|
|
|
pool.forEach(function (container)
|
|
{
|
|
if (container.parent)
|
|
{
|
|
c++;
|
|
}
|
|
});
|
|
|
|
return c;
|
|
};
|
|
|
|
/**
|
|
* Gets the total number of free canvas elements in the pool.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.free
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The number of free canvases.
|
|
*/
|
|
var free = function ()
|
|
{
|
|
return pool.length - total();
|
|
};
|
|
|
|
/**
|
|
* Disable context smoothing on any new Canvas element created.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.disableSmoothing
|
|
* @since 3.0.0
|
|
*/
|
|
var disableSmoothing = function ()
|
|
{
|
|
_disableContextSmoothing = true;
|
|
};
|
|
|
|
/**
|
|
* Enable context smoothing on any new Canvas element created.
|
|
*
|
|
* @function Phaser.Display.Canvas.CanvasPool.enableSmoothing
|
|
* @since 3.0.0
|
|
*/
|
|
var enableSmoothing = function ()
|
|
{
|
|
_disableContextSmoothing = false;
|
|
};
|
|
|
|
return {
|
|
create2D: create2D,
|
|
create: create,
|
|
createWebGL: createWebGL,
|
|
disableSmoothing: disableSmoothing,
|
|
enableSmoothing: enableSmoothing,
|
|
first: first,
|
|
free: free,
|
|
pool: pool,
|
|
remove: remove,
|
|
total: total
|
|
};
|
|
};
|
|
|
|
// If we export the called function here, it'll only be invoked once (not every time it's required).
|
|
module.exports = CanvasPool();
|
|
|
|
|
|
/***/ }),
|
|
/* 66 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Perimeter = __webpack_require__(67);
|
|
var Point = __webpack_require__(14);
|
|
|
|
/**
|
|
* Calculates the coordinates of a point at a certain `position` on the Rectangle's perimeter.
|
|
*
|
|
* The `position` is a fraction between 0 and 1 which defines how far into the perimeter the point is.
|
|
*
|
|
* A value of 0 or 1 returns the point at the top left corner of the rectangle, while a value of 0.5 returns the point at the bottom right corner of the rectangle. Values between 0 and 0.5 are on the top or the right side and values between 0.5 and 1 are on the bottom or the left side.
|
|
*
|
|
* @function Phaser.Geom.Rectangle.GetPoint
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [out,$return]
|
|
*
|
|
* @param {Phaser.Geom.Rectangle} rectangle - The Rectangle to get the perimeter point from.
|
|
* @param {number} position - The normalized distance into the Rectangle's perimeter to return.
|
|
* @param {(Phaser.Geom.Point|object)} [out] - An object to update with the `x` and `y` coordinates of the point.
|
|
*
|
|
* @return {Phaser.Geom.Point} The updated `output` object, or a new Point if no `output` object was given.
|
|
*/
|
|
var GetPoint = function (rectangle, position, out)
|
|
{
|
|
if (out === undefined) { out = new Point(); }
|
|
|
|
if (position <= 0 || position >= 1)
|
|
{
|
|
out.x = rectangle.x;
|
|
out.y = rectangle.y;
|
|
|
|
return out;
|
|
}
|
|
|
|
var p = Perimeter(rectangle) * position;
|
|
|
|
if (position > 0.5)
|
|
{
|
|
p -= (rectangle.width + rectangle.height);
|
|
|
|
if (p <= rectangle.width)
|
|
{
|
|
// Face 3
|
|
out.x = rectangle.right - p;
|
|
out.y = rectangle.bottom;
|
|
}
|
|
else
|
|
{
|
|
// Face 4
|
|
out.x = rectangle.x;
|
|
out.y = rectangle.bottom - (p - rectangle.width);
|
|
}
|
|
}
|
|
else if (p <= rectangle.width)
|
|
{
|
|
// Face 1
|
|
out.x = rectangle.x + p;
|
|
out.y = rectangle.y;
|
|
}
|
|
else
|
|
{
|
|
// Face 2
|
|
out.x = rectangle.right;
|
|
out.y = rectangle.y + (p - rectangle.width);
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = GetPoint;
|
|
|
|
|
|
/***/ }),
|
|
/* 67 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculates the perimeter of a Rectangle.
|
|
*
|
|
* @function Phaser.Geom.Rectangle.Perimeter
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Geom.Rectangle} rect - The Rectangle to use.
|
|
*
|
|
* @return {number} The perimeter of the Rectangle, equal to `(width * 2) + (height * 2)`.
|
|
*/
|
|
var Perimeter = function (rect)
|
|
{
|
|
return 2 * (rect.width + rect.height);
|
|
};
|
|
|
|
module.exports = Perimeter;
|
|
|
|
|
|
/***/ }),
|
|
/* 68 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var Clamp = __webpack_require__(1);
|
|
var Extend = __webpack_require__(19);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Frame is a section of a Texture.
|
|
*
|
|
* @class Frame
|
|
* @memberof Phaser.Textures
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Textures.Texture} texture - The Texture this Frame is a part of.
|
|
* @param {(number|string)} name - The name of this Frame. The name is unique within the Texture.
|
|
* @param {number} sourceIndex - The index of the TextureSource that this Frame is a part of.
|
|
* @param {number} x - The x coordinate of the top-left of this Frame.
|
|
* @param {number} y - The y coordinate of the top-left of this Frame.
|
|
* @param {number} width - The width of this Frame.
|
|
* @param {number} height - The height of this Frame.
|
|
*/
|
|
var Frame = new Class({
|
|
|
|
initialize:
|
|
|
|
function Frame (texture, name, sourceIndex, x, y, width, height)
|
|
{
|
|
/**
|
|
* The Texture this Frame is a part of.
|
|
*
|
|
* @name Phaser.Textures.Frame#texture
|
|
* @type {Phaser.Textures.Texture}
|
|
* @since 3.0.0
|
|
*/
|
|
this.texture = texture;
|
|
|
|
/**
|
|
* The name of this Frame.
|
|
* The name is unique within the Texture.
|
|
*
|
|
* @name Phaser.Textures.Frame#name
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*/
|
|
this.name = name;
|
|
|
|
/**
|
|
* The TextureSource this Frame is part of.
|
|
*
|
|
* @name Phaser.Textures.Frame#source
|
|
* @type {Phaser.Textures.TextureSource}
|
|
* @since 3.0.0
|
|
*/
|
|
this.source = texture.source[sourceIndex];
|
|
|
|
/**
|
|
* The index of the TextureSource in the Texture sources array.
|
|
*
|
|
* @name Phaser.Textures.Frame#sourceIndex
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.sourceIndex = sourceIndex;
|
|
|
|
/**
|
|
* A reference to the Texture Source WebGL Texture that this Frame is using.
|
|
*
|
|
* @name Phaser.Textures.Frame#glTexture
|
|
* @type {?WebGLTexture}
|
|
* @default null
|
|
* @since 3.11.0
|
|
*/
|
|
this.glTexture = this.source.glTexture;
|
|
|
|
/**
|
|
* X position within the source image to cut from.
|
|
*
|
|
* @name Phaser.Textures.Frame#cutX
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.cutX;
|
|
|
|
/**
|
|
* Y position within the source image to cut from.
|
|
*
|
|
* @name Phaser.Textures.Frame#cutY
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.cutY;
|
|
|
|
/**
|
|
* The width of the area in the source image to cut.
|
|
*
|
|
* @name Phaser.Textures.Frame#cutWidth
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.cutWidth;
|
|
|
|
/**
|
|
* The height of the area in the source image to cut.
|
|
*
|
|
* @name Phaser.Textures.Frame#cutHeight
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.cutHeight;
|
|
|
|
/**
|
|
* The X rendering offset of this Frame, taking trim into account.
|
|
*
|
|
* @name Phaser.Textures.Frame#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.x = 0;
|
|
|
|
/**
|
|
* The Y rendering offset of this Frame, taking trim into account.
|
|
*
|
|
* @name Phaser.Textures.Frame#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.y = 0;
|
|
|
|
/**
|
|
* The rendering width of this Frame, taking trim into account.
|
|
*
|
|
* @name Phaser.Textures.Frame#width
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.width;
|
|
|
|
/**
|
|
* The rendering height of this Frame, taking trim into account.
|
|
*
|
|
* @name Phaser.Textures.Frame#height
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.height;
|
|
|
|
/**
|
|
* Half the width, floored.
|
|
* Precalculated for the renderer.
|
|
*
|
|
* @name Phaser.Textures.Frame#halfWidth
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.halfWidth;
|
|
|
|
/**
|
|
* Half the height, floored.
|
|
* Precalculated for the renderer.
|
|
*
|
|
* @name Phaser.Textures.Frame#halfHeight
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.halfHeight;
|
|
|
|
/**
|
|
* The x center of this frame, floored.
|
|
*
|
|
* @name Phaser.Textures.Frame#centerX
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.centerX;
|
|
|
|
/**
|
|
* The y center of this frame, floored.
|
|
*
|
|
* @name Phaser.Textures.Frame#centerY
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.centerY;
|
|
|
|
/**
|
|
* The horizontal pivot point of this Frame.
|
|
*
|
|
* @name Phaser.Textures.Frame#pivotX
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.pivotX = 0;
|
|
|
|
/**
|
|
* The vertical pivot point of this Frame.
|
|
*
|
|
* @name Phaser.Textures.Frame#pivotY
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.pivotY = 0;
|
|
|
|
/**
|
|
* Does this Frame have a custom pivot point?
|
|
*
|
|
* @name Phaser.Textures.Frame#customPivot
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
this.customPivot = false;
|
|
|
|
/**
|
|
* **CURRENTLY UNSUPPORTED**
|
|
*
|
|
* Is this frame is rotated or not in the Texture?
|
|
* Rotation allows you to use rotated frames in texture atlas packing.
|
|
* It has nothing to do with Sprite rotation.
|
|
*
|
|
* @name Phaser.Textures.Frame#rotated
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
this.rotated = false;
|
|
|
|
/**
|
|
* Over-rides the Renderer setting.
|
|
* -1 = use Renderer Setting
|
|
* 0 = No rounding
|
|
* 1 = Round
|
|
*
|
|
* @name Phaser.Textures.Frame#autoRound
|
|
* @type {number}
|
|
* @default -1
|
|
* @since 3.0.0
|
|
*/
|
|
this.autoRound = -1;
|
|
|
|
/**
|
|
* Any Frame specific custom data can be stored here.
|
|
*
|
|
* @name Phaser.Textures.Frame#customData
|
|
* @type {object}
|
|
* @since 3.0.0
|
|
*/
|
|
this.customData = {};
|
|
|
|
/**
|
|
* WebGL UV u0 value.
|
|
*
|
|
* @name Phaser.Textures.Frame#u0
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.11.0
|
|
*/
|
|
this.u0 = 0;
|
|
|
|
/**
|
|
* WebGL UV v0 value.
|
|
*
|
|
* @name Phaser.Textures.Frame#v0
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.11.0
|
|
*/
|
|
this.v0 = 0;
|
|
|
|
/**
|
|
* WebGL UV u1 value.
|
|
*
|
|
* @name Phaser.Textures.Frame#u1
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.11.0
|
|
*/
|
|
this.u1 = 0;
|
|
|
|
/**
|
|
* WebGL UV v1 value.
|
|
*
|
|
* @name Phaser.Textures.Frame#v1
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.11.0
|
|
*/
|
|
this.v1 = 0;
|
|
|
|
/**
|
|
* The un-modified source frame, trim and UV data.
|
|
*
|
|
* @name Phaser.Textures.Frame#data
|
|
* @type {object}
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
this.data = {
|
|
cut: {
|
|
x: 0,
|
|
y: 0,
|
|
w: 0,
|
|
h: 0,
|
|
r: 0,
|
|
b: 0
|
|
},
|
|
trim: false,
|
|
sourceSize: {
|
|
w: 0,
|
|
h: 0
|
|
},
|
|
spriteSourceSize: {
|
|
x: 0,
|
|
y: 0,
|
|
w: 0,
|
|
h: 0,
|
|
r: 0,
|
|
b: 0
|
|
},
|
|
radius: 0,
|
|
drawImage: {
|
|
x: 0,
|
|
y: 0,
|
|
width: 0,
|
|
height: 0
|
|
}
|
|
};
|
|
|
|
this.setSize(width, height, x, y);
|
|
},
|
|
|
|
/**
|
|
* Sets the width, height, x and y of this Frame.
|
|
*
|
|
* This is called automatically by the constructor
|
|
* and should rarely be changed on-the-fly.
|
|
*
|
|
* @method Phaser.Textures.Frame#setSize
|
|
* @since 3.7.0
|
|
*
|
|
* @param {number} width - The width of the frame before being trimmed.
|
|
* @param {number} height - The height of the frame before being trimmed.
|
|
* @param {number} [x=0] - The x coordinate of the top-left of this Frame.
|
|
* @param {number} [y=0] - The y coordinate of the top-left of this Frame.
|
|
*
|
|
* @return {this} This Frame object.
|
|
*/
|
|
setSize: function (width, height, x, y)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = 0; }
|
|
|
|
this.cutX = x;
|
|
this.cutY = y;
|
|
this.cutWidth = width;
|
|
this.cutHeight = height;
|
|
|
|
this.width = width;
|
|
this.height = height;
|
|
|
|
this.halfWidth = Math.floor(width * 0.5);
|
|
this.halfHeight = Math.floor(height * 0.5);
|
|
|
|
this.centerX = Math.floor(width / 2);
|
|
this.centerY = Math.floor(height / 2);
|
|
|
|
var data = this.data;
|
|
var cut = data.cut;
|
|
|
|
cut.x = x;
|
|
cut.y = y;
|
|
cut.w = width;
|
|
cut.h = height;
|
|
cut.r = x + width;
|
|
cut.b = y + height;
|
|
|
|
data.sourceSize.w = width;
|
|
data.sourceSize.h = height;
|
|
|
|
data.spriteSourceSize.w = width;
|
|
data.spriteSourceSize.h = height;
|
|
|
|
data.radius = 0.5 * Math.sqrt(width * width + height * height);
|
|
|
|
var drawImage = data.drawImage;
|
|
|
|
drawImage.x = x;
|
|
drawImage.y = y;
|
|
drawImage.width = width;
|
|
drawImage.height = height;
|
|
|
|
return this.updateUVs();
|
|
},
|
|
|
|
/**
|
|
* If the frame was trimmed when added to the Texture Atlas, this records the trim and source data.
|
|
*
|
|
* @method Phaser.Textures.Frame#setTrim
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} actualWidth - The width of the frame before being trimmed.
|
|
* @param {number} actualHeight - The height of the frame before being trimmed.
|
|
* @param {number} destX - The destination X position of the trimmed frame for display.
|
|
* @param {number} destY - The destination Y position of the trimmed frame for display.
|
|
* @param {number} destWidth - The destination width of the trimmed frame for display.
|
|
* @param {number} destHeight - The destination height of the trimmed frame for display.
|
|
*
|
|
* @return {this} This Frame object.
|
|
*/
|
|
setTrim: function (actualWidth, actualHeight, destX, destY, destWidth, destHeight)
|
|
{
|
|
var data = this.data;
|
|
var ss = data.spriteSourceSize;
|
|
|
|
// Store actual values
|
|
|
|
data.trim = true;
|
|
|
|
data.sourceSize.w = actualWidth;
|
|
data.sourceSize.h = actualHeight;
|
|
|
|
ss.x = destX;
|
|
ss.y = destY;
|
|
ss.w = destWidth;
|
|
ss.h = destHeight;
|
|
ss.r = destX + destWidth;
|
|
ss.b = destY + destHeight;
|
|
|
|
// Adjust properties
|
|
this.x = destX;
|
|
this.y = destY;
|
|
|
|
this.width = destWidth;
|
|
this.height = destHeight;
|
|
|
|
this.halfWidth = destWidth * 0.5;
|
|
this.halfHeight = destHeight * 0.5;
|
|
|
|
this.centerX = Math.floor(destWidth / 2);
|
|
this.centerY = Math.floor(destHeight / 2);
|
|
|
|
return this.updateUVs();
|
|
},
|
|
|
|
/**
|
|
* Takes a crop data object and, based on the rectangular region given, calculates the
|
|
* required UV coordinates in order to crop this Frame for WebGL and Canvas rendering.
|
|
*
|
|
* This is called directly by the Game Object Texture Components `setCrop` method.
|
|
* Please use that method to crop a Game Object.
|
|
*
|
|
* @method Phaser.Textures.Frame#setCropUVs
|
|
* @since 3.11.0
|
|
*
|
|
* @param {object} crop - The crop data object. This is the `GameObject._crop` property.
|
|
* @param {number} x - The x coordinate to start the crop from. Cannot be negative or exceed the Frame width.
|
|
* @param {number} y - The y coordinate to start the crop from. Cannot be negative or exceed the Frame height.
|
|
* @param {number} width - The width of the crop rectangle. Cannot exceed the Frame width.
|
|
* @param {number} height - The height of the crop rectangle. Cannot exceed the Frame height.
|
|
* @param {boolean} flipX - Does the parent Game Object have flipX set?
|
|
* @param {boolean} flipY - Does the parent Game Object have flipY set?
|
|
*
|
|
* @return {object} The updated crop data object.
|
|
*/
|
|
setCropUVs: function (crop, x, y, width, height, flipX, flipY)
|
|
{
|
|
// Clamp the input values
|
|
|
|
var cx = this.cutX;
|
|
var cy = this.cutY;
|
|
var cw = this.cutWidth;
|
|
var ch = this.cutHeight;
|
|
var rw = this.realWidth;
|
|
var rh = this.realHeight;
|
|
|
|
x = Clamp(x, 0, rw);
|
|
y = Clamp(y, 0, rh);
|
|
|
|
width = Clamp(width, 0, rw - x);
|
|
height = Clamp(height, 0, rh - y);
|
|
|
|
var ox = cx + x;
|
|
var oy = cy + y;
|
|
var ow = width;
|
|
var oh = height;
|
|
|
|
var data = this.data;
|
|
|
|
if (data.trim)
|
|
{
|
|
var ss = data.spriteSourceSize;
|
|
|
|
// Need to check for intersection between the cut area and the crop area
|
|
// If there is none, we set UV to be empty, otherwise set it to be the intersection area
|
|
|
|
width = Clamp(width, 0, cw - x);
|
|
height = Clamp(height, 0, ch - y);
|
|
|
|
var cropRight = x + width;
|
|
var cropBottom = y + height;
|
|
|
|
var intersects = !(ss.r < x || ss.b < y || ss.x > cropRight || ss.y > cropBottom);
|
|
|
|
if (intersects)
|
|
{
|
|
var ix = Math.max(ss.x, x);
|
|
var iy = Math.max(ss.y, y);
|
|
var iw = Math.min(ss.r, cropRight) - ix;
|
|
var ih = Math.min(ss.b, cropBottom) - iy;
|
|
|
|
ow = iw;
|
|
oh = ih;
|
|
|
|
if (flipX)
|
|
{
|
|
ox = cx + (cw - (ix - ss.x) - iw);
|
|
}
|
|
else
|
|
{
|
|
ox = cx + (ix - ss.x);
|
|
}
|
|
|
|
if (flipY)
|
|
{
|
|
oy = cy + (ch - (iy - ss.y) - ih);
|
|
}
|
|
else
|
|
{
|
|
oy = cy + (iy - ss.y);
|
|
}
|
|
|
|
x = ix;
|
|
y = iy;
|
|
|
|
width = iw;
|
|
height = ih;
|
|
}
|
|
else
|
|
{
|
|
ox = 0;
|
|
oy = 0;
|
|
ow = 0;
|
|
oh = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (flipX)
|
|
{
|
|
ox = cx + (cw - x - width);
|
|
}
|
|
|
|
if (flipY)
|
|
{
|
|
oy = cy + (ch - y - height);
|
|
}
|
|
}
|
|
|
|
var tw = this.source.width;
|
|
var th = this.source.height;
|
|
|
|
// Map the given coordinates into UV space, clamping to the 0-1 range.
|
|
|
|
crop.u0 = Math.max(0, ox / tw);
|
|
crop.v0 = Math.max(0, oy / th);
|
|
crop.u1 = Math.min(1, (ox + ow) / tw);
|
|
crop.v1 = Math.min(1, (oy + oh) / th);
|
|
|
|
crop.x = x;
|
|
crop.y = y;
|
|
|
|
crop.cx = ox;
|
|
crop.cy = oy;
|
|
crop.cw = ow;
|
|
crop.ch = oh;
|
|
|
|
crop.width = width;
|
|
crop.height = height;
|
|
|
|
crop.flipX = flipX;
|
|
crop.flipY = flipY;
|
|
|
|
return crop;
|
|
},
|
|
|
|
/**
|
|
* Takes a crop data object and recalculates the UVs based on the dimensions inside the crop object.
|
|
* Called automatically by `setFrame`.
|
|
*
|
|
* @method Phaser.Textures.Frame#updateCropUVs
|
|
* @since 3.11.0
|
|
*
|
|
* @param {object} crop - The crop data object. This is the `GameObject._crop` property.
|
|
* @param {boolean} flipX - Does the parent Game Object have flipX set?
|
|
* @param {boolean} flipY - Does the parent Game Object have flipY set?
|
|
*
|
|
* @return {object} The updated crop data object.
|
|
*/
|
|
updateCropUVs: function (crop, flipX, flipY)
|
|
{
|
|
return this.setCropUVs(crop, crop.x, crop.y, crop.width, crop.height, flipX, flipY);
|
|
},
|
|
|
|
/**
|
|
* Directly sets the canvas and WebGL UV data for this frame.
|
|
*
|
|
* Use this if you need to override the values that are generated automatically
|
|
* when the Frame is created.
|
|
*
|
|
* @method Phaser.Textures.Frame#setUVs
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number} width - Width of this frame for the Canvas data.
|
|
* @param {number} height - Height of this frame for the Canvas data.
|
|
* @param {number} u0 - UV u0 value.
|
|
* @param {number} v0 - UV v0 value.
|
|
* @param {number} u1 - UV u1 value.
|
|
* @param {number} v1 - UV v1 value.
|
|
*
|
|
* @return {this} This Frame object.
|
|
*/
|
|
setUVs: function (width, height, u0, v0, u1, v1)
|
|
{
|
|
// Canvas data
|
|
|
|
var cd = this.data.drawImage;
|
|
|
|
cd.width = width;
|
|
cd.height = height;
|
|
|
|
// WebGL data
|
|
|
|
this.u0 = u0;
|
|
this.v0 = v0;
|
|
|
|
this.u1 = u1;
|
|
this.v1 = v1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Updates the internal WebGL UV cache and the drawImage cache.
|
|
*
|
|
* @method Phaser.Textures.Frame#updateUVs
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Frame object.
|
|
*/
|
|
updateUVs: function ()
|
|
{
|
|
var cx = this.cutX;
|
|
var cy = this.cutY;
|
|
var cw = this.cutWidth;
|
|
var ch = this.cutHeight;
|
|
|
|
// Canvas data
|
|
|
|
var cd = this.data.drawImage;
|
|
|
|
cd.width = cw;
|
|
cd.height = ch;
|
|
|
|
// WebGL data
|
|
|
|
var tw = this.source.width;
|
|
var th = this.source.height;
|
|
|
|
this.u0 = cx / tw;
|
|
this.v0 = cy / th;
|
|
|
|
this.u1 = (cx + cw) / tw;
|
|
this.v1 = (cy + ch) / th;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Updates the internal WebGL UV cache.
|
|
*
|
|
* @method Phaser.Textures.Frame#updateUVsInverted
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Frame object.
|
|
*/
|
|
updateUVsInverted: function ()
|
|
{
|
|
var tw = this.source.width;
|
|
var th = this.source.height;
|
|
|
|
this.u0 = (this.cutX + this.cutHeight) / tw;
|
|
this.v0 = this.cutY / th;
|
|
|
|
this.u1 = this.cutX / tw;
|
|
this.v1 = (this.cutY + this.cutWidth) / th;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Clones this Frame into a new Frame object.
|
|
*
|
|
* @method Phaser.Textures.Frame#clone
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Textures.Frame} A clone of this Frame.
|
|
*/
|
|
clone: function ()
|
|
{
|
|
var clone = new Frame(this.texture, this.name, this.sourceIndex);
|
|
|
|
clone.cutX = this.cutX;
|
|
clone.cutY = this.cutY;
|
|
clone.cutWidth = this.cutWidth;
|
|
clone.cutHeight = this.cutHeight;
|
|
|
|
clone.x = this.x;
|
|
clone.y = this.y;
|
|
|
|
clone.width = this.width;
|
|
clone.height = this.height;
|
|
|
|
clone.halfWidth = this.halfWidth;
|
|
clone.halfHeight = this.halfHeight;
|
|
|
|
clone.centerX = this.centerX;
|
|
clone.centerY = this.centerY;
|
|
|
|
clone.rotated = this.rotated;
|
|
|
|
clone.data = Extend(true, clone.data, this.data);
|
|
|
|
clone.updateUVs();
|
|
|
|
return clone;
|
|
},
|
|
|
|
/**
|
|
* Destroys this Frame by nulling its reference to the parent Texture and and data objects.
|
|
*
|
|
* @method Phaser.Textures.Frame#destroy
|
|
* @since 3.0.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.source = null;
|
|
this.texture = null;
|
|
this.glTexture = null;
|
|
this.customData = null;
|
|
this.data = null;
|
|
},
|
|
|
|
/**
|
|
* The width of the Frame in its un-trimmed, un-padded state, as prepared in the art package,
|
|
* before being packed.
|
|
*
|
|
* @name Phaser.Textures.Frame#realWidth
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
realWidth: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.data.sourceSize.w;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The height of the Frame in its un-trimmed, un-padded state, as prepared in the art package,
|
|
* before being packed.
|
|
*
|
|
* @name Phaser.Textures.Frame#realHeight
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
realHeight: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.data.sourceSize.h;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The radius of the Frame (derived from sqrt(w * w + h * h) / 2)
|
|
*
|
|
* @name Phaser.Textures.Frame#radius
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
radius: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.data.radius;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Is the Frame trimmed or not?
|
|
*
|
|
* @name Phaser.Textures.Frame#trimmed
|
|
* @type {boolean}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
trimmed: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.data.trim;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The Canvas drawImage data object.
|
|
*
|
|
* @name Phaser.Textures.Frame#canvasData
|
|
* @type {object}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
canvasData: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.data.drawImage;
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = Frame;
|
|
|
|
|
|
/***/ }),
|
|
/* 69 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var BuildGameObject = __webpack_require__(70);
|
|
var Class = __webpack_require__(0);
|
|
var GetValue = __webpack_require__(10);
|
|
var ResizeEvent = __webpack_require__(184);
|
|
var ScenePlugin = __webpack_require__(185);
|
|
var SpineCanvas = __webpack_require__(209);
|
|
var SpineWebgl = __webpack_require__(210);
|
|
var Spine = {
|
|
canvas: SpineCanvas,
|
|
webgl: SpineWebgl
|
|
};
|
|
var SpineFile = __webpack_require__(211);
|
|
var SpineGameObject = __webpack_require__(227);
|
|
var SpineContainer = __webpack_require__(260);
|
|
var NOOP = __webpack_require__(2);
|
|
|
|
/**
|
|
* @classdesc
|
|
* The Spine Plugin is a Scene based plugin that handles the creation and rendering of Spine Game Objects.
|
|
*
|
|
* Find more details about Spine itself at http://esotericsoftware.com/.
|
|
*
|
|
* All rendering and object creation is handled via the official Spine Runtimes. This version of the plugin
|
|
* uses the Spine 3.8.95 runtimes. Please note that due to the way the Spine runtimes use semver, you will
|
|
* get breaking changes in point-releases. Therefore, files created in a different version of Spine may not
|
|
* work as a result, without you first updating the runtimes and rebuilding the plugin.
|
|
*
|
|
* Esoteric themselves recommend that you freeze your Spine editor version against the runtime versions.
|
|
* You can find more information about this here: http://esotericsoftware.com/spine-settings#Version
|
|
*
|
|
* Please note that you require a Spine license in order to use Spine Runtimes in your games.
|
|
*
|
|
* You can install this plugin into your Phaser game by either importing it, if you're using ES6:
|
|
*
|
|
* ```javascript
|
|
* import * as SpinePlugin from './SpinePlugin.js';
|
|
* ```
|
|
*
|
|
* and then adding it to your Phaser Game configuration:
|
|
*
|
|
* ```javascript
|
|
* plugins: {
|
|
* scene: [
|
|
* { key: 'SpinePlugin', plugin: window.SpinePlugin, mapping: 'spine' }
|
|
* ]
|
|
* }
|
|
* ```
|
|
*
|
|
* If you're using ES5 then you can load the Spine Plugin in a Scene files payload, _within_ your
|
|
* Game Configuration object, like this:
|
|
*
|
|
* ```javascript
|
|
* scene: {
|
|
* preload: preload,
|
|
* create: create,
|
|
* pack: {
|
|
* files: [
|
|
* { type: 'scenePlugin', key: 'SpinePlugin', url: 'plugins/SpinePlugin.js', sceneKey: 'spine' }
|
|
* ]
|
|
* }
|
|
* }
|
|
* ```
|
|
*
|
|
* Loading it like this allows you to then use commands such as `this.load.spine` from within the
|
|
* same Scene. Alternatively, you can use the method `this.load.plugin` to load the plugin via the normal
|
|
* Phaser Loader. However, doing so will not add it to the current Scene. It will be available from any
|
|
* subsequent Scenes.
|
|
*
|
|
* ## A note about inlined data:
|
|
*
|
|
* If you need to load Spine assets from inline / base64 encoded data, then you should not use the Loader
|
|
* at all. Instead, call the functions directly as required:
|
|
*
|
|
* scene.cache.json.add
|
|
* scene.cache.custom.spine.add
|
|
* scene.textures.addBase64
|
|
*
|
|
* ## Using the plugin
|
|
*
|
|
* Assuming a default environment you access it from within a Scene by using the `this.spine` reference.
|
|
*
|
|
* When this plugin is installed into a Scene it will add a Loader File Type, allowing you to load
|
|
* Spine files directly, i.e.:
|
|
*
|
|
* ```javascript
|
|
* this.load.spine('stretchyman', 'stretchyman-pro.json', [ 'stretchyman-pma.atlas' ], true);
|
|
* ```
|
|
*
|
|
* It also installs two Game Object Factory methods, allowing you to create Spine Game Objects
|
|
* and Spine Containers:
|
|
*
|
|
* ```javascript
|
|
* const man = this.add.spine(512, 650, 'stretchyman');
|
|
*
|
|
* const container = this.add.spineContainer();
|
|
*
|
|
* container.add(man);
|
|
* ```
|
|
*
|
|
* The first argument is the key which you used when importing the Spine data. There are lots of
|
|
* things you can specify, such as the animation name, skeleton, slot attachments and more. Please
|
|
* see the respective documentation and examples for further details.
|
|
*
|
|
* Phaser expects the Spine data to be exported from the Spine application in a JSON format, not binary.
|
|
* The associated atlas files are scanned for any texture files present in them, which are then loaded.
|
|
* If you have exported your Spine data with preMultipliedAlpha set, then you should enable this in the
|
|
* load arguments, or you may see black outlines around skeleton textures.
|
|
*
|
|
* The Spine plugin is local to the Scene in which it is installed. This means a change to something,
|
|
* such as the Skeleton Debug Renderer, in this Scene, will not impact the renderer in any other Scene.
|
|
* The only exception to this is with the caches this plugin creates. Spine atlas and texture data are
|
|
* stored in their own caches, which are global, meaning they're accessible from any Scene in your
|
|
* game, regardless if the Scene loaded the Spine data or not.
|
|
*
|
|
* When destroying a Phaser Game instance, if you need to re-create it again on the same page without
|
|
* reloading, you must remember to remove the Spine Plugin as part of your tear-down process:
|
|
*
|
|
* ```javascript
|
|
* this.plugins.removeScenePlugin('SpinePlugin');
|
|
* ```
|
|
*
|
|
* For details about the Spine Runtime API see http://esotericsoftware.com/spine-api-reference
|
|
*
|
|
* @class SpinePlugin
|
|
* @extends Phaser.Plugins.ScenePlugin
|
|
* @constructor
|
|
* @since 3.19.0
|
|
*
|
|
* @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin.
|
|
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Phaser Plugin Manager.
|
|
* @param {string} pluginKey - The key under which this plugin has been installed into the Scene Systems.
|
|
*/
|
|
var SpinePlugin = new Class({
|
|
|
|
Extends: ScenePlugin,
|
|
|
|
initialize:
|
|
|
|
function SpinePlugin (scene, pluginManager, pluginKey)
|
|
{
|
|
ScenePlugin.call(this, scene, pluginManager, pluginKey);
|
|
|
|
var game = pluginManager.game;
|
|
|
|
/**
|
|
* A read-only flag that indicates if the game is running under WebGL or Canvas.
|
|
*
|
|
* @name SpinePlugin#isWebGL
|
|
* @type {boolean}
|
|
* @readonly
|
|
* @since 3.19.0
|
|
*/
|
|
this.isWebGL = (game.config.renderType === 2);
|
|
|
|
/**
|
|
* A custom cache that stores the Spine atlas data.
|
|
*
|
|
* This cache is global across your game, allowing you to access Spine data loaded from other Scenes,
|
|
* no matter which Scene you are in.
|
|
*
|
|
* @name SpinePlugin#cache
|
|
* @type {Phaser.Cache.BaseCache}
|
|
* @since 3.19.0
|
|
*/
|
|
this.cache = game.cache.addCustom('spine');
|
|
|
|
/**
|
|
* A custom cache that stores the Spine Textures.
|
|
*
|
|
* This cache is global across your game, allowing you to access Spine data loaded from other Scenes,
|
|
* no matter which Scene you are in.
|
|
*
|
|
* @name SpinePlugin#spineTextures
|
|
* @type {Phaser.Cache.BaseCache}
|
|
* @since 3.19.0
|
|
*/
|
|
this.spineTextures = game.cache.addCustom('spineTextures');
|
|
|
|
/**
|
|
* A reference to the global JSON Cache.
|
|
*
|
|
* @name SpinePlugin#json
|
|
* @type {Phaser.Cache.BaseCache}
|
|
* @since 3.19.0
|
|
*/
|
|
this.json = game.cache.json;
|
|
|
|
/**
|
|
* A reference to the global Texture Manager.
|
|
*
|
|
* @name SpinePlugin#textures
|
|
* @type {Phaser.Textures.TextureManager}
|
|
* @since 3.19.0
|
|
*/
|
|
this.textures = game.textures;
|
|
|
|
/**
|
|
* A flag that sets if the Skeleton Renderers will render debug information over the top
|
|
* of the skeleton or not.
|
|
*
|
|
* @name SpinePlugin#drawDebug
|
|
* @type {boolean}
|
|
* @since 3.19.0
|
|
*/
|
|
this.drawDebug = false;
|
|
|
|
/**
|
|
* The underlying WebGL context of the Phaser renderer.
|
|
*
|
|
* Only set if running in WebGL mode.
|
|
*
|
|
* @name SpinePlugin#gl
|
|
* @type {WebGLRenderingContext}
|
|
* @since 3.19.0
|
|
*/
|
|
this.gl;
|
|
|
|
/**
|
|
* A reference to either the Canvas or WebGL Renderer that this Game is using.
|
|
*
|
|
* @name SpinePlugin#renderer
|
|
* @type {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)}
|
|
* @since 3.19.0
|
|
*/
|
|
this.renderer;
|
|
|
|
/**
|
|
* An instance of the Spine WebGL Scene Renderer.
|
|
*
|
|
* There is only one instance of the Scene Renderer shared across the whole plugin.
|
|
*
|
|
* Only set if running in WebGL mode.
|
|
*
|
|
* @name SpinePlugin#sceneRenderer
|
|
* @type {spine.webgl.SceneRenderer}
|
|
* @since 3.19.0
|
|
*/
|
|
this.sceneRenderer;
|
|
|
|
/**
|
|
* An instance of the Spine Skeleton Renderer.
|
|
*
|
|
* @name SpinePlugin#skeletonRenderer
|
|
* @type {(spine.canvas.SkeletonRenderer|spine.webgl.SkeletonRenderer)}
|
|
* @since 3.19.0
|
|
*/
|
|
this.skeletonRenderer;
|
|
|
|
/**
|
|
* An instance of the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only set if running in WebGL mode.
|
|
*
|
|
* @name SpinePlugin#skeletonDebugRenderer
|
|
* @type {spine.webgl.skeletonDebugRenderer}
|
|
* @since 3.19.0
|
|
*/
|
|
this.skeletonDebugRenderer;
|
|
|
|
/**
|
|
* A reference to the Spine runtime.
|
|
* This is the runtime created by Esoteric Software.
|
|
*
|
|
* @name SpinePlugin#plugin
|
|
* @type {spine}
|
|
* @since 3.19.0
|
|
*/
|
|
this.plugin = Spine;
|
|
|
|
/**
|
|
* An internal vector3 used by the screen to world method.
|
|
*
|
|
* @name SpinePlugin#temp1
|
|
* @private
|
|
* @type {spine.webgl.Vector3}
|
|
* @since 3.19.0
|
|
*/
|
|
this.temp1;
|
|
|
|
/**
|
|
* An internal vector3 used by the screen to world method.
|
|
*
|
|
* @name SpinePlugin#temp2
|
|
* @private
|
|
* @type {spine.webgl.Vector3}
|
|
* @since 3.19.0
|
|
*/
|
|
this.temp2;
|
|
|
|
if (this.isWebGL)
|
|
{
|
|
this.runtime = Spine.webgl;
|
|
|
|
this.renderer = game.renderer;
|
|
this.gl = game.renderer.gl;
|
|
|
|
this.getAtlas = this.getAtlasWebGL;
|
|
}
|
|
else
|
|
{
|
|
this.runtime = Spine.canvas;
|
|
|
|
this.renderer = game.renderer;
|
|
|
|
this.getAtlas = this.getAtlasCanvas;
|
|
}
|
|
|
|
// Headless mode?
|
|
if (!this.renderer)
|
|
{
|
|
this.renderer = {
|
|
width: game.scale.width,
|
|
height: game.scale.height,
|
|
preRender: NOOP,
|
|
postRender: NOOP,
|
|
render: NOOP,
|
|
destroy: NOOP
|
|
};
|
|
}
|
|
|
|
var add = function (x, y, key, animationName, loop)
|
|
{
|
|
var spinePlugin = this.scene.sys[pluginKey];
|
|
var spineGO = new SpineGameObject(this.scene, spinePlugin, x, y, key, animationName, loop);
|
|
|
|
this.displayList.add(spineGO);
|
|
this.updateList.add(spineGO);
|
|
|
|
return spineGO;
|
|
};
|
|
|
|
var make = function (config, addToScene)
|
|
{
|
|
if (config === undefined) { config = {}; }
|
|
|
|
var key = GetValue(config, 'key', null);
|
|
var animationName = GetValue(config, 'animationName', null);
|
|
var loop = GetValue(config, 'loop', false);
|
|
|
|
var spinePlugin = this.scene.sys[pluginKey];
|
|
var spineGO = new SpineGameObject(this.scene, spinePlugin, 0, 0, key, animationName, loop);
|
|
|
|
if (addToScene !== undefined)
|
|
{
|
|
config.add = addToScene;
|
|
}
|
|
|
|
BuildGameObject(this.scene, spineGO, config);
|
|
|
|
// Spine specific
|
|
var skinName = GetValue(config, 'skinName', false);
|
|
|
|
if (skinName)
|
|
{
|
|
spineGO.setSkinByName(skinName);
|
|
}
|
|
|
|
var slotName = GetValue(config, 'slotName', false);
|
|
var attachmentName = GetValue(config, 'attachmentName', null);
|
|
|
|
if (slotName)
|
|
{
|
|
spineGO.setAttachment(slotName, attachmentName);
|
|
}
|
|
|
|
return spineGO.refresh();
|
|
};
|
|
|
|
var addContainer = function (x, y, children)
|
|
{
|
|
var spinePlugin = this.scene.sys[pluginKey];
|
|
var spineGO = new SpineContainer(this.scene, spinePlugin, x, y, children);
|
|
|
|
this.displayList.add(spineGO);
|
|
|
|
return spineGO;
|
|
};
|
|
|
|
var makeContainer = function (config, addToScene)
|
|
{
|
|
if (config === undefined) { config = {}; }
|
|
|
|
var x = GetValue(config, 'x', 0);
|
|
var y = GetValue(config, 'y', 0);
|
|
var children = GetValue(config, 'children', null);
|
|
|
|
var spinePlugin = this.scene.sys[pluginKey];
|
|
var container = new SpineContainer(this.scene, spinePlugin, x, y, children);
|
|
|
|
if (addToScene !== undefined)
|
|
{
|
|
config.add = addToScene;
|
|
}
|
|
|
|
BuildGameObject(this.scene, container, config);
|
|
|
|
return container;
|
|
};
|
|
|
|
pluginManager.registerFileType('spine', this.spineFileCallback, scene);
|
|
pluginManager.registerGameObject('spine', add, make);
|
|
pluginManager.registerGameObject('spineContainer', addContainer, makeContainer);
|
|
},
|
|
|
|
/**
|
|
* Internal boot handler.
|
|
*
|
|
* @method SpinePlugin#boot
|
|
* @private
|
|
* @since 3.19.0
|
|
*/
|
|
boot: function ()
|
|
{
|
|
if (this.isWebGL)
|
|
{
|
|
this.bootWebGL();
|
|
this.onResize();
|
|
this.game.scale.on(ResizeEvent, this.onResize, this);
|
|
}
|
|
else
|
|
{
|
|
this.bootCanvas();
|
|
}
|
|
|
|
var eventEmitter = this.systems.events;
|
|
|
|
eventEmitter.once('shutdown', this.shutdown, this);
|
|
eventEmitter.once('destroy', this.destroy, this);
|
|
|
|
this.game.events.once('destroy', this.gameDestroy, this);
|
|
},
|
|
|
|
/**
|
|
* Internal boot handler for the Canvas Renderer.
|
|
*
|
|
* @method SpinePlugin#bootCanvas
|
|
* @private
|
|
* @since 3.19.0
|
|
*/
|
|
bootCanvas: function ()
|
|
{
|
|
this.skeletonRenderer = new Spine.canvas.SkeletonRenderer(this.scene.sys.context);
|
|
},
|
|
|
|
/**
|
|
* Internal boot handler for the WebGL Renderer.
|
|
*
|
|
* @method SpinePlugin#bootWebGL
|
|
* @private
|
|
* @since 3.19.0
|
|
*/
|
|
bootWebGL: function ()
|
|
{
|
|
var sceneRenderer = this.renderer.spineSceneRenderer;
|
|
|
|
if (!sceneRenderer)
|
|
{
|
|
sceneRenderer = new Spine.webgl.SceneRenderer(this.renderer.canvas, this.gl, true);
|
|
|
|
this.renderer.spineSceneRenderer = sceneRenderer;
|
|
}
|
|
|
|
// All scene share the same instance
|
|
this.sceneRenderer = sceneRenderer;
|
|
this.skeletonRenderer = sceneRenderer.skeletonRenderer;
|
|
this.skeletonDebugRenderer = sceneRenderer.skeletonDebugRenderer;
|
|
|
|
this.temp1 = new Spine.webgl.Vector3(0, 0, 0);
|
|
this.temp2 = new Spine.webgl.Vector3(0, 0, 0);
|
|
},
|
|
|
|
/**
|
|
* Gets a loaded Spine Atlas from the cache and creates a new Spine Texture Atlas,
|
|
* then returns it. You do not normally need to invoke this method directly.
|
|
*
|
|
* @method SpinePlugin#getAtlasCanvas
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} key - The key of the Spine Atlas to create.
|
|
*
|
|
* @return {spine.TextureAtlas} The Spine Texture Atlas, or undefined if the given key wasn't found.
|
|
*/
|
|
getAtlasCanvas: function (key)
|
|
{
|
|
var atlasEntry = this.cache.get(key);
|
|
|
|
if (!atlasEntry)
|
|
{
|
|
console.warn('No atlas data for: ' + key);
|
|
return;
|
|
}
|
|
|
|
var atlas;
|
|
var spineTextures = this.spineTextures;
|
|
|
|
if (spineTextures.has(key))
|
|
{
|
|
atlas = spineTextures.get(key);
|
|
}
|
|
else
|
|
{
|
|
var textures = this.textures;
|
|
|
|
atlas = new this.runtime.TextureAtlas(atlasEntry.data, function (path)
|
|
{
|
|
return new Spine.canvas.CanvasTexture(textures.get(atlasEntry.prefix + path).getSourceImage());
|
|
});
|
|
}
|
|
|
|
return atlas;
|
|
},
|
|
|
|
/**
|
|
* Gets a loaded Spine Atlas from the cache and creates a new Spine Texture Atlas,
|
|
* then returns it. You do not normally need to invoke this method directly.
|
|
*
|
|
* @method SpinePlugin#getAtlasWebGL
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} key - The key of the Spine Atlas to create.
|
|
*
|
|
* @return {spine.TextureAtlas} The Spine Texture Atlas, or undefined if the given key wasn't found.
|
|
*/
|
|
getAtlasWebGL: function (key)
|
|
{
|
|
var atlasEntry = this.cache.get(key);
|
|
|
|
if (!atlasEntry)
|
|
{
|
|
console.warn('No atlas data for: ' + key);
|
|
return;
|
|
}
|
|
|
|
var atlas;
|
|
var spineTextures = this.spineTextures;
|
|
|
|
if (spineTextures.has(key))
|
|
{
|
|
atlas = spineTextures.get(key);
|
|
}
|
|
else
|
|
{
|
|
var textures = this.textures;
|
|
|
|
var gl = this.sceneRenderer.context.gl;
|
|
|
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
|
|
atlas = new this.runtime.TextureAtlas(atlasEntry.data, function (path)
|
|
{
|
|
return new Spine.webgl.GLTexture(gl, textures.get(atlasEntry.prefix + path).getSourceImage(), false);
|
|
});
|
|
}
|
|
|
|
return atlas;
|
|
},
|
|
|
|
/**
|
|
* Adds a Spine Skeleton and Atlas file, or array of files, to the current load queue.
|
|
*
|
|
* You can call this method from within your Scene's `preload`, along with any other files you wish to load:
|
|
*
|
|
* ```javascript
|
|
* function preload ()
|
|
* {
|
|
* this.load.spine('spineBoy', 'boy.json', 'boy.atlas', true);
|
|
* }
|
|
* ```
|
|
*
|
|
* The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts,
|
|
* or if it's already running, when the next free load slot becomes available. This happens automatically if you
|
|
* are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued
|
|
* it means you cannot use the file immediately after calling this method, but must wait for the file to complete.
|
|
* The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the
|
|
* Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been
|
|
* loaded.
|
|
*
|
|
* If you call this from outside of `preload` then you are responsible for starting the Loader afterwards and monitoring
|
|
* its events to know when it's safe to use the asset. Please see the Phaser.Loader.LoaderPlugin class for more details.
|
|
*
|
|
* Phaser expects the Spine data to be exported from the Spine application in a JSON format, not binary. The associated
|
|
* atlas files are scanned for any texture files present in them, which are then loaded. If you have exported
|
|
* your Spine data with preMultipliedAlpha set, then you should enable this in the arguments, or you may see black
|
|
* outlines around skeleton textures.
|
|
*
|
|
* The key must be a unique String. It is used to add the file to the global Spine cache upon a successful load.
|
|
* The key should be unique both in terms of files being loaded and files already present in the Spine cache.
|
|
* Loading a file using a key that is already taken will result in a warning.
|
|
*
|
|
* Instead of passing arguments you can pass a configuration object, such as:
|
|
*
|
|
* ```javascript
|
|
* this.load.spine({
|
|
* key: 'mainmenu',
|
|
* jsonURL: 'boy.json',
|
|
* atlasURL: 'boy.atlas',
|
|
* preMultipliedAlpha: true
|
|
* });
|
|
* ```
|
|
*
|
|
* If you need to load multiple Spine atlas files, provide them as an array:
|
|
*
|
|
* ```javascript
|
|
* function preload ()
|
|
* {
|
|
* this.load.spine('demos', 'demos.json', [ 'atlas1.atlas', 'atlas2.atlas' ], true);
|
|
* }
|
|
* ```
|
|
*
|
|
* See the documentation for `Phaser.Types.Loader.FileTypes.SpineFileConfig` for more details.
|
|
*
|
|
* If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files
|
|
* key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and
|
|
* this is what you would use to retrieve the data from the Spine plugin.
|
|
*
|
|
* The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it.
|
|
*
|
|
* If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien"
|
|
* and no URL is given then the Loader will set the URL to be "alien.json". It will always add `.json` as the extension, although
|
|
* this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL.
|
|
*
|
|
* Note: The ability to load this type of file will only be available if the Spine Plugin has been built or loaded into Phaser.
|
|
*
|
|
* @method Phaser.Loader.LoaderPlugin#spine
|
|
* @fires Phaser.Loader.LoaderPlugin#ADD
|
|
* @since 3.19.0
|
|
*
|
|
* @param {(string|Phaser.Types.Loader.FileTypes.JSONFileConfig|Phaser.Types.Loader.FileTypes.JSONFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them.
|
|
* @param {string} jsonURL - The absolute or relative URL to load the Spine json file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json".
|
|
* @param {string|string[]} atlasURL - The absolute or relative URL to load the Spine atlas file from. If undefined or `null` it will be set to `<key>.atlas`, i.e. if `key` was "alien" then the URL will be "alien.atlas".
|
|
* @param {boolean} [preMultipliedAlpha=false] - Do the texture files include pre-multiplied alpha or not?
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [textureXhrSettings] - An XHR Settings configuration object for the Spine json file. Used in replacement of the Loaders default XHR Settings.
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the Spine atlas file. Used in replacement of the Loaders default XHR Settings.
|
|
* @param {object} [settings] - An external Settings configuration object { prefix: '' }
|
|
* @return {Phaser.Loader.LoaderPlugin} The Loader instance.
|
|
*/
|
|
spineFileCallback: function (key, jsonURL, atlasURL, preMultipliedAlpha, jsonXhrSettings, atlasXhrSettings, settings)
|
|
{
|
|
var multifile;
|
|
settings = settings || {};
|
|
|
|
if (Array.isArray(key))
|
|
{
|
|
for (var i = 0; i < key.length; i++)
|
|
{
|
|
multifile = new SpineFile(this, key[i]);
|
|
|
|
// Support prefix key
|
|
multifile.prefix = multifile.prefix || settings.prefix || '';
|
|
|
|
this.addFile(multifile.files);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
multifile = new SpineFile(this, key, jsonURL, atlasURL, preMultipliedAlpha, jsonXhrSettings, atlasXhrSettings);
|
|
|
|
// Support prefix key
|
|
multifile.prefix = multifile.prefix || settings.prefix || '';
|
|
|
|
this.addFile(multifile.files);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Converts the given x and y screen coordinates into the world space of the given Skeleton.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#worldToLocal
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} x - The screen space x coordinate to convert.
|
|
* @param {number} y - The screen space y coordinate to convert.
|
|
* @param {spine.Skeleton} skeleton - The Spine Skeleton to convert into.
|
|
* @param {spine.Bone} [bone] - Optional bone of the Skeleton to convert into.
|
|
*
|
|
* @return {spine.Vector2} A Vector2 containing the translated point.
|
|
*/
|
|
worldToLocal: function (x, y, skeleton, bone)
|
|
{
|
|
var temp1 = this.temp1;
|
|
var temp2 = this.temp2;
|
|
var camera = this.sceneRenderer.camera;
|
|
|
|
temp1.set(x + skeleton.x, y - skeleton.y, 0);
|
|
|
|
var width = camera.viewportWidth;
|
|
var height = camera.viewportHeight;
|
|
|
|
camera.screenToWorld(temp1, width, height);
|
|
|
|
if (bone && bone.parent !== null)
|
|
{
|
|
bone.parent.worldToLocal(temp2.set(temp1.x - skeleton.x, temp1.y - skeleton.y, 0));
|
|
|
|
return new this.runtime.Vector2(temp2.x, temp2.y);
|
|
}
|
|
else if (bone)
|
|
{
|
|
return new this.runtime.Vector2(temp1.x - skeleton.x, temp1.y - skeleton.y);
|
|
}
|
|
else
|
|
{
|
|
return new this.runtime.Vector2(temp1.x, temp1.y);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Returns a Spine Vector2 based on the given x and y values.
|
|
*
|
|
* @method SpinePlugin#getVector2
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} x - The Vector x value.
|
|
* @param {number} y - The Vector y value.
|
|
*
|
|
* @return {spine.Vector2} A Spine Vector2 based on the given values.
|
|
*/
|
|
getVector2: function (x, y)
|
|
{
|
|
return new this.runtime.Vector2(x, y);
|
|
},
|
|
|
|
/**
|
|
* Returns a Spine Vector2 based on the given x, y and z values.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#getVector3
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} x - The Vector x value.
|
|
* @param {number} y - The Vector y value.
|
|
* @param {number} z - The Vector z value.
|
|
*
|
|
* @return {spine.Vector2} A Spine Vector2 based on the given values.
|
|
*/
|
|
getVector3: function (x, y, z)
|
|
{
|
|
return new Spine.webgl.Vector3(x, y, z);
|
|
},
|
|
|
|
/**
|
|
* Sets `drawBones` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugBones
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugBones: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawBones = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets `drawRegionAttachments` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugRegionAttachments
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugRegionAttachments: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawRegionAttachments = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets `drawBoundingBoxes` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugBoundingBoxes
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugBoundingBoxes: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawBoundingBoxes = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets `drawMeshHull` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugMeshHull
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugMeshHull: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawMeshHull = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets `drawMeshTriangles` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugMeshTriangles
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugMeshTriangles: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawMeshTriangles = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets `drawPaths` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugPaths
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugPaths: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawPaths = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets `drawSkeletonXY` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugSkeletonXY
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugSkeletonXY: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawSkeletonXY = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets `drawClipping` in the Spine Skeleton Debug Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setDebugClipping
|
|
* @since 3.19.0
|
|
*
|
|
* @param {boolean} [value=true] - The value to set in the debug property.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setDebugClipping: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.skeletonDebugRenderer.drawClipping = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the given vertex effect on the Spine Skeleton Renderer.
|
|
*
|
|
* Only works in WebGL.
|
|
*
|
|
* @method SpinePlugin#setEffect
|
|
* @since 3.19.0
|
|
*
|
|
* @param {spine.VertexEffect} [effect] - The vertex effect to set on the Skeleton Renderer.
|
|
*
|
|
* @return {this} This Spine Plugin.
|
|
*/
|
|
setEffect: function (effect)
|
|
{
|
|
this.sceneRenderer.skeletonRenderer.vertexEffect = effect;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Creates a Spine Skeleton based on the given key and optional Skeleton JSON data.
|
|
*
|
|
* The Skeleton data should have already been loaded before calling this method.
|
|
*
|
|
* @method SpinePlugin#createSkeleton
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} key - The key of the Spine skeleton data, as loaded by the plugin. If the Spine JSON contains multiple skeletons, reference them with a period, i.e. `set.spineBoy`.
|
|
* @param {object} [skeletonJSON] - Optional Skeleton JSON data to use, instead of getting it from the cache.
|
|
*
|
|
* @return {(any|null)} This Spine Skeleton data object, or `null` if the key was invalid.
|
|
*/
|
|
createSkeleton: function (key, skeletonJSON)
|
|
{
|
|
var atlasKey = key;
|
|
var jsonKey = key;
|
|
var split = (key.indexOf('.') !== -1);
|
|
|
|
if (split)
|
|
{
|
|
var parts = key.split('.');
|
|
|
|
atlasKey = parts.shift();
|
|
jsonKey = parts.join('.');
|
|
}
|
|
|
|
var atlasData = this.cache.get(atlasKey);
|
|
var atlas = this.getAtlas(atlasKey);
|
|
|
|
if (!atlas)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (!this.spineTextures.has(atlasKey))
|
|
{
|
|
var gl = this.gl;
|
|
var i;
|
|
var atlasPage;
|
|
var realTextureKey;
|
|
|
|
if (this.isWebGL)
|
|
{
|
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
}
|
|
|
|
for (i = 0; i < atlas.pages.length; i ++)
|
|
{
|
|
atlasPage = atlas.pages[i];
|
|
realTextureKey = atlasData.prefix ? atlasData.prefix + atlasPage.name : atlasPage.name;
|
|
if (this.isWebGL)
|
|
{
|
|
atlasPage.setTexture(new this.runtime.GLTexture(gl, this.textures.get(realTextureKey).getSourceImage(), false));
|
|
}
|
|
else
|
|
{
|
|
atlasPage.setTexture(new this.runtime.CanvasTexture(this.textures.get(realTextureKey).getSourceImage()));
|
|
}
|
|
}
|
|
|
|
this.spineTextures.add(atlasKey, atlas);
|
|
}
|
|
|
|
var preMultipliedAlpha = atlasData.preMultipliedAlpha;
|
|
|
|
var atlasLoader = new this.runtime.AtlasAttachmentLoader(atlas);
|
|
|
|
var skeletonJson = new this.runtime.SkeletonJson(atlasLoader);
|
|
|
|
var data;
|
|
|
|
if (skeletonJSON)
|
|
{
|
|
data = skeletonJSON;
|
|
}
|
|
else
|
|
{
|
|
var json = this.json.get(atlasKey);
|
|
|
|
data = (split) ? GetValue(json, jsonKey) : json;
|
|
}
|
|
|
|
if (data)
|
|
{
|
|
var skeletonData = skeletonJson.readSkeletonData(data);
|
|
|
|
var skeleton = new this.runtime.Skeleton(skeletonData);
|
|
|
|
return { skeletonData: skeletonData, skeleton: skeleton, preMultipliedAlpha: preMultipliedAlpha };
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Creates a new Animation State and Animation State Data for the given skeleton.
|
|
*
|
|
* The returned object contains two properties: `state` and `stateData` respectively.
|
|
*
|
|
* @method SpinePlugin#createAnimationState
|
|
* @since 3.19.0
|
|
*
|
|
* @param {spine.Skeleton} skeleton - The Skeleton to create the Animation State for.
|
|
*
|
|
* @return {any} An object containing the Animation State and Animation State Data instances.
|
|
*/
|
|
createAnimationState: function (skeleton)
|
|
{
|
|
var stateData = new this.runtime.AnimationStateData(skeleton.data);
|
|
|
|
var state = new this.runtime.AnimationState(stateData);
|
|
|
|
return { stateData: stateData, state: state };
|
|
},
|
|
|
|
/**
|
|
* Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
|
*
|
|
* The returned object contains two properties: `offset` and `size`:
|
|
*
|
|
* `offset` - The distance from the skeleton origin to the bottom left corner of the AABB.
|
|
* `size` - The width and height of the AABB.
|
|
*
|
|
* @method SpinePlugin#getBounds
|
|
* @since 3.19.0
|
|
*
|
|
* @param {spine.Skeleton} skeleton - The Skeleton to get the bounds from.
|
|
*
|
|
* @return {any} The bounds object.
|
|
*/
|
|
getBounds: function (skeleton)
|
|
{
|
|
var offset = new this.runtime.Vector2();
|
|
var size = new this.runtime.Vector2();
|
|
|
|
skeleton.getBounds(offset, size, []);
|
|
|
|
return { offset: offset, size: size };
|
|
},
|
|
|
|
/**
|
|
* Internal handler for when the renderer resizes.
|
|
*
|
|
* Only called if running in WebGL.
|
|
*
|
|
* @method SpinePlugin#onResize
|
|
* @since 3.19.0
|
|
*/
|
|
onResize: function ()
|
|
{
|
|
var renderer = this.renderer;
|
|
var sceneRenderer = this.sceneRenderer;
|
|
|
|
var viewportWidth = renderer.width;
|
|
var viewportHeight = renderer.height;
|
|
|
|
sceneRenderer.camera.position.x = viewportWidth / 2;
|
|
sceneRenderer.camera.position.y = viewportHeight / 2;
|
|
|
|
sceneRenderer.camera.setViewport(viewportWidth, viewportHeight);
|
|
},
|
|
|
|
/**
|
|
* The Scene that owns this plugin is shutting down.
|
|
*
|
|
* We need to kill and reset all internal properties as well as stop listening to Scene events.
|
|
*
|
|
* @method SpinePlugin#shutdown
|
|
* @private
|
|
* @since 3.19.0
|
|
*/
|
|
shutdown: function ()
|
|
{
|
|
var eventEmitter = this.systems.events;
|
|
|
|
eventEmitter.off('shutdown', this.shutdown, this);
|
|
|
|
if (this.isWebGL)
|
|
{
|
|
this.game.scale.off(ResizeEvent, this.onResize, this);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* The Scene that owns this plugin is being destroyed.
|
|
*
|
|
* We need to shutdown and then kill off all external references.
|
|
*
|
|
* @method SpinePlugin#destroy
|
|
* @private
|
|
* @since 3.19.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.shutdown();
|
|
|
|
this.game = null;
|
|
this.scene = null;
|
|
this.systems = null;
|
|
|
|
this.cache = null;
|
|
this.spineTextures = null;
|
|
this.json = null;
|
|
this.textures = null;
|
|
this.skeletonRenderer = null;
|
|
this.gl = null;
|
|
},
|
|
|
|
/**
|
|
* The Game that owns this plugin is being destroyed.
|
|
*
|
|
* Dispose of the Scene Renderer and remove the Game Objects.
|
|
*
|
|
* @method SpinePlugin#gameDestroy
|
|
* @private
|
|
* @since 3.50.0
|
|
*/
|
|
gameDestroy: function ()
|
|
{
|
|
this.pluginManager.removeGameObject('spine', true, true);
|
|
this.pluginManager.removeGameObject('spineContainer', true, true);
|
|
|
|
this.pluginManager = null;
|
|
|
|
var sceneRenderer = this.renderer.spineSceneRenderer;
|
|
|
|
if (sceneRenderer)
|
|
{
|
|
sceneRenderer.dispose();
|
|
}
|
|
|
|
this.renderer.spineSceneRenderer = null;
|
|
this.sceneRenderer = null;
|
|
}
|
|
|
|
});
|
|
|
|
SpinePlugin.SpineGameObject = SpineGameObject;
|
|
SpinePlugin.SpineContainer = SpineContainer;
|
|
|
|
/**
|
|
* Creates a new Spine Game Object and adds it to the Scene.
|
|
*
|
|
* The x and y coordinate given is used to set the placement of the root Spine bone, which can vary from
|
|
* skeleton to skeleton. All rotation and scaling happens from the root bone placement. Spine Game Objects
|
|
* do not have a Phaser origin.
|
|
*
|
|
* If the Spine JSON file exported multiple Skeletons within it, then you can specify them by using a period
|
|
* character in the key. For example, if you loaded a Spine JSON using the key `monsters` and it contains
|
|
* multiple Skeletons, including one called `goblin` then you would use the key `monsters.goblin` to reference
|
|
* that.
|
|
*
|
|
* ```javascript
|
|
* let jelly = this.add.spine(512, 550, 'jelly', 'jelly-think', true);
|
|
* ```
|
|
*
|
|
* The key is optional. If not passed here, you need to call `SpineGameObject.setSkeleton()` to use it.
|
|
*
|
|
* The animation name is also optional and can be set later via `SpineGameObject.setAnimation`.
|
|
*
|
|
* Should you wish for more control over the object creation, such as setting a slot attachment or skin
|
|
* name, then use `SpinePlugin.make` instead.
|
|
*
|
|
* @method SpinePlugin#add
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} x - The horizontal position of this Game Object in the world.
|
|
* @param {number} y - The vertical position of this Game Object in the world.
|
|
* @param {string} [key] - The key of the Spine Skeleton this Game Object will use, as stored in the Spine Plugin.
|
|
* @param {string} [animationName] - The name of the animation to set on this Skeleton.
|
|
* @param {boolean} [loop=false] - Should the animation playback be looped or not?
|
|
*
|
|
* @return {SpineGameObject} The Game Object that was created.
|
|
*/
|
|
|
|
/**
|
|
* Creates a new Spine Game Object from the given configuration file and optionally adds it to the Scene.
|
|
*
|
|
* The x and y coordinate given is used to set the placement of the root Spine bone, which can vary from
|
|
* skeleton to skeleton. All rotation and scaling happens from the root bone placement. Spine Game Objects
|
|
* do not have a Phaser origin.
|
|
*
|
|
* If the Spine JSON file exported multiple Skeletons within it, then you can specify them by using a period
|
|
* character in the key. For example, if you loaded a Spine JSON using the key `monsters` and it contains
|
|
* multiple Skeletons, including one called `goblin` then you would use the key `monsters.goblin` to reference
|
|
* that.
|
|
*
|
|
* ```javascript
|
|
* let jelly = this.make.spine({
|
|
* x: 500, y: 500, key: 'jelly',
|
|
* scale: 1.5,
|
|
* skinName: 'square_Green',
|
|
* animationName: 'jelly-idle', loop: true,
|
|
* slotName: 'hat', attachmentName: 'images/La_14'
|
|
* });
|
|
* ```
|
|
*
|
|
* @method SpinePlugin#make
|
|
* @since 3.19.0
|
|
*
|
|
* @param {any} config - The configuration object this Game Object will use to create itself.
|
|
* @param {boolean} [addToScene] - Add this Game Object to the Scene after creating it? If set this argument overrides the `add` property in the config object.
|
|
*
|
|
* @return {SpineGameObject} The Game Object that was created.
|
|
*/
|
|
|
|
module.exports = SpinePlugin;
|
|
|
|
|
|
/***/ }),
|
|
/* 70 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var BlendModes = __webpack_require__(15);
|
|
var GetAdvancedValue = __webpack_require__(71);
|
|
|
|
/**
|
|
* Builds a Game Object using the provided configuration object.
|
|
*
|
|
* @function Phaser.GameObjects.BuildGameObject
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scene} scene - A reference to the Scene.
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The initial GameObject.
|
|
* @param {Phaser.Types.GameObjects.GameObjectConfig} config - The config to build the GameObject with.
|
|
*
|
|
* @return {Phaser.GameObjects.GameObject} The built Game Object.
|
|
*/
|
|
var BuildGameObject = function (scene, gameObject, config)
|
|
{
|
|
// Position
|
|
|
|
gameObject.x = GetAdvancedValue(config, 'x', 0);
|
|
gameObject.y = GetAdvancedValue(config, 'y', 0);
|
|
gameObject.depth = GetAdvancedValue(config, 'depth', 0);
|
|
|
|
// Flip
|
|
|
|
gameObject.flipX = GetAdvancedValue(config, 'flipX', false);
|
|
gameObject.flipY = GetAdvancedValue(config, 'flipY', false);
|
|
|
|
// Scale
|
|
// Either: { scale: 2 } or { scale: { x: 2, y: 2 }}
|
|
|
|
var scale = GetAdvancedValue(config, 'scale', null);
|
|
|
|
if (typeof scale === 'number')
|
|
{
|
|
gameObject.setScale(scale);
|
|
}
|
|
else if (scale !== null)
|
|
{
|
|
gameObject.scaleX = GetAdvancedValue(scale, 'x', 1);
|
|
gameObject.scaleY = GetAdvancedValue(scale, 'y', 1);
|
|
}
|
|
|
|
// ScrollFactor
|
|
// Either: { scrollFactor: 2 } or { scrollFactor: { x: 2, y: 2 }}
|
|
|
|
var scrollFactor = GetAdvancedValue(config, 'scrollFactor', null);
|
|
|
|
if (typeof scrollFactor === 'number')
|
|
{
|
|
gameObject.setScrollFactor(scrollFactor);
|
|
}
|
|
else if (scrollFactor !== null)
|
|
{
|
|
gameObject.scrollFactorX = GetAdvancedValue(scrollFactor, 'x', 1);
|
|
gameObject.scrollFactorY = GetAdvancedValue(scrollFactor, 'y', 1);
|
|
}
|
|
|
|
// Rotation
|
|
|
|
gameObject.rotation = GetAdvancedValue(config, 'rotation', 0);
|
|
|
|
var angle = GetAdvancedValue(config, 'angle', null);
|
|
|
|
if (angle !== null)
|
|
{
|
|
gameObject.angle = angle;
|
|
}
|
|
|
|
// Alpha
|
|
|
|
gameObject.alpha = GetAdvancedValue(config, 'alpha', 1);
|
|
|
|
// Origin
|
|
// Either: { origin: 0.5 } or { origin: { x: 0.5, y: 0.5 }}
|
|
|
|
var origin = GetAdvancedValue(config, 'origin', null);
|
|
|
|
if (typeof origin === 'number')
|
|
{
|
|
gameObject.setOrigin(origin);
|
|
}
|
|
else if (origin !== null)
|
|
{
|
|
var ox = GetAdvancedValue(origin, 'x', 0.5);
|
|
var oy = GetAdvancedValue(origin, 'y', 0.5);
|
|
|
|
gameObject.setOrigin(ox, oy);
|
|
}
|
|
|
|
// BlendMode
|
|
|
|
gameObject.blendMode = GetAdvancedValue(config, 'blendMode', BlendModes.NORMAL);
|
|
|
|
// Visible
|
|
|
|
gameObject.visible = GetAdvancedValue(config, 'visible', true);
|
|
|
|
// Add to Scene
|
|
|
|
var add = GetAdvancedValue(config, 'add', true);
|
|
|
|
if (add)
|
|
{
|
|
scene.sys.displayList.add(gameObject);
|
|
}
|
|
|
|
if (gameObject.preUpdate)
|
|
{
|
|
scene.sys.updateList.add(gameObject);
|
|
}
|
|
|
|
return gameObject;
|
|
};
|
|
|
|
module.exports = BuildGameObject;
|
|
|
|
|
|
/***/ }),
|
|
/* 71 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var MATH = __webpack_require__(72);
|
|
var GetValue = __webpack_require__(10);
|
|
|
|
/**
|
|
* Retrieves a value from an object. Allows for more advanced selection options, including:
|
|
*
|
|
* Allowed types:
|
|
*
|
|
* Implicit
|
|
* {
|
|
* x: 4
|
|
* }
|
|
*
|
|
* From function
|
|
* {
|
|
* x: function ()
|
|
* }
|
|
*
|
|
* Randomly pick one element from the array
|
|
* {
|
|
* x: [a, b, c, d, e, f]
|
|
* }
|
|
*
|
|
* Random integer between min and max:
|
|
* {
|
|
* x: { randInt: [min, max] }
|
|
* }
|
|
*
|
|
* Random float between min and max:
|
|
* {
|
|
* x: { randFloat: [min, max] }
|
|
* }
|
|
*
|
|
*
|
|
* @function Phaser.Utils.Objects.GetAdvancedValue
|
|
* @since 3.0.0
|
|
*
|
|
* @param {object} source - The object to retrieve the value from.
|
|
* @param {string} key - The name of the property to retrieve from the object. If a property is nested, the names of its preceding properties should be separated by a dot (`.`) - `banner.hideBanner` would return the value of the `hideBanner` property from the object stored in the `banner` property of the `source` object.
|
|
* @param {*} defaultValue - The value to return if the `key` isn't found in the `source` object.
|
|
*
|
|
* @return {*} The value of the requested key.
|
|
*/
|
|
var GetAdvancedValue = function (source, key, defaultValue)
|
|
{
|
|
var value = GetValue(source, key, null);
|
|
|
|
if (value === null)
|
|
{
|
|
return defaultValue;
|
|
}
|
|
else if (Array.isArray(value))
|
|
{
|
|
return MATH.RND.pick(value);
|
|
}
|
|
else if (typeof value === 'object')
|
|
{
|
|
if (value.hasOwnProperty('randInt'))
|
|
{
|
|
return MATH.RND.integerInRange(value.randInt[0], value.randInt[1]);
|
|
}
|
|
else if (value.hasOwnProperty('randFloat'))
|
|
{
|
|
return MATH.RND.realInRange(value.randFloat[0], value.randFloat[1]);
|
|
}
|
|
}
|
|
else if (typeof value === 'function')
|
|
{
|
|
return value(key);
|
|
}
|
|
|
|
return value;
|
|
};
|
|
|
|
module.exports = GetAdvancedValue;
|
|
|
|
|
|
/***/ }),
|
|
/* 72 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CONST = __webpack_require__(4);
|
|
var Extend = __webpack_require__(19);
|
|
|
|
/**
|
|
* @namespace Phaser.Math
|
|
*/
|
|
|
|
var PhaserMath = {
|
|
|
|
// Collections of functions
|
|
Angle: __webpack_require__(73),
|
|
Distance: __webpack_require__(82),
|
|
Easing: __webpack_require__(90),
|
|
Fuzzy: __webpack_require__(135),
|
|
Interpolation: __webpack_require__(140),
|
|
Pow2: __webpack_require__(148),
|
|
Snap: __webpack_require__(152),
|
|
|
|
// Expose the RNG Class
|
|
RandomDataGenerator: __webpack_require__(156),
|
|
|
|
// Single functions
|
|
Average: __webpack_require__(157),
|
|
Bernstein: __webpack_require__(36),
|
|
Between: __webpack_require__(158),
|
|
CatmullRom: __webpack_require__(38),
|
|
CeilTo: __webpack_require__(159),
|
|
Clamp: __webpack_require__(1),
|
|
DegToRad: __webpack_require__(21),
|
|
Difference: __webpack_require__(160),
|
|
Euler: __webpack_require__(161),
|
|
Factorial: __webpack_require__(37),
|
|
FloatBetween: __webpack_require__(20),
|
|
FloorTo: __webpack_require__(162),
|
|
FromPercent: __webpack_require__(163),
|
|
GetSpeed: __webpack_require__(164),
|
|
IsEven: __webpack_require__(165),
|
|
IsEvenStrict: __webpack_require__(166),
|
|
Linear: __webpack_require__(39),
|
|
LinearXY: __webpack_require__(167),
|
|
MaxAdd: __webpack_require__(168),
|
|
Median: __webpack_require__(169),
|
|
MinSub: __webpack_require__(170),
|
|
Percent: __webpack_require__(171),
|
|
RadToDeg: __webpack_require__(9),
|
|
RandomXY: __webpack_require__(172),
|
|
RandomXYZ: __webpack_require__(173),
|
|
RandomXYZW: __webpack_require__(174),
|
|
Rotate: __webpack_require__(175),
|
|
RotateAround: __webpack_require__(42),
|
|
RotateAroundDistance: __webpack_require__(176),
|
|
RotateTo: __webpack_require__(177),
|
|
RoundAwayFromZero: __webpack_require__(43),
|
|
RoundTo: __webpack_require__(178),
|
|
SinCosTableGenerator: __webpack_require__(179),
|
|
SmootherStep: __webpack_require__(41),
|
|
SmoothStep: __webpack_require__(40),
|
|
ToXY: __webpack_require__(180),
|
|
TransformXY: __webpack_require__(44),
|
|
Within: __webpack_require__(181),
|
|
Wrap: __webpack_require__(6),
|
|
|
|
// Vector classes
|
|
Vector2: __webpack_require__(3),
|
|
Vector3: __webpack_require__(16),
|
|
Vector4: __webpack_require__(182),
|
|
Matrix3: __webpack_require__(45),
|
|
Matrix4: __webpack_require__(22),
|
|
Quaternion: __webpack_require__(46),
|
|
RotateVec3: __webpack_require__(183)
|
|
|
|
};
|
|
|
|
// Merge in the consts
|
|
|
|
PhaserMath = Extend(false, PhaserMath, CONST);
|
|
|
|
// Export it
|
|
|
|
module.exports = PhaserMath;
|
|
|
|
|
|
/***/ }),
|
|
/* 73 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Angle
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Between: __webpack_require__(31),
|
|
BetweenPoints: __webpack_require__(74),
|
|
BetweenPointsY: __webpack_require__(75),
|
|
BetweenY: __webpack_require__(76),
|
|
CounterClockwise: __webpack_require__(8),
|
|
Normalize: __webpack_require__(32),
|
|
Random: __webpack_require__(77),
|
|
RandomDegrees: __webpack_require__(78),
|
|
Reverse: __webpack_require__(79),
|
|
RotateTo: __webpack_require__(80),
|
|
ShortestBetween: __webpack_require__(81),
|
|
Wrap: __webpack_require__(33),
|
|
WrapDegrees: __webpack_require__(34)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 74 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Find the angle of a segment from (point1.x, point1.y) -> (point2.x, point2.y).
|
|
*
|
|
* Calculates the angle of the vector from the first point to the second point.
|
|
*
|
|
* @function Phaser.Math.Angle.BetweenPoints
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} point1 - The first point.
|
|
* @param {Phaser.Types.Math.Vector2Like} point2 - The second point.
|
|
*
|
|
* @return {number} The angle in radians.
|
|
*/
|
|
var BetweenPoints = function (point1, point2)
|
|
{
|
|
return Math.atan2(point2.y - point1.y, point2.x - point1.x);
|
|
};
|
|
|
|
module.exports = BetweenPoints;
|
|
|
|
|
|
/***/ }),
|
|
/* 75 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Find the angle of a segment from (point1.x, point1.y) -> (point2.x, point2.y).
|
|
*
|
|
* The difference between this method and {@link Phaser.Math.Angle.BetweenPoints} is that this assumes the y coordinate
|
|
* travels down the screen.
|
|
*
|
|
* @function Phaser.Math.Angle.BetweenPointsY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} point1 - The first point.
|
|
* @param {Phaser.Types.Math.Vector2Like} point2 - The second point.
|
|
*
|
|
* @return {number} The angle in radians.
|
|
*/
|
|
var BetweenPointsY = function (point1, point2)
|
|
{
|
|
return Math.atan2(point2.x - point1.x, point2.y - point1.y);
|
|
};
|
|
|
|
module.exports = BetweenPointsY;
|
|
|
|
|
|
/***/ }),
|
|
/* 76 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Find the angle of a segment from (x1, y1) -> (x2, y2).
|
|
*
|
|
* The difference between this method and {@link Phaser.Math.Angle.Between} is that this assumes the y coordinate
|
|
* travels down the screen.
|
|
*
|
|
* @function Phaser.Math.Angle.BetweenY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x1 - The x coordinate of the first point.
|
|
* @param {number} y1 - The y coordinate of the first point.
|
|
* @param {number} x2 - The x coordinate of the second point.
|
|
* @param {number} y2 - The y coordinate of the second point.
|
|
*
|
|
* @return {number} The angle in radians.
|
|
*/
|
|
var BetweenY = function (x1, y1, x2, y2)
|
|
{
|
|
return Math.atan2(x2 - x1, y2 - y1);
|
|
};
|
|
|
|
module.exports = BetweenY;
|
|
|
|
|
|
/***/ }),
|
|
/* 77 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author @samme
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var FloatBetween = __webpack_require__(20);
|
|
|
|
/**
|
|
* Returns a random angle in the range [-pi, pi].
|
|
*
|
|
* @function Phaser.Math.Angle.Random
|
|
* @since 3.23.0
|
|
*
|
|
* @return {number} The angle, in radians.
|
|
*/
|
|
var Random = function ()
|
|
{
|
|
return FloatBetween(-Math.PI, Math.PI);
|
|
};
|
|
|
|
module.exports = Random;
|
|
|
|
|
|
/***/ }),
|
|
/* 78 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author @samme
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var FloatBetween = __webpack_require__(20);
|
|
|
|
/**
|
|
* Returns a random angle in the range [-180, 180].
|
|
*
|
|
* @function Phaser.Math.Angle.RandomDegrees
|
|
* @since 3.23.0
|
|
*
|
|
* @return {number} The angle, in degrees.
|
|
*/
|
|
var RandomDegrees = function ()
|
|
{
|
|
return FloatBetween(-180, 180);
|
|
};
|
|
|
|
module.exports = RandomDegrees;
|
|
|
|
|
|
/***/ }),
|
|
/* 79 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Normalize = __webpack_require__(32);
|
|
|
|
/**
|
|
* Reverse the given angle.
|
|
*
|
|
* @function Phaser.Math.Angle.Reverse
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} angle - The angle to reverse, in radians.
|
|
*
|
|
* @return {number} The reversed angle, in radians.
|
|
*/
|
|
var Reverse = function (angle)
|
|
{
|
|
return Normalize(angle + Math.PI);
|
|
};
|
|
|
|
module.exports = Reverse;
|
|
|
|
|
|
/***/ }),
|
|
/* 80 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var MATH_CONST = __webpack_require__(4);
|
|
|
|
/**
|
|
* Rotates `currentAngle` towards `targetAngle`, taking the shortest rotation distance. The `lerp` argument is the amount to rotate by in this call.
|
|
*
|
|
* @function Phaser.Math.Angle.RotateTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} currentAngle - The current angle, in radians.
|
|
* @param {number} targetAngle - The target angle to rotate to, in radians.
|
|
* @param {number} [lerp=0.05] - The lerp value to add to the current angle.
|
|
*
|
|
* @return {number} The adjusted angle.
|
|
*/
|
|
var RotateTo = function (currentAngle, targetAngle, lerp)
|
|
{
|
|
if (lerp === undefined) { lerp = 0.05; }
|
|
|
|
if (currentAngle === targetAngle)
|
|
{
|
|
return currentAngle;
|
|
}
|
|
|
|
if (Math.abs(targetAngle - currentAngle) <= lerp || Math.abs(targetAngle - currentAngle) >= (MATH_CONST.PI2 - lerp))
|
|
{
|
|
currentAngle = targetAngle;
|
|
}
|
|
else
|
|
{
|
|
if (Math.abs(targetAngle - currentAngle) > Math.PI)
|
|
{
|
|
if (targetAngle < currentAngle)
|
|
{
|
|
targetAngle += MATH_CONST.PI2;
|
|
}
|
|
else
|
|
{
|
|
targetAngle -= MATH_CONST.PI2;
|
|
}
|
|
}
|
|
|
|
if (targetAngle > currentAngle)
|
|
{
|
|
currentAngle += lerp;
|
|
}
|
|
else if (targetAngle < currentAngle)
|
|
{
|
|
currentAngle -= lerp;
|
|
}
|
|
}
|
|
|
|
return currentAngle;
|
|
};
|
|
|
|
module.exports = RotateTo;
|
|
|
|
|
|
/***/ }),
|
|
/* 81 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Gets the shortest angle between `angle1` and `angle2`.
|
|
*
|
|
* Both angles must be in the range -180 to 180, which is the same clamped
|
|
* range that `sprite.angle` uses, so you can pass in two sprite angles to
|
|
* this method and get the shortest angle back between the two of them.
|
|
*
|
|
* The angle returned will be in the same range. If the returned angle is
|
|
* greater than 0 then it's a counter-clockwise rotation, if < 0 then it's
|
|
* a clockwise rotation.
|
|
*
|
|
* @function Phaser.Math.Angle.ShortestBetween
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} angle1 - The first angle in the range -180 to 180.
|
|
* @param {number} angle2 - The second angle in the range -180 to 180.
|
|
*
|
|
* @return {number} The shortest angle, in degrees. If greater than zero it's a counter-clockwise rotation.
|
|
*/
|
|
var ShortestBetween = function (angle1, angle2)
|
|
{
|
|
var difference = angle2 - angle1;
|
|
|
|
if (difference === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
var times = Math.floor((difference - (-180)) / 360);
|
|
|
|
return difference - (times * 360);
|
|
|
|
};
|
|
|
|
module.exports = ShortestBetween;
|
|
|
|
|
|
/***/ }),
|
|
/* 82 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Distance
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Between: __webpack_require__(83),
|
|
BetweenPoints: __webpack_require__(84),
|
|
BetweenPointsSquared: __webpack_require__(85),
|
|
Chebyshev: __webpack_require__(86),
|
|
Power: __webpack_require__(87),
|
|
Snake: __webpack_require__(88),
|
|
Squared: __webpack_require__(89)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 83 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the distance between two sets of coordinates (points).
|
|
*
|
|
* @function Phaser.Math.Distance.Between
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x1 - The x coordinate of the first point.
|
|
* @param {number} y1 - The y coordinate of the first point.
|
|
* @param {number} x2 - The x coordinate of the second point.
|
|
* @param {number} y2 - The y coordinate of the second point.
|
|
*
|
|
* @return {number} The distance between each point.
|
|
*/
|
|
var DistanceBetween = function (x1, y1, x2, y2)
|
|
{
|
|
var dx = x1 - x2;
|
|
var dy = y1 - y2;
|
|
|
|
return Math.sqrt(dx * dx + dy * dy);
|
|
};
|
|
|
|
module.exports = DistanceBetween;
|
|
|
|
|
|
/***/ }),
|
|
/* 84 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author samme
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the distance between two points.
|
|
*
|
|
* @function Phaser.Math.Distance.BetweenPoints
|
|
* @since 3.22.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} a - The first point.
|
|
* @param {Phaser.Types.Math.Vector2Like} b - The second point.
|
|
*
|
|
* @return {number} The distance between the points.
|
|
*/
|
|
var DistanceBetweenPoints = function (a, b)
|
|
{
|
|
var dx = a.x - b.x;
|
|
var dy = a.y - b.y;
|
|
|
|
return Math.sqrt(dx * dx + dy * dy);
|
|
};
|
|
|
|
module.exports = DistanceBetweenPoints;
|
|
|
|
|
|
/***/ }),
|
|
/* 85 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author samme
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the squared distance between two points.
|
|
*
|
|
* @function Phaser.Math.Distance.BetweenPointsSquared
|
|
* @since 3.22.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} a - The first point.
|
|
* @param {Phaser.Types.Math.Vector2Like} b - The second point.
|
|
*
|
|
* @return {number} The squared distance between the points.
|
|
*/
|
|
var DistanceBetweenPointsSquared = function (a, b)
|
|
{
|
|
var dx = a.x - b.x;
|
|
var dy = a.y - b.y;
|
|
|
|
return dx * dx + dy * dy;
|
|
};
|
|
|
|
module.exports = DistanceBetweenPointsSquared;
|
|
|
|
|
|
/***/ }),
|
|
/* 86 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author samme
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the Chebyshev distance between two sets of coordinates (points).
|
|
*
|
|
* Chebyshev distance (or chessboard distance) is the maximum of the horizontal and vertical distances.
|
|
* It's the effective distance when movement can be horizontal, vertical, or diagonal.
|
|
*
|
|
* @function Phaser.Math.Distance.Chebyshev
|
|
* @since 3.22.0
|
|
*
|
|
* @param {number} x1 - The x coordinate of the first point.
|
|
* @param {number} y1 - The y coordinate of the first point.
|
|
* @param {number} x2 - The x coordinate of the second point.
|
|
* @param {number} y2 - The y coordinate of the second point.
|
|
*
|
|
* @return {number} The distance between each point.
|
|
*/
|
|
var ChebyshevDistance = function (x1, y1, x2, y2)
|
|
{
|
|
return Math.max(Math.abs(x1 - x2), Math.abs(y1 - y2));
|
|
};
|
|
|
|
module.exports = ChebyshevDistance;
|
|
|
|
|
|
/***/ }),
|
|
/* 87 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the distance between two sets of coordinates (points) to the power of `pow`.
|
|
*
|
|
* @function Phaser.Math.Distance.Power
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x1 - The x coordinate of the first point.
|
|
* @param {number} y1 - The y coordinate of the first point.
|
|
* @param {number} x2 - The x coordinate of the second point.
|
|
* @param {number} y2 - The y coordinate of the second point.
|
|
* @param {number} pow - The exponent.
|
|
*
|
|
* @return {number} The distance between each point.
|
|
*/
|
|
var DistancePower = function (x1, y1, x2, y2, pow)
|
|
{
|
|
if (pow === undefined) { pow = 2; }
|
|
|
|
return Math.sqrt(Math.pow(x2 - x1, pow) + Math.pow(y2 - y1, pow));
|
|
};
|
|
|
|
module.exports = DistancePower;
|
|
|
|
|
|
/***/ }),
|
|
/* 88 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author samme
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the snake distance between two sets of coordinates (points).
|
|
*
|
|
* Snake distance (rectilinear distance, Manhattan distance) is the sum of the horizontal and vertical distances.
|
|
* It's the effective distance when movement is allowed only horizontally or vertically (but not both).
|
|
*
|
|
* @function Phaser.Math.Distance.Snake
|
|
* @since 3.22.0
|
|
*
|
|
* @param {number} x1 - The x coordinate of the first point.
|
|
* @param {number} y1 - The y coordinate of the first point.
|
|
* @param {number} x2 - The x coordinate of the second point.
|
|
* @param {number} y2 - The y coordinate of the second point.
|
|
*
|
|
* @return {number} The distance between each point.
|
|
*/
|
|
var SnakeDistance = function (x1, y1, x2, y2)
|
|
{
|
|
return Math.abs(x1 - x2) + Math.abs(y1 - y2);
|
|
};
|
|
|
|
module.exports = SnakeDistance;
|
|
|
|
|
|
/***/ }),
|
|
/* 89 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the distance between two sets of coordinates (points), squared.
|
|
*
|
|
* @function Phaser.Math.Distance.Squared
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} x1 - The x coordinate of the first point.
|
|
* @param {number} y1 - The y coordinate of the first point.
|
|
* @param {number} x2 - The x coordinate of the second point.
|
|
* @param {number} y2 - The y coordinate of the second point.
|
|
*
|
|
* @return {number} The distance between each point, squared.
|
|
*/
|
|
var DistanceSquared = function (x1, y1, x2, y2)
|
|
{
|
|
var dx = x1 - x2;
|
|
var dy = y1 - y2;
|
|
|
|
return dx * dx + dy * dy;
|
|
};
|
|
|
|
module.exports = DistanceSquared;
|
|
|
|
|
|
/***/ }),
|
|
/* 90 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Back: __webpack_require__(91),
|
|
Bounce: __webpack_require__(95),
|
|
Circular: __webpack_require__(99),
|
|
Cubic: __webpack_require__(103),
|
|
Elastic: __webpack_require__(107),
|
|
Expo: __webpack_require__(111),
|
|
Linear: __webpack_require__(115),
|
|
Quadratic: __webpack_require__(117),
|
|
Quartic: __webpack_require__(121),
|
|
Quintic: __webpack_require__(125),
|
|
Sine: __webpack_require__(129),
|
|
Stepped: __webpack_require__(133)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 91 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Back
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(92),
|
|
Out: __webpack_require__(93),
|
|
InOut: __webpack_require__(94)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 92 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Back ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Back.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
* @param {number} [overshoot=1.70158] - The overshoot amount.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v, overshoot)
|
|
{
|
|
if (overshoot === undefined) { overshoot = 1.70158; }
|
|
|
|
return v * v * ((overshoot + 1) * v - overshoot);
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 93 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Back ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Back.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
* @param {number} [overshoot=1.70158] - The overshoot amount.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v, overshoot)
|
|
{
|
|
if (overshoot === undefined) { overshoot = 1.70158; }
|
|
|
|
return --v * v * ((overshoot + 1) * v + overshoot) + 1;
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 94 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Back ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Back.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
* @param {number} [overshoot=1.70158] - The overshoot amount.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v, overshoot)
|
|
{
|
|
if (overshoot === undefined) { overshoot = 1.70158; }
|
|
|
|
var s = overshoot * 1.525;
|
|
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return 0.5 * (v * v * ((s + 1) * v - s));
|
|
}
|
|
else
|
|
{
|
|
return 0.5 * ((v -= 2) * v * ((s + 1) * v + s) + 2);
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 95 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Bounce
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(96),
|
|
Out: __webpack_require__(97),
|
|
InOut: __webpack_require__(98)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 96 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Bounce ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Bounce.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
v = 1 - v;
|
|
|
|
if (v < 1 / 2.75)
|
|
{
|
|
return 1 - (7.5625 * v * v);
|
|
}
|
|
else if (v < 2 / 2.75)
|
|
{
|
|
return 1 - (7.5625 * (v -= 1.5 / 2.75) * v + 0.75);
|
|
}
|
|
else if (v < 2.5 / 2.75)
|
|
{
|
|
return 1 - (7.5625 * (v -= 2.25 / 2.75) * v + 0.9375);
|
|
}
|
|
else
|
|
{
|
|
return 1 - (7.5625 * (v -= 2.625 / 2.75) * v + 0.984375);
|
|
}
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 97 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Bounce ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Bounce.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
if (v < 1 / 2.75)
|
|
{
|
|
return 7.5625 * v * v;
|
|
}
|
|
else if (v < 2 / 2.75)
|
|
{
|
|
return 7.5625 * (v -= 1.5 / 2.75) * v + 0.75;
|
|
}
|
|
else if (v < 2.5 / 2.75)
|
|
{
|
|
return 7.5625 * (v -= 2.25 / 2.75) * v + 0.9375;
|
|
}
|
|
else
|
|
{
|
|
return 7.5625 * (v -= 2.625 / 2.75) * v + 0.984375;
|
|
}
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 98 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Bounce ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Bounce.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
var reverse = false;
|
|
|
|
if (v < 0.5)
|
|
{
|
|
v = 1 - (v * 2);
|
|
reverse = true;
|
|
}
|
|
else
|
|
{
|
|
v = (v * 2) - 1;
|
|
}
|
|
|
|
if (v < 1 / 2.75)
|
|
{
|
|
v = 7.5625 * v * v;
|
|
}
|
|
else if (v < 2 / 2.75)
|
|
{
|
|
v = 7.5625 * (v -= 1.5 / 2.75) * v + 0.75;
|
|
}
|
|
else if (v < 2.5 / 2.75)
|
|
{
|
|
v = 7.5625 * (v -= 2.25 / 2.75) * v + 0.9375;
|
|
}
|
|
else
|
|
{
|
|
v = 7.5625 * (v -= 2.625 / 2.75) * v + 0.984375;
|
|
}
|
|
|
|
if (reverse)
|
|
{
|
|
return (1 - v) * 0.5;
|
|
}
|
|
else
|
|
{
|
|
return v * 0.5 + 0.5;
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 99 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Circular
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(100),
|
|
Out: __webpack_require__(101),
|
|
InOut: __webpack_require__(102)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 100 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Circular ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Circular.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
return 1 - Math.sqrt(1 - v * v);
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 101 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Circular ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Circular.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
return Math.sqrt(1 - (--v * v));
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 102 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Circular ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Circular.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return -0.5 * (Math.sqrt(1 - v * v) - 1);
|
|
}
|
|
else
|
|
{
|
|
return 0.5 * (Math.sqrt(1 - (v -= 2) * v) + 1);
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 103 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Cubic
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(104),
|
|
Out: __webpack_require__(105),
|
|
InOut: __webpack_require__(106)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 104 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Cubic ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Cubic.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
return v * v * v;
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 105 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Cubic ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Cubic.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
return --v * v * v + 1;
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 106 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Cubic ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Cubic.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return 0.5 * v * v * v;
|
|
}
|
|
else
|
|
{
|
|
return 0.5 * ((v -= 2) * v * v + 2);
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 107 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Elastic
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(108),
|
|
Out: __webpack_require__(109),
|
|
InOut: __webpack_require__(110)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 108 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Elastic ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Elastic.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
* @param {number} [amplitude=0.1] - The amplitude of the elastic ease.
|
|
* @param {number} [period=0.1] - Sets how tight the sine-wave is, where smaller values are tighter waves, which result in more cycles.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v, amplitude, period)
|
|
{
|
|
if (amplitude === undefined) { amplitude = 0.1; }
|
|
if (period === undefined) { period = 0.1; }
|
|
|
|
if (v === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (v === 1)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
var s = period / 4;
|
|
|
|
if (amplitude < 1)
|
|
{
|
|
amplitude = 1;
|
|
}
|
|
else
|
|
{
|
|
s = period * Math.asin(1 / amplitude) / (2 * Math.PI);
|
|
}
|
|
|
|
return -(amplitude * Math.pow(2, 10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / period));
|
|
}
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 109 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Elastic ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Elastic.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
* @param {number} [amplitude=0.1] - The amplitude of the elastic ease.
|
|
* @param {number} [period=0.1] - Sets how tight the sine-wave is, where smaller values are tighter waves, which result in more cycles.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v, amplitude, period)
|
|
{
|
|
if (amplitude === undefined) { amplitude = 0.1; }
|
|
if (period === undefined) { period = 0.1; }
|
|
|
|
if (v === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (v === 1)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
var s = period / 4;
|
|
|
|
if (amplitude < 1)
|
|
{
|
|
amplitude = 1;
|
|
}
|
|
else
|
|
{
|
|
s = period * Math.asin(1 / amplitude) / (2 * Math.PI);
|
|
}
|
|
|
|
return (amplitude * Math.pow(2, -10 * v) * Math.sin((v - s) * (2 * Math.PI) / period) + 1);
|
|
}
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 110 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Elastic ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Elastic.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
* @param {number} [amplitude=0.1] - The amplitude of the elastic ease.
|
|
* @param {number} [period=0.1] - Sets how tight the sine-wave is, where smaller values are tighter waves, which result in more cycles.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v, amplitude, period)
|
|
{
|
|
if (amplitude === undefined) { amplitude = 0.1; }
|
|
if (period === undefined) { period = 0.1; }
|
|
|
|
if (v === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (v === 1)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
var s = period / 4;
|
|
|
|
if (amplitude < 1)
|
|
{
|
|
amplitude = 1;
|
|
}
|
|
else
|
|
{
|
|
s = period * Math.asin(1 / amplitude) / (2 * Math.PI);
|
|
}
|
|
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return -0.5 * (amplitude * Math.pow(2, 10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / period));
|
|
}
|
|
else
|
|
{
|
|
return amplitude * Math.pow(2, -10 * (v -= 1)) * Math.sin((v - s) * (2 * Math.PI) / period) * 0.5 + 1;
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 111 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Expo
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(112),
|
|
Out: __webpack_require__(113),
|
|
InOut: __webpack_require__(114)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 112 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Exponential ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Expo.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
return Math.pow(2, 10 * (v - 1)) - 0.001;
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 113 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Exponential ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Expo.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
return 1 - Math.pow(2, -10 * v);
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 114 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Exponential ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Expo.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return 0.5 * Math.pow(2, 10 * (v - 1));
|
|
}
|
|
else
|
|
{
|
|
return 0.5 * (2 - Math.pow(2, -10 * (v - 1)));
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 115 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
module.exports = __webpack_require__(116);
|
|
|
|
|
|
/***/ }),
|
|
/* 116 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Linear easing (no variation).
|
|
*
|
|
* @function Phaser.Math.Easing.Linear
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Linear = function (v)
|
|
{
|
|
return v;
|
|
};
|
|
|
|
module.exports = Linear;
|
|
|
|
|
|
/***/ }),
|
|
/* 117 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Quadratic
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(118),
|
|
Out: __webpack_require__(119),
|
|
InOut: __webpack_require__(120)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 118 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quadratic ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Quadratic.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
return v * v;
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 119 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quadratic ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Quadratic.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
return v * (2 - v);
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 120 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quadratic ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Quadratic.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return 0.5 * v * v;
|
|
}
|
|
else
|
|
{
|
|
return -0.5 * (--v * (v - 2) - 1);
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 121 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Quartic
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(122),
|
|
Out: __webpack_require__(123),
|
|
InOut: __webpack_require__(124)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 122 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quartic ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Quartic.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
return v * v * v * v;
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 123 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quartic ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Quartic.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
return 1 - (--v * v * v * v);
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 124 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quartic ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Quartic.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return 0.5 * v * v * v * v;
|
|
}
|
|
else
|
|
{
|
|
return -0.5 * ((v -= 2) * v * v * v - 2);
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 125 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Quintic
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(126),
|
|
Out: __webpack_require__(127),
|
|
InOut: __webpack_require__(128)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 126 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quintic ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Quintic.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
return v * v * v * v * v;
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 127 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quintic ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Quintic.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
return --v * v * v * v * v + 1;
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 128 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Quintic ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Quintic.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
if ((v *= 2) < 1)
|
|
{
|
|
return 0.5 * v * v * v * v * v;
|
|
}
|
|
else
|
|
{
|
|
return 0.5 * ((v -= 2) * v * v * v * v + 2);
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 129 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Sine
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
In: __webpack_require__(130),
|
|
Out: __webpack_require__(131),
|
|
InOut: __webpack_require__(132)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 130 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Sinusoidal ease-in.
|
|
*
|
|
* @function Phaser.Math.Easing.Sine.In
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var In = function (v)
|
|
{
|
|
if (v === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (v === 1)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 1 - Math.cos(v * Math.PI / 2);
|
|
}
|
|
};
|
|
|
|
module.exports = In;
|
|
|
|
|
|
/***/ }),
|
|
/* 131 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Sinusoidal ease-out.
|
|
*
|
|
* @function Phaser.Math.Easing.Sine.Out
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Out = function (v)
|
|
{
|
|
if (v === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (v === 1)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return Math.sin(v * Math.PI / 2);
|
|
}
|
|
};
|
|
|
|
module.exports = Out;
|
|
|
|
|
|
/***/ }),
|
|
/* 132 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Sinusoidal ease-in/out.
|
|
*
|
|
* @function Phaser.Math.Easing.Sine.InOut
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var InOut = function (v)
|
|
{
|
|
if (v === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (v === 1)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return 0.5 * (1 - Math.cos(Math.PI * v));
|
|
}
|
|
};
|
|
|
|
module.exports = InOut;
|
|
|
|
|
|
/***/ }),
|
|
/* 133 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Easing.Stepped
|
|
*/
|
|
|
|
module.exports = __webpack_require__(134);
|
|
|
|
|
|
/***/ }),
|
|
/* 134 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Stepped easing.
|
|
*
|
|
* @function Phaser.Math.Easing.Stepped
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} v - The value to be tweened.
|
|
* @param {number} [steps=1] - The number of steps in the ease.
|
|
*
|
|
* @return {number} The tweened value.
|
|
*/
|
|
var Stepped = function (v, steps)
|
|
{
|
|
if (steps === undefined) { steps = 1; }
|
|
|
|
if (v <= 0)
|
|
{
|
|
return 0;
|
|
}
|
|
else if (v >= 1)
|
|
{
|
|
return 1;
|
|
}
|
|
else
|
|
{
|
|
return (((steps * v) | 0) + 1) * (1 / steps);
|
|
}
|
|
};
|
|
|
|
module.exports = Stepped;
|
|
|
|
|
|
/***/ }),
|
|
/* 135 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Fuzzy
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Ceil: __webpack_require__(136),
|
|
Equal: __webpack_require__(35),
|
|
Floor: __webpack_require__(137),
|
|
GreaterThan: __webpack_require__(138),
|
|
LessThan: __webpack_require__(139)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 136 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the fuzzy ceiling of the given value.
|
|
*
|
|
* @function Phaser.Math.Fuzzy.Ceil
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value.
|
|
* @param {number} [epsilon=0.0001] - The epsilon.
|
|
*
|
|
* @return {number} The fuzzy ceiling of the value.
|
|
*/
|
|
var Ceil = function (value, epsilon)
|
|
{
|
|
if (epsilon === undefined) { epsilon = 0.0001; }
|
|
|
|
return Math.ceil(value - epsilon);
|
|
};
|
|
|
|
module.exports = Ceil;
|
|
|
|
|
|
/***/ }),
|
|
/* 137 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the fuzzy floor of the given value.
|
|
*
|
|
* @function Phaser.Math.Fuzzy.Floor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value.
|
|
* @param {number} [epsilon=0.0001] - The epsilon.
|
|
*
|
|
* @return {number} The floor of the value.
|
|
*/
|
|
var Floor = function (value, epsilon)
|
|
{
|
|
if (epsilon === undefined) { epsilon = 0.0001; }
|
|
|
|
return Math.floor(value + epsilon);
|
|
};
|
|
|
|
module.exports = Floor;
|
|
|
|
|
|
/***/ }),
|
|
/* 138 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Check whether `a` is fuzzily greater than `b`.
|
|
*
|
|
* `a` is fuzzily greater than `b` if it is more than `b - epsilon`.
|
|
*
|
|
* @function Phaser.Math.Fuzzy.GreaterThan
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} a - The first value.
|
|
* @param {number} b - The second value.
|
|
* @param {number} [epsilon=0.0001] - The epsilon.
|
|
*
|
|
* @return {boolean} `true` if `a` is fuzzily greater than than `b`, otherwise `false`.
|
|
*/
|
|
var GreaterThan = function (a, b, epsilon)
|
|
{
|
|
if (epsilon === undefined) { epsilon = 0.0001; }
|
|
|
|
return a > b - epsilon;
|
|
};
|
|
|
|
module.exports = GreaterThan;
|
|
|
|
|
|
/***/ }),
|
|
/* 139 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Check whether `a` is fuzzily less than `b`.
|
|
*
|
|
* `a` is fuzzily less than `b` if it is less than `b + epsilon`.
|
|
*
|
|
* @function Phaser.Math.Fuzzy.LessThan
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} a - The first value.
|
|
* @param {number} b - The second value.
|
|
* @param {number} [epsilon=0.0001] - The epsilon.
|
|
*
|
|
* @return {boolean} `true` if `a` is fuzzily less than `b`, otherwise `false`.
|
|
*/
|
|
var LessThan = function (a, b, epsilon)
|
|
{
|
|
if (epsilon === undefined) { epsilon = 0.0001; }
|
|
|
|
return a < b + epsilon;
|
|
};
|
|
|
|
module.exports = LessThan;
|
|
|
|
|
|
/***/ }),
|
|
/* 140 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Interpolation
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Bezier: __webpack_require__(141),
|
|
CatmullRom: __webpack_require__(142),
|
|
CubicBezier: __webpack_require__(143),
|
|
Linear: __webpack_require__(144),
|
|
QuadraticBezier: __webpack_require__(145),
|
|
SmoothStep: __webpack_require__(146),
|
|
SmootherStep: __webpack_require__(147)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 141 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Bernstein = __webpack_require__(36);
|
|
|
|
/**
|
|
* A bezier interpolation method.
|
|
*
|
|
* @function Phaser.Math.Interpolation.Bezier
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number[]} v - The input array of values to interpolate between.
|
|
* @param {number} k - The percentage of interpolation, between 0 and 1.
|
|
*
|
|
* @return {number} The interpolated value.
|
|
*/
|
|
var BezierInterpolation = function (v, k)
|
|
{
|
|
var b = 0;
|
|
var n = v.length - 1;
|
|
|
|
for (var i = 0; i <= n; i++)
|
|
{
|
|
b += Math.pow(1 - k, n - i) * Math.pow(k, i) * v[i] * Bernstein(n, i);
|
|
}
|
|
|
|
return b;
|
|
};
|
|
|
|
module.exports = BezierInterpolation;
|
|
|
|
|
|
/***/ }),
|
|
/* 142 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CatmullRom = __webpack_require__(38);
|
|
|
|
/**
|
|
* A Catmull-Rom interpolation method.
|
|
*
|
|
* @function Phaser.Math.Interpolation.CatmullRom
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number[]} v - The input array of values to interpolate between.
|
|
* @param {number} k - The percentage of interpolation, between 0 and 1.
|
|
*
|
|
* @return {number} The interpolated value.
|
|
*/
|
|
var CatmullRomInterpolation = function (v, k)
|
|
{
|
|
var m = v.length - 1;
|
|
var f = m * k;
|
|
var i = Math.floor(f);
|
|
|
|
if (v[0] === v[m])
|
|
{
|
|
if (k < 0)
|
|
{
|
|
i = Math.floor(f = m * (1 + k));
|
|
}
|
|
|
|
return CatmullRom(f - i, v[(i - 1 + m) % m], v[i], v[(i + 1) % m], v[(i + 2) % m]);
|
|
}
|
|
else
|
|
{
|
|
if (k < 0)
|
|
{
|
|
return v[0] - (CatmullRom(-f, v[0], v[0], v[1], v[1]) - v[0]);
|
|
}
|
|
|
|
if (k > 1)
|
|
{
|
|
return v[m] - (CatmullRom(f - m, v[m], v[m], v[m - 1], v[m - 1]) - v[m]);
|
|
}
|
|
|
|
return CatmullRom(f - i, v[i ? i - 1 : 0], v[i], v[m < i + 1 ? m : i + 1], v[m < i + 2 ? m : i + 2]);
|
|
}
|
|
};
|
|
|
|
module.exports = CatmullRomInterpolation;
|
|
|
|
|
|
/***/ }),
|
|
/* 143 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function P0 (t, p)
|
|
{
|
|
var k = 1 - t;
|
|
|
|
return k * k * k * p;
|
|
}
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function P1 (t, p)
|
|
{
|
|
var k = 1 - t;
|
|
|
|
return 3 * k * k * t * p;
|
|
}
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function P2 (t, p)
|
|
{
|
|
return 3 * (1 - t) * t * t * p;
|
|
}
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function P3 (t, p)
|
|
{
|
|
return t * t * t * p;
|
|
}
|
|
|
|
/**
|
|
* A cubic bezier interpolation method.
|
|
*
|
|
* https://medium.com/@adrian_cooney/bezier-interpolation-13b68563313a
|
|
*
|
|
* @function Phaser.Math.Interpolation.CubicBezier
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} t - The percentage of interpolation, between 0 and 1.
|
|
* @param {number} p0 - The start point.
|
|
* @param {number} p1 - The first control point.
|
|
* @param {number} p2 - The second control point.
|
|
* @param {number} p3 - The end point.
|
|
*
|
|
* @return {number} The interpolated value.
|
|
*/
|
|
var CubicBezierInterpolation = function (t, p0, p1, p2, p3)
|
|
{
|
|
return P0(t, p0) + P1(t, p1) + P2(t, p2) + P3(t, p3);
|
|
};
|
|
|
|
module.exports = CubicBezierInterpolation;
|
|
|
|
|
|
/***/ }),
|
|
/* 144 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Linear = __webpack_require__(39);
|
|
|
|
/**
|
|
* A linear interpolation method.
|
|
*
|
|
* @function Phaser.Math.Interpolation.Linear
|
|
* @since 3.0.0
|
|
* @see {@link https://en.wikipedia.org/wiki/Linear_interpolation}
|
|
*
|
|
* @param {number[]} v - The input array of values to interpolate between.
|
|
* @param {!number} k - The percentage of interpolation, between 0 and 1.
|
|
*
|
|
* @return {!number} The interpolated value.
|
|
*/
|
|
var LinearInterpolation = function (v, k)
|
|
{
|
|
var m = v.length - 1;
|
|
var f = m * k;
|
|
var i = Math.floor(f);
|
|
|
|
if (k < 0)
|
|
{
|
|
return Linear(v[0], v[1], f);
|
|
}
|
|
else if (k > 1)
|
|
{
|
|
return Linear(v[m], v[m - 1], m - f);
|
|
}
|
|
else
|
|
{
|
|
return Linear(v[i], v[(i + 1 > m) ? m : i + 1], f - i);
|
|
}
|
|
};
|
|
|
|
module.exports = LinearInterpolation;
|
|
|
|
|
|
/***/ }),
|
|
/* 145 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function P0 (t, p)
|
|
{
|
|
var k = 1 - t;
|
|
|
|
return k * k * p;
|
|
}
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function P1 (t, p)
|
|
{
|
|
return 2 * (1 - t) * t * p;
|
|
}
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function P2 (t, p)
|
|
{
|
|
return t * t * p;
|
|
}
|
|
|
|
// https://github.com/mrdoob/three.js/blob/master/src/extras/core/Interpolations.js
|
|
|
|
/**
|
|
* A quadratic bezier interpolation method.
|
|
*
|
|
* @function Phaser.Math.Interpolation.QuadraticBezier
|
|
* @since 3.2.0
|
|
*
|
|
* @param {number} t - The percentage of interpolation, between 0 and 1.
|
|
* @param {number} p0 - The start point.
|
|
* @param {number} p1 - The control point.
|
|
* @param {number} p2 - The end point.
|
|
*
|
|
* @return {number} The interpolated value.
|
|
*/
|
|
var QuadraticBezierInterpolation = function (t, p0, p1, p2)
|
|
{
|
|
return P0(t, p0) + P1(t, p1) + P2(t, p2);
|
|
};
|
|
|
|
module.exports = QuadraticBezierInterpolation;
|
|
|
|
|
|
/***/ }),
|
|
/* 146 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SmoothStep = __webpack_require__(40);
|
|
|
|
/**
|
|
* A Smooth Step interpolation method.
|
|
*
|
|
* @function Phaser.Math.Interpolation.SmoothStep
|
|
* @since 3.9.0
|
|
* @see {@link https://en.wikipedia.org/wiki/Smoothstep}
|
|
*
|
|
* @param {number} t - The percentage of interpolation, between 0 and 1.
|
|
* @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'.
|
|
* @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'.
|
|
*
|
|
* @return {number} The interpolated value.
|
|
*/
|
|
var SmoothStepInterpolation = function (t, min, max)
|
|
{
|
|
return min + (max - min) * SmoothStep(t, 0, 1);
|
|
};
|
|
|
|
module.exports = SmoothStepInterpolation;
|
|
|
|
|
|
/***/ }),
|
|
/* 147 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SmootherStep = __webpack_require__(41);
|
|
|
|
/**
|
|
* A Smoother Step interpolation method.
|
|
*
|
|
* @function Phaser.Math.Interpolation.SmootherStep
|
|
* @since 3.9.0
|
|
* @see {@link https://en.wikipedia.org/wiki/Smoothstep#Variations}
|
|
*
|
|
* @param {number} t - The percentage of interpolation, between 0 and 1.
|
|
* @param {number} min - The minimum value, also known as the 'left edge', assumed smaller than the 'right edge'.
|
|
* @param {number} max - The maximum value, also known as the 'right edge', assumed greater than the 'left edge'.
|
|
*
|
|
* @return {number} The interpolated value.
|
|
*/
|
|
var SmootherStepInterpolation = function (t, min, max)
|
|
{
|
|
return min + (max - min) * SmootherStep(t, 0, 1);
|
|
};
|
|
|
|
module.exports = SmootherStepInterpolation;
|
|
|
|
|
|
/***/ }),
|
|
/* 148 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Pow2
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
GetNext: __webpack_require__(149),
|
|
IsSize: __webpack_require__(150),
|
|
IsValue: __webpack_require__(151)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 149 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Returns the nearest power of 2 to the given `value`.
|
|
*
|
|
* @function Phaser.Math.Pow2.GetNext
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value.
|
|
*
|
|
* @return {number} The nearest power of 2 to `value`.
|
|
*/
|
|
var GetPowerOfTwo = function (value)
|
|
{
|
|
var index = Math.log(value) / 0.6931471805599453;
|
|
|
|
return (1 << Math.ceil(index));
|
|
};
|
|
|
|
module.exports = GetPowerOfTwo;
|
|
|
|
|
|
/***/ }),
|
|
/* 150 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Checks if the given `width` and `height` are a power of two.
|
|
* Useful for checking texture dimensions.
|
|
*
|
|
* @function Phaser.Math.Pow2.IsSize
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} width - The width.
|
|
* @param {number} height - The height.
|
|
*
|
|
* @return {boolean} `true` if `width` and `height` are a power of two, otherwise `false`.
|
|
*/
|
|
var IsSizePowerOfTwo = function (width, height)
|
|
{
|
|
return (width > 0 && (width & (width - 1)) === 0 && height > 0 && (height & (height - 1)) === 0);
|
|
};
|
|
|
|
module.exports = IsSizePowerOfTwo;
|
|
|
|
|
|
/***/ }),
|
|
/* 151 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Tests the value and returns `true` if it is a power of two.
|
|
*
|
|
* @function Phaser.Math.Pow2.IsValue
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to check if it's a power of two.
|
|
*
|
|
* @return {boolean} Returns `true` if `value` is a power of two, otherwise `false`.
|
|
*/
|
|
var IsValuePowerOfTwo = function (value)
|
|
{
|
|
return (value > 0 && (value & (value - 1)) === 0);
|
|
};
|
|
|
|
module.exports = IsValuePowerOfTwo;
|
|
|
|
|
|
/***/ }),
|
|
/* 152 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Math.Snap
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Ceil: __webpack_require__(153),
|
|
Floor: __webpack_require__(154),
|
|
To: __webpack_require__(155)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 153 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Snap a value to nearest grid slice, using ceil.
|
|
*
|
|
* Example: if you have an interval gap of `5` and a position of `12`... you will snap to `15`.
|
|
* As will `14` snap to `15`... but `16` will snap to `20`.
|
|
*
|
|
* @function Phaser.Math.Snap.Ceil
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to snap.
|
|
* @param {number} gap - The interval gap of the grid.
|
|
* @param {number} [start=0] - Optional starting offset for gap.
|
|
* @param {boolean} [divide=false] - If `true` it will divide the snapped value by the gap before returning.
|
|
*
|
|
* @return {number} The snapped value.
|
|
*/
|
|
var SnapCeil = function (value, gap, start, divide)
|
|
{
|
|
if (start === undefined) { start = 0; }
|
|
|
|
if (gap === 0)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
value -= start;
|
|
value = gap * Math.ceil(value / gap);
|
|
|
|
return (divide) ? (start + value) / gap : start + value;
|
|
};
|
|
|
|
module.exports = SnapCeil;
|
|
|
|
|
|
/***/ }),
|
|
/* 154 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Snap a value to nearest grid slice, using floor.
|
|
*
|
|
* Example: if you have an interval gap of `5` and a position of `12`... you will snap to `10`.
|
|
* As will `14` snap to `10`... but `16` will snap to `15`.
|
|
*
|
|
* @function Phaser.Math.Snap.Floor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to snap.
|
|
* @param {number} gap - The interval gap of the grid.
|
|
* @param {number} [start=0] - Optional starting offset for gap.
|
|
* @param {boolean} [divide=false] - If `true` it will divide the snapped value by the gap before returning.
|
|
*
|
|
* @return {number} The snapped value.
|
|
*/
|
|
var SnapFloor = function (value, gap, start, divide)
|
|
{
|
|
if (start === undefined) { start = 0; }
|
|
|
|
if (gap === 0)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
value -= start;
|
|
value = gap * Math.floor(value / gap);
|
|
|
|
return (divide) ? (start + value) / gap : start + value;
|
|
};
|
|
|
|
module.exports = SnapFloor;
|
|
|
|
|
|
/***/ }),
|
|
/* 155 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Snap a value to nearest grid slice, using rounding.
|
|
*
|
|
* Example: if you have an interval gap of `5` and a position of `12`... you will snap to `10` whereas `14` will snap to `15`.
|
|
*
|
|
* @function Phaser.Math.Snap.To
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to snap.
|
|
* @param {number} gap - The interval gap of the grid.
|
|
* @param {number} [start=0] - Optional starting offset for gap.
|
|
* @param {boolean} [divide=false] - If `true` it will divide the snapped value by the gap before returning.
|
|
*
|
|
* @return {number} The snapped value.
|
|
*/
|
|
var SnapTo = function (value, gap, start, divide)
|
|
{
|
|
if (start === undefined) { start = 0; }
|
|
|
|
if (gap === 0)
|
|
{
|
|
return value;
|
|
}
|
|
|
|
value -= start;
|
|
value = gap * Math.round(value / gap);
|
|
|
|
return (divide) ? (start + value) / gap : start + value;
|
|
};
|
|
|
|
module.exports = SnapTo;
|
|
|
|
|
|
/***/ }),
|
|
/* 156 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A seeded Random Data Generator.
|
|
*
|
|
* Access via `Phaser.Math.RND` which is an instance of this class pre-defined
|
|
* by Phaser. Or, create your own instance to use as you require.
|
|
*
|
|
* The `Math.RND` generator is seeded by the Game Config property value `seed`.
|
|
* If no such config property exists, a random number is used.
|
|
*
|
|
* If you create your own instance of this class you should provide a seed for it.
|
|
* If no seed is given it will use a 'random' one based on Date.now.
|
|
*
|
|
* @class RandomDataGenerator
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|string[])} [seeds] - The seeds to use for the random number generator.
|
|
*/
|
|
var RandomDataGenerator = new Class({
|
|
|
|
initialize:
|
|
|
|
function RandomDataGenerator (seeds)
|
|
{
|
|
if (seeds === undefined) { seeds = [ (Date.now() * Math.random()).toString() ]; }
|
|
|
|
/**
|
|
* Internal var.
|
|
*
|
|
* @name Phaser.Math.RandomDataGenerator#c
|
|
* @type {number}
|
|
* @default 1
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
this.c = 1;
|
|
|
|
/**
|
|
* Internal var.
|
|
*
|
|
* @name Phaser.Math.RandomDataGenerator#s0
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
this.s0 = 0;
|
|
|
|
/**
|
|
* Internal var.
|
|
*
|
|
* @name Phaser.Math.RandomDataGenerator#s1
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
this.s1 = 0;
|
|
|
|
/**
|
|
* Internal var.
|
|
*
|
|
* @name Phaser.Math.RandomDataGenerator#s2
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
this.s2 = 0;
|
|
|
|
/**
|
|
* Internal var.
|
|
*
|
|
* @name Phaser.Math.RandomDataGenerator#n
|
|
* @type {number}
|
|
* @default 0
|
|
* @private
|
|
* @since 3.2.0
|
|
*/
|
|
this.n = 0;
|
|
|
|
/**
|
|
* Signs to choose from.
|
|
*
|
|
* @name Phaser.Math.RandomDataGenerator#signs
|
|
* @type {number[]}
|
|
* @since 3.0.0
|
|
*/
|
|
this.signs = [ -1, 1 ];
|
|
|
|
if (seeds)
|
|
{
|
|
this.init(seeds);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Private random helper.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#rnd
|
|
* @since 3.0.0
|
|
* @private
|
|
*
|
|
* @return {number} A random number.
|
|
*/
|
|
rnd: function ()
|
|
{
|
|
var t = 2091639 * this.s0 + this.c * 2.3283064365386963e-10; // 2^-32
|
|
|
|
this.c = t | 0;
|
|
this.s0 = this.s1;
|
|
this.s1 = this.s2;
|
|
this.s2 = t - this.c;
|
|
|
|
return this.s2;
|
|
},
|
|
|
|
/**
|
|
* Internal method that creates a seed hash.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#hash
|
|
* @since 3.0.0
|
|
* @private
|
|
*
|
|
* @param {string} data - The value to hash.
|
|
*
|
|
* @return {number} The hashed value.
|
|
*/
|
|
hash: function (data)
|
|
{
|
|
var h;
|
|
var n = this.n;
|
|
|
|
data = data.toString();
|
|
|
|
for (var i = 0; i < data.length; i++)
|
|
{
|
|
n += data.charCodeAt(i);
|
|
h = 0.02519603282416938 * n;
|
|
n = h >>> 0;
|
|
h -= n;
|
|
h *= n;
|
|
n = h >>> 0;
|
|
h -= n;
|
|
n += h * 0x100000000;// 2^32
|
|
}
|
|
|
|
this.n = n;
|
|
|
|
return (n >>> 0) * 2.3283064365386963e-10;// 2^-32
|
|
},
|
|
|
|
/**
|
|
* Initialize the state of the random data generator.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#init
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|string[])} seeds - The seeds to initialize the random data generator with.
|
|
*/
|
|
init: function (seeds)
|
|
{
|
|
if (typeof seeds === 'string')
|
|
{
|
|
this.state(seeds);
|
|
}
|
|
else
|
|
{
|
|
this.sow(seeds);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Reset the seed of the random data generator.
|
|
*
|
|
* _Note_: the seed array is only processed up to the first `undefined` (or `null`) value, should such be present.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#sow
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string[]} seeds - The array of seeds: the `toString()` of each value is used.
|
|
*/
|
|
sow: function (seeds)
|
|
{
|
|
// Always reset to default seed
|
|
this.n = 0xefc8249d;
|
|
this.s0 = this.hash(' ');
|
|
this.s1 = this.hash(' ');
|
|
this.s2 = this.hash(' ');
|
|
this.c = 1;
|
|
|
|
if (!seeds)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Apply any seeds
|
|
for (var i = 0; i < seeds.length && (seeds[i] != null); i++)
|
|
{
|
|
var seed = seeds[i];
|
|
|
|
this.s0 -= this.hash(seed);
|
|
this.s0 += ~~(this.s0 < 0);
|
|
this.s1 -= this.hash(seed);
|
|
this.s1 += ~~(this.s1 < 0);
|
|
this.s2 -= this.hash(seed);
|
|
this.s2 += ~~(this.s2 < 0);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Returns a random integer between 0 and 2^32.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#integer
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} A random integer between 0 and 2^32.
|
|
*/
|
|
integer: function ()
|
|
{
|
|
// 2^32
|
|
return this.rnd() * 0x100000000;
|
|
},
|
|
|
|
/**
|
|
* Returns a random real number between 0 and 1.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#frac
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} A random real number between 0 and 1.
|
|
*/
|
|
frac: function ()
|
|
{
|
|
// 2^-53
|
|
return this.rnd() + (this.rnd() * 0x200000 | 0) * 1.1102230246251565e-16;
|
|
},
|
|
|
|
/**
|
|
* Returns a random real number between 0 and 2^32.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#real
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} A random real number between 0 and 2^32.
|
|
*/
|
|
real: function ()
|
|
{
|
|
return this.integer() + this.frac();
|
|
},
|
|
|
|
/**
|
|
* Returns a random integer between and including min and max.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#integerInRange
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} min - The minimum value in the range.
|
|
* @param {number} max - The maximum value in the range.
|
|
*
|
|
* @return {number} A random number between min and max.
|
|
*/
|
|
integerInRange: function (min, max)
|
|
{
|
|
return Math.floor(this.realInRange(0, max - min + 1) + min);
|
|
},
|
|
|
|
/**
|
|
* Returns a random integer between and including min and max.
|
|
* This method is an alias for RandomDataGenerator.integerInRange.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#between
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} min - The minimum value in the range.
|
|
* @param {number} max - The maximum value in the range.
|
|
*
|
|
* @return {number} A random number between min and max.
|
|
*/
|
|
between: function (min, max)
|
|
{
|
|
return Math.floor(this.realInRange(0, max - min + 1) + min);
|
|
},
|
|
|
|
/**
|
|
* Returns a random real number between min and max.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#realInRange
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} min - The minimum value in the range.
|
|
* @param {number} max - The maximum value in the range.
|
|
*
|
|
* @return {number} A random number between min and max.
|
|
*/
|
|
realInRange: function (min, max)
|
|
{
|
|
return this.frac() * (max - min) + min;
|
|
},
|
|
|
|
/**
|
|
* Returns a random real number between -1 and 1.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#normal
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} A random real number between -1 and 1.
|
|
*/
|
|
normal: function ()
|
|
{
|
|
return 1 - (2 * this.frac());
|
|
},
|
|
|
|
/**
|
|
* Returns a valid RFC4122 version4 ID hex string from https://gist.github.com/1308368
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#uuid
|
|
* @since 3.0.0
|
|
*
|
|
* @return {string} A valid RFC4122 version4 ID hex string
|
|
*/
|
|
uuid: function ()
|
|
{
|
|
var a = '';
|
|
var b = '';
|
|
|
|
for (b = a = ''; a++ < 36; b += ~a % 5 | a * 3 & 4 ? (a ^ 15 ? 8 ^ this.frac() * (a ^ 20 ? 16 : 4) : 4).toString(16) : '-')
|
|
{
|
|
// eslint-disable-next-line no-empty
|
|
}
|
|
|
|
return b;
|
|
},
|
|
|
|
/**
|
|
* Returns a random element from within the given array.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#pick
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[]} - [array]
|
|
* @genericUse {T} - [$return]
|
|
*
|
|
* @param {T[]} array - The array to pick a random element from.
|
|
*
|
|
* @return {T} A random member of the array.
|
|
*/
|
|
pick: function (array)
|
|
{
|
|
return array[this.integerInRange(0, array.length - 1)];
|
|
},
|
|
|
|
/**
|
|
* Returns a sign to be used with multiplication operator.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#sign
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} -1 or +1.
|
|
*/
|
|
sign: function ()
|
|
{
|
|
return this.pick(this.signs);
|
|
},
|
|
|
|
/**
|
|
* Returns a random element from within the given array, favoring the earlier entries.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#weightedPick
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[]} - [array]
|
|
* @genericUse {T} - [$return]
|
|
*
|
|
* @param {T[]} array - The array to pick a random element from.
|
|
*
|
|
* @return {T} A random member of the array.
|
|
*/
|
|
weightedPick: function (array)
|
|
{
|
|
return array[~~(Math.pow(this.frac(), 2) * (array.length - 1) + 0.5)];
|
|
},
|
|
|
|
/**
|
|
* Returns a random timestamp between min and max, or between the beginning of 2000 and the end of 2020 if min and max aren't specified.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#timestamp
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} min - The minimum value in the range.
|
|
* @param {number} max - The maximum value in the range.
|
|
*
|
|
* @return {number} A random timestamp between min and max.
|
|
*/
|
|
timestamp: function (min, max)
|
|
{
|
|
return this.realInRange(min || 946684800000, max || 1577862000000);
|
|
},
|
|
|
|
/**
|
|
* Returns a random angle between -180 and 180.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#angle
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} A random number between -180 and 180.
|
|
*/
|
|
angle: function ()
|
|
{
|
|
return this.integerInRange(-180, 180);
|
|
},
|
|
|
|
/**
|
|
* Returns a random rotation in radians, between -3.141 and 3.141
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#rotation
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} A random number between -3.141 and 3.141
|
|
*/
|
|
rotation: function ()
|
|
{
|
|
return this.realInRange(-3.1415926, 3.1415926);
|
|
},
|
|
|
|
/**
|
|
* Gets or Sets the state of the generator. This allows you to retain the values
|
|
* that the generator is using between games, i.e. in a game save file.
|
|
*
|
|
* To seed this generator with a previously saved state you can pass it as the
|
|
* `seed` value in your game config, or call this method directly after Phaser has booted.
|
|
*
|
|
* Call this method with no parameters to return the current state.
|
|
*
|
|
* If providing a state it should match the same format that this method
|
|
* returns, which is a string with a header `!rnd` followed by the `c`,
|
|
* `s0`, `s1` and `s2` values respectively, each comma-delimited.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#state
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} [state] - Generator state to be set.
|
|
*
|
|
* @return {string} The current state of the generator.
|
|
*/
|
|
state: function (state)
|
|
{
|
|
if (typeof state === 'string' && state.match(/^!rnd/))
|
|
{
|
|
state = state.split(',');
|
|
|
|
this.c = parseFloat(state[1]);
|
|
this.s0 = parseFloat(state[2]);
|
|
this.s1 = parseFloat(state[3]);
|
|
this.s2 = parseFloat(state[4]);
|
|
}
|
|
|
|
return [ '!rnd', this.c, this.s0, this.s1, this.s2 ].join(',');
|
|
},
|
|
|
|
/**
|
|
* Shuffles the given array, using the current seed.
|
|
*
|
|
* @method Phaser.Math.RandomDataGenerator#shuffle
|
|
* @since 3.7.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[]} - [array,$return]
|
|
*
|
|
* @param {T[]} [array] - The array to be shuffled.
|
|
*
|
|
* @return {T[]} The shuffled array.
|
|
*/
|
|
shuffle: function (array)
|
|
{
|
|
var len = array.length - 1;
|
|
|
|
for (var i = len; i > 0; i--)
|
|
{
|
|
var randomIndex = Math.floor(this.frac() * (i + 1));
|
|
var itemAtIndex = array[randomIndex];
|
|
|
|
array[randomIndex] = array[i];
|
|
array[i] = itemAtIndex;
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = RandomDataGenerator;
|
|
|
|
|
|
/***/ }),
|
|
/* 157 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the mean average of the given values.
|
|
*
|
|
* @function Phaser.Math.Average
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number[]} values - The values to average.
|
|
*
|
|
* @return {number} The average value.
|
|
*/
|
|
var Average = function (values)
|
|
{
|
|
var sum = 0;
|
|
|
|
for (var i = 0; i < values.length; i++)
|
|
{
|
|
sum += (+values[i]);
|
|
}
|
|
|
|
return sum / values.length;
|
|
};
|
|
|
|
module.exports = Average;
|
|
|
|
|
|
/***/ }),
|
|
/* 158 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Compute a random integer between the `min` and `max` values, inclusive.
|
|
*
|
|
* @function Phaser.Math.Between
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} min - The minimum value.
|
|
* @param {number} max - The maximum value.
|
|
*
|
|
* @return {number} The random integer.
|
|
*/
|
|
var Between = function (min, max)
|
|
{
|
|
return Math.floor(Math.random() * (max - min + 1) + min);
|
|
};
|
|
|
|
module.exports = Between;
|
|
|
|
|
|
/***/ }),
|
|
/* 159 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Ceils to some place comparative to a `base`, default is 10 for decimal place.
|
|
*
|
|
* The `place` is represented by the power applied to `base` to get that place.
|
|
*
|
|
* @function Phaser.Math.CeilTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to round.
|
|
* @param {number} [place=0] - The place to round to.
|
|
* @param {number} [base=10] - The base to round in. Default is 10 for decimal.
|
|
*
|
|
* @return {number} The rounded value.
|
|
*/
|
|
var CeilTo = function (value, place, base)
|
|
{
|
|
if (place === undefined) { place = 0; }
|
|
if (base === undefined) { base = 10; }
|
|
|
|
var p = Math.pow(base, -place);
|
|
|
|
return Math.ceil(value * p) / p;
|
|
};
|
|
|
|
module.exports = CeilTo;
|
|
|
|
|
|
/***/ }),
|
|
/* 160 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculates the positive difference of two given numbers.
|
|
*
|
|
* @function Phaser.Math.Difference
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} a - The first number in the calculation.
|
|
* @param {number} b - The second number in the calculation.
|
|
*
|
|
* @return {number} The positive difference of the two given numbers.
|
|
*/
|
|
var Difference = function (a, b)
|
|
{
|
|
return Math.abs(a - b);
|
|
};
|
|
|
|
module.exports = Difference;
|
|
|
|
|
|
/***/ }),
|
|
/* 161 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Clamp = __webpack_require__(1);
|
|
var Class = __webpack_require__(0);
|
|
var Matrix4 = __webpack_require__(22);
|
|
var NOOP = __webpack_require__(2);
|
|
|
|
var tempMatrix = new Matrix4();
|
|
|
|
/**
|
|
* @classdesc
|
|
*
|
|
* @class Euler
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.50.0
|
|
*
|
|
* @param {number} [x] - The x component.
|
|
* @param {number} [y] - The y component.
|
|
* @param {number} [z] - The z component.
|
|
*/
|
|
var Euler = new Class({
|
|
|
|
initialize:
|
|
|
|
function Euler (x, y, z, order)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = 0; }
|
|
if (z === undefined) { z = 0; }
|
|
if (order === undefined) { order = Euler.DefaultOrder; }
|
|
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._order = order;
|
|
|
|
this.onChangeCallback = NOOP;
|
|
},
|
|
|
|
x: {
|
|
get: function ()
|
|
{
|
|
return this._x;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._x = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
y: {
|
|
get: function ()
|
|
{
|
|
return this._y;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._y = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
z: {
|
|
get: function ()
|
|
{
|
|
return this._z;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._z = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
order: {
|
|
get: function ()
|
|
{
|
|
return this._order;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._order = value;
|
|
|
|
this.onChangeCallback(this);
|
|
}
|
|
},
|
|
|
|
set: function (x, y, z, order)
|
|
{
|
|
if (order === undefined) { order = this._order; }
|
|
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._order = order;
|
|
|
|
this.onChangeCallback(this);
|
|
|
|
return this;
|
|
},
|
|
|
|
copy: function (euler)
|
|
{
|
|
return this.set(euler.x, euler.y, euler.z, euler.order);
|
|
},
|
|
|
|
setFromQuaternion: function (quaternion, order, update)
|
|
{
|
|
if (order === undefined) { order = this._order; }
|
|
if (update === undefined) { update = false; }
|
|
|
|
tempMatrix.fromQuat(quaternion);
|
|
|
|
return this.setFromRotationMatrix(tempMatrix, order, update);
|
|
},
|
|
|
|
setFromRotationMatrix: function (matrix, order, update)
|
|
{
|
|
if (order === undefined) { order = this._order; }
|
|
if (update === undefined) { update = false; }
|
|
|
|
var elements = matrix.val;
|
|
|
|
// Upper 3x3 of matrix is un-scaled rotation matrix
|
|
var m11 = elements[0];
|
|
var m12 = elements[4];
|
|
var m13 = elements[8];
|
|
var m21 = elements[1];
|
|
var m22 = elements[5];
|
|
var m23 = elements[9];
|
|
var m31 = elements[2];
|
|
var m32 = elements[6];
|
|
var m33 = elements[10];
|
|
|
|
var x = 0;
|
|
var y = 0;
|
|
var z = 0;
|
|
var epsilon = 0.99999;
|
|
|
|
switch (order)
|
|
{
|
|
case 'XYZ':
|
|
{
|
|
y = Math.asin(Clamp(m13, -1, 1));
|
|
|
|
if (Math.abs(m13) < epsilon)
|
|
{
|
|
x = Math.atan2(-m23, m33);
|
|
z = Math.atan2(-m12, m11);
|
|
}
|
|
else
|
|
{
|
|
x = Math.atan2(m32, m22);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'YXZ':
|
|
{
|
|
x = Math.asin(-Clamp(m23, -1, 1));
|
|
|
|
if (Math.abs(m23) < epsilon)
|
|
{
|
|
y = Math.atan2(m13, m33);
|
|
z = Math.atan2(m21, m22);
|
|
}
|
|
else
|
|
{
|
|
y = Math.atan2(-m31, m11);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'ZXY':
|
|
{
|
|
x = Math.asin(Clamp(m32, -1, 1));
|
|
|
|
if (Math.abs(m32) < epsilon)
|
|
{
|
|
y = Math.atan2(-m31, m33);
|
|
z = Math.atan2(-m12, m22);
|
|
}
|
|
else
|
|
{
|
|
z = Math.atan2(m21, m11);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'ZYX':
|
|
{
|
|
y = Math.asin(-Clamp(m31, -1, 1));
|
|
|
|
if (Math.abs(m31) < epsilon)
|
|
{
|
|
x = Math.atan2(m32, m33);
|
|
z = Math.atan2(m21, m11);
|
|
}
|
|
else
|
|
{
|
|
z = Math.atan2(-m12, m22);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'YZX':
|
|
{
|
|
z = Math.asin(Clamp(m21, -1, 1));
|
|
|
|
if (Math.abs(m21) < epsilon)
|
|
{
|
|
x = Math.atan2(-m23, m22);
|
|
y = Math.atan2(-m31, m11);
|
|
}
|
|
else
|
|
{
|
|
y = Math.atan2(m13, m33);
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
case 'XZY':
|
|
{
|
|
z = Math.asin(-Clamp(m12, -1, 1));
|
|
|
|
if (Math.abs(m12) < epsilon)
|
|
{
|
|
x = Math.atan2(m32, m22);
|
|
y = Math.atan2(m13, m11);
|
|
}
|
|
else
|
|
{
|
|
x = Math.atan2(-m23, m33);
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
|
|
this._x = x;
|
|
this._y = y;
|
|
this._z = z;
|
|
this._order = order;
|
|
|
|
if (update)
|
|
{
|
|
this.onChangeCallback(this);
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
});
|
|
|
|
Euler.RotationOrders = [ 'XYZ', 'YXZ', 'ZXY', 'ZYX', 'YZX', 'XZY' ];
|
|
|
|
Euler.DefaultOrder = 'XYZ';
|
|
|
|
module.exports = Euler;
|
|
|
|
|
|
/***/ }),
|
|
/* 162 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Floors to some place comparative to a `base`, default is 10 for decimal place.
|
|
*
|
|
* The `place` is represented by the power applied to `base` to get that place.
|
|
*
|
|
* @function Phaser.Math.FloorTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to round.
|
|
* @param {number} [place=0] - The place to round to.
|
|
* @param {number} [base=10] - The base to round in. Default is 10 for decimal.
|
|
*
|
|
* @return {number} The rounded value.
|
|
*/
|
|
var FloorTo = function (value, place, base)
|
|
{
|
|
if (place === undefined) { place = 0; }
|
|
if (base === undefined) { base = 10; }
|
|
|
|
var p = Math.pow(base, -place);
|
|
|
|
return Math.floor(value * p) / p;
|
|
};
|
|
|
|
module.exports = FloorTo;
|
|
|
|
|
|
/***/ }),
|
|
/* 163 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Clamp = __webpack_require__(1);
|
|
|
|
/**
|
|
* Return a value based on the range between `min` and `max` and the percentage given.
|
|
*
|
|
* @function Phaser.Math.FromPercent
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} percent - A value between 0 and 1 representing the percentage.
|
|
* @param {number} min - The minimum value.
|
|
* @param {number} [max] - The maximum value.
|
|
*
|
|
* @return {number} The value that is `percent` percent between `min` and `max`.
|
|
*/
|
|
var FromPercent = function (percent, min, max)
|
|
{
|
|
percent = Clamp(percent, 0, 1);
|
|
|
|
return (max - min) * percent + min;
|
|
};
|
|
|
|
module.exports = FromPercent;
|
|
|
|
|
|
/***/ }),
|
|
/* 164 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate a per-ms speed from a distance and time (given in seconds).
|
|
*
|
|
* @function Phaser.Math.GetSpeed
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} distance - The distance.
|
|
* @param {number} time - The time, in seconds.
|
|
*
|
|
* @return {number} The speed, in distance per ms.
|
|
*
|
|
* @example
|
|
* // 400px over 1 second is 0.4 px/ms
|
|
* Phaser.Math.GetSpeed(400, 1) // -> 0.4
|
|
*/
|
|
var GetSpeed = function (distance, time)
|
|
{
|
|
return (distance / time) / 1000;
|
|
};
|
|
|
|
module.exports = GetSpeed;
|
|
|
|
|
|
/***/ }),
|
|
/* 165 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Check if a given value is an even number.
|
|
*
|
|
* @function Phaser.Math.IsEven
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The number to perform the check with.
|
|
*
|
|
* @return {boolean} Whether the number is even or not.
|
|
*/
|
|
var IsEven = function (value)
|
|
{
|
|
// Use abstract equality == for "is number" test
|
|
|
|
// eslint-disable-next-line eqeqeq
|
|
return (value == parseFloat(value)) ? !(value % 2) : void 0;
|
|
};
|
|
|
|
module.exports = IsEven;
|
|
|
|
|
|
/***/ }),
|
|
/* 166 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Check if a given value is an even number using a strict type check.
|
|
*
|
|
* @function Phaser.Math.IsEvenStrict
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The number to perform the check with.
|
|
*
|
|
* @return {boolean} Whether the number is even or not.
|
|
*/
|
|
var IsEvenStrict = function (value)
|
|
{
|
|
// Use strict equality === for "is number" test
|
|
return (value === parseFloat(value)) ? !(value % 2) : void 0;
|
|
};
|
|
|
|
module.exports = IsEvenStrict;
|
|
|
|
|
|
/***/ }),
|
|
/* 167 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Greg McLean <GregDevProjects>
|
|
* @copyright 2021 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Interpolates two given Vectors and returns a new Vector between them.
|
|
*
|
|
* Does not modify either of the passed Vectors.
|
|
*
|
|
* @function Phaser.Math.LinearXY
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Math.Vector2} vector1 - Starting vector
|
|
* @param {Phaser.Math.Vector2} vector2 - Ending vector
|
|
* @param {number} [t=0] - The percentage between vector1 and vector2 to return, represented as a number between 0 and 1.
|
|
*
|
|
* @return {Phaser.Math.Vector2} The step t% of the way between vector1 and vector2.
|
|
*/
|
|
var LinearXY = function (vector1, vector2, t)
|
|
{
|
|
if (t === undefined) { t = 0; }
|
|
|
|
return vector1.clone().lerp(vector2, t);
|
|
};
|
|
|
|
module.exports = LinearXY;
|
|
|
|
|
|
/***/ }),
|
|
/* 168 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Add an `amount` to a `value`, limiting the maximum result to `max`.
|
|
*
|
|
* @function Phaser.Math.MaxAdd
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to add to.
|
|
* @param {number} amount - The amount to add.
|
|
* @param {number} max - The maximum value to return.
|
|
*
|
|
* @return {number} The resulting value.
|
|
*/
|
|
var MaxAdd = function (value, amount, max)
|
|
{
|
|
return Math.min(value + amount, max);
|
|
};
|
|
|
|
module.exports = MaxAdd;
|
|
|
|
|
|
/***/ }),
|
|
/* 169 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Vladislav Forsh <vlad@robowhale.com>
|
|
* @copyright 2021 RoboWhale
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the median of the given values. The values are sorted and the middle value is returned.
|
|
* In case of an even number of values, the average of the two middle values is returned.
|
|
*
|
|
* @function Phaser.Math.Median
|
|
* @since 3.54.0
|
|
*
|
|
* @param {number[]} values - The values to average.
|
|
*
|
|
* @return {number} The median value.
|
|
*/
|
|
var Median = function (values)
|
|
{
|
|
var valuesNum = values.length;
|
|
if (valuesNum === 0)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
values.sort(function (a, b) { return a - b; });
|
|
|
|
var halfIndex = Math.floor(valuesNum / 2);
|
|
|
|
return valuesNum % 2 === 0
|
|
? (values[halfIndex] + values[halfIndex - 1]) / 2
|
|
: values[halfIndex];
|
|
};
|
|
|
|
module.exports = Median;
|
|
|
|
|
|
/***/ }),
|
|
/* 170 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Subtract an `amount` from `value`, limiting the minimum result to `min`.
|
|
*
|
|
* @function Phaser.Math.MinSub
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to subtract from.
|
|
* @param {number} amount - The amount to subtract.
|
|
* @param {number} min - The minimum value to return.
|
|
*
|
|
* @return {number} The resulting value.
|
|
*/
|
|
var MinSub = function (value, amount, min)
|
|
{
|
|
return Math.max(value - amount, min);
|
|
};
|
|
|
|
module.exports = MinSub;
|
|
|
|
|
|
/***/ }),
|
|
/* 171 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Work out what percentage `value` is of the range between `min` and `max`.
|
|
* If `max` isn't given then it will return the percentage of `value` to `min`.
|
|
*
|
|
* You can optionally specify an `upperMax` value, which is a mid-way point in the range that represents 100%, after which the % starts to go down to zero again.
|
|
*
|
|
* @function Phaser.Math.Percent
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to determine the percentage of.
|
|
* @param {number} min - The minimum value.
|
|
* @param {number} [max] - The maximum value.
|
|
* @param {number} [upperMax] - The mid-way point in the range that represents 100%.
|
|
*
|
|
* @return {number} A value between 0 and 1 representing the percentage.
|
|
*/
|
|
var Percent = function (value, min, max, upperMax)
|
|
{
|
|
if (max === undefined) { max = min + 1; }
|
|
|
|
var percentage = (value - min) / (max - min);
|
|
|
|
if (percentage > 1)
|
|
{
|
|
if (upperMax !== undefined)
|
|
{
|
|
percentage = ((upperMax - value)) / (upperMax - max);
|
|
|
|
if (percentage < 0)
|
|
{
|
|
percentage = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
percentage = 1;
|
|
}
|
|
}
|
|
else if (percentage < 0)
|
|
{
|
|
percentage = 0;
|
|
}
|
|
|
|
return percentage;
|
|
};
|
|
|
|
module.exports = Percent;
|
|
|
|
|
|
/***/ }),
|
|
/* 172 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Compute a random unit vector.
|
|
*
|
|
* Computes random values for the given vector between -1 and 1 that can be used to represent a direction.
|
|
*
|
|
* Optionally accepts a scale value to scale the resulting vector by.
|
|
*
|
|
* @function Phaser.Math.RandomXY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector2} vector - The Vector to compute random values for.
|
|
* @param {number} [scale=1] - The scale of the random values.
|
|
*
|
|
* @return {Phaser.Math.Vector2} The given Vector.
|
|
*/
|
|
var RandomXY = function (vector, scale)
|
|
{
|
|
if (scale === undefined) { scale = 1; }
|
|
|
|
var r = Math.random() * 2 * Math.PI;
|
|
|
|
vector.x = Math.cos(r) * scale;
|
|
vector.y = Math.sin(r) * scale;
|
|
|
|
return vector;
|
|
};
|
|
|
|
module.exports = RandomXY;
|
|
|
|
|
|
/***/ }),
|
|
/* 173 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Compute a random position vector in a spherical area, optionally defined by the given radius.
|
|
*
|
|
* @function Phaser.Math.RandomXYZ
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} vec3 - The Vector to compute random values for.
|
|
* @param {number} [radius=1] - The radius.
|
|
*
|
|
* @return {Phaser.Math.Vector3} The given Vector.
|
|
*/
|
|
var RandomXYZ = function (vec3, radius)
|
|
{
|
|
if (radius === undefined) { radius = 1; }
|
|
|
|
var r = Math.random() * 2 * Math.PI;
|
|
var z = (Math.random() * 2) - 1;
|
|
var zScale = Math.sqrt(1 - z * z) * radius;
|
|
|
|
vec3.x = Math.cos(r) * zScale;
|
|
vec3.y = Math.sin(r) * zScale;
|
|
vec3.z = z * radius;
|
|
|
|
return vec3;
|
|
};
|
|
|
|
module.exports = RandomXYZ;
|
|
|
|
|
|
/***/ }),
|
|
/* 174 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Compute a random four-dimensional vector.
|
|
*
|
|
* @function Phaser.Math.RandomXYZW
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector4} vec4 - The Vector to compute random values for.
|
|
* @param {number} [scale=1] - The scale of the random values.
|
|
*
|
|
* @return {Phaser.Math.Vector4} The given Vector.
|
|
*/
|
|
var RandomXYZW = function (vec4, scale)
|
|
{
|
|
if (scale === undefined) { scale = 1; }
|
|
|
|
vec4.x = (Math.random() * 2 - 1) * scale;
|
|
vec4.y = (Math.random() * 2 - 1) * scale;
|
|
vec4.z = (Math.random() * 2 - 1) * scale;
|
|
vec4.w = (Math.random() * 2 - 1) * scale;
|
|
|
|
return vec4;
|
|
};
|
|
|
|
module.exports = RandomXYZW;
|
|
|
|
|
|
/***/ }),
|
|
/* 175 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Rotate a given point by a given angle around the origin (0, 0), in an anti-clockwise direction.
|
|
*
|
|
* @function Phaser.Math.Rotate
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Geom.Point|object)} point - The point to be rotated.
|
|
* @param {number} angle - The angle to be rotated by in an anticlockwise direction.
|
|
*
|
|
* @return {Phaser.Geom.Point} The given point, rotated by the given angle in an anticlockwise direction.
|
|
*/
|
|
var Rotate = function (point, angle)
|
|
{
|
|
var x = point.x;
|
|
var y = point.y;
|
|
|
|
point.x = (x * Math.cos(angle)) - (y * Math.sin(angle));
|
|
point.y = (x * Math.sin(angle)) + (y * Math.cos(angle));
|
|
|
|
return point;
|
|
};
|
|
|
|
module.exports = Rotate;
|
|
|
|
|
|
/***/ }),
|
|
/* 176 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Rotate a `point` around `x` and `y` by the given `angle` and `distance`.
|
|
*
|
|
* In polar notation, this maps a point from (r, t) to (distance, t + angle), vs. the origin (x, y).
|
|
*
|
|
* @function Phaser.Math.RotateAroundDistance
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Types.Math.Vector2Like} T - [point,$return]
|
|
*
|
|
* @param {(Phaser.Geom.Point|object)} point - The point to be rotated.
|
|
* @param {number} x - The horizontal coordinate to rotate around.
|
|
* @param {number} y - The vertical coordinate to rotate around.
|
|
* @param {number} angle - The angle of rotation in radians.
|
|
* @param {number} distance - The distance from (x, y) to place the point at.
|
|
*
|
|
* @return {Phaser.Types.Math.Vector2Like} The given point.
|
|
*/
|
|
var RotateAroundDistance = function (point, x, y, angle, distance)
|
|
{
|
|
var t = angle + Math.atan2(point.y - y, point.x - x);
|
|
|
|
point.x = x + (distance * Math.cos(t));
|
|
point.y = y + (distance * Math.sin(t));
|
|
|
|
return point;
|
|
};
|
|
|
|
module.exports = RotateAroundDistance;
|
|
|
|
|
|
/***/ }),
|
|
/* 177 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author samme
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Position a `point` at the given `angle` and `distance` to (`x`, `y`).
|
|
*
|
|
* @function Phaser.Math.RotateTo
|
|
* @since 3.24.0
|
|
*
|
|
* @generic {Phaser.Types.Math.Vector2Like} T - [point,$return]
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} point - The point to be positioned.
|
|
* @param {number} x - The horizontal coordinate to position from.
|
|
* @param {number} y - The vertical coordinate to position from.
|
|
* @param {number} angle - The angle of rotation in radians.
|
|
* @param {number} distance - The distance from (x, y) to place the point at.
|
|
*
|
|
* @return {Phaser.Types.Math.Vector2Like} The given point.
|
|
*/
|
|
var RotateTo = function (point, x, y, angle, distance)
|
|
{
|
|
point.x = x + (distance * Math.cos(angle));
|
|
point.y = y + (distance * Math.sin(angle));
|
|
|
|
return point;
|
|
};
|
|
|
|
module.exports = RotateTo;
|
|
|
|
|
|
/***/ }),
|
|
/* 178 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Round a value to the given precision.
|
|
*
|
|
* For example:
|
|
*
|
|
* ```javascript
|
|
* RoundTo(123.456, 0) = 123
|
|
* RoundTo(123.456, 1) = 120
|
|
* RoundTo(123.456, 2) = 100
|
|
* ```
|
|
*
|
|
* To round the decimal, i.e. to round to precision, pass in a negative `place`:
|
|
*
|
|
* ```javascript
|
|
* RoundTo(123.456789, 0) = 123
|
|
* RoundTo(123.456789, -1) = 123.5
|
|
* RoundTo(123.456789, -2) = 123.46
|
|
* RoundTo(123.456789, -3) = 123.457
|
|
* ```
|
|
*
|
|
* @function Phaser.Math.RoundTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to round.
|
|
* @param {number} [place=0] - The place to round to. Positive to round the units, negative to round the decimal.
|
|
* @param {number} [base=10] - The base to round in. Default is 10 for decimal.
|
|
*
|
|
* @return {number} The rounded value.
|
|
*/
|
|
var RoundTo = function (value, place, base)
|
|
{
|
|
if (place === undefined) { place = 0; }
|
|
if (base === undefined) { base = 10; }
|
|
|
|
var p = Math.pow(base, -place);
|
|
|
|
return Math.round(value * p) / p;
|
|
};
|
|
|
|
module.exports = RoundTo;
|
|
|
|
|
|
/***/ }),
|
|
/* 179 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Generate a series of sine and cosine values.
|
|
*
|
|
* @function Phaser.Math.SinCosTableGenerator
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} length - The number of values to generate.
|
|
* @param {number} [sinAmp=1] - The sine value amplitude.
|
|
* @param {number} [cosAmp=1] - The cosine value amplitude.
|
|
* @param {number} [frequency=1] - The frequency of the values.
|
|
*
|
|
* @return {Phaser.Types.Math.SinCosTable} The generated values.
|
|
*/
|
|
var SinCosTableGenerator = function (length, sinAmp, cosAmp, frequency)
|
|
{
|
|
if (sinAmp === undefined) { sinAmp = 1; }
|
|
if (cosAmp === undefined) { cosAmp = 1; }
|
|
if (frequency === undefined) { frequency = 1; }
|
|
|
|
frequency *= Math.PI / length;
|
|
|
|
var cos = [];
|
|
var sin = [];
|
|
|
|
for (var c = 0; c < length; c++)
|
|
{
|
|
cosAmp -= sinAmp * frequency;
|
|
sinAmp += cosAmp * frequency;
|
|
|
|
cos[c] = cosAmp;
|
|
sin[c] = sinAmp;
|
|
}
|
|
|
|
return {
|
|
sin: sin,
|
|
cos: cos,
|
|
length: length
|
|
};
|
|
};
|
|
|
|
module.exports = SinCosTableGenerator;
|
|
|
|
|
|
/***/ }),
|
|
/* 180 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
/**
|
|
* Returns a Vector2 containing the x and y position of the given index in a `width` x `height` sized grid.
|
|
*
|
|
* For example, in a 6 x 4 grid, index 16 would equal x: 4 y: 2.
|
|
*
|
|
* If the given index is out of range an empty Vector2 is returned.
|
|
*
|
|
* @function Phaser.Math.ToXY
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} index - The position within the grid to get the x/y value for.
|
|
* @param {number} width - The width of the grid.
|
|
* @param {number} height - The height of the grid.
|
|
* @param {Phaser.Math.Vector2} [out] - An optional Vector2 to store the result in. If not given, a new Vector2 instance will be created.
|
|
*
|
|
* @return {Phaser.Math.Vector2} A Vector2 where the x and y properties contain the given grid index.
|
|
*/
|
|
var ToXY = function (index, width, height, out)
|
|
{
|
|
if (out === undefined) { out = new Vector2(); }
|
|
|
|
var x = 0;
|
|
var y = 0;
|
|
var total = width * height;
|
|
|
|
if (index > 0 && index <= total)
|
|
{
|
|
if (index > width - 1)
|
|
{
|
|
y = Math.floor(index / width);
|
|
x = index - (y * width);
|
|
}
|
|
else
|
|
{
|
|
x = index;
|
|
}
|
|
}
|
|
|
|
return out.set(x, y);
|
|
};
|
|
|
|
module.exports = ToXY;
|
|
|
|
|
|
/***/ }),
|
|
/* 181 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Checks if the two values are within the given `tolerance` of each other.
|
|
*
|
|
* @function Phaser.Math.Within
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} a - The first value to use in the calculation.
|
|
* @param {number} b - The second value to use in the calculation.
|
|
* @param {number} tolerance - The tolerance. Anything equal to or less than this value is considered as being within range.
|
|
*
|
|
* @return {boolean} Returns `true` if `a` is less than or equal to the tolerance of `b`.
|
|
*/
|
|
var Within = function (a, b, tolerance)
|
|
{
|
|
return (Math.abs(a - b) <= tolerance);
|
|
};
|
|
|
|
module.exports = Within;
|
|
|
|
|
|
/***/ }),
|
|
/* 182 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Adapted from [gl-matrix](https://github.com/toji/gl-matrix) by toji
|
|
// and [vecmath](https://github.com/mattdesl/vecmath) by mattdesl
|
|
|
|
var Class = __webpack_require__(0);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A representation of a vector in 4D space.
|
|
*
|
|
* A four-component vector.
|
|
*
|
|
* @class Vector4
|
|
* @memberof Phaser.Math
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x] - The x component.
|
|
* @param {number} [y] - The y component.
|
|
* @param {number} [z] - The z component.
|
|
* @param {number} [w] - The w component.
|
|
*/
|
|
var Vector4 = new Class({
|
|
|
|
initialize:
|
|
|
|
function Vector4 (x, y, z, w)
|
|
{
|
|
/**
|
|
* The x component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector4#x
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.x = 0;
|
|
|
|
/**
|
|
* The y component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector4#y
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.y = 0;
|
|
|
|
/**
|
|
* The z component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector4#z
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.z = 0;
|
|
|
|
/**
|
|
* The w component of this Vector.
|
|
*
|
|
* @name Phaser.Math.Vector4#w
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
this.w = 0;
|
|
|
|
if (typeof x === 'object')
|
|
{
|
|
this.x = x.x || 0;
|
|
this.y = x.y || 0;
|
|
this.z = x.z || 0;
|
|
this.w = x.w || 0;
|
|
}
|
|
else
|
|
{
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
this.z = z || 0;
|
|
this.w = w || 0;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Make a clone of this Vector4.
|
|
*
|
|
* @method Phaser.Math.Vector4#clone
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector4} A clone of this Vector4.
|
|
*/
|
|
clone: function ()
|
|
{
|
|
return new Vector4(this.x, this.y, this.z, this.w);
|
|
},
|
|
|
|
/**
|
|
* Copy the components of a given Vector into this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#copy
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector4} src - The Vector to copy the components from.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
copy: function (src)
|
|
{
|
|
this.x = src.x;
|
|
this.y = src.y;
|
|
this.z = src.z || 0;
|
|
this.w = src.w || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Check whether this Vector is equal to a given Vector.
|
|
*
|
|
* Performs a strict quality check against each Vector's components.
|
|
*
|
|
* @method Phaser.Math.Vector4#equals
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector4} v - The vector to check equality with.
|
|
*
|
|
* @return {boolean} A boolean indicating whether the two Vectors are equal or not.
|
|
*/
|
|
equals: function (v)
|
|
{
|
|
return ((this.x === v.x) && (this.y === v.y) && (this.z === v.z) && (this.w === v.w));
|
|
},
|
|
|
|
/**
|
|
* Set the `x`, `y`, `z` and `w` components of the this Vector to the given `x`, `y`, `z` and `w` values.
|
|
*
|
|
* @method Phaser.Math.Vector4#set
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(number|object)} x - The x value to set for this Vector, or an object containing x, y, z and w components.
|
|
* @param {number} y - The y value to set for this Vector.
|
|
* @param {number} z - The z value to set for this Vector.
|
|
* @param {number} w - The z value to set for this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
set: function (x, y, z, w)
|
|
{
|
|
if (typeof x === 'object')
|
|
{
|
|
this.x = x.x || 0;
|
|
this.y = x.y || 0;
|
|
this.z = x.z || 0;
|
|
this.w = x.w || 0;
|
|
}
|
|
else
|
|
{
|
|
this.x = x || 0;
|
|
this.y = y || 0;
|
|
this.z = z || 0;
|
|
this.w = w || 0;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Add a given Vector to this Vector. Addition is component-wise.
|
|
*
|
|
* @method Phaser.Math.Vector4#add
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to add to this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
add: function (v)
|
|
{
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
this.z += v.z || 0;
|
|
this.w += v.w || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Subtract the given Vector from this Vector. Subtraction is component-wise.
|
|
*
|
|
* @method Phaser.Math.Vector4#subtract
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to subtract from this Vector.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
subtract: function (v)
|
|
{
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
this.z -= v.z || 0;
|
|
this.w -= v.w || 0;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Scale this Vector by the given value.
|
|
*
|
|
* @method Phaser.Math.Vector4#scale
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} scale - The value to scale this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
scale: function (scale)
|
|
{
|
|
this.x *= scale;
|
|
this.y *= scale;
|
|
this.z *= scale;
|
|
this.w *= scale;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the length (or magnitude) of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#length
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Vector.
|
|
*/
|
|
length: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var w = this.w;
|
|
|
|
return Math.sqrt(x * x + y * y + z * z + w * w);
|
|
},
|
|
|
|
/**
|
|
* Calculate the length of this Vector squared.
|
|
*
|
|
* @method Phaser.Math.Vector4#lengthSq
|
|
* @since 3.0.0
|
|
*
|
|
* @return {number} The length of this Vector, squared.
|
|
*/
|
|
lengthSq: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var w = this.w;
|
|
|
|
return x * x + y * y + z * z + w * w;
|
|
},
|
|
|
|
/**
|
|
* Normalize this Vector.
|
|
*
|
|
* Makes the vector a unit length vector (magnitude of 1) in the same direction.
|
|
*
|
|
* @method Phaser.Math.Vector4#normalize
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
normalize: function ()
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var w = this.w;
|
|
var len = x * x + y * y + z * z + w * w;
|
|
|
|
if (len > 0)
|
|
{
|
|
len = 1 / Math.sqrt(len);
|
|
|
|
this.x = x * len;
|
|
this.y = y * len;
|
|
this.z = z * len;
|
|
this.w = w * len;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the dot product of this Vector and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#dot
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector4} v - The Vector4 to dot product with this Vector4.
|
|
*
|
|
* @return {number} The dot product of this Vector and the given Vector.
|
|
*/
|
|
dot: function (v)
|
|
{
|
|
return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
|
|
},
|
|
|
|
/**
|
|
* Linearly interpolate between this Vector and the given Vector.
|
|
*
|
|
* Interpolates this Vector towards the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#lerp
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector4} v - The Vector4 to interpolate towards.
|
|
* @param {number} [t=0] - The interpolation percentage, between 0 and 1.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
lerp: function (v, t)
|
|
{
|
|
if (t === undefined) { t = 0; }
|
|
|
|
var ax = this.x;
|
|
var ay = this.y;
|
|
var az = this.z;
|
|
var aw = this.w;
|
|
|
|
this.x = ax + t * (v.x - ax);
|
|
this.y = ay + t * (v.y - ay);
|
|
this.z = az + t * (v.z - az);
|
|
this.w = aw + t * (v.w - aw);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Perform a component-wise multiplication between this Vector and the given Vector.
|
|
*
|
|
* Multiplies this Vector by the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#multiply
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to multiply this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
multiply: function (v)
|
|
{
|
|
this.x *= v.x;
|
|
this.y *= v.y;
|
|
this.z *= v.z || 1;
|
|
this.w *= v.w || 1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Perform a component-wise division between this Vector and the given Vector.
|
|
*
|
|
* Divides this Vector by the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#divide
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to divide this Vector by.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
divide: function (v)
|
|
{
|
|
this.x /= v.x;
|
|
this.y /= v.y;
|
|
this.z /= v.z || 1;
|
|
this.w /= v.w || 1;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance between this Vector and the given Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#distance
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to calculate the distance to.
|
|
*
|
|
* @return {number} The distance from this Vector to the given Vector.
|
|
*/
|
|
distance: function (v)
|
|
{
|
|
var dx = v.x - this.x;
|
|
var dy = v.y - this.y;
|
|
var dz = v.z - this.z || 0;
|
|
var dw = v.w - this.w || 0;
|
|
|
|
return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw);
|
|
},
|
|
|
|
/**
|
|
* Calculate the distance between this Vector and the given Vector, squared.
|
|
*
|
|
* @method Phaser.Math.Vector4#distanceSq
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Math.Vector2|Phaser.Math.Vector3|Phaser.Math.Vector4)} v - The Vector to calculate the distance to.
|
|
*
|
|
* @return {number} The distance from this Vector to the given Vector, squared.
|
|
*/
|
|
distanceSq: function (v)
|
|
{
|
|
var dx = v.x - this.x;
|
|
var dy = v.y - this.y;
|
|
var dz = v.z - this.z || 0;
|
|
var dw = v.w - this.w || 0;
|
|
|
|
return dx * dx + dy * dy + dz * dz + dw * dw;
|
|
},
|
|
|
|
/**
|
|
* Negate the `x`, `y`, `z` and `w` components of this Vector.
|
|
*
|
|
* @method Phaser.Math.Vector4#negate
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
negate: function ()
|
|
{
|
|
this.x = -this.x;
|
|
this.y = -this.y;
|
|
this.z = -this.z;
|
|
this.w = -this.w;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform this Vector with the given Matrix.
|
|
*
|
|
* @method Phaser.Math.Vector4#transformMat4
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Matrix4} mat - The Matrix4 to transform this Vector4 with.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
transformMat4: function (mat)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var w = this.w;
|
|
var m = mat.val;
|
|
|
|
this.x = m[0] * x + m[4] * y + m[8] * z + m[12] * w;
|
|
this.y = m[1] * x + m[5] * y + m[9] * z + m[13] * w;
|
|
this.z = m[2] * x + m[6] * y + m[10] * z + m[14] * w;
|
|
this.w = m[3] * x + m[7] * y + m[11] * z + m[15] * w;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Transform this Vector with the given Quaternion.
|
|
*
|
|
* @method Phaser.Math.Vector4#transformQuat
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Quaternion} q - The Quaternion to transform this Vector with.
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
transformQuat: function (q)
|
|
{
|
|
var x = this.x;
|
|
var y = this.y;
|
|
var z = this.z;
|
|
var qx = q.x;
|
|
var qy = q.y;
|
|
var qz = q.z;
|
|
var qw = q.w;
|
|
|
|
// calculate quat * vec
|
|
var ix = qw * x + qy * z - qz * y;
|
|
var iy = qw * y + qz * x - qx * z;
|
|
var iz = qw * z + qx * y - qy * x;
|
|
var iw = -qx * x - qy * y - qz * z;
|
|
|
|
// calculate result * inverse quat
|
|
this.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
|
|
this.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
|
|
this.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Make this Vector the zero vector (0, 0, 0, 0).
|
|
*
|
|
* @method Phaser.Math.Vector4#reset
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Phaser.Math.Vector4} This Vector4.
|
|
*/
|
|
reset: function ()
|
|
{
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
this.w = 0;
|
|
|
|
return this;
|
|
}
|
|
|
|
});
|
|
|
|
Vector4.prototype.sub = Vector4.prototype.subtract;
|
|
Vector4.prototype.mul = Vector4.prototype.multiply;
|
|
Vector4.prototype.div = Vector4.prototype.divide;
|
|
Vector4.prototype.dist = Vector4.prototype.distance;
|
|
Vector4.prototype.distSq = Vector4.prototype.distanceSq;
|
|
Vector4.prototype.len = Vector4.prototype.length;
|
|
Vector4.prototype.lenSq = Vector4.prototype.lengthSq;
|
|
|
|
module.exports = Vector4;
|
|
|
|
|
|
/***/ }),
|
|
/* 183 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Vector3 = __webpack_require__(16);
|
|
var Matrix4 = __webpack_require__(22);
|
|
var Quaternion = __webpack_require__(46);
|
|
|
|
var tmpMat4 = new Matrix4();
|
|
var tmpQuat = new Quaternion();
|
|
var tmpVec3 = new Vector3();
|
|
|
|
/**
|
|
* Rotates a vector in place by axis angle.
|
|
*
|
|
* This is the same as transforming a point by an
|
|
* axis-angle quaternion, but it has higher precision.
|
|
*
|
|
* @function Phaser.Math.RotateVec3
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Math.Vector3} vec - The vector to be rotated.
|
|
* @param {Phaser.Math.Vector3} axis - The axis to rotate around.
|
|
* @param {number} radians - The angle of rotation in radians.
|
|
*
|
|
* @return {Phaser.Math.Vector3} The given vector.
|
|
*/
|
|
var RotateVec3 = function (vec, axis, radians)
|
|
{
|
|
// Set the quaternion to our axis angle
|
|
tmpQuat.setAxisAngle(axis, radians);
|
|
|
|
// Create a rotation matrix from the axis angle
|
|
tmpMat4.fromRotationTranslation(tmpQuat, tmpVec3.set(0, 0, 0));
|
|
|
|
// Multiply our vector by the rotation matrix
|
|
return vec.transformMat4(tmpMat4);
|
|
};
|
|
|
|
module.exports = RotateVec3;
|
|
|
|
|
|
/***/ }),
|
|
/* 184 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scale Manager Resize Event.
|
|
*
|
|
* This event is dispatched whenever the Scale Manager detects a resize event from the browser.
|
|
* It sends three parameters to the callback, each of them being Size components. You can read
|
|
* the `width`, `height`, `aspectRatio` and other properties of these components to help with
|
|
* scaling your own game content.
|
|
*
|
|
* @event Phaser.Scale.Events#RESIZE
|
|
* @type {string}
|
|
* @since 3.16.1
|
|
*
|
|
* @param {Phaser.Structs.Size} gameSize - A reference to the Game Size component. This is the un-scaled size of your game canvas.
|
|
* @param {Phaser.Structs.Size} baseSize - A reference to the Base Size component. This is the game size.
|
|
* @param {Phaser.Structs.Size} displaySize - A reference to the Display Size component. This is the scaled canvas size, after applying zoom and scale mode.
|
|
* @param {number} previousWidth - If the `gameSize` has changed, this value contains its previous width, otherwise it contains the current width.
|
|
* @param {number} previousHeight - If the `gameSize` has changed, this value contains its previous height, otherwise it contains the current height.
|
|
*/
|
|
module.exports = 'resize';
|
|
|
|
|
|
/***/ }),
|
|
/* 185 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser3-plugin-template/blob/master/LICENSE|MIT License}
|
|
*/
|
|
|
|
var BasePlugin = __webpack_require__(186);
|
|
var Class = __webpack_require__(0);
|
|
var SceneEvents = __webpack_require__(23);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Scene Level Plugin is installed into every Scene and belongs to that Scene.
|
|
* It can listen for Scene events and respond to them.
|
|
* It can map itself to a Scene property, or into the Scene Systems, or both.
|
|
*
|
|
* @class ScenePlugin
|
|
* @memberof Phaser.Plugins
|
|
* @extends Phaser.Plugins.BasePlugin
|
|
* @constructor
|
|
* @since 3.8.0
|
|
*
|
|
* @param {Phaser.Scene} scene - A reference to the Scene that has installed this plugin.
|
|
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Plugin Manager.
|
|
* @param {string} pluginKey - The key under which this plugin has been installed into the Scene Systems.
|
|
*/
|
|
var ScenePlugin = new Class({
|
|
|
|
Extends: BasePlugin,
|
|
|
|
initialize:
|
|
|
|
function ScenePlugin (scene, pluginManager, pluginKey)
|
|
{
|
|
BasePlugin.call(this, pluginManager);
|
|
|
|
/**
|
|
* A reference to the Scene that has installed this plugin.
|
|
* Only set if it's a Scene Plugin, otherwise `null`.
|
|
* This property is only set when the plugin is instantiated and added to the Scene, not before.
|
|
* You can use it during the `boot` method.
|
|
*
|
|
* @name Phaser.Plugins.ScenePlugin#scene
|
|
* @type {?Phaser.Scene}
|
|
* @protected
|
|
* @since 3.8.0
|
|
*/
|
|
this.scene = scene;
|
|
|
|
/**
|
|
* A reference to the Scene Systems of the Scene that has installed this plugin.
|
|
* Only set if it's a Scene Plugin, otherwise `null`.
|
|
* This property is only set when the plugin is instantiated and added to the Scene, not before.
|
|
* You can use it during the `boot` method.
|
|
*
|
|
* @name Phaser.Plugins.ScenePlugin#systems
|
|
* @type {?Phaser.Scenes.Systems}
|
|
* @protected
|
|
* @since 3.8.0
|
|
*/
|
|
this.systems = scene.sys;
|
|
|
|
/**
|
|
* The key under which this plugin was installed into the Scene Systems.
|
|
*
|
|
* This property is only set when the plugin is instantiated and added to the Scene, not before.
|
|
* You can use it during the `boot` method.
|
|
*
|
|
* @name Phaser.Plugins.ScenePlugin#pluginKey
|
|
* @type {string}
|
|
* @readonly
|
|
* @since 3.54.0
|
|
*/
|
|
this.pluginKey = pluginKey;
|
|
|
|
scene.sys.events.once(SceneEvents.BOOT, this.boot, this);
|
|
},
|
|
|
|
/**
|
|
* This method is called when the Scene boots. It is only ever called once.
|
|
*
|
|
* By this point the plugin properties `scene` and `systems` will have already been set.
|
|
*
|
|
* In here you can listen for {@link Phaser.Scenes.Events Scene events} and set-up whatever you need for this plugin to run.
|
|
* Here are the Scene events you can listen to:
|
|
*
|
|
* - start
|
|
* - ready
|
|
* - preupdate
|
|
* - update
|
|
* - postupdate
|
|
* - resize
|
|
* - pause
|
|
* - resume
|
|
* - sleep
|
|
* - wake
|
|
* - transitioninit
|
|
* - transitionstart
|
|
* - transitioncomplete
|
|
* - transitionout
|
|
* - shutdown
|
|
* - destroy
|
|
*
|
|
* At the very least you should offer a destroy handler for when the Scene closes down, i.e:
|
|
*
|
|
* ```javascript
|
|
* var eventEmitter = this.systems.events;
|
|
* eventEmitter.once('destroy', this.sceneDestroy, this);
|
|
* ```
|
|
*
|
|
* @method Phaser.Plugins.ScenePlugin#boot
|
|
* @since 3.8.0
|
|
*/
|
|
boot: function ()
|
|
{
|
|
},
|
|
|
|
/**
|
|
* Game instance has been destroyed.
|
|
*
|
|
* You must release everything in here, all references, all objects, free it all up.
|
|
*
|
|
* @method Phaser.Plugins.ScenePlugin#destroy
|
|
* @since 3.8.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.pluginManager = null;
|
|
this.game = null;
|
|
this.scene = null;
|
|
this.systems = null;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = ScenePlugin;
|
|
|
|
|
|
/***/ }),
|
|
/* 186 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser3-plugin-template/blob/master/LICENSE|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Global Plugin is installed just once into the Game owned Plugin Manager.
|
|
* It can listen for Game events and respond to them.
|
|
*
|
|
* @class BasePlugin
|
|
* @memberof Phaser.Plugins
|
|
* @constructor
|
|
* @since 3.8.0
|
|
*
|
|
* @param {Phaser.Plugins.PluginManager} pluginManager - A reference to the Plugin Manager.
|
|
*/
|
|
var BasePlugin = new Class({
|
|
|
|
initialize:
|
|
|
|
function BasePlugin (pluginManager)
|
|
{
|
|
/**
|
|
* A handy reference to the Plugin Manager that is responsible for this plugin.
|
|
* Can be used as a route to gain access to game systems and events.
|
|
*
|
|
* @name Phaser.Plugins.BasePlugin#pluginManager
|
|
* @type {Phaser.Plugins.PluginManager}
|
|
* @protected
|
|
* @since 3.8.0
|
|
*/
|
|
this.pluginManager = pluginManager;
|
|
|
|
/**
|
|
* A reference to the Game instance this plugin is running under.
|
|
*
|
|
* @name Phaser.Plugins.BasePlugin#game
|
|
* @type {Phaser.Game}
|
|
* @protected
|
|
* @since 3.8.0
|
|
*/
|
|
this.game = pluginManager.game;
|
|
},
|
|
|
|
/**
|
|
* The PluginManager calls this method on a Global Plugin when the plugin is first instantiated.
|
|
* It will never be called again on this instance.
|
|
* In here you can set-up whatever you need for this plugin to run.
|
|
* If a plugin is set to automatically start then `BasePlugin.start` will be called immediately after this.
|
|
* On a Scene Plugin, this method is never called. Use {@link Phaser.Plugins.ScenePlugin#boot} instead.
|
|
*
|
|
* @method Phaser.Plugins.BasePlugin#init
|
|
* @since 3.8.0
|
|
*
|
|
* @param {?any} [data] - A value specified by the user, if any, from the `data` property of the plugin's configuration object (if started at game boot) or passed in the PluginManager's `install` method (if started manually).
|
|
*/
|
|
init: function ()
|
|
{
|
|
},
|
|
|
|
/**
|
|
* The PluginManager calls this method on a Global Plugin when the plugin is started.
|
|
* If a plugin is stopped, and then started again, this will get called again.
|
|
* Typically called immediately after `BasePlugin.init`.
|
|
* On a Scene Plugin, this method is never called.
|
|
*
|
|
* @method Phaser.Plugins.BasePlugin#start
|
|
* @since 3.8.0
|
|
*/
|
|
start: function ()
|
|
{
|
|
// Here are the game-level events you can listen to.
|
|
// At the very least you should offer a destroy handler for when the game closes down.
|
|
|
|
// var eventEmitter = this.game.events;
|
|
|
|
// eventEmitter.once('destroy', this.gameDestroy, this);
|
|
// eventEmitter.on('pause', this.gamePause, this);
|
|
// eventEmitter.on('resume', this.gameResume, this);
|
|
// eventEmitter.on('resize', this.gameResize, this);
|
|
// eventEmitter.on('prestep', this.gamePreStep, this);
|
|
// eventEmitter.on('step', this.gameStep, this);
|
|
// eventEmitter.on('poststep', this.gamePostStep, this);
|
|
// eventEmitter.on('prerender', this.gamePreRender, this);
|
|
// eventEmitter.on('postrender', this.gamePostRender, this);
|
|
},
|
|
|
|
/**
|
|
* The PluginManager calls this method on a Global Plugin when the plugin is stopped.
|
|
* The game code has requested that your plugin stop doing whatever it does.
|
|
* It is now considered as 'inactive' by the PluginManager.
|
|
* Handle that process here (i.e. stop listening for events, etc)
|
|
* If the plugin is started again then `BasePlugin.start` will be called again.
|
|
* On a Scene Plugin, this method is never called.
|
|
*
|
|
* @method Phaser.Plugins.BasePlugin#stop
|
|
* @since 3.8.0
|
|
*/
|
|
stop: function ()
|
|
{
|
|
},
|
|
|
|
/**
|
|
* Game instance has been destroyed.
|
|
* You must release everything in here, all references, all objects, free it all up.
|
|
*
|
|
* @method Phaser.Plugins.BasePlugin#destroy
|
|
* @since 3.8.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.pluginManager = null;
|
|
this.game = null;
|
|
this.scene = null;
|
|
this.systems = null;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = BasePlugin;
|
|
|
|
|
|
/***/ }),
|
|
/* 187 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Game Object Added to Scene Event.
|
|
*
|
|
* This event is dispatched when a Game Object is added to a Scene.
|
|
*
|
|
* Listen for it from a Scene using `this.events.on('addedtoscene', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#ADDED_TO_SCENE
|
|
* @type {string}
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was added to the Scene.
|
|
* @param {Phaser.Scene} scene - The Scene to which the Game Object was added.
|
|
*/
|
|
module.exports = 'addedtoscene';
|
|
|
|
|
|
/***/ }),
|
|
/* 188 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Boot Event.
|
|
*
|
|
* This event is dispatched by a Scene during the Scene Systems boot process. Primarily used by Scene Plugins.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('boot', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#BOOT
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
*/
|
|
module.exports = 'boot';
|
|
|
|
|
|
/***/ }),
|
|
/* 189 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Create Event.
|
|
*
|
|
* This event is dispatched by a Scene after it has been created by the Scene Manager.
|
|
*
|
|
* If a Scene has a `create` method then this event is emitted _after_ that has run.
|
|
*
|
|
* If there is a transition, this event will be fired after the `TRANSITION_START` event.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('create', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#CREATE
|
|
* @type {string}
|
|
* @since 3.17.0
|
|
*
|
|
* @param {Phaser.Scene} scene - A reference to the Scene that emitted this event.
|
|
*/
|
|
module.exports = 'create';
|
|
|
|
|
|
/***/ }),
|
|
/* 190 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Destroy Event.
|
|
*
|
|
* This event is dispatched by a Scene during the Scene Systems destroy process.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('destroy', listener)`.
|
|
*
|
|
* You should destroy any resources that may be in use by your Scene in this event handler.
|
|
*
|
|
* @event Phaser.Scenes.Events#DESTROY
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
*/
|
|
module.exports = 'destroy';
|
|
|
|
|
|
/***/ }),
|
|
/* 191 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Pause Event.
|
|
*
|
|
* This event is dispatched by a Scene when it is paused, either directly via the `pause` method, or as an
|
|
* action from another Scene.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('pause', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#PAUSE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {any} [data] - An optional data object that was passed to this Scene when it was paused.
|
|
*/
|
|
module.exports = 'pause';
|
|
|
|
|
|
/***/ }),
|
|
/* 192 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Post Update Event.
|
|
*
|
|
* This event is dispatched by a Scene during the main game loop step.
|
|
*
|
|
* The event flow for a single step of a Scene is as follows:
|
|
*
|
|
* 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE}
|
|
* 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE}
|
|
* 3. The `Scene.update` method is called, if it exists
|
|
* 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE}
|
|
* 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER}
|
|
* 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER}
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('postupdate', listener)`.
|
|
*
|
|
* A Scene will only run its step if it is active.
|
|
*
|
|
* @event Phaser.Scenes.Events#POST_UPDATE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
|
|
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
|
|
*/
|
|
module.exports = 'postupdate';
|
|
|
|
|
|
/***/ }),
|
|
/* 193 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author samme
|
|
* @copyright 2021 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Pre-Render Event.
|
|
*
|
|
* This event is dispatched by a Scene during the main game loop step.
|
|
*
|
|
* The event flow for a single step of a Scene is as follows:
|
|
*
|
|
* 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE}
|
|
* 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE}
|
|
* 3. The `Scene.update` method is called, if it exists
|
|
* 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE}
|
|
* 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER}
|
|
* 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER}
|
|
*
|
|
* Listen to this event from a Scene using `this.events.on('prerender', listener)`.
|
|
*
|
|
* A Scene will only render if it is visible.
|
|
*
|
|
* This event is dispatched after the Scene Display List is sorted and before the Scene is rendered.
|
|
*
|
|
* @event Phaser.Scenes.Events#PRE_RENDER
|
|
* @type {string}
|
|
* @since 3.53.0
|
|
*
|
|
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The renderer that rendered the Scene.
|
|
*/
|
|
module.exports = 'prerender';
|
|
|
|
|
|
/***/ }),
|
|
/* 194 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Pre Update Event.
|
|
*
|
|
* This event is dispatched by a Scene during the main game loop step.
|
|
*
|
|
* The event flow for a single step of a Scene is as follows:
|
|
*
|
|
* 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE}
|
|
* 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE}
|
|
* 3. The `Scene.update` method is called, if it exists
|
|
* 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE}
|
|
* 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER}
|
|
* 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER}
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('preupdate', listener)`.
|
|
*
|
|
* A Scene will only run its step if it is active.
|
|
*
|
|
* @event Phaser.Scenes.Events#PRE_UPDATE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
|
|
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
|
|
*/
|
|
module.exports = 'preupdate';
|
|
|
|
|
|
/***/ }),
|
|
/* 195 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Ready Event.
|
|
*
|
|
* This event is dispatched by a Scene during the Scene Systems start process.
|
|
* By this point in the process the Scene is now fully active and rendering.
|
|
* This event is meant for your game code to use, as all plugins have responded to the earlier 'start' event.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('ready', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#READY
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {any} [data] - An optional data object that was passed to this Scene when it was started.
|
|
*/
|
|
module.exports = 'ready';
|
|
|
|
|
|
/***/ }),
|
|
/* 196 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Game Object Removed from Scene Event.
|
|
*
|
|
* This event is dispatched when a Game Object is removed from a Scene.
|
|
*
|
|
* Listen for it from a Scene using `this.events.on('removedfromscene', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#REMOVED_FROM_SCENE
|
|
* @type {string}
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was removed from the Scene.
|
|
* @param {Phaser.Scene} scene - The Scene from which the Game Object was removed.
|
|
*/
|
|
module.exports = 'removedfromscene';
|
|
|
|
|
|
/***/ }),
|
|
/* 197 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Render Event.
|
|
*
|
|
* This event is dispatched by a Scene during the main game loop step.
|
|
*
|
|
* The event flow for a single step of a Scene is as follows:
|
|
*
|
|
* 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE}
|
|
* 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE}
|
|
* 3. The `Scene.update` method is called, if it exists
|
|
* 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE}
|
|
* 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER}
|
|
* 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER}
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('render', listener)`.
|
|
*
|
|
* A Scene will only render if it is visible.
|
|
*
|
|
* By the time this event is dispatched, the Scene will have already been rendered.
|
|
*
|
|
* @event Phaser.Scenes.Events#RENDER
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The renderer that rendered the Scene.
|
|
*/
|
|
module.exports = 'render';
|
|
|
|
|
|
/***/ }),
|
|
/* 198 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Resume Event.
|
|
*
|
|
* This event is dispatched by a Scene when it is resumed from a paused state, either directly via the `resume` method,
|
|
* or as an action from another Scene.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('resume', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#RESUME
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {any} [data] - An optional data object that was passed to this Scene when it was resumed.
|
|
*/
|
|
module.exports = 'resume';
|
|
|
|
|
|
/***/ }),
|
|
/* 199 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Shutdown Event.
|
|
*
|
|
* This event is dispatched by a Scene during the Scene Systems shutdown process.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('shutdown', listener)`.
|
|
*
|
|
* You should free-up any resources that may be in use by your Scene in this event handler, on the understanding
|
|
* that the Scene may, at any time, become active again. A shutdown Scene is not 'destroyed', it's simply not
|
|
* currently active. Use the [DESTROY]{@linkcode Phaser.Scenes.Events#event:DESTROY} event to completely clear resources.
|
|
*
|
|
* @event Phaser.Scenes.Events#SHUTDOWN
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {any} [data] - An optional data object that was passed to this Scene when it was shutdown.
|
|
*/
|
|
module.exports = 'shutdown';
|
|
|
|
|
|
/***/ }),
|
|
/* 200 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Sleep Event.
|
|
*
|
|
* This event is dispatched by a Scene when it is sent to sleep, either directly via the `sleep` method,
|
|
* or as an action from another Scene.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('sleep', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#SLEEP
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {any} [data] - An optional data object that was passed to this Scene when it was sent to sleep.
|
|
*/
|
|
module.exports = 'sleep';
|
|
|
|
|
|
/***/ }),
|
|
/* 201 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Start Event.
|
|
*
|
|
* This event is dispatched by a Scene during the Scene Systems start process. Primarily used by Scene Plugins.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('start', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#START
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
*/
|
|
module.exports = 'start';
|
|
|
|
|
|
/***/ }),
|
|
/* 202 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Transition Complete Event.
|
|
*
|
|
* This event is dispatched by the Target Scene of a transition.
|
|
*
|
|
* It happens when the transition process has completed. This occurs when the duration timer equals or exceeds the duration
|
|
* of the transition.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('transitioncomplete', listener)`.
|
|
*
|
|
* The Scene Transition event flow is as follows:
|
|
*
|
|
* 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event.
|
|
* 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method.
|
|
* 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ...
|
|
* 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to.
|
|
* 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes.
|
|
*
|
|
* @event Phaser.Scenes.Events#TRANSITION_COMPLETE
|
|
* @type {string}
|
|
* @since 3.5.0
|
|
*
|
|
* @param {Phaser.Scene} scene -The Scene on which the transitioned completed.
|
|
*/
|
|
module.exports = 'transitioncomplete';
|
|
|
|
|
|
/***/ }),
|
|
/* 203 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Transition Init Event.
|
|
*
|
|
* This event is dispatched by the Target Scene of a transition.
|
|
*
|
|
* It happens immediately after the `Scene.init` method is called. If the Scene does not have an `init` method,
|
|
* this event is not dispatched.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('transitioninit', listener)`.
|
|
*
|
|
* The Scene Transition event flow is as follows:
|
|
*
|
|
* 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event.
|
|
* 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method.
|
|
* 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ...
|
|
* 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to.
|
|
* 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes.
|
|
*
|
|
* @event Phaser.Scenes.Events#TRANSITION_INIT
|
|
* @type {string}
|
|
* @since 3.5.0
|
|
*
|
|
* @param {Phaser.Scene} from - A reference to the Scene that is being transitioned from.
|
|
* @param {number} duration - The duration of the transition in ms.
|
|
*/
|
|
module.exports = 'transitioninit';
|
|
|
|
|
|
/***/ }),
|
|
/* 204 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Transition Out Event.
|
|
*
|
|
* This event is dispatched by a Scene when it initiates a transition to another Scene.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('transitionout', listener)`.
|
|
*
|
|
* The Scene Transition event flow is as follows:
|
|
*
|
|
* 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event.
|
|
* 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method.
|
|
* 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ...
|
|
* 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to.
|
|
* 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes.
|
|
*
|
|
* @event Phaser.Scenes.Events#TRANSITION_OUT
|
|
* @type {string}
|
|
* @since 3.5.0
|
|
*
|
|
* @param {Phaser.Scene} target - A reference to the Scene that is being transitioned to.
|
|
* @param {number} duration - The duration of the transition in ms.
|
|
*/
|
|
module.exports = 'transitionout';
|
|
|
|
|
|
/***/ }),
|
|
/* 205 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Transition Start Event.
|
|
*
|
|
* This event is dispatched by the Target Scene of a transition, only if that Scene was not asleep.
|
|
*
|
|
* It happens immediately after the `Scene.create` method is called. If the Scene does not have a `create` method,
|
|
* this event is dispatched anyway.
|
|
*
|
|
* If the Target Scene was sleeping then the [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} event is
|
|
* dispatched instead of this event.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('transitionstart', listener)`.
|
|
*
|
|
* The Scene Transition event flow is as follows:
|
|
*
|
|
* 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event.
|
|
* 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method.
|
|
* 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ...
|
|
* 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to.
|
|
* 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes.
|
|
*
|
|
* @event Phaser.Scenes.Events#TRANSITION_START
|
|
* @type {string}
|
|
* @since 3.5.0
|
|
*
|
|
* @param {Phaser.Scene} from - A reference to the Scene that is being transitioned from.
|
|
* @param {number} duration - The duration of the transition in ms.
|
|
*/
|
|
module.exports = 'transitionstart';
|
|
|
|
|
|
/***/ }),
|
|
/* 206 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Transition Wake Event.
|
|
*
|
|
* This event is dispatched by the Target Scene of a transition, only if that Scene was asleep before
|
|
* the transition began. If the Scene was not asleep the [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} event is dispatched instead.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('transitionwake', listener)`.
|
|
*
|
|
* The Scene Transition event flow is as follows:
|
|
*
|
|
* 1. [TRANSITION_OUT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_OUT} - the Scene that started the transition will emit this event.
|
|
* 2. [TRANSITION_INIT]{@linkcode Phaser.Scenes.Events#event:TRANSITION_INIT} - the Target Scene will emit this event if it has an `init` method.
|
|
* 3. [TRANSITION_START]{@linkcode Phaser.Scenes.Events#event:TRANSITION_START} - the Target Scene will emit this event after its `create` method is called, OR ...
|
|
* 4. [TRANSITION_WAKE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_WAKE} - the Target Scene will emit this event if it was asleep and has been woken-up to be transitioned to.
|
|
* 5. [TRANSITION_COMPLETE]{@linkcode Phaser.Scenes.Events#event:TRANSITION_COMPLETE} - the Target Scene will emit this event when the transition finishes.
|
|
*
|
|
* @event Phaser.Scenes.Events#TRANSITION_WAKE
|
|
* @type {string}
|
|
* @since 3.5.0
|
|
*
|
|
* @param {Phaser.Scene} from - A reference to the Scene that is being transitioned from.
|
|
* @param {number} duration - The duration of the transition in ms.
|
|
*/
|
|
module.exports = 'transitionwake';
|
|
|
|
|
|
/***/ }),
|
|
/* 207 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Update Event.
|
|
*
|
|
* This event is dispatched by a Scene during the main game loop step.
|
|
*
|
|
* The event flow for a single step of a Scene is as follows:
|
|
*
|
|
* 1. [PRE_UPDATE]{@linkcode Phaser.Scenes.Events#event:PRE_UPDATE}
|
|
* 2. [UPDATE]{@linkcode Phaser.Scenes.Events#event:UPDATE}
|
|
* 3. The `Scene.update` method is called, if it exists and the Scene is in a Running state, otherwise this is skipped.
|
|
* 4. [POST_UPDATE]{@linkcode Phaser.Scenes.Events#event:POST_UPDATE}
|
|
* 5. [PRE_RENDER]{@linkcode Phaser.Scenes.Events#event:PRE_RENDER}
|
|
* 6. [RENDER]{@linkcode Phaser.Scenes.Events#event:RENDER}
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('update', listener)`.
|
|
*
|
|
* A Scene will only run its step if it is active.
|
|
*
|
|
* @event Phaser.Scenes.Events#UPDATE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {number} time - The current time. Either a High Resolution Timer value if it comes from Request Animation Frame, or Date.now if using SetTimeout.
|
|
* @param {number} delta - The delta time in ms since the last frame. This is a smoothed and capped value based on the FPS rate.
|
|
*/
|
|
module.exports = 'update';
|
|
|
|
|
|
/***/ }),
|
|
/* 208 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Scene Systems Wake Event.
|
|
*
|
|
* This event is dispatched by a Scene when it is woken from sleep, either directly via the `wake` method,
|
|
* or as an action from another Scene.
|
|
*
|
|
* Listen to it from a Scene using `this.events.on('wake', listener)`.
|
|
*
|
|
* @event Phaser.Scenes.Events#WAKE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scenes.Systems} sys - A reference to the Scene Systems class of the Scene that emitted this event.
|
|
* @param {any} [data] - An optional data object that was passed to this Scene when it was woken up.
|
|
*/
|
|
module.exports = 'wake';
|
|
|
|
|
|
/***/ }),
|
|
/* 209 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/*** IMPORTS FROM imports-loader ***/
|
|
|
|
(function() {
|
|
"use strict";
|
|
var spine = (() => {
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// spine-canvas/src/index.ts
|
|
var src_exports = {};
|
|
__export(src_exports, {
|
|
AlphaTimeline: () => AlphaTimeline,
|
|
Animation: () => Animation,
|
|
AnimationState: () => AnimationState,
|
|
AnimationStateAdapter: () => AnimationStateAdapter,
|
|
AnimationStateData: () => AnimationStateData,
|
|
AssetManager: () => AssetManager,
|
|
AssetManagerBase: () => AssetManagerBase,
|
|
AtlasAttachmentLoader: () => AtlasAttachmentLoader,
|
|
Attachment: () => Attachment,
|
|
AttachmentTimeline: () => AttachmentTimeline,
|
|
BinaryInput: () => BinaryInput,
|
|
BlendMode: () => BlendMode,
|
|
Bone: () => Bone,
|
|
BoneData: () => BoneData,
|
|
BoundingBoxAttachment: () => BoundingBoxAttachment,
|
|
CURRENT: () => CURRENT,
|
|
CanvasTexture: () => CanvasTexture,
|
|
ClippingAttachment: () => ClippingAttachment,
|
|
Color: () => Color,
|
|
ConstraintData: () => ConstraintData,
|
|
CurveTimeline: () => CurveTimeline,
|
|
CurveTimeline1: () => CurveTimeline1,
|
|
CurveTimeline2: () => CurveTimeline2,
|
|
DebugUtils: () => DebugUtils,
|
|
DeformTimeline: () => DeformTimeline,
|
|
Downloader: () => Downloader,
|
|
DrawOrderTimeline: () => DrawOrderTimeline,
|
|
Event: () => Event,
|
|
EventData: () => EventData,
|
|
EventQueue: () => EventQueue,
|
|
EventTimeline: () => EventTimeline,
|
|
EventType: () => EventType,
|
|
FIRST: () => FIRST,
|
|
FakeTexture: () => FakeTexture,
|
|
HOLD_FIRST: () => HOLD_FIRST,
|
|
HOLD_MIX: () => HOLD_MIX,
|
|
HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT,
|
|
IkConstraint: () => IkConstraint,
|
|
IkConstraintData: () => IkConstraintData,
|
|
IkConstraintTimeline: () => IkConstraintTimeline,
|
|
IntSet: () => IntSet,
|
|
Interpolation: () => Interpolation,
|
|
MathUtils: () => MathUtils,
|
|
MeshAttachment: () => MeshAttachment,
|
|
MixBlend: () => MixBlend,
|
|
MixDirection: () => MixDirection,
|
|
PathAttachment: () => PathAttachment,
|
|
PathConstraint: () => PathConstraint,
|
|
PathConstraintData: () => PathConstraintData,
|
|
PathConstraintMixTimeline: () => PathConstraintMixTimeline,
|
|
PathConstraintPositionTimeline: () => PathConstraintPositionTimeline,
|
|
PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline,
|
|
PointAttachment: () => PointAttachment,
|
|
Pool: () => Pool,
|
|
PositionMode: () => PositionMode,
|
|
Pow: () => Pow,
|
|
PowOut: () => PowOut,
|
|
RGB2Timeline: () => RGB2Timeline,
|
|
RGBA2Timeline: () => RGBA2Timeline,
|
|
RGBATimeline: () => RGBATimeline,
|
|
RGBTimeline: () => RGBTimeline,
|
|
RegionAttachment: () => RegionAttachment,
|
|
RotateMode: () => RotateMode,
|
|
RotateTimeline: () => RotateTimeline,
|
|
SETUP: () => SETUP,
|
|
SUBSEQUENT: () => SUBSEQUENT,
|
|
ScaleTimeline: () => ScaleTimeline,
|
|
ScaleXTimeline: () => ScaleXTimeline,
|
|
ScaleYTimeline: () => ScaleYTimeline,
|
|
SequenceTimeline: () => SequenceTimeline,
|
|
ShearTimeline: () => ShearTimeline,
|
|
ShearXTimeline: () => ShearXTimeline,
|
|
ShearYTimeline: () => ShearYTimeline,
|
|
Skeleton: () => Skeleton,
|
|
SkeletonBinary: () => SkeletonBinary,
|
|
SkeletonBounds: () => SkeletonBounds,
|
|
SkeletonClipping: () => SkeletonClipping,
|
|
SkeletonData: () => SkeletonData,
|
|
SkeletonJson: () => SkeletonJson,
|
|
SkeletonRenderer: () => SkeletonRenderer,
|
|
Skin: () => Skin,
|
|
SkinEntry: () => SkinEntry,
|
|
Slot: () => Slot,
|
|
SlotData: () => SlotData,
|
|
SpacingMode: () => SpacingMode,
|
|
StringSet: () => StringSet,
|
|
Texture: () => Texture,
|
|
TextureAtlas: () => TextureAtlas,
|
|
TextureAtlasPage: () => TextureAtlasPage,
|
|
TextureAtlasRegion: () => TextureAtlasRegion,
|
|
TextureFilter: () => TextureFilter,
|
|
TextureRegion: () => TextureRegion,
|
|
TextureWrap: () => TextureWrap,
|
|
TimeKeeper: () => TimeKeeper,
|
|
Timeline: () => Timeline,
|
|
TrackEntry: () => TrackEntry,
|
|
TransformConstraint: () => TransformConstraint,
|
|
TransformConstraintData: () => TransformConstraintData,
|
|
TransformConstraintTimeline: () => TransformConstraintTimeline,
|
|
TransformMode: () => TransformMode,
|
|
TranslateTimeline: () => TranslateTimeline,
|
|
TranslateXTimeline: () => TranslateXTimeline,
|
|
TranslateYTimeline: () => TranslateYTimeline,
|
|
Triangulator: () => Triangulator,
|
|
Utils: () => Utils,
|
|
Vector2: () => Vector2,
|
|
VertexAttachment: () => VertexAttachment,
|
|
WindowedMean: () => WindowedMean
|
|
});
|
|
|
|
// spine-core/src/Utils.ts
|
|
var IntSet = class {
|
|
constructor() {
|
|
this.array = new Array();
|
|
}
|
|
add(value) {
|
|
let contains = this.contains(value);
|
|
this.array[value | 0] = value | 0;
|
|
return !contains;
|
|
}
|
|
contains(value) {
|
|
return this.array[value | 0] != void 0;
|
|
}
|
|
remove(value) {
|
|
this.array[value | 0] = void 0;
|
|
}
|
|
clear() {
|
|
this.array.length = 0;
|
|
}
|
|
};
|
|
var StringSet = class {
|
|
constructor() {
|
|
this.entries = {};
|
|
this.size = 0;
|
|
}
|
|
add(value) {
|
|
let contains = this.entries[value];
|
|
this.entries[value] = true;
|
|
if (!contains) {
|
|
this.size++;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
addAll(values) {
|
|
let oldSize = this.size;
|
|
for (var i = 0, n = values.length; i < n; i++)
|
|
this.add(values[i]);
|
|
return oldSize != this.size;
|
|
}
|
|
contains(value) {
|
|
return this.entries[value];
|
|
}
|
|
clear() {
|
|
this.entries = {};
|
|
this.size = 0;
|
|
}
|
|
};
|
|
var _Color = class {
|
|
constructor(r = 0, g = 0, b = 0, a = 0) {
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b;
|
|
this.a = a;
|
|
}
|
|
set(r, g, b, a) {
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b;
|
|
this.a = a;
|
|
return this.clamp();
|
|
}
|
|
setFromColor(c) {
|
|
this.r = c.r;
|
|
this.g = c.g;
|
|
this.b = c.b;
|
|
this.a = c.a;
|
|
return this;
|
|
}
|
|
setFromString(hex) {
|
|
hex = hex.charAt(0) == "#" ? hex.substr(1) : hex;
|
|
this.r = parseInt(hex.substr(0, 2), 16) / 255;
|
|
this.g = parseInt(hex.substr(2, 2), 16) / 255;
|
|
this.b = parseInt(hex.substr(4, 2), 16) / 255;
|
|
this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255;
|
|
return this;
|
|
}
|
|
add(r, g, b, a) {
|
|
this.r += r;
|
|
this.g += g;
|
|
this.b += b;
|
|
this.a += a;
|
|
return this.clamp();
|
|
}
|
|
clamp() {
|
|
if (this.r < 0)
|
|
this.r = 0;
|
|
else if (this.r > 1)
|
|
this.r = 1;
|
|
if (this.g < 0)
|
|
this.g = 0;
|
|
else if (this.g > 1)
|
|
this.g = 1;
|
|
if (this.b < 0)
|
|
this.b = 0;
|
|
else if (this.b > 1)
|
|
this.b = 1;
|
|
if (this.a < 0)
|
|
this.a = 0;
|
|
else if (this.a > 1)
|
|
this.a = 1;
|
|
return this;
|
|
}
|
|
static rgba8888ToColor(color, value) {
|
|
color.r = ((value & 4278190080) >>> 24) / 255;
|
|
color.g = ((value & 16711680) >>> 16) / 255;
|
|
color.b = ((value & 65280) >>> 8) / 255;
|
|
color.a = (value & 255) / 255;
|
|
}
|
|
static rgb888ToColor(color, value) {
|
|
color.r = ((value & 16711680) >>> 16) / 255;
|
|
color.g = ((value & 65280) >>> 8) / 255;
|
|
color.b = (value & 255) / 255;
|
|
}
|
|
static fromString(hex) {
|
|
return new _Color().setFromString(hex);
|
|
}
|
|
};
|
|
var Color = _Color;
|
|
Color.WHITE = new _Color(1, 1, 1, 1);
|
|
Color.RED = new _Color(1, 0, 0, 1);
|
|
Color.GREEN = new _Color(0, 1, 0, 1);
|
|
Color.BLUE = new _Color(0, 0, 1, 1);
|
|
Color.MAGENTA = new _Color(1, 0, 1, 1);
|
|
var _MathUtils = class {
|
|
static clamp(value, min, max) {
|
|
if (value < min)
|
|
return min;
|
|
if (value > max)
|
|
return max;
|
|
return value;
|
|
}
|
|
static cosDeg(degrees) {
|
|
return Math.cos(degrees * _MathUtils.degRad);
|
|
}
|
|
static sinDeg(degrees) {
|
|
return Math.sin(degrees * _MathUtils.degRad);
|
|
}
|
|
static signum(value) {
|
|
return value > 0 ? 1 : value < 0 ? -1 : 0;
|
|
}
|
|
static toInt(x) {
|
|
return x > 0 ? Math.floor(x) : Math.ceil(x);
|
|
}
|
|
static cbrt(x) {
|
|
let y = Math.pow(Math.abs(x), 1 / 3);
|
|
return x < 0 ? -y : y;
|
|
}
|
|
static randomTriangular(min, max) {
|
|
return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5);
|
|
}
|
|
static randomTriangularWith(min, max, mode) {
|
|
let u = Math.random();
|
|
let d = max - min;
|
|
if (u <= (mode - min) / d)
|
|
return min + Math.sqrt(u * d * (mode - min));
|
|
return max - Math.sqrt((1 - u) * d * (max - mode));
|
|
}
|
|
static isPowerOfTwo(value) {
|
|
return value && (value & value - 1) === 0;
|
|
}
|
|
};
|
|
var MathUtils = _MathUtils;
|
|
MathUtils.PI = 3.1415927;
|
|
MathUtils.PI2 = _MathUtils.PI * 2;
|
|
MathUtils.radiansToDegrees = 180 / _MathUtils.PI;
|
|
MathUtils.radDeg = _MathUtils.radiansToDegrees;
|
|
MathUtils.degreesToRadians = _MathUtils.PI / 180;
|
|
MathUtils.degRad = _MathUtils.degreesToRadians;
|
|
var Interpolation = class {
|
|
apply(start, end, a) {
|
|
return start + (end - start) * this.applyInternal(a);
|
|
}
|
|
};
|
|
var Pow = class extends Interpolation {
|
|
constructor(power) {
|
|
super();
|
|
this.power = 2;
|
|
this.power = power;
|
|
}
|
|
applyInternal(a) {
|
|
if (a <= 0.5)
|
|
return Math.pow(a * 2, this.power) / 2;
|
|
return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1;
|
|
}
|
|
};
|
|
var PowOut = class extends Pow {
|
|
constructor(power) {
|
|
super(power);
|
|
}
|
|
applyInternal(a) {
|
|
return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1;
|
|
}
|
|
};
|
|
var _Utils = class {
|
|
static arrayCopy(source, sourceStart, dest, destStart, numElements) {
|
|
for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) {
|
|
dest[j] = source[i];
|
|
}
|
|
}
|
|
static arrayFill(array, fromIndex, toIndex, value) {
|
|
for (let i = fromIndex; i < toIndex; i++)
|
|
array[i] = value;
|
|
}
|
|
static setArraySize(array, size, value = 0) {
|
|
let oldSize = array.length;
|
|
if (oldSize == size)
|
|
return array;
|
|
array.length = size;
|
|
if (oldSize < size) {
|
|
for (let i = oldSize; i < size; i++)
|
|
array[i] = value;
|
|
}
|
|
return array;
|
|
}
|
|
static ensureArrayCapacity(array, size, value = 0) {
|
|
if (array.length >= size)
|
|
return array;
|
|
return _Utils.setArraySize(array, size, value);
|
|
}
|
|
static newArray(size, defaultValue) {
|
|
let array = new Array(size);
|
|
for (let i = 0; i < size; i++)
|
|
array[i] = defaultValue;
|
|
return array;
|
|
}
|
|
static newFloatArray(size) {
|
|
if (_Utils.SUPPORTS_TYPED_ARRAYS)
|
|
return new Float32Array(size);
|
|
else {
|
|
let array = new Array(size);
|
|
for (let i = 0; i < array.length; i++)
|
|
array[i] = 0;
|
|
return array;
|
|
}
|
|
}
|
|
static newShortArray(size) {
|
|
if (_Utils.SUPPORTS_TYPED_ARRAYS)
|
|
return new Int16Array(size);
|
|
else {
|
|
let array = new Array(size);
|
|
for (let i = 0; i < array.length; i++)
|
|
array[i] = 0;
|
|
return array;
|
|
}
|
|
}
|
|
static toFloatArray(array) {
|
|
return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
|
|
}
|
|
static toSinglePrecision(value) {
|
|
return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value;
|
|
}
|
|
static webkit602BugfixHelper(alpha, blend) {
|
|
}
|
|
static contains(array, element, identity = true) {
|
|
for (var i = 0; i < array.length; i++)
|
|
if (array[i] == element)
|
|
return true;
|
|
return false;
|
|
}
|
|
static enumValue(type, name) {
|
|
return type[name[0].toUpperCase() + name.slice(1)];
|
|
}
|
|
};
|
|
var Utils = _Utils;
|
|
Utils.SUPPORTS_TYPED_ARRAYS = typeof Float32Array !== "undefined";
|
|
var DebugUtils = class {
|
|
static logBones(skeleton) {
|
|
for (let i = 0; i < skeleton.bones.length; i++) {
|
|
let bone = skeleton.bones[i];
|
|
console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY);
|
|
}
|
|
}
|
|
};
|
|
var Pool = class {
|
|
constructor(instantiator) {
|
|
this.items = new Array();
|
|
this.instantiator = instantiator;
|
|
}
|
|
obtain() {
|
|
return this.items.length > 0 ? this.items.pop() : this.instantiator();
|
|
}
|
|
free(item) {
|
|
if (item.reset)
|
|
item.reset();
|
|
this.items.push(item);
|
|
}
|
|
freeAll(items) {
|
|
for (let i = 0; i < items.length; i++)
|
|
this.free(items[i]);
|
|
}
|
|
clear() {
|
|
this.items.length = 0;
|
|
}
|
|
};
|
|
var Vector2 = class {
|
|
constructor(x = 0, y = 0) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
set(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
return this;
|
|
}
|
|
length() {
|
|
let x = this.x;
|
|
let y = this.y;
|
|
return Math.sqrt(x * x + y * y);
|
|
}
|
|
normalize() {
|
|
let len = this.length();
|
|
if (len != 0) {
|
|
this.x /= len;
|
|
this.y /= len;
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
var TimeKeeper = class {
|
|
constructor() {
|
|
this.maxDelta = 0.064;
|
|
this.framesPerSecond = 0;
|
|
this.delta = 0;
|
|
this.totalTime = 0;
|
|
this.lastTime = Date.now() / 1e3;
|
|
this.frameCount = 0;
|
|
this.frameTime = 0;
|
|
}
|
|
update() {
|
|
let now = Date.now() / 1e3;
|
|
this.delta = now - this.lastTime;
|
|
this.frameTime += this.delta;
|
|
this.totalTime += this.delta;
|
|
if (this.delta > this.maxDelta)
|
|
this.delta = this.maxDelta;
|
|
this.lastTime = now;
|
|
this.frameCount++;
|
|
if (this.frameTime > 1) {
|
|
this.framesPerSecond = this.frameCount / this.frameTime;
|
|
this.frameTime = 0;
|
|
this.frameCount = 0;
|
|
}
|
|
}
|
|
};
|
|
var WindowedMean = class {
|
|
constructor(windowSize = 32) {
|
|
this.addedValues = 0;
|
|
this.lastValue = 0;
|
|
this.mean = 0;
|
|
this.dirty = true;
|
|
this.values = new Array(windowSize);
|
|
}
|
|
hasEnoughData() {
|
|
return this.addedValues >= this.values.length;
|
|
}
|
|
addValue(value) {
|
|
if (this.addedValues < this.values.length)
|
|
this.addedValues++;
|
|
this.values[this.lastValue++] = value;
|
|
if (this.lastValue > this.values.length - 1)
|
|
this.lastValue = 0;
|
|
this.dirty = true;
|
|
}
|
|
getMean() {
|
|
if (this.hasEnoughData()) {
|
|
if (this.dirty) {
|
|
let mean = 0;
|
|
for (let i = 0; i < this.values.length; i++)
|
|
mean += this.values[i];
|
|
this.mean = mean / this.values.length;
|
|
this.dirty = false;
|
|
}
|
|
return this.mean;
|
|
}
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/Attachment.ts
|
|
var Attachment = class {
|
|
constructor(name) {
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.name = name;
|
|
}
|
|
};
|
|
var _VertexAttachment = class extends Attachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.id = _VertexAttachment.nextID++;
|
|
this.bones = null;
|
|
this.vertices = [];
|
|
this.worldVerticesLength = 0;
|
|
this.timelineAttachment = this;
|
|
}
|
|
computeWorldVertices(slot, start, count, worldVertices2, offset, stride) {
|
|
count = offset + (count >> 1) * stride;
|
|
let skeleton = slot.bone.skeleton;
|
|
let deformArray = slot.deform;
|
|
let vertices = this.vertices;
|
|
let bones = this.bones;
|
|
if (!bones) {
|
|
if (deformArray.length > 0)
|
|
vertices = deformArray;
|
|
let bone = slot.bone;
|
|
let x = bone.worldX;
|
|
let y = bone.worldY;
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) {
|
|
let vx = vertices[v2], vy = vertices[v2 + 1];
|
|
worldVertices2[w] = vx * a + vy * b + x;
|
|
worldVertices2[w + 1] = vx * c + vy * d + y;
|
|
}
|
|
return;
|
|
}
|
|
let v = 0, skip = 0;
|
|
for (let i = 0; i < start; i += 2) {
|
|
let n = bones[v];
|
|
v += n + 1;
|
|
skip += n;
|
|
}
|
|
let skeletonBones = skeleton.bones;
|
|
if (deformArray.length == 0) {
|
|
for (let w = offset, b = skip * 3; w < count; w += stride) {
|
|
let wx = 0, wy = 0;
|
|
let n = bones[v++];
|
|
n += v;
|
|
for (; v < n; v++, b += 3) {
|
|
let bone = skeletonBones[bones[v]];
|
|
let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
|
|
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
|
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
|
}
|
|
worldVertices2[w] = wx;
|
|
worldVertices2[w + 1] = wy;
|
|
}
|
|
} else {
|
|
let deform = deformArray;
|
|
for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {
|
|
let wx = 0, wy = 0;
|
|
let n = bones[v++];
|
|
n += v;
|
|
for (; v < n; v++, b += 3, f += 2) {
|
|
let bone = skeletonBones[bones[v]];
|
|
let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
|
|
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
|
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
|
}
|
|
worldVertices2[w] = wx;
|
|
worldVertices2[w + 1] = wy;
|
|
}
|
|
}
|
|
}
|
|
copyTo(attachment) {
|
|
if (this.bones) {
|
|
attachment.bones = new Array(this.bones.length);
|
|
Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length);
|
|
} else
|
|
attachment.bones = null;
|
|
if (this.vertices) {
|
|
attachment.vertices = Utils.newFloatArray(this.vertices.length);
|
|
Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length);
|
|
}
|
|
attachment.worldVerticesLength = this.worldVerticesLength;
|
|
attachment.timelineAttachment = this.timelineAttachment;
|
|
}
|
|
};
|
|
var VertexAttachment = _VertexAttachment;
|
|
VertexAttachment.nextID = 0;
|
|
|
|
// spine-core/src/attachments/Sequence.ts
|
|
var _Sequence = class {
|
|
constructor(count) {
|
|
this.id = _Sequence.nextID();
|
|
this.start = 0;
|
|
this.digits = 0;
|
|
this.setupIndex = 0;
|
|
this.regions = new Array(count);
|
|
}
|
|
copy() {
|
|
let copy = new _Sequence(this.regions.length);
|
|
Utils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length);
|
|
copy.start = this.start;
|
|
copy.digits = this.digits;
|
|
copy.setupIndex = this.setupIndex;
|
|
return copy;
|
|
}
|
|
apply(slot, attachment) {
|
|
let index = slot.sequenceIndex;
|
|
if (index == -1)
|
|
index = this.setupIndex;
|
|
if (index >= this.regions.length)
|
|
index = this.regions.length - 1;
|
|
let region = this.regions[index];
|
|
if (attachment.region != region) {
|
|
attachment.region = region;
|
|
attachment.updateRegion();
|
|
}
|
|
}
|
|
getPath(basePath, index) {
|
|
let result = basePath;
|
|
let frame = (this.start + index).toString();
|
|
for (let i = this.digits - frame.length; i > 0; i--)
|
|
result += "0";
|
|
result += frame;
|
|
return result;
|
|
}
|
|
static nextID() {
|
|
return _Sequence._nextID++;
|
|
}
|
|
};
|
|
var Sequence = _Sequence;
|
|
Sequence._nextID = 0;
|
|
var SequenceMode = /* @__PURE__ */ ((SequenceMode2) => {
|
|
SequenceMode2[SequenceMode2["hold"] = 0] = "hold";
|
|
SequenceMode2[SequenceMode2["once"] = 1] = "once";
|
|
SequenceMode2[SequenceMode2["loop"] = 2] = "loop";
|
|
SequenceMode2[SequenceMode2["pingpong"] = 3] = "pingpong";
|
|
SequenceMode2[SequenceMode2["onceReverse"] = 4] = "onceReverse";
|
|
SequenceMode2[SequenceMode2["loopReverse"] = 5] = "loopReverse";
|
|
SequenceMode2[SequenceMode2["pingpongReverse"] = 6] = "pingpongReverse";
|
|
return SequenceMode2;
|
|
})(SequenceMode || {});
|
|
var SequenceModeValues = [
|
|
0 /* hold */,
|
|
1 /* once */,
|
|
2 /* loop */,
|
|
3 /* pingpong */,
|
|
4 /* onceReverse */,
|
|
5 /* loopReverse */,
|
|
6 /* pingpongReverse */
|
|
];
|
|
|
|
// spine-core/src/Animation.ts
|
|
var Animation = class {
|
|
constructor(name, timelines, duration) {
|
|
this.timelines = [];
|
|
this.timelineIds = new StringSet();
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.name = name;
|
|
this.setTimelines(timelines);
|
|
this.duration = duration;
|
|
}
|
|
setTimelines(timelines) {
|
|
if (!timelines)
|
|
throw new Error("timelines cannot be null.");
|
|
this.timelines = timelines;
|
|
this.timelineIds.clear();
|
|
for (var i = 0; i < timelines.length; i++)
|
|
this.timelineIds.addAll(timelines[i].getPropertyIds());
|
|
}
|
|
hasTimeline(ids) {
|
|
for (let i = 0; i < ids.length; i++)
|
|
if (this.timelineIds.contains(ids[i]))
|
|
return true;
|
|
return false;
|
|
}
|
|
apply(skeleton, lastTime, time, loop, events, alpha, blend, direction) {
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
if (loop && this.duration != 0) {
|
|
time %= this.duration;
|
|
if (lastTime > 0)
|
|
lastTime %= this.duration;
|
|
}
|
|
let timelines = this.timelines;
|
|
for (let i = 0, n = timelines.length; i < n; i++)
|
|
timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction);
|
|
}
|
|
};
|
|
var MixBlend = /* @__PURE__ */ ((MixBlend2) => {
|
|
MixBlend2[MixBlend2["setup"] = 0] = "setup";
|
|
MixBlend2[MixBlend2["first"] = 1] = "first";
|
|
MixBlend2[MixBlend2["replace"] = 2] = "replace";
|
|
MixBlend2[MixBlend2["add"] = 3] = "add";
|
|
return MixBlend2;
|
|
})(MixBlend || {});
|
|
var MixDirection = /* @__PURE__ */ ((MixDirection2) => {
|
|
MixDirection2[MixDirection2["mixIn"] = 0] = "mixIn";
|
|
MixDirection2[MixDirection2["mixOut"] = 1] = "mixOut";
|
|
return MixDirection2;
|
|
})(MixDirection || {});
|
|
var Property = {
|
|
rotate: 0,
|
|
x: 1,
|
|
y: 2,
|
|
scaleX: 3,
|
|
scaleY: 4,
|
|
shearX: 5,
|
|
shearY: 6,
|
|
rgb: 7,
|
|
alpha: 8,
|
|
rgb2: 9,
|
|
attachment: 10,
|
|
deform: 11,
|
|
event: 12,
|
|
drawOrder: 13,
|
|
ikConstraint: 14,
|
|
transformConstraint: 15,
|
|
pathConstraintPosition: 16,
|
|
pathConstraintSpacing: 17,
|
|
pathConstraintMix: 18,
|
|
sequence: 19
|
|
};
|
|
var Timeline = class {
|
|
constructor(frameCount, propertyIds) {
|
|
this.propertyIds = propertyIds;
|
|
this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries());
|
|
}
|
|
getPropertyIds() {
|
|
return this.propertyIds;
|
|
}
|
|
getFrameEntries() {
|
|
return 1;
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length / this.getFrameEntries();
|
|
}
|
|
getDuration() {
|
|
return this.frames[this.frames.length - this.getFrameEntries()];
|
|
}
|
|
static search1(frames, time) {
|
|
let n = frames.length;
|
|
for (let i = 1; i < n; i++)
|
|
if (frames[i] > time)
|
|
return i - 1;
|
|
return n - 1;
|
|
}
|
|
static search(frames, time, step) {
|
|
let n = frames.length;
|
|
for (let i = step; i < n; i += step)
|
|
if (frames[i] > time)
|
|
return i - step;
|
|
return n - step;
|
|
}
|
|
};
|
|
var CurveTimeline = class extends Timeline {
|
|
constructor(frameCount, bezierCount, propertyIds) {
|
|
super(frameCount, propertyIds);
|
|
this.curves = Utils.newFloatArray(frameCount + bezierCount * 18);
|
|
this.curves[frameCount - 1] = 1;
|
|
}
|
|
setLinear(frame) {
|
|
this.curves[frame] = 0;
|
|
}
|
|
setStepped(frame) {
|
|
this.curves[frame] = 1;
|
|
}
|
|
shrink(bezierCount) {
|
|
let size = this.getFrameCount() + bezierCount * 18;
|
|
if (this.curves.length > size) {
|
|
let newCurves = Utils.newFloatArray(size);
|
|
Utils.arrayCopy(this.curves, 0, newCurves, 0, size);
|
|
this.curves = newCurves;
|
|
}
|
|
}
|
|
setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) {
|
|
let curves = this.curves;
|
|
let i = this.getFrameCount() + bezier * 18;
|
|
if (value == 0)
|
|
curves[frame] = 2 + i;
|
|
let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03;
|
|
let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3;
|
|
let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
|
|
let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667;
|
|
let x = time1 + dx, y = value1 + dy;
|
|
for (let n = i + 18; i < n; i += 2) {
|
|
curves[i] = x;
|
|
curves[i + 1] = y;
|
|
dx += ddx;
|
|
dy += ddy;
|
|
ddx += dddx;
|
|
ddy += dddy;
|
|
x += dx;
|
|
y += dy;
|
|
}
|
|
}
|
|
getBezierValue(time, frameIndex, valueOffset, i) {
|
|
let curves = this.curves;
|
|
if (curves[i] > time) {
|
|
let x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset];
|
|
return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2);
|
|
}
|
|
let n = i + 18;
|
|
for (i += 2; i < n; i += 2) {
|
|
if (curves[i] >= time) {
|
|
let x2 = curves[i - 2], y2 = curves[i - 1];
|
|
return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2);
|
|
}
|
|
}
|
|
frameIndex += this.getFrameEntries();
|
|
let x = curves[n - 2], y = curves[n - 1];
|
|
return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y);
|
|
}
|
|
};
|
|
var CurveTimeline1 = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, propertyId) {
|
|
super(frameCount, bezierCount, [propertyId]);
|
|
}
|
|
getFrameEntries() {
|
|
return 2;
|
|
}
|
|
setFrame(frame, time, value) {
|
|
frame <<= 1;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = value;
|
|
}
|
|
getCurveValue(time) {
|
|
let frames = this.frames;
|
|
let i = frames.length - 2;
|
|
for (let ii = 2; ii <= i; ii += 2) {
|
|
if (frames[ii] > time) {
|
|
i = ii - 2;
|
|
break;
|
|
}
|
|
}
|
|
let curveType = this.curves[i >> 1];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i], value = frames[i + 1];
|
|
return value + (time - before) / (frames[i + 2] - before) * (frames[i + 2 + 1] - value);
|
|
case 1:
|
|
return frames[i + 1];
|
|
}
|
|
return this.getBezierValue(time, i, 1, curveType - 2);
|
|
}
|
|
};
|
|
var CurveTimeline2 = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, propertyId1, propertyId2) {
|
|
super(frameCount, bezierCount, [propertyId1, propertyId2]);
|
|
}
|
|
getFrameEntries() {
|
|
return 3;
|
|
}
|
|
setFrame(frame, time, value1, value2) {
|
|
frame *= 3;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = value1;
|
|
this.frames[frame + 2] = value2;
|
|
}
|
|
};
|
|
var RotateTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.rotate + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.rotation = bone.data.rotation;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.rotation += (bone.data.rotation - bone.rotation) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.rotation = bone.data.rotation + r * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
r += bone.data.rotation - bone.rotation;
|
|
case 3 /* add */:
|
|
bone.rotation += r * alpha;
|
|
}
|
|
}
|
|
};
|
|
var TranslateTimeline = class extends CurveTimeline2 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(
|
|
frameCount,
|
|
bezierCount,
|
|
Property.x + "|" + boneIndex,
|
|
Property.y + "|" + boneIndex
|
|
);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x;
|
|
bone.y = bone.data.y;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.x += (bone.data.x - bone.x) * alpha;
|
|
bone.y += (bone.data.y - bone.y) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = 0, y = 0;
|
|
let i = Timeline.search(frames, time, 3);
|
|
let curveType = this.curves[i / 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 3] - before);
|
|
x += (frames[i + 3 + 1] - x) * t;
|
|
y += (frames[i + 3 + 2] - y) * t;
|
|
break;
|
|
case 1:
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
break;
|
|
default:
|
|
x = this.getBezierValue(time, i, 1, curveType - 2);
|
|
y = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x + x * alpha;
|
|
bone.y = bone.data.y + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.x += (bone.data.x + x - bone.x) * alpha;
|
|
bone.y += (bone.data.y + y - bone.y) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.x += x * alpha;
|
|
bone.y += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var TranslateXTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.x + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.x += (bone.data.x - bone.x) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x + x * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.x += (bone.data.x + x - bone.x) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.x += x * alpha;
|
|
}
|
|
}
|
|
};
|
|
var TranslateYTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.y + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.y = bone.data.y;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.y += (bone.data.y - bone.y) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let y = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.y = bone.data.y + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.y += (bone.data.y + y - bone.y) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.y += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var ScaleTimeline = class extends CurveTimeline2 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(
|
|
frameCount,
|
|
bezierCount,
|
|
Property.scaleX + "|" + boneIndex,
|
|
Property.scaleY + "|" + boneIndex
|
|
);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.scaleX = bone.data.scaleX;
|
|
bone.scaleY = bone.data.scaleY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
|
|
bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x, y;
|
|
let i = Timeline.search(frames, time, 3);
|
|
let curveType = this.curves[i / 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 3] - before);
|
|
x += (frames[i + 3 + 1] - x) * t;
|
|
y += (frames[i + 3 + 2] - y) * t;
|
|
break;
|
|
case 1:
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
break;
|
|
default:
|
|
x = this.getBezierValue(time, i, 1, curveType - 2);
|
|
y = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
x *= bone.data.scaleX;
|
|
y *= bone.data.scaleY;
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */) {
|
|
bone.scaleX += x - bone.data.scaleX;
|
|
bone.scaleY += y - bone.data.scaleY;
|
|
} else {
|
|
bone.scaleX = x;
|
|
bone.scaleY = y;
|
|
}
|
|
} else {
|
|
let bx = 0, by = 0;
|
|
if (direction == 1 /* mixOut */) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = bone.data.scaleX;
|
|
by = bone.data.scaleY;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = bone.scaleX;
|
|
by = bone.scaleY;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);
|
|
by = Math.abs(bone.data.scaleY) * MathUtils.signum(y);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = Math.abs(bone.scaleX) * MathUtils.signum(x);
|
|
by = Math.abs(bone.scaleY) * MathUtils.signum(y);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var ScaleXTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.scaleX = bone.data.scaleX;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = this.getCurveValue(time) * bone.data.scaleX;
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */)
|
|
bone.scaleX += x - bone.data.scaleX;
|
|
else
|
|
bone.scaleX = x;
|
|
} else {
|
|
let bx = 0;
|
|
if (direction == 1 /* mixOut */) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = bone.data.scaleX;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = bone.scaleX;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = Math.abs(bone.scaleX) * MathUtils.signum(x);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var ScaleYTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.scaleY + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.scaleY = bone.data.scaleY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let y = this.getCurveValue(time) * bone.data.scaleY;
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */)
|
|
bone.scaleY += y - bone.data.scaleY;
|
|
else
|
|
bone.scaleY = y;
|
|
} else {
|
|
let by = 0;
|
|
if (direction == 1 /* mixOut */) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
by = bone.data.scaleY;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
by = bone.scaleY;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
by = Math.abs(bone.data.scaleY) * MathUtils.signum(y);
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
by = Math.abs(bone.scaleY) * MathUtils.signum(y);
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var ShearTimeline = class extends CurveTimeline2 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(
|
|
frameCount,
|
|
bezierCount,
|
|
Property.shearX + "|" + boneIndex,
|
|
Property.shearY + "|" + boneIndex
|
|
);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX;
|
|
bone.shearY = bone.data.shearY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
|
|
bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = 0, y = 0;
|
|
let i = Timeline.search(frames, time, 3);
|
|
let curveType = this.curves[i / 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 3] - before);
|
|
x += (frames[i + 3 + 1] - x) * t;
|
|
y += (frames[i + 3 + 2] - y) * t;
|
|
break;
|
|
case 1:
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
break;
|
|
default:
|
|
x = this.getBezierValue(time, i, 1, curveType - 2);
|
|
y = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX + x * alpha;
|
|
bone.shearY = bone.data.shearY + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
|
|
bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.shearX += x * alpha;
|
|
bone.shearY += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var ShearXTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.shearX + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX + x * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.shearX += x * alpha;
|
|
}
|
|
}
|
|
};
|
|
var ShearYTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.shearY + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearY = bone.data.shearY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let y = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearY = bone.data.shearY + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.shearY += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var RGBATimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex,
|
|
Property.alpha + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 5;
|
|
}
|
|
setFrame(frame, time, r, g, b, a) {
|
|
frame *= 5;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
this.frames[frame + 4] = a;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let color = slot.color;
|
|
if (time < frames[0]) {
|
|
let setup = slot.data.color;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
color.setFromColor(setup);
|
|
return;
|
|
case 1 /* first */:
|
|
color.add(
|
|
(setup.r - color.r) * alpha,
|
|
(setup.g - color.g) * alpha,
|
|
(setup.b - color.b) * alpha,
|
|
(setup.a - color.a) * alpha
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0, a = 0;
|
|
let i = Timeline.search(frames, time, 5);
|
|
let curveType = this.curves[i / 5];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
let t = (time - before) / (frames[i + 5] - before);
|
|
r += (frames[i + 5 + 1] - r) * t;
|
|
g += (frames[i + 5 + 2] - g) * t;
|
|
b += (frames[i + 5 + 3] - b) * t;
|
|
a += (frames[i + 5 + 4] - a) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
a = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
}
|
|
if (alpha == 1)
|
|
color.set(r, g, b, a);
|
|
else {
|
|
if (blend == 0 /* setup */)
|
|
color.setFromColor(slot.data.color);
|
|
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
|
}
|
|
}
|
|
};
|
|
var RGBTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 4;
|
|
}
|
|
setFrame(frame, time, r, g, b) {
|
|
frame <<= 2;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let color = slot.color;
|
|
if (time < frames[0]) {
|
|
let setup = slot.data.color;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
color.r = setup.r;
|
|
color.g = setup.g;
|
|
color.b = setup.b;
|
|
return;
|
|
case 1 /* first */:
|
|
color.r += (setup.r - color.r) * alpha;
|
|
color.g += (setup.g - color.g) * alpha;
|
|
color.b += (setup.b - color.b) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0;
|
|
let i = Timeline.search(frames, time, 4);
|
|
let curveType = this.curves[i >> 2];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
let t = (time - before) / (frames[i + 4] - before);
|
|
r += (frames[i + 4 + 1] - r) * t;
|
|
g += (frames[i + 4 + 2] - g) * t;
|
|
b += (frames[i + 4 + 3] - b) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
}
|
|
if (alpha == 1) {
|
|
color.r = r;
|
|
color.g = g;
|
|
color.b = b;
|
|
} else {
|
|
if (blend == 0 /* setup */) {
|
|
let setup = slot.data.color;
|
|
color.r = setup.r;
|
|
color.g = setup.g;
|
|
color.b = setup.b;
|
|
}
|
|
color.r += (r - color.r) * alpha;
|
|
color.g += (g - color.g) * alpha;
|
|
color.b += (b - color.b) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var AlphaTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, Property.alpha + "|" + slotIndex);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let color = slot.color;
|
|
if (time < this.frames[0]) {
|
|
let setup = slot.data.color;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
color.a = setup.a;
|
|
return;
|
|
case 1 /* first */:
|
|
color.a += (setup.a - color.a) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let a = this.getCurveValue(time);
|
|
if (alpha == 1)
|
|
color.a = a;
|
|
else {
|
|
if (blend == 0 /* setup */)
|
|
color.a = slot.data.color.a;
|
|
color.a += (a - color.a) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var RGBA2Timeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex,
|
|
Property.alpha + "|" + slotIndex,
|
|
Property.rgb2 + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 8;
|
|
}
|
|
setFrame(frame, time, r, g, b, a, r2, g2, b2) {
|
|
frame <<= 3;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
this.frames[frame + 4] = a;
|
|
this.frames[frame + 5] = r2;
|
|
this.frames[frame + 6] = g2;
|
|
this.frames[frame + 7] = b2;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let light = slot.color, dark = slot.darkColor;
|
|
if (time < frames[0]) {
|
|
let setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
light.setFromColor(setupLight);
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
return;
|
|
case 1 /* first */:
|
|
light.add(
|
|
(setupLight.r - light.r) * alpha,
|
|
(setupLight.g - light.g) * alpha,
|
|
(setupLight.b - light.b) * alpha,
|
|
(setupLight.a - light.a) * alpha
|
|
);
|
|
dark.r += (setupDark.r - dark.r) * alpha;
|
|
dark.g += (setupDark.g - dark.g) * alpha;
|
|
dark.b += (setupDark.b - dark.b) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;
|
|
let i = Timeline.search(frames, time, 8);
|
|
let curveType = this.curves[i >> 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
r2 = frames[i + 5];
|
|
g2 = frames[i + 6];
|
|
b2 = frames[i + 7];
|
|
let t = (time - before) / (frames[i + 8] - before);
|
|
r += (frames[i + 8 + 1] - r) * t;
|
|
g += (frames[i + 8 + 2] - g) * t;
|
|
b += (frames[i + 8 + 3] - b) * t;
|
|
a += (frames[i + 8 + 4] - a) * t;
|
|
r2 += (frames[i + 8 + 5] - r2) * t;
|
|
g2 += (frames[i + 8 + 6] - g2) * t;
|
|
b2 += (frames[i + 8 + 7] - b2) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
r2 = frames[i + 5];
|
|
g2 = frames[i + 6];
|
|
b2 = frames[i + 7];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
a = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
r2 = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2);
|
|
g2 = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2);
|
|
b2 = this.getBezierValue(time, i, 7, curveType + 18 * 6 - 2);
|
|
}
|
|
if (alpha == 1) {
|
|
light.set(r, g, b, a);
|
|
dark.r = r2;
|
|
dark.g = g2;
|
|
dark.b = b2;
|
|
} else {
|
|
if (blend == 0 /* setup */) {
|
|
light.setFromColor(slot.data.color);
|
|
let setupDark = slot.data.darkColor;
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
}
|
|
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
|
|
dark.r += (r2 - dark.r) * alpha;
|
|
dark.g += (g2 - dark.g) * alpha;
|
|
dark.b += (b2 - dark.b) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var RGB2Timeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex,
|
|
Property.rgb2 + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 7;
|
|
}
|
|
setFrame(frame, time, r, g, b, r2, g2, b2) {
|
|
frame *= 7;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
this.frames[frame + 4] = r2;
|
|
this.frames[frame + 5] = g2;
|
|
this.frames[frame + 6] = b2;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let light = slot.color, dark = slot.darkColor;
|
|
if (time < frames[0]) {
|
|
let setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
light.r = setupLight.r;
|
|
light.g = setupLight.g;
|
|
light.b = setupLight.b;
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
return;
|
|
case 1 /* first */:
|
|
light.r += (setupLight.r - light.r) * alpha;
|
|
light.g += (setupLight.g - light.g) * alpha;
|
|
light.b += (setupLight.b - light.b) * alpha;
|
|
dark.r += (setupDark.r - dark.r) * alpha;
|
|
dark.g += (setupDark.g - dark.g) * alpha;
|
|
dark.b += (setupDark.b - dark.b) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;
|
|
let i = Timeline.search(frames, time, 7);
|
|
let curveType = this.curves[i / 7];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
r2 = frames[i + 4];
|
|
g2 = frames[i + 5];
|
|
b2 = frames[i + 6];
|
|
let t = (time - before) / (frames[i + 7] - before);
|
|
r += (frames[i + 7 + 1] - r) * t;
|
|
g += (frames[i + 7 + 2] - g) * t;
|
|
b += (frames[i + 7 + 3] - b) * t;
|
|
r2 += (frames[i + 7 + 4] - r2) * t;
|
|
g2 += (frames[i + 7 + 5] - g2) * t;
|
|
b2 += (frames[i + 7 + 6] - b2) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
r2 = frames[i + 4];
|
|
g2 = frames[i + 5];
|
|
b2 = frames[i + 6];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
r2 = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
g2 = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2);
|
|
b2 = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2);
|
|
}
|
|
if (alpha == 1) {
|
|
light.r = r;
|
|
light.g = g;
|
|
light.b = b;
|
|
dark.r = r2;
|
|
dark.g = g2;
|
|
dark.b = b2;
|
|
} else {
|
|
if (blend == 0 /* setup */) {
|
|
let setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
|
light.r = setupLight.r;
|
|
light.g = setupLight.g;
|
|
light.b = setupLight.b;
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
}
|
|
light.r += (r - light.r) * alpha;
|
|
light.g += (g - light.g) * alpha;
|
|
light.b += (b - light.b) * alpha;
|
|
dark.r += (r2 - dark.r) * alpha;
|
|
dark.g += (g2 - dark.g) * alpha;
|
|
dark.b += (b2 - dark.b) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var AttachmentTimeline = class extends Timeline {
|
|
constructor(frameCount, slotIndex) {
|
|
super(frameCount, [
|
|
Property.attachment + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
this.attachmentNames = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, time, attachmentName) {
|
|
this.frames[frame] = time;
|
|
this.attachmentNames[frame] = attachmentName;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
if (direction == 1 /* mixOut */) {
|
|
if (blend == 0 /* setup */)
|
|
this.setAttachment(skeleton, slot, slot.data.attachmentName);
|
|
return;
|
|
}
|
|
if (time < this.frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
this.setAttachment(skeleton, slot, slot.data.attachmentName);
|
|
return;
|
|
}
|
|
this.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]);
|
|
}
|
|
setAttachment(skeleton, slot, attachmentName) {
|
|
slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
|
|
}
|
|
};
|
|
var DeformTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex, attachment) {
|
|
super(frameCount, bezierCount, [
|
|
Property.deform + "|" + slotIndex + "|" + attachment.id
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
this.attachment = attachment;
|
|
this.vertices = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, time, vertices) {
|
|
this.frames[frame] = time;
|
|
this.vertices[frame] = vertices;
|
|
}
|
|
setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) {
|
|
let curves = this.curves;
|
|
let i = this.getFrameCount() + bezier * 18;
|
|
if (value == 0)
|
|
curves[frame] = 2 + i;
|
|
let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06;
|
|
let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018;
|
|
let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
|
|
let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667;
|
|
let x = time1 + dx, y = dy;
|
|
for (let n = i + 18; i < n; i += 2) {
|
|
curves[i] = x;
|
|
curves[i + 1] = y;
|
|
dx += ddx;
|
|
dy += ddy;
|
|
ddx += dddx;
|
|
ddy += dddy;
|
|
x += dx;
|
|
y += dy;
|
|
}
|
|
}
|
|
getCurvePercent(time, frame) {
|
|
let curves = this.curves;
|
|
let i = curves[frame];
|
|
switch (i) {
|
|
case 0:
|
|
let x2 = this.frames[frame];
|
|
return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2);
|
|
case 1:
|
|
return 0;
|
|
}
|
|
i -= 2;
|
|
if (curves[i] > time) {
|
|
let x2 = this.frames[frame];
|
|
return curves[i + 1] * (time - x2) / (curves[i] - x2);
|
|
}
|
|
let n = i + 18;
|
|
for (i += 2; i < n; i += 2) {
|
|
if (curves[i] >= time) {
|
|
let x2 = curves[i - 2], y2 = curves[i - 1];
|
|
return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2);
|
|
}
|
|
}
|
|
let x = curves[n - 2], y = curves[n - 1];
|
|
return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x);
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let slotAttachment = slot.getAttachment();
|
|
if (!slotAttachment)
|
|
return;
|
|
if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != this.attachment)
|
|
return;
|
|
let deform = slot.deform;
|
|
if (deform.length == 0)
|
|
blend = 0 /* setup */;
|
|
let vertices = this.vertices;
|
|
let vertexCount = vertices[0].length;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
deform.length = 0;
|
|
return;
|
|
case 1 /* first */:
|
|
if (alpha == 1) {
|
|
deform.length = 0;
|
|
return;
|
|
}
|
|
deform.length = vertexCount;
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (var i = 0; i < vertexCount; i++)
|
|
deform[i] += (setupVertices[i] - deform[i]) * alpha;
|
|
} else {
|
|
alpha = 1 - alpha;
|
|
for (var i = 0; i < vertexCount; i++)
|
|
deform[i] *= alpha;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
deform.length = vertexCount;
|
|
if (time >= frames[frames.length - 1]) {
|
|
let lastVertices = vertices[frames.length - 1];
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */) {
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += lastVertices[i2] - setupVertices[i2];
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += lastVertices[i2];
|
|
}
|
|
} else
|
|
Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount);
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */: {
|
|
let vertexAttachment2 = slotAttachment;
|
|
if (!vertexAttachment2.bones) {
|
|
let setupVertices = vertexAttachment2.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let setup = setupVertices[i2];
|
|
deform[i2] = setup + (lastVertices[i2] - setup) * alpha;
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] = lastVertices[i2] * alpha;
|
|
}
|
|
break;
|
|
}
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += (lastVertices[i2] - deform[i2]) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += (lastVertices[i2] - setupVertices[i2]) * alpha;
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += lastVertices[i2] * alpha;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
let frame = Timeline.search1(frames, time);
|
|
let percent = this.getCurvePercent(time, frame);
|
|
let prevVertices = vertices[frame];
|
|
let nextVertices = vertices[frame + 1];
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */) {
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += prev + (nextVertices[i2] - prev) * percent - setupVertices[i2];
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += prev + (nextVertices[i2] - prev) * percent;
|
|
}
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] = prev + (nextVertices[i2] - prev) * percent;
|
|
}
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */: {
|
|
let vertexAttachment2 = slotAttachment;
|
|
if (!vertexAttachment2.bones) {
|
|
let setupVertices = vertexAttachment2.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2], setup = setupVertices[i2];
|
|
deform[i2] = setup + (prev + (nextVertices[i2] - prev) * percent - setup) * alpha;
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] = (prev + (nextVertices[i2] - prev) * percent) * alpha;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += (prev + (nextVertices[i2] - prev) * percent - deform[i2]) * alpha;
|
|
}
|
|
break;
|
|
case 3 /* add */:
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += (prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]) * alpha;
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += (prev + (nextVertices[i2] - prev) * percent) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var _EventTimeline = class extends Timeline {
|
|
constructor(frameCount) {
|
|
super(frameCount, _EventTimeline.propertyIds);
|
|
this.events = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, event) {
|
|
this.frames[frame] = event.time;
|
|
this.events[frame] = event;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
if (!firedEvents)
|
|
return;
|
|
let frames = this.frames;
|
|
let frameCount = this.frames.length;
|
|
if (lastTime > time) {
|
|
this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction);
|
|
lastTime = -1;
|
|
} else if (lastTime >= frames[frameCount - 1])
|
|
return;
|
|
if (time < frames[0])
|
|
return;
|
|
let i = 0;
|
|
if (lastTime < frames[0])
|
|
i = 0;
|
|
else {
|
|
i = Timeline.search1(frames, lastTime) + 1;
|
|
let frameTime = frames[i];
|
|
while (i > 0) {
|
|
if (frames[i - 1] != frameTime)
|
|
break;
|
|
i--;
|
|
}
|
|
}
|
|
for (; i < frameCount && time >= frames[i]; i++)
|
|
firedEvents.push(this.events[i]);
|
|
}
|
|
};
|
|
var EventTimeline = _EventTimeline;
|
|
EventTimeline.propertyIds = ["" + Property.event];
|
|
var _DrawOrderTimeline = class extends Timeline {
|
|
constructor(frameCount) {
|
|
super(frameCount, _DrawOrderTimeline.propertyIds);
|
|
this.drawOrders = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, time, drawOrder) {
|
|
this.frames[frame] = time;
|
|
this.drawOrders[frame] = drawOrder;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
if (direction == 1 /* mixOut */) {
|
|
if (blend == 0 /* setup */)
|
|
Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
|
|
return;
|
|
}
|
|
if (time < this.frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
|
|
return;
|
|
}
|
|
let idx = Timeline.search1(this.frames, time);
|
|
let drawOrderToSetupIndex = this.drawOrders[idx];
|
|
if (!drawOrderToSetupIndex)
|
|
Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
|
|
else {
|
|
let drawOrder = skeleton.drawOrder;
|
|
let slots = skeleton.slots;
|
|
for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
|
|
drawOrder[i] = slots[drawOrderToSetupIndex[i]];
|
|
}
|
|
}
|
|
};
|
|
var DrawOrderTimeline = _DrawOrderTimeline;
|
|
DrawOrderTimeline.propertyIds = ["" + Property.drawOrder];
|
|
var IkConstraintTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, ikConstraintIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.ikConstraint + "|" + ikConstraintIndex
|
|
]);
|
|
this.ikConstraintIndex = 0;
|
|
this.ikConstraintIndex = ikConstraintIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 6;
|
|
}
|
|
setFrame(frame, time, mix, softness, bendDirection, compress, stretch) {
|
|
frame *= 6;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = mix;
|
|
this.frames[frame + 2] = softness;
|
|
this.frames[frame + 3] = bendDirection;
|
|
this.frames[frame + 4] = compress ? 1 : 0;
|
|
this.frames[frame + 5] = stretch ? 1 : 0;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.ikConstraints[this.ikConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.mix = constraint.data.mix;
|
|
constraint.softness = constraint.data.softness;
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
|
|
constraint.softness += (constraint.data.softness - constraint.softness) * alpha;
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
}
|
|
return;
|
|
}
|
|
let mix = 0, softness = 0;
|
|
let i = Timeline.search(frames, time, 6);
|
|
let curveType = this.curves[i / 6];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
mix = frames[i + 1];
|
|
softness = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 6] - before);
|
|
mix += (frames[i + 6 + 1] - mix) * t;
|
|
softness += (frames[i + 6 + 2] - softness) * t;
|
|
break;
|
|
case 1:
|
|
mix = frames[i + 1];
|
|
softness = frames[i + 2];
|
|
break;
|
|
default:
|
|
mix = this.getBezierValue(time, i, 1, curveType - 2);
|
|
softness = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
if (blend == 0 /* setup */) {
|
|
constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha;
|
|
constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha;
|
|
if (direction == 1 /* mixOut */) {
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
} else {
|
|
constraint.bendDirection = frames[i + 3];
|
|
constraint.compress = frames[i + 4] != 0;
|
|
constraint.stretch = frames[i + 5] != 0;
|
|
}
|
|
} else {
|
|
constraint.mix += (mix - constraint.mix) * alpha;
|
|
constraint.softness += (softness - constraint.softness) * alpha;
|
|
if (direction == 0 /* mixIn */) {
|
|
constraint.bendDirection = frames[i + 3];
|
|
constraint.compress = frames[i + 4] != 0;
|
|
constraint.stretch = frames[i + 5] != 0;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var TransformConstraintTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, transformConstraintIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.transformConstraint + "|" + transformConstraintIndex
|
|
]);
|
|
this.transformConstraintIndex = 0;
|
|
this.transformConstraintIndex = transformConstraintIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 7;
|
|
}
|
|
setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) {
|
|
let frames = this.frames;
|
|
frame *= 7;
|
|
frames[frame] = time;
|
|
frames[frame + 1] = mixRotate;
|
|
frames[frame + 2] = mixX;
|
|
frames[frame + 3] = mixY;
|
|
frames[frame + 4] = mixScaleX;
|
|
frames[frame + 5] = mixScaleY;
|
|
frames[frame + 6] = mixShearY;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.transformConstraints[this.transformConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
let data = constraint.data;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.mixRotate = data.mixRotate;
|
|
constraint.mixX = data.mixX;
|
|
constraint.mixY = data.mixY;
|
|
constraint.mixScaleX = data.mixScaleX;
|
|
constraint.mixScaleY = data.mixScaleY;
|
|
constraint.mixShearY = data.mixShearY;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (data.mixX - constraint.mixX) * alpha;
|
|
constraint.mixY += (data.mixY - constraint.mixY) * alpha;
|
|
constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha;
|
|
constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha;
|
|
constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let rotate, x, y, scaleX, scaleY, shearY;
|
|
let i = Timeline.search(frames, time, 7);
|
|
let curveType = this.curves[i / 7];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
scaleX = frames[i + 4];
|
|
scaleY = frames[i + 5];
|
|
shearY = frames[i + 6];
|
|
let t = (time - before) / (frames[i + 7] - before);
|
|
rotate += (frames[i + 7 + 1] - rotate) * t;
|
|
x += (frames[i + 7 + 2] - x) * t;
|
|
y += (frames[i + 7 + 3] - y) * t;
|
|
scaleX += (frames[i + 7 + 4] - scaleX) * t;
|
|
scaleY += (frames[i + 7 + 5] - scaleY) * t;
|
|
shearY += (frames[i + 7 + 6] - shearY) * t;
|
|
break;
|
|
case 1:
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
scaleX = frames[i + 4];
|
|
scaleY = frames[i + 5];
|
|
shearY = frames[i + 6];
|
|
break;
|
|
default:
|
|
rotate = this.getBezierValue(time, i, 1, curveType - 2);
|
|
x = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
y = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
scaleX = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
scaleY = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2);
|
|
shearY = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2);
|
|
}
|
|
if (blend == 0 /* setup */) {
|
|
let data = constraint.data;
|
|
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
|
|
constraint.mixX = data.mixX + (x - data.mixX) * alpha;
|
|
constraint.mixY = data.mixY + (y - data.mixY) * alpha;
|
|
constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha;
|
|
constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha;
|
|
constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha;
|
|
} else {
|
|
constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (x - constraint.mixX) * alpha;
|
|
constraint.mixY += (y - constraint.mixY) * alpha;
|
|
constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha;
|
|
constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha;
|
|
constraint.mixShearY += (shearY - constraint.mixShearY) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var PathConstraintPositionTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, pathConstraintIndex) {
|
|
super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex);
|
|
this.pathConstraintIndex = 0;
|
|
this.pathConstraintIndex = pathConstraintIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.pathConstraints[this.pathConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.position = constraint.data.position;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.position += (constraint.data.position - constraint.position) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let position = this.getCurveValue(time);
|
|
if (blend == 0 /* setup */)
|
|
constraint.position = constraint.data.position + (position - constraint.data.position) * alpha;
|
|
else
|
|
constraint.position += (position - constraint.position) * alpha;
|
|
}
|
|
};
|
|
var PathConstraintSpacingTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, pathConstraintIndex) {
|
|
super(frameCount, bezierCount, Property.pathConstraintSpacing + "|" + pathConstraintIndex);
|
|
this.pathConstraintIndex = 0;
|
|
this.pathConstraintIndex = pathConstraintIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.pathConstraints[this.pathConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.spacing = constraint.data.spacing;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let spacing = this.getCurveValue(time);
|
|
if (blend == 0 /* setup */)
|
|
constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha;
|
|
else
|
|
constraint.spacing += (spacing - constraint.spacing) * alpha;
|
|
}
|
|
};
|
|
var PathConstraintMixTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, pathConstraintIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.pathConstraintMix + "|" + pathConstraintIndex
|
|
]);
|
|
this.pathConstraintIndex = 0;
|
|
this.pathConstraintIndex = pathConstraintIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 4;
|
|
}
|
|
setFrame(frame, time, mixRotate, mixX, mixY) {
|
|
let frames = this.frames;
|
|
frame <<= 2;
|
|
frames[frame] = time;
|
|
frames[frame + 1] = mixRotate;
|
|
frames[frame + 2] = mixX;
|
|
frames[frame + 3] = mixY;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.pathConstraints[this.pathConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.mixRotate = constraint.data.mixRotate;
|
|
constraint.mixX = constraint.data.mixX;
|
|
constraint.mixY = constraint.data.mixY;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha;
|
|
constraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let rotate, x, y;
|
|
let i = Timeline.search(frames, time, 4);
|
|
let curveType = this.curves[i >> 2];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
let t = (time - before) / (frames[i + 4] - before);
|
|
rotate += (frames[i + 4 + 1] - rotate) * t;
|
|
x += (frames[i + 4 + 2] - x) * t;
|
|
y += (frames[i + 4 + 3] - y) * t;
|
|
break;
|
|
case 1:
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
break;
|
|
default:
|
|
rotate = this.getBezierValue(time, i, 1, curveType - 2);
|
|
x = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
y = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
}
|
|
if (blend == 0 /* setup */) {
|
|
let data = constraint.data;
|
|
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
|
|
constraint.mixX = data.mixX + (x - data.mixX) * alpha;
|
|
constraint.mixY = data.mixY + (y - data.mixY) * alpha;
|
|
} else {
|
|
constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (x - constraint.mixX) * alpha;
|
|
constraint.mixY += (y - constraint.mixY) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var _SequenceTimeline = class extends Timeline {
|
|
constructor(frameCount, slotIndex, attachment) {
|
|
super(frameCount, [
|
|
Property.sequence + "|" + slotIndex + "|" + attachment.sequence.id
|
|
]);
|
|
this.slotIndex = slotIndex;
|
|
this.attachment = attachment;
|
|
}
|
|
getFrameEntries() {
|
|
return _SequenceTimeline.ENTRIES;
|
|
}
|
|
getSlotIndex() {
|
|
return this.slotIndex;
|
|
}
|
|
getAttachment() {
|
|
return this.attachment;
|
|
}
|
|
setFrame(frame, time, mode, index, delay) {
|
|
let frames = this.frames;
|
|
frame *= _SequenceTimeline.ENTRIES;
|
|
frames[frame] = time;
|
|
frames[frame + _SequenceTimeline.MODE] = mode | index << 4;
|
|
frames[frame + _SequenceTimeline.DELAY] = delay;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let slotAttachment = slot.attachment;
|
|
let attachment = this.attachment;
|
|
if (slotAttachment != attachment) {
|
|
if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != attachment)
|
|
return;
|
|
}
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
slot.sequenceIndex = -1;
|
|
return;
|
|
}
|
|
let i = Timeline.search(frames, time, _SequenceTimeline.ENTRIES);
|
|
let before = frames[i];
|
|
let modeAndIndex = frames[i + _SequenceTimeline.MODE];
|
|
let delay = frames[i + _SequenceTimeline.DELAY];
|
|
if (!this.attachment.sequence)
|
|
return;
|
|
let index = modeAndIndex >> 4, count = this.attachment.sequence.regions.length;
|
|
let mode = SequenceModeValues[modeAndIndex & 15];
|
|
if (mode != 0 /* hold */) {
|
|
index += (time - before) / delay + 1e-5 | 0;
|
|
switch (mode) {
|
|
case 1 /* once */:
|
|
index = Math.min(count - 1, index);
|
|
break;
|
|
case 2 /* loop */:
|
|
index %= count;
|
|
break;
|
|
case 3 /* pingpong */: {
|
|
let n = (count << 1) - 2;
|
|
index = n == 0 ? 0 : index % n;
|
|
if (index >= count)
|
|
index = n - index;
|
|
break;
|
|
}
|
|
case 4 /* onceReverse */:
|
|
index = Math.max(count - 1 - index, 0);
|
|
break;
|
|
case 5 /* loopReverse */:
|
|
index = count - 1 - index % count;
|
|
break;
|
|
case 6 /* pingpongReverse */: {
|
|
let n = (count << 1) - 2;
|
|
index = n == 0 ? 0 : (index + count - 1) % n;
|
|
if (index >= count)
|
|
index = n - index;
|
|
}
|
|
}
|
|
}
|
|
slot.sequenceIndex = index;
|
|
}
|
|
};
|
|
var SequenceTimeline = _SequenceTimeline;
|
|
SequenceTimeline.ENTRIES = 3;
|
|
SequenceTimeline.MODE = 1;
|
|
SequenceTimeline.DELAY = 2;
|
|
|
|
// spine-core/src/AnimationState.ts
|
|
var _AnimationState = class {
|
|
constructor(data) {
|
|
this.tracks = new Array();
|
|
this.timeScale = 1;
|
|
this.unkeyedState = 0;
|
|
this.events = new Array();
|
|
this.listeners = new Array();
|
|
this.queue = new EventQueue(this);
|
|
this.propertyIDs = new StringSet();
|
|
this.animationsChanged = false;
|
|
this.trackEntryPool = new Pool(() => new TrackEntry());
|
|
this.data = data;
|
|
}
|
|
static emptyAnimation() {
|
|
return _AnimationState._emptyAnimation;
|
|
}
|
|
update(delta) {
|
|
delta *= this.timeScale;
|
|
let tracks = this.tracks;
|
|
for (let i = 0, n = tracks.length; i < n; i++) {
|
|
let current = tracks[i];
|
|
if (!current)
|
|
continue;
|
|
current.animationLast = current.nextAnimationLast;
|
|
current.trackLast = current.nextTrackLast;
|
|
let currentDelta = delta * current.timeScale;
|
|
if (current.delay > 0) {
|
|
current.delay -= currentDelta;
|
|
if (current.delay > 0)
|
|
continue;
|
|
currentDelta = -current.delay;
|
|
current.delay = 0;
|
|
}
|
|
let next = current.next;
|
|
if (next) {
|
|
let nextTime = current.trackLast - next.delay;
|
|
if (nextTime >= 0) {
|
|
next.delay = 0;
|
|
next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale;
|
|
current.trackTime += currentDelta;
|
|
this.setCurrent(i, next, true);
|
|
while (next.mixingFrom) {
|
|
next.mixTime += delta;
|
|
next = next.mixingFrom;
|
|
}
|
|
continue;
|
|
}
|
|
} else if (current.trackLast >= current.trackEnd && !current.mixingFrom) {
|
|
tracks[i] = null;
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
continue;
|
|
}
|
|
if (current.mixingFrom && this.updateMixingFrom(current, delta)) {
|
|
let from = current.mixingFrom;
|
|
current.mixingFrom = null;
|
|
if (from)
|
|
from.mixingTo = null;
|
|
while (from) {
|
|
this.queue.end(from);
|
|
from = from.mixingFrom;
|
|
}
|
|
}
|
|
current.trackTime += currentDelta;
|
|
}
|
|
this.queue.drain();
|
|
}
|
|
updateMixingFrom(to, delta) {
|
|
let from = to.mixingFrom;
|
|
if (!from)
|
|
return true;
|
|
let finished = this.updateMixingFrom(from, delta);
|
|
from.animationLast = from.nextAnimationLast;
|
|
from.trackLast = from.nextTrackLast;
|
|
if (to.mixTime > 0 && to.mixTime >= to.mixDuration) {
|
|
if (from.totalAlpha == 0 || to.mixDuration == 0) {
|
|
to.mixingFrom = from.mixingFrom;
|
|
if (from.mixingFrom)
|
|
from.mixingFrom.mixingTo = to;
|
|
to.interruptAlpha = from.interruptAlpha;
|
|
this.queue.end(from);
|
|
}
|
|
return finished;
|
|
}
|
|
from.trackTime += delta * from.timeScale;
|
|
to.mixTime += delta;
|
|
return false;
|
|
}
|
|
apply(skeleton) {
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
if (this.animationsChanged)
|
|
this._animationsChanged();
|
|
let events = this.events;
|
|
let tracks = this.tracks;
|
|
let applied = false;
|
|
for (let i2 = 0, n2 = tracks.length; i2 < n2; i2++) {
|
|
let current = tracks[i2];
|
|
if (!current || current.delay > 0)
|
|
continue;
|
|
applied = true;
|
|
let blend = i2 == 0 ? 1 /* first */ : current.mixBlend;
|
|
let mix = current.alpha;
|
|
if (current.mixingFrom)
|
|
mix *= this.applyMixingFrom(current, skeleton, blend);
|
|
else if (current.trackTime >= current.trackEnd && !current.next)
|
|
mix = 0;
|
|
let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime;
|
|
let applyEvents = events;
|
|
if (current.reverse) {
|
|
applyTime = current.animation.duration - applyTime;
|
|
applyEvents = null;
|
|
}
|
|
let timelines = current.animation.timelines;
|
|
let timelineCount = timelines.length;
|
|
if (i2 == 0 && mix == 1 || blend == 3 /* add */) {
|
|
for (let ii = 0; ii < timelineCount; ii++) {
|
|
Utils.webkit602BugfixHelper(mix, blend);
|
|
var timeline = timelines[ii];
|
|
if (timeline instanceof AttachmentTimeline)
|
|
this.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, true);
|
|
else
|
|
timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, 0 /* mixIn */);
|
|
}
|
|
} else {
|
|
let timelineMode = current.timelineMode;
|
|
let shortestRotation = current.shortestRotation;
|
|
let firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1;
|
|
if (firstFrame)
|
|
current.timelinesRotation.length = timelineCount << 1;
|
|
for (let ii = 0; ii < timelineCount; ii++) {
|
|
let timeline2 = timelines[ii];
|
|
let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : 0 /* setup */;
|
|
if (!shortestRotation && timeline2 instanceof RotateTimeline) {
|
|
this.applyRotateTimeline(timeline2, skeleton, applyTime, mix, timelineBlend, current.timelinesRotation, ii << 1, firstFrame);
|
|
} else if (timeline2 instanceof AttachmentTimeline) {
|
|
this.applyAttachmentTimeline(timeline2, skeleton, applyTime, blend, true);
|
|
} else {
|
|
Utils.webkit602BugfixHelper(mix, blend);
|
|
timeline2.apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, 0 /* mixIn */);
|
|
}
|
|
}
|
|
}
|
|
this.queueEvents(current, animationTime);
|
|
events.length = 0;
|
|
current.nextAnimationLast = animationTime;
|
|
current.nextTrackLast = current.trackTime;
|
|
}
|
|
var setupState = this.unkeyedState + SETUP;
|
|
var slots = skeleton.slots;
|
|
for (var i = 0, n = skeleton.slots.length; i < n; i++) {
|
|
var slot = slots[i];
|
|
if (slot.attachmentState == setupState) {
|
|
var attachmentName = slot.data.attachmentName;
|
|
slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));
|
|
}
|
|
}
|
|
this.unkeyedState += 2;
|
|
this.queue.drain();
|
|
return applied;
|
|
}
|
|
applyMixingFrom(to, skeleton, blend) {
|
|
let from = to.mixingFrom;
|
|
if (from.mixingFrom)
|
|
this.applyMixingFrom(from, skeleton, blend);
|
|
let mix = 0;
|
|
if (to.mixDuration == 0) {
|
|
mix = 1;
|
|
if (blend == 1 /* first */)
|
|
blend = 0 /* setup */;
|
|
} else {
|
|
mix = to.mixTime / to.mixDuration;
|
|
if (mix > 1)
|
|
mix = 1;
|
|
if (blend != 1 /* first */)
|
|
blend = from.mixBlend;
|
|
}
|
|
let attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold;
|
|
let timelines = from.animation.timelines;
|
|
let timelineCount = timelines.length;
|
|
let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix);
|
|
let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime;
|
|
let events = null;
|
|
if (from.reverse)
|
|
applyTime = from.animation.duration - applyTime;
|
|
else if (mix < from.eventThreshold)
|
|
events = this.events;
|
|
if (blend == 3 /* add */) {
|
|
for (let i = 0; i < timelineCount; i++)
|
|
timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, 1 /* mixOut */);
|
|
} else {
|
|
let timelineMode = from.timelineMode;
|
|
let timelineHoldMix = from.timelineHoldMix;
|
|
let shortestRotation = from.shortestRotation;
|
|
let firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1;
|
|
if (firstFrame)
|
|
from.timelinesRotation.length = timelineCount << 1;
|
|
from.totalAlpha = 0;
|
|
for (let i = 0; i < timelineCount; i++) {
|
|
let timeline = timelines[i];
|
|
let direction = 1 /* mixOut */;
|
|
let timelineBlend;
|
|
let alpha = 0;
|
|
switch (timelineMode[i]) {
|
|
case SUBSEQUENT:
|
|
if (!drawOrder && timeline instanceof DrawOrderTimeline)
|
|
continue;
|
|
timelineBlend = blend;
|
|
alpha = alphaMix;
|
|
break;
|
|
case FIRST:
|
|
timelineBlend = 0 /* setup */;
|
|
alpha = alphaMix;
|
|
break;
|
|
case HOLD_SUBSEQUENT:
|
|
timelineBlend = blend;
|
|
alpha = alphaHold;
|
|
break;
|
|
case HOLD_FIRST:
|
|
timelineBlend = 0 /* setup */;
|
|
alpha = alphaHold;
|
|
break;
|
|
default:
|
|
timelineBlend = 0 /* setup */;
|
|
let holdMix = timelineHoldMix[i];
|
|
alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);
|
|
break;
|
|
}
|
|
from.totalAlpha += alpha;
|
|
if (!shortestRotation && timeline instanceof RotateTimeline)
|
|
this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame);
|
|
else if (timeline instanceof AttachmentTimeline)
|
|
this.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments);
|
|
else {
|
|
Utils.webkit602BugfixHelper(alpha, blend);
|
|
if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == 0 /* setup */)
|
|
direction = 0 /* mixIn */;
|
|
timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction);
|
|
}
|
|
}
|
|
}
|
|
if (to.mixDuration > 0)
|
|
this.queueEvents(from, animationTime);
|
|
this.events.length = 0;
|
|
from.nextAnimationLast = animationTime;
|
|
from.nextTrackLast = from.trackTime;
|
|
return mix;
|
|
}
|
|
applyAttachmentTimeline(timeline, skeleton, time, blend, attachments) {
|
|
var slot = skeleton.slots[timeline.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
if (time < timeline.frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
|
|
} else
|
|
this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments);
|
|
if (slot.attachmentState <= this.unkeyedState)
|
|
slot.attachmentState = this.unkeyedState + SETUP;
|
|
}
|
|
setAttachment(skeleton, slot, attachmentName, attachments) {
|
|
slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));
|
|
if (attachments)
|
|
slot.attachmentState = this.unkeyedState + CURRENT;
|
|
}
|
|
applyRotateTimeline(timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) {
|
|
if (firstFrame)
|
|
timelinesRotation[i] = 0;
|
|
if (alpha == 1) {
|
|
timeline.apply(skeleton, 0, time, null, 1, blend, 0 /* mixIn */);
|
|
return;
|
|
}
|
|
let bone = skeleton.bones[timeline.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = timeline.frames;
|
|
let r1 = 0, r2 = 0;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.rotation = bone.data.rotation;
|
|
default:
|
|
return;
|
|
case 1 /* first */:
|
|
r1 = bone.rotation;
|
|
r2 = bone.data.rotation;
|
|
}
|
|
} else {
|
|
r1 = blend == 0 /* setup */ ? bone.data.rotation : bone.rotation;
|
|
r2 = bone.data.rotation + timeline.getCurveValue(time);
|
|
}
|
|
let total = 0, diff = r2 - r1;
|
|
diff -= (16384 - (16384.499999999996 - diff / 360 | 0)) * 360;
|
|
if (diff == 0) {
|
|
total = timelinesRotation[i];
|
|
} else {
|
|
let lastTotal = 0, lastDiff = 0;
|
|
if (firstFrame) {
|
|
lastTotal = 0;
|
|
lastDiff = diff;
|
|
} else {
|
|
lastTotal = timelinesRotation[i];
|
|
lastDiff = timelinesRotation[i + 1];
|
|
}
|
|
let current = diff > 0, dir = lastTotal >= 0;
|
|
if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) {
|
|
if (Math.abs(lastTotal) > 180)
|
|
lastTotal += 360 * MathUtils.signum(lastTotal);
|
|
dir = current;
|
|
}
|
|
total = diff + lastTotal - lastTotal % 360;
|
|
if (dir != current)
|
|
total += 360 * MathUtils.signum(lastTotal);
|
|
timelinesRotation[i] = total;
|
|
}
|
|
timelinesRotation[i + 1] = diff;
|
|
bone.rotation = r1 + total * alpha;
|
|
}
|
|
queueEvents(entry, animationTime) {
|
|
let animationStart = entry.animationStart, animationEnd = entry.animationEnd;
|
|
let duration = animationEnd - animationStart;
|
|
let trackLastWrapped = entry.trackLast % duration;
|
|
let events = this.events;
|
|
let i = 0, n = events.length;
|
|
for (; i < n; i++) {
|
|
let event = events[i];
|
|
if (event.time < trackLastWrapped)
|
|
break;
|
|
if (event.time > animationEnd)
|
|
continue;
|
|
this.queue.event(entry, event);
|
|
}
|
|
let complete = false;
|
|
if (entry.loop)
|
|
complete = duration == 0 || trackLastWrapped > entry.trackTime % duration;
|
|
else
|
|
complete = animationTime >= animationEnd && entry.animationLast < animationEnd;
|
|
if (complete)
|
|
this.queue.complete(entry);
|
|
for (; i < n; i++) {
|
|
let event = events[i];
|
|
if (event.time < animationStart)
|
|
continue;
|
|
this.queue.event(entry, event);
|
|
}
|
|
}
|
|
clearTracks() {
|
|
let oldDrainDisabled = this.queue.drainDisabled;
|
|
this.queue.drainDisabled = true;
|
|
for (let i = 0, n = this.tracks.length; i < n; i++)
|
|
this.clearTrack(i);
|
|
this.tracks.length = 0;
|
|
this.queue.drainDisabled = oldDrainDisabled;
|
|
this.queue.drain();
|
|
}
|
|
clearTrack(trackIndex) {
|
|
if (trackIndex >= this.tracks.length)
|
|
return;
|
|
let current = this.tracks[trackIndex];
|
|
if (!current)
|
|
return;
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
let entry = current;
|
|
while (true) {
|
|
let from = entry.mixingFrom;
|
|
if (!from)
|
|
break;
|
|
this.queue.end(from);
|
|
entry.mixingFrom = null;
|
|
entry.mixingTo = null;
|
|
entry = from;
|
|
}
|
|
this.tracks[current.trackIndex] = null;
|
|
this.queue.drain();
|
|
}
|
|
setCurrent(index, current, interrupt) {
|
|
let from = this.expandToIndex(index);
|
|
this.tracks[index] = current;
|
|
current.previous = null;
|
|
if (from) {
|
|
if (interrupt)
|
|
this.queue.interrupt(from);
|
|
current.mixingFrom = from;
|
|
from.mixingTo = current;
|
|
current.mixTime = 0;
|
|
if (from.mixingFrom && from.mixDuration > 0)
|
|
current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration);
|
|
from.timelinesRotation.length = 0;
|
|
}
|
|
this.queue.start(current);
|
|
}
|
|
setAnimation(trackIndex, animationName, loop = false) {
|
|
let animation = this.data.skeletonData.findAnimation(animationName);
|
|
if (!animation)
|
|
throw new Error("Animation not found: " + animationName);
|
|
return this.setAnimationWith(trackIndex, animation, loop);
|
|
}
|
|
setAnimationWith(trackIndex, animation, loop = false) {
|
|
if (!animation)
|
|
throw new Error("animation cannot be null.");
|
|
let interrupt = true;
|
|
let current = this.expandToIndex(trackIndex);
|
|
if (current) {
|
|
if (current.nextTrackLast == -1) {
|
|
this.tracks[trackIndex] = current.mixingFrom;
|
|
this.queue.interrupt(current);
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
current = current.mixingFrom;
|
|
interrupt = false;
|
|
} else
|
|
this.clearNext(current);
|
|
}
|
|
let entry = this.trackEntry(trackIndex, animation, loop, current);
|
|
this.setCurrent(trackIndex, entry, interrupt);
|
|
this.queue.drain();
|
|
return entry;
|
|
}
|
|
addAnimation(trackIndex, animationName, loop = false, delay = 0) {
|
|
let animation = this.data.skeletonData.findAnimation(animationName);
|
|
if (!animation)
|
|
throw new Error("Animation not found: " + animationName);
|
|
return this.addAnimationWith(trackIndex, animation, loop, delay);
|
|
}
|
|
addAnimationWith(trackIndex, animation, loop = false, delay = 0) {
|
|
if (!animation)
|
|
throw new Error("animation cannot be null.");
|
|
let last = this.expandToIndex(trackIndex);
|
|
if (last) {
|
|
while (last.next)
|
|
last = last.next;
|
|
}
|
|
let entry = this.trackEntry(trackIndex, animation, loop, last);
|
|
if (!last) {
|
|
this.setCurrent(trackIndex, entry, true);
|
|
this.queue.drain();
|
|
} else {
|
|
last.next = entry;
|
|
entry.previous = last;
|
|
if (delay <= 0)
|
|
delay += last.getTrackComplete() - entry.mixDuration;
|
|
}
|
|
entry.delay = delay;
|
|
return entry;
|
|
}
|
|
setEmptyAnimation(trackIndex, mixDuration = 0) {
|
|
let entry = this.setAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false);
|
|
entry.mixDuration = mixDuration;
|
|
entry.trackEnd = mixDuration;
|
|
return entry;
|
|
}
|
|
addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) {
|
|
let entry = this.addAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false, delay);
|
|
if (delay <= 0)
|
|
entry.delay += entry.mixDuration - mixDuration;
|
|
entry.mixDuration = mixDuration;
|
|
entry.trackEnd = mixDuration;
|
|
return entry;
|
|
}
|
|
setEmptyAnimations(mixDuration = 0) {
|
|
let oldDrainDisabled = this.queue.drainDisabled;
|
|
this.queue.drainDisabled = true;
|
|
for (let i = 0, n = this.tracks.length; i < n; i++) {
|
|
let current = this.tracks[i];
|
|
if (current)
|
|
this.setEmptyAnimation(current.trackIndex, mixDuration);
|
|
}
|
|
this.queue.drainDisabled = oldDrainDisabled;
|
|
this.queue.drain();
|
|
}
|
|
expandToIndex(index) {
|
|
if (index < this.tracks.length)
|
|
return this.tracks[index];
|
|
Utils.ensureArrayCapacity(this.tracks, index + 1, null);
|
|
this.tracks.length = index + 1;
|
|
return null;
|
|
}
|
|
trackEntry(trackIndex, animation, loop, last) {
|
|
let entry = this.trackEntryPool.obtain();
|
|
entry.reset();
|
|
entry.trackIndex = trackIndex;
|
|
entry.animation = animation;
|
|
entry.loop = loop;
|
|
entry.holdPrevious = false;
|
|
entry.reverse = false;
|
|
entry.shortestRotation = false;
|
|
entry.eventThreshold = 0;
|
|
entry.attachmentThreshold = 0;
|
|
entry.drawOrderThreshold = 0;
|
|
entry.animationStart = 0;
|
|
entry.animationEnd = animation.duration;
|
|
entry.animationLast = -1;
|
|
entry.nextAnimationLast = -1;
|
|
entry.delay = 0;
|
|
entry.trackTime = 0;
|
|
entry.trackLast = -1;
|
|
entry.nextTrackLast = -1;
|
|
entry.trackEnd = Number.MAX_VALUE;
|
|
entry.timeScale = 1;
|
|
entry.alpha = 1;
|
|
entry.mixTime = 0;
|
|
entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation);
|
|
entry.interruptAlpha = 1;
|
|
entry.totalAlpha = 0;
|
|
entry.mixBlend = 2 /* replace */;
|
|
return entry;
|
|
}
|
|
clearNext(entry) {
|
|
let next = entry.next;
|
|
while (next) {
|
|
this.queue.dispose(next);
|
|
next = next.next;
|
|
}
|
|
entry.next = null;
|
|
}
|
|
_animationsChanged() {
|
|
this.animationsChanged = false;
|
|
this.propertyIDs.clear();
|
|
let tracks = this.tracks;
|
|
for (let i = 0, n = tracks.length; i < n; i++) {
|
|
let entry = tracks[i];
|
|
if (!entry)
|
|
continue;
|
|
while (entry.mixingFrom)
|
|
entry = entry.mixingFrom;
|
|
do {
|
|
if (!entry.mixingTo || entry.mixBlend != 3 /* add */)
|
|
this.computeHold(entry);
|
|
entry = entry.mixingTo;
|
|
} while (entry);
|
|
}
|
|
}
|
|
computeHold(entry) {
|
|
let to = entry.mixingTo;
|
|
let timelines = entry.animation.timelines;
|
|
let timelinesCount = entry.animation.timelines.length;
|
|
let timelineMode = entry.timelineMode;
|
|
timelineMode.length = timelinesCount;
|
|
let timelineHoldMix = entry.timelineHoldMix;
|
|
timelineHoldMix.length = 0;
|
|
let propertyIDs = this.propertyIDs;
|
|
if (to && to.holdPrevious) {
|
|
for (let i = 0; i < timelinesCount; i++)
|
|
timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT;
|
|
return;
|
|
}
|
|
outer:
|
|
for (let i = 0; i < timelinesCount; i++) {
|
|
let timeline = timelines[i];
|
|
let ids = timeline.getPropertyIds();
|
|
if (!propertyIDs.addAll(ids))
|
|
timelineMode[i] = SUBSEQUENT;
|
|
else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline || timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) {
|
|
timelineMode[i] = FIRST;
|
|
} else {
|
|
for (let next = to.mixingTo; next; next = next.mixingTo) {
|
|
if (next.animation.hasTimeline(ids))
|
|
continue;
|
|
if (entry.mixDuration > 0) {
|
|
timelineMode[i] = HOLD_MIX;
|
|
timelineHoldMix[i] = next;
|
|
continue outer;
|
|
}
|
|
break;
|
|
}
|
|
timelineMode[i] = HOLD_FIRST;
|
|
}
|
|
}
|
|
}
|
|
getCurrent(trackIndex) {
|
|
if (trackIndex >= this.tracks.length)
|
|
return null;
|
|
return this.tracks[trackIndex];
|
|
}
|
|
addListener(listener) {
|
|
if (!listener)
|
|
throw new Error("listener cannot be null.");
|
|
this.listeners.push(listener);
|
|
}
|
|
removeListener(listener) {
|
|
let index = this.listeners.indexOf(listener);
|
|
if (index >= 0)
|
|
this.listeners.splice(index, 1);
|
|
}
|
|
clearListeners() {
|
|
this.listeners.length = 0;
|
|
}
|
|
clearListenerNotifications() {
|
|
this.queue.clear();
|
|
}
|
|
};
|
|
var AnimationState = _AnimationState;
|
|
AnimationState._emptyAnimation = new Animation("<empty>", [], 0);
|
|
var TrackEntry = class {
|
|
constructor() {
|
|
this.animation = null;
|
|
this.previous = null;
|
|
this.next = null;
|
|
this.mixingFrom = null;
|
|
this.mixingTo = null;
|
|
this.listener = null;
|
|
this.trackIndex = 0;
|
|
this.loop = false;
|
|
this.holdPrevious = false;
|
|
this.reverse = false;
|
|
this.shortestRotation = false;
|
|
this.eventThreshold = 0;
|
|
this.attachmentThreshold = 0;
|
|
this.drawOrderThreshold = 0;
|
|
this.animationStart = 0;
|
|
this.animationEnd = 0;
|
|
this.animationLast = 0;
|
|
this.nextAnimationLast = 0;
|
|
this.delay = 0;
|
|
this.trackTime = 0;
|
|
this.trackLast = 0;
|
|
this.nextTrackLast = 0;
|
|
this.trackEnd = 0;
|
|
this.timeScale = 0;
|
|
this.alpha = 0;
|
|
this.mixTime = 0;
|
|
this.mixDuration = 0;
|
|
this.interruptAlpha = 0;
|
|
this.totalAlpha = 0;
|
|
this.mixBlend = 2 /* replace */;
|
|
this.timelineMode = new Array();
|
|
this.timelineHoldMix = new Array();
|
|
this.timelinesRotation = new Array();
|
|
}
|
|
reset() {
|
|
this.next = null;
|
|
this.previous = null;
|
|
this.mixingFrom = null;
|
|
this.mixingTo = null;
|
|
this.animation = null;
|
|
this.listener = null;
|
|
this.timelineMode.length = 0;
|
|
this.timelineHoldMix.length = 0;
|
|
this.timelinesRotation.length = 0;
|
|
}
|
|
getAnimationTime() {
|
|
if (this.loop) {
|
|
let duration = this.animationEnd - this.animationStart;
|
|
if (duration == 0)
|
|
return this.animationStart;
|
|
return this.trackTime % duration + this.animationStart;
|
|
}
|
|
return Math.min(this.trackTime + this.animationStart, this.animationEnd);
|
|
}
|
|
setAnimationLast(animationLast) {
|
|
this.animationLast = animationLast;
|
|
this.nextAnimationLast = animationLast;
|
|
}
|
|
isComplete() {
|
|
return this.trackTime >= this.animationEnd - this.animationStart;
|
|
}
|
|
resetRotationDirections() {
|
|
this.timelinesRotation.length = 0;
|
|
}
|
|
getTrackComplete() {
|
|
let duration = this.animationEnd - this.animationStart;
|
|
if (duration != 0) {
|
|
if (this.loop)
|
|
return duration * (1 + (this.trackTime / duration | 0));
|
|
if (this.trackTime < duration)
|
|
return duration;
|
|
}
|
|
return this.trackTime;
|
|
}
|
|
};
|
|
var EventQueue = class {
|
|
constructor(animState) {
|
|
this.objects = [];
|
|
this.drainDisabled = false;
|
|
this.animState = animState;
|
|
}
|
|
start(entry) {
|
|
this.objects.push(EventType.start);
|
|
this.objects.push(entry);
|
|
this.animState.animationsChanged = true;
|
|
}
|
|
interrupt(entry) {
|
|
this.objects.push(EventType.interrupt);
|
|
this.objects.push(entry);
|
|
}
|
|
end(entry) {
|
|
this.objects.push(EventType.end);
|
|
this.objects.push(entry);
|
|
this.animState.animationsChanged = true;
|
|
}
|
|
dispose(entry) {
|
|
this.objects.push(EventType.dispose);
|
|
this.objects.push(entry);
|
|
}
|
|
complete(entry) {
|
|
this.objects.push(EventType.complete);
|
|
this.objects.push(entry);
|
|
}
|
|
event(entry, event) {
|
|
this.objects.push(EventType.event);
|
|
this.objects.push(entry);
|
|
this.objects.push(event);
|
|
}
|
|
drain() {
|
|
if (this.drainDisabled)
|
|
return;
|
|
this.drainDisabled = true;
|
|
let objects = this.objects;
|
|
let listeners = this.animState.listeners;
|
|
for (let i = 0; i < objects.length; i += 2) {
|
|
let type = objects[i];
|
|
let entry = objects[i + 1];
|
|
switch (type) {
|
|
case EventType.start:
|
|
if (entry.listener && entry.listener.start)
|
|
entry.listener.start(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.start)
|
|
listener.start(entry);
|
|
}
|
|
break;
|
|
case EventType.interrupt:
|
|
if (entry.listener && entry.listener.interrupt)
|
|
entry.listener.interrupt(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.interrupt)
|
|
listener.interrupt(entry);
|
|
}
|
|
break;
|
|
case EventType.end:
|
|
if (entry.listener && entry.listener.end)
|
|
entry.listener.end(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.end)
|
|
listener.end(entry);
|
|
}
|
|
case EventType.dispose:
|
|
if (entry.listener && entry.listener.dispose)
|
|
entry.listener.dispose(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.dispose)
|
|
listener.dispose(entry);
|
|
}
|
|
this.animState.trackEntryPool.free(entry);
|
|
break;
|
|
case EventType.complete:
|
|
if (entry.listener && entry.listener.complete)
|
|
entry.listener.complete(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.complete)
|
|
listener.complete(entry);
|
|
}
|
|
break;
|
|
case EventType.event:
|
|
let event = objects[i++ + 2];
|
|
if (entry.listener && entry.listener.event)
|
|
entry.listener.event(entry, event);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.event)
|
|
listener.event(entry, event);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
this.clear();
|
|
this.drainDisabled = false;
|
|
}
|
|
clear() {
|
|
this.objects.length = 0;
|
|
}
|
|
};
|
|
var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
EventType2[EventType2["start"] = 0] = "start";
|
|
EventType2[EventType2["interrupt"] = 1] = "interrupt";
|
|
EventType2[EventType2["end"] = 2] = "end";
|
|
EventType2[EventType2["dispose"] = 3] = "dispose";
|
|
EventType2[EventType2["complete"] = 4] = "complete";
|
|
EventType2[EventType2["event"] = 5] = "event";
|
|
return EventType2;
|
|
})(EventType || {});
|
|
var AnimationStateAdapter = class {
|
|
start(entry) {
|
|
}
|
|
interrupt(entry) {
|
|
}
|
|
end(entry) {
|
|
}
|
|
dispose(entry) {
|
|
}
|
|
complete(entry) {
|
|
}
|
|
event(entry, event) {
|
|
}
|
|
};
|
|
var SUBSEQUENT = 0;
|
|
var FIRST = 1;
|
|
var HOLD_SUBSEQUENT = 2;
|
|
var HOLD_FIRST = 3;
|
|
var HOLD_MIX = 4;
|
|
var SETUP = 1;
|
|
var CURRENT = 2;
|
|
|
|
// spine-core/src/AnimationStateData.ts
|
|
var AnimationStateData = class {
|
|
constructor(skeletonData) {
|
|
this.animationToMixTime = {};
|
|
this.defaultMix = 0;
|
|
if (!skeletonData)
|
|
throw new Error("skeletonData cannot be null.");
|
|
this.skeletonData = skeletonData;
|
|
}
|
|
setMix(fromName, toName, duration) {
|
|
let from = this.skeletonData.findAnimation(fromName);
|
|
if (!from)
|
|
throw new Error("Animation not found: " + fromName);
|
|
let to = this.skeletonData.findAnimation(toName);
|
|
if (!to)
|
|
throw new Error("Animation not found: " + toName);
|
|
this.setMixWith(from, to, duration);
|
|
}
|
|
setMixWith(from, to, duration) {
|
|
if (!from)
|
|
throw new Error("from cannot be null.");
|
|
if (!to)
|
|
throw new Error("to cannot be null.");
|
|
let key = from.name + "." + to.name;
|
|
this.animationToMixTime[key] = duration;
|
|
}
|
|
getMix(from, to) {
|
|
let key = from.name + "." + to.name;
|
|
let value = this.animationToMixTime[key];
|
|
return value === void 0 ? this.defaultMix : value;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/BoundingBoxAttachment.ts
|
|
var BoundingBoxAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.color = new Color(1, 1, 1, 1);
|
|
}
|
|
copy() {
|
|
let copy = new BoundingBoxAttachment(this.name);
|
|
this.copyTo(copy);
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/ClippingAttachment.ts
|
|
var ClippingAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.endSlot = null;
|
|
this.color = new Color(0.2275, 0.2275, 0.8078, 1);
|
|
}
|
|
copy() {
|
|
let copy = new ClippingAttachment(this.name);
|
|
this.copyTo(copy);
|
|
copy.endSlot = this.endSlot;
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Texture.ts
|
|
var Texture = class {
|
|
constructor(image) {
|
|
this._image = image;
|
|
}
|
|
getImage() {
|
|
return this._image;
|
|
}
|
|
};
|
|
var TextureFilter = /* @__PURE__ */ ((TextureFilter3) => {
|
|
TextureFilter3[TextureFilter3["Nearest"] = 9728] = "Nearest";
|
|
TextureFilter3[TextureFilter3["Linear"] = 9729] = "Linear";
|
|
TextureFilter3[TextureFilter3["MipMap"] = 9987] = "MipMap";
|
|
TextureFilter3[TextureFilter3["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest";
|
|
TextureFilter3[TextureFilter3["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest";
|
|
TextureFilter3[TextureFilter3["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear";
|
|
TextureFilter3[TextureFilter3["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear";
|
|
return TextureFilter3;
|
|
})(TextureFilter || {});
|
|
var TextureWrap = /* @__PURE__ */ ((TextureWrap3) => {
|
|
TextureWrap3[TextureWrap3["MirroredRepeat"] = 33648] = "MirroredRepeat";
|
|
TextureWrap3[TextureWrap3["ClampToEdge"] = 33071] = "ClampToEdge";
|
|
TextureWrap3[TextureWrap3["Repeat"] = 10497] = "Repeat";
|
|
return TextureWrap3;
|
|
})(TextureWrap || {});
|
|
var TextureRegion = class {
|
|
constructor() {
|
|
this.u = 0;
|
|
this.v = 0;
|
|
this.u2 = 0;
|
|
this.v2 = 0;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.degrees = 0;
|
|
this.offsetX = 0;
|
|
this.offsetY = 0;
|
|
this.originalWidth = 0;
|
|
this.originalHeight = 0;
|
|
}
|
|
};
|
|
var FakeTexture = class extends Texture {
|
|
setFilters(minFilter, magFilter) {
|
|
}
|
|
setWraps(uWrap, vWrap) {
|
|
}
|
|
dispose() {
|
|
}
|
|
};
|
|
|
|
// spine-core/src/TextureAtlas.ts
|
|
var TextureAtlas = class {
|
|
constructor(atlasText) {
|
|
this.pages = new Array();
|
|
this.regions = new Array();
|
|
let reader = new TextureAtlasReader(atlasText);
|
|
let entry = new Array(4);
|
|
let pageFields = {};
|
|
pageFields["size"] = (page2) => {
|
|
page2.width = parseInt(entry[1]);
|
|
page2.height = parseInt(entry[2]);
|
|
};
|
|
pageFields["format"] = () => {
|
|
};
|
|
pageFields["filter"] = (page2) => {
|
|
page2.minFilter = Utils.enumValue(TextureFilter, entry[1]);
|
|
page2.magFilter = Utils.enumValue(TextureFilter, entry[2]);
|
|
};
|
|
pageFields["repeat"] = (page2) => {
|
|
if (entry[1].indexOf("x") != -1)
|
|
page2.uWrap = 10497 /* Repeat */;
|
|
if (entry[1].indexOf("y") != -1)
|
|
page2.vWrap = 10497 /* Repeat */;
|
|
};
|
|
pageFields["pma"] = (page2) => {
|
|
page2.pma = entry[1] == "true";
|
|
};
|
|
var regionFields = {};
|
|
regionFields["xy"] = (region) => {
|
|
region.x = parseInt(entry[1]);
|
|
region.y = parseInt(entry[2]);
|
|
};
|
|
regionFields["size"] = (region) => {
|
|
region.width = parseInt(entry[1]);
|
|
region.height = parseInt(entry[2]);
|
|
};
|
|
regionFields["bounds"] = (region) => {
|
|
region.x = parseInt(entry[1]);
|
|
region.y = parseInt(entry[2]);
|
|
region.width = parseInt(entry[3]);
|
|
region.height = parseInt(entry[4]);
|
|
};
|
|
regionFields["offset"] = (region) => {
|
|
region.offsetX = parseInt(entry[1]);
|
|
region.offsetY = parseInt(entry[2]);
|
|
};
|
|
regionFields["orig"] = (region) => {
|
|
region.originalWidth = parseInt(entry[1]);
|
|
region.originalHeight = parseInt(entry[2]);
|
|
};
|
|
regionFields["offsets"] = (region) => {
|
|
region.offsetX = parseInt(entry[1]);
|
|
region.offsetY = parseInt(entry[2]);
|
|
region.originalWidth = parseInt(entry[3]);
|
|
region.originalHeight = parseInt(entry[4]);
|
|
};
|
|
regionFields["rotate"] = (region) => {
|
|
let value = entry[1];
|
|
if (value == "true")
|
|
region.degrees = 90;
|
|
else if (value != "false")
|
|
region.degrees = parseInt(value);
|
|
};
|
|
regionFields["index"] = (region) => {
|
|
region.index = parseInt(entry[1]);
|
|
};
|
|
let line = reader.readLine();
|
|
while (line && line.trim().length == 0)
|
|
line = reader.readLine();
|
|
while (true) {
|
|
if (!line || line.trim().length == 0)
|
|
break;
|
|
if (reader.readEntry(entry, line) == 0)
|
|
break;
|
|
line = reader.readLine();
|
|
}
|
|
let page = null;
|
|
let names = null;
|
|
let values = null;
|
|
while (true) {
|
|
if (line === null)
|
|
break;
|
|
if (line.trim().length == 0) {
|
|
page = null;
|
|
line = reader.readLine();
|
|
} else if (!page) {
|
|
page = new TextureAtlasPage(line.trim());
|
|
while (true) {
|
|
if (reader.readEntry(entry, line = reader.readLine()) == 0)
|
|
break;
|
|
let field = pageFields[entry[0]];
|
|
if (field)
|
|
field(page);
|
|
}
|
|
this.pages.push(page);
|
|
} else {
|
|
let region = new TextureAtlasRegion(page, line);
|
|
while (true) {
|
|
let count = reader.readEntry(entry, line = reader.readLine());
|
|
if (count == 0)
|
|
break;
|
|
let field = regionFields[entry[0]];
|
|
if (field)
|
|
field(region);
|
|
else {
|
|
if (!names)
|
|
names = [];
|
|
if (!values)
|
|
values = [];
|
|
names.push(entry[0]);
|
|
let entryValues = [];
|
|
for (let i = 0; i < count; i++)
|
|
entryValues.push(parseInt(entry[i + 1]));
|
|
values.push(entryValues);
|
|
}
|
|
}
|
|
if (region.originalWidth == 0 && region.originalHeight == 0) {
|
|
region.originalWidth = region.width;
|
|
region.originalHeight = region.height;
|
|
}
|
|
if (names && names.length > 0 && values && values.length > 0) {
|
|
region.names = names;
|
|
region.values = values;
|
|
names = null;
|
|
values = null;
|
|
}
|
|
region.u = region.x / page.width;
|
|
region.v = region.y / page.height;
|
|
if (region.degrees == 90) {
|
|
region.u2 = (region.x + region.height) / page.width;
|
|
region.v2 = (region.y + region.width) / page.height;
|
|
} else {
|
|
region.u2 = (region.x + region.width) / page.width;
|
|
region.v2 = (region.y + region.height) / page.height;
|
|
}
|
|
this.regions.push(region);
|
|
}
|
|
}
|
|
}
|
|
findRegion(name) {
|
|
for (let i = 0; i < this.regions.length; i++) {
|
|
if (this.regions[i].name == name) {
|
|
return this.regions[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
setTextures(assetManager, pathPrefix = "") {
|
|
for (let page of this.pages)
|
|
page.setTexture(assetManager.get(pathPrefix + page.name));
|
|
}
|
|
dispose() {
|
|
var _a;
|
|
for (let i = 0; i < this.pages.length; i++) {
|
|
(_a = this.pages[i].texture) == null ? void 0 : _a.dispose();
|
|
}
|
|
}
|
|
};
|
|
var TextureAtlasReader = class {
|
|
constructor(text) {
|
|
this.index = 0;
|
|
this.lines = text.split(/\r\n|\r|\n/);
|
|
}
|
|
readLine() {
|
|
if (this.index >= this.lines.length)
|
|
return null;
|
|
return this.lines[this.index++];
|
|
}
|
|
readEntry(entry, line) {
|
|
if (!line)
|
|
return 0;
|
|
line = line.trim();
|
|
if (line.length == 0)
|
|
return 0;
|
|
let colon = line.indexOf(":");
|
|
if (colon == -1)
|
|
return 0;
|
|
entry[0] = line.substr(0, colon).trim();
|
|
for (let i = 1, lastMatch = colon + 1; ; i++) {
|
|
let comma = line.indexOf(",", lastMatch);
|
|
if (comma == -1) {
|
|
entry[i] = line.substr(lastMatch).trim();
|
|
return i;
|
|
}
|
|
entry[i] = line.substr(lastMatch, comma - lastMatch).trim();
|
|
lastMatch = comma + 1;
|
|
if (i == 4)
|
|
return 4;
|
|
}
|
|
}
|
|
};
|
|
var TextureAtlasPage = class {
|
|
constructor(name) {
|
|
this.minFilter = 9728 /* Nearest */;
|
|
this.magFilter = 9728 /* Nearest */;
|
|
this.uWrap = 33071 /* ClampToEdge */;
|
|
this.vWrap = 33071 /* ClampToEdge */;
|
|
this.texture = null;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.pma = false;
|
|
this.name = name;
|
|
}
|
|
setTexture(texture) {
|
|
this.texture = texture;
|
|
texture.setFilters(this.minFilter, this.magFilter);
|
|
texture.setWraps(this.uWrap, this.vWrap);
|
|
}
|
|
};
|
|
var TextureAtlasRegion = class extends TextureRegion {
|
|
constructor(page, name) {
|
|
super();
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.offsetX = 0;
|
|
this.offsetY = 0;
|
|
this.originalWidth = 0;
|
|
this.originalHeight = 0;
|
|
this.index = 0;
|
|
this.degrees = 0;
|
|
this.names = null;
|
|
this.values = null;
|
|
this.page = page;
|
|
this.name = name;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/MeshAttachment.ts
|
|
var MeshAttachment = class extends VertexAttachment {
|
|
constructor(name, path) {
|
|
super(name);
|
|
this.region = null;
|
|
this.regionUVs = [];
|
|
this.uvs = [];
|
|
this.triangles = [];
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.hullLength = 0;
|
|
this.edges = [];
|
|
this.parentMesh = null;
|
|
this.sequence = null;
|
|
this.tempColor = new Color(0, 0, 0, 0);
|
|
this.path = path;
|
|
}
|
|
updateRegion() {
|
|
if (!this.region)
|
|
throw new Error("Region not set.");
|
|
let regionUVs = this.regionUVs;
|
|
if (!this.uvs || this.uvs.length != regionUVs.length)
|
|
this.uvs = Utils.newFloatArray(regionUVs.length);
|
|
let uvs = this.uvs;
|
|
let n = this.uvs.length;
|
|
let u = this.region.u, v = this.region.v, width = 0, height = 0;
|
|
if (this.region instanceof TextureAtlasRegion) {
|
|
let region = this.region, image = region.page.texture.getImage();
|
|
let textureWidth = image.width, textureHeight = image.height;
|
|
switch (region.degrees) {
|
|
case 90:
|
|
u -= (region.originalHeight - region.offsetY - region.height) / textureWidth;
|
|
v -= (region.originalWidth - region.offsetX - region.width) / textureHeight;
|
|
width = region.originalHeight / textureWidth;
|
|
height = region.originalWidth / textureHeight;
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + regionUVs[i + 1] * width;
|
|
uvs[i + 1] = v + (1 - regionUVs[i]) * height;
|
|
}
|
|
return;
|
|
case 180:
|
|
u -= (region.originalWidth - region.offsetX - region.width) / textureWidth;
|
|
v -= region.offsetY / textureHeight;
|
|
width = region.originalWidth / textureWidth;
|
|
height = region.originalHeight / textureHeight;
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + (1 - regionUVs[i]) * width;
|
|
uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;
|
|
}
|
|
return;
|
|
case 270:
|
|
u -= region.offsetY / textureWidth;
|
|
v -= region.offsetX / textureHeight;
|
|
width = region.originalHeight / textureWidth;
|
|
height = region.originalWidth / textureHeight;
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + (1 - regionUVs[i + 1]) * width;
|
|
uvs[i + 1] = v + regionUVs[i] * height;
|
|
}
|
|
return;
|
|
}
|
|
u -= region.offsetX / textureWidth;
|
|
v -= (region.originalHeight - region.offsetY - region.height) / textureHeight;
|
|
width = region.originalWidth / textureWidth;
|
|
height = region.originalHeight / textureHeight;
|
|
} else if (!this.region) {
|
|
u = v = 0;
|
|
width = height = 1;
|
|
} else {
|
|
width = this.region.u2 - u;
|
|
height = this.region.v2 - v;
|
|
}
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + regionUVs[i] * width;
|
|
uvs[i + 1] = v + regionUVs[i + 1] * height;
|
|
}
|
|
}
|
|
getParentMesh() {
|
|
return this.parentMesh;
|
|
}
|
|
setParentMesh(parentMesh) {
|
|
this.parentMesh = parentMesh;
|
|
if (parentMesh) {
|
|
this.bones = parentMesh.bones;
|
|
this.vertices = parentMesh.vertices;
|
|
this.worldVerticesLength = parentMesh.worldVerticesLength;
|
|
this.regionUVs = parentMesh.regionUVs;
|
|
this.triangles = parentMesh.triangles;
|
|
this.hullLength = parentMesh.hullLength;
|
|
this.worldVerticesLength = parentMesh.worldVerticesLength;
|
|
}
|
|
}
|
|
copy() {
|
|
if (this.parentMesh)
|
|
return this.newLinkedMesh();
|
|
let copy = new MeshAttachment(this.name, this.path);
|
|
copy.region = this.region;
|
|
copy.color.setFromColor(this.color);
|
|
this.copyTo(copy);
|
|
copy.regionUVs = new Array(this.regionUVs.length);
|
|
Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length);
|
|
copy.uvs = new Array(this.uvs.length);
|
|
Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length);
|
|
copy.triangles = new Array(this.triangles.length);
|
|
Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length);
|
|
copy.hullLength = this.hullLength;
|
|
copy.sequence = this.sequence != null ? this.sequence.copy() : null;
|
|
if (this.edges) {
|
|
copy.edges = new Array(this.edges.length);
|
|
Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length);
|
|
}
|
|
copy.width = this.width;
|
|
copy.height = this.height;
|
|
return copy;
|
|
}
|
|
computeWorldVertices(slot, start, count, worldVertices2, offset, stride) {
|
|
if (this.sequence != null)
|
|
this.sequence.apply(slot, this);
|
|
super.computeWorldVertices(slot, start, count, worldVertices2, offset, stride);
|
|
}
|
|
newLinkedMesh() {
|
|
let copy = new MeshAttachment(this.name, this.path);
|
|
copy.region = this.region;
|
|
copy.color.setFromColor(this.color);
|
|
copy.timelineAttachment = this.timelineAttachment;
|
|
copy.setParentMesh(this.parentMesh ? this.parentMesh : this);
|
|
if (copy.region != null)
|
|
copy.updateRegion();
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/PathAttachment.ts
|
|
var PathAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.lengths = [];
|
|
this.closed = false;
|
|
this.constantSpeed = false;
|
|
this.color = new Color(1, 1, 1, 1);
|
|
}
|
|
copy() {
|
|
let copy = new PathAttachment(this.name);
|
|
this.copyTo(copy);
|
|
copy.lengths = new Array(this.lengths.length);
|
|
Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length);
|
|
copy.closed = closed;
|
|
copy.constantSpeed = this.constantSpeed;
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/PointAttachment.ts
|
|
var PointAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.rotation = 0;
|
|
this.color = new Color(0.38, 0.94, 0, 1);
|
|
}
|
|
computeWorldPosition(bone, point) {
|
|
point.x = this.x * bone.a + this.y * bone.b + bone.worldX;
|
|
point.y = this.x * bone.c + this.y * bone.d + bone.worldY;
|
|
return point;
|
|
}
|
|
computeWorldRotation(bone) {
|
|
let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation);
|
|
let x = cos * bone.a + sin * bone.b;
|
|
let y = cos * bone.c + sin * bone.d;
|
|
return Math.atan2(y, x) * MathUtils.radDeg;
|
|
}
|
|
copy() {
|
|
let copy = new PointAttachment(this.name);
|
|
copy.x = this.x;
|
|
copy.y = this.y;
|
|
copy.rotation = this.rotation;
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/RegionAttachment.ts
|
|
var _RegionAttachment = class extends Attachment {
|
|
constructor(name, path) {
|
|
super(name);
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.scaleX = 1;
|
|
this.scaleY = 1;
|
|
this.rotation = 0;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.rendererObject = null;
|
|
this.region = null;
|
|
this.sequence = null;
|
|
this.offset = Utils.newFloatArray(8);
|
|
this.uvs = Utils.newFloatArray(8);
|
|
this.tempColor = new Color(1, 1, 1, 1);
|
|
this.path = path;
|
|
}
|
|
updateRegion() {
|
|
if (!this.region)
|
|
throw new Error("Region not set.");
|
|
let region = this.region;
|
|
let uvs = this.uvs;
|
|
if (region == null) {
|
|
uvs[0] = 0;
|
|
uvs[1] = 0;
|
|
uvs[2] = 0;
|
|
uvs[3] = 1;
|
|
uvs[4] = 1;
|
|
uvs[5] = 1;
|
|
uvs[6] = 1;
|
|
uvs[7] = 0;
|
|
return;
|
|
}
|
|
let regionScaleX = this.width / this.region.originalWidth * this.scaleX;
|
|
let regionScaleY = this.height / this.region.originalHeight * this.scaleY;
|
|
let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX;
|
|
let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY;
|
|
let localX2 = localX + this.region.width * regionScaleX;
|
|
let localY2 = localY + this.region.height * regionScaleY;
|
|
let radians = this.rotation * Math.PI / 180;
|
|
let cos = Math.cos(radians);
|
|
let sin = Math.sin(radians);
|
|
let x = this.x, y = this.y;
|
|
let localXCos = localX * cos + x;
|
|
let localXSin = localX * sin;
|
|
let localYCos = localY * cos + y;
|
|
let localYSin = localY * sin;
|
|
let localX2Cos = localX2 * cos + x;
|
|
let localX2Sin = localX2 * sin;
|
|
let localY2Cos = localY2 * cos + y;
|
|
let localY2Sin = localY2 * sin;
|
|
let offset = this.offset;
|
|
offset[0] = localXCos - localYSin;
|
|
offset[1] = localYCos + localXSin;
|
|
offset[2] = localXCos - localY2Sin;
|
|
offset[3] = localY2Cos + localXSin;
|
|
offset[4] = localX2Cos - localY2Sin;
|
|
offset[5] = localY2Cos + localX2Sin;
|
|
offset[6] = localX2Cos - localYSin;
|
|
offset[7] = localYCos + localX2Sin;
|
|
if (region.degrees == 90) {
|
|
uvs[0] = region.u2;
|
|
uvs[1] = region.v2;
|
|
uvs[2] = region.u;
|
|
uvs[3] = region.v2;
|
|
uvs[4] = region.u;
|
|
uvs[5] = region.v;
|
|
uvs[6] = region.u2;
|
|
uvs[7] = region.v;
|
|
} else {
|
|
uvs[0] = region.u;
|
|
uvs[1] = region.v2;
|
|
uvs[2] = region.u;
|
|
uvs[3] = region.v;
|
|
uvs[4] = region.u2;
|
|
uvs[5] = region.v;
|
|
uvs[6] = region.u2;
|
|
uvs[7] = region.v2;
|
|
}
|
|
}
|
|
computeWorldVertices(slot, worldVertices2, offset, stride) {
|
|
if (this.sequence != null)
|
|
this.sequence.apply(slot, this);
|
|
let bone = slot.bone;
|
|
let vertexOffset = this.offset;
|
|
let x = bone.worldX, y = bone.worldY;
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
let offsetX = 0, offsetY = 0;
|
|
offsetX = vertexOffset[0];
|
|
offsetY = vertexOffset[1];
|
|
worldVertices2[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices2[offset + 1] = offsetX * c + offsetY * d + y;
|
|
offset += stride;
|
|
offsetX = vertexOffset[2];
|
|
offsetY = vertexOffset[3];
|
|
worldVertices2[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices2[offset + 1] = offsetX * c + offsetY * d + y;
|
|
offset += stride;
|
|
offsetX = vertexOffset[4];
|
|
offsetY = vertexOffset[5];
|
|
worldVertices2[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices2[offset + 1] = offsetX * c + offsetY * d + y;
|
|
offset += stride;
|
|
offsetX = vertexOffset[6];
|
|
offsetY = vertexOffset[7];
|
|
worldVertices2[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices2[offset + 1] = offsetX * c + offsetY * d + y;
|
|
}
|
|
copy() {
|
|
let copy = new _RegionAttachment(this.name, this.path);
|
|
copy.region = this.region;
|
|
copy.rendererObject = this.rendererObject;
|
|
copy.x = this.x;
|
|
copy.y = this.y;
|
|
copy.scaleX = this.scaleX;
|
|
copy.scaleY = this.scaleY;
|
|
copy.rotation = this.rotation;
|
|
copy.width = this.width;
|
|
copy.height = this.height;
|
|
Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8);
|
|
Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8);
|
|
copy.color.setFromColor(this.color);
|
|
copy.sequence = this.sequence != null ? this.sequence.copy() : null;
|
|
return copy;
|
|
}
|
|
};
|
|
var RegionAttachment = _RegionAttachment;
|
|
RegionAttachment.X1 = 0;
|
|
RegionAttachment.Y1 = 1;
|
|
RegionAttachment.C1R = 2;
|
|
RegionAttachment.C1G = 3;
|
|
RegionAttachment.C1B = 4;
|
|
RegionAttachment.C1A = 5;
|
|
RegionAttachment.U1 = 6;
|
|
RegionAttachment.V1 = 7;
|
|
RegionAttachment.X2 = 8;
|
|
RegionAttachment.Y2 = 9;
|
|
RegionAttachment.C2R = 10;
|
|
RegionAttachment.C2G = 11;
|
|
RegionAttachment.C2B = 12;
|
|
RegionAttachment.C2A = 13;
|
|
RegionAttachment.U2 = 14;
|
|
RegionAttachment.V2 = 15;
|
|
RegionAttachment.X3 = 16;
|
|
RegionAttachment.Y3 = 17;
|
|
RegionAttachment.C3R = 18;
|
|
RegionAttachment.C3G = 19;
|
|
RegionAttachment.C3B = 20;
|
|
RegionAttachment.C3A = 21;
|
|
RegionAttachment.U3 = 22;
|
|
RegionAttachment.V3 = 23;
|
|
RegionAttachment.X4 = 24;
|
|
RegionAttachment.Y4 = 25;
|
|
RegionAttachment.C4R = 26;
|
|
RegionAttachment.C4G = 27;
|
|
RegionAttachment.C4B = 28;
|
|
RegionAttachment.C4A = 29;
|
|
RegionAttachment.U4 = 30;
|
|
RegionAttachment.V4 = 31;
|
|
|
|
// spine-core/src/AtlasAttachmentLoader.ts
|
|
var AtlasAttachmentLoader = class {
|
|
constructor(atlas) {
|
|
this.atlas = atlas;
|
|
}
|
|
loadSequence(name, basePath, sequence) {
|
|
let regions = sequence.regions;
|
|
for (let i = 0, n = regions.length; i < n; i++) {
|
|
let path = sequence.getPath(basePath, i);
|
|
let region = this.atlas.findRegion(path);
|
|
if (region == null)
|
|
throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")");
|
|
regions[i] = region;
|
|
regions[i].renderObject = regions[i];
|
|
}
|
|
}
|
|
newRegionAttachment(skin, name, path, sequence) {
|
|
let attachment = new RegionAttachment(name, path);
|
|
if (sequence != null) {
|
|
this.loadSequence(name, path, sequence);
|
|
} else {
|
|
let region = this.atlas.findRegion(path);
|
|
if (!region)
|
|
throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")");
|
|
region.renderObject = region;
|
|
attachment.region = region;
|
|
}
|
|
return attachment;
|
|
}
|
|
newMeshAttachment(skin, name, path, sequence) {
|
|
let attachment = new MeshAttachment(name, path);
|
|
if (sequence != null) {
|
|
this.loadSequence(name, path, sequence);
|
|
} else {
|
|
let region = this.atlas.findRegion(path);
|
|
if (!region)
|
|
throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
|
|
region.renderObject = region;
|
|
attachment.region = region;
|
|
}
|
|
return attachment;
|
|
}
|
|
newBoundingBoxAttachment(skin, name) {
|
|
return new BoundingBoxAttachment(name);
|
|
}
|
|
newPathAttachment(skin, name) {
|
|
return new PathAttachment(name);
|
|
}
|
|
newPointAttachment(skin, name) {
|
|
return new PointAttachment(name);
|
|
}
|
|
newClippingAttachment(skin, name) {
|
|
return new ClippingAttachment(name);
|
|
}
|
|
};
|
|
|
|
// spine-core/src/BoneData.ts
|
|
var BoneData = class {
|
|
constructor(index, name, parent) {
|
|
this.index = 0;
|
|
this.parent = null;
|
|
this.length = 0;
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.rotation = 0;
|
|
this.scaleX = 1;
|
|
this.scaleY = 1;
|
|
this.shearX = 0;
|
|
this.shearY = 0;
|
|
this.transformMode = TransformMode.Normal;
|
|
this.skinRequired = false;
|
|
this.color = new Color();
|
|
if (index < 0)
|
|
throw new Error("index must be >= 0.");
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.index = index;
|
|
this.name = name;
|
|
this.parent = parent;
|
|
}
|
|
};
|
|
var TransformMode = /* @__PURE__ */ ((TransformMode2) => {
|
|
TransformMode2[TransformMode2["Normal"] = 0] = "Normal";
|
|
TransformMode2[TransformMode2["OnlyTranslation"] = 1] = "OnlyTranslation";
|
|
TransformMode2[TransformMode2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection";
|
|
TransformMode2[TransformMode2["NoScale"] = 3] = "NoScale";
|
|
TransformMode2[TransformMode2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection";
|
|
return TransformMode2;
|
|
})(TransformMode || {});
|
|
|
|
// spine-core/src/Bone.ts
|
|
var Bone = class {
|
|
constructor(data, skeleton, parent) {
|
|
this.parent = null;
|
|
this.children = new Array();
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.rotation = 0;
|
|
this.scaleX = 0;
|
|
this.scaleY = 0;
|
|
this.shearX = 0;
|
|
this.shearY = 0;
|
|
this.ax = 0;
|
|
this.ay = 0;
|
|
this.arotation = 0;
|
|
this.ascaleX = 0;
|
|
this.ascaleY = 0;
|
|
this.ashearX = 0;
|
|
this.ashearY = 0;
|
|
this.a = 0;
|
|
this.b = 0;
|
|
this.c = 0;
|
|
this.d = 0;
|
|
this.worldY = 0;
|
|
this.worldX = 0;
|
|
this.sorted = false;
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.skeleton = skeleton;
|
|
this.parent = parent;
|
|
this.setToSetupPose();
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
this.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY);
|
|
}
|
|
updateWorldTransform() {
|
|
this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);
|
|
}
|
|
updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY) {
|
|
this.ax = x;
|
|
this.ay = y;
|
|
this.arotation = rotation;
|
|
this.ascaleX = scaleX;
|
|
this.ascaleY = scaleY;
|
|
this.ashearX = shearX;
|
|
this.ashearY = shearY;
|
|
let parent = this.parent;
|
|
if (!parent) {
|
|
let skeleton = this.skeleton;
|
|
let rotationY = rotation + 90 + shearY;
|
|
let sx = skeleton.scaleX;
|
|
let sy = skeleton.scaleY;
|
|
this.a = MathUtils.cosDeg(rotation + shearX) * scaleX * sx;
|
|
this.b = MathUtils.cosDeg(rotationY) * scaleY * sx;
|
|
this.c = MathUtils.sinDeg(rotation + shearX) * scaleX * sy;
|
|
this.d = MathUtils.sinDeg(rotationY) * scaleY * sy;
|
|
this.worldX = x * sx + skeleton.x;
|
|
this.worldY = y * sy + skeleton.y;
|
|
return;
|
|
}
|
|
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
|
this.worldX = pa * x + pb * y + parent.worldX;
|
|
this.worldY = pc * x + pd * y + parent.worldY;
|
|
switch (this.data.transformMode) {
|
|
case 0 /* Normal */: {
|
|
let rotationY = rotation + 90 + shearY;
|
|
let la = MathUtils.cosDeg(rotation + shearX) * scaleX;
|
|
let lb = MathUtils.cosDeg(rotationY) * scaleY;
|
|
let lc = MathUtils.sinDeg(rotation + shearX) * scaleX;
|
|
let ld = MathUtils.sinDeg(rotationY) * scaleY;
|
|
this.a = pa * la + pb * lc;
|
|
this.b = pa * lb + pb * ld;
|
|
this.c = pc * la + pd * lc;
|
|
this.d = pc * lb + pd * ld;
|
|
return;
|
|
}
|
|
case 1 /* OnlyTranslation */: {
|
|
let rotationY = rotation + 90 + shearY;
|
|
this.a = MathUtils.cosDeg(rotation + shearX) * scaleX;
|
|
this.b = MathUtils.cosDeg(rotationY) * scaleY;
|
|
this.c = MathUtils.sinDeg(rotation + shearX) * scaleX;
|
|
this.d = MathUtils.sinDeg(rotationY) * scaleY;
|
|
break;
|
|
}
|
|
case 2 /* NoRotationOrReflection */: {
|
|
let s = pa * pa + pc * pc;
|
|
let prx = 0;
|
|
if (s > 1e-4) {
|
|
s = Math.abs(pa * pd - pb * pc) / s;
|
|
pa /= this.skeleton.scaleX;
|
|
pc /= this.skeleton.scaleY;
|
|
pb = pc * s;
|
|
pd = pa * s;
|
|
prx = Math.atan2(pc, pa) * MathUtils.radDeg;
|
|
} else {
|
|
pa = 0;
|
|
pc = 0;
|
|
prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg;
|
|
}
|
|
let rx = rotation + shearX - prx;
|
|
let ry = rotation + shearY - prx + 90;
|
|
let la = MathUtils.cosDeg(rx) * scaleX;
|
|
let lb = MathUtils.cosDeg(ry) * scaleY;
|
|
let lc = MathUtils.sinDeg(rx) * scaleX;
|
|
let ld = MathUtils.sinDeg(ry) * scaleY;
|
|
this.a = pa * la - pb * lc;
|
|
this.b = pa * lb - pb * ld;
|
|
this.c = pc * la + pd * lc;
|
|
this.d = pc * lb + pd * ld;
|
|
break;
|
|
}
|
|
case 3 /* NoScale */:
|
|
case 4 /* NoScaleOrReflection */: {
|
|
let cos = MathUtils.cosDeg(rotation);
|
|
let sin = MathUtils.sinDeg(rotation);
|
|
let za = (pa * cos + pb * sin) / this.skeleton.scaleX;
|
|
let zc = (pc * cos + pd * sin) / this.skeleton.scaleY;
|
|
let s = Math.sqrt(za * za + zc * zc);
|
|
if (s > 1e-5)
|
|
s = 1 / s;
|
|
za *= s;
|
|
zc *= s;
|
|
s = Math.sqrt(za * za + zc * zc);
|
|
if (this.data.transformMode == 3 /* NoScale */ && pa * pd - pb * pc < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0))
|
|
s = -s;
|
|
let r = Math.PI / 2 + Math.atan2(zc, za);
|
|
let zb = Math.cos(r) * s;
|
|
let zd = Math.sin(r) * s;
|
|
let la = MathUtils.cosDeg(shearX) * scaleX;
|
|
let lb = MathUtils.cosDeg(90 + shearY) * scaleY;
|
|
let lc = MathUtils.sinDeg(shearX) * scaleX;
|
|
let ld = MathUtils.sinDeg(90 + shearY) * scaleY;
|
|
this.a = za * la + zb * lc;
|
|
this.b = za * lb + zb * ld;
|
|
this.c = zc * la + zd * lc;
|
|
this.d = zc * lb + zd * ld;
|
|
break;
|
|
}
|
|
}
|
|
this.a *= this.skeleton.scaleX;
|
|
this.b *= this.skeleton.scaleX;
|
|
this.c *= this.skeleton.scaleY;
|
|
this.d *= this.skeleton.scaleY;
|
|
}
|
|
setToSetupPose() {
|
|
let data = this.data;
|
|
this.x = data.x;
|
|
this.y = data.y;
|
|
this.rotation = data.rotation;
|
|
this.scaleX = data.scaleX;
|
|
this.scaleY = data.scaleY;
|
|
this.shearX = data.shearX;
|
|
this.shearY = data.shearY;
|
|
}
|
|
getWorldRotationX() {
|
|
return Math.atan2(this.c, this.a) * MathUtils.radDeg;
|
|
}
|
|
getWorldRotationY() {
|
|
return Math.atan2(this.d, this.b) * MathUtils.radDeg;
|
|
}
|
|
getWorldScaleX() {
|
|
return Math.sqrt(this.a * this.a + this.c * this.c);
|
|
}
|
|
getWorldScaleY() {
|
|
return Math.sqrt(this.b * this.b + this.d * this.d);
|
|
}
|
|
updateAppliedTransform() {
|
|
let parent = this.parent;
|
|
if (!parent) {
|
|
this.ax = this.worldX - this.skeleton.x;
|
|
this.ay = this.worldY - this.skeleton.y;
|
|
this.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg;
|
|
this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c);
|
|
this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d);
|
|
this.ashearX = 0;
|
|
this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg;
|
|
return;
|
|
}
|
|
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
|
let pid = 1 / (pa * pd - pb * pc);
|
|
let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY;
|
|
this.ax = dx * pd * pid - dy * pb * pid;
|
|
this.ay = dy * pa * pid - dx * pc * pid;
|
|
let ia = pid * pd;
|
|
let id = pid * pa;
|
|
let ib = pid * pb;
|
|
let ic = pid * pc;
|
|
let ra = ia * this.a - ib * this.c;
|
|
let rb = ia * this.b - ib * this.d;
|
|
let rc = id * this.c - ic * this.a;
|
|
let rd = id * this.d - ic * this.b;
|
|
this.ashearX = 0;
|
|
this.ascaleX = Math.sqrt(ra * ra + rc * rc);
|
|
if (this.ascaleX > 1e-4) {
|
|
let det = ra * rd - rb * rc;
|
|
this.ascaleY = det / this.ascaleX;
|
|
this.ashearY = Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;
|
|
this.arotation = Math.atan2(rc, ra) * MathUtils.radDeg;
|
|
} else {
|
|
this.ascaleX = 0;
|
|
this.ascaleY = Math.sqrt(rb * rb + rd * rd);
|
|
this.ashearY = 0;
|
|
this.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;
|
|
}
|
|
}
|
|
worldToLocal(world) {
|
|
let invDet = 1 / (this.a * this.d - this.b * this.c);
|
|
let x = world.x - this.worldX, y = world.y - this.worldY;
|
|
world.x = x * this.d * invDet - y * this.b * invDet;
|
|
world.y = y * this.a * invDet - x * this.c * invDet;
|
|
return world;
|
|
}
|
|
localToWorld(local) {
|
|
let x = local.x, y = local.y;
|
|
local.x = x * this.a + y * this.b + this.worldX;
|
|
local.y = x * this.c + y * this.d + this.worldY;
|
|
return local;
|
|
}
|
|
worldToLocalRotation(worldRotation) {
|
|
let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation);
|
|
return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX;
|
|
}
|
|
localToWorldRotation(localRotation) {
|
|
localRotation -= this.rotation - this.shearX;
|
|
let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation);
|
|
return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg;
|
|
}
|
|
rotateWorld(degrees) {
|
|
let a = this.a, b = this.b, c = this.c, d = this.d;
|
|
let cos = MathUtils.cosDeg(degrees), sin = MathUtils.sinDeg(degrees);
|
|
this.a = cos * a - sin * c;
|
|
this.b = cos * b - sin * d;
|
|
this.c = sin * a + cos * c;
|
|
this.d = sin * b + cos * d;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/ConstraintData.ts
|
|
var ConstraintData = class {
|
|
constructor(name, order, skinRequired) {
|
|
this.name = name;
|
|
this.order = order;
|
|
this.skinRequired = skinRequired;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/AssetManagerBase.ts
|
|
var AssetManagerBase = class {
|
|
constructor(textureLoader, pathPrefix = "", downloader = new Downloader()) {
|
|
this.pathPrefix = "";
|
|
this.assets = {};
|
|
this.errors = {};
|
|
this.toLoad = 0;
|
|
this.loaded = 0;
|
|
this.textureLoader = textureLoader;
|
|
this.pathPrefix = pathPrefix;
|
|
this.downloader = downloader;
|
|
}
|
|
start(path) {
|
|
this.toLoad++;
|
|
return this.pathPrefix + path;
|
|
}
|
|
success(callback, path, asset) {
|
|
this.toLoad--;
|
|
this.loaded++;
|
|
this.assets[path] = asset;
|
|
if (callback)
|
|
callback(path, asset);
|
|
}
|
|
error(callback, path, message) {
|
|
this.toLoad--;
|
|
this.loaded++;
|
|
this.errors[path] = message;
|
|
if (callback)
|
|
callback(path, message);
|
|
}
|
|
loadAll() {
|
|
let promise = new Promise((resolve, reject) => {
|
|
let check = () => {
|
|
if (this.isLoadingComplete()) {
|
|
if (this.hasErrors())
|
|
reject(this.errors);
|
|
else
|
|
resolve(this);
|
|
return;
|
|
}
|
|
requestAnimationFrame(check);
|
|
};
|
|
requestAnimationFrame(check);
|
|
});
|
|
return promise;
|
|
}
|
|
setRawDataURI(path, data) {
|
|
this.downloader.rawDataUris[this.pathPrefix + path] = data;
|
|
}
|
|
loadBinary(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
this.downloader.downloadBinary(path, (data) => {
|
|
this.success(success, path, data);
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
loadText(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
this.downloader.downloadText(path, (data) => {
|
|
this.success(success, path, data);
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
loadJson(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
this.downloader.downloadJson(path, (data) => {
|
|
this.success(success, path, data);
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
loadTexture(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
let isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document);
|
|
let isWebWorker = !isBrowser;
|
|
if (isWebWorker) {
|
|
fetch(path, { mode: "cors" }).then((response) => {
|
|
if (response.ok)
|
|
return response.blob();
|
|
this.error(error, path, `Couldn't load image: ${path}`);
|
|
return null;
|
|
}).then((blob) => {
|
|
return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null;
|
|
}).then((bitmap) => {
|
|
if (bitmap)
|
|
this.success(success, path, this.textureLoader(bitmap));
|
|
});
|
|
} else {
|
|
let image = new Image();
|
|
image.crossOrigin = "anonymous";
|
|
image.onload = () => {
|
|
this.success(success, path, this.textureLoader(image));
|
|
};
|
|
image.onerror = () => {
|
|
this.error(error, path, `Couldn't load image: ${path}`);
|
|
};
|
|
if (this.downloader.rawDataUris[path])
|
|
path = this.downloader.rawDataUris[path];
|
|
image.src = path;
|
|
}
|
|
}
|
|
loadTextureAtlas(path, success = () => {
|
|
}, error = () => {
|
|
}, fileAlias) {
|
|
let index = path.lastIndexOf("/");
|
|
let parent = index >= 0 ? path.substring(0, index + 1) : "";
|
|
path = this.start(path);
|
|
this.downloader.downloadText(path, (atlasText) => {
|
|
try {
|
|
let atlas = new TextureAtlas(atlasText);
|
|
let toLoad = atlas.pages.length, abort = false;
|
|
for (let page of atlas.pages) {
|
|
this.loadTexture(
|
|
!fileAlias ? parent + page.name : fileAlias[page.name],
|
|
(imagePath, texture) => {
|
|
if (!abort) {
|
|
page.setTexture(texture);
|
|
if (--toLoad == 0)
|
|
this.success(success, path, atlas);
|
|
}
|
|
},
|
|
(imagePath, message) => {
|
|
if (!abort)
|
|
this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`);
|
|
abort = true;
|
|
}
|
|
);
|
|
}
|
|
} catch (e) {
|
|
this.error(error, path, `Couldn't parse texture atlas ${path}: ${e.message}`);
|
|
}
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
get(path) {
|
|
return this.assets[this.pathPrefix + path];
|
|
}
|
|
require(path) {
|
|
path = this.pathPrefix + path;
|
|
let asset = this.assets[path];
|
|
if (asset)
|
|
return asset;
|
|
let error = this.errors[path];
|
|
throw Error("Asset not found: " + path + (error ? "\n" + error : ""));
|
|
}
|
|
remove(path) {
|
|
path = this.pathPrefix + path;
|
|
let asset = this.assets[path];
|
|
if (asset.dispose)
|
|
asset.dispose();
|
|
delete this.assets[path];
|
|
return asset;
|
|
}
|
|
removeAll() {
|
|
for (let key in this.assets) {
|
|
let asset = this.assets[key];
|
|
if (asset.dispose)
|
|
asset.dispose();
|
|
}
|
|
this.assets = {};
|
|
}
|
|
isLoadingComplete() {
|
|
return this.toLoad == 0;
|
|
}
|
|
getToLoad() {
|
|
return this.toLoad;
|
|
}
|
|
getLoaded() {
|
|
return this.loaded;
|
|
}
|
|
dispose() {
|
|
this.removeAll();
|
|
}
|
|
hasErrors() {
|
|
return Object.keys(this.errors).length > 0;
|
|
}
|
|
getErrors() {
|
|
return this.errors;
|
|
}
|
|
};
|
|
var Downloader = class {
|
|
constructor() {
|
|
this.callbacks = {};
|
|
this.rawDataUris = {};
|
|
}
|
|
dataUriToString(dataUri) {
|
|
if (!dataUri.startsWith("data:")) {
|
|
throw new Error("Not a data URI.");
|
|
}
|
|
let base64Idx = dataUri.indexOf("base64,");
|
|
if (base64Idx != -1) {
|
|
base64Idx += "base64,".length;
|
|
return atob(dataUri.substr(base64Idx));
|
|
} else {
|
|
return dataUri.substr(dataUri.indexOf(",") + 1);
|
|
}
|
|
}
|
|
base64ToUint8Array(base64) {
|
|
var binary_string = window.atob(base64);
|
|
var len = binary_string.length;
|
|
var bytes = new Uint8Array(len);
|
|
for (var i = 0; i < len; i++) {
|
|
bytes[i] = binary_string.charCodeAt(i);
|
|
}
|
|
return bytes;
|
|
}
|
|
dataUriToUint8Array(dataUri) {
|
|
if (!dataUri.startsWith("data:")) {
|
|
throw new Error("Not a data URI.");
|
|
}
|
|
let base64Idx = dataUri.indexOf("base64,");
|
|
if (base64Idx == -1)
|
|
throw new Error("Not a binary data URI.");
|
|
base64Idx += "base64,".length;
|
|
return this.base64ToUint8Array(dataUri.substr(base64Idx));
|
|
}
|
|
downloadText(url, success, error) {
|
|
if (this.start(url, success, error))
|
|
return;
|
|
if (this.rawDataUris[url]) {
|
|
try {
|
|
let dataUri = this.rawDataUris[url];
|
|
this.finish(url, 200, this.dataUriToString(dataUri));
|
|
} catch (e) {
|
|
this.finish(url, 400, JSON.stringify(e));
|
|
}
|
|
return;
|
|
}
|
|
let request = new XMLHttpRequest();
|
|
request.overrideMimeType("text/html");
|
|
request.open("GET", url, true);
|
|
let done = () => {
|
|
this.finish(url, request.status, request.responseText);
|
|
};
|
|
request.onload = done;
|
|
request.onerror = done;
|
|
request.send();
|
|
}
|
|
downloadJson(url, success, error) {
|
|
this.downloadText(url, (data) => {
|
|
success(JSON.parse(data));
|
|
}, error);
|
|
}
|
|
downloadBinary(url, success, error) {
|
|
if (this.start(url, success, error))
|
|
return;
|
|
if (this.rawDataUris[url]) {
|
|
try {
|
|
let dataUri = this.rawDataUris[url];
|
|
this.finish(url, 200, this.dataUriToUint8Array(dataUri));
|
|
} catch (e) {
|
|
this.finish(url, 400, JSON.stringify(e));
|
|
}
|
|
return;
|
|
}
|
|
let request = new XMLHttpRequest();
|
|
request.open("GET", url, true);
|
|
request.responseType = "arraybuffer";
|
|
let onerror = () => {
|
|
this.finish(url, request.status, request.response);
|
|
};
|
|
request.onload = () => {
|
|
if (request.status == 200 || request.status == 0)
|
|
this.finish(url, 200, new Uint8Array(request.response));
|
|
else
|
|
onerror();
|
|
};
|
|
request.onerror = onerror;
|
|
request.send();
|
|
}
|
|
start(url, success, error) {
|
|
let callbacks = this.callbacks[url];
|
|
try {
|
|
if (callbacks)
|
|
return true;
|
|
this.callbacks[url] = callbacks = [];
|
|
} finally {
|
|
callbacks.push(success, error);
|
|
}
|
|
}
|
|
finish(url, status, data) {
|
|
let callbacks = this.callbacks[url];
|
|
delete this.callbacks[url];
|
|
let args = status == 200 || status == 0 ? [data] : [status, data];
|
|
for (let i = args.length - 1, n = callbacks.length; i < n; i += 2)
|
|
callbacks[i].apply(null, args);
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Event.ts
|
|
var Event = class {
|
|
constructor(time, data) {
|
|
this.intValue = 0;
|
|
this.floatValue = 0;
|
|
this.stringValue = null;
|
|
this.time = 0;
|
|
this.volume = 0;
|
|
this.balance = 0;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
this.time = time;
|
|
this.data = data;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/EventData.ts
|
|
var EventData = class {
|
|
constructor(name) {
|
|
this.intValue = 0;
|
|
this.floatValue = 0;
|
|
this.stringValue = null;
|
|
this.audioPath = null;
|
|
this.volume = 0;
|
|
this.balance = 0;
|
|
this.name = name;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/IkConstraint.ts
|
|
var IkConstraint = class {
|
|
constructor(data, skeleton) {
|
|
this.bendDirection = 0;
|
|
this.compress = false;
|
|
this.stretch = false;
|
|
this.mix = 1;
|
|
this.softness = 0;
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.mix = data.mix;
|
|
this.softness = data.softness;
|
|
this.bendDirection = data.bendDirection;
|
|
this.compress = data.compress;
|
|
this.stretch = data.stretch;
|
|
this.bones = new Array();
|
|
for (let i = 0; i < data.bones.length; i++) {
|
|
let bone = skeleton.findBone(data.bones[i].name);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${data.bones[i].name}`);
|
|
this.bones.push(bone);
|
|
}
|
|
let target = skeleton.findBone(data.target.name);
|
|
if (!target)
|
|
throw new Error(`Couldn't find bone ${data.target.name}`);
|
|
this.target = target;
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
if (this.mix == 0)
|
|
return;
|
|
let target = this.target;
|
|
let bones = this.bones;
|
|
switch (bones.length) {
|
|
case 1:
|
|
this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix);
|
|
break;
|
|
case 2:
|
|
this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix);
|
|
break;
|
|
}
|
|
}
|
|
apply1(bone, targetX, targetY, compress, stretch, uniform, alpha) {
|
|
let p = bone.parent;
|
|
if (!p)
|
|
throw new Error("IK bone must have parent.");
|
|
let pa = p.a, pb = p.b, pc = p.c, pd = p.d;
|
|
let rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0;
|
|
switch (bone.data.transformMode) {
|
|
case 1 /* OnlyTranslation */:
|
|
tx = targetX - bone.worldX;
|
|
ty = targetY - bone.worldY;
|
|
break;
|
|
case 2 /* NoRotationOrReflection */:
|
|
let s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
|
|
let sa = pa / bone.skeleton.scaleX;
|
|
let sc = pc / bone.skeleton.scaleY;
|
|
pb = -sc * s * bone.skeleton.scaleX;
|
|
pd = sa * s * bone.skeleton.scaleY;
|
|
rotationIK += Math.atan2(sc, sa) * MathUtils.radDeg;
|
|
default:
|
|
let x = targetX - p.worldX, y = targetY - p.worldY;
|
|
let d = pa * pd - pb * pc;
|
|
tx = (x * pd - y * pb) / d - bone.ax;
|
|
ty = (y * pa - x * pc) / d - bone.ay;
|
|
}
|
|
rotationIK += Math.atan2(ty, tx) * MathUtils.radDeg;
|
|
if (bone.ascaleX < 0)
|
|
rotationIK += 180;
|
|
if (rotationIK > 180)
|
|
rotationIK -= 360;
|
|
else if (rotationIK < -180)
|
|
rotationIK += 360;
|
|
let sx = bone.ascaleX, sy = bone.ascaleY;
|
|
if (compress || stretch) {
|
|
switch (bone.data.transformMode) {
|
|
case 3 /* NoScale */:
|
|
case 4 /* NoScaleOrReflection */:
|
|
tx = targetX - bone.worldX;
|
|
ty = targetY - bone.worldY;
|
|
}
|
|
let b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty);
|
|
if (compress && dd < b || stretch && dd > b && b > 1e-4) {
|
|
let s = (dd / b - 1) * alpha + 1;
|
|
sx *= s;
|
|
if (uniform)
|
|
sy *= s;
|
|
}
|
|
}
|
|
bone.updateWorldTransformWith(
|
|
bone.ax,
|
|
bone.ay,
|
|
bone.arotation + rotationIK * alpha,
|
|
sx,
|
|
sy,
|
|
bone.ashearX,
|
|
bone.ashearY
|
|
);
|
|
}
|
|
apply2(parent, child, targetX, targetY, bendDir, stretch, uniform, softness, alpha) {
|
|
let px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX;
|
|
let os1 = 0, os2 = 0, s2 = 0;
|
|
if (psx < 0) {
|
|
psx = -psx;
|
|
os1 = 180;
|
|
s2 = -1;
|
|
} else {
|
|
os1 = 0;
|
|
s2 = 1;
|
|
}
|
|
if (psy < 0) {
|
|
psy = -psy;
|
|
s2 = -s2;
|
|
}
|
|
if (csx < 0) {
|
|
csx = -csx;
|
|
os2 = 180;
|
|
} else
|
|
os2 = 0;
|
|
let cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d;
|
|
let u = Math.abs(psx - psy) <= 1e-4;
|
|
if (!u || stretch) {
|
|
cy = 0;
|
|
cwx = a * cx + parent.worldX;
|
|
cwy = c * cx + parent.worldY;
|
|
} else {
|
|
cy = child.ay;
|
|
cwx = a * cx + b * cy + parent.worldX;
|
|
cwy = c * cx + d * cy + parent.worldY;
|
|
}
|
|
let pp = parent.parent;
|
|
if (!pp)
|
|
throw new Error("IK parent must itself have a parent.");
|
|
a = pp.a;
|
|
b = pp.b;
|
|
c = pp.c;
|
|
d = pp.d;
|
|
let id = 1 / (a * d - b * c), x = cwx - pp.worldX, y = cwy - pp.worldY;
|
|
let dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;
|
|
let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
|
|
if (l1 < 1e-4) {
|
|
this.apply1(parent, targetX, targetY, false, stretch, false, alpha);
|
|
child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
|
|
return;
|
|
}
|
|
x = targetX - pp.worldX;
|
|
y = targetY - pp.worldY;
|
|
let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;
|
|
let dd = tx * tx + ty * ty;
|
|
if (softness != 0) {
|
|
softness *= psx * (csx + 1) * 0.5;
|
|
let td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness;
|
|
if (sd > 0) {
|
|
let p = Math.min(1, sd / (softness * 2)) - 1;
|
|
p = (sd - softness * (1 - p * p)) / td;
|
|
tx -= p * tx;
|
|
ty -= p * ty;
|
|
dd = tx * tx + ty * ty;
|
|
}
|
|
}
|
|
outer:
|
|
if (u) {
|
|
l2 *= psx;
|
|
let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
|
if (cos < -1) {
|
|
cos = -1;
|
|
a2 = Math.PI * bendDir;
|
|
} else if (cos > 1) {
|
|
cos = 1;
|
|
a2 = 0;
|
|
if (stretch) {
|
|
a = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;
|
|
sx *= a;
|
|
if (uniform)
|
|
sy *= a;
|
|
}
|
|
} else
|
|
a2 = Math.acos(cos) * bendDir;
|
|
a = l1 + l2 * cos;
|
|
b = l2 * Math.sin(a2);
|
|
a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b);
|
|
} else {
|
|
a = psx * l2;
|
|
b = psy * l2;
|
|
let aa = a * a, bb = b * b, ta = Math.atan2(ty, tx);
|
|
c = bb * l1 * l1 + aa * dd - aa * bb;
|
|
let c1 = -2 * bb * l1, c2 = bb - aa;
|
|
d = c1 * c1 - 4 * c2 * c;
|
|
if (d >= 0) {
|
|
let q = Math.sqrt(d);
|
|
if (c1 < 0)
|
|
q = -q;
|
|
q = -(c1 + q) * 0.5;
|
|
let r0 = q / c2, r1 = c / q;
|
|
let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
|
|
if (r * r <= dd) {
|
|
y = Math.sqrt(dd - r * r) * bendDir;
|
|
a1 = ta - Math.atan2(y, r);
|
|
a2 = Math.atan2(y / psy, (r - l1) / psx);
|
|
break outer;
|
|
}
|
|
}
|
|
let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0;
|
|
let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;
|
|
c = -a * l1 / (aa - bb);
|
|
if (c >= -1 && c <= 1) {
|
|
c = Math.acos(c);
|
|
x = a * Math.cos(c) + l1;
|
|
y = b * Math.sin(c);
|
|
d = x * x + y * y;
|
|
if (d < minDist) {
|
|
minAngle = c;
|
|
minDist = d;
|
|
minX = x;
|
|
minY = y;
|
|
}
|
|
if (d > maxDist) {
|
|
maxAngle = c;
|
|
maxDist = d;
|
|
maxX = x;
|
|
maxY = y;
|
|
}
|
|
}
|
|
if (dd <= (minDist + maxDist) * 0.5) {
|
|
a1 = ta - Math.atan2(minY * bendDir, minX);
|
|
a2 = minAngle * bendDir;
|
|
} else {
|
|
a1 = ta - Math.atan2(maxY * bendDir, maxX);
|
|
a2 = maxAngle * bendDir;
|
|
}
|
|
}
|
|
let os = Math.atan2(cy, cx) * s2;
|
|
let rotation = parent.arotation;
|
|
a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation;
|
|
if (a1 > 180)
|
|
a1 -= 360;
|
|
else if (a1 < -180)
|
|
a1 += 360;
|
|
parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0);
|
|
rotation = child.arotation;
|
|
a2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation;
|
|
if (a2 > 180)
|
|
a2 -= 360;
|
|
else if (a2 < -180)
|
|
a2 += 360;
|
|
child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
|
|
}
|
|
};
|
|
|
|
// spine-core/src/IkConstraintData.ts
|
|
var IkConstraintData = class extends ConstraintData {
|
|
constructor(name) {
|
|
super(name, 0, false);
|
|
this.bones = new Array();
|
|
this._target = null;
|
|
this.bendDirection = 1;
|
|
this.compress = false;
|
|
this.stretch = false;
|
|
this.uniform = false;
|
|
this.mix = 1;
|
|
this.softness = 0;
|
|
}
|
|
set target(boneData) {
|
|
this._target = boneData;
|
|
}
|
|
get target() {
|
|
if (!this._target)
|
|
throw new Error("BoneData not set.");
|
|
else
|
|
return this._target;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/PathConstraintData.ts
|
|
var PathConstraintData = class extends ConstraintData {
|
|
constructor(name) {
|
|
super(name, 0, false);
|
|
this.bones = new Array();
|
|
this._target = null;
|
|
this.positionMode = PositionMode.Fixed;
|
|
this.spacingMode = SpacingMode.Fixed;
|
|
this.rotateMode = RotateMode.Chain;
|
|
this.offsetRotation = 0;
|
|
this.position = 0;
|
|
this.spacing = 0;
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
}
|
|
set target(slotData) {
|
|
this._target = slotData;
|
|
}
|
|
get target() {
|
|
if (!this._target)
|
|
throw new Error("SlotData not set.");
|
|
else
|
|
return this._target;
|
|
}
|
|
};
|
|
var PositionMode = /* @__PURE__ */ ((PositionMode2) => {
|
|
PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed";
|
|
PositionMode2[PositionMode2["Percent"] = 1] = "Percent";
|
|
return PositionMode2;
|
|
})(PositionMode || {});
|
|
var SpacingMode = /* @__PURE__ */ ((SpacingMode2) => {
|
|
SpacingMode2[SpacingMode2["Length"] = 0] = "Length";
|
|
SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed";
|
|
SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent";
|
|
SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional";
|
|
return SpacingMode2;
|
|
})(SpacingMode || {});
|
|
var RotateMode = /* @__PURE__ */ ((RotateMode2) => {
|
|
RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent";
|
|
RotateMode2[RotateMode2["Chain"] = 1] = "Chain";
|
|
RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale";
|
|
return RotateMode2;
|
|
})(RotateMode || {});
|
|
|
|
// spine-core/src/PathConstraint.ts
|
|
var _PathConstraint = class {
|
|
constructor(data, skeleton) {
|
|
this.position = 0;
|
|
this.spacing = 0;
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
this.spaces = new Array();
|
|
this.positions = new Array();
|
|
this.world = new Array();
|
|
this.curves = new Array();
|
|
this.lengths = new Array();
|
|
this.segments = new Array();
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.bones = new Array();
|
|
for (let i = 0, n = data.bones.length; i < n; i++) {
|
|
let bone = skeleton.findBone(data.bones[i].name);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${data.bones[i].name}.`);
|
|
this.bones.push(bone);
|
|
}
|
|
let target = skeleton.findSlot(data.target.name);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${data.target.name}`);
|
|
this.target = target;
|
|
this.position = data.position;
|
|
this.spacing = data.spacing;
|
|
this.mixRotate = data.mixRotate;
|
|
this.mixX = data.mixX;
|
|
this.mixY = data.mixY;
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
let attachment = this.target.getAttachment();
|
|
if (!(attachment instanceof PathAttachment))
|
|
return;
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;
|
|
if (mixRotate == 0 && mixX == 0 && mixY == 0)
|
|
return;
|
|
let data = this.data;
|
|
let tangents = data.rotateMode == 0 /* Tangent */, scale = data.rotateMode == 2 /* ChainScale */;
|
|
let bones = this.bones;
|
|
let boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1;
|
|
let spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : [];
|
|
let spacing = this.spacing;
|
|
switch (data.spacingMode) {
|
|
case 2 /* Percent */:
|
|
if (scale) {
|
|
for (let i = 0, n = spacesCount - 1; i < n; i++) {
|
|
let bone = bones[i];
|
|
let setupLength = bone.data.length;
|
|
if (setupLength < _PathConstraint.epsilon)
|
|
lengths[i] = 0;
|
|
else {
|
|
let x = setupLength * bone.a, y = setupLength * bone.c;
|
|
lengths[i] = Math.sqrt(x * x + y * y);
|
|
}
|
|
}
|
|
}
|
|
Utils.arrayFill(spaces, 1, spacesCount, spacing);
|
|
break;
|
|
case 3 /* Proportional */:
|
|
let sum = 0;
|
|
for (let i = 0, n = spacesCount - 1; i < n; ) {
|
|
let bone = bones[i];
|
|
let setupLength = bone.data.length;
|
|
if (setupLength < _PathConstraint.epsilon) {
|
|
if (scale)
|
|
lengths[i] = 0;
|
|
spaces[++i] = spacing;
|
|
} else {
|
|
let x = setupLength * bone.a, y = setupLength * bone.c;
|
|
let length = Math.sqrt(x * x + y * y);
|
|
if (scale)
|
|
lengths[i] = length;
|
|
spaces[++i] = length;
|
|
sum += length;
|
|
}
|
|
}
|
|
if (sum > 0) {
|
|
sum = spacesCount / sum * spacing;
|
|
for (let i = 1; i < spacesCount; i++)
|
|
spaces[i] *= sum;
|
|
}
|
|
break;
|
|
default:
|
|
let lengthSpacing = data.spacingMode == 0 /* Length */;
|
|
for (let i = 0, n = spacesCount - 1; i < n; ) {
|
|
let bone = bones[i];
|
|
let setupLength = bone.data.length;
|
|
if (setupLength < _PathConstraint.epsilon) {
|
|
if (scale)
|
|
lengths[i] = 0;
|
|
spaces[++i] = spacing;
|
|
} else {
|
|
let x = setupLength * bone.a, y = setupLength * bone.c;
|
|
let length = Math.sqrt(x * x + y * y);
|
|
if (scale)
|
|
lengths[i] = length;
|
|
spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
|
|
}
|
|
}
|
|
}
|
|
let positions = this.computeWorldPositions(attachment, spacesCount, tangents);
|
|
let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;
|
|
let tip = false;
|
|
if (offsetRotation == 0)
|
|
tip = data.rotateMode == 1 /* Chain */;
|
|
else {
|
|
tip = false;
|
|
let p = this.target.bone;
|
|
offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad;
|
|
}
|
|
for (let i = 0, p = 3; i < boneCount; i++, p += 3) {
|
|
let bone = bones[i];
|
|
bone.worldX += (boneX - bone.worldX) * mixX;
|
|
bone.worldY += (boneY - bone.worldY) * mixY;
|
|
let x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
|
|
if (scale) {
|
|
let length = lengths[i];
|
|
if (length != 0) {
|
|
let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;
|
|
bone.a *= s;
|
|
bone.c *= s;
|
|
}
|
|
}
|
|
boneX = x;
|
|
boneY = y;
|
|
if (mixRotate > 0) {
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0;
|
|
if (tangents)
|
|
r = positions[p - 1];
|
|
else if (spaces[i + 1] == 0)
|
|
r = positions[p + 2];
|
|
else
|
|
r = Math.atan2(dy, dx);
|
|
r -= Math.atan2(c, a);
|
|
if (tip) {
|
|
cos = Math.cos(r);
|
|
sin = Math.sin(r);
|
|
let length = bone.data.length;
|
|
boneX += (length * (cos * a - sin * c) - dx) * mixRotate;
|
|
boneY += (length * (sin * a + cos * c) - dy) * mixRotate;
|
|
} else {
|
|
r += offsetRotation;
|
|
}
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r *= mixRotate;
|
|
cos = Math.cos(r);
|
|
sin = Math.sin(r);
|
|
bone.a = cos * a - sin * c;
|
|
bone.b = cos * b - sin * d;
|
|
bone.c = sin * a + cos * c;
|
|
bone.d = sin * b + cos * d;
|
|
}
|
|
bone.updateAppliedTransform();
|
|
}
|
|
}
|
|
computeWorldPositions(path, spacesCount, tangents) {
|
|
let target = this.target;
|
|
let position = this.position;
|
|
let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = this.world;
|
|
let closed2 = path.closed;
|
|
let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE;
|
|
if (!path.constantSpeed) {
|
|
let lengths = path.lengths;
|
|
curveCount -= closed2 ? 1 : 2;
|
|
let pathLength2 = lengths[curveCount];
|
|
if (this.data.positionMode == 1 /* Percent */)
|
|
position *= pathLength2;
|
|
let multiplier2;
|
|
switch (this.data.spacingMode) {
|
|
case 2 /* Percent */:
|
|
multiplier2 = pathLength2;
|
|
break;
|
|
case 3 /* Proportional */:
|
|
multiplier2 = pathLength2 / spacesCount;
|
|
break;
|
|
default:
|
|
multiplier2 = 1;
|
|
}
|
|
world = Utils.setArraySize(this.world, 8);
|
|
for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
|
|
let space = spaces[i] * multiplier2;
|
|
position += space;
|
|
let p = position;
|
|
if (closed2) {
|
|
p %= pathLength2;
|
|
if (p < 0)
|
|
p += pathLength2;
|
|
curve = 0;
|
|
} else if (p < 0) {
|
|
if (prevCurve != _PathConstraint.BEFORE) {
|
|
prevCurve = _PathConstraint.BEFORE;
|
|
path.computeWorldVertices(target, 2, 4, world, 0, 2);
|
|
}
|
|
this.addBeforePosition(p, world, 0, out, o);
|
|
continue;
|
|
} else if (p > pathLength2) {
|
|
if (prevCurve != _PathConstraint.AFTER) {
|
|
prevCurve = _PathConstraint.AFTER;
|
|
path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);
|
|
}
|
|
this.addAfterPosition(p - pathLength2, world, 0, out, o);
|
|
continue;
|
|
}
|
|
for (; ; curve++) {
|
|
let length = lengths[curve];
|
|
if (p > length)
|
|
continue;
|
|
if (curve == 0)
|
|
p /= length;
|
|
else {
|
|
let prev = lengths[curve - 1];
|
|
p = (p - prev) / (length - prev);
|
|
}
|
|
break;
|
|
}
|
|
if (curve != prevCurve) {
|
|
prevCurve = curve;
|
|
if (closed2 && curve == curveCount) {
|
|
path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);
|
|
path.computeWorldVertices(target, 0, 4, world, 4, 2);
|
|
} else
|
|
path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);
|
|
}
|
|
this.addCurvePosition(
|
|
p,
|
|
world[0],
|
|
world[1],
|
|
world[2],
|
|
world[3],
|
|
world[4],
|
|
world[5],
|
|
world[6],
|
|
world[7],
|
|
out,
|
|
o,
|
|
tangents || i > 0 && space == 0
|
|
);
|
|
}
|
|
return out;
|
|
}
|
|
if (closed2) {
|
|
verticesLength += 2;
|
|
world = Utils.setArraySize(this.world, verticesLength);
|
|
path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);
|
|
path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);
|
|
world[verticesLength - 2] = world[0];
|
|
world[verticesLength - 1] = world[1];
|
|
} else {
|
|
curveCount--;
|
|
verticesLength -= 4;
|
|
world = Utils.setArraySize(this.world, verticesLength);
|
|
path.computeWorldVertices(target, 2, verticesLength, world, 0, 2);
|
|
}
|
|
let curves = Utils.setArraySize(this.curves, curveCount);
|
|
let pathLength = 0;
|
|
let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
|
|
let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0;
|
|
for (let i = 0, w = 2; i < curveCount; i++, w += 6) {
|
|
cx1 = world[w];
|
|
cy1 = world[w + 1];
|
|
cx2 = world[w + 2];
|
|
cy2 = world[w + 3];
|
|
x2 = world[w + 4];
|
|
y2 = world[w + 5];
|
|
tmpx = (x1 - cx1 * 2 + cx2) * 0.1875;
|
|
tmpy = (y1 - cy1 * 2 + cy2) * 0.1875;
|
|
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;
|
|
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;
|
|
ddfx = tmpx * 2 + dddfx;
|
|
ddfy = tmpy * 2 + dddfy;
|
|
dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;
|
|
dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
ddfx += dddfx;
|
|
ddfy += dddfy;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
dfx += ddfx + dddfx;
|
|
dfy += ddfy + dddfy;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
curves[i] = pathLength;
|
|
x1 = x2;
|
|
y1 = y2;
|
|
}
|
|
if (this.data.positionMode == 1 /* Percent */)
|
|
position *= pathLength;
|
|
let multiplier;
|
|
switch (this.data.spacingMode) {
|
|
case 2 /* Percent */:
|
|
multiplier = pathLength;
|
|
break;
|
|
case 3 /* Proportional */:
|
|
multiplier = pathLength / spacesCount;
|
|
break;
|
|
default:
|
|
multiplier = 1;
|
|
}
|
|
let segments = this.segments;
|
|
let curveLength = 0;
|
|
for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
|
|
let space = spaces[i] * multiplier;
|
|
position += space;
|
|
let p = position;
|
|
if (closed2) {
|
|
p %= pathLength;
|
|
if (p < 0)
|
|
p += pathLength;
|
|
curve = 0;
|
|
} else if (p < 0) {
|
|
this.addBeforePosition(p, world, 0, out, o);
|
|
continue;
|
|
} else if (p > pathLength) {
|
|
this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
|
|
continue;
|
|
}
|
|
for (; ; curve++) {
|
|
let length = curves[curve];
|
|
if (p > length)
|
|
continue;
|
|
if (curve == 0)
|
|
p /= length;
|
|
else {
|
|
let prev = curves[curve - 1];
|
|
p = (p - prev) / (length - prev);
|
|
}
|
|
break;
|
|
}
|
|
if (curve != prevCurve) {
|
|
prevCurve = curve;
|
|
let ii = curve * 6;
|
|
x1 = world[ii];
|
|
y1 = world[ii + 1];
|
|
cx1 = world[ii + 2];
|
|
cy1 = world[ii + 3];
|
|
cx2 = world[ii + 4];
|
|
cy2 = world[ii + 5];
|
|
x2 = world[ii + 6];
|
|
y2 = world[ii + 7];
|
|
tmpx = (x1 - cx1 * 2 + cx2) * 0.03;
|
|
tmpy = (y1 - cy1 * 2 + cy2) * 0.03;
|
|
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3;
|
|
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3;
|
|
ddfx = tmpx * 2 + dddfx;
|
|
ddfy = tmpy * 2 + dddfy;
|
|
dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;
|
|
dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;
|
|
curveLength = Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[0] = curveLength;
|
|
for (ii = 1; ii < 8; ii++) {
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
ddfx += dddfx;
|
|
ddfy += dddfy;
|
|
curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[ii] = curveLength;
|
|
}
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[8] = curveLength;
|
|
dfx += ddfx + dddfx;
|
|
dfy += ddfy + dddfy;
|
|
curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[9] = curveLength;
|
|
segment = 0;
|
|
}
|
|
p *= curveLength;
|
|
for (; ; segment++) {
|
|
let length = segments[segment];
|
|
if (p > length)
|
|
continue;
|
|
if (segment == 0)
|
|
p /= length;
|
|
else {
|
|
let prev = segments[segment - 1];
|
|
p = segment + (p - prev) / (length - prev);
|
|
}
|
|
break;
|
|
}
|
|
this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space == 0);
|
|
}
|
|
return out;
|
|
}
|
|
addBeforePosition(p, temp, i, out, o) {
|
|
let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx);
|
|
out[o] = x1 + p * Math.cos(r);
|
|
out[o + 1] = y1 + p * Math.sin(r);
|
|
out[o + 2] = r;
|
|
}
|
|
addAfterPosition(p, temp, i, out, o) {
|
|
let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx);
|
|
out[o] = x1 + p * Math.cos(r);
|
|
out[o + 1] = y1 + p * Math.sin(r);
|
|
out[o + 2] = r;
|
|
}
|
|
addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) {
|
|
if (p == 0 || isNaN(p)) {
|
|
out[o] = x1;
|
|
out[o + 1] = y1;
|
|
out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);
|
|
return;
|
|
}
|
|
let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u;
|
|
let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p;
|
|
let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;
|
|
out[o] = x;
|
|
out[o + 1] = y;
|
|
if (tangents) {
|
|
if (p < 1e-3)
|
|
out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);
|
|
else
|
|
out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
|
|
}
|
|
}
|
|
};
|
|
var PathConstraint = _PathConstraint;
|
|
PathConstraint.NONE = -1;
|
|
PathConstraint.BEFORE = -2;
|
|
PathConstraint.AFTER = -3;
|
|
PathConstraint.epsilon = 1e-5;
|
|
|
|
// spine-core/src/Slot.ts
|
|
var Slot = class {
|
|
constructor(data, bone) {
|
|
this.darkColor = null;
|
|
this.attachment = null;
|
|
this.attachmentState = 0;
|
|
this.sequenceIndex = -1;
|
|
this.deform = new Array();
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!bone)
|
|
throw new Error("bone cannot be null.");
|
|
this.data = data;
|
|
this.bone = bone;
|
|
this.color = new Color();
|
|
this.darkColor = !data.darkColor ? null : new Color();
|
|
this.setToSetupPose();
|
|
}
|
|
getSkeleton() {
|
|
return this.bone.skeleton;
|
|
}
|
|
getAttachment() {
|
|
return this.attachment;
|
|
}
|
|
setAttachment(attachment) {
|
|
if (this.attachment == attachment)
|
|
return;
|
|
if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.timelineAttachment != this.attachment.timelineAttachment) {
|
|
this.deform.length = 0;
|
|
}
|
|
this.attachment = attachment;
|
|
this.sequenceIndex = -1;
|
|
}
|
|
setToSetupPose() {
|
|
this.color.setFromColor(this.data.color);
|
|
if (this.darkColor)
|
|
this.darkColor.setFromColor(this.data.darkColor);
|
|
if (!this.data.attachmentName)
|
|
this.attachment = null;
|
|
else {
|
|
this.attachment = null;
|
|
this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName));
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/TransformConstraint.ts
|
|
var TransformConstraint = class {
|
|
constructor(data, skeleton) {
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
this.mixScaleX = 0;
|
|
this.mixScaleY = 0;
|
|
this.mixShearY = 0;
|
|
this.temp = new Vector2();
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.mixRotate = data.mixRotate;
|
|
this.mixX = data.mixX;
|
|
this.mixY = data.mixY;
|
|
this.mixScaleX = data.mixScaleX;
|
|
this.mixScaleY = data.mixScaleY;
|
|
this.mixShearY = data.mixShearY;
|
|
this.bones = new Array();
|
|
for (let i = 0; i < data.bones.length; i++) {
|
|
let bone = skeleton.findBone(data.bones[i].name);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${data.bones[i].name}.`);
|
|
this.bones.push(bone);
|
|
}
|
|
let target = skeleton.findBone(data.target.name);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${data.target.name}.`);
|
|
this.target = target;
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0)
|
|
return;
|
|
if (this.data.local) {
|
|
if (this.data.relative)
|
|
this.applyRelativeLocal();
|
|
else
|
|
this.applyAbsoluteLocal();
|
|
} else {
|
|
if (this.data.relative)
|
|
this.applyRelativeWorld();
|
|
else
|
|
this.applyAbsoluteWorld();
|
|
}
|
|
}
|
|
applyAbsoluteWorld() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let translate = mixX != 0 || mixY != 0;
|
|
let target = this.target;
|
|
let ta = target.a, tb = target.b, tc = target.c, td = target.d;
|
|
let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;
|
|
let offsetRotation = this.data.offsetRotation * degRadReflect;
|
|
let offsetShearY = this.data.offsetShearY * degRadReflect;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (mixRotate != 0) {
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
let r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation;
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r *= mixRotate;
|
|
let cos = Math.cos(r), sin = Math.sin(r);
|
|
bone.a = cos * a - sin * c;
|
|
bone.b = cos * b - sin * d;
|
|
bone.c = sin * a + cos * c;
|
|
bone.d = sin * b + cos * d;
|
|
}
|
|
if (translate) {
|
|
let temp = this.temp;
|
|
target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));
|
|
bone.worldX += (temp.x - bone.worldX) * mixX;
|
|
bone.worldY += (temp.y - bone.worldY) * mixY;
|
|
}
|
|
if (mixScaleX != 0) {
|
|
let s = Math.sqrt(bone.a * bone.a + bone.c * bone.c);
|
|
if (s != 0)
|
|
s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s;
|
|
bone.a *= s;
|
|
bone.c *= s;
|
|
}
|
|
if (mixScaleY != 0) {
|
|
let s = Math.sqrt(bone.b * bone.b + bone.d * bone.d);
|
|
if (s != 0)
|
|
s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s;
|
|
bone.b *= s;
|
|
bone.d *= s;
|
|
}
|
|
if (mixShearY > 0) {
|
|
let b = bone.b, d = bone.d;
|
|
let by = Math.atan2(d, b);
|
|
let r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a));
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r = by + (r + offsetShearY) * mixShearY;
|
|
let s = Math.sqrt(b * b + d * d);
|
|
bone.b = Math.cos(r) * s;
|
|
bone.d = Math.sin(r) * s;
|
|
}
|
|
bone.updateAppliedTransform();
|
|
}
|
|
}
|
|
applyRelativeWorld() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let translate = mixX != 0 || mixY != 0;
|
|
let target = this.target;
|
|
let ta = target.a, tb = target.b, tc = target.c, td = target.d;
|
|
let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;
|
|
let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (mixRotate != 0) {
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
let r = Math.atan2(tc, ta) + offsetRotation;
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r *= mixRotate;
|
|
let cos = Math.cos(r), sin = Math.sin(r);
|
|
bone.a = cos * a - sin * c;
|
|
bone.b = cos * b - sin * d;
|
|
bone.c = sin * a + cos * c;
|
|
bone.d = sin * b + cos * d;
|
|
}
|
|
if (translate) {
|
|
let temp = this.temp;
|
|
target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));
|
|
bone.worldX += temp.x * mixX;
|
|
bone.worldY += temp.y * mixY;
|
|
}
|
|
if (mixScaleX != 0) {
|
|
let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1;
|
|
bone.a *= s;
|
|
bone.c *= s;
|
|
}
|
|
if (mixScaleY != 0) {
|
|
let s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1;
|
|
bone.b *= s;
|
|
bone.d *= s;
|
|
}
|
|
if (mixShearY > 0) {
|
|
let r = Math.atan2(td, tb) - Math.atan2(tc, ta);
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
let b = bone.b, d = bone.d;
|
|
r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY;
|
|
let s = Math.sqrt(b * b + d * d);
|
|
bone.b = Math.cos(r) * s;
|
|
bone.d = Math.sin(r) * s;
|
|
}
|
|
bone.updateAppliedTransform();
|
|
}
|
|
}
|
|
applyAbsoluteLocal() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let target = this.target;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
let rotation = bone.arotation;
|
|
if (mixRotate != 0) {
|
|
let r = target.arotation - rotation + this.data.offsetRotation;
|
|
r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360;
|
|
rotation += r * mixRotate;
|
|
}
|
|
let x = bone.ax, y = bone.ay;
|
|
x += (target.ax - x + this.data.offsetX) * mixX;
|
|
y += (target.ay - y + this.data.offsetY) * mixY;
|
|
let scaleX = bone.ascaleX, scaleY = bone.ascaleY;
|
|
if (mixScaleX != 0 && scaleX != 0)
|
|
scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX;
|
|
if (mixScaleY != 0 && scaleY != 0)
|
|
scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY;
|
|
let shearY = bone.ashearY;
|
|
if (mixShearY != 0) {
|
|
let r = target.ashearY - shearY + this.data.offsetShearY;
|
|
r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360;
|
|
shearY += r * mixShearY;
|
|
}
|
|
bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
|
}
|
|
}
|
|
applyRelativeLocal() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let target = this.target;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
let rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate;
|
|
let x = bone.ax + (target.ax + this.data.offsetX) * mixX;
|
|
let y = bone.ay + (target.ay + this.data.offsetY) * mixY;
|
|
let scaleX = bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX + 1);
|
|
let scaleY = bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY + 1);
|
|
let shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY;
|
|
bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Skeleton.ts
|
|
var _Skeleton = class {
|
|
constructor(data) {
|
|
this._updateCache = new Array();
|
|
this.skin = null;
|
|
this.scaleX = 1;
|
|
this._scaleY = 1;
|
|
this.x = 0;
|
|
this.y = 0;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
this.data = data;
|
|
this.bones = new Array();
|
|
for (let i = 0; i < data.bones.length; i++) {
|
|
let boneData = data.bones[i];
|
|
let bone;
|
|
if (!boneData.parent)
|
|
bone = new Bone(boneData, this, null);
|
|
else {
|
|
let parent = this.bones[boneData.parent.index];
|
|
bone = new Bone(boneData, this, parent);
|
|
parent.children.push(bone);
|
|
}
|
|
this.bones.push(bone);
|
|
}
|
|
this.slots = new Array();
|
|
this.drawOrder = new Array();
|
|
for (let i = 0; i < data.slots.length; i++) {
|
|
let slotData = data.slots[i];
|
|
let bone = this.bones[slotData.boneData.index];
|
|
let slot = new Slot(slotData, bone);
|
|
this.slots.push(slot);
|
|
this.drawOrder.push(slot);
|
|
}
|
|
this.ikConstraints = new Array();
|
|
for (let i = 0; i < data.ikConstraints.length; i++) {
|
|
let ikConstraintData = data.ikConstraints[i];
|
|
this.ikConstraints.push(new IkConstraint(ikConstraintData, this));
|
|
}
|
|
this.transformConstraints = new Array();
|
|
for (let i = 0; i < data.transformConstraints.length; i++) {
|
|
let transformConstraintData = data.transformConstraints[i];
|
|
this.transformConstraints.push(new TransformConstraint(transformConstraintData, this));
|
|
}
|
|
this.pathConstraints = new Array();
|
|
for (let i = 0; i < data.pathConstraints.length; i++) {
|
|
let pathConstraintData = data.pathConstraints[i];
|
|
this.pathConstraints.push(new PathConstraint(pathConstraintData, this));
|
|
}
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.updateCache();
|
|
}
|
|
get scaleY() {
|
|
return _Skeleton.yDown ? -this._scaleY : this._scaleY;
|
|
}
|
|
set scaleY(scaleY) {
|
|
this._scaleY = scaleY;
|
|
}
|
|
updateCache() {
|
|
let updateCache = this._updateCache;
|
|
updateCache.length = 0;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
bone.sorted = bone.data.skinRequired;
|
|
bone.active = !bone.sorted;
|
|
}
|
|
if (this.skin) {
|
|
let skinBones = this.skin.bones;
|
|
for (let i = 0, n = this.skin.bones.length; i < n; i++) {
|
|
let bone = this.bones[skinBones[i].index];
|
|
do {
|
|
bone.sorted = false;
|
|
bone.active = true;
|
|
bone = bone.parent;
|
|
} while (bone);
|
|
}
|
|
}
|
|
let ikConstraints = this.ikConstraints;
|
|
let transformConstraints = this.transformConstraints;
|
|
let pathConstraints = this.pathConstraints;
|
|
let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length;
|
|
let constraintCount = ikCount + transformCount + pathCount;
|
|
outer:
|
|
for (let i = 0; i < constraintCount; i++) {
|
|
for (let ii = 0; ii < ikCount; ii++) {
|
|
let constraint = ikConstraints[ii];
|
|
if (constraint.data.order == i) {
|
|
this.sortIkConstraint(constraint);
|
|
continue outer;
|
|
}
|
|
}
|
|
for (let ii = 0; ii < transformCount; ii++) {
|
|
let constraint = transformConstraints[ii];
|
|
if (constraint.data.order == i) {
|
|
this.sortTransformConstraint(constraint);
|
|
continue outer;
|
|
}
|
|
}
|
|
for (let ii = 0; ii < pathCount; ii++) {
|
|
let constraint = pathConstraints[ii];
|
|
if (constraint.data.order == i) {
|
|
this.sortPathConstraint(constraint);
|
|
continue outer;
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = bones.length; i < n; i++)
|
|
this.sortBone(bones[i]);
|
|
}
|
|
sortIkConstraint(constraint) {
|
|
constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true));
|
|
if (!constraint.active)
|
|
return;
|
|
let target = constraint.target;
|
|
this.sortBone(target);
|
|
let constrained = constraint.bones;
|
|
let parent = constrained[0];
|
|
this.sortBone(parent);
|
|
if (constrained.length == 1) {
|
|
this._updateCache.push(constraint);
|
|
this.sortReset(parent.children);
|
|
} else {
|
|
let child = constrained[constrained.length - 1];
|
|
this.sortBone(child);
|
|
this._updateCache.push(constraint);
|
|
this.sortReset(parent.children);
|
|
child.sorted = true;
|
|
}
|
|
}
|
|
sortPathConstraint(constraint) {
|
|
constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true));
|
|
if (!constraint.active)
|
|
return;
|
|
let slot = constraint.target;
|
|
let slotIndex = slot.data.index;
|
|
let slotBone = slot.bone;
|
|
if (this.skin)
|
|
this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);
|
|
if (this.data.defaultSkin && this.data.defaultSkin != this.skin)
|
|
this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone);
|
|
for (let i = 0, n = this.data.skins.length; i < n; i++)
|
|
this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone);
|
|
let attachment = slot.getAttachment();
|
|
if (attachment instanceof PathAttachment)
|
|
this.sortPathConstraintAttachmentWith(attachment, slotBone);
|
|
let constrained = constraint.bones;
|
|
let boneCount = constrained.length;
|
|
for (let i = 0; i < boneCount; i++)
|
|
this.sortBone(constrained[i]);
|
|
this._updateCache.push(constraint);
|
|
for (let i = 0; i < boneCount; i++)
|
|
this.sortReset(constrained[i].children);
|
|
for (let i = 0; i < boneCount; i++)
|
|
constrained[i].sorted = true;
|
|
}
|
|
sortTransformConstraint(constraint) {
|
|
constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true));
|
|
if (!constraint.active)
|
|
return;
|
|
this.sortBone(constraint.target);
|
|
let constrained = constraint.bones;
|
|
let boneCount = constrained.length;
|
|
if (constraint.data.local) {
|
|
for (let i = 0; i < boneCount; i++) {
|
|
let child = constrained[i];
|
|
this.sortBone(child.parent);
|
|
this.sortBone(child);
|
|
}
|
|
} else {
|
|
for (let i = 0; i < boneCount; i++) {
|
|
this.sortBone(constrained[i]);
|
|
}
|
|
}
|
|
this._updateCache.push(constraint);
|
|
for (let i = 0; i < boneCount; i++)
|
|
this.sortReset(constrained[i].children);
|
|
for (let i = 0; i < boneCount; i++)
|
|
constrained[i].sorted = true;
|
|
}
|
|
sortPathConstraintAttachment(skin, slotIndex, slotBone) {
|
|
let attachments = skin.attachments[slotIndex];
|
|
if (!attachments)
|
|
return;
|
|
for (let key in attachments) {
|
|
this.sortPathConstraintAttachmentWith(attachments[key], slotBone);
|
|
}
|
|
}
|
|
sortPathConstraintAttachmentWith(attachment, slotBone) {
|
|
if (!(attachment instanceof PathAttachment))
|
|
return;
|
|
let pathBones = attachment.bones;
|
|
if (!pathBones)
|
|
this.sortBone(slotBone);
|
|
else {
|
|
let bones = this.bones;
|
|
for (let i = 0, n = pathBones.length; i < n; ) {
|
|
let nn = pathBones[i++];
|
|
nn += i;
|
|
while (i < nn)
|
|
this.sortBone(bones[pathBones[i++]]);
|
|
}
|
|
}
|
|
}
|
|
sortBone(bone) {
|
|
if (!bone)
|
|
return;
|
|
if (bone.sorted)
|
|
return;
|
|
let parent = bone.parent;
|
|
if (parent)
|
|
this.sortBone(parent);
|
|
bone.sorted = true;
|
|
this._updateCache.push(bone);
|
|
}
|
|
sortReset(bones) {
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (!bone.active)
|
|
continue;
|
|
if (bone.sorted)
|
|
this.sortReset(bone.children);
|
|
bone.sorted = false;
|
|
}
|
|
}
|
|
updateWorldTransform() {
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
bone.ax = bone.x;
|
|
bone.ay = bone.y;
|
|
bone.arotation = bone.rotation;
|
|
bone.ascaleX = bone.scaleX;
|
|
bone.ascaleY = bone.scaleY;
|
|
bone.ashearX = bone.shearX;
|
|
bone.ashearY = bone.shearY;
|
|
}
|
|
let updateCache = this._updateCache;
|
|
for (let i = 0, n = updateCache.length; i < n; i++)
|
|
updateCache[i].update();
|
|
}
|
|
updateWorldTransformWith(parent) {
|
|
let rootBone = this.getRootBone();
|
|
if (!rootBone)
|
|
throw new Error("Root bone must not be null.");
|
|
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
|
rootBone.worldX = pa * this.x + pb * this.y + parent.worldX;
|
|
rootBone.worldY = pc * this.x + pd * this.y + parent.worldY;
|
|
let rotationY = rootBone.rotation + 90 + rootBone.shearY;
|
|
let la = MathUtils.cosDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
|
|
let lb = MathUtils.cosDeg(rotationY) * rootBone.scaleY;
|
|
let lc = MathUtils.sinDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
|
|
let ld = MathUtils.sinDeg(rotationY) * rootBone.scaleY;
|
|
rootBone.a = (pa * la + pb * lc) * this.scaleX;
|
|
rootBone.b = (pa * lb + pb * ld) * this.scaleX;
|
|
rootBone.c = (pc * la + pd * lc) * this.scaleY;
|
|
rootBone.d = (pc * lb + pd * ld) * this.scaleY;
|
|
let updateCache = this._updateCache;
|
|
for (let i = 0, n = updateCache.length; i < n; i++) {
|
|
let updatable = updateCache[i];
|
|
if (updatable != rootBone)
|
|
updatable.update();
|
|
}
|
|
}
|
|
setToSetupPose() {
|
|
this.setBonesToSetupPose();
|
|
this.setSlotsToSetupPose();
|
|
}
|
|
setBonesToSetupPose() {
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++)
|
|
bones[i].setToSetupPose();
|
|
let ikConstraints = this.ikConstraints;
|
|
for (let i = 0, n = ikConstraints.length; i < n; i++) {
|
|
let constraint = ikConstraints[i];
|
|
constraint.mix = constraint.data.mix;
|
|
constraint.softness = constraint.data.softness;
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
}
|
|
let transformConstraints = this.transformConstraints;
|
|
for (let i = 0, n = transformConstraints.length; i < n; i++) {
|
|
let constraint = transformConstraints[i];
|
|
let data = constraint.data;
|
|
constraint.mixRotate = data.mixRotate;
|
|
constraint.mixX = data.mixX;
|
|
constraint.mixY = data.mixY;
|
|
constraint.mixScaleX = data.mixScaleX;
|
|
constraint.mixScaleY = data.mixScaleY;
|
|
constraint.mixShearY = data.mixShearY;
|
|
}
|
|
let pathConstraints = this.pathConstraints;
|
|
for (let i = 0, n = pathConstraints.length; i < n; i++) {
|
|
let constraint = pathConstraints[i];
|
|
let data = constraint.data;
|
|
constraint.position = data.position;
|
|
constraint.spacing = data.spacing;
|
|
constraint.mixRotate = data.mixRotate;
|
|
constraint.mixX = data.mixX;
|
|
constraint.mixY = data.mixY;
|
|
}
|
|
}
|
|
setSlotsToSetupPose() {
|
|
let slots = this.slots;
|
|
Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length);
|
|
for (let i = 0, n = slots.length; i < n; i++)
|
|
slots[i].setToSetupPose();
|
|
}
|
|
getRootBone() {
|
|
if (this.bones.length == 0)
|
|
return null;
|
|
return this.bones[0];
|
|
}
|
|
findBone(boneName) {
|
|
if (!boneName)
|
|
throw new Error("boneName cannot be null.");
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (bone.data.name == boneName)
|
|
return bone;
|
|
}
|
|
return null;
|
|
}
|
|
findSlot(slotName) {
|
|
if (!slotName)
|
|
throw new Error("slotName cannot be null.");
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (slot.data.name == slotName)
|
|
return slot;
|
|
}
|
|
return null;
|
|
}
|
|
setSkinByName(skinName) {
|
|
let skin = this.data.findSkin(skinName);
|
|
if (!skin)
|
|
throw new Error("Skin not found: " + skinName);
|
|
this.setSkin(skin);
|
|
}
|
|
setSkin(newSkin) {
|
|
if (newSkin == this.skin)
|
|
return;
|
|
if (newSkin) {
|
|
if (this.skin)
|
|
newSkin.attachAll(this, this.skin);
|
|
else {
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
let name = slot.data.attachmentName;
|
|
if (name) {
|
|
let attachment = newSkin.getAttachment(i, name);
|
|
if (attachment)
|
|
slot.setAttachment(attachment);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.skin = newSkin;
|
|
this.updateCache();
|
|
}
|
|
getAttachmentByName(slotName, attachmentName) {
|
|
let slot = this.data.findSlot(slotName);
|
|
if (!slot)
|
|
throw new Error(`Can't find slot with name ${slotName}`);
|
|
return this.getAttachment(slot.index, attachmentName);
|
|
}
|
|
getAttachment(slotIndex, attachmentName) {
|
|
if (!attachmentName)
|
|
throw new Error("attachmentName cannot be null.");
|
|
if (this.skin) {
|
|
let attachment = this.skin.getAttachment(slotIndex, attachmentName);
|
|
if (attachment)
|
|
return attachment;
|
|
}
|
|
if (this.data.defaultSkin)
|
|
return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);
|
|
return null;
|
|
}
|
|
setAttachment(slotName, attachmentName) {
|
|
if (!slotName)
|
|
throw new Error("slotName cannot be null.");
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (slot.data.name == slotName) {
|
|
let attachment = null;
|
|
if (attachmentName) {
|
|
attachment = this.getAttachment(i, attachmentName);
|
|
if (!attachment)
|
|
throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName);
|
|
}
|
|
slot.setAttachment(attachment);
|
|
return;
|
|
}
|
|
}
|
|
throw new Error("Slot not found: " + slotName);
|
|
}
|
|
findIkConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let ikConstraints = this.ikConstraints;
|
|
for (let i = 0, n = ikConstraints.length; i < n; i++) {
|
|
let ikConstraint = ikConstraints[i];
|
|
if (ikConstraint.data.name == constraintName)
|
|
return ikConstraint;
|
|
}
|
|
return null;
|
|
}
|
|
findTransformConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let transformConstraints = this.transformConstraints;
|
|
for (let i = 0, n = transformConstraints.length; i < n; i++) {
|
|
let constraint = transformConstraints[i];
|
|
if (constraint.data.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
findPathConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let pathConstraints = this.pathConstraints;
|
|
for (let i = 0, n = pathConstraints.length; i < n; i++) {
|
|
let constraint = pathConstraints[i];
|
|
if (constraint.data.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
getBoundsRect() {
|
|
let offset = new Vector2();
|
|
let size = new Vector2();
|
|
this.getBounds(offset, size);
|
|
return { x: offset.x, y: offset.y, width: size.x, height: size.y };
|
|
}
|
|
getBounds(offset, size, temp = new Array(2)) {
|
|
if (!offset)
|
|
throw new Error("offset cannot be null.");
|
|
if (!size)
|
|
throw new Error("size cannot be null.");
|
|
let drawOrder = this.drawOrder;
|
|
let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
|
|
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
|
let slot = drawOrder[i];
|
|
if (!slot.bone.active)
|
|
continue;
|
|
let verticesLength = 0;
|
|
let vertices = null;
|
|
let attachment = slot.getAttachment();
|
|
if (attachment instanceof RegionAttachment) {
|
|
verticesLength = 8;
|
|
vertices = Utils.setArraySize(temp, verticesLength, 0);
|
|
attachment.computeWorldVertices(slot, vertices, 0, 2);
|
|
} else if (attachment instanceof MeshAttachment) {
|
|
let mesh = attachment;
|
|
verticesLength = mesh.worldVerticesLength;
|
|
vertices = Utils.setArraySize(temp, verticesLength, 0);
|
|
mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
|
|
}
|
|
if (vertices) {
|
|
for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) {
|
|
let x = vertices[ii], y = vertices[ii + 1];
|
|
minX = Math.min(minX, x);
|
|
minY = Math.min(minY, y);
|
|
maxX = Math.max(maxX, x);
|
|
maxY = Math.max(maxY, y);
|
|
}
|
|
}
|
|
}
|
|
offset.set(minX, minY);
|
|
size.set(maxX - minX, maxY - minY);
|
|
}
|
|
};
|
|
var Skeleton = _Skeleton;
|
|
Skeleton.yDown = false;
|
|
|
|
// spine-core/src/SkeletonData.ts
|
|
var SkeletonData = class {
|
|
constructor() {
|
|
this.name = null;
|
|
this.bones = new Array();
|
|
this.slots = new Array();
|
|
this.skins = new Array();
|
|
this.defaultSkin = null;
|
|
this.events = new Array();
|
|
this.animations = new Array();
|
|
this.ikConstraints = new Array();
|
|
this.transformConstraints = new Array();
|
|
this.pathConstraints = new Array();
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.version = null;
|
|
this.hash = null;
|
|
this.fps = 0;
|
|
this.imagesPath = null;
|
|
this.audioPath = null;
|
|
}
|
|
findBone(boneName) {
|
|
if (!boneName)
|
|
throw new Error("boneName cannot be null.");
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (bone.name == boneName)
|
|
return bone;
|
|
}
|
|
return null;
|
|
}
|
|
findSlot(slotName) {
|
|
if (!slotName)
|
|
throw new Error("slotName cannot be null.");
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (slot.name == slotName)
|
|
return slot;
|
|
}
|
|
return null;
|
|
}
|
|
findSkin(skinName) {
|
|
if (!skinName)
|
|
throw new Error("skinName cannot be null.");
|
|
let skins = this.skins;
|
|
for (let i = 0, n = skins.length; i < n; i++) {
|
|
let skin = skins[i];
|
|
if (skin.name == skinName)
|
|
return skin;
|
|
}
|
|
return null;
|
|
}
|
|
findEvent(eventDataName) {
|
|
if (!eventDataName)
|
|
throw new Error("eventDataName cannot be null.");
|
|
let events = this.events;
|
|
for (let i = 0, n = events.length; i < n; i++) {
|
|
let event = events[i];
|
|
if (event.name == eventDataName)
|
|
return event;
|
|
}
|
|
return null;
|
|
}
|
|
findAnimation(animationName) {
|
|
if (!animationName)
|
|
throw new Error("animationName cannot be null.");
|
|
let animations = this.animations;
|
|
for (let i = 0, n = animations.length; i < n; i++) {
|
|
let animation = animations[i];
|
|
if (animation.name == animationName)
|
|
return animation;
|
|
}
|
|
return null;
|
|
}
|
|
findIkConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let ikConstraints = this.ikConstraints;
|
|
for (let i = 0, n = ikConstraints.length; i < n; i++) {
|
|
let constraint = ikConstraints[i];
|
|
if (constraint.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
findTransformConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let transformConstraints = this.transformConstraints;
|
|
for (let i = 0, n = transformConstraints.length; i < n; i++) {
|
|
let constraint = transformConstraints[i];
|
|
if (constraint.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
findPathConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let pathConstraints = this.pathConstraints;
|
|
for (let i = 0, n = pathConstraints.length; i < n; i++) {
|
|
let constraint = pathConstraints[i];
|
|
if (constraint.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Skin.ts
|
|
var SkinEntry = class {
|
|
constructor(slotIndex = 0, name, attachment) {
|
|
this.slotIndex = slotIndex;
|
|
this.name = name;
|
|
this.attachment = attachment;
|
|
}
|
|
};
|
|
var Skin = class {
|
|
constructor(name) {
|
|
this.attachments = new Array();
|
|
this.bones = Array();
|
|
this.constraints = new Array();
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.name = name;
|
|
}
|
|
setAttachment(slotIndex, name, attachment) {
|
|
if (!attachment)
|
|
throw new Error("attachment cannot be null.");
|
|
let attachments = this.attachments;
|
|
if (slotIndex >= attachments.length)
|
|
attachments.length = slotIndex + 1;
|
|
if (!attachments[slotIndex])
|
|
attachments[slotIndex] = {};
|
|
attachments[slotIndex][name] = attachment;
|
|
}
|
|
addSkin(skin) {
|
|
for (let i = 0; i < skin.bones.length; i++) {
|
|
let bone = skin.bones[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.bones.length; ii++) {
|
|
if (this.bones[ii] == bone) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.bones.push(bone);
|
|
}
|
|
for (let i = 0; i < skin.constraints.length; i++) {
|
|
let constraint = skin.constraints[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.constraints.length; ii++) {
|
|
if (this.constraints[ii] == constraint) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.constraints.push(constraint);
|
|
}
|
|
let attachments = skin.getAttachments();
|
|
for (let i = 0; i < attachments.length; i++) {
|
|
var attachment = attachments[i];
|
|
this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
|
}
|
|
}
|
|
copySkin(skin) {
|
|
for (let i = 0; i < skin.bones.length; i++) {
|
|
let bone = skin.bones[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.bones.length; ii++) {
|
|
if (this.bones[ii] == bone) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.bones.push(bone);
|
|
}
|
|
for (let i = 0; i < skin.constraints.length; i++) {
|
|
let constraint = skin.constraints[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.constraints.length; ii++) {
|
|
if (this.constraints[ii] == constraint) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.constraints.push(constraint);
|
|
}
|
|
let attachments = skin.getAttachments();
|
|
for (let i = 0; i < attachments.length; i++) {
|
|
var attachment = attachments[i];
|
|
if (!attachment.attachment)
|
|
continue;
|
|
if (attachment.attachment instanceof MeshAttachment) {
|
|
attachment.attachment = attachment.attachment.newLinkedMesh();
|
|
this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
|
} else {
|
|
attachment.attachment = attachment.attachment.copy();
|
|
this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
|
}
|
|
}
|
|
}
|
|
getAttachment(slotIndex, name) {
|
|
let dictionary = this.attachments[slotIndex];
|
|
return dictionary ? dictionary[name] : null;
|
|
}
|
|
removeAttachment(slotIndex, name) {
|
|
let dictionary = this.attachments[slotIndex];
|
|
if (dictionary)
|
|
delete dictionary[name];
|
|
}
|
|
getAttachments() {
|
|
let entries = new Array();
|
|
for (var i = 0; i < this.attachments.length; i++) {
|
|
let slotAttachments = this.attachments[i];
|
|
if (slotAttachments) {
|
|
for (let name in slotAttachments) {
|
|
let attachment = slotAttachments[name];
|
|
if (attachment)
|
|
entries.push(new SkinEntry(i, name, attachment));
|
|
}
|
|
}
|
|
}
|
|
return entries;
|
|
}
|
|
getAttachmentsForSlot(slotIndex, attachments) {
|
|
let slotAttachments = this.attachments[slotIndex];
|
|
if (slotAttachments) {
|
|
for (let name in slotAttachments) {
|
|
let attachment = slotAttachments[name];
|
|
if (attachment)
|
|
attachments.push(new SkinEntry(slotIndex, name, attachment));
|
|
}
|
|
}
|
|
}
|
|
clear() {
|
|
this.attachments.length = 0;
|
|
this.bones.length = 0;
|
|
this.constraints.length = 0;
|
|
}
|
|
attachAll(skeleton, oldSkin) {
|
|
let slotIndex = 0;
|
|
for (let i = 0; i < skeleton.slots.length; i++) {
|
|
let slot = skeleton.slots[i];
|
|
let slotAttachment = slot.getAttachment();
|
|
if (slotAttachment && slotIndex < oldSkin.attachments.length) {
|
|
let dictionary = oldSkin.attachments[slotIndex];
|
|
for (let key in dictionary) {
|
|
let skinAttachment = dictionary[key];
|
|
if (slotAttachment == skinAttachment) {
|
|
let attachment = this.getAttachment(slotIndex, key);
|
|
if (attachment)
|
|
slot.setAttachment(attachment);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
slotIndex++;
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SlotData.ts
|
|
var SlotData = class {
|
|
constructor(index, name, boneData) {
|
|
this.index = 0;
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.darkColor = null;
|
|
this.attachmentName = null;
|
|
this.blendMode = BlendMode.Normal;
|
|
if (index < 0)
|
|
throw new Error("index must be >= 0.");
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
if (!boneData)
|
|
throw new Error("boneData cannot be null.");
|
|
this.index = index;
|
|
this.name = name;
|
|
this.boneData = boneData;
|
|
}
|
|
};
|
|
var BlendMode = /* @__PURE__ */ ((BlendMode3) => {
|
|
BlendMode3[BlendMode3["Normal"] = 0] = "Normal";
|
|
BlendMode3[BlendMode3["Additive"] = 1] = "Additive";
|
|
BlendMode3[BlendMode3["Multiply"] = 2] = "Multiply";
|
|
BlendMode3[BlendMode3["Screen"] = 3] = "Screen";
|
|
return BlendMode3;
|
|
})(BlendMode || {});
|
|
|
|
// spine-core/src/TransformConstraintData.ts
|
|
var TransformConstraintData = class extends ConstraintData {
|
|
constructor(name) {
|
|
super(name, 0, false);
|
|
this.bones = new Array();
|
|
this._target = null;
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
this.mixScaleX = 0;
|
|
this.mixScaleY = 0;
|
|
this.mixShearY = 0;
|
|
this.offsetRotation = 0;
|
|
this.offsetX = 0;
|
|
this.offsetY = 0;
|
|
this.offsetScaleX = 0;
|
|
this.offsetScaleY = 0;
|
|
this.offsetShearY = 0;
|
|
this.relative = false;
|
|
this.local = false;
|
|
}
|
|
set target(boneData) {
|
|
this._target = boneData;
|
|
}
|
|
get target() {
|
|
if (!this._target)
|
|
throw new Error("BoneData not set.");
|
|
else
|
|
return this._target;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SkeletonBinary.ts
|
|
var SkeletonBinary = class {
|
|
constructor(attachmentLoader) {
|
|
this.scale = 1;
|
|
this.linkedMeshes = new Array();
|
|
this.attachmentLoader = attachmentLoader;
|
|
}
|
|
readSkeletonData(binary) {
|
|
let scale = this.scale;
|
|
let skeletonData = new SkeletonData();
|
|
skeletonData.name = "";
|
|
let input = new BinaryInput(binary);
|
|
let lowHash = input.readInt32();
|
|
let highHash = input.readInt32();
|
|
skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16);
|
|
skeletonData.version = input.readString();
|
|
skeletonData.x = input.readFloat();
|
|
skeletonData.y = input.readFloat();
|
|
skeletonData.width = input.readFloat();
|
|
skeletonData.height = input.readFloat();
|
|
let nonessential = input.readBoolean();
|
|
if (nonessential) {
|
|
skeletonData.fps = input.readFloat();
|
|
skeletonData.imagesPath = input.readString();
|
|
skeletonData.audioPath = input.readString();
|
|
}
|
|
let n = 0;
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let str = input.readString();
|
|
if (!str)
|
|
throw new Error("String in string table must not be null.");
|
|
input.strings.push(str);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("Bone name must not be null.");
|
|
let parent = i == 0 ? null : skeletonData.bones[input.readInt(true)];
|
|
let data = new BoneData(i, name, parent);
|
|
data.rotation = input.readFloat();
|
|
data.x = input.readFloat() * scale;
|
|
data.y = input.readFloat() * scale;
|
|
data.scaleX = input.readFloat();
|
|
data.scaleY = input.readFloat();
|
|
data.shearX = input.readFloat();
|
|
data.shearY = input.readFloat();
|
|
data.length = input.readFloat() * scale;
|
|
data.transformMode = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(data.color, input.readInt32());
|
|
skeletonData.bones.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let slotName = input.readString();
|
|
if (!slotName)
|
|
throw new Error("Slot name must not be null.");
|
|
let boneData = skeletonData.bones[input.readInt(true)];
|
|
let data = new SlotData(i, slotName, boneData);
|
|
Color.rgba8888ToColor(data.color, input.readInt32());
|
|
let darkColor = input.readInt32();
|
|
if (darkColor != -1)
|
|
Color.rgb888ToColor(data.darkColor = new Color(), darkColor);
|
|
data.attachmentName = input.readStringRef();
|
|
data.blendMode = input.readInt(true);
|
|
skeletonData.slots.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0, nn; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("IK constraint data name must not be null.");
|
|
let data = new IkConstraintData(name);
|
|
data.order = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
nn = input.readInt(true);
|
|
for (let ii = 0; ii < nn; ii++)
|
|
data.bones.push(skeletonData.bones[input.readInt(true)]);
|
|
data.target = skeletonData.bones[input.readInt(true)];
|
|
data.mix = input.readFloat();
|
|
data.softness = input.readFloat() * scale;
|
|
data.bendDirection = input.readByte();
|
|
data.compress = input.readBoolean();
|
|
data.stretch = input.readBoolean();
|
|
data.uniform = input.readBoolean();
|
|
skeletonData.ikConstraints.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0, nn; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("Transform constraint data name must not be null.");
|
|
let data = new TransformConstraintData(name);
|
|
data.order = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
nn = input.readInt(true);
|
|
for (let ii = 0; ii < nn; ii++)
|
|
data.bones.push(skeletonData.bones[input.readInt(true)]);
|
|
data.target = skeletonData.bones[input.readInt(true)];
|
|
data.local = input.readBoolean();
|
|
data.relative = input.readBoolean();
|
|
data.offsetRotation = input.readFloat();
|
|
data.offsetX = input.readFloat() * scale;
|
|
data.offsetY = input.readFloat() * scale;
|
|
data.offsetScaleX = input.readFloat();
|
|
data.offsetScaleY = input.readFloat();
|
|
data.offsetShearY = input.readFloat();
|
|
data.mixRotate = input.readFloat();
|
|
data.mixX = input.readFloat();
|
|
data.mixY = input.readFloat();
|
|
data.mixScaleX = input.readFloat();
|
|
data.mixScaleY = input.readFloat();
|
|
data.mixShearY = input.readFloat();
|
|
skeletonData.transformConstraints.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0, nn; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("Path constraint data name must not be null.");
|
|
let data = new PathConstraintData(name);
|
|
data.order = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
nn = input.readInt(true);
|
|
for (let ii = 0; ii < nn; ii++)
|
|
data.bones.push(skeletonData.bones[input.readInt(true)]);
|
|
data.target = skeletonData.slots[input.readInt(true)];
|
|
data.positionMode = input.readInt(true);
|
|
data.spacingMode = input.readInt(true);
|
|
data.rotateMode = input.readInt(true);
|
|
data.offsetRotation = input.readFloat();
|
|
data.position = input.readFloat();
|
|
if (data.positionMode == 0 /* Fixed */)
|
|
data.position *= scale;
|
|
data.spacing = input.readFloat();
|
|
if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */)
|
|
data.spacing *= scale;
|
|
data.mixRotate = input.readFloat();
|
|
data.mixX = input.readFloat();
|
|
data.mixY = input.readFloat();
|
|
skeletonData.pathConstraints.push(data);
|
|
}
|
|
let defaultSkin = this.readSkin(input, skeletonData, true, nonessential);
|
|
if (defaultSkin) {
|
|
skeletonData.defaultSkin = defaultSkin;
|
|
skeletonData.skins.push(defaultSkin);
|
|
}
|
|
{
|
|
let i = skeletonData.skins.length;
|
|
Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true));
|
|
for (; i < n; i++) {
|
|
let skin = this.readSkin(input, skeletonData, false, nonessential);
|
|
if (!skin)
|
|
throw new Error("readSkin() should not have returned null.");
|
|
skeletonData.skins[i] = skin;
|
|
}
|
|
}
|
|
n = this.linkedMeshes.length;
|
|
for (let i = 0; i < n; i++) {
|
|
let linkedMesh = this.linkedMeshes[i];
|
|
let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
|
if (!skin)
|
|
throw new Error("Not skin found for linked mesh.");
|
|
if (!linkedMesh.parent)
|
|
throw new Error("Linked mesh parent must not be null");
|
|
let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
|
if (!parent)
|
|
throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);
|
|
linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh;
|
|
linkedMesh.mesh.setParentMesh(parent);
|
|
if (linkedMesh.mesh.region != null)
|
|
linkedMesh.mesh.updateRegion();
|
|
}
|
|
this.linkedMeshes.length = 0;
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let eventName = input.readStringRef();
|
|
if (!eventName)
|
|
throw new Error();
|
|
let data = new EventData(eventName);
|
|
data.intValue = input.readInt(false);
|
|
data.floatValue = input.readFloat();
|
|
data.stringValue = input.readString();
|
|
data.audioPath = input.readString();
|
|
if (data.audioPath) {
|
|
data.volume = input.readFloat();
|
|
data.balance = input.readFloat();
|
|
}
|
|
skeletonData.events.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let animationName = input.readString();
|
|
if (!animationName)
|
|
throw new Error("Animatio name must not be null.");
|
|
skeletonData.animations.push(this.readAnimation(input, animationName, skeletonData));
|
|
}
|
|
return skeletonData;
|
|
}
|
|
readSkin(input, skeletonData, defaultSkin, nonessential) {
|
|
let skin = null;
|
|
let slotCount = 0;
|
|
if (defaultSkin) {
|
|
slotCount = input.readInt(true);
|
|
if (slotCount == 0)
|
|
return null;
|
|
skin = new Skin("default");
|
|
} else {
|
|
let skinName = input.readStringRef();
|
|
if (!skinName)
|
|
throw new Error("Skin name must not be null.");
|
|
skin = new Skin(skinName);
|
|
skin.bones.length = input.readInt(true);
|
|
for (let i = 0, n = skin.bones.length; i < n; i++)
|
|
skin.bones[i] = skeletonData.bones[input.readInt(true)];
|
|
for (let i = 0, n = input.readInt(true); i < n; i++)
|
|
skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]);
|
|
for (let i = 0, n = input.readInt(true); i < n; i++)
|
|
skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]);
|
|
for (let i = 0, n = input.readInt(true); i < n; i++)
|
|
skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]);
|
|
slotCount = input.readInt(true);
|
|
}
|
|
for (let i = 0; i < slotCount; i++) {
|
|
let slotIndex = input.readInt(true);
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let name = input.readStringRef();
|
|
if (!name)
|
|
throw new Error("Attachment name must not be null");
|
|
let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential);
|
|
if (attachment)
|
|
skin.setAttachment(slotIndex, name, attachment);
|
|
}
|
|
}
|
|
return skin;
|
|
}
|
|
readAttachment(input, skeletonData, skin, slotIndex, attachmentName, nonessential) {
|
|
let scale = this.scale;
|
|
let name = input.readStringRef();
|
|
if (!name)
|
|
name = attachmentName;
|
|
switch (input.readByte()) {
|
|
case AttachmentType.Region: {
|
|
let path = input.readStringRef();
|
|
let rotation = input.readFloat();
|
|
let x = input.readFloat();
|
|
let y = input.readFloat();
|
|
let scaleX = input.readFloat();
|
|
let scaleY = input.readFloat();
|
|
let width = input.readFloat();
|
|
let height = input.readFloat();
|
|
let color = input.readInt32();
|
|
let sequence = this.readSequence(input);
|
|
if (!path)
|
|
path = name;
|
|
let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);
|
|
if (!region)
|
|
return null;
|
|
region.path = path;
|
|
region.x = x * scale;
|
|
region.y = y * scale;
|
|
region.scaleX = scaleX;
|
|
region.scaleY = scaleY;
|
|
region.rotation = rotation;
|
|
region.width = width * scale;
|
|
region.height = height * scale;
|
|
Color.rgba8888ToColor(region.color, color);
|
|
region.sequence = sequence;
|
|
if (sequence == null)
|
|
region.updateRegion();
|
|
return region;
|
|
}
|
|
case AttachmentType.BoundingBox: {
|
|
let vertexCount = input.readInt(true);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);
|
|
if (!box)
|
|
return null;
|
|
box.worldVerticesLength = vertexCount << 1;
|
|
box.vertices = vertices.vertices;
|
|
box.bones = vertices.bones;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(box.color, color);
|
|
return box;
|
|
}
|
|
case AttachmentType.Mesh: {
|
|
let path = input.readStringRef();
|
|
let color = input.readInt32();
|
|
let vertexCount = input.readInt(true);
|
|
let uvs = this.readFloatArray(input, vertexCount << 1, 1);
|
|
let triangles = this.readShortArray(input);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let hullLength = input.readInt(true);
|
|
let sequence = this.readSequence(input);
|
|
let edges = [];
|
|
let width = 0, height = 0;
|
|
if (nonessential) {
|
|
edges = this.readShortArray(input);
|
|
width = input.readFloat();
|
|
height = input.readFloat();
|
|
}
|
|
if (!path)
|
|
path = name;
|
|
let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
|
if (!mesh)
|
|
return null;
|
|
mesh.path = path;
|
|
Color.rgba8888ToColor(mesh.color, color);
|
|
mesh.bones = vertices.bones;
|
|
mesh.vertices = vertices.vertices;
|
|
mesh.worldVerticesLength = vertexCount << 1;
|
|
mesh.triangles = triangles;
|
|
mesh.regionUVs = uvs;
|
|
if (sequence == null)
|
|
mesh.updateRegion();
|
|
mesh.hullLength = hullLength << 1;
|
|
mesh.sequence = sequence;
|
|
if (nonessential) {
|
|
mesh.edges = edges;
|
|
mesh.width = width * scale;
|
|
mesh.height = height * scale;
|
|
}
|
|
return mesh;
|
|
}
|
|
case AttachmentType.LinkedMesh: {
|
|
let path = input.readStringRef();
|
|
let color = input.readInt32();
|
|
let skinName = input.readStringRef();
|
|
let parent = input.readStringRef();
|
|
let inheritTimelines = input.readBoolean();
|
|
let sequence = this.readSequence(input);
|
|
let width = 0, height = 0;
|
|
if (nonessential) {
|
|
width = input.readFloat();
|
|
height = input.readFloat();
|
|
}
|
|
if (!path)
|
|
path = name;
|
|
let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
|
if (!mesh)
|
|
return null;
|
|
mesh.path = path;
|
|
Color.rgba8888ToColor(mesh.color, color);
|
|
mesh.sequence = sequence;
|
|
if (nonessential) {
|
|
mesh.width = width * scale;
|
|
mesh.height = height * scale;
|
|
}
|
|
this.linkedMeshes.push(new LinkedMesh(mesh, skinName, slotIndex, parent, inheritTimelines));
|
|
return mesh;
|
|
}
|
|
case AttachmentType.Path: {
|
|
let closed2 = input.readBoolean();
|
|
let constantSpeed = input.readBoolean();
|
|
let vertexCount = input.readInt(true);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let lengths = Utils.newArray(vertexCount / 3, 0);
|
|
for (let i = 0, n = lengths.length; i < n; i++)
|
|
lengths[i] = input.readFloat() * scale;
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let path = this.attachmentLoader.newPathAttachment(skin, name);
|
|
if (!path)
|
|
return null;
|
|
path.closed = closed2;
|
|
path.constantSpeed = constantSpeed;
|
|
path.worldVerticesLength = vertexCount << 1;
|
|
path.vertices = vertices.vertices;
|
|
path.bones = vertices.bones;
|
|
path.lengths = lengths;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(path.color, color);
|
|
return path;
|
|
}
|
|
case AttachmentType.Point: {
|
|
let rotation = input.readFloat();
|
|
let x = input.readFloat();
|
|
let y = input.readFloat();
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let point = this.attachmentLoader.newPointAttachment(skin, name);
|
|
if (!point)
|
|
return null;
|
|
point.x = x * scale;
|
|
point.y = y * scale;
|
|
point.rotation = rotation;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(point.color, color);
|
|
return point;
|
|
}
|
|
case AttachmentType.Clipping: {
|
|
let endSlotIndex = input.readInt(true);
|
|
let vertexCount = input.readInt(true);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let clip = this.attachmentLoader.newClippingAttachment(skin, name);
|
|
if (!clip)
|
|
return null;
|
|
clip.endSlot = skeletonData.slots[endSlotIndex];
|
|
clip.worldVerticesLength = vertexCount << 1;
|
|
clip.vertices = vertices.vertices;
|
|
clip.bones = vertices.bones;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(clip.color, color);
|
|
return clip;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
readSequence(input) {
|
|
if (!input.readBoolean())
|
|
return null;
|
|
let sequence = new Sequence(input.readInt(true));
|
|
sequence.start = input.readInt(true);
|
|
sequence.digits = input.readInt(true);
|
|
sequence.setupIndex = input.readInt(true);
|
|
return sequence;
|
|
}
|
|
readVertices(input, vertexCount) {
|
|
let scale = this.scale;
|
|
let verticesLength = vertexCount << 1;
|
|
let vertices = new Vertices();
|
|
if (!input.readBoolean()) {
|
|
vertices.vertices = this.readFloatArray(input, verticesLength, scale);
|
|
return vertices;
|
|
}
|
|
let weights = new Array();
|
|
let bonesArray = new Array();
|
|
for (let i = 0; i < vertexCount; i++) {
|
|
let boneCount = input.readInt(true);
|
|
bonesArray.push(boneCount);
|
|
for (let ii = 0; ii < boneCount; ii++) {
|
|
bonesArray.push(input.readInt(true));
|
|
weights.push(input.readFloat() * scale);
|
|
weights.push(input.readFloat() * scale);
|
|
weights.push(input.readFloat());
|
|
}
|
|
}
|
|
vertices.vertices = Utils.toFloatArray(weights);
|
|
vertices.bones = bonesArray;
|
|
return vertices;
|
|
}
|
|
readFloatArray(input, n, scale) {
|
|
let array = new Array(n);
|
|
if (scale == 1) {
|
|
for (let i = 0; i < n; i++)
|
|
array[i] = input.readFloat();
|
|
} else {
|
|
for (let i = 0; i < n; i++)
|
|
array[i] = input.readFloat() * scale;
|
|
}
|
|
return array;
|
|
}
|
|
readShortArray(input) {
|
|
let n = input.readInt(true);
|
|
let array = new Array(n);
|
|
for (let i = 0; i < n; i++)
|
|
array[i] = input.readShort();
|
|
return array;
|
|
}
|
|
readAnimation(input, name, skeletonData) {
|
|
input.readInt(true);
|
|
let timelines = new Array();
|
|
let scale = this.scale;
|
|
let tempColor1 = new Color();
|
|
let tempColor2 = new Color();
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let slotIndex = input.readInt(true);
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let timelineType = input.readByte();
|
|
let frameCount = input.readInt(true);
|
|
let frameLast = frameCount - 1;
|
|
switch (timelineType) {
|
|
case SLOT_ATTACHMENT: {
|
|
let timeline = new AttachmentTimeline(frameCount, slotIndex);
|
|
for (let frame = 0; frame < frameCount; frame++)
|
|
timeline.setFrame(frame, input.readFloat(), input.readStringRef());
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGBA: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
let a = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b, a);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
let a2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1);
|
|
}
|
|
time = time2;
|
|
r = r2;
|
|
g = g2;
|
|
b = b2;
|
|
a = a2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGB: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);
|
|
}
|
|
time = time2;
|
|
r = r2;
|
|
g = g2;
|
|
b = b2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGBA2: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
let a = input.readUnsignedByte() / 255;
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let nr = input.readUnsignedByte() / 255;
|
|
let ng = input.readUnsignedByte() / 255;
|
|
let nb = input.readUnsignedByte() / 255;
|
|
let na = input.readUnsignedByte() / 255;
|
|
let nr2 = input.readUnsignedByte() / 255;
|
|
let ng2 = input.readUnsignedByte() / 255;
|
|
let nb2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1);
|
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1);
|
|
}
|
|
time = time2;
|
|
r = nr;
|
|
g = ng;
|
|
b = nb;
|
|
a = na;
|
|
r2 = nr2;
|
|
g2 = ng2;
|
|
b2 = nb2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGB2: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b, r2, g2, b2);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let nr = input.readUnsignedByte() / 255;
|
|
let ng = input.readUnsignedByte() / 255;
|
|
let nb = input.readUnsignedByte() / 255;
|
|
let nr2 = input.readUnsignedByte() / 255;
|
|
let ng2 = input.readUnsignedByte() / 255;
|
|
let nb2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1);
|
|
}
|
|
time = time2;
|
|
r = nr;
|
|
g = ng;
|
|
b = nb;
|
|
r2 = nr2;
|
|
g2 = ng2;
|
|
b2 = nb2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_ALPHA: {
|
|
let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex);
|
|
let time = input.readFloat(), a = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, a);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let a2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1);
|
|
}
|
|
time = time2;
|
|
a = a2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let boneIndex = input.readInt(true);
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true);
|
|
switch (type) {
|
|
case BONE_ROTATE:
|
|
timelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_TRANSLATE:
|
|
timelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale));
|
|
break;
|
|
case BONE_TRANSLATEX:
|
|
timelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale));
|
|
break;
|
|
case BONE_TRANSLATEY:
|
|
timelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale));
|
|
break;
|
|
case BONE_SCALE:
|
|
timelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SCALEX:
|
|
timelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SCALEY:
|
|
timelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SHEAR:
|
|
timelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SHEARX:
|
|
timelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SHEARY:
|
|
timelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;
|
|
let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index);
|
|
let time = input.readFloat(), mix = input.readFloat(), softness = input.readFloat() * scale;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mix, softness, input.readByte(), input.readBoolean(), input.readBoolean());
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), mix2 = input.readFloat(), softness2 = input.readFloat() * scale;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale);
|
|
}
|
|
time = time2;
|
|
mix = mix2;
|
|
softness = softness2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;
|
|
let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index);
|
|
let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat();
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat();
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
mixScaleX = mixScaleX2;
|
|
mixScaleY = mixScaleY2;
|
|
mixShearY = mixShearY2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let index = input.readInt(true);
|
|
let data = skeletonData.pathConstraints[index];
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
switch (input.readByte()) {
|
|
case PATH_POSITION:
|
|
timelines.push(readTimeline1(
|
|
input,
|
|
new PathConstraintPositionTimeline(input.readInt(true), input.readInt(true), index),
|
|
data.positionMode == 0 /* Fixed */ ? scale : 1
|
|
));
|
|
break;
|
|
case PATH_SPACING:
|
|
timelines.push(readTimeline1(
|
|
input,
|
|
new PathConstraintSpacingTimeline(input.readInt(true), input.readInt(true), index),
|
|
data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */ ? scale : 1
|
|
));
|
|
break;
|
|
case PATH_MIX:
|
|
let timeline = new PathConstraintMixTimeline(input.readInt(true), input.readInt(true), index);
|
|
let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat();
|
|
for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat();
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let skin = skeletonData.skins[input.readInt(true)];
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let slotIndex = input.readInt(true);
|
|
for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) {
|
|
let attachmentName = input.readStringRef();
|
|
if (!attachmentName)
|
|
throw new Error("attachmentName must not be null.");
|
|
let attachment = skin.getAttachment(slotIndex, attachmentName);
|
|
let timelineType = input.readByte();
|
|
let frameCount = input.readInt(true);
|
|
let frameLast = frameCount - 1;
|
|
switch (timelineType) {
|
|
case ATTACHMENT_DEFORM: {
|
|
let vertexAttachment = attachment;
|
|
let weighted = vertexAttachment.bones;
|
|
let vertices = vertexAttachment.vertices;
|
|
let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment);
|
|
let time = input.readFloat();
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
let deform;
|
|
let end = input.readInt(true);
|
|
if (end == 0)
|
|
deform = weighted ? Utils.newFloatArray(deformLength) : vertices;
|
|
else {
|
|
deform = Utils.newFloatArray(deformLength);
|
|
let start = input.readInt(true);
|
|
end += start;
|
|
if (scale == 1) {
|
|
for (let v = start; v < end; v++)
|
|
deform[v] = input.readFloat();
|
|
} else {
|
|
for (let v = start; v < end; v++)
|
|
deform[v] = input.readFloat() * scale;
|
|
}
|
|
if (!weighted) {
|
|
for (let v = 0, vn = deform.length; v < vn; v++)
|
|
deform[v] += vertices[v];
|
|
}
|
|
}
|
|
timeline.setFrame(frame, time, deform);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
|
|
}
|
|
time = time2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case ATTACHMENT_SEQUENCE: {
|
|
let timeline = new SequenceTimeline(frameCount, slotIndex, attachment);
|
|
for (let frame = 0; frame < frameCount; frame++) {
|
|
let time = input.readFloat();
|
|
let modeAndIndex = input.readInt32();
|
|
timeline.setFrame(
|
|
frame,
|
|
time,
|
|
SequenceModeValues[modeAndIndex & 15],
|
|
modeAndIndex >> 4,
|
|
input.readFloat()
|
|
);
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let drawOrderCount = input.readInt(true);
|
|
if (drawOrderCount > 0) {
|
|
let timeline = new DrawOrderTimeline(drawOrderCount);
|
|
let slotCount = skeletonData.slots.length;
|
|
for (let i = 0; i < drawOrderCount; i++) {
|
|
let time = input.readFloat();
|
|
let offsetCount = input.readInt(true);
|
|
let drawOrder = Utils.newArray(slotCount, 0);
|
|
for (let ii = slotCount - 1; ii >= 0; ii--)
|
|
drawOrder[ii] = -1;
|
|
let unchanged = Utils.newArray(slotCount - offsetCount, 0);
|
|
let originalIndex = 0, unchangedIndex = 0;
|
|
for (let ii = 0; ii < offsetCount; ii++) {
|
|
let slotIndex = input.readInt(true);
|
|
while (originalIndex != slotIndex)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
drawOrder[originalIndex + input.readInt(true)] = originalIndex++;
|
|
}
|
|
while (originalIndex < slotCount)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
for (let ii = slotCount - 1; ii >= 0; ii--)
|
|
if (drawOrder[ii] == -1)
|
|
drawOrder[ii] = unchanged[--unchangedIndex];
|
|
timeline.setFrame(i, time, drawOrder);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
let eventCount = input.readInt(true);
|
|
if (eventCount > 0) {
|
|
let timeline = new EventTimeline(eventCount);
|
|
for (let i = 0; i < eventCount; i++) {
|
|
let time = input.readFloat();
|
|
let eventData = skeletonData.events[input.readInt(true)];
|
|
let event = new Event(time, eventData);
|
|
event.intValue = input.readInt(false);
|
|
event.floatValue = input.readFloat();
|
|
event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue;
|
|
if (event.data.audioPath) {
|
|
event.volume = input.readFloat();
|
|
event.balance = input.readFloat();
|
|
}
|
|
timeline.setFrame(i, event);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
let duration = 0;
|
|
for (let i = 0, n = timelines.length; i < n; i++)
|
|
duration = Math.max(duration, timelines[i].getDuration());
|
|
return new Animation(name, timelines, duration);
|
|
}
|
|
};
|
|
var BinaryInput = class {
|
|
constructor(data, strings = new Array(), index = 0, buffer = new DataView(data.buffer)) {
|
|
this.strings = strings;
|
|
this.index = index;
|
|
this.buffer = buffer;
|
|
}
|
|
readByte() {
|
|
return this.buffer.getInt8(this.index++);
|
|
}
|
|
readUnsignedByte() {
|
|
return this.buffer.getUint8(this.index++);
|
|
}
|
|
readShort() {
|
|
let value = this.buffer.getInt16(this.index);
|
|
this.index += 2;
|
|
return value;
|
|
}
|
|
readInt32() {
|
|
let value = this.buffer.getInt32(this.index);
|
|
this.index += 4;
|
|
return value;
|
|
}
|
|
readInt(optimizePositive) {
|
|
let b = this.readByte();
|
|
let result = b & 127;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 7;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 14;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 21;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 28;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return optimizePositive ? result : result >>> 1 ^ -(result & 1);
|
|
}
|
|
readStringRef() {
|
|
let index = this.readInt(true);
|
|
return index == 0 ? null : this.strings[index - 1];
|
|
}
|
|
readString() {
|
|
let byteCount = this.readInt(true);
|
|
switch (byteCount) {
|
|
case 0:
|
|
return null;
|
|
case 1:
|
|
return "";
|
|
}
|
|
byteCount--;
|
|
let chars = "";
|
|
let charCount = 0;
|
|
for (let i = 0; i < byteCount; ) {
|
|
let b = this.readUnsignedByte();
|
|
switch (b >> 4) {
|
|
case 12:
|
|
case 13:
|
|
chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63);
|
|
i += 2;
|
|
break;
|
|
case 14:
|
|
chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63);
|
|
i += 3;
|
|
break;
|
|
default:
|
|
chars += String.fromCharCode(b);
|
|
i++;
|
|
}
|
|
}
|
|
return chars;
|
|
}
|
|
readFloat() {
|
|
let value = this.buffer.getFloat32(this.index);
|
|
this.index += 4;
|
|
return value;
|
|
}
|
|
readBoolean() {
|
|
return this.readByte() != 0;
|
|
}
|
|
};
|
|
var LinkedMesh = class {
|
|
constructor(mesh, skin, slotIndex, parent, inheritDeform) {
|
|
this.mesh = mesh;
|
|
this.skin = skin;
|
|
this.slotIndex = slotIndex;
|
|
this.parent = parent;
|
|
this.inheritTimeline = inheritDeform;
|
|
}
|
|
};
|
|
var Vertices = class {
|
|
constructor(bones = null, vertices = null) {
|
|
this.bones = bones;
|
|
this.vertices = vertices;
|
|
}
|
|
};
|
|
var AttachmentType = /* @__PURE__ */ ((AttachmentType2) => {
|
|
AttachmentType2[AttachmentType2["Region"] = 0] = "Region";
|
|
AttachmentType2[AttachmentType2["BoundingBox"] = 1] = "BoundingBox";
|
|
AttachmentType2[AttachmentType2["Mesh"] = 2] = "Mesh";
|
|
AttachmentType2[AttachmentType2["LinkedMesh"] = 3] = "LinkedMesh";
|
|
AttachmentType2[AttachmentType2["Path"] = 4] = "Path";
|
|
AttachmentType2[AttachmentType2["Point"] = 5] = "Point";
|
|
AttachmentType2[AttachmentType2["Clipping"] = 6] = "Clipping";
|
|
return AttachmentType2;
|
|
})(AttachmentType || {});
|
|
function readTimeline1(input, timeline, scale) {
|
|
let time = input.readFloat(), value = input.readFloat() * scale;
|
|
for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {
|
|
timeline.setFrame(frame, time, value);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), value2 = input.readFloat() * scale;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale);
|
|
}
|
|
time = time2;
|
|
value = value2;
|
|
}
|
|
return timeline;
|
|
}
|
|
function readTimeline2(input, timeline, scale) {
|
|
let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale;
|
|
for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {
|
|
timeline.setFrame(frame, time, value1, value2);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale);
|
|
}
|
|
time = time2;
|
|
value1 = nvalue1;
|
|
value2 = nvalue2;
|
|
}
|
|
return timeline;
|
|
}
|
|
function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) {
|
|
timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2);
|
|
}
|
|
var BONE_ROTATE = 0;
|
|
var BONE_TRANSLATE = 1;
|
|
var BONE_TRANSLATEX = 2;
|
|
var BONE_TRANSLATEY = 3;
|
|
var BONE_SCALE = 4;
|
|
var BONE_SCALEX = 5;
|
|
var BONE_SCALEY = 6;
|
|
var BONE_SHEAR = 7;
|
|
var BONE_SHEARX = 8;
|
|
var BONE_SHEARY = 9;
|
|
var SLOT_ATTACHMENT = 0;
|
|
var SLOT_RGBA = 1;
|
|
var SLOT_RGB = 2;
|
|
var SLOT_RGBA2 = 3;
|
|
var SLOT_RGB2 = 4;
|
|
var SLOT_ALPHA = 5;
|
|
var ATTACHMENT_DEFORM = 0;
|
|
var ATTACHMENT_SEQUENCE = 1;
|
|
var PATH_POSITION = 0;
|
|
var PATH_SPACING = 1;
|
|
var PATH_MIX = 2;
|
|
var CURVE_STEPPED = 1;
|
|
var CURVE_BEZIER = 2;
|
|
|
|
// spine-core/src/SkeletonBounds.ts
|
|
var SkeletonBounds = class {
|
|
constructor() {
|
|
this.minX = 0;
|
|
this.minY = 0;
|
|
this.maxX = 0;
|
|
this.maxY = 0;
|
|
this.boundingBoxes = new Array();
|
|
this.polygons = new Array();
|
|
this.polygonPool = new Pool(() => {
|
|
return Utils.newFloatArray(16);
|
|
});
|
|
}
|
|
update(skeleton, updateAabb) {
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
let boundingBoxes = this.boundingBoxes;
|
|
let polygons = this.polygons;
|
|
let polygonPool = this.polygonPool;
|
|
let slots = skeleton.slots;
|
|
let slotCount = slots.length;
|
|
boundingBoxes.length = 0;
|
|
polygonPool.freeAll(polygons);
|
|
polygons.length = 0;
|
|
for (let i = 0; i < slotCount; i++) {
|
|
let slot = slots[i];
|
|
if (!slot.bone.active)
|
|
continue;
|
|
let attachment = slot.getAttachment();
|
|
if (attachment instanceof BoundingBoxAttachment) {
|
|
let boundingBox = attachment;
|
|
boundingBoxes.push(boundingBox);
|
|
let polygon = polygonPool.obtain();
|
|
if (polygon.length != boundingBox.worldVerticesLength) {
|
|
polygon = Utils.newFloatArray(boundingBox.worldVerticesLength);
|
|
}
|
|
polygons.push(polygon);
|
|
boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2);
|
|
}
|
|
}
|
|
if (updateAabb) {
|
|
this.aabbCompute();
|
|
} else {
|
|
this.minX = Number.POSITIVE_INFINITY;
|
|
this.minY = Number.POSITIVE_INFINITY;
|
|
this.maxX = Number.NEGATIVE_INFINITY;
|
|
this.maxY = Number.NEGATIVE_INFINITY;
|
|
}
|
|
}
|
|
aabbCompute() {
|
|
let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
|
|
let polygons = this.polygons;
|
|
for (let i = 0, n = polygons.length; i < n; i++) {
|
|
let polygon = polygons[i];
|
|
let vertices = polygon;
|
|
for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) {
|
|
let x = vertices[ii];
|
|
let y = vertices[ii + 1];
|
|
minX = Math.min(minX, x);
|
|
minY = Math.min(minY, y);
|
|
maxX = Math.max(maxX, x);
|
|
maxY = Math.max(maxY, y);
|
|
}
|
|
}
|
|
this.minX = minX;
|
|
this.minY = minY;
|
|
this.maxX = maxX;
|
|
this.maxY = maxY;
|
|
}
|
|
aabbContainsPoint(x, y) {
|
|
return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;
|
|
}
|
|
aabbIntersectsSegment(x1, y1, x2, y2) {
|
|
let minX = this.minX;
|
|
let minY = this.minY;
|
|
let maxX = this.maxX;
|
|
let maxY = this.maxY;
|
|
if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY)
|
|
return false;
|
|
let m = (y2 - y1) / (x2 - x1);
|
|
let y = m * (minX - x1) + y1;
|
|
if (y > minY && y < maxY)
|
|
return true;
|
|
y = m * (maxX - x1) + y1;
|
|
if (y > minY && y < maxY)
|
|
return true;
|
|
let x = (minY - y1) / m + x1;
|
|
if (x > minX && x < maxX)
|
|
return true;
|
|
x = (maxY - y1) / m + x1;
|
|
if (x > minX && x < maxX)
|
|
return true;
|
|
return false;
|
|
}
|
|
aabbIntersectsSkeleton(bounds) {
|
|
return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY;
|
|
}
|
|
containsPoint(x, y) {
|
|
let polygons = this.polygons;
|
|
for (let i = 0, n = polygons.length; i < n; i++)
|
|
if (this.containsPointPolygon(polygons[i], x, y))
|
|
return this.boundingBoxes[i];
|
|
return null;
|
|
}
|
|
containsPointPolygon(polygon, x, y) {
|
|
let vertices = polygon;
|
|
let nn = polygon.length;
|
|
let prevIndex = nn - 2;
|
|
let inside = false;
|
|
for (let ii = 0; ii < nn; ii += 2) {
|
|
let vertexY = vertices[ii + 1];
|
|
let prevY = vertices[prevIndex + 1];
|
|
if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) {
|
|
let vertexX = vertices[ii];
|
|
if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x)
|
|
inside = !inside;
|
|
}
|
|
prevIndex = ii;
|
|
}
|
|
return inside;
|
|
}
|
|
intersectsSegment(x1, y1, x2, y2) {
|
|
let polygons = this.polygons;
|
|
for (let i = 0, n = polygons.length; i < n; i++)
|
|
if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2))
|
|
return this.boundingBoxes[i];
|
|
return null;
|
|
}
|
|
intersectsSegmentPolygon(polygon, x1, y1, x2, y2) {
|
|
let vertices = polygon;
|
|
let nn = polygon.length;
|
|
let width12 = x1 - x2, height12 = y1 - y2;
|
|
let det1 = x1 * y2 - y1 * x2;
|
|
let x3 = vertices[nn - 2], y3 = vertices[nn - 1];
|
|
for (let ii = 0; ii < nn; ii += 2) {
|
|
let x4 = vertices[ii], y4 = vertices[ii + 1];
|
|
let det2 = x3 * y4 - y3 * x4;
|
|
let width34 = x3 - x4, height34 = y3 - y4;
|
|
let det3 = width12 * height34 - height12 * width34;
|
|
let x = (det1 * width34 - width12 * det2) / det3;
|
|
if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) {
|
|
let y = (det1 * height34 - height12 * det2) / det3;
|
|
if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1))
|
|
return true;
|
|
}
|
|
x3 = x4;
|
|
y3 = y4;
|
|
}
|
|
return false;
|
|
}
|
|
getPolygon(boundingBox) {
|
|
if (!boundingBox)
|
|
throw new Error("boundingBox cannot be null.");
|
|
let index = this.boundingBoxes.indexOf(boundingBox);
|
|
return index == -1 ? null : this.polygons[index];
|
|
}
|
|
getWidth() {
|
|
return this.maxX - this.minX;
|
|
}
|
|
getHeight() {
|
|
return this.maxY - this.minY;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Triangulator.ts
|
|
var Triangulator = class {
|
|
constructor() {
|
|
this.convexPolygons = new Array();
|
|
this.convexPolygonsIndices = new Array();
|
|
this.indicesArray = new Array();
|
|
this.isConcaveArray = new Array();
|
|
this.triangles = new Array();
|
|
this.polygonPool = new Pool(() => {
|
|
return new Array();
|
|
});
|
|
this.polygonIndicesPool = new Pool(() => {
|
|
return new Array();
|
|
});
|
|
}
|
|
triangulate(verticesArray) {
|
|
let vertices = verticesArray;
|
|
let vertexCount = verticesArray.length >> 1;
|
|
let indices = this.indicesArray;
|
|
indices.length = 0;
|
|
for (let i = 0; i < vertexCount; i++)
|
|
indices[i] = i;
|
|
let isConcave = this.isConcaveArray;
|
|
isConcave.length = 0;
|
|
for (let i = 0, n = vertexCount; i < n; ++i)
|
|
isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices);
|
|
let triangles = this.triangles;
|
|
triangles.length = 0;
|
|
while (vertexCount > 3) {
|
|
let previous = vertexCount - 1, i = 0, next = 1;
|
|
while (true) {
|
|
outer:
|
|
if (!isConcave[i]) {
|
|
let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
|
|
let p1x = vertices[p1], p1y = vertices[p1 + 1];
|
|
let p2x = vertices[p2], p2y = vertices[p2 + 1];
|
|
let p3x = vertices[p3], p3y = vertices[p3 + 1];
|
|
for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
|
|
if (!isConcave[ii])
|
|
continue;
|
|
let v = indices[ii] << 1;
|
|
let vx = vertices[v], vy = vertices[v + 1];
|
|
if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
|
|
if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
|
|
if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
|
|
break outer;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (next == 0) {
|
|
do {
|
|
if (!isConcave[i])
|
|
break;
|
|
i--;
|
|
} while (i > 0);
|
|
break;
|
|
}
|
|
previous = i;
|
|
i = next;
|
|
next = (next + 1) % vertexCount;
|
|
}
|
|
triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
|
|
triangles.push(indices[i]);
|
|
triangles.push(indices[(i + 1) % vertexCount]);
|
|
indices.splice(i, 1);
|
|
isConcave.splice(i, 1);
|
|
vertexCount--;
|
|
let previousIndex = (vertexCount + i - 1) % vertexCount;
|
|
let nextIndex = i == vertexCount ? 0 : i;
|
|
isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices);
|
|
isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices);
|
|
}
|
|
if (vertexCount == 3) {
|
|
triangles.push(indices[2]);
|
|
triangles.push(indices[0]);
|
|
triangles.push(indices[1]);
|
|
}
|
|
return triangles;
|
|
}
|
|
decompose(verticesArray, triangles) {
|
|
let vertices = verticesArray;
|
|
let convexPolygons = this.convexPolygons;
|
|
this.polygonPool.freeAll(convexPolygons);
|
|
convexPolygons.length = 0;
|
|
let convexPolygonsIndices = this.convexPolygonsIndices;
|
|
this.polygonIndicesPool.freeAll(convexPolygonsIndices);
|
|
convexPolygonsIndices.length = 0;
|
|
let polygonIndices = this.polygonIndicesPool.obtain();
|
|
polygonIndices.length = 0;
|
|
let polygon = this.polygonPool.obtain();
|
|
polygon.length = 0;
|
|
let fanBaseIndex = -1, lastWinding = 0;
|
|
for (let i = 0, n = triangles.length; i < n; i += 3) {
|
|
let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
|
|
let x1 = vertices[t1], y1 = vertices[t1 + 1];
|
|
let x2 = vertices[t2], y2 = vertices[t2 + 1];
|
|
let x3 = vertices[t3], y3 = vertices[t3 + 1];
|
|
let merged = false;
|
|
if (fanBaseIndex == t1) {
|
|
let o = polygon.length - 4;
|
|
let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
|
|
let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
|
|
if (winding1 == lastWinding && winding2 == lastWinding) {
|
|
polygon.push(x3);
|
|
polygon.push(y3);
|
|
polygonIndices.push(t3);
|
|
merged = true;
|
|
}
|
|
}
|
|
if (!merged) {
|
|
if (polygon.length > 0) {
|
|
convexPolygons.push(polygon);
|
|
convexPolygonsIndices.push(polygonIndices);
|
|
} else {
|
|
this.polygonPool.free(polygon);
|
|
this.polygonIndicesPool.free(polygonIndices);
|
|
}
|
|
polygon = this.polygonPool.obtain();
|
|
polygon.length = 0;
|
|
polygon.push(x1);
|
|
polygon.push(y1);
|
|
polygon.push(x2);
|
|
polygon.push(y2);
|
|
polygon.push(x3);
|
|
polygon.push(y3);
|
|
polygonIndices = this.polygonIndicesPool.obtain();
|
|
polygonIndices.length = 0;
|
|
polygonIndices.push(t1);
|
|
polygonIndices.push(t2);
|
|
polygonIndices.push(t3);
|
|
lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3);
|
|
fanBaseIndex = t1;
|
|
}
|
|
}
|
|
if (polygon.length > 0) {
|
|
convexPolygons.push(polygon);
|
|
convexPolygonsIndices.push(polygonIndices);
|
|
}
|
|
for (let i = 0, n = convexPolygons.length; i < n; i++) {
|
|
polygonIndices = convexPolygonsIndices[i];
|
|
if (polygonIndices.length == 0)
|
|
continue;
|
|
let firstIndex = polygonIndices[0];
|
|
let lastIndex = polygonIndices[polygonIndices.length - 1];
|
|
polygon = convexPolygons[i];
|
|
let o = polygon.length - 4;
|
|
let prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
|
|
let prevX = polygon[o + 2], prevY = polygon[o + 3];
|
|
let firstX = polygon[0], firstY = polygon[1];
|
|
let secondX = polygon[2], secondY = polygon[3];
|
|
let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
|
|
for (let ii = 0; ii < n; ii++) {
|
|
if (ii == i)
|
|
continue;
|
|
let otherIndices = convexPolygonsIndices[ii];
|
|
if (otherIndices.length != 3)
|
|
continue;
|
|
let otherFirstIndex = otherIndices[0];
|
|
let otherSecondIndex = otherIndices[1];
|
|
let otherLastIndex = otherIndices[2];
|
|
let otherPoly = convexPolygons[ii];
|
|
let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
|
|
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
|
|
continue;
|
|
let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
|
|
let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY);
|
|
if (winding1 == winding && winding2 == winding) {
|
|
otherPoly.length = 0;
|
|
otherIndices.length = 0;
|
|
polygon.push(x3);
|
|
polygon.push(y3);
|
|
polygonIndices.push(otherLastIndex);
|
|
prevPrevX = prevX;
|
|
prevPrevY = prevY;
|
|
prevX = x3;
|
|
prevY = y3;
|
|
ii = 0;
|
|
}
|
|
}
|
|
}
|
|
for (let i = convexPolygons.length - 1; i >= 0; i--) {
|
|
polygon = convexPolygons[i];
|
|
if (polygon.length == 0) {
|
|
convexPolygons.splice(i, 1);
|
|
this.polygonPool.free(polygon);
|
|
polygonIndices = convexPolygonsIndices[i];
|
|
convexPolygonsIndices.splice(i, 1);
|
|
this.polygonIndicesPool.free(polygonIndices);
|
|
}
|
|
}
|
|
return convexPolygons;
|
|
}
|
|
static isConcave(index, vertexCount, vertices, indices) {
|
|
let previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
|
|
let current = indices[index] << 1;
|
|
let next = indices[(index + 1) % vertexCount] << 1;
|
|
return !this.positiveArea(
|
|
vertices[previous],
|
|
vertices[previous + 1],
|
|
vertices[current],
|
|
vertices[current + 1],
|
|
vertices[next],
|
|
vertices[next + 1]
|
|
);
|
|
}
|
|
static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) {
|
|
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
|
|
}
|
|
static winding(p1x, p1y, p2x, p2y, p3x, p3y) {
|
|
let px = p2x - p1x, py = p2y - p1y;
|
|
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SkeletonClipping.ts
|
|
var SkeletonClipping = class {
|
|
constructor() {
|
|
this.triangulator = new Triangulator();
|
|
this.clippingPolygon = new Array();
|
|
this.clipOutput = new Array();
|
|
this.clippedVertices = new Array();
|
|
this.clippedTriangles = new Array();
|
|
this.scratch = new Array();
|
|
this.clipAttachment = null;
|
|
this.clippingPolygons = null;
|
|
}
|
|
clipStart(slot, clip) {
|
|
if (this.clipAttachment)
|
|
return 0;
|
|
this.clipAttachment = clip;
|
|
let n = clip.worldVerticesLength;
|
|
let vertices = Utils.setArraySize(this.clippingPolygon, n);
|
|
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
|
|
let clippingPolygon = this.clippingPolygon;
|
|
SkeletonClipping.makeClockwise(clippingPolygon);
|
|
let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));
|
|
for (let i = 0, n2 = clippingPolygons.length; i < n2; i++) {
|
|
let polygon = clippingPolygons[i];
|
|
SkeletonClipping.makeClockwise(polygon);
|
|
polygon.push(polygon[0]);
|
|
polygon.push(polygon[1]);
|
|
}
|
|
return clippingPolygons.length;
|
|
}
|
|
clipEndWithSlot(slot) {
|
|
if (this.clipAttachment && this.clipAttachment.endSlot == slot.data)
|
|
this.clipEnd();
|
|
}
|
|
clipEnd() {
|
|
if (!this.clipAttachment)
|
|
return;
|
|
this.clipAttachment = null;
|
|
this.clippingPolygons = null;
|
|
this.clippedVertices.length = 0;
|
|
this.clippedTriangles.length = 0;
|
|
this.clippingPolygon.length = 0;
|
|
}
|
|
isClipping() {
|
|
return this.clipAttachment != null;
|
|
}
|
|
clipTriangles(vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
|
|
let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
|
|
let clippedTriangles = this.clippedTriangles;
|
|
let polygons = this.clippingPolygons;
|
|
let polygonsCount = polygons.length;
|
|
let vertexSize = twoColor ? 12 : 8;
|
|
let index = 0;
|
|
clippedVertices.length = 0;
|
|
clippedTriangles.length = 0;
|
|
outer:
|
|
for (let i = 0; i < trianglesLength; i += 3) {
|
|
let vertexOffset = triangles[i] << 1;
|
|
let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
|
|
let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
|
|
vertexOffset = triangles[i + 1] << 1;
|
|
let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
|
|
let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
|
|
vertexOffset = triangles[i + 2] << 1;
|
|
let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
|
|
let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
|
|
for (let p = 0; p < polygonsCount; p++) {
|
|
let s = clippedVertices.length;
|
|
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
|
|
let clipOutputLength = clipOutput.length;
|
|
if (clipOutputLength == 0)
|
|
continue;
|
|
let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
|
|
let d = 1 / (d0 * d2 + d1 * (y1 - y3));
|
|
let clipOutputCount = clipOutputLength >> 1;
|
|
let clipOutputItems = this.clipOutput;
|
|
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
|
|
for (let ii = 0; ii < clipOutputLength; ii += 2) {
|
|
let x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
|
|
clippedVerticesItems[s] = x;
|
|
clippedVerticesItems[s + 1] = y;
|
|
clippedVerticesItems[s + 2] = light.r;
|
|
clippedVerticesItems[s + 3] = light.g;
|
|
clippedVerticesItems[s + 4] = light.b;
|
|
clippedVerticesItems[s + 5] = light.a;
|
|
let c0 = x - x3, c1 = y - y3;
|
|
let a = (d0 * c0 + d1 * c1) * d;
|
|
let b = (d4 * c0 + d2 * c1) * d;
|
|
let c = 1 - a - b;
|
|
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
|
|
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
|
|
if (twoColor) {
|
|
clippedVerticesItems[s + 8] = dark.r;
|
|
clippedVerticesItems[s + 9] = dark.g;
|
|
clippedVerticesItems[s + 10] = dark.b;
|
|
clippedVerticesItems[s + 11] = dark.a;
|
|
}
|
|
s += vertexSize;
|
|
}
|
|
s = clippedTriangles.length;
|
|
let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
|
|
clipOutputCount--;
|
|
for (let ii = 1; ii < clipOutputCount; ii++) {
|
|
clippedTrianglesItems[s] = index;
|
|
clippedTrianglesItems[s + 1] = index + ii;
|
|
clippedTrianglesItems[s + 2] = index + ii + 1;
|
|
s += 3;
|
|
}
|
|
index += clipOutputCount + 1;
|
|
} else {
|
|
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
|
|
clippedVerticesItems[s] = x1;
|
|
clippedVerticesItems[s + 1] = y1;
|
|
clippedVerticesItems[s + 2] = light.r;
|
|
clippedVerticesItems[s + 3] = light.g;
|
|
clippedVerticesItems[s + 4] = light.b;
|
|
clippedVerticesItems[s + 5] = light.a;
|
|
if (!twoColor) {
|
|
clippedVerticesItems[s + 6] = u1;
|
|
clippedVerticesItems[s + 7] = v1;
|
|
clippedVerticesItems[s + 8] = x2;
|
|
clippedVerticesItems[s + 9] = y2;
|
|
clippedVerticesItems[s + 10] = light.r;
|
|
clippedVerticesItems[s + 11] = light.g;
|
|
clippedVerticesItems[s + 12] = light.b;
|
|
clippedVerticesItems[s + 13] = light.a;
|
|
clippedVerticesItems[s + 14] = u2;
|
|
clippedVerticesItems[s + 15] = v2;
|
|
clippedVerticesItems[s + 16] = x3;
|
|
clippedVerticesItems[s + 17] = y3;
|
|
clippedVerticesItems[s + 18] = light.r;
|
|
clippedVerticesItems[s + 19] = light.g;
|
|
clippedVerticesItems[s + 20] = light.b;
|
|
clippedVerticesItems[s + 21] = light.a;
|
|
clippedVerticesItems[s + 22] = u3;
|
|
clippedVerticesItems[s + 23] = v3;
|
|
} else {
|
|
clippedVerticesItems[s + 6] = u1;
|
|
clippedVerticesItems[s + 7] = v1;
|
|
clippedVerticesItems[s + 8] = dark.r;
|
|
clippedVerticesItems[s + 9] = dark.g;
|
|
clippedVerticesItems[s + 10] = dark.b;
|
|
clippedVerticesItems[s + 11] = dark.a;
|
|
clippedVerticesItems[s + 12] = x2;
|
|
clippedVerticesItems[s + 13] = y2;
|
|
clippedVerticesItems[s + 14] = light.r;
|
|
clippedVerticesItems[s + 15] = light.g;
|
|
clippedVerticesItems[s + 16] = light.b;
|
|
clippedVerticesItems[s + 17] = light.a;
|
|
clippedVerticesItems[s + 18] = u2;
|
|
clippedVerticesItems[s + 19] = v2;
|
|
clippedVerticesItems[s + 20] = dark.r;
|
|
clippedVerticesItems[s + 21] = dark.g;
|
|
clippedVerticesItems[s + 22] = dark.b;
|
|
clippedVerticesItems[s + 23] = dark.a;
|
|
clippedVerticesItems[s + 24] = x3;
|
|
clippedVerticesItems[s + 25] = y3;
|
|
clippedVerticesItems[s + 26] = light.r;
|
|
clippedVerticesItems[s + 27] = light.g;
|
|
clippedVerticesItems[s + 28] = light.b;
|
|
clippedVerticesItems[s + 29] = light.a;
|
|
clippedVerticesItems[s + 30] = u3;
|
|
clippedVerticesItems[s + 31] = v3;
|
|
clippedVerticesItems[s + 32] = dark.r;
|
|
clippedVerticesItems[s + 33] = dark.g;
|
|
clippedVerticesItems[s + 34] = dark.b;
|
|
clippedVerticesItems[s + 35] = dark.a;
|
|
}
|
|
s = clippedTriangles.length;
|
|
let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);
|
|
clippedTrianglesItems[s] = index;
|
|
clippedTrianglesItems[s + 1] = index + 1;
|
|
clippedTrianglesItems[s + 2] = index + 2;
|
|
index += 3;
|
|
continue outer;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
clip(x1, y1, x2, y2, x3, y3, clippingArea, output) {
|
|
let originalOutput = output;
|
|
let clipped = false;
|
|
let input;
|
|
if (clippingArea.length % 4 >= 2) {
|
|
input = output;
|
|
output = this.scratch;
|
|
} else
|
|
input = this.scratch;
|
|
input.length = 0;
|
|
input.push(x1);
|
|
input.push(y1);
|
|
input.push(x2);
|
|
input.push(y2);
|
|
input.push(x3);
|
|
input.push(y3);
|
|
input.push(x1);
|
|
input.push(y1);
|
|
output.length = 0;
|
|
let clippingVertices = clippingArea;
|
|
let clippingVerticesLast = clippingArea.length - 4;
|
|
for (let i = 0; ; i += 2) {
|
|
let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
|
|
let edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
|
|
let deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
|
|
let inputVertices = input;
|
|
let inputVerticesLength = input.length - 2, outputStart = output.length;
|
|
for (let ii = 0; ii < inputVerticesLength; ii += 2) {
|
|
let inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
|
|
let inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
|
|
let side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
|
|
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
|
|
if (side2) {
|
|
output.push(inputX2);
|
|
output.push(inputY2);
|
|
continue;
|
|
}
|
|
let c0 = inputY2 - inputY, c2 = inputX2 - inputX;
|
|
let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
|
|
if (Math.abs(s) > 1e-6) {
|
|
let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
|
|
output.push(edgeX + (edgeX2 - edgeX) * ua);
|
|
output.push(edgeY + (edgeY2 - edgeY) * ua);
|
|
} else {
|
|
output.push(edgeX);
|
|
output.push(edgeY);
|
|
}
|
|
} else if (side2) {
|
|
let c0 = inputY2 - inputY, c2 = inputX2 - inputX;
|
|
let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
|
|
if (Math.abs(s) > 1e-6) {
|
|
let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
|
|
output.push(edgeX + (edgeX2 - edgeX) * ua);
|
|
output.push(edgeY + (edgeY2 - edgeY) * ua);
|
|
} else {
|
|
output.push(edgeX);
|
|
output.push(edgeY);
|
|
}
|
|
output.push(inputX2);
|
|
output.push(inputY2);
|
|
}
|
|
clipped = true;
|
|
}
|
|
if (outputStart == output.length) {
|
|
originalOutput.length = 0;
|
|
return true;
|
|
}
|
|
output.push(output[0]);
|
|
output.push(output[1]);
|
|
if (i == clippingVerticesLast)
|
|
break;
|
|
let temp = output;
|
|
output = input;
|
|
output.length = 0;
|
|
input = temp;
|
|
}
|
|
if (originalOutput != output) {
|
|
originalOutput.length = 0;
|
|
for (let i = 0, n = output.length - 2; i < n; i++)
|
|
originalOutput[i] = output[i];
|
|
} else
|
|
originalOutput.length = originalOutput.length - 2;
|
|
return clipped;
|
|
}
|
|
static makeClockwise(polygon) {
|
|
let vertices = polygon;
|
|
let verticeslength = polygon.length;
|
|
let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
|
|
for (let i = 0, n = verticeslength - 3; i < n; i += 2) {
|
|
p1x = vertices[i];
|
|
p1y = vertices[i + 1];
|
|
p2x = vertices[i + 2];
|
|
p2y = vertices[i + 3];
|
|
area += p1x * p2y - p2x * p1y;
|
|
}
|
|
if (area < 0)
|
|
return;
|
|
for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
|
|
let x = vertices[i], y = vertices[i + 1];
|
|
let other = lastX - i;
|
|
vertices[i] = vertices[other];
|
|
vertices[i + 1] = vertices[other + 1];
|
|
vertices[other] = x;
|
|
vertices[other + 1] = y;
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SkeletonJson.ts
|
|
var SkeletonJson = class {
|
|
constructor(attachmentLoader) {
|
|
this.scale = 1;
|
|
this.linkedMeshes = new Array();
|
|
this.attachmentLoader = attachmentLoader;
|
|
}
|
|
readSkeletonData(json) {
|
|
let scale = this.scale;
|
|
let skeletonData = new SkeletonData();
|
|
let root = typeof json === "string" ? JSON.parse(json) : json;
|
|
let skeletonMap = root.skeleton;
|
|
if (skeletonMap) {
|
|
skeletonData.hash = skeletonMap.hash;
|
|
skeletonData.version = skeletonMap.spine;
|
|
skeletonData.x = skeletonMap.x;
|
|
skeletonData.y = skeletonMap.y;
|
|
skeletonData.width = skeletonMap.width;
|
|
skeletonData.height = skeletonMap.height;
|
|
skeletonData.fps = skeletonMap.fps;
|
|
skeletonData.imagesPath = skeletonMap.images;
|
|
}
|
|
if (root.bones) {
|
|
for (let i = 0; i < root.bones.length; i++) {
|
|
let boneMap = root.bones[i];
|
|
let parent = null;
|
|
let parentName = getValue(boneMap, "parent", null);
|
|
if (parentName)
|
|
parent = skeletonData.findBone(parentName);
|
|
let data = new BoneData(skeletonData.bones.length, boneMap.name, parent);
|
|
data.length = getValue(boneMap, "length", 0) * scale;
|
|
data.x = getValue(boneMap, "x", 0) * scale;
|
|
data.y = getValue(boneMap, "y", 0) * scale;
|
|
data.rotation = getValue(boneMap, "rotation", 0);
|
|
data.scaleX = getValue(boneMap, "scaleX", 1);
|
|
data.scaleY = getValue(boneMap, "scaleY", 1);
|
|
data.shearX = getValue(boneMap, "shearX", 0);
|
|
data.shearY = getValue(boneMap, "shearY", 0);
|
|
data.transformMode = Utils.enumValue(TransformMode, getValue(boneMap, "transform", "Normal"));
|
|
data.skinRequired = getValue(boneMap, "skin", false);
|
|
let color = getValue(boneMap, "color", null);
|
|
if (color)
|
|
data.color.setFromString(color);
|
|
skeletonData.bones.push(data);
|
|
}
|
|
}
|
|
if (root.slots) {
|
|
for (let i = 0; i < root.slots.length; i++) {
|
|
let slotMap = root.slots[i];
|
|
let boneData = skeletonData.findBone(slotMap.bone);
|
|
if (!boneData)
|
|
throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotMap.name}`);
|
|
let data = new SlotData(skeletonData.slots.length, slotMap.name, boneData);
|
|
let color = getValue(slotMap, "color", null);
|
|
if (color)
|
|
data.color.setFromString(color);
|
|
let dark = getValue(slotMap, "dark", null);
|
|
if (dark)
|
|
data.darkColor = Color.fromString(dark);
|
|
data.attachmentName = getValue(slotMap, "attachment", null);
|
|
data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal"));
|
|
skeletonData.slots.push(data);
|
|
}
|
|
}
|
|
if (root.ik) {
|
|
for (let i = 0; i < root.ik.length; i++) {
|
|
let constraintMap = root.ik[i];
|
|
let data = new IkConstraintData(constraintMap.name);
|
|
data.order = getValue(constraintMap, "order", 0);
|
|
data.skinRequired = getValue(constraintMap, "skin", false);
|
|
for (let ii = 0; ii < constraintMap.bones.length; ii++) {
|
|
let bone = skeletonData.findBone(constraintMap.bones[ii]);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`);
|
|
data.bones.push(bone);
|
|
}
|
|
let target = skeletonData.findBone(constraintMap.target);
|
|
;
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`);
|
|
data.target = target;
|
|
data.mix = getValue(constraintMap, "mix", 1);
|
|
data.softness = getValue(constraintMap, "softness", 0) * scale;
|
|
data.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1;
|
|
data.compress = getValue(constraintMap, "compress", false);
|
|
data.stretch = getValue(constraintMap, "stretch", false);
|
|
data.uniform = getValue(constraintMap, "uniform", false);
|
|
skeletonData.ikConstraints.push(data);
|
|
}
|
|
}
|
|
if (root.transform) {
|
|
for (let i = 0; i < root.transform.length; i++) {
|
|
let constraintMap = root.transform[i];
|
|
let data = new TransformConstraintData(constraintMap.name);
|
|
data.order = getValue(constraintMap, "order", 0);
|
|
data.skinRequired = getValue(constraintMap, "skin", false);
|
|
for (let ii = 0; ii < constraintMap.bones.length; ii++) {
|
|
let boneName = constraintMap.bones[ii];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`);
|
|
data.bones.push(bone);
|
|
}
|
|
let targetName = constraintMap.target;
|
|
let target = skeletonData.findBone(targetName);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`);
|
|
data.target = target;
|
|
data.local = getValue(constraintMap, "local", false);
|
|
data.relative = getValue(constraintMap, "relative", false);
|
|
data.offsetRotation = getValue(constraintMap, "rotation", 0);
|
|
data.offsetX = getValue(constraintMap, "x", 0) * scale;
|
|
data.offsetY = getValue(constraintMap, "y", 0) * scale;
|
|
data.offsetScaleX = getValue(constraintMap, "scaleX", 0);
|
|
data.offsetScaleY = getValue(constraintMap, "scaleY", 0);
|
|
data.offsetShearY = getValue(constraintMap, "shearY", 0);
|
|
data.mixRotate = getValue(constraintMap, "mixRotate", 1);
|
|
data.mixX = getValue(constraintMap, "mixX", 1);
|
|
data.mixY = getValue(constraintMap, "mixY", data.mixX);
|
|
data.mixScaleX = getValue(constraintMap, "mixScaleX", 1);
|
|
data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX);
|
|
data.mixShearY = getValue(constraintMap, "mixShearY", 1);
|
|
skeletonData.transformConstraints.push(data);
|
|
}
|
|
}
|
|
if (root.path) {
|
|
for (let i = 0; i < root.path.length; i++) {
|
|
let constraintMap = root.path[i];
|
|
let data = new PathConstraintData(constraintMap.name);
|
|
data.order = getValue(constraintMap, "order", 0);
|
|
data.skinRequired = getValue(constraintMap, "skin", false);
|
|
for (let ii = 0; ii < constraintMap.bones.length; ii++) {
|
|
let boneName = constraintMap.bones[ii];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`);
|
|
data.bones.push(bone);
|
|
}
|
|
let targetName = constraintMap.target;
|
|
let target = skeletonData.findSlot(targetName);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`);
|
|
data.target = target;
|
|
data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent"));
|
|
data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length"));
|
|
data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent"));
|
|
data.offsetRotation = getValue(constraintMap, "rotation", 0);
|
|
data.position = getValue(constraintMap, "position", 0);
|
|
if (data.positionMode == 0 /* Fixed */)
|
|
data.position *= scale;
|
|
data.spacing = getValue(constraintMap, "spacing", 0);
|
|
if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */)
|
|
data.spacing *= scale;
|
|
data.mixRotate = getValue(constraintMap, "mixRotate", 1);
|
|
data.mixX = getValue(constraintMap, "mixX", 1);
|
|
data.mixY = getValue(constraintMap, "mixY", data.mixX);
|
|
skeletonData.pathConstraints.push(data);
|
|
}
|
|
}
|
|
if (root.skins) {
|
|
for (let i = 0; i < root.skins.length; i++) {
|
|
let skinMap = root.skins[i];
|
|
let skin = new Skin(skinMap.name);
|
|
if (skinMap.bones) {
|
|
for (let ii = 0; ii < skinMap.bones.length; ii++) {
|
|
let boneName = skinMap.bones[ii];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`);
|
|
skin.bones.push(bone);
|
|
}
|
|
}
|
|
if (skinMap.ik) {
|
|
for (let ii = 0; ii < skinMap.ik.length; ii++) {
|
|
let constraintName = skinMap.ik[ii];
|
|
let constraint = skeletonData.findIkConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`);
|
|
skin.constraints.push(constraint);
|
|
}
|
|
}
|
|
if (skinMap.transform) {
|
|
for (let ii = 0; ii < skinMap.transform.length; ii++) {
|
|
let constraintName = skinMap.transform[ii];
|
|
let constraint = skeletonData.findTransformConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`);
|
|
skin.constraints.push(constraint);
|
|
}
|
|
}
|
|
if (skinMap.path) {
|
|
for (let ii = 0; ii < skinMap.path.length; ii++) {
|
|
let constraintName = skinMap.path[ii];
|
|
let constraint = skeletonData.findPathConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`);
|
|
skin.constraints.push(constraint);
|
|
}
|
|
}
|
|
for (let slotName in skinMap.attachments) {
|
|
let slot = skeletonData.findSlot(slotName);
|
|
if (!slot)
|
|
throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`);
|
|
let slotMap = skinMap.attachments[slotName];
|
|
for (let entryName in slotMap) {
|
|
let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData);
|
|
if (attachment)
|
|
skin.setAttachment(slot.index, entryName, attachment);
|
|
}
|
|
}
|
|
skeletonData.skins.push(skin);
|
|
if (skin.name == "default")
|
|
skeletonData.defaultSkin = skin;
|
|
}
|
|
}
|
|
for (let i = 0, n = this.linkedMeshes.length; i < n; i++) {
|
|
let linkedMesh = this.linkedMeshes[i];
|
|
let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
|
if (!skin)
|
|
throw new Error(`Skin not found: ${linkedMesh.skin}`);
|
|
let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
|
if (!parent)
|
|
throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);
|
|
linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh;
|
|
linkedMesh.mesh.setParentMesh(parent);
|
|
if (linkedMesh.mesh.region != null)
|
|
linkedMesh.mesh.updateRegion();
|
|
}
|
|
this.linkedMeshes.length = 0;
|
|
if (root.events) {
|
|
for (let eventName in root.events) {
|
|
let eventMap = root.events[eventName];
|
|
let data = new EventData(eventName);
|
|
data.intValue = getValue(eventMap, "int", 0);
|
|
data.floatValue = getValue(eventMap, "float", 0);
|
|
data.stringValue = getValue(eventMap, "string", "");
|
|
data.audioPath = getValue(eventMap, "audio", null);
|
|
if (data.audioPath) {
|
|
data.volume = getValue(eventMap, "volume", 1);
|
|
data.balance = getValue(eventMap, "balance", 0);
|
|
}
|
|
skeletonData.events.push(data);
|
|
}
|
|
}
|
|
if (root.animations) {
|
|
for (let animationName in root.animations) {
|
|
let animationMap = root.animations[animationName];
|
|
this.readAnimation(animationMap, animationName, skeletonData);
|
|
}
|
|
}
|
|
return skeletonData;
|
|
}
|
|
readAttachment(map, skin, slotIndex, name, skeletonData) {
|
|
let scale = this.scale;
|
|
name = getValue(map, "name", name);
|
|
switch (getValue(map, "type", "region")) {
|
|
case "region": {
|
|
let path = getValue(map, "path", name);
|
|
let sequence = this.readSequence(getValue(map, "sequence", null));
|
|
let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);
|
|
if (!region)
|
|
return null;
|
|
region.path = path;
|
|
region.x = getValue(map, "x", 0) * scale;
|
|
region.y = getValue(map, "y", 0) * scale;
|
|
region.scaleX = getValue(map, "scaleX", 1);
|
|
region.scaleY = getValue(map, "scaleY", 1);
|
|
region.rotation = getValue(map, "rotation", 0);
|
|
region.width = map.width * scale;
|
|
region.height = map.height * scale;
|
|
region.sequence = sequence;
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
region.color.setFromString(color);
|
|
if (region.region != null)
|
|
region.updateRegion();
|
|
return region;
|
|
}
|
|
case "boundingbox": {
|
|
let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);
|
|
if (!box)
|
|
return null;
|
|
this.readVertices(map, box, map.vertexCount << 1);
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
box.color.setFromString(color);
|
|
return box;
|
|
}
|
|
case "mesh":
|
|
case "linkedmesh": {
|
|
let path = getValue(map, "path", name);
|
|
let sequence = this.readSequence(getValue(map, "sequence", null));
|
|
let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
|
if (!mesh)
|
|
return null;
|
|
mesh.path = path;
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
mesh.color.setFromString(color);
|
|
mesh.width = getValue(map, "width", 0) * scale;
|
|
mesh.height = getValue(map, "height", 0) * scale;
|
|
mesh.sequence = sequence;
|
|
let parent = getValue(map, "parent", null);
|
|
if (parent) {
|
|
this.linkedMeshes.push(new LinkedMesh2(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "timelines", true)));
|
|
return mesh;
|
|
}
|
|
let uvs = map.uvs;
|
|
this.readVertices(map, mesh, uvs.length);
|
|
mesh.triangles = map.triangles;
|
|
mesh.regionUVs = uvs;
|
|
if (mesh.region != null)
|
|
mesh.updateRegion();
|
|
mesh.edges = getValue(map, "edges", null);
|
|
mesh.hullLength = getValue(map, "hull", 0) * 2;
|
|
return mesh;
|
|
}
|
|
case "path": {
|
|
let path = this.attachmentLoader.newPathAttachment(skin, name);
|
|
if (!path)
|
|
return null;
|
|
path.closed = getValue(map, "closed", false);
|
|
path.constantSpeed = getValue(map, "constantSpeed", true);
|
|
let vertexCount = map.vertexCount;
|
|
this.readVertices(map, path, vertexCount << 1);
|
|
let lengths = Utils.newArray(vertexCount / 3, 0);
|
|
for (let i = 0; i < map.lengths.length; i++)
|
|
lengths[i] = map.lengths[i] * scale;
|
|
path.lengths = lengths;
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
path.color.setFromString(color);
|
|
return path;
|
|
}
|
|
case "point": {
|
|
let point = this.attachmentLoader.newPointAttachment(skin, name);
|
|
if (!point)
|
|
return null;
|
|
point.x = getValue(map, "x", 0) * scale;
|
|
point.y = getValue(map, "y", 0) * scale;
|
|
point.rotation = getValue(map, "rotation", 0);
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
point.color.setFromString(color);
|
|
return point;
|
|
}
|
|
case "clipping": {
|
|
let clip = this.attachmentLoader.newClippingAttachment(skin, name);
|
|
if (!clip)
|
|
return null;
|
|
let end = getValue(map, "end", null);
|
|
if (end)
|
|
clip.endSlot = skeletonData.findSlot(end);
|
|
let vertexCount = map.vertexCount;
|
|
this.readVertices(map, clip, vertexCount << 1);
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
clip.color.setFromString(color);
|
|
return clip;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
readSequence(map) {
|
|
if (map == null)
|
|
return null;
|
|
let sequence = new Sequence(getValue(map, "count", 0));
|
|
sequence.start = getValue(map, "start", 1);
|
|
sequence.digits = getValue(map, "digits", 0);
|
|
sequence.setupIndex = getValue(map, "setup", 0);
|
|
return sequence;
|
|
}
|
|
readVertices(map, attachment, verticesLength) {
|
|
let scale = this.scale;
|
|
attachment.worldVerticesLength = verticesLength;
|
|
let vertices = map.vertices;
|
|
if (verticesLength == vertices.length) {
|
|
let scaledVertices = Utils.toFloatArray(vertices);
|
|
if (scale != 1) {
|
|
for (let i = 0, n = vertices.length; i < n; i++)
|
|
scaledVertices[i] *= scale;
|
|
}
|
|
attachment.vertices = scaledVertices;
|
|
return;
|
|
}
|
|
let weights = new Array();
|
|
let bones = new Array();
|
|
for (let i = 0, n = vertices.length; i < n; ) {
|
|
let boneCount = vertices[i++];
|
|
bones.push(boneCount);
|
|
for (let nn = i + boneCount * 4; i < nn; i += 4) {
|
|
bones.push(vertices[i]);
|
|
weights.push(vertices[i + 1] * scale);
|
|
weights.push(vertices[i + 2] * scale);
|
|
weights.push(vertices[i + 3]);
|
|
}
|
|
}
|
|
attachment.bones = bones;
|
|
attachment.vertices = Utils.toFloatArray(weights);
|
|
}
|
|
readAnimation(map, name, skeletonData) {
|
|
let scale = this.scale;
|
|
let timelines = new Array();
|
|
if (map.slots) {
|
|
for (let slotName in map.slots) {
|
|
let slotMap = map.slots[slotName];
|
|
let slot = skeletonData.findSlot(slotName);
|
|
if (!slot)
|
|
throw new Error("Slot not found: " + slotName);
|
|
let slotIndex = slot.index;
|
|
for (let timelineName in slotMap) {
|
|
let timelineMap = slotMap[timelineName];
|
|
if (!timelineMap)
|
|
continue;
|
|
let frames = timelineMap.length;
|
|
if (timelineName == "attachment") {
|
|
let timeline = new AttachmentTimeline(frames, slotIndex);
|
|
for (let frame = 0; frame < frames; frame++) {
|
|
let keyMap = timelineMap[frame];
|
|
timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null));
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "rgba") {
|
|
let timeline = new RGBATimeline(frames, frames << 2, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.color);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b, color.a);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.color);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "rgb") {
|
|
let timeline = new RGBTimeline(frames, frames * 3, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.color);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.color);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "alpha") {
|
|
timelines.push(readTimeline12(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1));
|
|
} else if (timelineName == "rgba2") {
|
|
let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.light);
|
|
let color2 = Color.fromString(keyMap.dark);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.light);
|
|
let newColor2 = Color.fromString(nextMap.dark);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
color2 = newColor2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "rgb2") {
|
|
let timeline = new RGB2Timeline(frames, frames * 6, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.light);
|
|
let color2 = Color.fromString(keyMap.dark);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.light);
|
|
let newColor2 = Color.fromString(nextMap.dark);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
color2 = newColor2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.bones) {
|
|
for (let boneName in map.bones) {
|
|
let boneMap = map.bones[boneName];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error("Bone not found: " + boneName);
|
|
let boneIndex = bone.index;
|
|
for (let timelineName in boneMap) {
|
|
let timelineMap = boneMap[timelineName];
|
|
let frames = timelineMap.length;
|
|
if (frames == 0)
|
|
continue;
|
|
if (timelineName === "rotate") {
|
|
timelines.push(readTimeline12(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1));
|
|
} else if (timelineName === "translate") {
|
|
let timeline = new TranslateTimeline(frames, frames << 1, boneIndex);
|
|
timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, scale));
|
|
} else if (timelineName === "translatex") {
|
|
let timeline = new TranslateXTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, scale));
|
|
} else if (timelineName === "translatey") {
|
|
let timeline = new TranslateYTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, scale));
|
|
} else if (timelineName === "scale") {
|
|
let timeline = new ScaleTimeline(frames, frames << 1, boneIndex);
|
|
timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 1, 1));
|
|
} else if (timelineName === "scalex") {
|
|
let timeline = new ScaleXTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 1, 1));
|
|
} else if (timelineName === "scaley") {
|
|
let timeline = new ScaleYTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 1, 1));
|
|
} else if (timelineName === "shear") {
|
|
let timeline = new ShearTimeline(frames, frames << 1, boneIndex);
|
|
timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, 1));
|
|
} else if (timelineName === "shearx") {
|
|
let timeline = new ShearXTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, 1));
|
|
} else if (timelineName === "sheary") {
|
|
let timeline = new ShearYTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, 1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.ik) {
|
|
for (let constraintName in map.ik) {
|
|
let constraintMap = map.ik[constraintName];
|
|
let keyMap = constraintMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
let constraint = skeletonData.findIkConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error("IK Constraint not found: " + constraintName);
|
|
let constraintIndex = skeletonData.ikConstraints.indexOf(constraint);
|
|
let timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mix = getValue(keyMap, "mix", 1);
|
|
let softness = getValue(keyMap, "softness", 0) * scale;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false));
|
|
let nextMap = constraintMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let mix2 = getValue(nextMap, "mix", 1);
|
|
let softness2 = getValue(nextMap, "softness", 0) * scale;
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale);
|
|
}
|
|
time = time2;
|
|
mix = mix2;
|
|
softness = softness2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
if (map.transform) {
|
|
for (let constraintName in map.transform) {
|
|
let timelineMap = map.transform[constraintName];
|
|
let keyMap = timelineMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
let constraint = skeletonData.findTransformConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error("Transform constraint not found: " + constraintName);
|
|
let constraintIndex = skeletonData.transformConstraints.indexOf(constraint);
|
|
let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mixRotate = getValue(keyMap, "mixRotate", 1);
|
|
let mixX = getValue(keyMap, "mixX", 1);
|
|
let mixY = getValue(keyMap, "mixY", mixX);
|
|
let mixScaleX = getValue(keyMap, "mixScaleX", 1);
|
|
let mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX);
|
|
let mixShearY = getValue(keyMap, "mixShearY", 1);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let mixRotate2 = getValue(nextMap, "mixRotate", 1);
|
|
let mixX2 = getValue(nextMap, "mixX", 1);
|
|
let mixY2 = getValue(nextMap, "mixY", mixX2);
|
|
let mixScaleX2 = getValue(nextMap, "mixScaleX", 1);
|
|
let mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2);
|
|
let mixShearY2 = getValue(nextMap, "mixShearY", 1);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
mixScaleX = mixScaleX2;
|
|
mixScaleY = mixScaleY2;
|
|
mixScaleX = mixScaleX2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
if (map.path) {
|
|
for (let constraintName in map.path) {
|
|
let constraintMap = map.path[constraintName];
|
|
let constraint = skeletonData.findPathConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error("Path constraint not found: " + constraintName);
|
|
let constraintIndex = skeletonData.pathConstraints.indexOf(constraint);
|
|
for (let timelineName in constraintMap) {
|
|
let timelineMap = constraintMap[timelineName];
|
|
let keyMap = timelineMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
let frames = timelineMap.length;
|
|
if (timelineName === "position") {
|
|
let timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.positionMode == 0 /* Fixed */ ? scale : 1));
|
|
} else if (timelineName === "spacing") {
|
|
let timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.spacingMode == 0 /* Length */ || constraint.spacingMode == 1 /* Fixed */ ? scale : 1));
|
|
} else if (timelineName === "mix") {
|
|
let timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mixRotate = getValue(keyMap, "mixRotate", 1);
|
|
let mixX = getValue(keyMap, "mixX", 1);
|
|
let mixY = getValue(keyMap, "mixY", mixX);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let mixRotate2 = getValue(nextMap, "mixRotate", 1);
|
|
let mixX2 = getValue(nextMap, "mixX", 1);
|
|
let mixY2 = getValue(nextMap, "mixY", mixX2);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.attachments) {
|
|
for (let attachmentsName in map.attachments) {
|
|
let attachmentsMap = map.attachments[attachmentsName];
|
|
let skin = skeletonData.findSkin(attachmentsName);
|
|
if (!skin)
|
|
throw new Error("Skin not found: " + attachmentsName);
|
|
for (let slotMapName in attachmentsMap) {
|
|
let slotMap = attachmentsMap[slotMapName];
|
|
let slot = skeletonData.findSlot(slotMapName);
|
|
if (!slot)
|
|
throw new Error("Slot not found: " + slotMapName);
|
|
let slotIndex = slot.index;
|
|
for (let attachmentMapName in slotMap) {
|
|
let attachmentMap = slotMap[attachmentMapName];
|
|
let attachment = skin.getAttachment(slotIndex, attachmentMapName);
|
|
for (let timelineMapName in attachmentMap) {
|
|
let timelineMap = attachmentMap[timelineMapName];
|
|
let keyMap = timelineMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
if (timelineMapName == "deform") {
|
|
let weighted = attachment.bones;
|
|
let vertices = attachment.vertices;
|
|
let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;
|
|
let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment);
|
|
let time = getValue(keyMap, "time", 0);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
let deform;
|
|
let verticesValue = getValue(keyMap, "vertices", null);
|
|
if (!verticesValue)
|
|
deform = weighted ? Utils.newFloatArray(deformLength) : vertices;
|
|
else {
|
|
deform = Utils.newFloatArray(deformLength);
|
|
let start = getValue(keyMap, "offset", 0);
|
|
Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length);
|
|
if (scale != 1) {
|
|
for (let i = start, n = i + verticesValue.length; i < n; i++)
|
|
deform[i] *= scale;
|
|
}
|
|
if (!weighted) {
|
|
for (let i = 0; i < deformLength; i++)
|
|
deform[i] += vertices[i];
|
|
}
|
|
}
|
|
timeline.setFrame(frame, time, deform);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let curve = keyMap.curve;
|
|
if (curve)
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
|
|
time = time2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineMapName == "sequence") {
|
|
let timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment);
|
|
let lastDelay = 0;
|
|
for (let frame = 0; frame < timelineMap.length; frame++) {
|
|
let delay = getValue(keyMap, "delay", lastDelay);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mode = SequenceMode[getValue(keyMap, "mode", "hold")];
|
|
let index = getValue(keyMap, "index", 0);
|
|
timeline.setFrame(frame, time, mode, index, delay);
|
|
lastDelay = delay;
|
|
keyMap = timelineMap[frame + 1];
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.drawOrder) {
|
|
let timeline = new DrawOrderTimeline(map.drawOrder.length);
|
|
let slotCount = skeletonData.slots.length;
|
|
let frame = 0;
|
|
for (let i = 0; i < map.drawOrder.length; i++, frame++) {
|
|
let drawOrderMap = map.drawOrder[i];
|
|
let drawOrder = null;
|
|
let offsets = getValue(drawOrderMap, "offsets", null);
|
|
if (offsets) {
|
|
drawOrder = Utils.newArray(slotCount, -1);
|
|
let unchanged = Utils.newArray(slotCount - offsets.length, 0);
|
|
let originalIndex = 0, unchangedIndex = 0;
|
|
for (let ii = 0; ii < offsets.length; ii++) {
|
|
let offsetMap = offsets[ii];
|
|
let slot = skeletonData.findSlot(offsetMap.slot);
|
|
if (!slot)
|
|
throw new Error("Slot not found: " + slot);
|
|
let slotIndex = slot.index;
|
|
while (originalIndex != slotIndex)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
drawOrder[originalIndex + offsetMap.offset] = originalIndex++;
|
|
}
|
|
while (originalIndex < slotCount)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
for (let ii = slotCount - 1; ii >= 0; ii--)
|
|
if (drawOrder[ii] == -1)
|
|
drawOrder[ii] = unchanged[--unchangedIndex];
|
|
}
|
|
timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
if (map.events) {
|
|
let timeline = new EventTimeline(map.events.length);
|
|
let frame = 0;
|
|
for (let i = 0; i < map.events.length; i++, frame++) {
|
|
let eventMap = map.events[i];
|
|
let eventData = skeletonData.findEvent(eventMap.name);
|
|
if (!eventData)
|
|
throw new Error("Event not found: " + eventMap.name);
|
|
let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData);
|
|
event.intValue = getValue(eventMap, "int", eventData.intValue);
|
|
event.floatValue = getValue(eventMap, "float", eventData.floatValue);
|
|
event.stringValue = getValue(eventMap, "string", eventData.stringValue);
|
|
if (event.data.audioPath) {
|
|
event.volume = getValue(eventMap, "volume", 1);
|
|
event.balance = getValue(eventMap, "balance", 0);
|
|
}
|
|
timeline.setFrame(frame, event);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
let duration = 0;
|
|
for (let i = 0, n = timelines.length; i < n; i++)
|
|
duration = Math.max(duration, timelines[i].getDuration());
|
|
skeletonData.animations.push(new Animation(name, timelines, duration));
|
|
}
|
|
};
|
|
var LinkedMesh2 = class {
|
|
constructor(mesh, skin, slotIndex, parent, inheritDeform) {
|
|
this.mesh = mesh;
|
|
this.skin = skin;
|
|
this.slotIndex = slotIndex;
|
|
this.parent = parent;
|
|
this.inheritTimeline = inheritDeform;
|
|
}
|
|
};
|
|
function readTimeline12(keys, timeline, defaultValue, scale) {
|
|
let keyMap = keys[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let value = getValue(keyMap, "value", defaultValue) * scale;
|
|
let bezier = 0;
|
|
for (let frame = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, value);
|
|
let nextMap = keys[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
return timeline;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let value2 = getValue(nextMap, "value", defaultValue) * scale;
|
|
if (keyMap.curve)
|
|
bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale);
|
|
time = time2;
|
|
value = value2;
|
|
keyMap = nextMap;
|
|
}
|
|
}
|
|
function readTimeline22(keys, timeline, name1, name2, defaultValue, scale) {
|
|
let keyMap = keys[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let value1 = getValue(keyMap, name1, defaultValue) * scale;
|
|
let value2 = getValue(keyMap, name2, defaultValue) * scale;
|
|
let bezier = 0;
|
|
for (let frame = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, value1, value2);
|
|
let nextMap = keys[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
return timeline;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let nvalue1 = getValue(nextMap, name1, defaultValue) * scale;
|
|
let nvalue2 = getValue(nextMap, name2, defaultValue) * scale;
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale);
|
|
}
|
|
time = time2;
|
|
value1 = nvalue1;
|
|
value2 = nvalue2;
|
|
keyMap = nextMap;
|
|
}
|
|
}
|
|
function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) {
|
|
if (curve == "stepped") {
|
|
timeline.setStepped(frame);
|
|
return bezier;
|
|
}
|
|
let i = value << 2;
|
|
let cx1 = curve[i];
|
|
let cy1 = curve[i + 1] * scale;
|
|
let cx2 = curve[i + 2];
|
|
let cy2 = curve[i + 3] * scale;
|
|
timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
|
|
return bezier + 1;
|
|
}
|
|
function getValue(map, property, defaultValue) {
|
|
return map[property] !== void 0 ? map[property] : defaultValue;
|
|
}
|
|
|
|
// spine-core/src/polyfills.ts
|
|
(() => {
|
|
if (typeof Math.fround === "undefined") {
|
|
Math.fround = function(array) {
|
|
return function(x) {
|
|
return array[0] = x, array[0];
|
|
};
|
|
}(new Float32Array(1));
|
|
}
|
|
})();
|
|
|
|
// spine-canvas/src/CanvasTexture.ts
|
|
var CanvasTexture = class extends Texture {
|
|
constructor(image) {
|
|
super(image);
|
|
}
|
|
setFilters(minFilter, magFilter) {
|
|
}
|
|
setWraps(uWrap, vWrap) {
|
|
}
|
|
dispose() {
|
|
}
|
|
};
|
|
|
|
// spine-canvas/src/AssetManager.ts
|
|
var AssetManager = class extends AssetManagerBase {
|
|
constructor(pathPrefix = "", downloader = new Downloader()) {
|
|
super((image) => {
|
|
return new CanvasTexture(image);
|
|
}, pathPrefix, downloader);
|
|
}
|
|
};
|
|
|
|
// spine-canvas/src/SkeletonRenderer.ts
|
|
var worldVertices = Utils.newFloatArray(8);
|
|
var _SkeletonRenderer = class {
|
|
constructor(context) {
|
|
this.triangleRendering = false;
|
|
this.debugRendering = false;
|
|
this.vertices = Utils.newFloatArray(8 * 1024);
|
|
this.tempColor = new Color();
|
|
this.ctx = context;
|
|
}
|
|
draw(skeleton) {
|
|
if (this.triangleRendering)
|
|
this.drawTriangles(skeleton);
|
|
else
|
|
this.drawImages(skeleton);
|
|
}
|
|
drawImages(skeleton) {
|
|
let ctx = this.ctx;
|
|
let color = this.tempColor;
|
|
let skeletonColor = skeleton.color;
|
|
let drawOrder = skeleton.drawOrder;
|
|
if (this.debugRendering)
|
|
ctx.strokeStyle = "green";
|
|
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
|
let slot = drawOrder[i];
|
|
let bone = slot.bone;
|
|
if (!bone.active)
|
|
continue;
|
|
let attachment = slot.getAttachment();
|
|
if (!(attachment instanceof RegionAttachment))
|
|
continue;
|
|
attachment.computeWorldVertices(slot, worldVertices, 0, 2);
|
|
let region = attachment.region;
|
|
let image = region.page.texture.getImage();
|
|
let slotColor = slot.color;
|
|
let regionColor = attachment.color;
|
|
color.set(
|
|
skeletonColor.r * slotColor.r * regionColor.r,
|
|
skeletonColor.g * slotColor.g * regionColor.g,
|
|
skeletonColor.b * slotColor.b * regionColor.b,
|
|
skeletonColor.a * slotColor.a * regionColor.a
|
|
);
|
|
ctx.save();
|
|
ctx.transform(bone.a, bone.c, bone.b, bone.d, bone.worldX, bone.worldY);
|
|
ctx.translate(attachment.offset[0], attachment.offset[1]);
|
|
ctx.rotate(attachment.rotation * Math.PI / 180);
|
|
let atlasScale = attachment.width / region.originalWidth;
|
|
ctx.scale(atlasScale * attachment.scaleX, atlasScale * attachment.scaleY);
|
|
let w = region.width, h = region.height;
|
|
ctx.translate(w / 2, h / 2);
|
|
if (attachment.region.degrees == 90) {
|
|
let t = w;
|
|
w = h;
|
|
h = t;
|
|
ctx.rotate(-Math.PI / 2);
|
|
}
|
|
ctx.scale(1, -1);
|
|
ctx.translate(-w / 2, -h / 2);
|
|
ctx.globalAlpha = color.a;
|
|
ctx.drawImage(image, region.x, region.y, w, h, 0, 0, w, h);
|
|
if (this.debugRendering)
|
|
ctx.strokeRect(0, 0, w, h);
|
|
ctx.restore();
|
|
}
|
|
}
|
|
drawTriangles(skeleton) {
|
|
let ctx = this.ctx;
|
|
let color = this.tempColor;
|
|
let skeletonColor = skeleton.color;
|
|
let drawOrder = skeleton.drawOrder;
|
|
let blendMode = null;
|
|
let vertices = this.vertices;
|
|
let triangles = null;
|
|
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
|
let slot = drawOrder[i];
|
|
let attachment = slot.getAttachment();
|
|
let texture;
|
|
let region;
|
|
if (attachment instanceof RegionAttachment) {
|
|
let regionAttachment = attachment;
|
|
vertices = this.computeRegionVertices(slot, regionAttachment, false);
|
|
triangles = _SkeletonRenderer.QUAD_TRIANGLES;
|
|
region = regionAttachment.region;
|
|
texture = region.page.texture.getImage();
|
|
} else if (attachment instanceof MeshAttachment) {
|
|
let mesh = attachment;
|
|
vertices = this.computeMeshVertices(slot, mesh, false);
|
|
triangles = mesh.triangles;
|
|
let region2 = mesh.region.renderObject;
|
|
texture = region2.page.texture.getImage();
|
|
} else
|
|
continue;
|
|
if (texture) {
|
|
if (slot.data.blendMode != blendMode)
|
|
blendMode = slot.data.blendMode;
|
|
let slotColor = slot.color;
|
|
let attachmentColor = attachment.color;
|
|
color.set(
|
|
skeletonColor.r * slotColor.r * attachmentColor.r,
|
|
skeletonColor.g * slotColor.g * attachmentColor.g,
|
|
skeletonColor.b * slotColor.b * attachmentColor.b,
|
|
skeletonColor.a * slotColor.a * attachmentColor.a
|
|
);
|
|
ctx.globalAlpha = color.a;
|
|
for (var j = 0; j < triangles.length; j += 3) {
|
|
let t1 = triangles[j] * 8, t2 = triangles[j + 1] * 8, t3 = triangles[j + 2] * 8;
|
|
let x0 = vertices[t1], y0 = vertices[t1 + 1], u0 = vertices[t1 + 6], v0 = vertices[t1 + 7];
|
|
let x1 = vertices[t2], y1 = vertices[t2 + 1], u1 = vertices[t2 + 6], v1 = vertices[t2 + 7];
|
|
let x2 = vertices[t3], y2 = vertices[t3 + 1], u2 = vertices[t3 + 6], v2 = vertices[t3 + 7];
|
|
this.drawTriangle(texture, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2);
|
|
if (this.debugRendering) {
|
|
ctx.strokeStyle = "green";
|
|
ctx.beginPath();
|
|
ctx.moveTo(x0, y0);
|
|
ctx.lineTo(x1, y1);
|
|
ctx.lineTo(x2, y2);
|
|
ctx.lineTo(x0, y0);
|
|
ctx.stroke();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.ctx.globalAlpha = 1;
|
|
}
|
|
drawTriangle(img, x0, y0, u0, v0, x1, y1, u1, v1, x2, y2, u2, v2) {
|
|
let ctx = this.ctx;
|
|
u0 *= img.width;
|
|
v0 *= img.height;
|
|
u1 *= img.width;
|
|
v1 *= img.height;
|
|
u2 *= img.width;
|
|
v2 *= img.height;
|
|
ctx.beginPath();
|
|
ctx.moveTo(x0, y0);
|
|
ctx.lineTo(x1, y1);
|
|
ctx.lineTo(x2, y2);
|
|
ctx.closePath();
|
|
x1 -= x0;
|
|
y1 -= y0;
|
|
x2 -= x0;
|
|
y2 -= y0;
|
|
u1 -= u0;
|
|
v1 -= v0;
|
|
u2 -= u0;
|
|
v2 -= v0;
|
|
var det = 1 / (u1 * v2 - u2 * v1), a = (v2 * x1 - v1 * x2) * det, b = (v2 * y1 - v1 * y2) * det, c = (u1 * x2 - u2 * x1) * det, d = (u1 * y2 - u2 * y1) * det, e = x0 - a * u0 - c * v0, f = y0 - b * u0 - d * v0;
|
|
ctx.save();
|
|
ctx.transform(a, b, c, d, e, f);
|
|
ctx.clip();
|
|
ctx.drawImage(img, 0, 0);
|
|
ctx.restore();
|
|
}
|
|
computeRegionVertices(slot, region, pma) {
|
|
let skeletonColor = slot.bone.skeleton.color;
|
|
let slotColor = slot.color;
|
|
let regionColor = region.color;
|
|
let alpha = skeletonColor.a * slotColor.a * regionColor.a;
|
|
let multiplier = pma ? alpha : 1;
|
|
let color = this.tempColor;
|
|
color.set(
|
|
skeletonColor.r * slotColor.r * regionColor.r * multiplier,
|
|
skeletonColor.g * slotColor.g * regionColor.g * multiplier,
|
|
skeletonColor.b * slotColor.b * regionColor.b * multiplier,
|
|
alpha
|
|
);
|
|
region.computeWorldVertices(slot, this.vertices, 0, _SkeletonRenderer.VERTEX_SIZE);
|
|
let vertices = this.vertices;
|
|
let uvs = region.uvs;
|
|
vertices[RegionAttachment.C1R] = color.r;
|
|
vertices[RegionAttachment.C1G] = color.g;
|
|
vertices[RegionAttachment.C1B] = color.b;
|
|
vertices[RegionAttachment.C1A] = color.a;
|
|
vertices[RegionAttachment.U1] = uvs[0];
|
|
vertices[RegionAttachment.V1] = uvs[1];
|
|
vertices[RegionAttachment.C2R] = color.r;
|
|
vertices[RegionAttachment.C2G] = color.g;
|
|
vertices[RegionAttachment.C2B] = color.b;
|
|
vertices[RegionAttachment.C2A] = color.a;
|
|
vertices[RegionAttachment.U2] = uvs[2];
|
|
vertices[RegionAttachment.V2] = uvs[3];
|
|
vertices[RegionAttachment.C3R] = color.r;
|
|
vertices[RegionAttachment.C3G] = color.g;
|
|
vertices[RegionAttachment.C3B] = color.b;
|
|
vertices[RegionAttachment.C3A] = color.a;
|
|
vertices[RegionAttachment.U3] = uvs[4];
|
|
vertices[RegionAttachment.V3] = uvs[5];
|
|
vertices[RegionAttachment.C4R] = color.r;
|
|
vertices[RegionAttachment.C4G] = color.g;
|
|
vertices[RegionAttachment.C4B] = color.b;
|
|
vertices[RegionAttachment.C4A] = color.a;
|
|
vertices[RegionAttachment.U4] = uvs[6];
|
|
vertices[RegionAttachment.V4] = uvs[7];
|
|
return vertices;
|
|
}
|
|
computeMeshVertices(slot, mesh, pma) {
|
|
let skeletonColor = slot.bone.skeleton.color;
|
|
let slotColor = slot.color;
|
|
let regionColor = mesh.color;
|
|
let alpha = skeletonColor.a * slotColor.a * regionColor.a;
|
|
let multiplier = pma ? alpha : 1;
|
|
let color = this.tempColor;
|
|
color.set(
|
|
skeletonColor.r * slotColor.r * regionColor.r * multiplier,
|
|
skeletonColor.g * slotColor.g * regionColor.g * multiplier,
|
|
skeletonColor.b * slotColor.b * regionColor.b * multiplier,
|
|
alpha
|
|
);
|
|
let vertexCount = mesh.worldVerticesLength / 2;
|
|
let vertices = this.vertices;
|
|
if (vertices.length < mesh.worldVerticesLength)
|
|
this.vertices = vertices = Utils.newFloatArray(mesh.worldVerticesLength);
|
|
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, _SkeletonRenderer.VERTEX_SIZE);
|
|
let uvs = mesh.uvs;
|
|
for (let i = 0, u = 0, v = 2; i < vertexCount; i++) {
|
|
vertices[v++] = color.r;
|
|
vertices[v++] = color.g;
|
|
vertices[v++] = color.b;
|
|
vertices[v++] = color.a;
|
|
vertices[v++] = uvs[u++];
|
|
vertices[v++] = uvs[u++];
|
|
v += 2;
|
|
}
|
|
return vertices;
|
|
}
|
|
};
|
|
var SkeletonRenderer = _SkeletonRenderer;
|
|
SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
|
|
SkeletonRenderer.VERTEX_SIZE = 2 + 2 + 4;
|
|
return __toCommonJS(src_exports);
|
|
})();
|
|
//# sourceMappingURL=spine-canvas.js.map
|
|
|
|
/*** EXPORTS FROM exports-loader ***/
|
|
module.exports = spine;
|
|
|
|
}.call(window));
|
|
|
|
|
|
/***/ }),
|
|
/* 210 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/*** IMPORTS FROM imports-loader ***/
|
|
|
|
(function() {
|
|
"use strict";
|
|
var spine = (() => {
|
|
var __defProp = Object.defineProperty;
|
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
var __export = (target, all) => {
|
|
for (var name in all)
|
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
};
|
|
var __copyProps = (to, from, except, desc) => {
|
|
if (from && typeof from === "object" || typeof from === "function") {
|
|
for (let key of __getOwnPropNames(from))
|
|
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
}
|
|
return to;
|
|
};
|
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
|
|
// spine-webgl/src/index.ts
|
|
var src_exports = {};
|
|
__export(src_exports, {
|
|
AlphaTimeline: () => AlphaTimeline,
|
|
Animation: () => Animation,
|
|
AnimationState: () => AnimationState,
|
|
AnimationStateAdapter: () => AnimationStateAdapter,
|
|
AnimationStateData: () => AnimationStateData,
|
|
AssetManager: () => AssetManager,
|
|
AssetManagerBase: () => AssetManagerBase,
|
|
AtlasAttachmentLoader: () => AtlasAttachmentLoader,
|
|
Attachment: () => Attachment,
|
|
AttachmentTimeline: () => AttachmentTimeline,
|
|
BinaryInput: () => BinaryInput,
|
|
BlendMode: () => BlendMode,
|
|
Bone: () => Bone,
|
|
BoneData: () => BoneData,
|
|
BoundingBoxAttachment: () => BoundingBoxAttachment,
|
|
CURRENT: () => CURRENT,
|
|
CameraController: () => CameraController,
|
|
ClippingAttachment: () => ClippingAttachment,
|
|
Color: () => Color,
|
|
Color2Attribute: () => Color2Attribute,
|
|
ColorAttribute: () => ColorAttribute,
|
|
ConstraintData: () => ConstraintData,
|
|
CurveTimeline: () => CurveTimeline,
|
|
CurveTimeline1: () => CurveTimeline1,
|
|
CurveTimeline2: () => CurveTimeline2,
|
|
DebugUtils: () => DebugUtils,
|
|
DeformTimeline: () => DeformTimeline,
|
|
Downloader: () => Downloader,
|
|
DrawOrderTimeline: () => DrawOrderTimeline,
|
|
Event: () => Event,
|
|
EventData: () => EventData,
|
|
EventQueue: () => EventQueue,
|
|
EventTimeline: () => EventTimeline,
|
|
EventType: () => EventType,
|
|
FIRST: () => FIRST,
|
|
FakeTexture: () => FakeTexture,
|
|
GLTexture: () => GLTexture,
|
|
HOLD_FIRST: () => HOLD_FIRST,
|
|
HOLD_MIX: () => HOLD_MIX,
|
|
HOLD_SUBSEQUENT: () => HOLD_SUBSEQUENT,
|
|
IkConstraint: () => IkConstraint,
|
|
IkConstraintData: () => IkConstraintData,
|
|
IkConstraintTimeline: () => IkConstraintTimeline,
|
|
Input: () => Input,
|
|
IntSet: () => IntSet,
|
|
Interpolation: () => Interpolation,
|
|
LoadingScreen: () => LoadingScreen,
|
|
M00: () => M00,
|
|
M01: () => M01,
|
|
M02: () => M02,
|
|
M03: () => M03,
|
|
M10: () => M10,
|
|
M11: () => M11,
|
|
M12: () => M12,
|
|
M13: () => M13,
|
|
M20: () => M20,
|
|
M21: () => M21,
|
|
M22: () => M22,
|
|
M23: () => M23,
|
|
M30: () => M30,
|
|
M31: () => M31,
|
|
M32: () => M32,
|
|
M33: () => M33,
|
|
ManagedWebGLRenderingContext: () => ManagedWebGLRenderingContext,
|
|
MathUtils: () => MathUtils,
|
|
Matrix4: () => Matrix42,
|
|
Mesh: () => Mesh,
|
|
MeshAttachment: () => MeshAttachment,
|
|
MixBlend: () => MixBlend,
|
|
MixDirection: () => MixDirection,
|
|
OrthoCamera: () => OrthoCamera,
|
|
PathAttachment: () => PathAttachment,
|
|
PathConstraint: () => PathConstraint,
|
|
PathConstraintData: () => PathConstraintData,
|
|
PathConstraintMixTimeline: () => PathConstraintMixTimeline,
|
|
PathConstraintPositionTimeline: () => PathConstraintPositionTimeline,
|
|
PathConstraintSpacingTimeline: () => PathConstraintSpacingTimeline,
|
|
PointAttachment: () => PointAttachment,
|
|
PolygonBatcher: () => PolygonBatcher,
|
|
Pool: () => Pool,
|
|
Position2Attribute: () => Position2Attribute,
|
|
Position3Attribute: () => Position3Attribute,
|
|
PositionMode: () => PositionMode,
|
|
Pow: () => Pow,
|
|
PowOut: () => PowOut,
|
|
RGB2Timeline: () => RGB2Timeline,
|
|
RGBA2Timeline: () => RGBA2Timeline,
|
|
RGBATimeline: () => RGBATimeline,
|
|
RGBTimeline: () => RGBTimeline,
|
|
RegionAttachment: () => RegionAttachment,
|
|
ResizeMode: () => ResizeMode,
|
|
RotateMode: () => RotateMode,
|
|
RotateTimeline: () => RotateTimeline,
|
|
SETUP: () => SETUP,
|
|
SUBSEQUENT: () => SUBSEQUENT,
|
|
ScaleTimeline: () => ScaleTimeline,
|
|
ScaleXTimeline: () => ScaleXTimeline,
|
|
ScaleYTimeline: () => ScaleYTimeline,
|
|
SceneRenderer: () => SceneRenderer,
|
|
SequenceTimeline: () => SequenceTimeline,
|
|
Shader: () => Shader,
|
|
ShapeRenderer: () => ShapeRenderer,
|
|
ShapeType: () => ShapeType,
|
|
ShearTimeline: () => ShearTimeline,
|
|
ShearXTimeline: () => ShearXTimeline,
|
|
ShearYTimeline: () => ShearYTimeline,
|
|
Skeleton: () => Skeleton,
|
|
SkeletonBinary: () => SkeletonBinary,
|
|
SkeletonBounds: () => SkeletonBounds,
|
|
SkeletonClipping: () => SkeletonClipping,
|
|
SkeletonData: () => SkeletonData,
|
|
SkeletonDebugRenderer: () => SkeletonDebugRenderer,
|
|
SkeletonJson: () => SkeletonJson,
|
|
SkeletonRenderer: () => SkeletonRenderer,
|
|
Skin: () => Skin,
|
|
SkinEntry: () => SkinEntry,
|
|
Slot: () => Slot,
|
|
SlotData: () => SlotData,
|
|
SpacingMode: () => SpacingMode,
|
|
SpineCanvas: () => SpineCanvas,
|
|
StringSet: () => StringSet,
|
|
TexCoordAttribute: () => TexCoordAttribute,
|
|
Texture: () => Texture,
|
|
TextureAtlas: () => TextureAtlas,
|
|
TextureAtlasPage: () => TextureAtlasPage,
|
|
TextureAtlasRegion: () => TextureAtlasRegion,
|
|
TextureFilter: () => TextureFilter,
|
|
TextureRegion: () => TextureRegion,
|
|
TextureWrap: () => TextureWrap,
|
|
TimeKeeper: () => TimeKeeper,
|
|
Timeline: () => Timeline,
|
|
Touch: () => Touch,
|
|
TrackEntry: () => TrackEntry,
|
|
TransformConstraint: () => TransformConstraint,
|
|
TransformConstraintData: () => TransformConstraintData,
|
|
TransformConstraintTimeline: () => TransformConstraintTimeline,
|
|
TransformMode: () => TransformMode,
|
|
TranslateTimeline: () => TranslateTimeline,
|
|
TranslateXTimeline: () => TranslateXTimeline,
|
|
TranslateYTimeline: () => TranslateYTimeline,
|
|
Triangulator: () => Triangulator,
|
|
Utils: () => Utils,
|
|
Vector2: () => Vector2,
|
|
Vector3: () => Vector3,
|
|
VertexAttachment: () => VertexAttachment,
|
|
VertexAttribute: () => VertexAttribute,
|
|
VertexAttributeType: () => VertexAttributeType,
|
|
WebGLBlendModeConverter: () => WebGLBlendModeConverter,
|
|
WindowedMean: () => WindowedMean
|
|
});
|
|
|
|
// spine-core/src/Utils.ts
|
|
var IntSet = class {
|
|
constructor() {
|
|
this.array = new Array();
|
|
}
|
|
add(value) {
|
|
let contains = this.contains(value);
|
|
this.array[value | 0] = value | 0;
|
|
return !contains;
|
|
}
|
|
contains(value) {
|
|
return this.array[value | 0] != void 0;
|
|
}
|
|
remove(value) {
|
|
this.array[value | 0] = void 0;
|
|
}
|
|
clear() {
|
|
this.array.length = 0;
|
|
}
|
|
};
|
|
var StringSet = class {
|
|
constructor() {
|
|
this.entries = {};
|
|
this.size = 0;
|
|
}
|
|
add(value) {
|
|
let contains = this.entries[value];
|
|
this.entries[value] = true;
|
|
if (!contains) {
|
|
this.size++;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
addAll(values) {
|
|
let oldSize = this.size;
|
|
for (var i = 0, n = values.length; i < n; i++)
|
|
this.add(values[i]);
|
|
return oldSize != this.size;
|
|
}
|
|
contains(value) {
|
|
return this.entries[value];
|
|
}
|
|
clear() {
|
|
this.entries = {};
|
|
this.size = 0;
|
|
}
|
|
};
|
|
var _Color = class {
|
|
constructor(r = 0, g = 0, b = 0, a = 0) {
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b;
|
|
this.a = a;
|
|
}
|
|
set(r, g, b, a) {
|
|
this.r = r;
|
|
this.g = g;
|
|
this.b = b;
|
|
this.a = a;
|
|
return this.clamp();
|
|
}
|
|
setFromColor(c) {
|
|
this.r = c.r;
|
|
this.g = c.g;
|
|
this.b = c.b;
|
|
this.a = c.a;
|
|
return this;
|
|
}
|
|
setFromString(hex) {
|
|
hex = hex.charAt(0) == "#" ? hex.substr(1) : hex;
|
|
this.r = parseInt(hex.substr(0, 2), 16) / 255;
|
|
this.g = parseInt(hex.substr(2, 2), 16) / 255;
|
|
this.b = parseInt(hex.substr(4, 2), 16) / 255;
|
|
this.a = hex.length != 8 ? 1 : parseInt(hex.substr(6, 2), 16) / 255;
|
|
return this;
|
|
}
|
|
add(r, g, b, a) {
|
|
this.r += r;
|
|
this.g += g;
|
|
this.b += b;
|
|
this.a += a;
|
|
return this.clamp();
|
|
}
|
|
clamp() {
|
|
if (this.r < 0)
|
|
this.r = 0;
|
|
else if (this.r > 1)
|
|
this.r = 1;
|
|
if (this.g < 0)
|
|
this.g = 0;
|
|
else if (this.g > 1)
|
|
this.g = 1;
|
|
if (this.b < 0)
|
|
this.b = 0;
|
|
else if (this.b > 1)
|
|
this.b = 1;
|
|
if (this.a < 0)
|
|
this.a = 0;
|
|
else if (this.a > 1)
|
|
this.a = 1;
|
|
return this;
|
|
}
|
|
static rgba8888ToColor(color, value) {
|
|
color.r = ((value & 4278190080) >>> 24) / 255;
|
|
color.g = ((value & 16711680) >>> 16) / 255;
|
|
color.b = ((value & 65280) >>> 8) / 255;
|
|
color.a = (value & 255) / 255;
|
|
}
|
|
static rgb888ToColor(color, value) {
|
|
color.r = ((value & 16711680) >>> 16) / 255;
|
|
color.g = ((value & 65280) >>> 8) / 255;
|
|
color.b = (value & 255) / 255;
|
|
}
|
|
static fromString(hex) {
|
|
return new _Color().setFromString(hex);
|
|
}
|
|
};
|
|
var Color = _Color;
|
|
Color.WHITE = new _Color(1, 1, 1, 1);
|
|
Color.RED = new _Color(1, 0, 0, 1);
|
|
Color.GREEN = new _Color(0, 1, 0, 1);
|
|
Color.BLUE = new _Color(0, 0, 1, 1);
|
|
Color.MAGENTA = new _Color(1, 0, 1, 1);
|
|
var _MathUtils = class {
|
|
static clamp(value, min, max) {
|
|
if (value < min)
|
|
return min;
|
|
if (value > max)
|
|
return max;
|
|
return value;
|
|
}
|
|
static cosDeg(degrees) {
|
|
return Math.cos(degrees * _MathUtils.degRad);
|
|
}
|
|
static sinDeg(degrees) {
|
|
return Math.sin(degrees * _MathUtils.degRad);
|
|
}
|
|
static signum(value) {
|
|
return value > 0 ? 1 : value < 0 ? -1 : 0;
|
|
}
|
|
static toInt(x) {
|
|
return x > 0 ? Math.floor(x) : Math.ceil(x);
|
|
}
|
|
static cbrt(x) {
|
|
let y = Math.pow(Math.abs(x), 1 / 3);
|
|
return x < 0 ? -y : y;
|
|
}
|
|
static randomTriangular(min, max) {
|
|
return _MathUtils.randomTriangularWith(min, max, (min + max) * 0.5);
|
|
}
|
|
static randomTriangularWith(min, max, mode) {
|
|
let u = Math.random();
|
|
let d = max - min;
|
|
if (u <= (mode - min) / d)
|
|
return min + Math.sqrt(u * d * (mode - min));
|
|
return max - Math.sqrt((1 - u) * d * (max - mode));
|
|
}
|
|
static isPowerOfTwo(value) {
|
|
return value && (value & value - 1) === 0;
|
|
}
|
|
};
|
|
var MathUtils = _MathUtils;
|
|
MathUtils.PI = 3.1415927;
|
|
MathUtils.PI2 = _MathUtils.PI * 2;
|
|
MathUtils.radiansToDegrees = 180 / _MathUtils.PI;
|
|
MathUtils.radDeg = _MathUtils.radiansToDegrees;
|
|
MathUtils.degreesToRadians = _MathUtils.PI / 180;
|
|
MathUtils.degRad = _MathUtils.degreesToRadians;
|
|
var Interpolation = class {
|
|
apply(start, end, a) {
|
|
return start + (end - start) * this.applyInternal(a);
|
|
}
|
|
};
|
|
var Pow = class extends Interpolation {
|
|
constructor(power) {
|
|
super();
|
|
this.power = 2;
|
|
this.power = power;
|
|
}
|
|
applyInternal(a) {
|
|
if (a <= 0.5)
|
|
return Math.pow(a * 2, this.power) / 2;
|
|
return Math.pow((a - 1) * 2, this.power) / (this.power % 2 == 0 ? -2 : 2) + 1;
|
|
}
|
|
};
|
|
var PowOut = class extends Pow {
|
|
constructor(power) {
|
|
super(power);
|
|
}
|
|
applyInternal(a) {
|
|
return Math.pow(a - 1, this.power) * (this.power % 2 == 0 ? -1 : 1) + 1;
|
|
}
|
|
};
|
|
var _Utils = class {
|
|
static arrayCopy(source, sourceStart, dest, destStart, numElements) {
|
|
for (let i = sourceStart, j = destStart; i < sourceStart + numElements; i++, j++) {
|
|
dest[j] = source[i];
|
|
}
|
|
}
|
|
static arrayFill(array, fromIndex, toIndex, value) {
|
|
for (let i = fromIndex; i < toIndex; i++)
|
|
array[i] = value;
|
|
}
|
|
static setArraySize(array, size, value = 0) {
|
|
let oldSize = array.length;
|
|
if (oldSize == size)
|
|
return array;
|
|
array.length = size;
|
|
if (oldSize < size) {
|
|
for (let i = oldSize; i < size; i++)
|
|
array[i] = value;
|
|
}
|
|
return array;
|
|
}
|
|
static ensureArrayCapacity(array, size, value = 0) {
|
|
if (array.length >= size)
|
|
return array;
|
|
return _Utils.setArraySize(array, size, value);
|
|
}
|
|
static newArray(size, defaultValue) {
|
|
let array = new Array(size);
|
|
for (let i = 0; i < size; i++)
|
|
array[i] = defaultValue;
|
|
return array;
|
|
}
|
|
static newFloatArray(size) {
|
|
if (_Utils.SUPPORTS_TYPED_ARRAYS)
|
|
return new Float32Array(size);
|
|
else {
|
|
let array = new Array(size);
|
|
for (let i = 0; i < array.length; i++)
|
|
array[i] = 0;
|
|
return array;
|
|
}
|
|
}
|
|
static newShortArray(size) {
|
|
if (_Utils.SUPPORTS_TYPED_ARRAYS)
|
|
return new Int16Array(size);
|
|
else {
|
|
let array = new Array(size);
|
|
for (let i = 0; i < array.length; i++)
|
|
array[i] = 0;
|
|
return array;
|
|
}
|
|
}
|
|
static toFloatArray(array) {
|
|
return _Utils.SUPPORTS_TYPED_ARRAYS ? new Float32Array(array) : array;
|
|
}
|
|
static toSinglePrecision(value) {
|
|
return _Utils.SUPPORTS_TYPED_ARRAYS ? Math.fround(value) : value;
|
|
}
|
|
static webkit602BugfixHelper(alpha, blend) {
|
|
}
|
|
static contains(array, element, identity = true) {
|
|
for (var i = 0; i < array.length; i++)
|
|
if (array[i] == element)
|
|
return true;
|
|
return false;
|
|
}
|
|
static enumValue(type, name) {
|
|
return type[name[0].toUpperCase() + name.slice(1)];
|
|
}
|
|
};
|
|
var Utils = _Utils;
|
|
Utils.SUPPORTS_TYPED_ARRAYS = typeof Float32Array !== "undefined";
|
|
var DebugUtils = class {
|
|
static logBones(skeleton) {
|
|
for (let i = 0; i < skeleton.bones.length; i++) {
|
|
let bone = skeleton.bones[i];
|
|
console.log(bone.data.name + ", " + bone.a + ", " + bone.b + ", " + bone.c + ", " + bone.d + ", " + bone.worldX + ", " + bone.worldY);
|
|
}
|
|
}
|
|
};
|
|
var Pool = class {
|
|
constructor(instantiator) {
|
|
this.items = new Array();
|
|
this.instantiator = instantiator;
|
|
}
|
|
obtain() {
|
|
return this.items.length > 0 ? this.items.pop() : this.instantiator();
|
|
}
|
|
free(item) {
|
|
if (item.reset)
|
|
item.reset();
|
|
this.items.push(item);
|
|
}
|
|
freeAll(items) {
|
|
for (let i = 0; i < items.length; i++)
|
|
this.free(items[i]);
|
|
}
|
|
clear() {
|
|
this.items.length = 0;
|
|
}
|
|
};
|
|
var Vector2 = class {
|
|
constructor(x = 0, y = 0) {
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
set(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
return this;
|
|
}
|
|
length() {
|
|
let x = this.x;
|
|
let y = this.y;
|
|
return Math.sqrt(x * x + y * y);
|
|
}
|
|
normalize() {
|
|
let len = this.length();
|
|
if (len != 0) {
|
|
this.x /= len;
|
|
this.y /= len;
|
|
}
|
|
return this;
|
|
}
|
|
};
|
|
var TimeKeeper = class {
|
|
constructor() {
|
|
this.maxDelta = 0.064;
|
|
this.framesPerSecond = 0;
|
|
this.delta = 0;
|
|
this.totalTime = 0;
|
|
this.lastTime = Date.now() / 1e3;
|
|
this.frameCount = 0;
|
|
this.frameTime = 0;
|
|
}
|
|
update() {
|
|
let now = Date.now() / 1e3;
|
|
this.delta = now - this.lastTime;
|
|
this.frameTime += this.delta;
|
|
this.totalTime += this.delta;
|
|
if (this.delta > this.maxDelta)
|
|
this.delta = this.maxDelta;
|
|
this.lastTime = now;
|
|
this.frameCount++;
|
|
if (this.frameTime > 1) {
|
|
this.framesPerSecond = this.frameCount / this.frameTime;
|
|
this.frameTime = 0;
|
|
this.frameCount = 0;
|
|
}
|
|
}
|
|
};
|
|
var WindowedMean = class {
|
|
constructor(windowSize = 32) {
|
|
this.addedValues = 0;
|
|
this.lastValue = 0;
|
|
this.mean = 0;
|
|
this.dirty = true;
|
|
this.values = new Array(windowSize);
|
|
}
|
|
hasEnoughData() {
|
|
return this.addedValues >= this.values.length;
|
|
}
|
|
addValue(value) {
|
|
if (this.addedValues < this.values.length)
|
|
this.addedValues++;
|
|
this.values[this.lastValue++] = value;
|
|
if (this.lastValue > this.values.length - 1)
|
|
this.lastValue = 0;
|
|
this.dirty = true;
|
|
}
|
|
getMean() {
|
|
if (this.hasEnoughData()) {
|
|
if (this.dirty) {
|
|
let mean = 0;
|
|
for (let i = 0; i < this.values.length; i++)
|
|
mean += this.values[i];
|
|
this.mean = mean / this.values.length;
|
|
this.dirty = false;
|
|
}
|
|
return this.mean;
|
|
}
|
|
return 0;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/Attachment.ts
|
|
var Attachment = class {
|
|
constructor(name) {
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.name = name;
|
|
}
|
|
};
|
|
var _VertexAttachment = class extends Attachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.id = _VertexAttachment.nextID++;
|
|
this.bones = null;
|
|
this.vertices = [];
|
|
this.worldVerticesLength = 0;
|
|
this.timelineAttachment = this;
|
|
}
|
|
computeWorldVertices(slot, start, count, worldVertices, offset, stride) {
|
|
count = offset + (count >> 1) * stride;
|
|
let skeleton = slot.bone.skeleton;
|
|
let deformArray = slot.deform;
|
|
let vertices = this.vertices;
|
|
let bones = this.bones;
|
|
if (!bones) {
|
|
if (deformArray.length > 0)
|
|
vertices = deformArray;
|
|
let bone = slot.bone;
|
|
let x = bone.worldX;
|
|
let y = bone.worldY;
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
for (let v2 = start, w = offset; w < count; v2 += 2, w += stride) {
|
|
let vx = vertices[v2], vy = vertices[v2 + 1];
|
|
worldVertices[w] = vx * a + vy * b + x;
|
|
worldVertices[w + 1] = vx * c + vy * d + y;
|
|
}
|
|
return;
|
|
}
|
|
let v = 0, skip = 0;
|
|
for (let i = 0; i < start; i += 2) {
|
|
let n = bones[v];
|
|
v += n + 1;
|
|
skip += n;
|
|
}
|
|
let skeletonBones = skeleton.bones;
|
|
if (deformArray.length == 0) {
|
|
for (let w = offset, b = skip * 3; w < count; w += stride) {
|
|
let wx = 0, wy = 0;
|
|
let n = bones[v++];
|
|
n += v;
|
|
for (; v < n; v++, b += 3) {
|
|
let bone = skeletonBones[bones[v]];
|
|
let vx = vertices[b], vy = vertices[b + 1], weight = vertices[b + 2];
|
|
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
|
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
|
}
|
|
worldVertices[w] = wx;
|
|
worldVertices[w + 1] = wy;
|
|
}
|
|
} else {
|
|
let deform = deformArray;
|
|
for (let w = offset, b = skip * 3, f = skip << 1; w < count; w += stride) {
|
|
let wx = 0, wy = 0;
|
|
let n = bones[v++];
|
|
n += v;
|
|
for (; v < n; v++, b += 3, f += 2) {
|
|
let bone = skeletonBones[bones[v]];
|
|
let vx = vertices[b] + deform[f], vy = vertices[b + 1] + deform[f + 1], weight = vertices[b + 2];
|
|
wx += (vx * bone.a + vy * bone.b + bone.worldX) * weight;
|
|
wy += (vx * bone.c + vy * bone.d + bone.worldY) * weight;
|
|
}
|
|
worldVertices[w] = wx;
|
|
worldVertices[w + 1] = wy;
|
|
}
|
|
}
|
|
}
|
|
copyTo(attachment) {
|
|
if (this.bones) {
|
|
attachment.bones = new Array(this.bones.length);
|
|
Utils.arrayCopy(this.bones, 0, attachment.bones, 0, this.bones.length);
|
|
} else
|
|
attachment.bones = null;
|
|
if (this.vertices) {
|
|
attachment.vertices = Utils.newFloatArray(this.vertices.length);
|
|
Utils.arrayCopy(this.vertices, 0, attachment.vertices, 0, this.vertices.length);
|
|
}
|
|
attachment.worldVerticesLength = this.worldVerticesLength;
|
|
attachment.timelineAttachment = this.timelineAttachment;
|
|
}
|
|
};
|
|
var VertexAttachment = _VertexAttachment;
|
|
VertexAttachment.nextID = 0;
|
|
|
|
// spine-core/src/attachments/Sequence.ts
|
|
var _Sequence = class {
|
|
constructor(count) {
|
|
this.id = _Sequence.nextID();
|
|
this.start = 0;
|
|
this.digits = 0;
|
|
this.setupIndex = 0;
|
|
this.regions = new Array(count);
|
|
}
|
|
copy() {
|
|
let copy = new _Sequence(this.regions.length);
|
|
Utils.arrayCopy(this.regions, 0, copy.regions, 0, this.regions.length);
|
|
copy.start = this.start;
|
|
copy.digits = this.digits;
|
|
copy.setupIndex = this.setupIndex;
|
|
return copy;
|
|
}
|
|
apply(slot, attachment) {
|
|
let index = slot.sequenceIndex;
|
|
if (index == -1)
|
|
index = this.setupIndex;
|
|
if (index >= this.regions.length)
|
|
index = this.regions.length - 1;
|
|
let region = this.regions[index];
|
|
if (attachment.region != region) {
|
|
attachment.region = region;
|
|
attachment.updateRegion();
|
|
}
|
|
}
|
|
getPath(basePath, index) {
|
|
let result = basePath;
|
|
let frame = (this.start + index).toString();
|
|
for (let i = this.digits - frame.length; i > 0; i--)
|
|
result += "0";
|
|
result += frame;
|
|
return result;
|
|
}
|
|
static nextID() {
|
|
return _Sequence._nextID++;
|
|
}
|
|
};
|
|
var Sequence = _Sequence;
|
|
Sequence._nextID = 0;
|
|
var SequenceMode = /* @__PURE__ */ ((SequenceMode2) => {
|
|
SequenceMode2[SequenceMode2["hold"] = 0] = "hold";
|
|
SequenceMode2[SequenceMode2["once"] = 1] = "once";
|
|
SequenceMode2[SequenceMode2["loop"] = 2] = "loop";
|
|
SequenceMode2[SequenceMode2["pingpong"] = 3] = "pingpong";
|
|
SequenceMode2[SequenceMode2["onceReverse"] = 4] = "onceReverse";
|
|
SequenceMode2[SequenceMode2["loopReverse"] = 5] = "loopReverse";
|
|
SequenceMode2[SequenceMode2["pingpongReverse"] = 6] = "pingpongReverse";
|
|
return SequenceMode2;
|
|
})(SequenceMode || {});
|
|
var SequenceModeValues = [
|
|
0 /* hold */,
|
|
1 /* once */,
|
|
2 /* loop */,
|
|
3 /* pingpong */,
|
|
4 /* onceReverse */,
|
|
5 /* loopReverse */,
|
|
6 /* pingpongReverse */
|
|
];
|
|
|
|
// spine-core/src/Animation.ts
|
|
var Animation = class {
|
|
constructor(name, timelines, duration) {
|
|
this.timelines = [];
|
|
this.timelineIds = new StringSet();
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.name = name;
|
|
this.setTimelines(timelines);
|
|
this.duration = duration;
|
|
}
|
|
setTimelines(timelines) {
|
|
if (!timelines)
|
|
throw new Error("timelines cannot be null.");
|
|
this.timelines = timelines;
|
|
this.timelineIds.clear();
|
|
for (var i = 0; i < timelines.length; i++)
|
|
this.timelineIds.addAll(timelines[i].getPropertyIds());
|
|
}
|
|
hasTimeline(ids) {
|
|
for (let i = 0; i < ids.length; i++)
|
|
if (this.timelineIds.contains(ids[i]))
|
|
return true;
|
|
return false;
|
|
}
|
|
apply(skeleton, lastTime, time, loop, events, alpha, blend, direction) {
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
if (loop && this.duration != 0) {
|
|
time %= this.duration;
|
|
if (lastTime > 0)
|
|
lastTime %= this.duration;
|
|
}
|
|
let timelines = this.timelines;
|
|
for (let i = 0, n = timelines.length; i < n; i++)
|
|
timelines[i].apply(skeleton, lastTime, time, events, alpha, blend, direction);
|
|
}
|
|
};
|
|
var MixBlend = /* @__PURE__ */ ((MixBlend2) => {
|
|
MixBlend2[MixBlend2["setup"] = 0] = "setup";
|
|
MixBlend2[MixBlend2["first"] = 1] = "first";
|
|
MixBlend2[MixBlend2["replace"] = 2] = "replace";
|
|
MixBlend2[MixBlend2["add"] = 3] = "add";
|
|
return MixBlend2;
|
|
})(MixBlend || {});
|
|
var MixDirection = /* @__PURE__ */ ((MixDirection2) => {
|
|
MixDirection2[MixDirection2["mixIn"] = 0] = "mixIn";
|
|
MixDirection2[MixDirection2["mixOut"] = 1] = "mixOut";
|
|
return MixDirection2;
|
|
})(MixDirection || {});
|
|
var Property = {
|
|
rotate: 0,
|
|
x: 1,
|
|
y: 2,
|
|
scaleX: 3,
|
|
scaleY: 4,
|
|
shearX: 5,
|
|
shearY: 6,
|
|
rgb: 7,
|
|
alpha: 8,
|
|
rgb2: 9,
|
|
attachment: 10,
|
|
deform: 11,
|
|
event: 12,
|
|
drawOrder: 13,
|
|
ikConstraint: 14,
|
|
transformConstraint: 15,
|
|
pathConstraintPosition: 16,
|
|
pathConstraintSpacing: 17,
|
|
pathConstraintMix: 18,
|
|
sequence: 19
|
|
};
|
|
var Timeline = class {
|
|
constructor(frameCount, propertyIds) {
|
|
this.propertyIds = propertyIds;
|
|
this.frames = Utils.newFloatArray(frameCount * this.getFrameEntries());
|
|
}
|
|
getPropertyIds() {
|
|
return this.propertyIds;
|
|
}
|
|
getFrameEntries() {
|
|
return 1;
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length / this.getFrameEntries();
|
|
}
|
|
getDuration() {
|
|
return this.frames[this.frames.length - this.getFrameEntries()];
|
|
}
|
|
static search1(frames, time) {
|
|
let n = frames.length;
|
|
for (let i = 1; i < n; i++)
|
|
if (frames[i] > time)
|
|
return i - 1;
|
|
return n - 1;
|
|
}
|
|
static search(frames, time, step) {
|
|
let n = frames.length;
|
|
for (let i = step; i < n; i += step)
|
|
if (frames[i] > time)
|
|
return i - step;
|
|
return n - step;
|
|
}
|
|
};
|
|
var CurveTimeline = class extends Timeline {
|
|
constructor(frameCount, bezierCount, propertyIds) {
|
|
super(frameCount, propertyIds);
|
|
this.curves = Utils.newFloatArray(frameCount + bezierCount * 18);
|
|
this.curves[frameCount - 1] = 1;
|
|
}
|
|
setLinear(frame) {
|
|
this.curves[frame] = 0;
|
|
}
|
|
setStepped(frame) {
|
|
this.curves[frame] = 1;
|
|
}
|
|
shrink(bezierCount) {
|
|
let size = this.getFrameCount() + bezierCount * 18;
|
|
if (this.curves.length > size) {
|
|
let newCurves = Utils.newFloatArray(size);
|
|
Utils.arrayCopy(this.curves, 0, newCurves, 0, size);
|
|
this.curves = newCurves;
|
|
}
|
|
}
|
|
setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) {
|
|
let curves = this.curves;
|
|
let i = this.getFrameCount() + bezier * 18;
|
|
if (value == 0)
|
|
curves[frame] = 2 + i;
|
|
let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = (value1 - cy1 * 2 + cy2) * 0.03;
|
|
let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = ((cy1 - cy2) * 3 - value1 + value2) * 6e-3;
|
|
let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
|
|
let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = (cy1 - value1) * 0.3 + tmpy + dddy * 0.16666667;
|
|
let x = time1 + dx, y = value1 + dy;
|
|
for (let n = i + 18; i < n; i += 2) {
|
|
curves[i] = x;
|
|
curves[i + 1] = y;
|
|
dx += ddx;
|
|
dy += ddy;
|
|
ddx += dddx;
|
|
ddy += dddy;
|
|
x += dx;
|
|
y += dy;
|
|
}
|
|
}
|
|
getBezierValue(time, frameIndex, valueOffset, i) {
|
|
let curves = this.curves;
|
|
if (curves[i] > time) {
|
|
let x2 = this.frames[frameIndex], y2 = this.frames[frameIndex + valueOffset];
|
|
return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2);
|
|
}
|
|
let n = i + 18;
|
|
for (i += 2; i < n; i += 2) {
|
|
if (curves[i] >= time) {
|
|
let x2 = curves[i - 2], y2 = curves[i - 1];
|
|
return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2);
|
|
}
|
|
}
|
|
frameIndex += this.getFrameEntries();
|
|
let x = curves[n - 2], y = curves[n - 1];
|
|
return y + (time - x) / (this.frames[frameIndex] - x) * (this.frames[frameIndex + valueOffset] - y);
|
|
}
|
|
};
|
|
var CurveTimeline1 = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, propertyId) {
|
|
super(frameCount, bezierCount, [propertyId]);
|
|
}
|
|
getFrameEntries() {
|
|
return 2;
|
|
}
|
|
setFrame(frame, time, value) {
|
|
frame <<= 1;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = value;
|
|
}
|
|
getCurveValue(time) {
|
|
let frames = this.frames;
|
|
let i = frames.length - 2;
|
|
for (let ii = 2; ii <= i; ii += 2) {
|
|
if (frames[ii] > time) {
|
|
i = ii - 2;
|
|
break;
|
|
}
|
|
}
|
|
let curveType = this.curves[i >> 1];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i], value = frames[i + 1];
|
|
return value + (time - before) / (frames[i + 2] - before) * (frames[i + 2 + 1] - value);
|
|
case 1:
|
|
return frames[i + 1];
|
|
}
|
|
return this.getBezierValue(time, i, 1, curveType - 2);
|
|
}
|
|
};
|
|
var CurveTimeline2 = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, propertyId1, propertyId2) {
|
|
super(frameCount, bezierCount, [propertyId1, propertyId2]);
|
|
}
|
|
getFrameEntries() {
|
|
return 3;
|
|
}
|
|
setFrame(frame, time, value1, value2) {
|
|
frame *= 3;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = value1;
|
|
this.frames[frame + 2] = value2;
|
|
}
|
|
};
|
|
var RotateTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.rotate + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.rotation = bone.data.rotation;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.rotation += (bone.data.rotation - bone.rotation) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.rotation = bone.data.rotation + r * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
r += bone.data.rotation - bone.rotation;
|
|
case 3 /* add */:
|
|
bone.rotation += r * alpha;
|
|
}
|
|
}
|
|
};
|
|
var TranslateTimeline = class extends CurveTimeline2 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(
|
|
frameCount,
|
|
bezierCount,
|
|
Property.x + "|" + boneIndex,
|
|
Property.y + "|" + boneIndex
|
|
);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x;
|
|
bone.y = bone.data.y;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.x += (bone.data.x - bone.x) * alpha;
|
|
bone.y += (bone.data.y - bone.y) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = 0, y = 0;
|
|
let i = Timeline.search(frames, time, 3);
|
|
let curveType = this.curves[i / 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 3] - before);
|
|
x += (frames[i + 3 + 1] - x) * t;
|
|
y += (frames[i + 3 + 2] - y) * t;
|
|
break;
|
|
case 1:
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
break;
|
|
default:
|
|
x = this.getBezierValue(time, i, 1, curveType - 2);
|
|
y = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x + x * alpha;
|
|
bone.y = bone.data.y + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.x += (bone.data.x + x - bone.x) * alpha;
|
|
bone.y += (bone.data.y + y - bone.y) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.x += x * alpha;
|
|
bone.y += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var TranslateXTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.x + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.x += (bone.data.x - bone.x) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.x = bone.data.x + x * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.x += (bone.data.x + x - bone.x) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.x += x * alpha;
|
|
}
|
|
}
|
|
};
|
|
var TranslateYTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.y + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.y = bone.data.y;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.y += (bone.data.y - bone.y) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let y = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.y = bone.data.y + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.y += (bone.data.y + y - bone.y) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.y += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var ScaleTimeline = class extends CurveTimeline2 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(
|
|
frameCount,
|
|
bezierCount,
|
|
Property.scaleX + "|" + boneIndex,
|
|
Property.scaleY + "|" + boneIndex
|
|
);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.scaleX = bone.data.scaleX;
|
|
bone.scaleY = bone.data.scaleY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
|
|
bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x, y;
|
|
let i = Timeline.search(frames, time, 3);
|
|
let curveType = this.curves[i / 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 3] - before);
|
|
x += (frames[i + 3 + 1] - x) * t;
|
|
y += (frames[i + 3 + 2] - y) * t;
|
|
break;
|
|
case 1:
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
break;
|
|
default:
|
|
x = this.getBezierValue(time, i, 1, curveType - 2);
|
|
y = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
x *= bone.data.scaleX;
|
|
y *= bone.data.scaleY;
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */) {
|
|
bone.scaleX += x - bone.data.scaleX;
|
|
bone.scaleY += y - bone.data.scaleY;
|
|
} else {
|
|
bone.scaleX = x;
|
|
bone.scaleY = y;
|
|
}
|
|
} else {
|
|
let bx = 0, by = 0;
|
|
if (direction == 1 /* mixOut */) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = bone.data.scaleX;
|
|
by = bone.data.scaleY;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = bone.scaleX;
|
|
by = bone.scaleY;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);
|
|
by = Math.abs(bone.data.scaleY) * MathUtils.signum(y);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = Math.abs(bone.scaleX) * MathUtils.signum(x);
|
|
by = Math.abs(bone.scaleY) * MathUtils.signum(y);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var ScaleXTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.scaleX + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.scaleX = bone.data.scaleX;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.scaleX += (bone.data.scaleX - bone.scaleX) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = this.getCurveValue(time) * bone.data.scaleX;
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */)
|
|
bone.scaleX += x - bone.data.scaleX;
|
|
else
|
|
bone.scaleX = x;
|
|
} else {
|
|
let bx = 0;
|
|
if (direction == 1 /* mixOut */) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = bone.data.scaleX;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = bone.scaleX;
|
|
bone.scaleX = bx + (Math.abs(x) * MathUtils.signum(bx) - bx) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bx = Math.abs(bone.data.scaleX) * MathUtils.signum(x);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bx = Math.abs(bone.scaleX) * MathUtils.signum(x);
|
|
bone.scaleX = bx + (x - bx) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleX += (x - bone.data.scaleX) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var ScaleYTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.scaleY + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.scaleY = bone.data.scaleY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.scaleY += (bone.data.scaleY - bone.scaleY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let y = this.getCurveValue(time) * bone.data.scaleY;
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */)
|
|
bone.scaleY += y - bone.data.scaleY;
|
|
else
|
|
bone.scaleY = y;
|
|
} else {
|
|
let by = 0;
|
|
if (direction == 1 /* mixOut */) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
by = bone.data.scaleY;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
by = bone.scaleY;
|
|
bone.scaleY = by + (Math.abs(y) * MathUtils.signum(by) - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
by = Math.abs(bone.data.scaleY) * MathUtils.signum(y);
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
by = Math.abs(bone.scaleY) * MathUtils.signum(y);
|
|
bone.scaleY = by + (y - by) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.scaleY += (y - bone.data.scaleY) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var ShearTimeline = class extends CurveTimeline2 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(
|
|
frameCount,
|
|
bezierCount,
|
|
Property.shearX + "|" + boneIndex,
|
|
Property.shearY + "|" + boneIndex
|
|
);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX;
|
|
bone.shearY = bone.data.shearY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
|
|
bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = 0, y = 0;
|
|
let i = Timeline.search(frames, time, 3);
|
|
let curveType = this.curves[i / 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 3] - before);
|
|
x += (frames[i + 3 + 1] - x) * t;
|
|
y += (frames[i + 3 + 2] - y) * t;
|
|
break;
|
|
case 1:
|
|
x = frames[i + 1];
|
|
y = frames[i + 2];
|
|
break;
|
|
default:
|
|
x = this.getBezierValue(time, i, 1, curveType - 2);
|
|
y = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX + x * alpha;
|
|
bone.shearY = bone.data.shearY + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
|
|
bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.shearX += x * alpha;
|
|
bone.shearY += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var ShearXTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.shearX + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.shearX += (bone.data.shearX - bone.shearX) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let x = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearX = bone.data.shearX + x * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.shearX += (bone.data.shearX + x - bone.shearX) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.shearX += x * alpha;
|
|
}
|
|
}
|
|
};
|
|
var ShearYTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, boneIndex) {
|
|
super(frameCount, bezierCount, Property.shearY + "|" + boneIndex);
|
|
this.boneIndex = 0;
|
|
this.boneIndex = boneIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let bone = skeleton.bones[this.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearY = bone.data.shearY;
|
|
return;
|
|
case 1 /* first */:
|
|
bone.shearY += (bone.data.shearY - bone.shearY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let y = this.getCurveValue(time);
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.shearY = bone.data.shearY + y * alpha;
|
|
break;
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
bone.shearY += (bone.data.shearY + y - bone.shearY) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
bone.shearY += y * alpha;
|
|
}
|
|
}
|
|
};
|
|
var RGBATimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex,
|
|
Property.alpha + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 5;
|
|
}
|
|
setFrame(frame, time, r, g, b, a) {
|
|
frame *= 5;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
this.frames[frame + 4] = a;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let color = slot.color;
|
|
if (time < frames[0]) {
|
|
let setup = slot.data.color;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
color.setFromColor(setup);
|
|
return;
|
|
case 1 /* first */:
|
|
color.add(
|
|
(setup.r - color.r) * alpha,
|
|
(setup.g - color.g) * alpha,
|
|
(setup.b - color.b) * alpha,
|
|
(setup.a - color.a) * alpha
|
|
);
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0, a = 0;
|
|
let i = Timeline.search(frames, time, 5);
|
|
let curveType = this.curves[i / 5];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
let t = (time - before) / (frames[i + 5] - before);
|
|
r += (frames[i + 5 + 1] - r) * t;
|
|
g += (frames[i + 5 + 2] - g) * t;
|
|
b += (frames[i + 5 + 3] - b) * t;
|
|
a += (frames[i + 5 + 4] - a) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
a = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
}
|
|
if (alpha == 1)
|
|
color.set(r, g, b, a);
|
|
else {
|
|
if (blend == 0 /* setup */)
|
|
color.setFromColor(slot.data.color);
|
|
color.add((r - color.r) * alpha, (g - color.g) * alpha, (b - color.b) * alpha, (a - color.a) * alpha);
|
|
}
|
|
}
|
|
};
|
|
var RGBTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 4;
|
|
}
|
|
setFrame(frame, time, r, g, b) {
|
|
frame <<= 2;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let color = slot.color;
|
|
if (time < frames[0]) {
|
|
let setup = slot.data.color;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
color.r = setup.r;
|
|
color.g = setup.g;
|
|
color.b = setup.b;
|
|
return;
|
|
case 1 /* first */:
|
|
color.r += (setup.r - color.r) * alpha;
|
|
color.g += (setup.g - color.g) * alpha;
|
|
color.b += (setup.b - color.b) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0;
|
|
let i = Timeline.search(frames, time, 4);
|
|
let curveType = this.curves[i >> 2];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
let t = (time - before) / (frames[i + 4] - before);
|
|
r += (frames[i + 4 + 1] - r) * t;
|
|
g += (frames[i + 4 + 2] - g) * t;
|
|
b += (frames[i + 4 + 3] - b) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
}
|
|
if (alpha == 1) {
|
|
color.r = r;
|
|
color.g = g;
|
|
color.b = b;
|
|
} else {
|
|
if (blend == 0 /* setup */) {
|
|
let setup = slot.data.color;
|
|
color.r = setup.r;
|
|
color.g = setup.g;
|
|
color.b = setup.b;
|
|
}
|
|
color.r += (r - color.r) * alpha;
|
|
color.g += (g - color.g) * alpha;
|
|
color.b += (b - color.b) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var AlphaTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, Property.alpha + "|" + slotIndex);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let color = slot.color;
|
|
if (time < this.frames[0]) {
|
|
let setup = slot.data.color;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
color.a = setup.a;
|
|
return;
|
|
case 1 /* first */:
|
|
color.a += (setup.a - color.a) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let a = this.getCurveValue(time);
|
|
if (alpha == 1)
|
|
color.a = a;
|
|
else {
|
|
if (blend == 0 /* setup */)
|
|
color.a = slot.data.color.a;
|
|
color.a += (a - color.a) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var RGBA2Timeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex,
|
|
Property.alpha + "|" + slotIndex,
|
|
Property.rgb2 + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 8;
|
|
}
|
|
setFrame(frame, time, r, g, b, a, r2, g2, b2) {
|
|
frame <<= 3;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
this.frames[frame + 4] = a;
|
|
this.frames[frame + 5] = r2;
|
|
this.frames[frame + 6] = g2;
|
|
this.frames[frame + 7] = b2;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let light = slot.color, dark = slot.darkColor;
|
|
if (time < frames[0]) {
|
|
let setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
light.setFromColor(setupLight);
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
return;
|
|
case 1 /* first */:
|
|
light.add(
|
|
(setupLight.r - light.r) * alpha,
|
|
(setupLight.g - light.g) * alpha,
|
|
(setupLight.b - light.b) * alpha,
|
|
(setupLight.a - light.a) * alpha
|
|
);
|
|
dark.r += (setupDark.r - dark.r) * alpha;
|
|
dark.g += (setupDark.g - dark.g) * alpha;
|
|
dark.b += (setupDark.b - dark.b) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;
|
|
let i = Timeline.search(frames, time, 8);
|
|
let curveType = this.curves[i >> 3];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
r2 = frames[i + 5];
|
|
g2 = frames[i + 6];
|
|
b2 = frames[i + 7];
|
|
let t = (time - before) / (frames[i + 8] - before);
|
|
r += (frames[i + 8 + 1] - r) * t;
|
|
g += (frames[i + 8 + 2] - g) * t;
|
|
b += (frames[i + 8 + 3] - b) * t;
|
|
a += (frames[i + 8 + 4] - a) * t;
|
|
r2 += (frames[i + 8 + 5] - r2) * t;
|
|
g2 += (frames[i + 8 + 6] - g2) * t;
|
|
b2 += (frames[i + 8 + 7] - b2) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
a = frames[i + 4];
|
|
r2 = frames[i + 5];
|
|
g2 = frames[i + 6];
|
|
b2 = frames[i + 7];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
a = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
r2 = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2);
|
|
g2 = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2);
|
|
b2 = this.getBezierValue(time, i, 7, curveType + 18 * 6 - 2);
|
|
}
|
|
if (alpha == 1) {
|
|
light.set(r, g, b, a);
|
|
dark.r = r2;
|
|
dark.g = g2;
|
|
dark.b = b2;
|
|
} else {
|
|
if (blend == 0 /* setup */) {
|
|
light.setFromColor(slot.data.color);
|
|
let setupDark = slot.data.darkColor;
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
}
|
|
light.add((r - light.r) * alpha, (g - light.g) * alpha, (b - light.b) * alpha, (a - light.a) * alpha);
|
|
dark.r += (r2 - dark.r) * alpha;
|
|
dark.g += (g2 - dark.g) * alpha;
|
|
dark.b += (b2 - dark.b) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var RGB2Timeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.rgb + "|" + slotIndex,
|
|
Property.rgb2 + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 7;
|
|
}
|
|
setFrame(frame, time, r, g, b, r2, g2, b2) {
|
|
frame *= 7;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = r;
|
|
this.frames[frame + 2] = g;
|
|
this.frames[frame + 3] = b;
|
|
this.frames[frame + 4] = r2;
|
|
this.frames[frame + 5] = g2;
|
|
this.frames[frame + 6] = b2;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let frames = this.frames;
|
|
let light = slot.color, dark = slot.darkColor;
|
|
if (time < frames[0]) {
|
|
let setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
light.r = setupLight.r;
|
|
light.g = setupLight.g;
|
|
light.b = setupLight.b;
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
return;
|
|
case 1 /* first */:
|
|
light.r += (setupLight.r - light.r) * alpha;
|
|
light.g += (setupLight.g - light.g) * alpha;
|
|
light.b += (setupLight.b - light.b) * alpha;
|
|
dark.r += (setupDark.r - dark.r) * alpha;
|
|
dark.g += (setupDark.g - dark.g) * alpha;
|
|
dark.b += (setupDark.b - dark.b) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let r = 0, g = 0, b = 0, a = 0, r2 = 0, g2 = 0, b2 = 0;
|
|
let i = Timeline.search(frames, time, 7);
|
|
let curveType = this.curves[i / 7];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
r2 = frames[i + 4];
|
|
g2 = frames[i + 5];
|
|
b2 = frames[i + 6];
|
|
let t = (time - before) / (frames[i + 7] - before);
|
|
r += (frames[i + 7 + 1] - r) * t;
|
|
g += (frames[i + 7 + 2] - g) * t;
|
|
b += (frames[i + 7 + 3] - b) * t;
|
|
r2 += (frames[i + 7 + 4] - r2) * t;
|
|
g2 += (frames[i + 7 + 5] - g2) * t;
|
|
b2 += (frames[i + 7 + 6] - b2) * t;
|
|
break;
|
|
case 1:
|
|
r = frames[i + 1];
|
|
g = frames[i + 2];
|
|
b = frames[i + 3];
|
|
r2 = frames[i + 4];
|
|
g2 = frames[i + 5];
|
|
b2 = frames[i + 6];
|
|
break;
|
|
default:
|
|
r = this.getBezierValue(time, i, 1, curveType - 2);
|
|
g = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
b = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
r2 = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
g2 = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2);
|
|
b2 = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2);
|
|
}
|
|
if (alpha == 1) {
|
|
light.r = r;
|
|
light.g = g;
|
|
light.b = b;
|
|
dark.r = r2;
|
|
dark.g = g2;
|
|
dark.b = b2;
|
|
} else {
|
|
if (blend == 0 /* setup */) {
|
|
let setupLight = slot.data.color, setupDark = slot.data.darkColor;
|
|
light.r = setupLight.r;
|
|
light.g = setupLight.g;
|
|
light.b = setupLight.b;
|
|
dark.r = setupDark.r;
|
|
dark.g = setupDark.g;
|
|
dark.b = setupDark.b;
|
|
}
|
|
light.r += (r - light.r) * alpha;
|
|
light.g += (g - light.g) * alpha;
|
|
light.b += (b - light.b) * alpha;
|
|
dark.r += (r2 - dark.r) * alpha;
|
|
dark.g += (g2 - dark.g) * alpha;
|
|
dark.b += (b2 - dark.b) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var AttachmentTimeline = class extends Timeline {
|
|
constructor(frameCount, slotIndex) {
|
|
super(frameCount, [
|
|
Property.attachment + "|" + slotIndex
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
this.attachmentNames = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, time, attachmentName) {
|
|
this.frames[frame] = time;
|
|
this.attachmentNames[frame] = attachmentName;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
if (direction == 1 /* mixOut */) {
|
|
if (blend == 0 /* setup */)
|
|
this.setAttachment(skeleton, slot, slot.data.attachmentName);
|
|
return;
|
|
}
|
|
if (time < this.frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
this.setAttachment(skeleton, slot, slot.data.attachmentName);
|
|
return;
|
|
}
|
|
this.setAttachment(skeleton, slot, this.attachmentNames[Timeline.search1(this.frames, time)]);
|
|
}
|
|
setAttachment(skeleton, slot, attachmentName) {
|
|
slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(this.slotIndex, attachmentName));
|
|
}
|
|
};
|
|
var DeformTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, slotIndex, attachment) {
|
|
super(frameCount, bezierCount, [
|
|
Property.deform + "|" + slotIndex + "|" + attachment.id
|
|
]);
|
|
this.slotIndex = 0;
|
|
this.slotIndex = slotIndex;
|
|
this.attachment = attachment;
|
|
this.vertices = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, time, vertices) {
|
|
this.frames[frame] = time;
|
|
this.vertices[frame] = vertices;
|
|
}
|
|
setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2) {
|
|
let curves = this.curves;
|
|
let i = this.getFrameCount() + bezier * 18;
|
|
if (value == 0)
|
|
curves[frame] = 2 + i;
|
|
let tmpx = (time1 - cx1 * 2 + cx2) * 0.03, tmpy = cy2 * 0.03 - cy1 * 0.06;
|
|
let dddx = ((cx1 - cx2) * 3 - time1 + time2) * 6e-3, dddy = (cy1 - cy2 + 0.33333333) * 0.018;
|
|
let ddx = tmpx * 2 + dddx, ddy = tmpy * 2 + dddy;
|
|
let dx = (cx1 - time1) * 0.3 + tmpx + dddx * 0.16666667, dy = cy1 * 0.3 + tmpy + dddy * 0.16666667;
|
|
let x = time1 + dx, y = dy;
|
|
for (let n = i + 18; i < n; i += 2) {
|
|
curves[i] = x;
|
|
curves[i + 1] = y;
|
|
dx += ddx;
|
|
dy += ddy;
|
|
ddx += dddx;
|
|
ddy += dddy;
|
|
x += dx;
|
|
y += dy;
|
|
}
|
|
}
|
|
getCurvePercent(time, frame) {
|
|
let curves = this.curves;
|
|
let i = curves[frame];
|
|
switch (i) {
|
|
case 0:
|
|
let x2 = this.frames[frame];
|
|
return (time - x2) / (this.frames[frame + this.getFrameEntries()] - x2);
|
|
case 1:
|
|
return 0;
|
|
}
|
|
i -= 2;
|
|
if (curves[i] > time) {
|
|
let x2 = this.frames[frame];
|
|
return curves[i + 1] * (time - x2) / (curves[i] - x2);
|
|
}
|
|
let n = i + 18;
|
|
for (i += 2; i < n; i += 2) {
|
|
if (curves[i] >= time) {
|
|
let x2 = curves[i - 2], y2 = curves[i - 1];
|
|
return y2 + (time - x2) / (curves[i] - x2) * (curves[i + 1] - y2);
|
|
}
|
|
}
|
|
let x = curves[n - 2], y = curves[n - 1];
|
|
return y + (1 - y) * (time - x) / (this.frames[frame + this.getFrameEntries()] - x);
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let slotAttachment = slot.getAttachment();
|
|
if (!slotAttachment)
|
|
return;
|
|
if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != this.attachment)
|
|
return;
|
|
let deform = slot.deform;
|
|
if (deform.length == 0)
|
|
blend = 0 /* setup */;
|
|
let vertices = this.vertices;
|
|
let vertexCount = vertices[0].length;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
deform.length = 0;
|
|
return;
|
|
case 1 /* first */:
|
|
if (alpha == 1) {
|
|
deform.length = 0;
|
|
return;
|
|
}
|
|
deform.length = vertexCount;
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (var i = 0; i < vertexCount; i++)
|
|
deform[i] += (setupVertices[i] - deform[i]) * alpha;
|
|
} else {
|
|
alpha = 1 - alpha;
|
|
for (var i = 0; i < vertexCount; i++)
|
|
deform[i] *= alpha;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
deform.length = vertexCount;
|
|
if (time >= frames[frames.length - 1]) {
|
|
let lastVertices = vertices[frames.length - 1];
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */) {
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += lastVertices[i2] - setupVertices[i2];
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += lastVertices[i2];
|
|
}
|
|
} else
|
|
Utils.arrayCopy(lastVertices, 0, deform, 0, vertexCount);
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */: {
|
|
let vertexAttachment2 = slotAttachment;
|
|
if (!vertexAttachment2.bones) {
|
|
let setupVertices = vertexAttachment2.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let setup = setupVertices[i2];
|
|
deform[i2] = setup + (lastVertices[i2] - setup) * alpha;
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] = lastVertices[i2] * alpha;
|
|
}
|
|
break;
|
|
}
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += (lastVertices[i2] - deform[i2]) * alpha;
|
|
break;
|
|
case 3 /* add */:
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += (lastVertices[i2] - setupVertices[i2]) * alpha;
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++)
|
|
deform[i2] += lastVertices[i2] * alpha;
|
|
}
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
let frame = Timeline.search1(frames, time);
|
|
let percent = this.getCurvePercent(time, frame);
|
|
let prevVertices = vertices[frame];
|
|
let nextVertices = vertices[frame + 1];
|
|
if (alpha == 1) {
|
|
if (blend == 3 /* add */) {
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += prev + (nextVertices[i2] - prev) * percent - setupVertices[i2];
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += prev + (nextVertices[i2] - prev) * percent;
|
|
}
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] = prev + (nextVertices[i2] - prev) * percent;
|
|
}
|
|
}
|
|
} else {
|
|
switch (blend) {
|
|
case 0 /* setup */: {
|
|
let vertexAttachment2 = slotAttachment;
|
|
if (!vertexAttachment2.bones) {
|
|
let setupVertices = vertexAttachment2.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2], setup = setupVertices[i2];
|
|
deform[i2] = setup + (prev + (nextVertices[i2] - prev) * percent - setup) * alpha;
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] = (prev + (nextVertices[i2] - prev) * percent) * alpha;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 1 /* first */:
|
|
case 2 /* replace */:
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += (prev + (nextVertices[i2] - prev) * percent - deform[i2]) * alpha;
|
|
}
|
|
break;
|
|
case 3 /* add */:
|
|
let vertexAttachment = slotAttachment;
|
|
if (!vertexAttachment.bones) {
|
|
let setupVertices = vertexAttachment.vertices;
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += (prev + (nextVertices[i2] - prev) * percent - setupVertices[i2]) * alpha;
|
|
}
|
|
} else {
|
|
for (let i2 = 0; i2 < vertexCount; i2++) {
|
|
let prev = prevVertices[i2];
|
|
deform[i2] += (prev + (nextVertices[i2] - prev) * percent) * alpha;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var _EventTimeline = class extends Timeline {
|
|
constructor(frameCount) {
|
|
super(frameCount, _EventTimeline.propertyIds);
|
|
this.events = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, event) {
|
|
this.frames[frame] = event.time;
|
|
this.events[frame] = event;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
if (!firedEvents)
|
|
return;
|
|
let frames = this.frames;
|
|
let frameCount = this.frames.length;
|
|
if (lastTime > time) {
|
|
this.apply(skeleton, lastTime, Number.MAX_VALUE, firedEvents, alpha, blend, direction);
|
|
lastTime = -1;
|
|
} else if (lastTime >= frames[frameCount - 1])
|
|
return;
|
|
if (time < frames[0])
|
|
return;
|
|
let i = 0;
|
|
if (lastTime < frames[0])
|
|
i = 0;
|
|
else {
|
|
i = Timeline.search1(frames, lastTime) + 1;
|
|
let frameTime = frames[i];
|
|
while (i > 0) {
|
|
if (frames[i - 1] != frameTime)
|
|
break;
|
|
i--;
|
|
}
|
|
}
|
|
for (; i < frameCount && time >= frames[i]; i++)
|
|
firedEvents.push(this.events[i]);
|
|
}
|
|
};
|
|
var EventTimeline = _EventTimeline;
|
|
EventTimeline.propertyIds = ["" + Property.event];
|
|
var _DrawOrderTimeline = class extends Timeline {
|
|
constructor(frameCount) {
|
|
super(frameCount, _DrawOrderTimeline.propertyIds);
|
|
this.drawOrders = new Array(frameCount);
|
|
}
|
|
getFrameCount() {
|
|
return this.frames.length;
|
|
}
|
|
setFrame(frame, time, drawOrder) {
|
|
this.frames[frame] = time;
|
|
this.drawOrders[frame] = drawOrder;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
if (direction == 1 /* mixOut */) {
|
|
if (blend == 0 /* setup */)
|
|
Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
|
|
return;
|
|
}
|
|
if (time < this.frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
|
|
return;
|
|
}
|
|
let idx = Timeline.search1(this.frames, time);
|
|
let drawOrderToSetupIndex = this.drawOrders[idx];
|
|
if (!drawOrderToSetupIndex)
|
|
Utils.arrayCopy(skeleton.slots, 0, skeleton.drawOrder, 0, skeleton.slots.length);
|
|
else {
|
|
let drawOrder = skeleton.drawOrder;
|
|
let slots = skeleton.slots;
|
|
for (let i = 0, n = drawOrderToSetupIndex.length; i < n; i++)
|
|
drawOrder[i] = slots[drawOrderToSetupIndex[i]];
|
|
}
|
|
}
|
|
};
|
|
var DrawOrderTimeline = _DrawOrderTimeline;
|
|
DrawOrderTimeline.propertyIds = ["" + Property.drawOrder];
|
|
var IkConstraintTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, ikConstraintIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.ikConstraint + "|" + ikConstraintIndex
|
|
]);
|
|
this.ikConstraintIndex = 0;
|
|
this.ikConstraintIndex = ikConstraintIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 6;
|
|
}
|
|
setFrame(frame, time, mix, softness, bendDirection, compress, stretch) {
|
|
frame *= 6;
|
|
this.frames[frame] = time;
|
|
this.frames[frame + 1] = mix;
|
|
this.frames[frame + 2] = softness;
|
|
this.frames[frame + 3] = bendDirection;
|
|
this.frames[frame + 4] = compress ? 1 : 0;
|
|
this.frames[frame + 5] = stretch ? 1 : 0;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.ikConstraints[this.ikConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.mix = constraint.data.mix;
|
|
constraint.softness = constraint.data.softness;
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.mix += (constraint.data.mix - constraint.mix) * alpha;
|
|
constraint.softness += (constraint.data.softness - constraint.softness) * alpha;
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
}
|
|
return;
|
|
}
|
|
let mix = 0, softness = 0;
|
|
let i = Timeline.search(frames, time, 6);
|
|
let curveType = this.curves[i / 6];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
mix = frames[i + 1];
|
|
softness = frames[i + 2];
|
|
let t = (time - before) / (frames[i + 6] - before);
|
|
mix += (frames[i + 6 + 1] - mix) * t;
|
|
softness += (frames[i + 6 + 2] - softness) * t;
|
|
break;
|
|
case 1:
|
|
mix = frames[i + 1];
|
|
softness = frames[i + 2];
|
|
break;
|
|
default:
|
|
mix = this.getBezierValue(time, i, 1, curveType - 2);
|
|
softness = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
}
|
|
if (blend == 0 /* setup */) {
|
|
constraint.mix = constraint.data.mix + (mix - constraint.data.mix) * alpha;
|
|
constraint.softness = constraint.data.softness + (softness - constraint.data.softness) * alpha;
|
|
if (direction == 1 /* mixOut */) {
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
} else {
|
|
constraint.bendDirection = frames[i + 3];
|
|
constraint.compress = frames[i + 4] != 0;
|
|
constraint.stretch = frames[i + 5] != 0;
|
|
}
|
|
} else {
|
|
constraint.mix += (mix - constraint.mix) * alpha;
|
|
constraint.softness += (softness - constraint.softness) * alpha;
|
|
if (direction == 0 /* mixIn */) {
|
|
constraint.bendDirection = frames[i + 3];
|
|
constraint.compress = frames[i + 4] != 0;
|
|
constraint.stretch = frames[i + 5] != 0;
|
|
}
|
|
}
|
|
}
|
|
};
|
|
var TransformConstraintTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, transformConstraintIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.transformConstraint + "|" + transformConstraintIndex
|
|
]);
|
|
this.transformConstraintIndex = 0;
|
|
this.transformConstraintIndex = transformConstraintIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 7;
|
|
}
|
|
setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY) {
|
|
let frames = this.frames;
|
|
frame *= 7;
|
|
frames[frame] = time;
|
|
frames[frame + 1] = mixRotate;
|
|
frames[frame + 2] = mixX;
|
|
frames[frame + 3] = mixY;
|
|
frames[frame + 4] = mixScaleX;
|
|
frames[frame + 5] = mixScaleY;
|
|
frames[frame + 6] = mixShearY;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.transformConstraints[this.transformConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
let data = constraint.data;
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.mixRotate = data.mixRotate;
|
|
constraint.mixX = data.mixX;
|
|
constraint.mixY = data.mixY;
|
|
constraint.mixScaleX = data.mixScaleX;
|
|
constraint.mixScaleY = data.mixScaleY;
|
|
constraint.mixShearY = data.mixShearY;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.mixRotate += (data.mixRotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (data.mixX - constraint.mixX) * alpha;
|
|
constraint.mixY += (data.mixY - constraint.mixY) * alpha;
|
|
constraint.mixScaleX += (data.mixScaleX - constraint.mixScaleX) * alpha;
|
|
constraint.mixScaleY += (data.mixScaleY - constraint.mixScaleY) * alpha;
|
|
constraint.mixShearY += (data.mixShearY - constraint.mixShearY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let rotate, x, y, scaleX, scaleY, shearY;
|
|
let i = Timeline.search(frames, time, 7);
|
|
let curveType = this.curves[i / 7];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
scaleX = frames[i + 4];
|
|
scaleY = frames[i + 5];
|
|
shearY = frames[i + 6];
|
|
let t = (time - before) / (frames[i + 7] - before);
|
|
rotate += (frames[i + 7 + 1] - rotate) * t;
|
|
x += (frames[i + 7 + 2] - x) * t;
|
|
y += (frames[i + 7 + 3] - y) * t;
|
|
scaleX += (frames[i + 7 + 4] - scaleX) * t;
|
|
scaleY += (frames[i + 7 + 5] - scaleY) * t;
|
|
shearY += (frames[i + 7 + 6] - shearY) * t;
|
|
break;
|
|
case 1:
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
scaleX = frames[i + 4];
|
|
scaleY = frames[i + 5];
|
|
shearY = frames[i + 6];
|
|
break;
|
|
default:
|
|
rotate = this.getBezierValue(time, i, 1, curveType - 2);
|
|
x = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
y = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
scaleX = this.getBezierValue(time, i, 4, curveType + 18 * 3 - 2);
|
|
scaleY = this.getBezierValue(time, i, 5, curveType + 18 * 4 - 2);
|
|
shearY = this.getBezierValue(time, i, 6, curveType + 18 * 5 - 2);
|
|
}
|
|
if (blend == 0 /* setup */) {
|
|
let data = constraint.data;
|
|
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
|
|
constraint.mixX = data.mixX + (x - data.mixX) * alpha;
|
|
constraint.mixY = data.mixY + (y - data.mixY) * alpha;
|
|
constraint.mixScaleX = data.mixScaleX + (scaleX - data.mixScaleX) * alpha;
|
|
constraint.mixScaleY = data.mixScaleY + (scaleY - data.mixScaleY) * alpha;
|
|
constraint.mixShearY = data.mixShearY + (shearY - data.mixShearY) * alpha;
|
|
} else {
|
|
constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (x - constraint.mixX) * alpha;
|
|
constraint.mixY += (y - constraint.mixY) * alpha;
|
|
constraint.mixScaleX += (scaleX - constraint.mixScaleX) * alpha;
|
|
constraint.mixScaleY += (scaleY - constraint.mixScaleY) * alpha;
|
|
constraint.mixShearY += (shearY - constraint.mixShearY) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var PathConstraintPositionTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, pathConstraintIndex) {
|
|
super(frameCount, bezierCount, Property.pathConstraintPosition + "|" + pathConstraintIndex);
|
|
this.pathConstraintIndex = 0;
|
|
this.pathConstraintIndex = pathConstraintIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.pathConstraints[this.pathConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.position = constraint.data.position;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.position += (constraint.data.position - constraint.position) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let position = this.getCurveValue(time);
|
|
if (blend == 0 /* setup */)
|
|
constraint.position = constraint.data.position + (position - constraint.data.position) * alpha;
|
|
else
|
|
constraint.position += (position - constraint.position) * alpha;
|
|
}
|
|
};
|
|
var PathConstraintSpacingTimeline = class extends CurveTimeline1 {
|
|
constructor(frameCount, bezierCount, pathConstraintIndex) {
|
|
super(frameCount, bezierCount, Property.pathConstraintSpacing + "|" + pathConstraintIndex);
|
|
this.pathConstraintIndex = 0;
|
|
this.pathConstraintIndex = pathConstraintIndex;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.pathConstraints[this.pathConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.spacing = constraint.data.spacing;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.spacing += (constraint.data.spacing - constraint.spacing) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let spacing = this.getCurveValue(time);
|
|
if (blend == 0 /* setup */)
|
|
constraint.spacing = constraint.data.spacing + (spacing - constraint.data.spacing) * alpha;
|
|
else
|
|
constraint.spacing += (spacing - constraint.spacing) * alpha;
|
|
}
|
|
};
|
|
var PathConstraintMixTimeline = class extends CurveTimeline {
|
|
constructor(frameCount, bezierCount, pathConstraintIndex) {
|
|
super(frameCount, bezierCount, [
|
|
Property.pathConstraintMix + "|" + pathConstraintIndex
|
|
]);
|
|
this.pathConstraintIndex = 0;
|
|
this.pathConstraintIndex = pathConstraintIndex;
|
|
}
|
|
getFrameEntries() {
|
|
return 4;
|
|
}
|
|
setFrame(frame, time, mixRotate, mixX, mixY) {
|
|
let frames = this.frames;
|
|
frame <<= 2;
|
|
frames[frame] = time;
|
|
frames[frame + 1] = mixRotate;
|
|
frames[frame + 2] = mixX;
|
|
frames[frame + 3] = mixY;
|
|
}
|
|
apply(skeleton, lastTime, time, firedEvents, alpha, blend, direction) {
|
|
let constraint = skeleton.pathConstraints[this.pathConstraintIndex];
|
|
if (!constraint.active)
|
|
return;
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
constraint.mixRotate = constraint.data.mixRotate;
|
|
constraint.mixX = constraint.data.mixX;
|
|
constraint.mixY = constraint.data.mixY;
|
|
return;
|
|
case 1 /* first */:
|
|
constraint.mixRotate += (constraint.data.mixRotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (constraint.data.mixX - constraint.mixX) * alpha;
|
|
constraint.mixY += (constraint.data.mixY - constraint.mixY) * alpha;
|
|
}
|
|
return;
|
|
}
|
|
let rotate, x, y;
|
|
let i = Timeline.search(frames, time, 4);
|
|
let curveType = this.curves[i >> 2];
|
|
switch (curveType) {
|
|
case 0:
|
|
let before = frames[i];
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
let t = (time - before) / (frames[i + 4] - before);
|
|
rotate += (frames[i + 4 + 1] - rotate) * t;
|
|
x += (frames[i + 4 + 2] - x) * t;
|
|
y += (frames[i + 4 + 3] - y) * t;
|
|
break;
|
|
case 1:
|
|
rotate = frames[i + 1];
|
|
x = frames[i + 2];
|
|
y = frames[i + 3];
|
|
break;
|
|
default:
|
|
rotate = this.getBezierValue(time, i, 1, curveType - 2);
|
|
x = this.getBezierValue(time, i, 2, curveType + 18 - 2);
|
|
y = this.getBezierValue(time, i, 3, curveType + 18 * 2 - 2);
|
|
}
|
|
if (blend == 0 /* setup */) {
|
|
let data = constraint.data;
|
|
constraint.mixRotate = data.mixRotate + (rotate - data.mixRotate) * alpha;
|
|
constraint.mixX = data.mixX + (x - data.mixX) * alpha;
|
|
constraint.mixY = data.mixY + (y - data.mixY) * alpha;
|
|
} else {
|
|
constraint.mixRotate += (rotate - constraint.mixRotate) * alpha;
|
|
constraint.mixX += (x - constraint.mixX) * alpha;
|
|
constraint.mixY += (y - constraint.mixY) * alpha;
|
|
}
|
|
}
|
|
};
|
|
var _SequenceTimeline = class extends Timeline {
|
|
constructor(frameCount, slotIndex, attachment) {
|
|
super(frameCount, [
|
|
Property.sequence + "|" + slotIndex + "|" + attachment.sequence.id
|
|
]);
|
|
this.slotIndex = slotIndex;
|
|
this.attachment = attachment;
|
|
}
|
|
getFrameEntries() {
|
|
return _SequenceTimeline.ENTRIES;
|
|
}
|
|
getSlotIndex() {
|
|
return this.slotIndex;
|
|
}
|
|
getAttachment() {
|
|
return this.attachment;
|
|
}
|
|
setFrame(frame, time, mode, index, delay) {
|
|
let frames = this.frames;
|
|
frame *= _SequenceTimeline.ENTRIES;
|
|
frames[frame] = time;
|
|
frames[frame + _SequenceTimeline.MODE] = mode | index << 4;
|
|
frames[frame + _SequenceTimeline.DELAY] = delay;
|
|
}
|
|
apply(skeleton, lastTime, time, events, alpha, blend, direction) {
|
|
let slot = skeleton.slots[this.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
let slotAttachment = slot.attachment;
|
|
let attachment = this.attachment;
|
|
if (slotAttachment != attachment) {
|
|
if (!(slotAttachment instanceof VertexAttachment) || slotAttachment.timelineAttachment != attachment)
|
|
return;
|
|
}
|
|
let frames = this.frames;
|
|
if (time < frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
slot.sequenceIndex = -1;
|
|
return;
|
|
}
|
|
let i = Timeline.search(frames, time, _SequenceTimeline.ENTRIES);
|
|
let before = frames[i];
|
|
let modeAndIndex = frames[i + _SequenceTimeline.MODE];
|
|
let delay = frames[i + _SequenceTimeline.DELAY];
|
|
if (!this.attachment.sequence)
|
|
return;
|
|
let index = modeAndIndex >> 4, count = this.attachment.sequence.regions.length;
|
|
let mode = SequenceModeValues[modeAndIndex & 15];
|
|
if (mode != 0 /* hold */) {
|
|
index += (time - before) / delay + 1e-5 | 0;
|
|
switch (mode) {
|
|
case 1 /* once */:
|
|
index = Math.min(count - 1, index);
|
|
break;
|
|
case 2 /* loop */:
|
|
index %= count;
|
|
break;
|
|
case 3 /* pingpong */: {
|
|
let n = (count << 1) - 2;
|
|
index = n == 0 ? 0 : index % n;
|
|
if (index >= count)
|
|
index = n - index;
|
|
break;
|
|
}
|
|
case 4 /* onceReverse */:
|
|
index = Math.max(count - 1 - index, 0);
|
|
break;
|
|
case 5 /* loopReverse */:
|
|
index = count - 1 - index % count;
|
|
break;
|
|
case 6 /* pingpongReverse */: {
|
|
let n = (count << 1) - 2;
|
|
index = n == 0 ? 0 : (index + count - 1) % n;
|
|
if (index >= count)
|
|
index = n - index;
|
|
}
|
|
}
|
|
}
|
|
slot.sequenceIndex = index;
|
|
}
|
|
};
|
|
var SequenceTimeline = _SequenceTimeline;
|
|
SequenceTimeline.ENTRIES = 3;
|
|
SequenceTimeline.MODE = 1;
|
|
SequenceTimeline.DELAY = 2;
|
|
|
|
// spine-core/src/AnimationState.ts
|
|
var _AnimationState = class {
|
|
constructor(data) {
|
|
this.tracks = new Array();
|
|
this.timeScale = 1;
|
|
this.unkeyedState = 0;
|
|
this.events = new Array();
|
|
this.listeners = new Array();
|
|
this.queue = new EventQueue(this);
|
|
this.propertyIDs = new StringSet();
|
|
this.animationsChanged = false;
|
|
this.trackEntryPool = new Pool(() => new TrackEntry());
|
|
this.data = data;
|
|
}
|
|
static emptyAnimation() {
|
|
return _AnimationState._emptyAnimation;
|
|
}
|
|
update(delta) {
|
|
delta *= this.timeScale;
|
|
let tracks = this.tracks;
|
|
for (let i = 0, n = tracks.length; i < n; i++) {
|
|
let current = tracks[i];
|
|
if (!current)
|
|
continue;
|
|
current.animationLast = current.nextAnimationLast;
|
|
current.trackLast = current.nextTrackLast;
|
|
let currentDelta = delta * current.timeScale;
|
|
if (current.delay > 0) {
|
|
current.delay -= currentDelta;
|
|
if (current.delay > 0)
|
|
continue;
|
|
currentDelta = -current.delay;
|
|
current.delay = 0;
|
|
}
|
|
let next = current.next;
|
|
if (next) {
|
|
let nextTime = current.trackLast - next.delay;
|
|
if (nextTime >= 0) {
|
|
next.delay = 0;
|
|
next.trackTime += current.timeScale == 0 ? 0 : (nextTime / current.timeScale + delta) * next.timeScale;
|
|
current.trackTime += currentDelta;
|
|
this.setCurrent(i, next, true);
|
|
while (next.mixingFrom) {
|
|
next.mixTime += delta;
|
|
next = next.mixingFrom;
|
|
}
|
|
continue;
|
|
}
|
|
} else if (current.trackLast >= current.trackEnd && !current.mixingFrom) {
|
|
tracks[i] = null;
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
continue;
|
|
}
|
|
if (current.mixingFrom && this.updateMixingFrom(current, delta)) {
|
|
let from = current.mixingFrom;
|
|
current.mixingFrom = null;
|
|
if (from)
|
|
from.mixingTo = null;
|
|
while (from) {
|
|
this.queue.end(from);
|
|
from = from.mixingFrom;
|
|
}
|
|
}
|
|
current.trackTime += currentDelta;
|
|
}
|
|
this.queue.drain();
|
|
}
|
|
updateMixingFrom(to, delta) {
|
|
let from = to.mixingFrom;
|
|
if (!from)
|
|
return true;
|
|
let finished = this.updateMixingFrom(from, delta);
|
|
from.animationLast = from.nextAnimationLast;
|
|
from.trackLast = from.nextTrackLast;
|
|
if (to.mixTime > 0 && to.mixTime >= to.mixDuration) {
|
|
if (from.totalAlpha == 0 || to.mixDuration == 0) {
|
|
to.mixingFrom = from.mixingFrom;
|
|
if (from.mixingFrom)
|
|
from.mixingFrom.mixingTo = to;
|
|
to.interruptAlpha = from.interruptAlpha;
|
|
this.queue.end(from);
|
|
}
|
|
return finished;
|
|
}
|
|
from.trackTime += delta * from.timeScale;
|
|
to.mixTime += delta;
|
|
return false;
|
|
}
|
|
apply(skeleton) {
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
if (this.animationsChanged)
|
|
this._animationsChanged();
|
|
let events = this.events;
|
|
let tracks = this.tracks;
|
|
let applied = false;
|
|
for (let i2 = 0, n2 = tracks.length; i2 < n2; i2++) {
|
|
let current = tracks[i2];
|
|
if (!current || current.delay > 0)
|
|
continue;
|
|
applied = true;
|
|
let blend = i2 == 0 ? 1 /* first */ : current.mixBlend;
|
|
let mix = current.alpha;
|
|
if (current.mixingFrom)
|
|
mix *= this.applyMixingFrom(current, skeleton, blend);
|
|
else if (current.trackTime >= current.trackEnd && !current.next)
|
|
mix = 0;
|
|
let animationLast = current.animationLast, animationTime = current.getAnimationTime(), applyTime = animationTime;
|
|
let applyEvents = events;
|
|
if (current.reverse) {
|
|
applyTime = current.animation.duration - applyTime;
|
|
applyEvents = null;
|
|
}
|
|
let timelines = current.animation.timelines;
|
|
let timelineCount = timelines.length;
|
|
if (i2 == 0 && mix == 1 || blend == 3 /* add */) {
|
|
for (let ii = 0; ii < timelineCount; ii++) {
|
|
Utils.webkit602BugfixHelper(mix, blend);
|
|
var timeline = timelines[ii];
|
|
if (timeline instanceof AttachmentTimeline)
|
|
this.applyAttachmentTimeline(timeline, skeleton, applyTime, blend, true);
|
|
else
|
|
timeline.apply(skeleton, animationLast, applyTime, applyEvents, mix, blend, 0 /* mixIn */);
|
|
}
|
|
} else {
|
|
let timelineMode = current.timelineMode;
|
|
let shortestRotation = current.shortestRotation;
|
|
let firstFrame = !shortestRotation && current.timelinesRotation.length != timelineCount << 1;
|
|
if (firstFrame)
|
|
current.timelinesRotation.length = timelineCount << 1;
|
|
for (let ii = 0; ii < timelineCount; ii++) {
|
|
let timeline2 = timelines[ii];
|
|
let timelineBlend = timelineMode[ii] == SUBSEQUENT ? blend : 0 /* setup */;
|
|
if (!shortestRotation && timeline2 instanceof RotateTimeline) {
|
|
this.applyRotateTimeline(timeline2, skeleton, applyTime, mix, timelineBlend, current.timelinesRotation, ii << 1, firstFrame);
|
|
} else if (timeline2 instanceof AttachmentTimeline) {
|
|
this.applyAttachmentTimeline(timeline2, skeleton, applyTime, blend, true);
|
|
} else {
|
|
Utils.webkit602BugfixHelper(mix, blend);
|
|
timeline2.apply(skeleton, animationLast, applyTime, applyEvents, mix, timelineBlend, 0 /* mixIn */);
|
|
}
|
|
}
|
|
}
|
|
this.queueEvents(current, animationTime);
|
|
events.length = 0;
|
|
current.nextAnimationLast = animationTime;
|
|
current.nextTrackLast = current.trackTime;
|
|
}
|
|
var setupState = this.unkeyedState + SETUP;
|
|
var slots = skeleton.slots;
|
|
for (var i = 0, n = skeleton.slots.length; i < n; i++) {
|
|
var slot = slots[i];
|
|
if (slot.attachmentState == setupState) {
|
|
var attachmentName = slot.data.attachmentName;
|
|
slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));
|
|
}
|
|
}
|
|
this.unkeyedState += 2;
|
|
this.queue.drain();
|
|
return applied;
|
|
}
|
|
applyMixingFrom(to, skeleton, blend) {
|
|
let from = to.mixingFrom;
|
|
if (from.mixingFrom)
|
|
this.applyMixingFrom(from, skeleton, blend);
|
|
let mix = 0;
|
|
if (to.mixDuration == 0) {
|
|
mix = 1;
|
|
if (blend == 1 /* first */)
|
|
blend = 0 /* setup */;
|
|
} else {
|
|
mix = to.mixTime / to.mixDuration;
|
|
if (mix > 1)
|
|
mix = 1;
|
|
if (blend != 1 /* first */)
|
|
blend = from.mixBlend;
|
|
}
|
|
let attachments = mix < from.attachmentThreshold, drawOrder = mix < from.drawOrderThreshold;
|
|
let timelines = from.animation.timelines;
|
|
let timelineCount = timelines.length;
|
|
let alphaHold = from.alpha * to.interruptAlpha, alphaMix = alphaHold * (1 - mix);
|
|
let animationLast = from.animationLast, animationTime = from.getAnimationTime(), applyTime = animationTime;
|
|
let events = null;
|
|
if (from.reverse)
|
|
applyTime = from.animation.duration - applyTime;
|
|
else if (mix < from.eventThreshold)
|
|
events = this.events;
|
|
if (blend == 3 /* add */) {
|
|
for (let i = 0; i < timelineCount; i++)
|
|
timelines[i].apply(skeleton, animationLast, applyTime, events, alphaMix, blend, 1 /* mixOut */);
|
|
} else {
|
|
let timelineMode = from.timelineMode;
|
|
let timelineHoldMix = from.timelineHoldMix;
|
|
let shortestRotation = from.shortestRotation;
|
|
let firstFrame = !shortestRotation && from.timelinesRotation.length != timelineCount << 1;
|
|
if (firstFrame)
|
|
from.timelinesRotation.length = timelineCount << 1;
|
|
from.totalAlpha = 0;
|
|
for (let i = 0; i < timelineCount; i++) {
|
|
let timeline = timelines[i];
|
|
let direction = 1 /* mixOut */;
|
|
let timelineBlend;
|
|
let alpha = 0;
|
|
switch (timelineMode[i]) {
|
|
case SUBSEQUENT:
|
|
if (!drawOrder && timeline instanceof DrawOrderTimeline)
|
|
continue;
|
|
timelineBlend = blend;
|
|
alpha = alphaMix;
|
|
break;
|
|
case FIRST:
|
|
timelineBlend = 0 /* setup */;
|
|
alpha = alphaMix;
|
|
break;
|
|
case HOLD_SUBSEQUENT:
|
|
timelineBlend = blend;
|
|
alpha = alphaHold;
|
|
break;
|
|
case HOLD_FIRST:
|
|
timelineBlend = 0 /* setup */;
|
|
alpha = alphaHold;
|
|
break;
|
|
default:
|
|
timelineBlend = 0 /* setup */;
|
|
let holdMix = timelineHoldMix[i];
|
|
alpha = alphaHold * Math.max(0, 1 - holdMix.mixTime / holdMix.mixDuration);
|
|
break;
|
|
}
|
|
from.totalAlpha += alpha;
|
|
if (!shortestRotation && timeline instanceof RotateTimeline)
|
|
this.applyRotateTimeline(timeline, skeleton, applyTime, alpha, timelineBlend, from.timelinesRotation, i << 1, firstFrame);
|
|
else if (timeline instanceof AttachmentTimeline)
|
|
this.applyAttachmentTimeline(timeline, skeleton, applyTime, timelineBlend, attachments);
|
|
else {
|
|
Utils.webkit602BugfixHelper(alpha, blend);
|
|
if (drawOrder && timeline instanceof DrawOrderTimeline && timelineBlend == 0 /* setup */)
|
|
direction = 0 /* mixIn */;
|
|
timeline.apply(skeleton, animationLast, applyTime, events, alpha, timelineBlend, direction);
|
|
}
|
|
}
|
|
}
|
|
if (to.mixDuration > 0)
|
|
this.queueEvents(from, animationTime);
|
|
this.events.length = 0;
|
|
from.nextAnimationLast = animationTime;
|
|
from.nextTrackLast = from.trackTime;
|
|
return mix;
|
|
}
|
|
applyAttachmentTimeline(timeline, skeleton, time, blend, attachments) {
|
|
var slot = skeleton.slots[timeline.slotIndex];
|
|
if (!slot.bone.active)
|
|
return;
|
|
if (time < timeline.frames[0]) {
|
|
if (blend == 0 /* setup */ || blend == 1 /* first */)
|
|
this.setAttachment(skeleton, slot, slot.data.attachmentName, attachments);
|
|
} else
|
|
this.setAttachment(skeleton, slot, timeline.attachmentNames[Timeline.search1(timeline.frames, time)], attachments);
|
|
if (slot.attachmentState <= this.unkeyedState)
|
|
slot.attachmentState = this.unkeyedState + SETUP;
|
|
}
|
|
setAttachment(skeleton, slot, attachmentName, attachments) {
|
|
slot.setAttachment(!attachmentName ? null : skeleton.getAttachment(slot.data.index, attachmentName));
|
|
if (attachments)
|
|
slot.attachmentState = this.unkeyedState + CURRENT;
|
|
}
|
|
applyRotateTimeline(timeline, skeleton, time, alpha, blend, timelinesRotation, i, firstFrame) {
|
|
if (firstFrame)
|
|
timelinesRotation[i] = 0;
|
|
if (alpha == 1) {
|
|
timeline.apply(skeleton, 0, time, null, 1, blend, 0 /* mixIn */);
|
|
return;
|
|
}
|
|
let bone = skeleton.bones[timeline.boneIndex];
|
|
if (!bone.active)
|
|
return;
|
|
let frames = timeline.frames;
|
|
let r1 = 0, r2 = 0;
|
|
if (time < frames[0]) {
|
|
switch (blend) {
|
|
case 0 /* setup */:
|
|
bone.rotation = bone.data.rotation;
|
|
default:
|
|
return;
|
|
case 1 /* first */:
|
|
r1 = bone.rotation;
|
|
r2 = bone.data.rotation;
|
|
}
|
|
} else {
|
|
r1 = blend == 0 /* setup */ ? bone.data.rotation : bone.rotation;
|
|
r2 = bone.data.rotation + timeline.getCurveValue(time);
|
|
}
|
|
let total = 0, diff = r2 - r1;
|
|
diff -= (16384 - (16384.499999999996 - diff / 360 | 0)) * 360;
|
|
if (diff == 0) {
|
|
total = timelinesRotation[i];
|
|
} else {
|
|
let lastTotal = 0, lastDiff = 0;
|
|
if (firstFrame) {
|
|
lastTotal = 0;
|
|
lastDiff = diff;
|
|
} else {
|
|
lastTotal = timelinesRotation[i];
|
|
lastDiff = timelinesRotation[i + 1];
|
|
}
|
|
let current = diff > 0, dir = lastTotal >= 0;
|
|
if (MathUtils.signum(lastDiff) != MathUtils.signum(diff) && Math.abs(lastDiff) <= 90) {
|
|
if (Math.abs(lastTotal) > 180)
|
|
lastTotal += 360 * MathUtils.signum(lastTotal);
|
|
dir = current;
|
|
}
|
|
total = diff + lastTotal - lastTotal % 360;
|
|
if (dir != current)
|
|
total += 360 * MathUtils.signum(lastTotal);
|
|
timelinesRotation[i] = total;
|
|
}
|
|
timelinesRotation[i + 1] = diff;
|
|
bone.rotation = r1 + total * alpha;
|
|
}
|
|
queueEvents(entry, animationTime) {
|
|
let animationStart = entry.animationStart, animationEnd = entry.animationEnd;
|
|
let duration = animationEnd - animationStart;
|
|
let trackLastWrapped = entry.trackLast % duration;
|
|
let events = this.events;
|
|
let i = 0, n = events.length;
|
|
for (; i < n; i++) {
|
|
let event = events[i];
|
|
if (event.time < trackLastWrapped)
|
|
break;
|
|
if (event.time > animationEnd)
|
|
continue;
|
|
this.queue.event(entry, event);
|
|
}
|
|
let complete = false;
|
|
if (entry.loop)
|
|
complete = duration == 0 || trackLastWrapped > entry.trackTime % duration;
|
|
else
|
|
complete = animationTime >= animationEnd && entry.animationLast < animationEnd;
|
|
if (complete)
|
|
this.queue.complete(entry);
|
|
for (; i < n; i++) {
|
|
let event = events[i];
|
|
if (event.time < animationStart)
|
|
continue;
|
|
this.queue.event(entry, event);
|
|
}
|
|
}
|
|
clearTracks() {
|
|
let oldDrainDisabled = this.queue.drainDisabled;
|
|
this.queue.drainDisabled = true;
|
|
for (let i = 0, n = this.tracks.length; i < n; i++)
|
|
this.clearTrack(i);
|
|
this.tracks.length = 0;
|
|
this.queue.drainDisabled = oldDrainDisabled;
|
|
this.queue.drain();
|
|
}
|
|
clearTrack(trackIndex) {
|
|
if (trackIndex >= this.tracks.length)
|
|
return;
|
|
let current = this.tracks[trackIndex];
|
|
if (!current)
|
|
return;
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
let entry = current;
|
|
while (true) {
|
|
let from = entry.mixingFrom;
|
|
if (!from)
|
|
break;
|
|
this.queue.end(from);
|
|
entry.mixingFrom = null;
|
|
entry.mixingTo = null;
|
|
entry = from;
|
|
}
|
|
this.tracks[current.trackIndex] = null;
|
|
this.queue.drain();
|
|
}
|
|
setCurrent(index, current, interrupt) {
|
|
let from = this.expandToIndex(index);
|
|
this.tracks[index] = current;
|
|
current.previous = null;
|
|
if (from) {
|
|
if (interrupt)
|
|
this.queue.interrupt(from);
|
|
current.mixingFrom = from;
|
|
from.mixingTo = current;
|
|
current.mixTime = 0;
|
|
if (from.mixingFrom && from.mixDuration > 0)
|
|
current.interruptAlpha *= Math.min(1, from.mixTime / from.mixDuration);
|
|
from.timelinesRotation.length = 0;
|
|
}
|
|
this.queue.start(current);
|
|
}
|
|
setAnimation(trackIndex, animationName, loop = false) {
|
|
let animation = this.data.skeletonData.findAnimation(animationName);
|
|
if (!animation)
|
|
throw new Error("Animation not found: " + animationName);
|
|
return this.setAnimationWith(trackIndex, animation, loop);
|
|
}
|
|
setAnimationWith(trackIndex, animation, loop = false) {
|
|
if (!animation)
|
|
throw new Error("animation cannot be null.");
|
|
let interrupt = true;
|
|
let current = this.expandToIndex(trackIndex);
|
|
if (current) {
|
|
if (current.nextTrackLast == -1) {
|
|
this.tracks[trackIndex] = current.mixingFrom;
|
|
this.queue.interrupt(current);
|
|
this.queue.end(current);
|
|
this.clearNext(current);
|
|
current = current.mixingFrom;
|
|
interrupt = false;
|
|
} else
|
|
this.clearNext(current);
|
|
}
|
|
let entry = this.trackEntry(trackIndex, animation, loop, current);
|
|
this.setCurrent(trackIndex, entry, interrupt);
|
|
this.queue.drain();
|
|
return entry;
|
|
}
|
|
addAnimation(trackIndex, animationName, loop = false, delay = 0) {
|
|
let animation = this.data.skeletonData.findAnimation(animationName);
|
|
if (!animation)
|
|
throw new Error("Animation not found: " + animationName);
|
|
return this.addAnimationWith(trackIndex, animation, loop, delay);
|
|
}
|
|
addAnimationWith(trackIndex, animation, loop = false, delay = 0) {
|
|
if (!animation)
|
|
throw new Error("animation cannot be null.");
|
|
let last = this.expandToIndex(trackIndex);
|
|
if (last) {
|
|
while (last.next)
|
|
last = last.next;
|
|
}
|
|
let entry = this.trackEntry(trackIndex, animation, loop, last);
|
|
if (!last) {
|
|
this.setCurrent(trackIndex, entry, true);
|
|
this.queue.drain();
|
|
} else {
|
|
last.next = entry;
|
|
entry.previous = last;
|
|
if (delay <= 0)
|
|
delay += last.getTrackComplete() - entry.mixDuration;
|
|
}
|
|
entry.delay = delay;
|
|
return entry;
|
|
}
|
|
setEmptyAnimation(trackIndex, mixDuration = 0) {
|
|
let entry = this.setAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false);
|
|
entry.mixDuration = mixDuration;
|
|
entry.trackEnd = mixDuration;
|
|
return entry;
|
|
}
|
|
addEmptyAnimation(trackIndex, mixDuration = 0, delay = 0) {
|
|
let entry = this.addAnimationWith(trackIndex, _AnimationState.emptyAnimation(), false, delay);
|
|
if (delay <= 0)
|
|
entry.delay += entry.mixDuration - mixDuration;
|
|
entry.mixDuration = mixDuration;
|
|
entry.trackEnd = mixDuration;
|
|
return entry;
|
|
}
|
|
setEmptyAnimations(mixDuration = 0) {
|
|
let oldDrainDisabled = this.queue.drainDisabled;
|
|
this.queue.drainDisabled = true;
|
|
for (let i = 0, n = this.tracks.length; i < n; i++) {
|
|
let current = this.tracks[i];
|
|
if (current)
|
|
this.setEmptyAnimation(current.trackIndex, mixDuration);
|
|
}
|
|
this.queue.drainDisabled = oldDrainDisabled;
|
|
this.queue.drain();
|
|
}
|
|
expandToIndex(index) {
|
|
if (index < this.tracks.length)
|
|
return this.tracks[index];
|
|
Utils.ensureArrayCapacity(this.tracks, index + 1, null);
|
|
this.tracks.length = index + 1;
|
|
return null;
|
|
}
|
|
trackEntry(trackIndex, animation, loop, last) {
|
|
let entry = this.trackEntryPool.obtain();
|
|
entry.reset();
|
|
entry.trackIndex = trackIndex;
|
|
entry.animation = animation;
|
|
entry.loop = loop;
|
|
entry.holdPrevious = false;
|
|
entry.reverse = false;
|
|
entry.shortestRotation = false;
|
|
entry.eventThreshold = 0;
|
|
entry.attachmentThreshold = 0;
|
|
entry.drawOrderThreshold = 0;
|
|
entry.animationStart = 0;
|
|
entry.animationEnd = animation.duration;
|
|
entry.animationLast = -1;
|
|
entry.nextAnimationLast = -1;
|
|
entry.delay = 0;
|
|
entry.trackTime = 0;
|
|
entry.trackLast = -1;
|
|
entry.nextTrackLast = -1;
|
|
entry.trackEnd = Number.MAX_VALUE;
|
|
entry.timeScale = 1;
|
|
entry.alpha = 1;
|
|
entry.mixTime = 0;
|
|
entry.mixDuration = !last ? 0 : this.data.getMix(last.animation, animation);
|
|
entry.interruptAlpha = 1;
|
|
entry.totalAlpha = 0;
|
|
entry.mixBlend = 2 /* replace */;
|
|
return entry;
|
|
}
|
|
clearNext(entry) {
|
|
let next = entry.next;
|
|
while (next) {
|
|
this.queue.dispose(next);
|
|
next = next.next;
|
|
}
|
|
entry.next = null;
|
|
}
|
|
_animationsChanged() {
|
|
this.animationsChanged = false;
|
|
this.propertyIDs.clear();
|
|
let tracks = this.tracks;
|
|
for (let i = 0, n = tracks.length; i < n; i++) {
|
|
let entry = tracks[i];
|
|
if (!entry)
|
|
continue;
|
|
while (entry.mixingFrom)
|
|
entry = entry.mixingFrom;
|
|
do {
|
|
if (!entry.mixingTo || entry.mixBlend != 3 /* add */)
|
|
this.computeHold(entry);
|
|
entry = entry.mixingTo;
|
|
} while (entry);
|
|
}
|
|
}
|
|
computeHold(entry) {
|
|
let to = entry.mixingTo;
|
|
let timelines = entry.animation.timelines;
|
|
let timelinesCount = entry.animation.timelines.length;
|
|
let timelineMode = entry.timelineMode;
|
|
timelineMode.length = timelinesCount;
|
|
let timelineHoldMix = entry.timelineHoldMix;
|
|
timelineHoldMix.length = 0;
|
|
let propertyIDs = this.propertyIDs;
|
|
if (to && to.holdPrevious) {
|
|
for (let i = 0; i < timelinesCount; i++)
|
|
timelineMode[i] = propertyIDs.addAll(timelines[i].getPropertyIds()) ? HOLD_FIRST : HOLD_SUBSEQUENT;
|
|
return;
|
|
}
|
|
outer:
|
|
for (let i = 0; i < timelinesCount; i++) {
|
|
let timeline = timelines[i];
|
|
let ids = timeline.getPropertyIds();
|
|
if (!propertyIDs.addAll(ids))
|
|
timelineMode[i] = SUBSEQUENT;
|
|
else if (!to || timeline instanceof AttachmentTimeline || timeline instanceof DrawOrderTimeline || timeline instanceof EventTimeline || !to.animation.hasTimeline(ids)) {
|
|
timelineMode[i] = FIRST;
|
|
} else {
|
|
for (let next = to.mixingTo; next; next = next.mixingTo) {
|
|
if (next.animation.hasTimeline(ids))
|
|
continue;
|
|
if (entry.mixDuration > 0) {
|
|
timelineMode[i] = HOLD_MIX;
|
|
timelineHoldMix[i] = next;
|
|
continue outer;
|
|
}
|
|
break;
|
|
}
|
|
timelineMode[i] = HOLD_FIRST;
|
|
}
|
|
}
|
|
}
|
|
getCurrent(trackIndex) {
|
|
if (trackIndex >= this.tracks.length)
|
|
return null;
|
|
return this.tracks[trackIndex];
|
|
}
|
|
addListener(listener) {
|
|
if (!listener)
|
|
throw new Error("listener cannot be null.");
|
|
this.listeners.push(listener);
|
|
}
|
|
removeListener(listener) {
|
|
let index = this.listeners.indexOf(listener);
|
|
if (index >= 0)
|
|
this.listeners.splice(index, 1);
|
|
}
|
|
clearListeners() {
|
|
this.listeners.length = 0;
|
|
}
|
|
clearListenerNotifications() {
|
|
this.queue.clear();
|
|
}
|
|
};
|
|
var AnimationState = _AnimationState;
|
|
AnimationState._emptyAnimation = new Animation("<empty>", [], 0);
|
|
var TrackEntry = class {
|
|
constructor() {
|
|
this.animation = null;
|
|
this.previous = null;
|
|
this.next = null;
|
|
this.mixingFrom = null;
|
|
this.mixingTo = null;
|
|
this.listener = null;
|
|
this.trackIndex = 0;
|
|
this.loop = false;
|
|
this.holdPrevious = false;
|
|
this.reverse = false;
|
|
this.shortestRotation = false;
|
|
this.eventThreshold = 0;
|
|
this.attachmentThreshold = 0;
|
|
this.drawOrderThreshold = 0;
|
|
this.animationStart = 0;
|
|
this.animationEnd = 0;
|
|
this.animationLast = 0;
|
|
this.nextAnimationLast = 0;
|
|
this.delay = 0;
|
|
this.trackTime = 0;
|
|
this.trackLast = 0;
|
|
this.nextTrackLast = 0;
|
|
this.trackEnd = 0;
|
|
this.timeScale = 0;
|
|
this.alpha = 0;
|
|
this.mixTime = 0;
|
|
this.mixDuration = 0;
|
|
this.interruptAlpha = 0;
|
|
this.totalAlpha = 0;
|
|
this.mixBlend = 2 /* replace */;
|
|
this.timelineMode = new Array();
|
|
this.timelineHoldMix = new Array();
|
|
this.timelinesRotation = new Array();
|
|
}
|
|
reset() {
|
|
this.next = null;
|
|
this.previous = null;
|
|
this.mixingFrom = null;
|
|
this.mixingTo = null;
|
|
this.animation = null;
|
|
this.listener = null;
|
|
this.timelineMode.length = 0;
|
|
this.timelineHoldMix.length = 0;
|
|
this.timelinesRotation.length = 0;
|
|
}
|
|
getAnimationTime() {
|
|
if (this.loop) {
|
|
let duration = this.animationEnd - this.animationStart;
|
|
if (duration == 0)
|
|
return this.animationStart;
|
|
return this.trackTime % duration + this.animationStart;
|
|
}
|
|
return Math.min(this.trackTime + this.animationStart, this.animationEnd);
|
|
}
|
|
setAnimationLast(animationLast) {
|
|
this.animationLast = animationLast;
|
|
this.nextAnimationLast = animationLast;
|
|
}
|
|
isComplete() {
|
|
return this.trackTime >= this.animationEnd - this.animationStart;
|
|
}
|
|
resetRotationDirections() {
|
|
this.timelinesRotation.length = 0;
|
|
}
|
|
getTrackComplete() {
|
|
let duration = this.animationEnd - this.animationStart;
|
|
if (duration != 0) {
|
|
if (this.loop)
|
|
return duration * (1 + (this.trackTime / duration | 0));
|
|
if (this.trackTime < duration)
|
|
return duration;
|
|
}
|
|
return this.trackTime;
|
|
}
|
|
};
|
|
var EventQueue = class {
|
|
constructor(animState) {
|
|
this.objects = [];
|
|
this.drainDisabled = false;
|
|
this.animState = animState;
|
|
}
|
|
start(entry) {
|
|
this.objects.push(EventType.start);
|
|
this.objects.push(entry);
|
|
this.animState.animationsChanged = true;
|
|
}
|
|
interrupt(entry) {
|
|
this.objects.push(EventType.interrupt);
|
|
this.objects.push(entry);
|
|
}
|
|
end(entry) {
|
|
this.objects.push(EventType.end);
|
|
this.objects.push(entry);
|
|
this.animState.animationsChanged = true;
|
|
}
|
|
dispose(entry) {
|
|
this.objects.push(EventType.dispose);
|
|
this.objects.push(entry);
|
|
}
|
|
complete(entry) {
|
|
this.objects.push(EventType.complete);
|
|
this.objects.push(entry);
|
|
}
|
|
event(entry, event) {
|
|
this.objects.push(EventType.event);
|
|
this.objects.push(entry);
|
|
this.objects.push(event);
|
|
}
|
|
drain() {
|
|
if (this.drainDisabled)
|
|
return;
|
|
this.drainDisabled = true;
|
|
let objects = this.objects;
|
|
let listeners = this.animState.listeners;
|
|
for (let i = 0; i < objects.length; i += 2) {
|
|
let type = objects[i];
|
|
let entry = objects[i + 1];
|
|
switch (type) {
|
|
case EventType.start:
|
|
if (entry.listener && entry.listener.start)
|
|
entry.listener.start(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.start)
|
|
listener.start(entry);
|
|
}
|
|
break;
|
|
case EventType.interrupt:
|
|
if (entry.listener && entry.listener.interrupt)
|
|
entry.listener.interrupt(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.interrupt)
|
|
listener.interrupt(entry);
|
|
}
|
|
break;
|
|
case EventType.end:
|
|
if (entry.listener && entry.listener.end)
|
|
entry.listener.end(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.end)
|
|
listener.end(entry);
|
|
}
|
|
case EventType.dispose:
|
|
if (entry.listener && entry.listener.dispose)
|
|
entry.listener.dispose(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.dispose)
|
|
listener.dispose(entry);
|
|
}
|
|
this.animState.trackEntryPool.free(entry);
|
|
break;
|
|
case EventType.complete:
|
|
if (entry.listener && entry.listener.complete)
|
|
entry.listener.complete(entry);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.complete)
|
|
listener.complete(entry);
|
|
}
|
|
break;
|
|
case EventType.event:
|
|
let event = objects[i++ + 2];
|
|
if (entry.listener && entry.listener.event)
|
|
entry.listener.event(entry, event);
|
|
for (let ii = 0; ii < listeners.length; ii++) {
|
|
let listener = listeners[ii];
|
|
if (listener.event)
|
|
listener.event(entry, event);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
this.clear();
|
|
this.drainDisabled = false;
|
|
}
|
|
clear() {
|
|
this.objects.length = 0;
|
|
}
|
|
};
|
|
var EventType = /* @__PURE__ */ ((EventType2) => {
|
|
EventType2[EventType2["start"] = 0] = "start";
|
|
EventType2[EventType2["interrupt"] = 1] = "interrupt";
|
|
EventType2[EventType2["end"] = 2] = "end";
|
|
EventType2[EventType2["dispose"] = 3] = "dispose";
|
|
EventType2[EventType2["complete"] = 4] = "complete";
|
|
EventType2[EventType2["event"] = 5] = "event";
|
|
return EventType2;
|
|
})(EventType || {});
|
|
var AnimationStateAdapter = class {
|
|
start(entry) {
|
|
}
|
|
interrupt(entry) {
|
|
}
|
|
end(entry) {
|
|
}
|
|
dispose(entry) {
|
|
}
|
|
complete(entry) {
|
|
}
|
|
event(entry, event) {
|
|
}
|
|
};
|
|
var SUBSEQUENT = 0;
|
|
var FIRST = 1;
|
|
var HOLD_SUBSEQUENT = 2;
|
|
var HOLD_FIRST = 3;
|
|
var HOLD_MIX = 4;
|
|
var SETUP = 1;
|
|
var CURRENT = 2;
|
|
|
|
// spine-core/src/AnimationStateData.ts
|
|
var AnimationStateData = class {
|
|
constructor(skeletonData) {
|
|
this.animationToMixTime = {};
|
|
this.defaultMix = 0;
|
|
if (!skeletonData)
|
|
throw new Error("skeletonData cannot be null.");
|
|
this.skeletonData = skeletonData;
|
|
}
|
|
setMix(fromName, toName, duration) {
|
|
let from = this.skeletonData.findAnimation(fromName);
|
|
if (!from)
|
|
throw new Error("Animation not found: " + fromName);
|
|
let to = this.skeletonData.findAnimation(toName);
|
|
if (!to)
|
|
throw new Error("Animation not found: " + toName);
|
|
this.setMixWith(from, to, duration);
|
|
}
|
|
setMixWith(from, to, duration) {
|
|
if (!from)
|
|
throw new Error("from cannot be null.");
|
|
if (!to)
|
|
throw new Error("to cannot be null.");
|
|
let key = from.name + "." + to.name;
|
|
this.animationToMixTime[key] = duration;
|
|
}
|
|
getMix(from, to) {
|
|
let key = from.name + "." + to.name;
|
|
let value = this.animationToMixTime[key];
|
|
return value === void 0 ? this.defaultMix : value;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/BoundingBoxAttachment.ts
|
|
var BoundingBoxAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.color = new Color(1, 1, 1, 1);
|
|
}
|
|
copy() {
|
|
let copy = new BoundingBoxAttachment(this.name);
|
|
this.copyTo(copy);
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/ClippingAttachment.ts
|
|
var ClippingAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.endSlot = null;
|
|
this.color = new Color(0.2275, 0.2275, 0.8078, 1);
|
|
}
|
|
copy() {
|
|
let copy = new ClippingAttachment(this.name);
|
|
this.copyTo(copy);
|
|
copy.endSlot = this.endSlot;
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Texture.ts
|
|
var Texture = class {
|
|
constructor(image) {
|
|
this._image = image;
|
|
}
|
|
getImage() {
|
|
return this._image;
|
|
}
|
|
};
|
|
var TextureFilter = /* @__PURE__ */ ((TextureFilter2) => {
|
|
TextureFilter2[TextureFilter2["Nearest"] = 9728] = "Nearest";
|
|
TextureFilter2[TextureFilter2["Linear"] = 9729] = "Linear";
|
|
TextureFilter2[TextureFilter2["MipMap"] = 9987] = "MipMap";
|
|
TextureFilter2[TextureFilter2["MipMapNearestNearest"] = 9984] = "MipMapNearestNearest";
|
|
TextureFilter2[TextureFilter2["MipMapLinearNearest"] = 9985] = "MipMapLinearNearest";
|
|
TextureFilter2[TextureFilter2["MipMapNearestLinear"] = 9986] = "MipMapNearestLinear";
|
|
TextureFilter2[TextureFilter2["MipMapLinearLinear"] = 9987] = "MipMapLinearLinear";
|
|
return TextureFilter2;
|
|
})(TextureFilter || {});
|
|
var TextureWrap = /* @__PURE__ */ ((TextureWrap3) => {
|
|
TextureWrap3[TextureWrap3["MirroredRepeat"] = 33648] = "MirroredRepeat";
|
|
TextureWrap3[TextureWrap3["ClampToEdge"] = 33071] = "ClampToEdge";
|
|
TextureWrap3[TextureWrap3["Repeat"] = 10497] = "Repeat";
|
|
return TextureWrap3;
|
|
})(TextureWrap || {});
|
|
var TextureRegion = class {
|
|
constructor() {
|
|
this.u = 0;
|
|
this.v = 0;
|
|
this.u2 = 0;
|
|
this.v2 = 0;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.degrees = 0;
|
|
this.offsetX = 0;
|
|
this.offsetY = 0;
|
|
this.originalWidth = 0;
|
|
this.originalHeight = 0;
|
|
}
|
|
};
|
|
var FakeTexture = class extends Texture {
|
|
setFilters(minFilter, magFilter) {
|
|
}
|
|
setWraps(uWrap, vWrap) {
|
|
}
|
|
dispose() {
|
|
}
|
|
};
|
|
|
|
// spine-core/src/TextureAtlas.ts
|
|
var TextureAtlas = class {
|
|
constructor(atlasText) {
|
|
this.pages = new Array();
|
|
this.regions = new Array();
|
|
let reader = new TextureAtlasReader(atlasText);
|
|
let entry = new Array(4);
|
|
let pageFields = {};
|
|
pageFields["size"] = (page2) => {
|
|
page2.width = parseInt(entry[1]);
|
|
page2.height = parseInt(entry[2]);
|
|
};
|
|
pageFields["format"] = () => {
|
|
};
|
|
pageFields["filter"] = (page2) => {
|
|
page2.minFilter = Utils.enumValue(TextureFilter, entry[1]);
|
|
page2.magFilter = Utils.enumValue(TextureFilter, entry[2]);
|
|
};
|
|
pageFields["repeat"] = (page2) => {
|
|
if (entry[1].indexOf("x") != -1)
|
|
page2.uWrap = 10497 /* Repeat */;
|
|
if (entry[1].indexOf("y") != -1)
|
|
page2.vWrap = 10497 /* Repeat */;
|
|
};
|
|
pageFields["pma"] = (page2) => {
|
|
page2.pma = entry[1] == "true";
|
|
};
|
|
var regionFields = {};
|
|
regionFields["xy"] = (region) => {
|
|
region.x = parseInt(entry[1]);
|
|
region.y = parseInt(entry[2]);
|
|
};
|
|
regionFields["size"] = (region) => {
|
|
region.width = parseInt(entry[1]);
|
|
region.height = parseInt(entry[2]);
|
|
};
|
|
regionFields["bounds"] = (region) => {
|
|
region.x = parseInt(entry[1]);
|
|
region.y = parseInt(entry[2]);
|
|
region.width = parseInt(entry[3]);
|
|
region.height = parseInt(entry[4]);
|
|
};
|
|
regionFields["offset"] = (region) => {
|
|
region.offsetX = parseInt(entry[1]);
|
|
region.offsetY = parseInt(entry[2]);
|
|
};
|
|
regionFields["orig"] = (region) => {
|
|
region.originalWidth = parseInt(entry[1]);
|
|
region.originalHeight = parseInt(entry[2]);
|
|
};
|
|
regionFields["offsets"] = (region) => {
|
|
region.offsetX = parseInt(entry[1]);
|
|
region.offsetY = parseInt(entry[2]);
|
|
region.originalWidth = parseInt(entry[3]);
|
|
region.originalHeight = parseInt(entry[4]);
|
|
};
|
|
regionFields["rotate"] = (region) => {
|
|
let value = entry[1];
|
|
if (value == "true")
|
|
region.degrees = 90;
|
|
else if (value != "false")
|
|
region.degrees = parseInt(value);
|
|
};
|
|
regionFields["index"] = (region) => {
|
|
region.index = parseInt(entry[1]);
|
|
};
|
|
let line = reader.readLine();
|
|
while (line && line.trim().length == 0)
|
|
line = reader.readLine();
|
|
while (true) {
|
|
if (!line || line.trim().length == 0)
|
|
break;
|
|
if (reader.readEntry(entry, line) == 0)
|
|
break;
|
|
line = reader.readLine();
|
|
}
|
|
let page = null;
|
|
let names = null;
|
|
let values = null;
|
|
while (true) {
|
|
if (line === null)
|
|
break;
|
|
if (line.trim().length == 0) {
|
|
page = null;
|
|
line = reader.readLine();
|
|
} else if (!page) {
|
|
page = new TextureAtlasPage(line.trim());
|
|
while (true) {
|
|
if (reader.readEntry(entry, line = reader.readLine()) == 0)
|
|
break;
|
|
let field = pageFields[entry[0]];
|
|
if (field)
|
|
field(page);
|
|
}
|
|
this.pages.push(page);
|
|
} else {
|
|
let region = new TextureAtlasRegion(page, line);
|
|
while (true) {
|
|
let count = reader.readEntry(entry, line = reader.readLine());
|
|
if (count == 0)
|
|
break;
|
|
let field = regionFields[entry[0]];
|
|
if (field)
|
|
field(region);
|
|
else {
|
|
if (!names)
|
|
names = [];
|
|
if (!values)
|
|
values = [];
|
|
names.push(entry[0]);
|
|
let entryValues = [];
|
|
for (let i = 0; i < count; i++)
|
|
entryValues.push(parseInt(entry[i + 1]));
|
|
values.push(entryValues);
|
|
}
|
|
}
|
|
if (region.originalWidth == 0 && region.originalHeight == 0) {
|
|
region.originalWidth = region.width;
|
|
region.originalHeight = region.height;
|
|
}
|
|
if (names && names.length > 0 && values && values.length > 0) {
|
|
region.names = names;
|
|
region.values = values;
|
|
names = null;
|
|
values = null;
|
|
}
|
|
region.u = region.x / page.width;
|
|
region.v = region.y / page.height;
|
|
if (region.degrees == 90) {
|
|
region.u2 = (region.x + region.height) / page.width;
|
|
region.v2 = (region.y + region.width) / page.height;
|
|
} else {
|
|
region.u2 = (region.x + region.width) / page.width;
|
|
region.v2 = (region.y + region.height) / page.height;
|
|
}
|
|
this.regions.push(region);
|
|
}
|
|
}
|
|
}
|
|
findRegion(name) {
|
|
for (let i = 0; i < this.regions.length; i++) {
|
|
if (this.regions[i].name == name) {
|
|
return this.regions[i];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
setTextures(assetManager, pathPrefix = "") {
|
|
for (let page of this.pages)
|
|
page.setTexture(assetManager.get(pathPrefix + page.name));
|
|
}
|
|
dispose() {
|
|
var _a;
|
|
for (let i = 0; i < this.pages.length; i++) {
|
|
(_a = this.pages[i].texture) == null ? void 0 : _a.dispose();
|
|
}
|
|
}
|
|
};
|
|
var TextureAtlasReader = class {
|
|
constructor(text) {
|
|
this.index = 0;
|
|
this.lines = text.split(/\r\n|\r|\n/);
|
|
}
|
|
readLine() {
|
|
if (this.index >= this.lines.length)
|
|
return null;
|
|
return this.lines[this.index++];
|
|
}
|
|
readEntry(entry, line) {
|
|
if (!line)
|
|
return 0;
|
|
line = line.trim();
|
|
if (line.length == 0)
|
|
return 0;
|
|
let colon = line.indexOf(":");
|
|
if (colon == -1)
|
|
return 0;
|
|
entry[0] = line.substr(0, colon).trim();
|
|
for (let i = 1, lastMatch = colon + 1; ; i++) {
|
|
let comma = line.indexOf(",", lastMatch);
|
|
if (comma == -1) {
|
|
entry[i] = line.substr(lastMatch).trim();
|
|
return i;
|
|
}
|
|
entry[i] = line.substr(lastMatch, comma - lastMatch).trim();
|
|
lastMatch = comma + 1;
|
|
if (i == 4)
|
|
return 4;
|
|
}
|
|
}
|
|
};
|
|
var TextureAtlasPage = class {
|
|
constructor(name) {
|
|
this.minFilter = 9728 /* Nearest */;
|
|
this.magFilter = 9728 /* Nearest */;
|
|
this.uWrap = 33071 /* ClampToEdge */;
|
|
this.vWrap = 33071 /* ClampToEdge */;
|
|
this.texture = null;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.pma = false;
|
|
this.name = name;
|
|
}
|
|
setTexture(texture) {
|
|
this.texture = texture;
|
|
texture.setFilters(this.minFilter, this.magFilter);
|
|
texture.setWraps(this.uWrap, this.vWrap);
|
|
}
|
|
};
|
|
var TextureAtlasRegion = class extends TextureRegion {
|
|
constructor(page, name) {
|
|
super();
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.offsetX = 0;
|
|
this.offsetY = 0;
|
|
this.originalWidth = 0;
|
|
this.originalHeight = 0;
|
|
this.index = 0;
|
|
this.degrees = 0;
|
|
this.names = null;
|
|
this.values = null;
|
|
this.page = page;
|
|
this.name = name;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/MeshAttachment.ts
|
|
var MeshAttachment = class extends VertexAttachment {
|
|
constructor(name, path) {
|
|
super(name);
|
|
this.region = null;
|
|
this.regionUVs = [];
|
|
this.uvs = [];
|
|
this.triangles = [];
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.hullLength = 0;
|
|
this.edges = [];
|
|
this.parentMesh = null;
|
|
this.sequence = null;
|
|
this.tempColor = new Color(0, 0, 0, 0);
|
|
this.path = path;
|
|
}
|
|
updateRegion() {
|
|
if (!this.region)
|
|
throw new Error("Region not set.");
|
|
let regionUVs = this.regionUVs;
|
|
if (!this.uvs || this.uvs.length != regionUVs.length)
|
|
this.uvs = Utils.newFloatArray(regionUVs.length);
|
|
let uvs = this.uvs;
|
|
let n = this.uvs.length;
|
|
let u = this.region.u, v = this.region.v, width = 0, height = 0;
|
|
if (this.region instanceof TextureAtlasRegion) {
|
|
let region = this.region, image = region.page.texture.getImage();
|
|
let textureWidth = image.width, textureHeight = image.height;
|
|
switch (region.degrees) {
|
|
case 90:
|
|
u -= (region.originalHeight - region.offsetY - region.height) / textureWidth;
|
|
v -= (region.originalWidth - region.offsetX - region.width) / textureHeight;
|
|
width = region.originalHeight / textureWidth;
|
|
height = region.originalWidth / textureHeight;
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + regionUVs[i + 1] * width;
|
|
uvs[i + 1] = v + (1 - regionUVs[i]) * height;
|
|
}
|
|
return;
|
|
case 180:
|
|
u -= (region.originalWidth - region.offsetX - region.width) / textureWidth;
|
|
v -= region.offsetY / textureHeight;
|
|
width = region.originalWidth / textureWidth;
|
|
height = region.originalHeight / textureHeight;
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + (1 - regionUVs[i]) * width;
|
|
uvs[i + 1] = v + (1 - regionUVs[i + 1]) * height;
|
|
}
|
|
return;
|
|
case 270:
|
|
u -= region.offsetY / textureWidth;
|
|
v -= region.offsetX / textureHeight;
|
|
width = region.originalHeight / textureWidth;
|
|
height = region.originalWidth / textureHeight;
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + (1 - regionUVs[i + 1]) * width;
|
|
uvs[i + 1] = v + regionUVs[i] * height;
|
|
}
|
|
return;
|
|
}
|
|
u -= region.offsetX / textureWidth;
|
|
v -= (region.originalHeight - region.offsetY - region.height) / textureHeight;
|
|
width = region.originalWidth / textureWidth;
|
|
height = region.originalHeight / textureHeight;
|
|
} else if (!this.region) {
|
|
u = v = 0;
|
|
width = height = 1;
|
|
} else {
|
|
width = this.region.u2 - u;
|
|
height = this.region.v2 - v;
|
|
}
|
|
for (let i = 0; i < n; i += 2) {
|
|
uvs[i] = u + regionUVs[i] * width;
|
|
uvs[i + 1] = v + regionUVs[i + 1] * height;
|
|
}
|
|
}
|
|
getParentMesh() {
|
|
return this.parentMesh;
|
|
}
|
|
setParentMesh(parentMesh) {
|
|
this.parentMesh = parentMesh;
|
|
if (parentMesh) {
|
|
this.bones = parentMesh.bones;
|
|
this.vertices = parentMesh.vertices;
|
|
this.worldVerticesLength = parentMesh.worldVerticesLength;
|
|
this.regionUVs = parentMesh.regionUVs;
|
|
this.triangles = parentMesh.triangles;
|
|
this.hullLength = parentMesh.hullLength;
|
|
this.worldVerticesLength = parentMesh.worldVerticesLength;
|
|
}
|
|
}
|
|
copy() {
|
|
if (this.parentMesh)
|
|
return this.newLinkedMesh();
|
|
let copy = new MeshAttachment(this.name, this.path);
|
|
copy.region = this.region;
|
|
copy.color.setFromColor(this.color);
|
|
this.copyTo(copy);
|
|
copy.regionUVs = new Array(this.regionUVs.length);
|
|
Utils.arrayCopy(this.regionUVs, 0, copy.regionUVs, 0, this.regionUVs.length);
|
|
copy.uvs = new Array(this.uvs.length);
|
|
Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, this.uvs.length);
|
|
copy.triangles = new Array(this.triangles.length);
|
|
Utils.arrayCopy(this.triangles, 0, copy.triangles, 0, this.triangles.length);
|
|
copy.hullLength = this.hullLength;
|
|
copy.sequence = this.sequence != null ? this.sequence.copy() : null;
|
|
if (this.edges) {
|
|
copy.edges = new Array(this.edges.length);
|
|
Utils.arrayCopy(this.edges, 0, copy.edges, 0, this.edges.length);
|
|
}
|
|
copy.width = this.width;
|
|
copy.height = this.height;
|
|
return copy;
|
|
}
|
|
computeWorldVertices(slot, start, count, worldVertices, offset, stride) {
|
|
if (this.sequence != null)
|
|
this.sequence.apply(slot, this);
|
|
super.computeWorldVertices(slot, start, count, worldVertices, offset, stride);
|
|
}
|
|
newLinkedMesh() {
|
|
let copy = new MeshAttachment(this.name, this.path);
|
|
copy.region = this.region;
|
|
copy.color.setFromColor(this.color);
|
|
copy.timelineAttachment = this.timelineAttachment;
|
|
copy.setParentMesh(this.parentMesh ? this.parentMesh : this);
|
|
if (copy.region != null)
|
|
copy.updateRegion();
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/PathAttachment.ts
|
|
var PathAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.lengths = [];
|
|
this.closed = false;
|
|
this.constantSpeed = false;
|
|
this.color = new Color(1, 1, 1, 1);
|
|
}
|
|
copy() {
|
|
let copy = new PathAttachment(this.name);
|
|
this.copyTo(copy);
|
|
copy.lengths = new Array(this.lengths.length);
|
|
Utils.arrayCopy(this.lengths, 0, copy.lengths, 0, this.lengths.length);
|
|
copy.closed = closed;
|
|
copy.constantSpeed = this.constantSpeed;
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/PointAttachment.ts
|
|
var PointAttachment = class extends VertexAttachment {
|
|
constructor(name) {
|
|
super(name);
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.rotation = 0;
|
|
this.color = new Color(0.38, 0.94, 0, 1);
|
|
}
|
|
computeWorldPosition(bone, point) {
|
|
point.x = this.x * bone.a + this.y * bone.b + bone.worldX;
|
|
point.y = this.x * bone.c + this.y * bone.d + bone.worldY;
|
|
return point;
|
|
}
|
|
computeWorldRotation(bone) {
|
|
let cos = MathUtils.cosDeg(this.rotation), sin = MathUtils.sinDeg(this.rotation);
|
|
let x = cos * bone.a + sin * bone.b;
|
|
let y = cos * bone.c + sin * bone.d;
|
|
return Math.atan2(y, x) * MathUtils.radDeg;
|
|
}
|
|
copy() {
|
|
let copy = new PointAttachment(this.name);
|
|
copy.x = this.x;
|
|
copy.y = this.y;
|
|
copy.rotation = this.rotation;
|
|
copy.color.setFromColor(this.color);
|
|
return copy;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/attachments/RegionAttachment.ts
|
|
var _RegionAttachment = class extends Attachment {
|
|
constructor(name, path) {
|
|
super(name);
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.scaleX = 1;
|
|
this.scaleY = 1;
|
|
this.rotation = 0;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.rendererObject = null;
|
|
this.region = null;
|
|
this.sequence = null;
|
|
this.offset = Utils.newFloatArray(8);
|
|
this.uvs = Utils.newFloatArray(8);
|
|
this.tempColor = new Color(1, 1, 1, 1);
|
|
this.path = path;
|
|
}
|
|
updateRegion() {
|
|
if (!this.region)
|
|
throw new Error("Region not set.");
|
|
let region = this.region;
|
|
let uvs = this.uvs;
|
|
if (region == null) {
|
|
uvs[0] = 0;
|
|
uvs[1] = 0;
|
|
uvs[2] = 0;
|
|
uvs[3] = 1;
|
|
uvs[4] = 1;
|
|
uvs[5] = 1;
|
|
uvs[6] = 1;
|
|
uvs[7] = 0;
|
|
return;
|
|
}
|
|
let regionScaleX = this.width / this.region.originalWidth * this.scaleX;
|
|
let regionScaleY = this.height / this.region.originalHeight * this.scaleY;
|
|
let localX = -this.width / 2 * this.scaleX + this.region.offsetX * regionScaleX;
|
|
let localY = -this.height / 2 * this.scaleY + this.region.offsetY * regionScaleY;
|
|
let localX2 = localX + this.region.width * regionScaleX;
|
|
let localY2 = localY + this.region.height * regionScaleY;
|
|
let radians = this.rotation * Math.PI / 180;
|
|
let cos = Math.cos(radians);
|
|
let sin = Math.sin(radians);
|
|
let x = this.x, y = this.y;
|
|
let localXCos = localX * cos + x;
|
|
let localXSin = localX * sin;
|
|
let localYCos = localY * cos + y;
|
|
let localYSin = localY * sin;
|
|
let localX2Cos = localX2 * cos + x;
|
|
let localX2Sin = localX2 * sin;
|
|
let localY2Cos = localY2 * cos + y;
|
|
let localY2Sin = localY2 * sin;
|
|
let offset = this.offset;
|
|
offset[0] = localXCos - localYSin;
|
|
offset[1] = localYCos + localXSin;
|
|
offset[2] = localXCos - localY2Sin;
|
|
offset[3] = localY2Cos + localXSin;
|
|
offset[4] = localX2Cos - localY2Sin;
|
|
offset[5] = localY2Cos + localX2Sin;
|
|
offset[6] = localX2Cos - localYSin;
|
|
offset[7] = localYCos + localX2Sin;
|
|
if (region.degrees == 90) {
|
|
uvs[0] = region.u2;
|
|
uvs[1] = region.v2;
|
|
uvs[2] = region.u;
|
|
uvs[3] = region.v2;
|
|
uvs[4] = region.u;
|
|
uvs[5] = region.v;
|
|
uvs[6] = region.u2;
|
|
uvs[7] = region.v;
|
|
} else {
|
|
uvs[0] = region.u;
|
|
uvs[1] = region.v2;
|
|
uvs[2] = region.u;
|
|
uvs[3] = region.v;
|
|
uvs[4] = region.u2;
|
|
uvs[5] = region.v;
|
|
uvs[6] = region.u2;
|
|
uvs[7] = region.v2;
|
|
}
|
|
}
|
|
computeWorldVertices(slot, worldVertices, offset, stride) {
|
|
if (this.sequence != null)
|
|
this.sequence.apply(slot, this);
|
|
let bone = slot.bone;
|
|
let vertexOffset = this.offset;
|
|
let x = bone.worldX, y = bone.worldY;
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
let offsetX = 0, offsetY = 0;
|
|
offsetX = vertexOffset[0];
|
|
offsetY = vertexOffset[1];
|
|
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
|
offset += stride;
|
|
offsetX = vertexOffset[2];
|
|
offsetY = vertexOffset[3];
|
|
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
|
offset += stride;
|
|
offsetX = vertexOffset[4];
|
|
offsetY = vertexOffset[5];
|
|
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
|
offset += stride;
|
|
offsetX = vertexOffset[6];
|
|
offsetY = vertexOffset[7];
|
|
worldVertices[offset] = offsetX * a + offsetY * b + x;
|
|
worldVertices[offset + 1] = offsetX * c + offsetY * d + y;
|
|
}
|
|
copy() {
|
|
let copy = new _RegionAttachment(this.name, this.path);
|
|
copy.region = this.region;
|
|
copy.rendererObject = this.rendererObject;
|
|
copy.x = this.x;
|
|
copy.y = this.y;
|
|
copy.scaleX = this.scaleX;
|
|
copy.scaleY = this.scaleY;
|
|
copy.rotation = this.rotation;
|
|
copy.width = this.width;
|
|
copy.height = this.height;
|
|
Utils.arrayCopy(this.uvs, 0, copy.uvs, 0, 8);
|
|
Utils.arrayCopy(this.offset, 0, copy.offset, 0, 8);
|
|
copy.color.setFromColor(this.color);
|
|
copy.sequence = this.sequence != null ? this.sequence.copy() : null;
|
|
return copy;
|
|
}
|
|
};
|
|
var RegionAttachment = _RegionAttachment;
|
|
RegionAttachment.X1 = 0;
|
|
RegionAttachment.Y1 = 1;
|
|
RegionAttachment.C1R = 2;
|
|
RegionAttachment.C1G = 3;
|
|
RegionAttachment.C1B = 4;
|
|
RegionAttachment.C1A = 5;
|
|
RegionAttachment.U1 = 6;
|
|
RegionAttachment.V1 = 7;
|
|
RegionAttachment.X2 = 8;
|
|
RegionAttachment.Y2 = 9;
|
|
RegionAttachment.C2R = 10;
|
|
RegionAttachment.C2G = 11;
|
|
RegionAttachment.C2B = 12;
|
|
RegionAttachment.C2A = 13;
|
|
RegionAttachment.U2 = 14;
|
|
RegionAttachment.V2 = 15;
|
|
RegionAttachment.X3 = 16;
|
|
RegionAttachment.Y3 = 17;
|
|
RegionAttachment.C3R = 18;
|
|
RegionAttachment.C3G = 19;
|
|
RegionAttachment.C3B = 20;
|
|
RegionAttachment.C3A = 21;
|
|
RegionAttachment.U3 = 22;
|
|
RegionAttachment.V3 = 23;
|
|
RegionAttachment.X4 = 24;
|
|
RegionAttachment.Y4 = 25;
|
|
RegionAttachment.C4R = 26;
|
|
RegionAttachment.C4G = 27;
|
|
RegionAttachment.C4B = 28;
|
|
RegionAttachment.C4A = 29;
|
|
RegionAttachment.U4 = 30;
|
|
RegionAttachment.V4 = 31;
|
|
|
|
// spine-core/src/AtlasAttachmentLoader.ts
|
|
var AtlasAttachmentLoader = class {
|
|
constructor(atlas) {
|
|
this.atlas = atlas;
|
|
}
|
|
loadSequence(name, basePath, sequence) {
|
|
let regions = sequence.regions;
|
|
for (let i = 0, n = regions.length; i < n; i++) {
|
|
let path = sequence.getPath(basePath, i);
|
|
let region = this.atlas.findRegion(path);
|
|
if (region == null)
|
|
throw new Error("Region not found in atlas: " + path + " (sequence: " + name + ")");
|
|
regions[i] = region;
|
|
regions[i].renderObject = regions[i];
|
|
}
|
|
}
|
|
newRegionAttachment(skin, name, path, sequence) {
|
|
let attachment = new RegionAttachment(name, path);
|
|
if (sequence != null) {
|
|
this.loadSequence(name, path, sequence);
|
|
} else {
|
|
let region = this.atlas.findRegion(path);
|
|
if (!region)
|
|
throw new Error("Region not found in atlas: " + path + " (region attachment: " + name + ")");
|
|
region.renderObject = region;
|
|
attachment.region = region;
|
|
}
|
|
return attachment;
|
|
}
|
|
newMeshAttachment(skin, name, path, sequence) {
|
|
let attachment = new MeshAttachment(name, path);
|
|
if (sequence != null) {
|
|
this.loadSequence(name, path, sequence);
|
|
} else {
|
|
let region = this.atlas.findRegion(path);
|
|
if (!region)
|
|
throw new Error("Region not found in atlas: " + path + " (mesh attachment: " + name + ")");
|
|
region.renderObject = region;
|
|
attachment.region = region;
|
|
}
|
|
return attachment;
|
|
}
|
|
newBoundingBoxAttachment(skin, name) {
|
|
return new BoundingBoxAttachment(name);
|
|
}
|
|
newPathAttachment(skin, name) {
|
|
return new PathAttachment(name);
|
|
}
|
|
newPointAttachment(skin, name) {
|
|
return new PointAttachment(name);
|
|
}
|
|
newClippingAttachment(skin, name) {
|
|
return new ClippingAttachment(name);
|
|
}
|
|
};
|
|
|
|
// spine-core/src/BoneData.ts
|
|
var BoneData = class {
|
|
constructor(index, name, parent) {
|
|
this.index = 0;
|
|
this.parent = null;
|
|
this.length = 0;
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.rotation = 0;
|
|
this.scaleX = 1;
|
|
this.scaleY = 1;
|
|
this.shearX = 0;
|
|
this.shearY = 0;
|
|
this.transformMode = TransformMode.Normal;
|
|
this.skinRequired = false;
|
|
this.color = new Color();
|
|
if (index < 0)
|
|
throw new Error("index must be >= 0.");
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.index = index;
|
|
this.name = name;
|
|
this.parent = parent;
|
|
}
|
|
};
|
|
var TransformMode = /* @__PURE__ */ ((TransformMode2) => {
|
|
TransformMode2[TransformMode2["Normal"] = 0] = "Normal";
|
|
TransformMode2[TransformMode2["OnlyTranslation"] = 1] = "OnlyTranslation";
|
|
TransformMode2[TransformMode2["NoRotationOrReflection"] = 2] = "NoRotationOrReflection";
|
|
TransformMode2[TransformMode2["NoScale"] = 3] = "NoScale";
|
|
TransformMode2[TransformMode2["NoScaleOrReflection"] = 4] = "NoScaleOrReflection";
|
|
return TransformMode2;
|
|
})(TransformMode || {});
|
|
|
|
// spine-core/src/Bone.ts
|
|
var Bone = class {
|
|
constructor(data, skeleton, parent) {
|
|
this.parent = null;
|
|
this.children = new Array();
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.rotation = 0;
|
|
this.scaleX = 0;
|
|
this.scaleY = 0;
|
|
this.shearX = 0;
|
|
this.shearY = 0;
|
|
this.ax = 0;
|
|
this.ay = 0;
|
|
this.arotation = 0;
|
|
this.ascaleX = 0;
|
|
this.ascaleY = 0;
|
|
this.ashearX = 0;
|
|
this.ashearY = 0;
|
|
this.a = 0;
|
|
this.b = 0;
|
|
this.c = 0;
|
|
this.d = 0;
|
|
this.worldY = 0;
|
|
this.worldX = 0;
|
|
this.sorted = false;
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.skeleton = skeleton;
|
|
this.parent = parent;
|
|
this.setToSetupPose();
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
this.updateWorldTransformWith(this.ax, this.ay, this.arotation, this.ascaleX, this.ascaleY, this.ashearX, this.ashearY);
|
|
}
|
|
updateWorldTransform() {
|
|
this.updateWorldTransformWith(this.x, this.y, this.rotation, this.scaleX, this.scaleY, this.shearX, this.shearY);
|
|
}
|
|
updateWorldTransformWith(x, y, rotation, scaleX, scaleY, shearX, shearY) {
|
|
this.ax = x;
|
|
this.ay = y;
|
|
this.arotation = rotation;
|
|
this.ascaleX = scaleX;
|
|
this.ascaleY = scaleY;
|
|
this.ashearX = shearX;
|
|
this.ashearY = shearY;
|
|
let parent = this.parent;
|
|
if (!parent) {
|
|
let skeleton = this.skeleton;
|
|
let rotationY = rotation + 90 + shearY;
|
|
let sx = skeleton.scaleX;
|
|
let sy = skeleton.scaleY;
|
|
this.a = MathUtils.cosDeg(rotation + shearX) * scaleX * sx;
|
|
this.b = MathUtils.cosDeg(rotationY) * scaleY * sx;
|
|
this.c = MathUtils.sinDeg(rotation + shearX) * scaleX * sy;
|
|
this.d = MathUtils.sinDeg(rotationY) * scaleY * sy;
|
|
this.worldX = x * sx + skeleton.x;
|
|
this.worldY = y * sy + skeleton.y;
|
|
return;
|
|
}
|
|
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
|
this.worldX = pa * x + pb * y + parent.worldX;
|
|
this.worldY = pc * x + pd * y + parent.worldY;
|
|
switch (this.data.transformMode) {
|
|
case 0 /* Normal */: {
|
|
let rotationY = rotation + 90 + shearY;
|
|
let la = MathUtils.cosDeg(rotation + shearX) * scaleX;
|
|
let lb = MathUtils.cosDeg(rotationY) * scaleY;
|
|
let lc = MathUtils.sinDeg(rotation + shearX) * scaleX;
|
|
let ld = MathUtils.sinDeg(rotationY) * scaleY;
|
|
this.a = pa * la + pb * lc;
|
|
this.b = pa * lb + pb * ld;
|
|
this.c = pc * la + pd * lc;
|
|
this.d = pc * lb + pd * ld;
|
|
return;
|
|
}
|
|
case 1 /* OnlyTranslation */: {
|
|
let rotationY = rotation + 90 + shearY;
|
|
this.a = MathUtils.cosDeg(rotation + shearX) * scaleX;
|
|
this.b = MathUtils.cosDeg(rotationY) * scaleY;
|
|
this.c = MathUtils.sinDeg(rotation + shearX) * scaleX;
|
|
this.d = MathUtils.sinDeg(rotationY) * scaleY;
|
|
break;
|
|
}
|
|
case 2 /* NoRotationOrReflection */: {
|
|
let s = pa * pa + pc * pc;
|
|
let prx = 0;
|
|
if (s > 1e-4) {
|
|
s = Math.abs(pa * pd - pb * pc) / s;
|
|
pa /= this.skeleton.scaleX;
|
|
pc /= this.skeleton.scaleY;
|
|
pb = pc * s;
|
|
pd = pa * s;
|
|
prx = Math.atan2(pc, pa) * MathUtils.radDeg;
|
|
} else {
|
|
pa = 0;
|
|
pc = 0;
|
|
prx = 90 - Math.atan2(pd, pb) * MathUtils.radDeg;
|
|
}
|
|
let rx = rotation + shearX - prx;
|
|
let ry = rotation + shearY - prx + 90;
|
|
let la = MathUtils.cosDeg(rx) * scaleX;
|
|
let lb = MathUtils.cosDeg(ry) * scaleY;
|
|
let lc = MathUtils.sinDeg(rx) * scaleX;
|
|
let ld = MathUtils.sinDeg(ry) * scaleY;
|
|
this.a = pa * la - pb * lc;
|
|
this.b = pa * lb - pb * ld;
|
|
this.c = pc * la + pd * lc;
|
|
this.d = pc * lb + pd * ld;
|
|
break;
|
|
}
|
|
case 3 /* NoScale */:
|
|
case 4 /* NoScaleOrReflection */: {
|
|
let cos = MathUtils.cosDeg(rotation);
|
|
let sin = MathUtils.sinDeg(rotation);
|
|
let za = (pa * cos + pb * sin) / this.skeleton.scaleX;
|
|
let zc = (pc * cos + pd * sin) / this.skeleton.scaleY;
|
|
let s = Math.sqrt(za * za + zc * zc);
|
|
if (s > 1e-5)
|
|
s = 1 / s;
|
|
za *= s;
|
|
zc *= s;
|
|
s = Math.sqrt(za * za + zc * zc);
|
|
if (this.data.transformMode == 3 /* NoScale */ && pa * pd - pb * pc < 0 != (this.skeleton.scaleX < 0 != this.skeleton.scaleY < 0))
|
|
s = -s;
|
|
let r = Math.PI / 2 + Math.atan2(zc, za);
|
|
let zb = Math.cos(r) * s;
|
|
let zd = Math.sin(r) * s;
|
|
let la = MathUtils.cosDeg(shearX) * scaleX;
|
|
let lb = MathUtils.cosDeg(90 + shearY) * scaleY;
|
|
let lc = MathUtils.sinDeg(shearX) * scaleX;
|
|
let ld = MathUtils.sinDeg(90 + shearY) * scaleY;
|
|
this.a = za * la + zb * lc;
|
|
this.b = za * lb + zb * ld;
|
|
this.c = zc * la + zd * lc;
|
|
this.d = zc * lb + zd * ld;
|
|
break;
|
|
}
|
|
}
|
|
this.a *= this.skeleton.scaleX;
|
|
this.b *= this.skeleton.scaleX;
|
|
this.c *= this.skeleton.scaleY;
|
|
this.d *= this.skeleton.scaleY;
|
|
}
|
|
setToSetupPose() {
|
|
let data = this.data;
|
|
this.x = data.x;
|
|
this.y = data.y;
|
|
this.rotation = data.rotation;
|
|
this.scaleX = data.scaleX;
|
|
this.scaleY = data.scaleY;
|
|
this.shearX = data.shearX;
|
|
this.shearY = data.shearY;
|
|
}
|
|
getWorldRotationX() {
|
|
return Math.atan2(this.c, this.a) * MathUtils.radDeg;
|
|
}
|
|
getWorldRotationY() {
|
|
return Math.atan2(this.d, this.b) * MathUtils.radDeg;
|
|
}
|
|
getWorldScaleX() {
|
|
return Math.sqrt(this.a * this.a + this.c * this.c);
|
|
}
|
|
getWorldScaleY() {
|
|
return Math.sqrt(this.b * this.b + this.d * this.d);
|
|
}
|
|
updateAppliedTransform() {
|
|
let parent = this.parent;
|
|
if (!parent) {
|
|
this.ax = this.worldX - this.skeleton.x;
|
|
this.ay = this.worldY - this.skeleton.y;
|
|
this.arotation = Math.atan2(this.c, this.a) * MathUtils.radDeg;
|
|
this.ascaleX = Math.sqrt(this.a * this.a + this.c * this.c);
|
|
this.ascaleY = Math.sqrt(this.b * this.b + this.d * this.d);
|
|
this.ashearX = 0;
|
|
this.ashearY = Math.atan2(this.a * this.b + this.c * this.d, this.a * this.d - this.b * this.c) * MathUtils.radDeg;
|
|
return;
|
|
}
|
|
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
|
let pid = 1 / (pa * pd - pb * pc);
|
|
let dx = this.worldX - parent.worldX, dy = this.worldY - parent.worldY;
|
|
this.ax = dx * pd * pid - dy * pb * pid;
|
|
this.ay = dy * pa * pid - dx * pc * pid;
|
|
let ia = pid * pd;
|
|
let id = pid * pa;
|
|
let ib = pid * pb;
|
|
let ic = pid * pc;
|
|
let ra = ia * this.a - ib * this.c;
|
|
let rb = ia * this.b - ib * this.d;
|
|
let rc = id * this.c - ic * this.a;
|
|
let rd = id * this.d - ic * this.b;
|
|
this.ashearX = 0;
|
|
this.ascaleX = Math.sqrt(ra * ra + rc * rc);
|
|
if (this.ascaleX > 1e-4) {
|
|
let det = ra * rd - rb * rc;
|
|
this.ascaleY = det / this.ascaleX;
|
|
this.ashearY = Math.atan2(ra * rb + rc * rd, det) * MathUtils.radDeg;
|
|
this.arotation = Math.atan2(rc, ra) * MathUtils.radDeg;
|
|
} else {
|
|
this.ascaleX = 0;
|
|
this.ascaleY = Math.sqrt(rb * rb + rd * rd);
|
|
this.ashearY = 0;
|
|
this.arotation = 90 - Math.atan2(rd, rb) * MathUtils.radDeg;
|
|
}
|
|
}
|
|
worldToLocal(world) {
|
|
let invDet = 1 / (this.a * this.d - this.b * this.c);
|
|
let x = world.x - this.worldX, y = world.y - this.worldY;
|
|
world.x = x * this.d * invDet - y * this.b * invDet;
|
|
world.y = y * this.a * invDet - x * this.c * invDet;
|
|
return world;
|
|
}
|
|
localToWorld(local) {
|
|
let x = local.x, y = local.y;
|
|
local.x = x * this.a + y * this.b + this.worldX;
|
|
local.y = x * this.c + y * this.d + this.worldY;
|
|
return local;
|
|
}
|
|
worldToLocalRotation(worldRotation) {
|
|
let sin = MathUtils.sinDeg(worldRotation), cos = MathUtils.cosDeg(worldRotation);
|
|
return Math.atan2(this.a * sin - this.c * cos, this.d * cos - this.b * sin) * MathUtils.radDeg + this.rotation - this.shearX;
|
|
}
|
|
localToWorldRotation(localRotation) {
|
|
localRotation -= this.rotation - this.shearX;
|
|
let sin = MathUtils.sinDeg(localRotation), cos = MathUtils.cosDeg(localRotation);
|
|
return Math.atan2(cos * this.c + sin * this.d, cos * this.a + sin * this.b) * MathUtils.radDeg;
|
|
}
|
|
rotateWorld(degrees) {
|
|
let a = this.a, b = this.b, c = this.c, d = this.d;
|
|
let cos = MathUtils.cosDeg(degrees), sin = MathUtils.sinDeg(degrees);
|
|
this.a = cos * a - sin * c;
|
|
this.b = cos * b - sin * d;
|
|
this.c = sin * a + cos * c;
|
|
this.d = sin * b + cos * d;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/ConstraintData.ts
|
|
var ConstraintData = class {
|
|
constructor(name, order, skinRequired) {
|
|
this.name = name;
|
|
this.order = order;
|
|
this.skinRequired = skinRequired;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/AssetManagerBase.ts
|
|
var AssetManagerBase = class {
|
|
constructor(textureLoader, pathPrefix = "", downloader = new Downloader()) {
|
|
this.pathPrefix = "";
|
|
this.assets = {};
|
|
this.errors = {};
|
|
this.toLoad = 0;
|
|
this.loaded = 0;
|
|
this.textureLoader = textureLoader;
|
|
this.pathPrefix = pathPrefix;
|
|
this.downloader = downloader;
|
|
}
|
|
start(path) {
|
|
this.toLoad++;
|
|
return this.pathPrefix + path;
|
|
}
|
|
success(callback, path, asset) {
|
|
this.toLoad--;
|
|
this.loaded++;
|
|
this.assets[path] = asset;
|
|
if (callback)
|
|
callback(path, asset);
|
|
}
|
|
error(callback, path, message) {
|
|
this.toLoad--;
|
|
this.loaded++;
|
|
this.errors[path] = message;
|
|
if (callback)
|
|
callback(path, message);
|
|
}
|
|
loadAll() {
|
|
let promise = new Promise((resolve, reject) => {
|
|
let check = () => {
|
|
if (this.isLoadingComplete()) {
|
|
if (this.hasErrors())
|
|
reject(this.errors);
|
|
else
|
|
resolve(this);
|
|
return;
|
|
}
|
|
requestAnimationFrame(check);
|
|
};
|
|
requestAnimationFrame(check);
|
|
});
|
|
return promise;
|
|
}
|
|
setRawDataURI(path, data) {
|
|
this.downloader.rawDataUris[this.pathPrefix + path] = data;
|
|
}
|
|
loadBinary(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
this.downloader.downloadBinary(path, (data) => {
|
|
this.success(success, path, data);
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load binary ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
loadText(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
this.downloader.downloadText(path, (data) => {
|
|
this.success(success, path, data);
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load text ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
loadJson(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
this.downloader.downloadJson(path, (data) => {
|
|
this.success(success, path, data);
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load JSON ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
loadTexture(path, success = () => {
|
|
}, error = () => {
|
|
}) {
|
|
path = this.start(path);
|
|
let isBrowser = !!(typeof window !== "undefined" && typeof navigator !== "undefined" && window.document);
|
|
let isWebWorker = !isBrowser;
|
|
if (isWebWorker) {
|
|
fetch(path, { mode: "cors" }).then((response) => {
|
|
if (response.ok)
|
|
return response.blob();
|
|
this.error(error, path, `Couldn't load image: ${path}`);
|
|
return null;
|
|
}).then((blob) => {
|
|
return blob ? createImageBitmap(blob, { premultiplyAlpha: "none", colorSpaceConversion: "none" }) : null;
|
|
}).then((bitmap) => {
|
|
if (bitmap)
|
|
this.success(success, path, this.textureLoader(bitmap));
|
|
});
|
|
} else {
|
|
let image = new Image();
|
|
image.crossOrigin = "anonymous";
|
|
image.onload = () => {
|
|
this.success(success, path, this.textureLoader(image));
|
|
};
|
|
image.onerror = () => {
|
|
this.error(error, path, `Couldn't load image: ${path}`);
|
|
};
|
|
if (this.downloader.rawDataUris[path])
|
|
path = this.downloader.rawDataUris[path];
|
|
image.src = path;
|
|
}
|
|
}
|
|
loadTextureAtlas(path, success = () => {
|
|
}, error = () => {
|
|
}, fileAlias) {
|
|
let index = path.lastIndexOf("/");
|
|
let parent = index >= 0 ? path.substring(0, index + 1) : "";
|
|
path = this.start(path);
|
|
this.downloader.downloadText(path, (atlasText) => {
|
|
try {
|
|
let atlas = new TextureAtlas(atlasText);
|
|
let toLoad = atlas.pages.length, abort = false;
|
|
for (let page of atlas.pages) {
|
|
this.loadTexture(
|
|
!fileAlias ? parent + page.name : fileAlias[page.name],
|
|
(imagePath, texture) => {
|
|
if (!abort) {
|
|
page.setTexture(texture);
|
|
if (--toLoad == 0)
|
|
this.success(success, path, atlas);
|
|
}
|
|
},
|
|
(imagePath, message) => {
|
|
if (!abort)
|
|
this.error(error, path, `Couldn't load texture atlas ${path} page image: ${imagePath}`);
|
|
abort = true;
|
|
}
|
|
);
|
|
}
|
|
} catch (e) {
|
|
this.error(error, path, `Couldn't parse texture atlas ${path}: ${e.message}`);
|
|
}
|
|
}, (status, responseText) => {
|
|
this.error(error, path, `Couldn't load texture atlas ${path}: status ${status}, ${responseText}`);
|
|
});
|
|
}
|
|
get(path) {
|
|
return this.assets[this.pathPrefix + path];
|
|
}
|
|
require(path) {
|
|
path = this.pathPrefix + path;
|
|
let asset = this.assets[path];
|
|
if (asset)
|
|
return asset;
|
|
let error = this.errors[path];
|
|
throw Error("Asset not found: " + path + (error ? "\n" + error : ""));
|
|
}
|
|
remove(path) {
|
|
path = this.pathPrefix + path;
|
|
let asset = this.assets[path];
|
|
if (asset.dispose)
|
|
asset.dispose();
|
|
delete this.assets[path];
|
|
return asset;
|
|
}
|
|
removeAll() {
|
|
for (let key in this.assets) {
|
|
let asset = this.assets[key];
|
|
if (asset.dispose)
|
|
asset.dispose();
|
|
}
|
|
this.assets = {};
|
|
}
|
|
isLoadingComplete() {
|
|
return this.toLoad == 0;
|
|
}
|
|
getToLoad() {
|
|
return this.toLoad;
|
|
}
|
|
getLoaded() {
|
|
return this.loaded;
|
|
}
|
|
dispose() {
|
|
this.removeAll();
|
|
}
|
|
hasErrors() {
|
|
return Object.keys(this.errors).length > 0;
|
|
}
|
|
getErrors() {
|
|
return this.errors;
|
|
}
|
|
};
|
|
var Downloader = class {
|
|
constructor() {
|
|
this.callbacks = {};
|
|
this.rawDataUris = {};
|
|
}
|
|
dataUriToString(dataUri) {
|
|
if (!dataUri.startsWith("data:")) {
|
|
throw new Error("Not a data URI.");
|
|
}
|
|
let base64Idx = dataUri.indexOf("base64,");
|
|
if (base64Idx != -1) {
|
|
base64Idx += "base64,".length;
|
|
return atob(dataUri.substr(base64Idx));
|
|
} else {
|
|
return dataUri.substr(dataUri.indexOf(",") + 1);
|
|
}
|
|
}
|
|
base64ToUint8Array(base64) {
|
|
var binary_string = window.atob(base64);
|
|
var len = binary_string.length;
|
|
var bytes = new Uint8Array(len);
|
|
for (var i = 0; i < len; i++) {
|
|
bytes[i] = binary_string.charCodeAt(i);
|
|
}
|
|
return bytes;
|
|
}
|
|
dataUriToUint8Array(dataUri) {
|
|
if (!dataUri.startsWith("data:")) {
|
|
throw new Error("Not a data URI.");
|
|
}
|
|
let base64Idx = dataUri.indexOf("base64,");
|
|
if (base64Idx == -1)
|
|
throw new Error("Not a binary data URI.");
|
|
base64Idx += "base64,".length;
|
|
return this.base64ToUint8Array(dataUri.substr(base64Idx));
|
|
}
|
|
downloadText(url, success, error) {
|
|
if (this.start(url, success, error))
|
|
return;
|
|
if (this.rawDataUris[url]) {
|
|
try {
|
|
let dataUri = this.rawDataUris[url];
|
|
this.finish(url, 200, this.dataUriToString(dataUri));
|
|
} catch (e) {
|
|
this.finish(url, 400, JSON.stringify(e));
|
|
}
|
|
return;
|
|
}
|
|
let request = new XMLHttpRequest();
|
|
request.overrideMimeType("text/html");
|
|
request.open("GET", url, true);
|
|
let done = () => {
|
|
this.finish(url, request.status, request.responseText);
|
|
};
|
|
request.onload = done;
|
|
request.onerror = done;
|
|
request.send();
|
|
}
|
|
downloadJson(url, success, error) {
|
|
this.downloadText(url, (data) => {
|
|
success(JSON.parse(data));
|
|
}, error);
|
|
}
|
|
downloadBinary(url, success, error) {
|
|
if (this.start(url, success, error))
|
|
return;
|
|
if (this.rawDataUris[url]) {
|
|
try {
|
|
let dataUri = this.rawDataUris[url];
|
|
this.finish(url, 200, this.dataUriToUint8Array(dataUri));
|
|
} catch (e) {
|
|
this.finish(url, 400, JSON.stringify(e));
|
|
}
|
|
return;
|
|
}
|
|
let request = new XMLHttpRequest();
|
|
request.open("GET", url, true);
|
|
request.responseType = "arraybuffer";
|
|
let onerror = () => {
|
|
this.finish(url, request.status, request.response);
|
|
};
|
|
request.onload = () => {
|
|
if (request.status == 200 || request.status == 0)
|
|
this.finish(url, 200, new Uint8Array(request.response));
|
|
else
|
|
onerror();
|
|
};
|
|
request.onerror = onerror;
|
|
request.send();
|
|
}
|
|
start(url, success, error) {
|
|
let callbacks = this.callbacks[url];
|
|
try {
|
|
if (callbacks)
|
|
return true;
|
|
this.callbacks[url] = callbacks = [];
|
|
} finally {
|
|
callbacks.push(success, error);
|
|
}
|
|
}
|
|
finish(url, status, data) {
|
|
let callbacks = this.callbacks[url];
|
|
delete this.callbacks[url];
|
|
let args = status == 200 || status == 0 ? [data] : [status, data];
|
|
for (let i = args.length - 1, n = callbacks.length; i < n; i += 2)
|
|
callbacks[i].apply(null, args);
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Event.ts
|
|
var Event = class {
|
|
constructor(time, data) {
|
|
this.intValue = 0;
|
|
this.floatValue = 0;
|
|
this.stringValue = null;
|
|
this.time = 0;
|
|
this.volume = 0;
|
|
this.balance = 0;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
this.time = time;
|
|
this.data = data;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/EventData.ts
|
|
var EventData = class {
|
|
constructor(name) {
|
|
this.intValue = 0;
|
|
this.floatValue = 0;
|
|
this.stringValue = null;
|
|
this.audioPath = null;
|
|
this.volume = 0;
|
|
this.balance = 0;
|
|
this.name = name;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/IkConstraint.ts
|
|
var IkConstraint = class {
|
|
constructor(data, skeleton) {
|
|
this.bendDirection = 0;
|
|
this.compress = false;
|
|
this.stretch = false;
|
|
this.mix = 1;
|
|
this.softness = 0;
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.mix = data.mix;
|
|
this.softness = data.softness;
|
|
this.bendDirection = data.bendDirection;
|
|
this.compress = data.compress;
|
|
this.stretch = data.stretch;
|
|
this.bones = new Array();
|
|
for (let i = 0; i < data.bones.length; i++) {
|
|
let bone = skeleton.findBone(data.bones[i].name);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${data.bones[i].name}`);
|
|
this.bones.push(bone);
|
|
}
|
|
let target = skeleton.findBone(data.target.name);
|
|
if (!target)
|
|
throw new Error(`Couldn't find bone ${data.target.name}`);
|
|
this.target = target;
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
if (this.mix == 0)
|
|
return;
|
|
let target = this.target;
|
|
let bones = this.bones;
|
|
switch (bones.length) {
|
|
case 1:
|
|
this.apply1(bones[0], target.worldX, target.worldY, this.compress, this.stretch, this.data.uniform, this.mix);
|
|
break;
|
|
case 2:
|
|
this.apply2(bones[0], bones[1], target.worldX, target.worldY, this.bendDirection, this.stretch, this.data.uniform, this.softness, this.mix);
|
|
break;
|
|
}
|
|
}
|
|
apply1(bone, targetX, targetY, compress, stretch, uniform, alpha) {
|
|
let p = bone.parent;
|
|
if (!p)
|
|
throw new Error("IK bone must have parent.");
|
|
let pa = p.a, pb = p.b, pc = p.c, pd = p.d;
|
|
let rotationIK = -bone.ashearX - bone.arotation, tx = 0, ty = 0;
|
|
switch (bone.data.transformMode) {
|
|
case 1 /* OnlyTranslation */:
|
|
tx = targetX - bone.worldX;
|
|
ty = targetY - bone.worldY;
|
|
break;
|
|
case 2 /* NoRotationOrReflection */:
|
|
let s = Math.abs(pa * pd - pb * pc) / (pa * pa + pc * pc);
|
|
let sa = pa / bone.skeleton.scaleX;
|
|
let sc = pc / bone.skeleton.scaleY;
|
|
pb = -sc * s * bone.skeleton.scaleX;
|
|
pd = sa * s * bone.skeleton.scaleY;
|
|
rotationIK += Math.atan2(sc, sa) * MathUtils.radDeg;
|
|
default:
|
|
let x = targetX - p.worldX, y = targetY - p.worldY;
|
|
let d = pa * pd - pb * pc;
|
|
tx = (x * pd - y * pb) / d - bone.ax;
|
|
ty = (y * pa - x * pc) / d - bone.ay;
|
|
}
|
|
rotationIK += Math.atan2(ty, tx) * MathUtils.radDeg;
|
|
if (bone.ascaleX < 0)
|
|
rotationIK += 180;
|
|
if (rotationIK > 180)
|
|
rotationIK -= 360;
|
|
else if (rotationIK < -180)
|
|
rotationIK += 360;
|
|
let sx = bone.ascaleX, sy = bone.ascaleY;
|
|
if (compress || stretch) {
|
|
switch (bone.data.transformMode) {
|
|
case 3 /* NoScale */:
|
|
case 4 /* NoScaleOrReflection */:
|
|
tx = targetX - bone.worldX;
|
|
ty = targetY - bone.worldY;
|
|
}
|
|
let b = bone.data.length * sx, dd = Math.sqrt(tx * tx + ty * ty);
|
|
if (compress && dd < b || stretch && dd > b && b > 1e-4) {
|
|
let s = (dd / b - 1) * alpha + 1;
|
|
sx *= s;
|
|
if (uniform)
|
|
sy *= s;
|
|
}
|
|
}
|
|
bone.updateWorldTransformWith(
|
|
bone.ax,
|
|
bone.ay,
|
|
bone.arotation + rotationIK * alpha,
|
|
sx,
|
|
sy,
|
|
bone.ashearX,
|
|
bone.ashearY
|
|
);
|
|
}
|
|
apply2(parent, child, targetX, targetY, bendDir, stretch, uniform, softness, alpha) {
|
|
let px = parent.ax, py = parent.ay, psx = parent.ascaleX, psy = parent.ascaleY, sx = psx, sy = psy, csx = child.ascaleX;
|
|
let os1 = 0, os2 = 0, s2 = 0;
|
|
if (psx < 0) {
|
|
psx = -psx;
|
|
os1 = 180;
|
|
s2 = -1;
|
|
} else {
|
|
os1 = 0;
|
|
s2 = 1;
|
|
}
|
|
if (psy < 0) {
|
|
psy = -psy;
|
|
s2 = -s2;
|
|
}
|
|
if (csx < 0) {
|
|
csx = -csx;
|
|
os2 = 180;
|
|
} else
|
|
os2 = 0;
|
|
let cx = child.ax, cy = 0, cwx = 0, cwy = 0, a = parent.a, b = parent.b, c = parent.c, d = parent.d;
|
|
let u = Math.abs(psx - psy) <= 1e-4;
|
|
if (!u || stretch) {
|
|
cy = 0;
|
|
cwx = a * cx + parent.worldX;
|
|
cwy = c * cx + parent.worldY;
|
|
} else {
|
|
cy = child.ay;
|
|
cwx = a * cx + b * cy + parent.worldX;
|
|
cwy = c * cx + d * cy + parent.worldY;
|
|
}
|
|
let pp = parent.parent;
|
|
if (!pp)
|
|
throw new Error("IK parent must itself have a parent.");
|
|
a = pp.a;
|
|
b = pp.b;
|
|
c = pp.c;
|
|
d = pp.d;
|
|
let id = 1 / (a * d - b * c), x = cwx - pp.worldX, y = cwy - pp.worldY;
|
|
let dx = (x * d - y * b) * id - px, dy = (y * a - x * c) * id - py;
|
|
let l1 = Math.sqrt(dx * dx + dy * dy), l2 = child.data.length * csx, a1, a2;
|
|
if (l1 < 1e-4) {
|
|
this.apply1(parent, targetX, targetY, false, stretch, false, alpha);
|
|
child.updateWorldTransformWith(cx, cy, 0, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
|
|
return;
|
|
}
|
|
x = targetX - pp.worldX;
|
|
y = targetY - pp.worldY;
|
|
let tx = (x * d - y * b) * id - px, ty = (y * a - x * c) * id - py;
|
|
let dd = tx * tx + ty * ty;
|
|
if (softness != 0) {
|
|
softness *= psx * (csx + 1) * 0.5;
|
|
let td = Math.sqrt(dd), sd = td - l1 - l2 * psx + softness;
|
|
if (sd > 0) {
|
|
let p = Math.min(1, sd / (softness * 2)) - 1;
|
|
p = (sd - softness * (1 - p * p)) / td;
|
|
tx -= p * tx;
|
|
ty -= p * ty;
|
|
dd = tx * tx + ty * ty;
|
|
}
|
|
}
|
|
outer:
|
|
if (u) {
|
|
l2 *= psx;
|
|
let cos = (dd - l1 * l1 - l2 * l2) / (2 * l1 * l2);
|
|
if (cos < -1) {
|
|
cos = -1;
|
|
a2 = Math.PI * bendDir;
|
|
} else if (cos > 1) {
|
|
cos = 1;
|
|
a2 = 0;
|
|
if (stretch) {
|
|
a = (Math.sqrt(dd) / (l1 + l2) - 1) * alpha + 1;
|
|
sx *= a;
|
|
if (uniform)
|
|
sy *= a;
|
|
}
|
|
} else
|
|
a2 = Math.acos(cos) * bendDir;
|
|
a = l1 + l2 * cos;
|
|
b = l2 * Math.sin(a2);
|
|
a1 = Math.atan2(ty * a - tx * b, tx * a + ty * b);
|
|
} else {
|
|
a = psx * l2;
|
|
b = psy * l2;
|
|
let aa = a * a, bb = b * b, ta = Math.atan2(ty, tx);
|
|
c = bb * l1 * l1 + aa * dd - aa * bb;
|
|
let c1 = -2 * bb * l1, c2 = bb - aa;
|
|
d = c1 * c1 - 4 * c2 * c;
|
|
if (d >= 0) {
|
|
let q = Math.sqrt(d);
|
|
if (c1 < 0)
|
|
q = -q;
|
|
q = -(c1 + q) * 0.5;
|
|
let r0 = q / c2, r1 = c / q;
|
|
let r = Math.abs(r0) < Math.abs(r1) ? r0 : r1;
|
|
if (r * r <= dd) {
|
|
y = Math.sqrt(dd - r * r) * bendDir;
|
|
a1 = ta - Math.atan2(y, r);
|
|
a2 = Math.atan2(y / psy, (r - l1) / psx);
|
|
break outer;
|
|
}
|
|
}
|
|
let minAngle = MathUtils.PI, minX = l1 - a, minDist = minX * minX, minY = 0;
|
|
let maxAngle = 0, maxX = l1 + a, maxDist = maxX * maxX, maxY = 0;
|
|
c = -a * l1 / (aa - bb);
|
|
if (c >= -1 && c <= 1) {
|
|
c = Math.acos(c);
|
|
x = a * Math.cos(c) + l1;
|
|
y = b * Math.sin(c);
|
|
d = x * x + y * y;
|
|
if (d < minDist) {
|
|
minAngle = c;
|
|
minDist = d;
|
|
minX = x;
|
|
minY = y;
|
|
}
|
|
if (d > maxDist) {
|
|
maxAngle = c;
|
|
maxDist = d;
|
|
maxX = x;
|
|
maxY = y;
|
|
}
|
|
}
|
|
if (dd <= (minDist + maxDist) * 0.5) {
|
|
a1 = ta - Math.atan2(minY * bendDir, minX);
|
|
a2 = minAngle * bendDir;
|
|
} else {
|
|
a1 = ta - Math.atan2(maxY * bendDir, maxX);
|
|
a2 = maxAngle * bendDir;
|
|
}
|
|
}
|
|
let os = Math.atan2(cy, cx) * s2;
|
|
let rotation = parent.arotation;
|
|
a1 = (a1 - os) * MathUtils.radDeg + os1 - rotation;
|
|
if (a1 > 180)
|
|
a1 -= 360;
|
|
else if (a1 < -180)
|
|
a1 += 360;
|
|
parent.updateWorldTransformWith(px, py, rotation + a1 * alpha, sx, sy, 0, 0);
|
|
rotation = child.arotation;
|
|
a2 = ((a2 + os) * MathUtils.radDeg - child.ashearX) * s2 + os2 - rotation;
|
|
if (a2 > 180)
|
|
a2 -= 360;
|
|
else if (a2 < -180)
|
|
a2 += 360;
|
|
child.updateWorldTransformWith(cx, cy, rotation + a2 * alpha, child.ascaleX, child.ascaleY, child.ashearX, child.ashearY);
|
|
}
|
|
};
|
|
|
|
// spine-core/src/IkConstraintData.ts
|
|
var IkConstraintData = class extends ConstraintData {
|
|
constructor(name) {
|
|
super(name, 0, false);
|
|
this.bones = new Array();
|
|
this._target = null;
|
|
this.bendDirection = 1;
|
|
this.compress = false;
|
|
this.stretch = false;
|
|
this.uniform = false;
|
|
this.mix = 1;
|
|
this.softness = 0;
|
|
}
|
|
set target(boneData) {
|
|
this._target = boneData;
|
|
}
|
|
get target() {
|
|
if (!this._target)
|
|
throw new Error("BoneData not set.");
|
|
else
|
|
return this._target;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/PathConstraintData.ts
|
|
var PathConstraintData = class extends ConstraintData {
|
|
constructor(name) {
|
|
super(name, 0, false);
|
|
this.bones = new Array();
|
|
this._target = null;
|
|
this.positionMode = PositionMode.Fixed;
|
|
this.spacingMode = SpacingMode.Fixed;
|
|
this.rotateMode = RotateMode.Chain;
|
|
this.offsetRotation = 0;
|
|
this.position = 0;
|
|
this.spacing = 0;
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
}
|
|
set target(slotData) {
|
|
this._target = slotData;
|
|
}
|
|
get target() {
|
|
if (!this._target)
|
|
throw new Error("SlotData not set.");
|
|
else
|
|
return this._target;
|
|
}
|
|
};
|
|
var PositionMode = /* @__PURE__ */ ((PositionMode2) => {
|
|
PositionMode2[PositionMode2["Fixed"] = 0] = "Fixed";
|
|
PositionMode2[PositionMode2["Percent"] = 1] = "Percent";
|
|
return PositionMode2;
|
|
})(PositionMode || {});
|
|
var SpacingMode = /* @__PURE__ */ ((SpacingMode2) => {
|
|
SpacingMode2[SpacingMode2["Length"] = 0] = "Length";
|
|
SpacingMode2[SpacingMode2["Fixed"] = 1] = "Fixed";
|
|
SpacingMode2[SpacingMode2["Percent"] = 2] = "Percent";
|
|
SpacingMode2[SpacingMode2["Proportional"] = 3] = "Proportional";
|
|
return SpacingMode2;
|
|
})(SpacingMode || {});
|
|
var RotateMode = /* @__PURE__ */ ((RotateMode2) => {
|
|
RotateMode2[RotateMode2["Tangent"] = 0] = "Tangent";
|
|
RotateMode2[RotateMode2["Chain"] = 1] = "Chain";
|
|
RotateMode2[RotateMode2["ChainScale"] = 2] = "ChainScale";
|
|
return RotateMode2;
|
|
})(RotateMode || {});
|
|
|
|
// spine-core/src/PathConstraint.ts
|
|
var _PathConstraint = class {
|
|
constructor(data, skeleton) {
|
|
this.position = 0;
|
|
this.spacing = 0;
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
this.spaces = new Array();
|
|
this.positions = new Array();
|
|
this.world = new Array();
|
|
this.curves = new Array();
|
|
this.lengths = new Array();
|
|
this.segments = new Array();
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.bones = new Array();
|
|
for (let i = 0, n = data.bones.length; i < n; i++) {
|
|
let bone = skeleton.findBone(data.bones[i].name);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${data.bones[i].name}.`);
|
|
this.bones.push(bone);
|
|
}
|
|
let target = skeleton.findSlot(data.target.name);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${data.target.name}`);
|
|
this.target = target;
|
|
this.position = data.position;
|
|
this.spacing = data.spacing;
|
|
this.mixRotate = data.mixRotate;
|
|
this.mixX = data.mixX;
|
|
this.mixY = data.mixY;
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
let attachment = this.target.getAttachment();
|
|
if (!(attachment instanceof PathAttachment))
|
|
return;
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY;
|
|
if (mixRotate == 0 && mixX == 0 && mixY == 0)
|
|
return;
|
|
let data = this.data;
|
|
let tangents = data.rotateMode == 0 /* Tangent */, scale = data.rotateMode == 2 /* ChainScale */;
|
|
let bones = this.bones;
|
|
let boneCount = bones.length, spacesCount = tangents ? boneCount : boneCount + 1;
|
|
let spaces = Utils.setArraySize(this.spaces, spacesCount), lengths = scale ? this.lengths = Utils.setArraySize(this.lengths, boneCount) : [];
|
|
let spacing = this.spacing;
|
|
switch (data.spacingMode) {
|
|
case 2 /* Percent */:
|
|
if (scale) {
|
|
for (let i = 0, n = spacesCount - 1; i < n; i++) {
|
|
let bone = bones[i];
|
|
let setupLength = bone.data.length;
|
|
if (setupLength < _PathConstraint.epsilon)
|
|
lengths[i] = 0;
|
|
else {
|
|
let x = setupLength * bone.a, y = setupLength * bone.c;
|
|
lengths[i] = Math.sqrt(x * x + y * y);
|
|
}
|
|
}
|
|
}
|
|
Utils.arrayFill(spaces, 1, spacesCount, spacing);
|
|
break;
|
|
case 3 /* Proportional */:
|
|
let sum = 0;
|
|
for (let i = 0, n = spacesCount - 1; i < n; ) {
|
|
let bone = bones[i];
|
|
let setupLength = bone.data.length;
|
|
if (setupLength < _PathConstraint.epsilon) {
|
|
if (scale)
|
|
lengths[i] = 0;
|
|
spaces[++i] = spacing;
|
|
} else {
|
|
let x = setupLength * bone.a, y = setupLength * bone.c;
|
|
let length = Math.sqrt(x * x + y * y);
|
|
if (scale)
|
|
lengths[i] = length;
|
|
spaces[++i] = length;
|
|
sum += length;
|
|
}
|
|
}
|
|
if (sum > 0) {
|
|
sum = spacesCount / sum * spacing;
|
|
for (let i = 1; i < spacesCount; i++)
|
|
spaces[i] *= sum;
|
|
}
|
|
break;
|
|
default:
|
|
let lengthSpacing = data.spacingMode == 0 /* Length */;
|
|
for (let i = 0, n = spacesCount - 1; i < n; ) {
|
|
let bone = bones[i];
|
|
let setupLength = bone.data.length;
|
|
if (setupLength < _PathConstraint.epsilon) {
|
|
if (scale)
|
|
lengths[i] = 0;
|
|
spaces[++i] = spacing;
|
|
} else {
|
|
let x = setupLength * bone.a, y = setupLength * bone.c;
|
|
let length = Math.sqrt(x * x + y * y);
|
|
if (scale)
|
|
lengths[i] = length;
|
|
spaces[++i] = (lengthSpacing ? setupLength + spacing : spacing) * length / setupLength;
|
|
}
|
|
}
|
|
}
|
|
let positions = this.computeWorldPositions(attachment, spacesCount, tangents);
|
|
let boneX = positions[0], boneY = positions[1], offsetRotation = data.offsetRotation;
|
|
let tip = false;
|
|
if (offsetRotation == 0)
|
|
tip = data.rotateMode == 1 /* Chain */;
|
|
else {
|
|
tip = false;
|
|
let p = this.target.bone;
|
|
offsetRotation *= p.a * p.d - p.b * p.c > 0 ? MathUtils.degRad : -MathUtils.degRad;
|
|
}
|
|
for (let i = 0, p = 3; i < boneCount; i++, p += 3) {
|
|
let bone = bones[i];
|
|
bone.worldX += (boneX - bone.worldX) * mixX;
|
|
bone.worldY += (boneY - bone.worldY) * mixY;
|
|
let x = positions[p], y = positions[p + 1], dx = x - boneX, dy = y - boneY;
|
|
if (scale) {
|
|
let length = lengths[i];
|
|
if (length != 0) {
|
|
let s = (Math.sqrt(dx * dx + dy * dy) / length - 1) * mixRotate + 1;
|
|
bone.a *= s;
|
|
bone.c *= s;
|
|
}
|
|
}
|
|
boneX = x;
|
|
boneY = y;
|
|
if (mixRotate > 0) {
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d, r = 0, cos = 0, sin = 0;
|
|
if (tangents)
|
|
r = positions[p - 1];
|
|
else if (spaces[i + 1] == 0)
|
|
r = positions[p + 2];
|
|
else
|
|
r = Math.atan2(dy, dx);
|
|
r -= Math.atan2(c, a);
|
|
if (tip) {
|
|
cos = Math.cos(r);
|
|
sin = Math.sin(r);
|
|
let length = bone.data.length;
|
|
boneX += (length * (cos * a - sin * c) - dx) * mixRotate;
|
|
boneY += (length * (sin * a + cos * c) - dy) * mixRotate;
|
|
} else {
|
|
r += offsetRotation;
|
|
}
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r *= mixRotate;
|
|
cos = Math.cos(r);
|
|
sin = Math.sin(r);
|
|
bone.a = cos * a - sin * c;
|
|
bone.b = cos * b - sin * d;
|
|
bone.c = sin * a + cos * c;
|
|
bone.d = sin * b + cos * d;
|
|
}
|
|
bone.updateAppliedTransform();
|
|
}
|
|
}
|
|
computeWorldPositions(path, spacesCount, tangents) {
|
|
let target = this.target;
|
|
let position = this.position;
|
|
let spaces = this.spaces, out = Utils.setArraySize(this.positions, spacesCount * 3 + 2), world = this.world;
|
|
let closed2 = path.closed;
|
|
let verticesLength = path.worldVerticesLength, curveCount = verticesLength / 6, prevCurve = _PathConstraint.NONE;
|
|
if (!path.constantSpeed) {
|
|
let lengths = path.lengths;
|
|
curveCount -= closed2 ? 1 : 2;
|
|
let pathLength2 = lengths[curveCount];
|
|
if (this.data.positionMode == 1 /* Percent */)
|
|
position *= pathLength2;
|
|
let multiplier2;
|
|
switch (this.data.spacingMode) {
|
|
case 2 /* Percent */:
|
|
multiplier2 = pathLength2;
|
|
break;
|
|
case 3 /* Proportional */:
|
|
multiplier2 = pathLength2 / spacesCount;
|
|
break;
|
|
default:
|
|
multiplier2 = 1;
|
|
}
|
|
world = Utils.setArraySize(this.world, 8);
|
|
for (let i = 0, o = 0, curve = 0; i < spacesCount; i++, o += 3) {
|
|
let space = spaces[i] * multiplier2;
|
|
position += space;
|
|
let p = position;
|
|
if (closed2) {
|
|
p %= pathLength2;
|
|
if (p < 0)
|
|
p += pathLength2;
|
|
curve = 0;
|
|
} else if (p < 0) {
|
|
if (prevCurve != _PathConstraint.BEFORE) {
|
|
prevCurve = _PathConstraint.BEFORE;
|
|
path.computeWorldVertices(target, 2, 4, world, 0, 2);
|
|
}
|
|
this.addBeforePosition(p, world, 0, out, o);
|
|
continue;
|
|
} else if (p > pathLength2) {
|
|
if (prevCurve != _PathConstraint.AFTER) {
|
|
prevCurve = _PathConstraint.AFTER;
|
|
path.computeWorldVertices(target, verticesLength - 6, 4, world, 0, 2);
|
|
}
|
|
this.addAfterPosition(p - pathLength2, world, 0, out, o);
|
|
continue;
|
|
}
|
|
for (; ; curve++) {
|
|
let length = lengths[curve];
|
|
if (p > length)
|
|
continue;
|
|
if (curve == 0)
|
|
p /= length;
|
|
else {
|
|
let prev = lengths[curve - 1];
|
|
p = (p - prev) / (length - prev);
|
|
}
|
|
break;
|
|
}
|
|
if (curve != prevCurve) {
|
|
prevCurve = curve;
|
|
if (closed2 && curve == curveCount) {
|
|
path.computeWorldVertices(target, verticesLength - 4, 4, world, 0, 2);
|
|
path.computeWorldVertices(target, 0, 4, world, 4, 2);
|
|
} else
|
|
path.computeWorldVertices(target, curve * 6 + 2, 8, world, 0, 2);
|
|
}
|
|
this.addCurvePosition(
|
|
p,
|
|
world[0],
|
|
world[1],
|
|
world[2],
|
|
world[3],
|
|
world[4],
|
|
world[5],
|
|
world[6],
|
|
world[7],
|
|
out,
|
|
o,
|
|
tangents || i > 0 && space == 0
|
|
);
|
|
}
|
|
return out;
|
|
}
|
|
if (closed2) {
|
|
verticesLength += 2;
|
|
world = Utils.setArraySize(this.world, verticesLength);
|
|
path.computeWorldVertices(target, 2, verticesLength - 4, world, 0, 2);
|
|
path.computeWorldVertices(target, 0, 2, world, verticesLength - 4, 2);
|
|
world[verticesLength - 2] = world[0];
|
|
world[verticesLength - 1] = world[1];
|
|
} else {
|
|
curveCount--;
|
|
verticesLength -= 4;
|
|
world = Utils.setArraySize(this.world, verticesLength);
|
|
path.computeWorldVertices(target, 2, verticesLength, world, 0, 2);
|
|
}
|
|
let curves = Utils.setArraySize(this.curves, curveCount);
|
|
let pathLength = 0;
|
|
let x1 = world[0], y1 = world[1], cx1 = 0, cy1 = 0, cx2 = 0, cy2 = 0, x2 = 0, y2 = 0;
|
|
let tmpx = 0, tmpy = 0, dddfx = 0, dddfy = 0, ddfx = 0, ddfy = 0, dfx = 0, dfy = 0;
|
|
for (let i = 0, w = 2; i < curveCount; i++, w += 6) {
|
|
cx1 = world[w];
|
|
cy1 = world[w + 1];
|
|
cx2 = world[w + 2];
|
|
cy2 = world[w + 3];
|
|
x2 = world[w + 4];
|
|
y2 = world[w + 5];
|
|
tmpx = (x1 - cx1 * 2 + cx2) * 0.1875;
|
|
tmpy = (y1 - cy1 * 2 + cy2) * 0.1875;
|
|
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 0.09375;
|
|
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 0.09375;
|
|
ddfx = tmpx * 2 + dddfx;
|
|
ddfy = tmpy * 2 + dddfy;
|
|
dfx = (cx1 - x1) * 0.75 + tmpx + dddfx * 0.16666667;
|
|
dfy = (cy1 - y1) * 0.75 + tmpy + dddfy * 0.16666667;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
ddfx += dddfx;
|
|
ddfy += dddfy;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
dfx += ddfx + dddfx;
|
|
dfy += ddfy + dddfy;
|
|
pathLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
curves[i] = pathLength;
|
|
x1 = x2;
|
|
y1 = y2;
|
|
}
|
|
if (this.data.positionMode == 1 /* Percent */)
|
|
position *= pathLength;
|
|
let multiplier;
|
|
switch (this.data.spacingMode) {
|
|
case 2 /* Percent */:
|
|
multiplier = pathLength;
|
|
break;
|
|
case 3 /* Proportional */:
|
|
multiplier = pathLength / spacesCount;
|
|
break;
|
|
default:
|
|
multiplier = 1;
|
|
}
|
|
let segments = this.segments;
|
|
let curveLength = 0;
|
|
for (let i = 0, o = 0, curve = 0, segment = 0; i < spacesCount; i++, o += 3) {
|
|
let space = spaces[i] * multiplier;
|
|
position += space;
|
|
let p = position;
|
|
if (closed2) {
|
|
p %= pathLength;
|
|
if (p < 0)
|
|
p += pathLength;
|
|
curve = 0;
|
|
} else if (p < 0) {
|
|
this.addBeforePosition(p, world, 0, out, o);
|
|
continue;
|
|
} else if (p > pathLength) {
|
|
this.addAfterPosition(p - pathLength, world, verticesLength - 4, out, o);
|
|
continue;
|
|
}
|
|
for (; ; curve++) {
|
|
let length = curves[curve];
|
|
if (p > length)
|
|
continue;
|
|
if (curve == 0)
|
|
p /= length;
|
|
else {
|
|
let prev = curves[curve - 1];
|
|
p = (p - prev) / (length - prev);
|
|
}
|
|
break;
|
|
}
|
|
if (curve != prevCurve) {
|
|
prevCurve = curve;
|
|
let ii = curve * 6;
|
|
x1 = world[ii];
|
|
y1 = world[ii + 1];
|
|
cx1 = world[ii + 2];
|
|
cy1 = world[ii + 3];
|
|
cx2 = world[ii + 4];
|
|
cy2 = world[ii + 5];
|
|
x2 = world[ii + 6];
|
|
y2 = world[ii + 7];
|
|
tmpx = (x1 - cx1 * 2 + cx2) * 0.03;
|
|
tmpy = (y1 - cy1 * 2 + cy2) * 0.03;
|
|
dddfx = ((cx1 - cx2) * 3 - x1 + x2) * 6e-3;
|
|
dddfy = ((cy1 - cy2) * 3 - y1 + y2) * 6e-3;
|
|
ddfx = tmpx * 2 + dddfx;
|
|
ddfy = tmpy * 2 + dddfy;
|
|
dfx = (cx1 - x1) * 0.3 + tmpx + dddfx * 0.16666667;
|
|
dfy = (cy1 - y1) * 0.3 + tmpy + dddfy * 0.16666667;
|
|
curveLength = Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[0] = curveLength;
|
|
for (ii = 1; ii < 8; ii++) {
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
ddfx += dddfx;
|
|
ddfy += dddfy;
|
|
curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[ii] = curveLength;
|
|
}
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[8] = curveLength;
|
|
dfx += ddfx + dddfx;
|
|
dfy += ddfy + dddfy;
|
|
curveLength += Math.sqrt(dfx * dfx + dfy * dfy);
|
|
segments[9] = curveLength;
|
|
segment = 0;
|
|
}
|
|
p *= curveLength;
|
|
for (; ; segment++) {
|
|
let length = segments[segment];
|
|
if (p > length)
|
|
continue;
|
|
if (segment == 0)
|
|
p /= length;
|
|
else {
|
|
let prev = segments[segment - 1];
|
|
p = segment + (p - prev) / (length - prev);
|
|
}
|
|
break;
|
|
}
|
|
this.addCurvePosition(p * 0.1, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents || i > 0 && space == 0);
|
|
}
|
|
return out;
|
|
}
|
|
addBeforePosition(p, temp, i, out, o) {
|
|
let x1 = temp[i], y1 = temp[i + 1], dx = temp[i + 2] - x1, dy = temp[i + 3] - y1, r = Math.atan2(dy, dx);
|
|
out[o] = x1 + p * Math.cos(r);
|
|
out[o + 1] = y1 + p * Math.sin(r);
|
|
out[o + 2] = r;
|
|
}
|
|
addAfterPosition(p, temp, i, out, o) {
|
|
let x1 = temp[i + 2], y1 = temp[i + 3], dx = x1 - temp[i], dy = y1 - temp[i + 1], r = Math.atan2(dy, dx);
|
|
out[o] = x1 + p * Math.cos(r);
|
|
out[o + 1] = y1 + p * Math.sin(r);
|
|
out[o + 2] = r;
|
|
}
|
|
addCurvePosition(p, x1, y1, cx1, cy1, cx2, cy2, x2, y2, out, o, tangents) {
|
|
if (p == 0 || isNaN(p)) {
|
|
out[o] = x1;
|
|
out[o + 1] = y1;
|
|
out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);
|
|
return;
|
|
}
|
|
let tt = p * p, ttt = tt * p, u = 1 - p, uu = u * u, uuu = uu * u;
|
|
let ut = u * p, ut3 = ut * 3, uut3 = u * ut3, utt3 = ut3 * p;
|
|
let x = x1 * uuu + cx1 * uut3 + cx2 * utt3 + x2 * ttt, y = y1 * uuu + cy1 * uut3 + cy2 * utt3 + y2 * ttt;
|
|
out[o] = x;
|
|
out[o + 1] = y;
|
|
if (tangents) {
|
|
if (p < 1e-3)
|
|
out[o + 2] = Math.atan2(cy1 - y1, cx1 - x1);
|
|
else
|
|
out[o + 2] = Math.atan2(y - (y1 * uu + cy1 * ut * 2 + cy2 * tt), x - (x1 * uu + cx1 * ut * 2 + cx2 * tt));
|
|
}
|
|
}
|
|
};
|
|
var PathConstraint = _PathConstraint;
|
|
PathConstraint.NONE = -1;
|
|
PathConstraint.BEFORE = -2;
|
|
PathConstraint.AFTER = -3;
|
|
PathConstraint.epsilon = 1e-5;
|
|
|
|
// spine-core/src/Slot.ts
|
|
var Slot = class {
|
|
constructor(data, bone) {
|
|
this.darkColor = null;
|
|
this.attachment = null;
|
|
this.attachmentState = 0;
|
|
this.sequenceIndex = -1;
|
|
this.deform = new Array();
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!bone)
|
|
throw new Error("bone cannot be null.");
|
|
this.data = data;
|
|
this.bone = bone;
|
|
this.color = new Color();
|
|
this.darkColor = !data.darkColor ? null : new Color();
|
|
this.setToSetupPose();
|
|
}
|
|
getSkeleton() {
|
|
return this.bone.skeleton;
|
|
}
|
|
getAttachment() {
|
|
return this.attachment;
|
|
}
|
|
setAttachment(attachment) {
|
|
if (this.attachment == attachment)
|
|
return;
|
|
if (!(attachment instanceof VertexAttachment) || !(this.attachment instanceof VertexAttachment) || attachment.timelineAttachment != this.attachment.timelineAttachment) {
|
|
this.deform.length = 0;
|
|
}
|
|
this.attachment = attachment;
|
|
this.sequenceIndex = -1;
|
|
}
|
|
setToSetupPose() {
|
|
this.color.setFromColor(this.data.color);
|
|
if (this.darkColor)
|
|
this.darkColor.setFromColor(this.data.darkColor);
|
|
if (!this.data.attachmentName)
|
|
this.attachment = null;
|
|
else {
|
|
this.attachment = null;
|
|
this.setAttachment(this.bone.skeleton.getAttachment(this.data.index, this.data.attachmentName));
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/TransformConstraint.ts
|
|
var TransformConstraint = class {
|
|
constructor(data, skeleton) {
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
this.mixScaleX = 0;
|
|
this.mixScaleY = 0;
|
|
this.mixShearY = 0;
|
|
this.temp = new Vector2();
|
|
this.active = false;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
this.data = data;
|
|
this.mixRotate = data.mixRotate;
|
|
this.mixX = data.mixX;
|
|
this.mixY = data.mixY;
|
|
this.mixScaleX = data.mixScaleX;
|
|
this.mixScaleY = data.mixScaleY;
|
|
this.mixShearY = data.mixShearY;
|
|
this.bones = new Array();
|
|
for (let i = 0; i < data.bones.length; i++) {
|
|
let bone = skeleton.findBone(data.bones[i].name);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${data.bones[i].name}.`);
|
|
this.bones.push(bone);
|
|
}
|
|
let target = skeleton.findBone(data.target.name);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${data.target.name}.`);
|
|
this.target = target;
|
|
}
|
|
isActive() {
|
|
return this.active;
|
|
}
|
|
update() {
|
|
if (this.mixRotate == 0 && this.mixX == 0 && this.mixY == 0 && this.mixScaleX == 0 && this.mixScaleY == 0 && this.mixShearY == 0)
|
|
return;
|
|
if (this.data.local) {
|
|
if (this.data.relative)
|
|
this.applyRelativeLocal();
|
|
else
|
|
this.applyAbsoluteLocal();
|
|
} else {
|
|
if (this.data.relative)
|
|
this.applyRelativeWorld();
|
|
else
|
|
this.applyAbsoluteWorld();
|
|
}
|
|
}
|
|
applyAbsoluteWorld() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let translate = mixX != 0 || mixY != 0;
|
|
let target = this.target;
|
|
let ta = target.a, tb = target.b, tc = target.c, td = target.d;
|
|
let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;
|
|
let offsetRotation = this.data.offsetRotation * degRadReflect;
|
|
let offsetShearY = this.data.offsetShearY * degRadReflect;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (mixRotate != 0) {
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
let r = Math.atan2(tc, ta) - Math.atan2(c, a) + offsetRotation;
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r *= mixRotate;
|
|
let cos = Math.cos(r), sin = Math.sin(r);
|
|
bone.a = cos * a - sin * c;
|
|
bone.b = cos * b - sin * d;
|
|
bone.c = sin * a + cos * c;
|
|
bone.d = sin * b + cos * d;
|
|
}
|
|
if (translate) {
|
|
let temp = this.temp;
|
|
target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));
|
|
bone.worldX += (temp.x - bone.worldX) * mixX;
|
|
bone.worldY += (temp.y - bone.worldY) * mixY;
|
|
}
|
|
if (mixScaleX != 0) {
|
|
let s = Math.sqrt(bone.a * bone.a + bone.c * bone.c);
|
|
if (s != 0)
|
|
s = (s + (Math.sqrt(ta * ta + tc * tc) - s + this.data.offsetScaleX) * mixScaleX) / s;
|
|
bone.a *= s;
|
|
bone.c *= s;
|
|
}
|
|
if (mixScaleY != 0) {
|
|
let s = Math.sqrt(bone.b * bone.b + bone.d * bone.d);
|
|
if (s != 0)
|
|
s = (s + (Math.sqrt(tb * tb + td * td) - s + this.data.offsetScaleY) * mixScaleY) / s;
|
|
bone.b *= s;
|
|
bone.d *= s;
|
|
}
|
|
if (mixShearY > 0) {
|
|
let b = bone.b, d = bone.d;
|
|
let by = Math.atan2(d, b);
|
|
let r = Math.atan2(td, tb) - Math.atan2(tc, ta) - (by - Math.atan2(bone.c, bone.a));
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r = by + (r + offsetShearY) * mixShearY;
|
|
let s = Math.sqrt(b * b + d * d);
|
|
bone.b = Math.cos(r) * s;
|
|
bone.d = Math.sin(r) * s;
|
|
}
|
|
bone.updateAppliedTransform();
|
|
}
|
|
}
|
|
applyRelativeWorld() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let translate = mixX != 0 || mixY != 0;
|
|
let target = this.target;
|
|
let ta = target.a, tb = target.b, tc = target.c, td = target.d;
|
|
let degRadReflect = ta * td - tb * tc > 0 ? MathUtils.degRad : -MathUtils.degRad;
|
|
let offsetRotation = this.data.offsetRotation * degRadReflect, offsetShearY = this.data.offsetShearY * degRadReflect;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (mixRotate != 0) {
|
|
let a = bone.a, b = bone.b, c = bone.c, d = bone.d;
|
|
let r = Math.atan2(tc, ta) + offsetRotation;
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
r *= mixRotate;
|
|
let cos = Math.cos(r), sin = Math.sin(r);
|
|
bone.a = cos * a - sin * c;
|
|
bone.b = cos * b - sin * d;
|
|
bone.c = sin * a + cos * c;
|
|
bone.d = sin * b + cos * d;
|
|
}
|
|
if (translate) {
|
|
let temp = this.temp;
|
|
target.localToWorld(temp.set(this.data.offsetX, this.data.offsetY));
|
|
bone.worldX += temp.x * mixX;
|
|
bone.worldY += temp.y * mixY;
|
|
}
|
|
if (mixScaleX != 0) {
|
|
let s = (Math.sqrt(ta * ta + tc * tc) - 1 + this.data.offsetScaleX) * mixScaleX + 1;
|
|
bone.a *= s;
|
|
bone.c *= s;
|
|
}
|
|
if (mixScaleY != 0) {
|
|
let s = (Math.sqrt(tb * tb + td * td) - 1 + this.data.offsetScaleY) * mixScaleY + 1;
|
|
bone.b *= s;
|
|
bone.d *= s;
|
|
}
|
|
if (mixShearY > 0) {
|
|
let r = Math.atan2(td, tb) - Math.atan2(tc, ta);
|
|
if (r > MathUtils.PI)
|
|
r -= MathUtils.PI2;
|
|
else if (r < -MathUtils.PI)
|
|
r += MathUtils.PI2;
|
|
let b = bone.b, d = bone.d;
|
|
r = Math.atan2(d, b) + (r - MathUtils.PI / 2 + offsetShearY) * mixShearY;
|
|
let s = Math.sqrt(b * b + d * d);
|
|
bone.b = Math.cos(r) * s;
|
|
bone.d = Math.sin(r) * s;
|
|
}
|
|
bone.updateAppliedTransform();
|
|
}
|
|
}
|
|
applyAbsoluteLocal() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let target = this.target;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
let rotation = bone.arotation;
|
|
if (mixRotate != 0) {
|
|
let r = target.arotation - rotation + this.data.offsetRotation;
|
|
r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360;
|
|
rotation += r * mixRotate;
|
|
}
|
|
let x = bone.ax, y = bone.ay;
|
|
x += (target.ax - x + this.data.offsetX) * mixX;
|
|
y += (target.ay - y + this.data.offsetY) * mixY;
|
|
let scaleX = bone.ascaleX, scaleY = bone.ascaleY;
|
|
if (mixScaleX != 0 && scaleX != 0)
|
|
scaleX = (scaleX + (target.ascaleX - scaleX + this.data.offsetScaleX) * mixScaleX) / scaleX;
|
|
if (mixScaleY != 0 && scaleY != 0)
|
|
scaleY = (scaleY + (target.ascaleY - scaleY + this.data.offsetScaleY) * mixScaleY) / scaleY;
|
|
let shearY = bone.ashearY;
|
|
if (mixShearY != 0) {
|
|
let r = target.ashearY - shearY + this.data.offsetShearY;
|
|
r -= (16384 - (16384.499999999996 - r / 360 | 0)) * 360;
|
|
shearY += r * mixShearY;
|
|
}
|
|
bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
|
}
|
|
}
|
|
applyRelativeLocal() {
|
|
let mixRotate = this.mixRotate, mixX = this.mixX, mixY = this.mixY, mixScaleX = this.mixScaleX, mixScaleY = this.mixScaleY, mixShearY = this.mixShearY;
|
|
let target = this.target;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
let rotation = bone.arotation + (target.arotation + this.data.offsetRotation) * mixRotate;
|
|
let x = bone.ax + (target.ax + this.data.offsetX) * mixX;
|
|
let y = bone.ay + (target.ay + this.data.offsetY) * mixY;
|
|
let scaleX = bone.ascaleX * ((target.ascaleX - 1 + this.data.offsetScaleX) * mixScaleX + 1);
|
|
let scaleY = bone.ascaleY * ((target.ascaleY - 1 + this.data.offsetScaleY) * mixScaleY + 1);
|
|
let shearY = bone.ashearY + (target.ashearY + this.data.offsetShearY) * mixShearY;
|
|
bone.updateWorldTransformWith(x, y, rotation, scaleX, scaleY, bone.ashearX, shearY);
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Skeleton.ts
|
|
var _Skeleton = class {
|
|
constructor(data) {
|
|
this._updateCache = new Array();
|
|
this.skin = null;
|
|
this.scaleX = 1;
|
|
this._scaleY = 1;
|
|
this.x = 0;
|
|
this.y = 0;
|
|
if (!data)
|
|
throw new Error("data cannot be null.");
|
|
this.data = data;
|
|
this.bones = new Array();
|
|
for (let i = 0; i < data.bones.length; i++) {
|
|
let boneData = data.bones[i];
|
|
let bone;
|
|
if (!boneData.parent)
|
|
bone = new Bone(boneData, this, null);
|
|
else {
|
|
let parent = this.bones[boneData.parent.index];
|
|
bone = new Bone(boneData, this, parent);
|
|
parent.children.push(bone);
|
|
}
|
|
this.bones.push(bone);
|
|
}
|
|
this.slots = new Array();
|
|
this.drawOrder = new Array();
|
|
for (let i = 0; i < data.slots.length; i++) {
|
|
let slotData = data.slots[i];
|
|
let bone = this.bones[slotData.boneData.index];
|
|
let slot = new Slot(slotData, bone);
|
|
this.slots.push(slot);
|
|
this.drawOrder.push(slot);
|
|
}
|
|
this.ikConstraints = new Array();
|
|
for (let i = 0; i < data.ikConstraints.length; i++) {
|
|
let ikConstraintData = data.ikConstraints[i];
|
|
this.ikConstraints.push(new IkConstraint(ikConstraintData, this));
|
|
}
|
|
this.transformConstraints = new Array();
|
|
for (let i = 0; i < data.transformConstraints.length; i++) {
|
|
let transformConstraintData = data.transformConstraints[i];
|
|
this.transformConstraints.push(new TransformConstraint(transformConstraintData, this));
|
|
}
|
|
this.pathConstraints = new Array();
|
|
for (let i = 0; i < data.pathConstraints.length; i++) {
|
|
let pathConstraintData = data.pathConstraints[i];
|
|
this.pathConstraints.push(new PathConstraint(pathConstraintData, this));
|
|
}
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.updateCache();
|
|
}
|
|
get scaleY() {
|
|
return _Skeleton.yDown ? -this._scaleY : this._scaleY;
|
|
}
|
|
set scaleY(scaleY) {
|
|
this._scaleY = scaleY;
|
|
}
|
|
updateCache() {
|
|
let updateCache = this._updateCache;
|
|
updateCache.length = 0;
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
bone.sorted = bone.data.skinRequired;
|
|
bone.active = !bone.sorted;
|
|
}
|
|
if (this.skin) {
|
|
let skinBones = this.skin.bones;
|
|
for (let i = 0, n = this.skin.bones.length; i < n; i++) {
|
|
let bone = this.bones[skinBones[i].index];
|
|
do {
|
|
bone.sorted = false;
|
|
bone.active = true;
|
|
bone = bone.parent;
|
|
} while (bone);
|
|
}
|
|
}
|
|
let ikConstraints = this.ikConstraints;
|
|
let transformConstraints = this.transformConstraints;
|
|
let pathConstraints = this.pathConstraints;
|
|
let ikCount = ikConstraints.length, transformCount = transformConstraints.length, pathCount = pathConstraints.length;
|
|
let constraintCount = ikCount + transformCount + pathCount;
|
|
outer:
|
|
for (let i = 0; i < constraintCount; i++) {
|
|
for (let ii = 0; ii < ikCount; ii++) {
|
|
let constraint = ikConstraints[ii];
|
|
if (constraint.data.order == i) {
|
|
this.sortIkConstraint(constraint);
|
|
continue outer;
|
|
}
|
|
}
|
|
for (let ii = 0; ii < transformCount; ii++) {
|
|
let constraint = transformConstraints[ii];
|
|
if (constraint.data.order == i) {
|
|
this.sortTransformConstraint(constraint);
|
|
continue outer;
|
|
}
|
|
}
|
|
for (let ii = 0; ii < pathCount; ii++) {
|
|
let constraint = pathConstraints[ii];
|
|
if (constraint.data.order == i) {
|
|
this.sortPathConstraint(constraint);
|
|
continue outer;
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = bones.length; i < n; i++)
|
|
this.sortBone(bones[i]);
|
|
}
|
|
sortIkConstraint(constraint) {
|
|
constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true));
|
|
if (!constraint.active)
|
|
return;
|
|
let target = constraint.target;
|
|
this.sortBone(target);
|
|
let constrained = constraint.bones;
|
|
let parent = constrained[0];
|
|
this.sortBone(parent);
|
|
if (constrained.length == 1) {
|
|
this._updateCache.push(constraint);
|
|
this.sortReset(parent.children);
|
|
} else {
|
|
let child = constrained[constrained.length - 1];
|
|
this.sortBone(child);
|
|
this._updateCache.push(constraint);
|
|
this.sortReset(parent.children);
|
|
child.sorted = true;
|
|
}
|
|
}
|
|
sortPathConstraint(constraint) {
|
|
constraint.active = constraint.target.bone.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true));
|
|
if (!constraint.active)
|
|
return;
|
|
let slot = constraint.target;
|
|
let slotIndex = slot.data.index;
|
|
let slotBone = slot.bone;
|
|
if (this.skin)
|
|
this.sortPathConstraintAttachment(this.skin, slotIndex, slotBone);
|
|
if (this.data.defaultSkin && this.data.defaultSkin != this.skin)
|
|
this.sortPathConstraintAttachment(this.data.defaultSkin, slotIndex, slotBone);
|
|
for (let i = 0, n = this.data.skins.length; i < n; i++)
|
|
this.sortPathConstraintAttachment(this.data.skins[i], slotIndex, slotBone);
|
|
let attachment = slot.getAttachment();
|
|
if (attachment instanceof PathAttachment)
|
|
this.sortPathConstraintAttachmentWith(attachment, slotBone);
|
|
let constrained = constraint.bones;
|
|
let boneCount = constrained.length;
|
|
for (let i = 0; i < boneCount; i++)
|
|
this.sortBone(constrained[i]);
|
|
this._updateCache.push(constraint);
|
|
for (let i = 0; i < boneCount; i++)
|
|
this.sortReset(constrained[i].children);
|
|
for (let i = 0; i < boneCount; i++)
|
|
constrained[i].sorted = true;
|
|
}
|
|
sortTransformConstraint(constraint) {
|
|
constraint.active = constraint.target.isActive() && (!constraint.data.skinRequired || this.skin && Utils.contains(this.skin.constraints, constraint.data, true));
|
|
if (!constraint.active)
|
|
return;
|
|
this.sortBone(constraint.target);
|
|
let constrained = constraint.bones;
|
|
let boneCount = constrained.length;
|
|
if (constraint.data.local) {
|
|
for (let i = 0; i < boneCount; i++) {
|
|
let child = constrained[i];
|
|
this.sortBone(child.parent);
|
|
this.sortBone(child);
|
|
}
|
|
} else {
|
|
for (let i = 0; i < boneCount; i++) {
|
|
this.sortBone(constrained[i]);
|
|
}
|
|
}
|
|
this._updateCache.push(constraint);
|
|
for (let i = 0; i < boneCount; i++)
|
|
this.sortReset(constrained[i].children);
|
|
for (let i = 0; i < boneCount; i++)
|
|
constrained[i].sorted = true;
|
|
}
|
|
sortPathConstraintAttachment(skin, slotIndex, slotBone) {
|
|
let attachments = skin.attachments[slotIndex];
|
|
if (!attachments)
|
|
return;
|
|
for (let key in attachments) {
|
|
this.sortPathConstraintAttachmentWith(attachments[key], slotBone);
|
|
}
|
|
}
|
|
sortPathConstraintAttachmentWith(attachment, slotBone) {
|
|
if (!(attachment instanceof PathAttachment))
|
|
return;
|
|
let pathBones = attachment.bones;
|
|
if (!pathBones)
|
|
this.sortBone(slotBone);
|
|
else {
|
|
let bones = this.bones;
|
|
for (let i = 0, n = pathBones.length; i < n; ) {
|
|
let nn = pathBones[i++];
|
|
nn += i;
|
|
while (i < nn)
|
|
this.sortBone(bones[pathBones[i++]]);
|
|
}
|
|
}
|
|
}
|
|
sortBone(bone) {
|
|
if (!bone)
|
|
return;
|
|
if (bone.sorted)
|
|
return;
|
|
let parent = bone.parent;
|
|
if (parent)
|
|
this.sortBone(parent);
|
|
bone.sorted = true;
|
|
this._updateCache.push(bone);
|
|
}
|
|
sortReset(bones) {
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (!bone.active)
|
|
continue;
|
|
if (bone.sorted)
|
|
this.sortReset(bone.children);
|
|
bone.sorted = false;
|
|
}
|
|
}
|
|
updateWorldTransform() {
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
bone.ax = bone.x;
|
|
bone.ay = bone.y;
|
|
bone.arotation = bone.rotation;
|
|
bone.ascaleX = bone.scaleX;
|
|
bone.ascaleY = bone.scaleY;
|
|
bone.ashearX = bone.shearX;
|
|
bone.ashearY = bone.shearY;
|
|
}
|
|
let updateCache = this._updateCache;
|
|
for (let i = 0, n = updateCache.length; i < n; i++)
|
|
updateCache[i].update();
|
|
}
|
|
updateWorldTransformWith(parent) {
|
|
let rootBone = this.getRootBone();
|
|
if (!rootBone)
|
|
throw new Error("Root bone must not be null.");
|
|
let pa = parent.a, pb = parent.b, pc = parent.c, pd = parent.d;
|
|
rootBone.worldX = pa * this.x + pb * this.y + parent.worldX;
|
|
rootBone.worldY = pc * this.x + pd * this.y + parent.worldY;
|
|
let rotationY = rootBone.rotation + 90 + rootBone.shearY;
|
|
let la = MathUtils.cosDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
|
|
let lb = MathUtils.cosDeg(rotationY) * rootBone.scaleY;
|
|
let lc = MathUtils.sinDeg(rootBone.rotation + rootBone.shearX) * rootBone.scaleX;
|
|
let ld = MathUtils.sinDeg(rotationY) * rootBone.scaleY;
|
|
rootBone.a = (pa * la + pb * lc) * this.scaleX;
|
|
rootBone.b = (pa * lb + pb * ld) * this.scaleX;
|
|
rootBone.c = (pc * la + pd * lc) * this.scaleY;
|
|
rootBone.d = (pc * lb + pd * ld) * this.scaleY;
|
|
let updateCache = this._updateCache;
|
|
for (let i = 0, n = updateCache.length; i < n; i++) {
|
|
let updatable = updateCache[i];
|
|
if (updatable != rootBone)
|
|
updatable.update();
|
|
}
|
|
}
|
|
setToSetupPose() {
|
|
this.setBonesToSetupPose();
|
|
this.setSlotsToSetupPose();
|
|
}
|
|
setBonesToSetupPose() {
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++)
|
|
bones[i].setToSetupPose();
|
|
let ikConstraints = this.ikConstraints;
|
|
for (let i = 0, n = ikConstraints.length; i < n; i++) {
|
|
let constraint = ikConstraints[i];
|
|
constraint.mix = constraint.data.mix;
|
|
constraint.softness = constraint.data.softness;
|
|
constraint.bendDirection = constraint.data.bendDirection;
|
|
constraint.compress = constraint.data.compress;
|
|
constraint.stretch = constraint.data.stretch;
|
|
}
|
|
let transformConstraints = this.transformConstraints;
|
|
for (let i = 0, n = transformConstraints.length; i < n; i++) {
|
|
let constraint = transformConstraints[i];
|
|
let data = constraint.data;
|
|
constraint.mixRotate = data.mixRotate;
|
|
constraint.mixX = data.mixX;
|
|
constraint.mixY = data.mixY;
|
|
constraint.mixScaleX = data.mixScaleX;
|
|
constraint.mixScaleY = data.mixScaleY;
|
|
constraint.mixShearY = data.mixShearY;
|
|
}
|
|
let pathConstraints = this.pathConstraints;
|
|
for (let i = 0, n = pathConstraints.length; i < n; i++) {
|
|
let constraint = pathConstraints[i];
|
|
let data = constraint.data;
|
|
constraint.position = data.position;
|
|
constraint.spacing = data.spacing;
|
|
constraint.mixRotate = data.mixRotate;
|
|
constraint.mixX = data.mixX;
|
|
constraint.mixY = data.mixY;
|
|
}
|
|
}
|
|
setSlotsToSetupPose() {
|
|
let slots = this.slots;
|
|
Utils.arrayCopy(slots, 0, this.drawOrder, 0, slots.length);
|
|
for (let i = 0, n = slots.length; i < n; i++)
|
|
slots[i].setToSetupPose();
|
|
}
|
|
getRootBone() {
|
|
if (this.bones.length == 0)
|
|
return null;
|
|
return this.bones[0];
|
|
}
|
|
findBone(boneName) {
|
|
if (!boneName)
|
|
throw new Error("boneName cannot be null.");
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (bone.data.name == boneName)
|
|
return bone;
|
|
}
|
|
return null;
|
|
}
|
|
findSlot(slotName) {
|
|
if (!slotName)
|
|
throw new Error("slotName cannot be null.");
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (slot.data.name == slotName)
|
|
return slot;
|
|
}
|
|
return null;
|
|
}
|
|
setSkinByName(skinName) {
|
|
let skin = this.data.findSkin(skinName);
|
|
if (!skin)
|
|
throw new Error("Skin not found: " + skinName);
|
|
this.setSkin(skin);
|
|
}
|
|
setSkin(newSkin) {
|
|
if (newSkin == this.skin)
|
|
return;
|
|
if (newSkin) {
|
|
if (this.skin)
|
|
newSkin.attachAll(this, this.skin);
|
|
else {
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
let name = slot.data.attachmentName;
|
|
if (name) {
|
|
let attachment = newSkin.getAttachment(i, name);
|
|
if (attachment)
|
|
slot.setAttachment(attachment);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
this.skin = newSkin;
|
|
this.updateCache();
|
|
}
|
|
getAttachmentByName(slotName, attachmentName) {
|
|
let slot = this.data.findSlot(slotName);
|
|
if (!slot)
|
|
throw new Error(`Can't find slot with name ${slotName}`);
|
|
return this.getAttachment(slot.index, attachmentName);
|
|
}
|
|
getAttachment(slotIndex, attachmentName) {
|
|
if (!attachmentName)
|
|
throw new Error("attachmentName cannot be null.");
|
|
if (this.skin) {
|
|
let attachment = this.skin.getAttachment(slotIndex, attachmentName);
|
|
if (attachment)
|
|
return attachment;
|
|
}
|
|
if (this.data.defaultSkin)
|
|
return this.data.defaultSkin.getAttachment(slotIndex, attachmentName);
|
|
return null;
|
|
}
|
|
setAttachment(slotName, attachmentName) {
|
|
if (!slotName)
|
|
throw new Error("slotName cannot be null.");
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (slot.data.name == slotName) {
|
|
let attachment = null;
|
|
if (attachmentName) {
|
|
attachment = this.getAttachment(i, attachmentName);
|
|
if (!attachment)
|
|
throw new Error("Attachment not found: " + attachmentName + ", for slot: " + slotName);
|
|
}
|
|
slot.setAttachment(attachment);
|
|
return;
|
|
}
|
|
}
|
|
throw new Error("Slot not found: " + slotName);
|
|
}
|
|
findIkConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let ikConstraints = this.ikConstraints;
|
|
for (let i = 0, n = ikConstraints.length; i < n; i++) {
|
|
let ikConstraint = ikConstraints[i];
|
|
if (ikConstraint.data.name == constraintName)
|
|
return ikConstraint;
|
|
}
|
|
return null;
|
|
}
|
|
findTransformConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let transformConstraints = this.transformConstraints;
|
|
for (let i = 0, n = transformConstraints.length; i < n; i++) {
|
|
let constraint = transformConstraints[i];
|
|
if (constraint.data.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
findPathConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let pathConstraints = this.pathConstraints;
|
|
for (let i = 0, n = pathConstraints.length; i < n; i++) {
|
|
let constraint = pathConstraints[i];
|
|
if (constraint.data.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
getBoundsRect() {
|
|
let offset = new Vector2();
|
|
let size = new Vector2();
|
|
this.getBounds(offset, size);
|
|
return { x: offset.x, y: offset.y, width: size.x, height: size.y };
|
|
}
|
|
getBounds(offset, size, temp = new Array(2)) {
|
|
if (!offset)
|
|
throw new Error("offset cannot be null.");
|
|
if (!size)
|
|
throw new Error("size cannot be null.");
|
|
let drawOrder = this.drawOrder;
|
|
let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
|
|
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
|
let slot = drawOrder[i];
|
|
if (!slot.bone.active)
|
|
continue;
|
|
let verticesLength = 0;
|
|
let vertices = null;
|
|
let attachment = slot.getAttachment();
|
|
if (attachment instanceof RegionAttachment) {
|
|
verticesLength = 8;
|
|
vertices = Utils.setArraySize(temp, verticesLength, 0);
|
|
attachment.computeWorldVertices(slot, vertices, 0, 2);
|
|
} else if (attachment instanceof MeshAttachment) {
|
|
let mesh = attachment;
|
|
verticesLength = mesh.worldVerticesLength;
|
|
vertices = Utils.setArraySize(temp, verticesLength, 0);
|
|
mesh.computeWorldVertices(slot, 0, verticesLength, vertices, 0, 2);
|
|
}
|
|
if (vertices) {
|
|
for (let ii = 0, nn = vertices.length; ii < nn; ii += 2) {
|
|
let x = vertices[ii], y = vertices[ii + 1];
|
|
minX = Math.min(minX, x);
|
|
minY = Math.min(minY, y);
|
|
maxX = Math.max(maxX, x);
|
|
maxY = Math.max(maxY, y);
|
|
}
|
|
}
|
|
}
|
|
offset.set(minX, minY);
|
|
size.set(maxX - minX, maxY - minY);
|
|
}
|
|
};
|
|
var Skeleton = _Skeleton;
|
|
Skeleton.yDown = false;
|
|
|
|
// spine-core/src/SkeletonData.ts
|
|
var SkeletonData = class {
|
|
constructor() {
|
|
this.name = null;
|
|
this.bones = new Array();
|
|
this.slots = new Array();
|
|
this.skins = new Array();
|
|
this.defaultSkin = null;
|
|
this.events = new Array();
|
|
this.animations = new Array();
|
|
this.ikConstraints = new Array();
|
|
this.transformConstraints = new Array();
|
|
this.pathConstraints = new Array();
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.version = null;
|
|
this.hash = null;
|
|
this.fps = 0;
|
|
this.imagesPath = null;
|
|
this.audioPath = null;
|
|
}
|
|
findBone(boneName) {
|
|
if (!boneName)
|
|
throw new Error("boneName cannot be null.");
|
|
let bones = this.bones;
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (bone.name == boneName)
|
|
return bone;
|
|
}
|
|
return null;
|
|
}
|
|
findSlot(slotName) {
|
|
if (!slotName)
|
|
throw new Error("slotName cannot be null.");
|
|
let slots = this.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (slot.name == slotName)
|
|
return slot;
|
|
}
|
|
return null;
|
|
}
|
|
findSkin(skinName) {
|
|
if (!skinName)
|
|
throw new Error("skinName cannot be null.");
|
|
let skins = this.skins;
|
|
for (let i = 0, n = skins.length; i < n; i++) {
|
|
let skin = skins[i];
|
|
if (skin.name == skinName)
|
|
return skin;
|
|
}
|
|
return null;
|
|
}
|
|
findEvent(eventDataName) {
|
|
if (!eventDataName)
|
|
throw new Error("eventDataName cannot be null.");
|
|
let events = this.events;
|
|
for (let i = 0, n = events.length; i < n; i++) {
|
|
let event = events[i];
|
|
if (event.name == eventDataName)
|
|
return event;
|
|
}
|
|
return null;
|
|
}
|
|
findAnimation(animationName) {
|
|
if (!animationName)
|
|
throw new Error("animationName cannot be null.");
|
|
let animations = this.animations;
|
|
for (let i = 0, n = animations.length; i < n; i++) {
|
|
let animation = animations[i];
|
|
if (animation.name == animationName)
|
|
return animation;
|
|
}
|
|
return null;
|
|
}
|
|
findIkConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let ikConstraints = this.ikConstraints;
|
|
for (let i = 0, n = ikConstraints.length; i < n; i++) {
|
|
let constraint = ikConstraints[i];
|
|
if (constraint.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
findTransformConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let transformConstraints = this.transformConstraints;
|
|
for (let i = 0, n = transformConstraints.length; i < n; i++) {
|
|
let constraint = transformConstraints[i];
|
|
if (constraint.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
findPathConstraint(constraintName) {
|
|
if (!constraintName)
|
|
throw new Error("constraintName cannot be null.");
|
|
let pathConstraints = this.pathConstraints;
|
|
for (let i = 0, n = pathConstraints.length; i < n; i++) {
|
|
let constraint = pathConstraints[i];
|
|
if (constraint.name == constraintName)
|
|
return constraint;
|
|
}
|
|
return null;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Skin.ts
|
|
var SkinEntry = class {
|
|
constructor(slotIndex = 0, name, attachment) {
|
|
this.slotIndex = slotIndex;
|
|
this.name = name;
|
|
this.attachment = attachment;
|
|
}
|
|
};
|
|
var Skin = class {
|
|
constructor(name) {
|
|
this.attachments = new Array();
|
|
this.bones = Array();
|
|
this.constraints = new Array();
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
this.name = name;
|
|
}
|
|
setAttachment(slotIndex, name, attachment) {
|
|
if (!attachment)
|
|
throw new Error("attachment cannot be null.");
|
|
let attachments = this.attachments;
|
|
if (slotIndex >= attachments.length)
|
|
attachments.length = slotIndex + 1;
|
|
if (!attachments[slotIndex])
|
|
attachments[slotIndex] = {};
|
|
attachments[slotIndex][name] = attachment;
|
|
}
|
|
addSkin(skin) {
|
|
for (let i = 0; i < skin.bones.length; i++) {
|
|
let bone = skin.bones[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.bones.length; ii++) {
|
|
if (this.bones[ii] == bone) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.bones.push(bone);
|
|
}
|
|
for (let i = 0; i < skin.constraints.length; i++) {
|
|
let constraint = skin.constraints[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.constraints.length; ii++) {
|
|
if (this.constraints[ii] == constraint) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.constraints.push(constraint);
|
|
}
|
|
let attachments = skin.getAttachments();
|
|
for (let i = 0; i < attachments.length; i++) {
|
|
var attachment = attachments[i];
|
|
this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
|
}
|
|
}
|
|
copySkin(skin) {
|
|
for (let i = 0; i < skin.bones.length; i++) {
|
|
let bone = skin.bones[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.bones.length; ii++) {
|
|
if (this.bones[ii] == bone) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.bones.push(bone);
|
|
}
|
|
for (let i = 0; i < skin.constraints.length; i++) {
|
|
let constraint = skin.constraints[i];
|
|
let contained = false;
|
|
for (let ii = 0; ii < this.constraints.length; ii++) {
|
|
if (this.constraints[ii] == constraint) {
|
|
contained = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!contained)
|
|
this.constraints.push(constraint);
|
|
}
|
|
let attachments = skin.getAttachments();
|
|
for (let i = 0; i < attachments.length; i++) {
|
|
var attachment = attachments[i];
|
|
if (!attachment.attachment)
|
|
continue;
|
|
if (attachment.attachment instanceof MeshAttachment) {
|
|
attachment.attachment = attachment.attachment.newLinkedMesh();
|
|
this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
|
} else {
|
|
attachment.attachment = attachment.attachment.copy();
|
|
this.setAttachment(attachment.slotIndex, attachment.name, attachment.attachment);
|
|
}
|
|
}
|
|
}
|
|
getAttachment(slotIndex, name) {
|
|
let dictionary = this.attachments[slotIndex];
|
|
return dictionary ? dictionary[name] : null;
|
|
}
|
|
removeAttachment(slotIndex, name) {
|
|
let dictionary = this.attachments[slotIndex];
|
|
if (dictionary)
|
|
delete dictionary[name];
|
|
}
|
|
getAttachments() {
|
|
let entries = new Array();
|
|
for (var i = 0; i < this.attachments.length; i++) {
|
|
let slotAttachments = this.attachments[i];
|
|
if (slotAttachments) {
|
|
for (let name in slotAttachments) {
|
|
let attachment = slotAttachments[name];
|
|
if (attachment)
|
|
entries.push(new SkinEntry(i, name, attachment));
|
|
}
|
|
}
|
|
}
|
|
return entries;
|
|
}
|
|
getAttachmentsForSlot(slotIndex, attachments) {
|
|
let slotAttachments = this.attachments[slotIndex];
|
|
if (slotAttachments) {
|
|
for (let name in slotAttachments) {
|
|
let attachment = slotAttachments[name];
|
|
if (attachment)
|
|
attachments.push(new SkinEntry(slotIndex, name, attachment));
|
|
}
|
|
}
|
|
}
|
|
clear() {
|
|
this.attachments.length = 0;
|
|
this.bones.length = 0;
|
|
this.constraints.length = 0;
|
|
}
|
|
attachAll(skeleton, oldSkin) {
|
|
let slotIndex = 0;
|
|
for (let i = 0; i < skeleton.slots.length; i++) {
|
|
let slot = skeleton.slots[i];
|
|
let slotAttachment = slot.getAttachment();
|
|
if (slotAttachment && slotIndex < oldSkin.attachments.length) {
|
|
let dictionary = oldSkin.attachments[slotIndex];
|
|
for (let key in dictionary) {
|
|
let skinAttachment = dictionary[key];
|
|
if (slotAttachment == skinAttachment) {
|
|
let attachment = this.getAttachment(slotIndex, key);
|
|
if (attachment)
|
|
slot.setAttachment(attachment);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
slotIndex++;
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SlotData.ts
|
|
var SlotData = class {
|
|
constructor(index, name, boneData) {
|
|
this.index = 0;
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.darkColor = null;
|
|
this.attachmentName = null;
|
|
this.blendMode = BlendMode.Normal;
|
|
if (index < 0)
|
|
throw new Error("index must be >= 0.");
|
|
if (!name)
|
|
throw new Error("name cannot be null.");
|
|
if (!boneData)
|
|
throw new Error("boneData cannot be null.");
|
|
this.index = index;
|
|
this.name = name;
|
|
this.boneData = boneData;
|
|
}
|
|
};
|
|
var BlendMode = /* @__PURE__ */ ((BlendMode3) => {
|
|
BlendMode3[BlendMode3["Normal"] = 0] = "Normal";
|
|
BlendMode3[BlendMode3["Additive"] = 1] = "Additive";
|
|
BlendMode3[BlendMode3["Multiply"] = 2] = "Multiply";
|
|
BlendMode3[BlendMode3["Screen"] = 3] = "Screen";
|
|
return BlendMode3;
|
|
})(BlendMode || {});
|
|
|
|
// spine-core/src/TransformConstraintData.ts
|
|
var TransformConstraintData = class extends ConstraintData {
|
|
constructor(name) {
|
|
super(name, 0, false);
|
|
this.bones = new Array();
|
|
this._target = null;
|
|
this.mixRotate = 0;
|
|
this.mixX = 0;
|
|
this.mixY = 0;
|
|
this.mixScaleX = 0;
|
|
this.mixScaleY = 0;
|
|
this.mixShearY = 0;
|
|
this.offsetRotation = 0;
|
|
this.offsetX = 0;
|
|
this.offsetY = 0;
|
|
this.offsetScaleX = 0;
|
|
this.offsetScaleY = 0;
|
|
this.offsetShearY = 0;
|
|
this.relative = false;
|
|
this.local = false;
|
|
}
|
|
set target(boneData) {
|
|
this._target = boneData;
|
|
}
|
|
get target() {
|
|
if (!this._target)
|
|
throw new Error("BoneData not set.");
|
|
else
|
|
return this._target;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SkeletonBinary.ts
|
|
var SkeletonBinary = class {
|
|
constructor(attachmentLoader) {
|
|
this.scale = 1;
|
|
this.linkedMeshes = new Array();
|
|
this.attachmentLoader = attachmentLoader;
|
|
}
|
|
readSkeletonData(binary) {
|
|
let scale = this.scale;
|
|
let skeletonData = new SkeletonData();
|
|
skeletonData.name = "";
|
|
let input = new BinaryInput(binary);
|
|
let lowHash = input.readInt32();
|
|
let highHash = input.readInt32();
|
|
skeletonData.hash = highHash == 0 && lowHash == 0 ? null : highHash.toString(16) + lowHash.toString(16);
|
|
skeletonData.version = input.readString();
|
|
skeletonData.x = input.readFloat();
|
|
skeletonData.y = input.readFloat();
|
|
skeletonData.width = input.readFloat();
|
|
skeletonData.height = input.readFloat();
|
|
let nonessential = input.readBoolean();
|
|
if (nonessential) {
|
|
skeletonData.fps = input.readFloat();
|
|
skeletonData.imagesPath = input.readString();
|
|
skeletonData.audioPath = input.readString();
|
|
}
|
|
let n = 0;
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let str = input.readString();
|
|
if (!str)
|
|
throw new Error("String in string table must not be null.");
|
|
input.strings.push(str);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("Bone name must not be null.");
|
|
let parent = i == 0 ? null : skeletonData.bones[input.readInt(true)];
|
|
let data = new BoneData(i, name, parent);
|
|
data.rotation = input.readFloat();
|
|
data.x = input.readFloat() * scale;
|
|
data.y = input.readFloat() * scale;
|
|
data.scaleX = input.readFloat();
|
|
data.scaleY = input.readFloat();
|
|
data.shearX = input.readFloat();
|
|
data.shearY = input.readFloat();
|
|
data.length = input.readFloat() * scale;
|
|
data.transformMode = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(data.color, input.readInt32());
|
|
skeletonData.bones.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let slotName = input.readString();
|
|
if (!slotName)
|
|
throw new Error("Slot name must not be null.");
|
|
let boneData = skeletonData.bones[input.readInt(true)];
|
|
let data = new SlotData(i, slotName, boneData);
|
|
Color.rgba8888ToColor(data.color, input.readInt32());
|
|
let darkColor = input.readInt32();
|
|
if (darkColor != -1)
|
|
Color.rgb888ToColor(data.darkColor = new Color(), darkColor);
|
|
data.attachmentName = input.readStringRef();
|
|
data.blendMode = input.readInt(true);
|
|
skeletonData.slots.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0, nn; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("IK constraint data name must not be null.");
|
|
let data = new IkConstraintData(name);
|
|
data.order = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
nn = input.readInt(true);
|
|
for (let ii = 0; ii < nn; ii++)
|
|
data.bones.push(skeletonData.bones[input.readInt(true)]);
|
|
data.target = skeletonData.bones[input.readInt(true)];
|
|
data.mix = input.readFloat();
|
|
data.softness = input.readFloat() * scale;
|
|
data.bendDirection = input.readByte();
|
|
data.compress = input.readBoolean();
|
|
data.stretch = input.readBoolean();
|
|
data.uniform = input.readBoolean();
|
|
skeletonData.ikConstraints.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0, nn; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("Transform constraint data name must not be null.");
|
|
let data = new TransformConstraintData(name);
|
|
data.order = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
nn = input.readInt(true);
|
|
for (let ii = 0; ii < nn; ii++)
|
|
data.bones.push(skeletonData.bones[input.readInt(true)]);
|
|
data.target = skeletonData.bones[input.readInt(true)];
|
|
data.local = input.readBoolean();
|
|
data.relative = input.readBoolean();
|
|
data.offsetRotation = input.readFloat();
|
|
data.offsetX = input.readFloat() * scale;
|
|
data.offsetY = input.readFloat() * scale;
|
|
data.offsetScaleX = input.readFloat();
|
|
data.offsetScaleY = input.readFloat();
|
|
data.offsetShearY = input.readFloat();
|
|
data.mixRotate = input.readFloat();
|
|
data.mixX = input.readFloat();
|
|
data.mixY = input.readFloat();
|
|
data.mixScaleX = input.readFloat();
|
|
data.mixScaleY = input.readFloat();
|
|
data.mixShearY = input.readFloat();
|
|
skeletonData.transformConstraints.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0, nn; i < n; i++) {
|
|
let name = input.readString();
|
|
if (!name)
|
|
throw new Error("Path constraint data name must not be null.");
|
|
let data = new PathConstraintData(name);
|
|
data.order = input.readInt(true);
|
|
data.skinRequired = input.readBoolean();
|
|
nn = input.readInt(true);
|
|
for (let ii = 0; ii < nn; ii++)
|
|
data.bones.push(skeletonData.bones[input.readInt(true)]);
|
|
data.target = skeletonData.slots[input.readInt(true)];
|
|
data.positionMode = input.readInt(true);
|
|
data.spacingMode = input.readInt(true);
|
|
data.rotateMode = input.readInt(true);
|
|
data.offsetRotation = input.readFloat();
|
|
data.position = input.readFloat();
|
|
if (data.positionMode == 0 /* Fixed */)
|
|
data.position *= scale;
|
|
data.spacing = input.readFloat();
|
|
if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */)
|
|
data.spacing *= scale;
|
|
data.mixRotate = input.readFloat();
|
|
data.mixX = input.readFloat();
|
|
data.mixY = input.readFloat();
|
|
skeletonData.pathConstraints.push(data);
|
|
}
|
|
let defaultSkin = this.readSkin(input, skeletonData, true, nonessential);
|
|
if (defaultSkin) {
|
|
skeletonData.defaultSkin = defaultSkin;
|
|
skeletonData.skins.push(defaultSkin);
|
|
}
|
|
{
|
|
let i = skeletonData.skins.length;
|
|
Utils.setArraySize(skeletonData.skins, n = i + input.readInt(true));
|
|
for (; i < n; i++) {
|
|
let skin = this.readSkin(input, skeletonData, false, nonessential);
|
|
if (!skin)
|
|
throw new Error("readSkin() should not have returned null.");
|
|
skeletonData.skins[i] = skin;
|
|
}
|
|
}
|
|
n = this.linkedMeshes.length;
|
|
for (let i = 0; i < n; i++) {
|
|
let linkedMesh = this.linkedMeshes[i];
|
|
let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
|
if (!skin)
|
|
throw new Error("Not skin found for linked mesh.");
|
|
if (!linkedMesh.parent)
|
|
throw new Error("Linked mesh parent must not be null");
|
|
let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
|
if (!parent)
|
|
throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);
|
|
linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh;
|
|
linkedMesh.mesh.setParentMesh(parent);
|
|
if (linkedMesh.mesh.region != null)
|
|
linkedMesh.mesh.updateRegion();
|
|
}
|
|
this.linkedMeshes.length = 0;
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let eventName = input.readStringRef();
|
|
if (!eventName)
|
|
throw new Error();
|
|
let data = new EventData(eventName);
|
|
data.intValue = input.readInt(false);
|
|
data.floatValue = input.readFloat();
|
|
data.stringValue = input.readString();
|
|
data.audioPath = input.readString();
|
|
if (data.audioPath) {
|
|
data.volume = input.readFloat();
|
|
data.balance = input.readFloat();
|
|
}
|
|
skeletonData.events.push(data);
|
|
}
|
|
n = input.readInt(true);
|
|
for (let i = 0; i < n; i++) {
|
|
let animationName = input.readString();
|
|
if (!animationName)
|
|
throw new Error("Animatio name must not be null.");
|
|
skeletonData.animations.push(this.readAnimation(input, animationName, skeletonData));
|
|
}
|
|
return skeletonData;
|
|
}
|
|
readSkin(input, skeletonData, defaultSkin, nonessential) {
|
|
let skin = null;
|
|
let slotCount = 0;
|
|
if (defaultSkin) {
|
|
slotCount = input.readInt(true);
|
|
if (slotCount == 0)
|
|
return null;
|
|
skin = new Skin("default");
|
|
} else {
|
|
let skinName = input.readStringRef();
|
|
if (!skinName)
|
|
throw new Error("Skin name must not be null.");
|
|
skin = new Skin(skinName);
|
|
skin.bones.length = input.readInt(true);
|
|
for (let i = 0, n = skin.bones.length; i < n; i++)
|
|
skin.bones[i] = skeletonData.bones[input.readInt(true)];
|
|
for (let i = 0, n = input.readInt(true); i < n; i++)
|
|
skin.constraints.push(skeletonData.ikConstraints[input.readInt(true)]);
|
|
for (let i = 0, n = input.readInt(true); i < n; i++)
|
|
skin.constraints.push(skeletonData.transformConstraints[input.readInt(true)]);
|
|
for (let i = 0, n = input.readInt(true); i < n; i++)
|
|
skin.constraints.push(skeletonData.pathConstraints[input.readInt(true)]);
|
|
slotCount = input.readInt(true);
|
|
}
|
|
for (let i = 0; i < slotCount; i++) {
|
|
let slotIndex = input.readInt(true);
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let name = input.readStringRef();
|
|
if (!name)
|
|
throw new Error("Attachment name must not be null");
|
|
let attachment = this.readAttachment(input, skeletonData, skin, slotIndex, name, nonessential);
|
|
if (attachment)
|
|
skin.setAttachment(slotIndex, name, attachment);
|
|
}
|
|
}
|
|
return skin;
|
|
}
|
|
readAttachment(input, skeletonData, skin, slotIndex, attachmentName, nonessential) {
|
|
let scale = this.scale;
|
|
let name = input.readStringRef();
|
|
if (!name)
|
|
name = attachmentName;
|
|
switch (input.readByte()) {
|
|
case AttachmentType.Region: {
|
|
let path = input.readStringRef();
|
|
let rotation = input.readFloat();
|
|
let x = input.readFloat();
|
|
let y = input.readFloat();
|
|
let scaleX = input.readFloat();
|
|
let scaleY = input.readFloat();
|
|
let width = input.readFloat();
|
|
let height = input.readFloat();
|
|
let color = input.readInt32();
|
|
let sequence = this.readSequence(input);
|
|
if (!path)
|
|
path = name;
|
|
let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);
|
|
if (!region)
|
|
return null;
|
|
region.path = path;
|
|
region.x = x * scale;
|
|
region.y = y * scale;
|
|
region.scaleX = scaleX;
|
|
region.scaleY = scaleY;
|
|
region.rotation = rotation;
|
|
region.width = width * scale;
|
|
region.height = height * scale;
|
|
Color.rgba8888ToColor(region.color, color);
|
|
region.sequence = sequence;
|
|
if (sequence == null)
|
|
region.updateRegion();
|
|
return region;
|
|
}
|
|
case AttachmentType.BoundingBox: {
|
|
let vertexCount = input.readInt(true);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);
|
|
if (!box)
|
|
return null;
|
|
box.worldVerticesLength = vertexCount << 1;
|
|
box.vertices = vertices.vertices;
|
|
box.bones = vertices.bones;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(box.color, color);
|
|
return box;
|
|
}
|
|
case AttachmentType.Mesh: {
|
|
let path = input.readStringRef();
|
|
let color = input.readInt32();
|
|
let vertexCount = input.readInt(true);
|
|
let uvs = this.readFloatArray(input, vertexCount << 1, 1);
|
|
let triangles = this.readShortArray(input);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let hullLength = input.readInt(true);
|
|
let sequence = this.readSequence(input);
|
|
let edges = [];
|
|
let width = 0, height = 0;
|
|
if (nonessential) {
|
|
edges = this.readShortArray(input);
|
|
width = input.readFloat();
|
|
height = input.readFloat();
|
|
}
|
|
if (!path)
|
|
path = name;
|
|
let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
|
if (!mesh)
|
|
return null;
|
|
mesh.path = path;
|
|
Color.rgba8888ToColor(mesh.color, color);
|
|
mesh.bones = vertices.bones;
|
|
mesh.vertices = vertices.vertices;
|
|
mesh.worldVerticesLength = vertexCount << 1;
|
|
mesh.triangles = triangles;
|
|
mesh.regionUVs = uvs;
|
|
if (sequence == null)
|
|
mesh.updateRegion();
|
|
mesh.hullLength = hullLength << 1;
|
|
mesh.sequence = sequence;
|
|
if (nonessential) {
|
|
mesh.edges = edges;
|
|
mesh.width = width * scale;
|
|
mesh.height = height * scale;
|
|
}
|
|
return mesh;
|
|
}
|
|
case AttachmentType.LinkedMesh: {
|
|
let path = input.readStringRef();
|
|
let color = input.readInt32();
|
|
let skinName = input.readStringRef();
|
|
let parent = input.readStringRef();
|
|
let inheritTimelines = input.readBoolean();
|
|
let sequence = this.readSequence(input);
|
|
let width = 0, height = 0;
|
|
if (nonessential) {
|
|
width = input.readFloat();
|
|
height = input.readFloat();
|
|
}
|
|
if (!path)
|
|
path = name;
|
|
let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
|
if (!mesh)
|
|
return null;
|
|
mesh.path = path;
|
|
Color.rgba8888ToColor(mesh.color, color);
|
|
mesh.sequence = sequence;
|
|
if (nonessential) {
|
|
mesh.width = width * scale;
|
|
mesh.height = height * scale;
|
|
}
|
|
this.linkedMeshes.push(new LinkedMesh(mesh, skinName, slotIndex, parent, inheritTimelines));
|
|
return mesh;
|
|
}
|
|
case AttachmentType.Path: {
|
|
let closed2 = input.readBoolean();
|
|
let constantSpeed = input.readBoolean();
|
|
let vertexCount = input.readInt(true);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let lengths = Utils.newArray(vertexCount / 3, 0);
|
|
for (let i = 0, n = lengths.length; i < n; i++)
|
|
lengths[i] = input.readFloat() * scale;
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let path = this.attachmentLoader.newPathAttachment(skin, name);
|
|
if (!path)
|
|
return null;
|
|
path.closed = closed2;
|
|
path.constantSpeed = constantSpeed;
|
|
path.worldVerticesLength = vertexCount << 1;
|
|
path.vertices = vertices.vertices;
|
|
path.bones = vertices.bones;
|
|
path.lengths = lengths;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(path.color, color);
|
|
return path;
|
|
}
|
|
case AttachmentType.Point: {
|
|
let rotation = input.readFloat();
|
|
let x = input.readFloat();
|
|
let y = input.readFloat();
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let point = this.attachmentLoader.newPointAttachment(skin, name);
|
|
if (!point)
|
|
return null;
|
|
point.x = x * scale;
|
|
point.y = y * scale;
|
|
point.rotation = rotation;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(point.color, color);
|
|
return point;
|
|
}
|
|
case AttachmentType.Clipping: {
|
|
let endSlotIndex = input.readInt(true);
|
|
let vertexCount = input.readInt(true);
|
|
let vertices = this.readVertices(input, vertexCount);
|
|
let color = nonessential ? input.readInt32() : 0;
|
|
let clip = this.attachmentLoader.newClippingAttachment(skin, name);
|
|
if (!clip)
|
|
return null;
|
|
clip.endSlot = skeletonData.slots[endSlotIndex];
|
|
clip.worldVerticesLength = vertexCount << 1;
|
|
clip.vertices = vertices.vertices;
|
|
clip.bones = vertices.bones;
|
|
if (nonessential)
|
|
Color.rgba8888ToColor(clip.color, color);
|
|
return clip;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
readSequence(input) {
|
|
if (!input.readBoolean())
|
|
return null;
|
|
let sequence = new Sequence(input.readInt(true));
|
|
sequence.start = input.readInt(true);
|
|
sequence.digits = input.readInt(true);
|
|
sequence.setupIndex = input.readInt(true);
|
|
return sequence;
|
|
}
|
|
readVertices(input, vertexCount) {
|
|
let scale = this.scale;
|
|
let verticesLength = vertexCount << 1;
|
|
let vertices = new Vertices();
|
|
if (!input.readBoolean()) {
|
|
vertices.vertices = this.readFloatArray(input, verticesLength, scale);
|
|
return vertices;
|
|
}
|
|
let weights = new Array();
|
|
let bonesArray = new Array();
|
|
for (let i = 0; i < vertexCount; i++) {
|
|
let boneCount = input.readInt(true);
|
|
bonesArray.push(boneCount);
|
|
for (let ii = 0; ii < boneCount; ii++) {
|
|
bonesArray.push(input.readInt(true));
|
|
weights.push(input.readFloat() * scale);
|
|
weights.push(input.readFloat() * scale);
|
|
weights.push(input.readFloat());
|
|
}
|
|
}
|
|
vertices.vertices = Utils.toFloatArray(weights);
|
|
vertices.bones = bonesArray;
|
|
return vertices;
|
|
}
|
|
readFloatArray(input, n, scale) {
|
|
let array = new Array(n);
|
|
if (scale == 1) {
|
|
for (let i = 0; i < n; i++)
|
|
array[i] = input.readFloat();
|
|
} else {
|
|
for (let i = 0; i < n; i++)
|
|
array[i] = input.readFloat() * scale;
|
|
}
|
|
return array;
|
|
}
|
|
readShortArray(input) {
|
|
let n = input.readInt(true);
|
|
let array = new Array(n);
|
|
for (let i = 0; i < n; i++)
|
|
array[i] = input.readShort();
|
|
return array;
|
|
}
|
|
readAnimation(input, name, skeletonData) {
|
|
input.readInt(true);
|
|
let timelines = new Array();
|
|
let scale = this.scale;
|
|
let tempColor1 = new Color();
|
|
let tempColor2 = new Color();
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let slotIndex = input.readInt(true);
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let timelineType = input.readByte();
|
|
let frameCount = input.readInt(true);
|
|
let frameLast = frameCount - 1;
|
|
switch (timelineType) {
|
|
case SLOT_ATTACHMENT: {
|
|
let timeline = new AttachmentTimeline(frameCount, slotIndex);
|
|
for (let frame = 0; frame < frameCount; frame++)
|
|
timeline.setFrame(frame, input.readFloat(), input.readStringRef());
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGBA: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGBATimeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
let a = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b, a);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
let a2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, a, a2, 1);
|
|
}
|
|
time = time2;
|
|
r = r2;
|
|
g = g2;
|
|
b = b2;
|
|
a = a2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGB: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGBTimeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, r2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, g2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, b2, 1);
|
|
}
|
|
time = time2;
|
|
r = r2;
|
|
g = g2;
|
|
b = b2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGBA2: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGBA2Timeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
let a = input.readUnsignedByte() / 255;
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b, a, r2, g2, b2);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let nr = input.readUnsignedByte() / 255;
|
|
let ng = input.readUnsignedByte() / 255;
|
|
let nb = input.readUnsignedByte() / 255;
|
|
let na = input.readUnsignedByte() / 255;
|
|
let nr2 = input.readUnsignedByte() / 255;
|
|
let ng2 = input.readUnsignedByte() / 255;
|
|
let nb2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, a, na, 1);
|
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, r2, nr2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, g2, ng2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 6, time, time2, b2, nb2, 1);
|
|
}
|
|
time = time2;
|
|
r = nr;
|
|
g = ng;
|
|
b = nb;
|
|
a = na;
|
|
r2 = nr2;
|
|
g2 = ng2;
|
|
b2 = nb2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_RGB2: {
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new RGB2Timeline(frameCount, bezierCount, slotIndex);
|
|
let time = input.readFloat();
|
|
let r = input.readUnsignedByte() / 255;
|
|
let g = input.readUnsignedByte() / 255;
|
|
let b = input.readUnsignedByte() / 255;
|
|
let r2 = input.readUnsignedByte() / 255;
|
|
let g2 = input.readUnsignedByte() / 255;
|
|
let b2 = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, r, g, b, r2, g2, b2);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let nr = input.readUnsignedByte() / 255;
|
|
let ng = input.readUnsignedByte() / 255;
|
|
let nb = input.readUnsignedByte() / 255;
|
|
let nr2 = input.readUnsignedByte() / 255;
|
|
let ng2 = input.readUnsignedByte() / 255;
|
|
let nb2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, r, nr, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, g, ng, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, b, nb, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, r2, nr2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, g2, ng2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, b2, nb2, 1);
|
|
}
|
|
time = time2;
|
|
r = nr;
|
|
g = ng;
|
|
b = nb;
|
|
r2 = nr2;
|
|
g2 = ng2;
|
|
b2 = nb2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case SLOT_ALPHA: {
|
|
let timeline = new AlphaTimeline(frameCount, input.readInt(true), slotIndex);
|
|
let time = input.readFloat(), a = input.readUnsignedByte() / 255;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, a);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
let a2 = input.readUnsignedByte() / 255;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, a, a2, 1);
|
|
}
|
|
time = time2;
|
|
a = a2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let boneIndex = input.readInt(true);
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let type = input.readByte(), frameCount = input.readInt(true), bezierCount = input.readInt(true);
|
|
switch (type) {
|
|
case BONE_ROTATE:
|
|
timelines.push(readTimeline1(input, new RotateTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_TRANSLATE:
|
|
timelines.push(readTimeline2(input, new TranslateTimeline(frameCount, bezierCount, boneIndex), scale));
|
|
break;
|
|
case BONE_TRANSLATEX:
|
|
timelines.push(readTimeline1(input, new TranslateXTimeline(frameCount, bezierCount, boneIndex), scale));
|
|
break;
|
|
case BONE_TRANSLATEY:
|
|
timelines.push(readTimeline1(input, new TranslateYTimeline(frameCount, bezierCount, boneIndex), scale));
|
|
break;
|
|
case BONE_SCALE:
|
|
timelines.push(readTimeline2(input, new ScaleTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SCALEX:
|
|
timelines.push(readTimeline1(input, new ScaleXTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SCALEY:
|
|
timelines.push(readTimeline1(input, new ScaleYTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SHEAR:
|
|
timelines.push(readTimeline2(input, new ShearTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SHEARX:
|
|
timelines.push(readTimeline1(input, new ShearXTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
break;
|
|
case BONE_SHEARY:
|
|
timelines.push(readTimeline1(input, new ShearYTimeline(frameCount, bezierCount, boneIndex), 1));
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;
|
|
let timeline = new IkConstraintTimeline(frameCount, input.readInt(true), index);
|
|
let time = input.readFloat(), mix = input.readFloat(), softness = input.readFloat() * scale;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mix, softness, input.readByte(), input.readBoolean(), input.readBoolean());
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), mix2 = input.readFloat(), softness2 = input.readFloat() * scale;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mix, mix2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, softness, softness2, scale);
|
|
}
|
|
time = time2;
|
|
mix = mix2;
|
|
softness = softness2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let index = input.readInt(true), frameCount = input.readInt(true), frameLast = frameCount - 1;
|
|
let timeline = new TransformConstraintTimeline(frameCount, input.readInt(true), index);
|
|
let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat(), mixScaleX = input.readFloat(), mixScaleY = input.readFloat(), mixShearY = input.readFloat();
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat(), mixScaleX2 = input.readFloat(), mixScaleY2 = input.readFloat(), mixShearY2 = input.readFloat();
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 5, time, time2, mixShearY, mixShearY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
mixScaleX = mixScaleX2;
|
|
mixScaleY = mixScaleY2;
|
|
mixShearY = mixShearY2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let index = input.readInt(true);
|
|
let data = skeletonData.pathConstraints[index];
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
switch (input.readByte()) {
|
|
case PATH_POSITION:
|
|
timelines.push(readTimeline1(
|
|
input,
|
|
new PathConstraintPositionTimeline(input.readInt(true), input.readInt(true), index),
|
|
data.positionMode == 0 /* Fixed */ ? scale : 1
|
|
));
|
|
break;
|
|
case PATH_SPACING:
|
|
timelines.push(readTimeline1(
|
|
input,
|
|
new PathConstraintSpacingTimeline(input.readInt(true), input.readInt(true), index),
|
|
data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */ ? scale : 1
|
|
));
|
|
break;
|
|
case PATH_MIX:
|
|
let timeline = new PathConstraintMixTimeline(input.readInt(true), input.readInt(true), index);
|
|
let time = input.readFloat(), mixRotate = input.readFloat(), mixX = input.readFloat(), mixY = input.readFloat();
|
|
for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), mixRotate2 = input.readFloat(), mixX2 = input.readFloat(), mixY2 = input.readFloat();
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, mixX, mixX2, 1);
|
|
setBezier(input, timeline, bezier++, frame, 2, time, time2, mixY, mixY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
for (let i = 0, n = input.readInt(true); i < n; i++) {
|
|
let skin = skeletonData.skins[input.readInt(true)];
|
|
for (let ii = 0, nn = input.readInt(true); ii < nn; ii++) {
|
|
let slotIndex = input.readInt(true);
|
|
for (let iii = 0, nnn = input.readInt(true); iii < nnn; iii++) {
|
|
let attachmentName = input.readStringRef();
|
|
if (!attachmentName)
|
|
throw new Error("attachmentName must not be null.");
|
|
let attachment = skin.getAttachment(slotIndex, attachmentName);
|
|
let timelineType = input.readByte();
|
|
let frameCount = input.readInt(true);
|
|
let frameLast = frameCount - 1;
|
|
switch (timelineType) {
|
|
case ATTACHMENT_DEFORM: {
|
|
let vertexAttachment = attachment;
|
|
let weighted = vertexAttachment.bones;
|
|
let vertices = vertexAttachment.vertices;
|
|
let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;
|
|
let bezierCount = input.readInt(true);
|
|
let timeline = new DeformTimeline(frameCount, bezierCount, slotIndex, vertexAttachment);
|
|
let time = input.readFloat();
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
let deform;
|
|
let end = input.readInt(true);
|
|
if (end == 0)
|
|
deform = weighted ? Utils.newFloatArray(deformLength) : vertices;
|
|
else {
|
|
deform = Utils.newFloatArray(deformLength);
|
|
let start = input.readInt(true);
|
|
end += start;
|
|
if (scale == 1) {
|
|
for (let v = start; v < end; v++)
|
|
deform[v] = input.readFloat();
|
|
} else {
|
|
for (let v = start; v < end; v++)
|
|
deform[v] = input.readFloat() * scale;
|
|
}
|
|
if (!weighted) {
|
|
for (let v = 0, vn = deform.length; v < vn; v++)
|
|
deform[v] += vertices[v];
|
|
}
|
|
}
|
|
timeline.setFrame(frame, time, deform);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat();
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, 0, 1, 1);
|
|
}
|
|
time = time2;
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
case ATTACHMENT_SEQUENCE: {
|
|
let timeline = new SequenceTimeline(frameCount, slotIndex, attachment);
|
|
for (let frame = 0; frame < frameCount; frame++) {
|
|
let time = input.readFloat();
|
|
let modeAndIndex = input.readInt32();
|
|
timeline.setFrame(
|
|
frame,
|
|
time,
|
|
SequenceModeValues[modeAndIndex & 15],
|
|
modeAndIndex >> 4,
|
|
input.readFloat()
|
|
);
|
|
}
|
|
timelines.push(timeline);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
let drawOrderCount = input.readInt(true);
|
|
if (drawOrderCount > 0) {
|
|
let timeline = new DrawOrderTimeline(drawOrderCount);
|
|
let slotCount = skeletonData.slots.length;
|
|
for (let i = 0; i < drawOrderCount; i++) {
|
|
let time = input.readFloat();
|
|
let offsetCount = input.readInt(true);
|
|
let drawOrder = Utils.newArray(slotCount, 0);
|
|
for (let ii = slotCount - 1; ii >= 0; ii--)
|
|
drawOrder[ii] = -1;
|
|
let unchanged = Utils.newArray(slotCount - offsetCount, 0);
|
|
let originalIndex = 0, unchangedIndex = 0;
|
|
for (let ii = 0; ii < offsetCount; ii++) {
|
|
let slotIndex = input.readInt(true);
|
|
while (originalIndex != slotIndex)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
drawOrder[originalIndex + input.readInt(true)] = originalIndex++;
|
|
}
|
|
while (originalIndex < slotCount)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
for (let ii = slotCount - 1; ii >= 0; ii--)
|
|
if (drawOrder[ii] == -1)
|
|
drawOrder[ii] = unchanged[--unchangedIndex];
|
|
timeline.setFrame(i, time, drawOrder);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
let eventCount = input.readInt(true);
|
|
if (eventCount > 0) {
|
|
let timeline = new EventTimeline(eventCount);
|
|
for (let i = 0; i < eventCount; i++) {
|
|
let time = input.readFloat();
|
|
let eventData = skeletonData.events[input.readInt(true)];
|
|
let event = new Event(time, eventData);
|
|
event.intValue = input.readInt(false);
|
|
event.floatValue = input.readFloat();
|
|
event.stringValue = input.readBoolean() ? input.readString() : eventData.stringValue;
|
|
if (event.data.audioPath) {
|
|
event.volume = input.readFloat();
|
|
event.balance = input.readFloat();
|
|
}
|
|
timeline.setFrame(i, event);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
let duration = 0;
|
|
for (let i = 0, n = timelines.length; i < n; i++)
|
|
duration = Math.max(duration, timelines[i].getDuration());
|
|
return new Animation(name, timelines, duration);
|
|
}
|
|
};
|
|
var BinaryInput = class {
|
|
constructor(data, strings = new Array(), index = 0, buffer = new DataView(data.buffer)) {
|
|
this.strings = strings;
|
|
this.index = index;
|
|
this.buffer = buffer;
|
|
}
|
|
readByte() {
|
|
return this.buffer.getInt8(this.index++);
|
|
}
|
|
readUnsignedByte() {
|
|
return this.buffer.getUint8(this.index++);
|
|
}
|
|
readShort() {
|
|
let value = this.buffer.getInt16(this.index);
|
|
this.index += 2;
|
|
return value;
|
|
}
|
|
readInt32() {
|
|
let value = this.buffer.getInt32(this.index);
|
|
this.index += 4;
|
|
return value;
|
|
}
|
|
readInt(optimizePositive) {
|
|
let b = this.readByte();
|
|
let result = b & 127;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 7;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 14;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 21;
|
|
if ((b & 128) != 0) {
|
|
b = this.readByte();
|
|
result |= (b & 127) << 28;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return optimizePositive ? result : result >>> 1 ^ -(result & 1);
|
|
}
|
|
readStringRef() {
|
|
let index = this.readInt(true);
|
|
return index == 0 ? null : this.strings[index - 1];
|
|
}
|
|
readString() {
|
|
let byteCount = this.readInt(true);
|
|
switch (byteCount) {
|
|
case 0:
|
|
return null;
|
|
case 1:
|
|
return "";
|
|
}
|
|
byteCount--;
|
|
let chars = "";
|
|
let charCount = 0;
|
|
for (let i = 0; i < byteCount; ) {
|
|
let b = this.readUnsignedByte();
|
|
switch (b >> 4) {
|
|
case 12:
|
|
case 13:
|
|
chars += String.fromCharCode((b & 31) << 6 | this.readByte() & 63);
|
|
i += 2;
|
|
break;
|
|
case 14:
|
|
chars += String.fromCharCode((b & 15) << 12 | (this.readByte() & 63) << 6 | this.readByte() & 63);
|
|
i += 3;
|
|
break;
|
|
default:
|
|
chars += String.fromCharCode(b);
|
|
i++;
|
|
}
|
|
}
|
|
return chars;
|
|
}
|
|
readFloat() {
|
|
let value = this.buffer.getFloat32(this.index);
|
|
this.index += 4;
|
|
return value;
|
|
}
|
|
readBoolean() {
|
|
return this.readByte() != 0;
|
|
}
|
|
};
|
|
var LinkedMesh = class {
|
|
constructor(mesh, skin, slotIndex, parent, inheritDeform) {
|
|
this.mesh = mesh;
|
|
this.skin = skin;
|
|
this.slotIndex = slotIndex;
|
|
this.parent = parent;
|
|
this.inheritTimeline = inheritDeform;
|
|
}
|
|
};
|
|
var Vertices = class {
|
|
constructor(bones = null, vertices = null) {
|
|
this.bones = bones;
|
|
this.vertices = vertices;
|
|
}
|
|
};
|
|
var AttachmentType = /* @__PURE__ */ ((AttachmentType2) => {
|
|
AttachmentType2[AttachmentType2["Region"] = 0] = "Region";
|
|
AttachmentType2[AttachmentType2["BoundingBox"] = 1] = "BoundingBox";
|
|
AttachmentType2[AttachmentType2["Mesh"] = 2] = "Mesh";
|
|
AttachmentType2[AttachmentType2["LinkedMesh"] = 3] = "LinkedMesh";
|
|
AttachmentType2[AttachmentType2["Path"] = 4] = "Path";
|
|
AttachmentType2[AttachmentType2["Point"] = 5] = "Point";
|
|
AttachmentType2[AttachmentType2["Clipping"] = 6] = "Clipping";
|
|
return AttachmentType2;
|
|
})(AttachmentType || {});
|
|
function readTimeline1(input, timeline, scale) {
|
|
let time = input.readFloat(), value = input.readFloat() * scale;
|
|
for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {
|
|
timeline.setFrame(frame, time, value);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), value2 = input.readFloat() * scale;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, value, value2, scale);
|
|
}
|
|
time = time2;
|
|
value = value2;
|
|
}
|
|
return timeline;
|
|
}
|
|
function readTimeline2(input, timeline, scale) {
|
|
let time = input.readFloat(), value1 = input.readFloat() * scale, value2 = input.readFloat() * scale;
|
|
for (let frame = 0, bezier = 0, frameLast = timeline.getFrameCount() - 1; ; frame++) {
|
|
timeline.setFrame(frame, time, value1, value2);
|
|
if (frame == frameLast)
|
|
break;
|
|
let time2 = input.readFloat(), nvalue1 = input.readFloat() * scale, nvalue2 = input.readFloat() * scale;
|
|
switch (input.readByte()) {
|
|
case CURVE_STEPPED:
|
|
timeline.setStepped(frame);
|
|
break;
|
|
case CURVE_BEZIER:
|
|
setBezier(input, timeline, bezier++, frame, 0, time, time2, value1, nvalue1, scale);
|
|
setBezier(input, timeline, bezier++, frame, 1, time, time2, value2, nvalue2, scale);
|
|
}
|
|
time = time2;
|
|
value1 = nvalue1;
|
|
value2 = nvalue2;
|
|
}
|
|
return timeline;
|
|
}
|
|
function setBezier(input, timeline, bezier, frame, value, time1, time2, value1, value2, scale) {
|
|
timeline.setBezier(bezier, frame, value, time1, value1, input.readFloat(), input.readFloat() * scale, input.readFloat(), input.readFloat() * scale, time2, value2);
|
|
}
|
|
var BONE_ROTATE = 0;
|
|
var BONE_TRANSLATE = 1;
|
|
var BONE_TRANSLATEX = 2;
|
|
var BONE_TRANSLATEY = 3;
|
|
var BONE_SCALE = 4;
|
|
var BONE_SCALEX = 5;
|
|
var BONE_SCALEY = 6;
|
|
var BONE_SHEAR = 7;
|
|
var BONE_SHEARX = 8;
|
|
var BONE_SHEARY = 9;
|
|
var SLOT_ATTACHMENT = 0;
|
|
var SLOT_RGBA = 1;
|
|
var SLOT_RGB = 2;
|
|
var SLOT_RGBA2 = 3;
|
|
var SLOT_RGB2 = 4;
|
|
var SLOT_ALPHA = 5;
|
|
var ATTACHMENT_DEFORM = 0;
|
|
var ATTACHMENT_SEQUENCE = 1;
|
|
var PATH_POSITION = 0;
|
|
var PATH_SPACING = 1;
|
|
var PATH_MIX = 2;
|
|
var CURVE_STEPPED = 1;
|
|
var CURVE_BEZIER = 2;
|
|
|
|
// spine-core/src/SkeletonBounds.ts
|
|
var SkeletonBounds = class {
|
|
constructor() {
|
|
this.minX = 0;
|
|
this.minY = 0;
|
|
this.maxX = 0;
|
|
this.maxY = 0;
|
|
this.boundingBoxes = new Array();
|
|
this.polygons = new Array();
|
|
this.polygonPool = new Pool(() => {
|
|
return Utils.newFloatArray(16);
|
|
});
|
|
}
|
|
update(skeleton, updateAabb) {
|
|
if (!skeleton)
|
|
throw new Error("skeleton cannot be null.");
|
|
let boundingBoxes = this.boundingBoxes;
|
|
let polygons = this.polygons;
|
|
let polygonPool = this.polygonPool;
|
|
let slots = skeleton.slots;
|
|
let slotCount = slots.length;
|
|
boundingBoxes.length = 0;
|
|
polygonPool.freeAll(polygons);
|
|
polygons.length = 0;
|
|
for (let i = 0; i < slotCount; i++) {
|
|
let slot = slots[i];
|
|
if (!slot.bone.active)
|
|
continue;
|
|
let attachment = slot.getAttachment();
|
|
if (attachment instanceof BoundingBoxAttachment) {
|
|
let boundingBox = attachment;
|
|
boundingBoxes.push(boundingBox);
|
|
let polygon = polygonPool.obtain();
|
|
if (polygon.length != boundingBox.worldVerticesLength) {
|
|
polygon = Utils.newFloatArray(boundingBox.worldVerticesLength);
|
|
}
|
|
polygons.push(polygon);
|
|
boundingBox.computeWorldVertices(slot, 0, boundingBox.worldVerticesLength, polygon, 0, 2);
|
|
}
|
|
}
|
|
if (updateAabb) {
|
|
this.aabbCompute();
|
|
} else {
|
|
this.minX = Number.POSITIVE_INFINITY;
|
|
this.minY = Number.POSITIVE_INFINITY;
|
|
this.maxX = Number.NEGATIVE_INFINITY;
|
|
this.maxY = Number.NEGATIVE_INFINITY;
|
|
}
|
|
}
|
|
aabbCompute() {
|
|
let minX = Number.POSITIVE_INFINITY, minY = Number.POSITIVE_INFINITY, maxX = Number.NEGATIVE_INFINITY, maxY = Number.NEGATIVE_INFINITY;
|
|
let polygons = this.polygons;
|
|
for (let i = 0, n = polygons.length; i < n; i++) {
|
|
let polygon = polygons[i];
|
|
let vertices = polygon;
|
|
for (let ii = 0, nn = polygon.length; ii < nn; ii += 2) {
|
|
let x = vertices[ii];
|
|
let y = vertices[ii + 1];
|
|
minX = Math.min(minX, x);
|
|
minY = Math.min(minY, y);
|
|
maxX = Math.max(maxX, x);
|
|
maxY = Math.max(maxY, y);
|
|
}
|
|
}
|
|
this.minX = minX;
|
|
this.minY = minY;
|
|
this.maxX = maxX;
|
|
this.maxY = maxY;
|
|
}
|
|
aabbContainsPoint(x, y) {
|
|
return x >= this.minX && x <= this.maxX && y >= this.minY && y <= this.maxY;
|
|
}
|
|
aabbIntersectsSegment(x1, y1, x2, y2) {
|
|
let minX = this.minX;
|
|
let minY = this.minY;
|
|
let maxX = this.maxX;
|
|
let maxY = this.maxY;
|
|
if (x1 <= minX && x2 <= minX || y1 <= minY && y2 <= minY || x1 >= maxX && x2 >= maxX || y1 >= maxY && y2 >= maxY)
|
|
return false;
|
|
let m = (y2 - y1) / (x2 - x1);
|
|
let y = m * (minX - x1) + y1;
|
|
if (y > minY && y < maxY)
|
|
return true;
|
|
y = m * (maxX - x1) + y1;
|
|
if (y > minY && y < maxY)
|
|
return true;
|
|
let x = (minY - y1) / m + x1;
|
|
if (x > minX && x < maxX)
|
|
return true;
|
|
x = (maxY - y1) / m + x1;
|
|
if (x > minX && x < maxX)
|
|
return true;
|
|
return false;
|
|
}
|
|
aabbIntersectsSkeleton(bounds) {
|
|
return this.minX < bounds.maxX && this.maxX > bounds.minX && this.minY < bounds.maxY && this.maxY > bounds.minY;
|
|
}
|
|
containsPoint(x, y) {
|
|
let polygons = this.polygons;
|
|
for (let i = 0, n = polygons.length; i < n; i++)
|
|
if (this.containsPointPolygon(polygons[i], x, y))
|
|
return this.boundingBoxes[i];
|
|
return null;
|
|
}
|
|
containsPointPolygon(polygon, x, y) {
|
|
let vertices = polygon;
|
|
let nn = polygon.length;
|
|
let prevIndex = nn - 2;
|
|
let inside = false;
|
|
for (let ii = 0; ii < nn; ii += 2) {
|
|
let vertexY = vertices[ii + 1];
|
|
let prevY = vertices[prevIndex + 1];
|
|
if (vertexY < y && prevY >= y || prevY < y && vertexY >= y) {
|
|
let vertexX = vertices[ii];
|
|
if (vertexX + (y - vertexY) / (prevY - vertexY) * (vertices[prevIndex] - vertexX) < x)
|
|
inside = !inside;
|
|
}
|
|
prevIndex = ii;
|
|
}
|
|
return inside;
|
|
}
|
|
intersectsSegment(x1, y1, x2, y2) {
|
|
let polygons = this.polygons;
|
|
for (let i = 0, n = polygons.length; i < n; i++)
|
|
if (this.intersectsSegmentPolygon(polygons[i], x1, y1, x2, y2))
|
|
return this.boundingBoxes[i];
|
|
return null;
|
|
}
|
|
intersectsSegmentPolygon(polygon, x1, y1, x2, y2) {
|
|
let vertices = polygon;
|
|
let nn = polygon.length;
|
|
let width12 = x1 - x2, height12 = y1 - y2;
|
|
let det1 = x1 * y2 - y1 * x2;
|
|
let x3 = vertices[nn - 2], y3 = vertices[nn - 1];
|
|
for (let ii = 0; ii < nn; ii += 2) {
|
|
let x4 = vertices[ii], y4 = vertices[ii + 1];
|
|
let det2 = x3 * y4 - y3 * x4;
|
|
let width34 = x3 - x4, height34 = y3 - y4;
|
|
let det3 = width12 * height34 - height12 * width34;
|
|
let x = (det1 * width34 - width12 * det2) / det3;
|
|
if ((x >= x3 && x <= x4 || x >= x4 && x <= x3) && (x >= x1 && x <= x2 || x >= x2 && x <= x1)) {
|
|
let y = (det1 * height34 - height12 * det2) / det3;
|
|
if ((y >= y3 && y <= y4 || y >= y4 && y <= y3) && (y >= y1 && y <= y2 || y >= y2 && y <= y1))
|
|
return true;
|
|
}
|
|
x3 = x4;
|
|
y3 = y4;
|
|
}
|
|
return false;
|
|
}
|
|
getPolygon(boundingBox) {
|
|
if (!boundingBox)
|
|
throw new Error("boundingBox cannot be null.");
|
|
let index = this.boundingBoxes.indexOf(boundingBox);
|
|
return index == -1 ? null : this.polygons[index];
|
|
}
|
|
getWidth() {
|
|
return this.maxX - this.minX;
|
|
}
|
|
getHeight() {
|
|
return this.maxY - this.minY;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/Triangulator.ts
|
|
var Triangulator = class {
|
|
constructor() {
|
|
this.convexPolygons = new Array();
|
|
this.convexPolygonsIndices = new Array();
|
|
this.indicesArray = new Array();
|
|
this.isConcaveArray = new Array();
|
|
this.triangles = new Array();
|
|
this.polygonPool = new Pool(() => {
|
|
return new Array();
|
|
});
|
|
this.polygonIndicesPool = new Pool(() => {
|
|
return new Array();
|
|
});
|
|
}
|
|
triangulate(verticesArray) {
|
|
let vertices = verticesArray;
|
|
let vertexCount = verticesArray.length >> 1;
|
|
let indices = this.indicesArray;
|
|
indices.length = 0;
|
|
for (let i = 0; i < vertexCount; i++)
|
|
indices[i] = i;
|
|
let isConcave = this.isConcaveArray;
|
|
isConcave.length = 0;
|
|
for (let i = 0, n = vertexCount; i < n; ++i)
|
|
isConcave[i] = Triangulator.isConcave(i, vertexCount, vertices, indices);
|
|
let triangles = this.triangles;
|
|
triangles.length = 0;
|
|
while (vertexCount > 3) {
|
|
let previous = vertexCount - 1, i = 0, next = 1;
|
|
while (true) {
|
|
outer:
|
|
if (!isConcave[i]) {
|
|
let p1 = indices[previous] << 1, p2 = indices[i] << 1, p3 = indices[next] << 1;
|
|
let p1x = vertices[p1], p1y = vertices[p1 + 1];
|
|
let p2x = vertices[p2], p2y = vertices[p2 + 1];
|
|
let p3x = vertices[p3], p3y = vertices[p3 + 1];
|
|
for (let ii = (next + 1) % vertexCount; ii != previous; ii = (ii + 1) % vertexCount) {
|
|
if (!isConcave[ii])
|
|
continue;
|
|
let v = indices[ii] << 1;
|
|
let vx = vertices[v], vy = vertices[v + 1];
|
|
if (Triangulator.positiveArea(p3x, p3y, p1x, p1y, vx, vy)) {
|
|
if (Triangulator.positiveArea(p1x, p1y, p2x, p2y, vx, vy)) {
|
|
if (Triangulator.positiveArea(p2x, p2y, p3x, p3y, vx, vy))
|
|
break outer;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
if (next == 0) {
|
|
do {
|
|
if (!isConcave[i])
|
|
break;
|
|
i--;
|
|
} while (i > 0);
|
|
break;
|
|
}
|
|
previous = i;
|
|
i = next;
|
|
next = (next + 1) % vertexCount;
|
|
}
|
|
triangles.push(indices[(vertexCount + i - 1) % vertexCount]);
|
|
triangles.push(indices[i]);
|
|
triangles.push(indices[(i + 1) % vertexCount]);
|
|
indices.splice(i, 1);
|
|
isConcave.splice(i, 1);
|
|
vertexCount--;
|
|
let previousIndex = (vertexCount + i - 1) % vertexCount;
|
|
let nextIndex = i == vertexCount ? 0 : i;
|
|
isConcave[previousIndex] = Triangulator.isConcave(previousIndex, vertexCount, vertices, indices);
|
|
isConcave[nextIndex] = Triangulator.isConcave(nextIndex, vertexCount, vertices, indices);
|
|
}
|
|
if (vertexCount == 3) {
|
|
triangles.push(indices[2]);
|
|
triangles.push(indices[0]);
|
|
triangles.push(indices[1]);
|
|
}
|
|
return triangles;
|
|
}
|
|
decompose(verticesArray, triangles) {
|
|
let vertices = verticesArray;
|
|
let convexPolygons = this.convexPolygons;
|
|
this.polygonPool.freeAll(convexPolygons);
|
|
convexPolygons.length = 0;
|
|
let convexPolygonsIndices = this.convexPolygonsIndices;
|
|
this.polygonIndicesPool.freeAll(convexPolygonsIndices);
|
|
convexPolygonsIndices.length = 0;
|
|
let polygonIndices = this.polygonIndicesPool.obtain();
|
|
polygonIndices.length = 0;
|
|
let polygon = this.polygonPool.obtain();
|
|
polygon.length = 0;
|
|
let fanBaseIndex = -1, lastWinding = 0;
|
|
for (let i = 0, n = triangles.length; i < n; i += 3) {
|
|
let t1 = triangles[i] << 1, t2 = triangles[i + 1] << 1, t3 = triangles[i + 2] << 1;
|
|
let x1 = vertices[t1], y1 = vertices[t1 + 1];
|
|
let x2 = vertices[t2], y2 = vertices[t2 + 1];
|
|
let x3 = vertices[t3], y3 = vertices[t3 + 1];
|
|
let merged = false;
|
|
if (fanBaseIndex == t1) {
|
|
let o = polygon.length - 4;
|
|
let winding1 = Triangulator.winding(polygon[o], polygon[o + 1], polygon[o + 2], polygon[o + 3], x3, y3);
|
|
let winding2 = Triangulator.winding(x3, y3, polygon[0], polygon[1], polygon[2], polygon[3]);
|
|
if (winding1 == lastWinding && winding2 == lastWinding) {
|
|
polygon.push(x3);
|
|
polygon.push(y3);
|
|
polygonIndices.push(t3);
|
|
merged = true;
|
|
}
|
|
}
|
|
if (!merged) {
|
|
if (polygon.length > 0) {
|
|
convexPolygons.push(polygon);
|
|
convexPolygonsIndices.push(polygonIndices);
|
|
} else {
|
|
this.polygonPool.free(polygon);
|
|
this.polygonIndicesPool.free(polygonIndices);
|
|
}
|
|
polygon = this.polygonPool.obtain();
|
|
polygon.length = 0;
|
|
polygon.push(x1);
|
|
polygon.push(y1);
|
|
polygon.push(x2);
|
|
polygon.push(y2);
|
|
polygon.push(x3);
|
|
polygon.push(y3);
|
|
polygonIndices = this.polygonIndicesPool.obtain();
|
|
polygonIndices.length = 0;
|
|
polygonIndices.push(t1);
|
|
polygonIndices.push(t2);
|
|
polygonIndices.push(t3);
|
|
lastWinding = Triangulator.winding(x1, y1, x2, y2, x3, y3);
|
|
fanBaseIndex = t1;
|
|
}
|
|
}
|
|
if (polygon.length > 0) {
|
|
convexPolygons.push(polygon);
|
|
convexPolygonsIndices.push(polygonIndices);
|
|
}
|
|
for (let i = 0, n = convexPolygons.length; i < n; i++) {
|
|
polygonIndices = convexPolygonsIndices[i];
|
|
if (polygonIndices.length == 0)
|
|
continue;
|
|
let firstIndex = polygonIndices[0];
|
|
let lastIndex = polygonIndices[polygonIndices.length - 1];
|
|
polygon = convexPolygons[i];
|
|
let o = polygon.length - 4;
|
|
let prevPrevX = polygon[o], prevPrevY = polygon[o + 1];
|
|
let prevX = polygon[o + 2], prevY = polygon[o + 3];
|
|
let firstX = polygon[0], firstY = polygon[1];
|
|
let secondX = polygon[2], secondY = polygon[3];
|
|
let winding = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, firstX, firstY);
|
|
for (let ii = 0; ii < n; ii++) {
|
|
if (ii == i)
|
|
continue;
|
|
let otherIndices = convexPolygonsIndices[ii];
|
|
if (otherIndices.length != 3)
|
|
continue;
|
|
let otherFirstIndex = otherIndices[0];
|
|
let otherSecondIndex = otherIndices[1];
|
|
let otherLastIndex = otherIndices[2];
|
|
let otherPoly = convexPolygons[ii];
|
|
let x3 = otherPoly[otherPoly.length - 2], y3 = otherPoly[otherPoly.length - 1];
|
|
if (otherFirstIndex != firstIndex || otherSecondIndex != lastIndex)
|
|
continue;
|
|
let winding1 = Triangulator.winding(prevPrevX, prevPrevY, prevX, prevY, x3, y3);
|
|
let winding2 = Triangulator.winding(x3, y3, firstX, firstY, secondX, secondY);
|
|
if (winding1 == winding && winding2 == winding) {
|
|
otherPoly.length = 0;
|
|
otherIndices.length = 0;
|
|
polygon.push(x3);
|
|
polygon.push(y3);
|
|
polygonIndices.push(otherLastIndex);
|
|
prevPrevX = prevX;
|
|
prevPrevY = prevY;
|
|
prevX = x3;
|
|
prevY = y3;
|
|
ii = 0;
|
|
}
|
|
}
|
|
}
|
|
for (let i = convexPolygons.length - 1; i >= 0; i--) {
|
|
polygon = convexPolygons[i];
|
|
if (polygon.length == 0) {
|
|
convexPolygons.splice(i, 1);
|
|
this.polygonPool.free(polygon);
|
|
polygonIndices = convexPolygonsIndices[i];
|
|
convexPolygonsIndices.splice(i, 1);
|
|
this.polygonIndicesPool.free(polygonIndices);
|
|
}
|
|
}
|
|
return convexPolygons;
|
|
}
|
|
static isConcave(index, vertexCount, vertices, indices) {
|
|
let previous = indices[(vertexCount + index - 1) % vertexCount] << 1;
|
|
let current = indices[index] << 1;
|
|
let next = indices[(index + 1) % vertexCount] << 1;
|
|
return !this.positiveArea(
|
|
vertices[previous],
|
|
vertices[previous + 1],
|
|
vertices[current],
|
|
vertices[current + 1],
|
|
vertices[next],
|
|
vertices[next + 1]
|
|
);
|
|
}
|
|
static positiveArea(p1x, p1y, p2x, p2y, p3x, p3y) {
|
|
return p1x * (p3y - p2y) + p2x * (p1y - p3y) + p3x * (p2y - p1y) >= 0;
|
|
}
|
|
static winding(p1x, p1y, p2x, p2y, p3x, p3y) {
|
|
let px = p2x - p1x, py = p2y - p1y;
|
|
return p3x * py - p3y * px + px * p1y - p1x * py >= 0 ? 1 : -1;
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SkeletonClipping.ts
|
|
var SkeletonClipping = class {
|
|
constructor() {
|
|
this.triangulator = new Triangulator();
|
|
this.clippingPolygon = new Array();
|
|
this.clipOutput = new Array();
|
|
this.clippedVertices = new Array();
|
|
this.clippedTriangles = new Array();
|
|
this.scratch = new Array();
|
|
this.clipAttachment = null;
|
|
this.clippingPolygons = null;
|
|
}
|
|
clipStart(slot, clip) {
|
|
if (this.clipAttachment)
|
|
return 0;
|
|
this.clipAttachment = clip;
|
|
let n = clip.worldVerticesLength;
|
|
let vertices = Utils.setArraySize(this.clippingPolygon, n);
|
|
clip.computeWorldVertices(slot, 0, n, vertices, 0, 2);
|
|
let clippingPolygon = this.clippingPolygon;
|
|
SkeletonClipping.makeClockwise(clippingPolygon);
|
|
let clippingPolygons = this.clippingPolygons = this.triangulator.decompose(clippingPolygon, this.triangulator.triangulate(clippingPolygon));
|
|
for (let i = 0, n2 = clippingPolygons.length; i < n2; i++) {
|
|
let polygon = clippingPolygons[i];
|
|
SkeletonClipping.makeClockwise(polygon);
|
|
polygon.push(polygon[0]);
|
|
polygon.push(polygon[1]);
|
|
}
|
|
return clippingPolygons.length;
|
|
}
|
|
clipEndWithSlot(slot) {
|
|
if (this.clipAttachment && this.clipAttachment.endSlot == slot.data)
|
|
this.clipEnd();
|
|
}
|
|
clipEnd() {
|
|
if (!this.clipAttachment)
|
|
return;
|
|
this.clipAttachment = null;
|
|
this.clippingPolygons = null;
|
|
this.clippedVertices.length = 0;
|
|
this.clippedTriangles.length = 0;
|
|
this.clippingPolygon.length = 0;
|
|
}
|
|
isClipping() {
|
|
return this.clipAttachment != null;
|
|
}
|
|
clipTriangles(vertices, verticesLength, triangles, trianglesLength, uvs, light, dark, twoColor) {
|
|
let clipOutput = this.clipOutput, clippedVertices = this.clippedVertices;
|
|
let clippedTriangles = this.clippedTriangles;
|
|
let polygons = this.clippingPolygons;
|
|
let polygonsCount = polygons.length;
|
|
let vertexSize = twoColor ? 12 : 8;
|
|
let index = 0;
|
|
clippedVertices.length = 0;
|
|
clippedTriangles.length = 0;
|
|
outer:
|
|
for (let i = 0; i < trianglesLength; i += 3) {
|
|
let vertexOffset = triangles[i] << 1;
|
|
let x1 = vertices[vertexOffset], y1 = vertices[vertexOffset + 1];
|
|
let u1 = uvs[vertexOffset], v1 = uvs[vertexOffset + 1];
|
|
vertexOffset = triangles[i + 1] << 1;
|
|
let x2 = vertices[vertexOffset], y2 = vertices[vertexOffset + 1];
|
|
let u2 = uvs[vertexOffset], v2 = uvs[vertexOffset + 1];
|
|
vertexOffset = triangles[i + 2] << 1;
|
|
let x3 = vertices[vertexOffset], y3 = vertices[vertexOffset + 1];
|
|
let u3 = uvs[vertexOffset], v3 = uvs[vertexOffset + 1];
|
|
for (let p = 0; p < polygonsCount; p++) {
|
|
let s = clippedVertices.length;
|
|
if (this.clip(x1, y1, x2, y2, x3, y3, polygons[p], clipOutput)) {
|
|
let clipOutputLength = clipOutput.length;
|
|
if (clipOutputLength == 0)
|
|
continue;
|
|
let d0 = y2 - y3, d1 = x3 - x2, d2 = x1 - x3, d4 = y3 - y1;
|
|
let d = 1 / (d0 * d2 + d1 * (y1 - y3));
|
|
let clipOutputCount = clipOutputLength >> 1;
|
|
let clipOutputItems = this.clipOutput;
|
|
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + clipOutputCount * vertexSize);
|
|
for (let ii = 0; ii < clipOutputLength; ii += 2) {
|
|
let x = clipOutputItems[ii], y = clipOutputItems[ii + 1];
|
|
clippedVerticesItems[s] = x;
|
|
clippedVerticesItems[s + 1] = y;
|
|
clippedVerticesItems[s + 2] = light.r;
|
|
clippedVerticesItems[s + 3] = light.g;
|
|
clippedVerticesItems[s + 4] = light.b;
|
|
clippedVerticesItems[s + 5] = light.a;
|
|
let c0 = x - x3, c1 = y - y3;
|
|
let a = (d0 * c0 + d1 * c1) * d;
|
|
let b = (d4 * c0 + d2 * c1) * d;
|
|
let c = 1 - a - b;
|
|
clippedVerticesItems[s + 6] = u1 * a + u2 * b + u3 * c;
|
|
clippedVerticesItems[s + 7] = v1 * a + v2 * b + v3 * c;
|
|
if (twoColor) {
|
|
clippedVerticesItems[s + 8] = dark.r;
|
|
clippedVerticesItems[s + 9] = dark.g;
|
|
clippedVerticesItems[s + 10] = dark.b;
|
|
clippedVerticesItems[s + 11] = dark.a;
|
|
}
|
|
s += vertexSize;
|
|
}
|
|
s = clippedTriangles.length;
|
|
let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3 * (clipOutputCount - 2));
|
|
clipOutputCount--;
|
|
for (let ii = 1; ii < clipOutputCount; ii++) {
|
|
clippedTrianglesItems[s] = index;
|
|
clippedTrianglesItems[s + 1] = index + ii;
|
|
clippedTrianglesItems[s + 2] = index + ii + 1;
|
|
s += 3;
|
|
}
|
|
index += clipOutputCount + 1;
|
|
} else {
|
|
let clippedVerticesItems = Utils.setArraySize(clippedVertices, s + 3 * vertexSize);
|
|
clippedVerticesItems[s] = x1;
|
|
clippedVerticesItems[s + 1] = y1;
|
|
clippedVerticesItems[s + 2] = light.r;
|
|
clippedVerticesItems[s + 3] = light.g;
|
|
clippedVerticesItems[s + 4] = light.b;
|
|
clippedVerticesItems[s + 5] = light.a;
|
|
if (!twoColor) {
|
|
clippedVerticesItems[s + 6] = u1;
|
|
clippedVerticesItems[s + 7] = v1;
|
|
clippedVerticesItems[s + 8] = x2;
|
|
clippedVerticesItems[s + 9] = y2;
|
|
clippedVerticesItems[s + 10] = light.r;
|
|
clippedVerticesItems[s + 11] = light.g;
|
|
clippedVerticesItems[s + 12] = light.b;
|
|
clippedVerticesItems[s + 13] = light.a;
|
|
clippedVerticesItems[s + 14] = u2;
|
|
clippedVerticesItems[s + 15] = v2;
|
|
clippedVerticesItems[s + 16] = x3;
|
|
clippedVerticesItems[s + 17] = y3;
|
|
clippedVerticesItems[s + 18] = light.r;
|
|
clippedVerticesItems[s + 19] = light.g;
|
|
clippedVerticesItems[s + 20] = light.b;
|
|
clippedVerticesItems[s + 21] = light.a;
|
|
clippedVerticesItems[s + 22] = u3;
|
|
clippedVerticesItems[s + 23] = v3;
|
|
} else {
|
|
clippedVerticesItems[s + 6] = u1;
|
|
clippedVerticesItems[s + 7] = v1;
|
|
clippedVerticesItems[s + 8] = dark.r;
|
|
clippedVerticesItems[s + 9] = dark.g;
|
|
clippedVerticesItems[s + 10] = dark.b;
|
|
clippedVerticesItems[s + 11] = dark.a;
|
|
clippedVerticesItems[s + 12] = x2;
|
|
clippedVerticesItems[s + 13] = y2;
|
|
clippedVerticesItems[s + 14] = light.r;
|
|
clippedVerticesItems[s + 15] = light.g;
|
|
clippedVerticesItems[s + 16] = light.b;
|
|
clippedVerticesItems[s + 17] = light.a;
|
|
clippedVerticesItems[s + 18] = u2;
|
|
clippedVerticesItems[s + 19] = v2;
|
|
clippedVerticesItems[s + 20] = dark.r;
|
|
clippedVerticesItems[s + 21] = dark.g;
|
|
clippedVerticesItems[s + 22] = dark.b;
|
|
clippedVerticesItems[s + 23] = dark.a;
|
|
clippedVerticesItems[s + 24] = x3;
|
|
clippedVerticesItems[s + 25] = y3;
|
|
clippedVerticesItems[s + 26] = light.r;
|
|
clippedVerticesItems[s + 27] = light.g;
|
|
clippedVerticesItems[s + 28] = light.b;
|
|
clippedVerticesItems[s + 29] = light.a;
|
|
clippedVerticesItems[s + 30] = u3;
|
|
clippedVerticesItems[s + 31] = v3;
|
|
clippedVerticesItems[s + 32] = dark.r;
|
|
clippedVerticesItems[s + 33] = dark.g;
|
|
clippedVerticesItems[s + 34] = dark.b;
|
|
clippedVerticesItems[s + 35] = dark.a;
|
|
}
|
|
s = clippedTriangles.length;
|
|
let clippedTrianglesItems = Utils.setArraySize(clippedTriangles, s + 3);
|
|
clippedTrianglesItems[s] = index;
|
|
clippedTrianglesItems[s + 1] = index + 1;
|
|
clippedTrianglesItems[s + 2] = index + 2;
|
|
index += 3;
|
|
continue outer;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
clip(x1, y1, x2, y2, x3, y3, clippingArea, output) {
|
|
let originalOutput = output;
|
|
let clipped = false;
|
|
let input;
|
|
if (clippingArea.length % 4 >= 2) {
|
|
input = output;
|
|
output = this.scratch;
|
|
} else
|
|
input = this.scratch;
|
|
input.length = 0;
|
|
input.push(x1);
|
|
input.push(y1);
|
|
input.push(x2);
|
|
input.push(y2);
|
|
input.push(x3);
|
|
input.push(y3);
|
|
input.push(x1);
|
|
input.push(y1);
|
|
output.length = 0;
|
|
let clippingVertices = clippingArea;
|
|
let clippingVerticesLast = clippingArea.length - 4;
|
|
for (let i = 0; ; i += 2) {
|
|
let edgeX = clippingVertices[i], edgeY = clippingVertices[i + 1];
|
|
let edgeX2 = clippingVertices[i + 2], edgeY2 = clippingVertices[i + 3];
|
|
let deltaX = edgeX - edgeX2, deltaY = edgeY - edgeY2;
|
|
let inputVertices = input;
|
|
let inputVerticesLength = input.length - 2, outputStart = output.length;
|
|
for (let ii = 0; ii < inputVerticesLength; ii += 2) {
|
|
let inputX = inputVertices[ii], inputY = inputVertices[ii + 1];
|
|
let inputX2 = inputVertices[ii + 2], inputY2 = inputVertices[ii + 3];
|
|
let side2 = deltaX * (inputY2 - edgeY2) - deltaY * (inputX2 - edgeX2) > 0;
|
|
if (deltaX * (inputY - edgeY2) - deltaY * (inputX - edgeX2) > 0) {
|
|
if (side2) {
|
|
output.push(inputX2);
|
|
output.push(inputY2);
|
|
continue;
|
|
}
|
|
let c0 = inputY2 - inputY, c2 = inputX2 - inputX;
|
|
let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
|
|
if (Math.abs(s) > 1e-6) {
|
|
let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
|
|
output.push(edgeX + (edgeX2 - edgeX) * ua);
|
|
output.push(edgeY + (edgeY2 - edgeY) * ua);
|
|
} else {
|
|
output.push(edgeX);
|
|
output.push(edgeY);
|
|
}
|
|
} else if (side2) {
|
|
let c0 = inputY2 - inputY, c2 = inputX2 - inputX;
|
|
let s = c0 * (edgeX2 - edgeX) - c2 * (edgeY2 - edgeY);
|
|
if (Math.abs(s) > 1e-6) {
|
|
let ua = (c2 * (edgeY - inputY) - c0 * (edgeX - inputX)) / s;
|
|
output.push(edgeX + (edgeX2 - edgeX) * ua);
|
|
output.push(edgeY + (edgeY2 - edgeY) * ua);
|
|
} else {
|
|
output.push(edgeX);
|
|
output.push(edgeY);
|
|
}
|
|
output.push(inputX2);
|
|
output.push(inputY2);
|
|
}
|
|
clipped = true;
|
|
}
|
|
if (outputStart == output.length) {
|
|
originalOutput.length = 0;
|
|
return true;
|
|
}
|
|
output.push(output[0]);
|
|
output.push(output[1]);
|
|
if (i == clippingVerticesLast)
|
|
break;
|
|
let temp = output;
|
|
output = input;
|
|
output.length = 0;
|
|
input = temp;
|
|
}
|
|
if (originalOutput != output) {
|
|
originalOutput.length = 0;
|
|
for (let i = 0, n = output.length - 2; i < n; i++)
|
|
originalOutput[i] = output[i];
|
|
} else
|
|
originalOutput.length = originalOutput.length - 2;
|
|
return clipped;
|
|
}
|
|
static makeClockwise(polygon) {
|
|
let vertices = polygon;
|
|
let verticeslength = polygon.length;
|
|
let area = vertices[verticeslength - 2] * vertices[1] - vertices[0] * vertices[verticeslength - 1], p1x = 0, p1y = 0, p2x = 0, p2y = 0;
|
|
for (let i = 0, n = verticeslength - 3; i < n; i += 2) {
|
|
p1x = vertices[i];
|
|
p1y = vertices[i + 1];
|
|
p2x = vertices[i + 2];
|
|
p2y = vertices[i + 3];
|
|
area += p1x * p2y - p2x * p1y;
|
|
}
|
|
if (area < 0)
|
|
return;
|
|
for (let i = 0, lastX = verticeslength - 2, n = verticeslength >> 1; i < n; i += 2) {
|
|
let x = vertices[i], y = vertices[i + 1];
|
|
let other = lastX - i;
|
|
vertices[i] = vertices[other];
|
|
vertices[i + 1] = vertices[other + 1];
|
|
vertices[other] = x;
|
|
vertices[other + 1] = y;
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-core/src/SkeletonJson.ts
|
|
var SkeletonJson = class {
|
|
constructor(attachmentLoader) {
|
|
this.scale = 1;
|
|
this.linkedMeshes = new Array();
|
|
this.attachmentLoader = attachmentLoader;
|
|
}
|
|
readSkeletonData(json) {
|
|
let scale = this.scale;
|
|
let skeletonData = new SkeletonData();
|
|
let root = typeof json === "string" ? JSON.parse(json) : json;
|
|
let skeletonMap = root.skeleton;
|
|
if (skeletonMap) {
|
|
skeletonData.hash = skeletonMap.hash;
|
|
skeletonData.version = skeletonMap.spine;
|
|
skeletonData.x = skeletonMap.x;
|
|
skeletonData.y = skeletonMap.y;
|
|
skeletonData.width = skeletonMap.width;
|
|
skeletonData.height = skeletonMap.height;
|
|
skeletonData.fps = skeletonMap.fps;
|
|
skeletonData.imagesPath = skeletonMap.images;
|
|
}
|
|
if (root.bones) {
|
|
for (let i = 0; i < root.bones.length; i++) {
|
|
let boneMap = root.bones[i];
|
|
let parent = null;
|
|
let parentName = getValue(boneMap, "parent", null);
|
|
if (parentName)
|
|
parent = skeletonData.findBone(parentName);
|
|
let data = new BoneData(skeletonData.bones.length, boneMap.name, parent);
|
|
data.length = getValue(boneMap, "length", 0) * scale;
|
|
data.x = getValue(boneMap, "x", 0) * scale;
|
|
data.y = getValue(boneMap, "y", 0) * scale;
|
|
data.rotation = getValue(boneMap, "rotation", 0);
|
|
data.scaleX = getValue(boneMap, "scaleX", 1);
|
|
data.scaleY = getValue(boneMap, "scaleY", 1);
|
|
data.shearX = getValue(boneMap, "shearX", 0);
|
|
data.shearY = getValue(boneMap, "shearY", 0);
|
|
data.transformMode = Utils.enumValue(TransformMode, getValue(boneMap, "transform", "Normal"));
|
|
data.skinRequired = getValue(boneMap, "skin", false);
|
|
let color = getValue(boneMap, "color", null);
|
|
if (color)
|
|
data.color.setFromString(color);
|
|
skeletonData.bones.push(data);
|
|
}
|
|
}
|
|
if (root.slots) {
|
|
for (let i = 0; i < root.slots.length; i++) {
|
|
let slotMap = root.slots[i];
|
|
let boneData = skeletonData.findBone(slotMap.bone);
|
|
if (!boneData)
|
|
throw new Error(`Couldn't find bone ${slotMap.bone} for slot ${slotMap.name}`);
|
|
let data = new SlotData(skeletonData.slots.length, slotMap.name, boneData);
|
|
let color = getValue(slotMap, "color", null);
|
|
if (color)
|
|
data.color.setFromString(color);
|
|
let dark = getValue(slotMap, "dark", null);
|
|
if (dark)
|
|
data.darkColor = Color.fromString(dark);
|
|
data.attachmentName = getValue(slotMap, "attachment", null);
|
|
data.blendMode = Utils.enumValue(BlendMode, getValue(slotMap, "blend", "normal"));
|
|
skeletonData.slots.push(data);
|
|
}
|
|
}
|
|
if (root.ik) {
|
|
for (let i = 0; i < root.ik.length; i++) {
|
|
let constraintMap = root.ik[i];
|
|
let data = new IkConstraintData(constraintMap.name);
|
|
data.order = getValue(constraintMap, "order", 0);
|
|
data.skinRequired = getValue(constraintMap, "skin", false);
|
|
for (let ii = 0; ii < constraintMap.bones.length; ii++) {
|
|
let bone = skeletonData.findBone(constraintMap.bones[ii]);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${constraintMap.bones[ii]} for IK constraint ${constraintMap.name}.`);
|
|
data.bones.push(bone);
|
|
}
|
|
let target = skeletonData.findBone(constraintMap.target);
|
|
;
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${constraintMap.target} for IK constraint ${constraintMap.name}.`);
|
|
data.target = target;
|
|
data.mix = getValue(constraintMap, "mix", 1);
|
|
data.softness = getValue(constraintMap, "softness", 0) * scale;
|
|
data.bendDirection = getValue(constraintMap, "bendPositive", true) ? 1 : -1;
|
|
data.compress = getValue(constraintMap, "compress", false);
|
|
data.stretch = getValue(constraintMap, "stretch", false);
|
|
data.uniform = getValue(constraintMap, "uniform", false);
|
|
skeletonData.ikConstraints.push(data);
|
|
}
|
|
}
|
|
if (root.transform) {
|
|
for (let i = 0; i < root.transform.length; i++) {
|
|
let constraintMap = root.transform[i];
|
|
let data = new TransformConstraintData(constraintMap.name);
|
|
data.order = getValue(constraintMap, "order", 0);
|
|
data.skinRequired = getValue(constraintMap, "skin", false);
|
|
for (let ii = 0; ii < constraintMap.bones.length; ii++) {
|
|
let boneName = constraintMap.bones[ii];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${boneName} for transform constraint ${constraintMap.name}.`);
|
|
data.bones.push(bone);
|
|
}
|
|
let targetName = constraintMap.target;
|
|
let target = skeletonData.findBone(targetName);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target bone ${targetName} for transform constraint ${constraintMap.name}.`);
|
|
data.target = target;
|
|
data.local = getValue(constraintMap, "local", false);
|
|
data.relative = getValue(constraintMap, "relative", false);
|
|
data.offsetRotation = getValue(constraintMap, "rotation", 0);
|
|
data.offsetX = getValue(constraintMap, "x", 0) * scale;
|
|
data.offsetY = getValue(constraintMap, "y", 0) * scale;
|
|
data.offsetScaleX = getValue(constraintMap, "scaleX", 0);
|
|
data.offsetScaleY = getValue(constraintMap, "scaleY", 0);
|
|
data.offsetShearY = getValue(constraintMap, "shearY", 0);
|
|
data.mixRotate = getValue(constraintMap, "mixRotate", 1);
|
|
data.mixX = getValue(constraintMap, "mixX", 1);
|
|
data.mixY = getValue(constraintMap, "mixY", data.mixX);
|
|
data.mixScaleX = getValue(constraintMap, "mixScaleX", 1);
|
|
data.mixScaleY = getValue(constraintMap, "mixScaleY", data.mixScaleX);
|
|
data.mixShearY = getValue(constraintMap, "mixShearY", 1);
|
|
skeletonData.transformConstraints.push(data);
|
|
}
|
|
}
|
|
if (root.path) {
|
|
for (let i = 0; i < root.path.length; i++) {
|
|
let constraintMap = root.path[i];
|
|
let data = new PathConstraintData(constraintMap.name);
|
|
data.order = getValue(constraintMap, "order", 0);
|
|
data.skinRequired = getValue(constraintMap, "skin", false);
|
|
for (let ii = 0; ii < constraintMap.bones.length; ii++) {
|
|
let boneName = constraintMap.bones[ii];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${boneName} for path constraint ${constraintMap.name}.`);
|
|
data.bones.push(bone);
|
|
}
|
|
let targetName = constraintMap.target;
|
|
let target = skeletonData.findSlot(targetName);
|
|
if (!target)
|
|
throw new Error(`Couldn't find target slot ${targetName} for path constraint ${constraintMap.name}.`);
|
|
data.target = target;
|
|
data.positionMode = Utils.enumValue(PositionMode, getValue(constraintMap, "positionMode", "Percent"));
|
|
data.spacingMode = Utils.enumValue(SpacingMode, getValue(constraintMap, "spacingMode", "Length"));
|
|
data.rotateMode = Utils.enumValue(RotateMode, getValue(constraintMap, "rotateMode", "Tangent"));
|
|
data.offsetRotation = getValue(constraintMap, "rotation", 0);
|
|
data.position = getValue(constraintMap, "position", 0);
|
|
if (data.positionMode == 0 /* Fixed */)
|
|
data.position *= scale;
|
|
data.spacing = getValue(constraintMap, "spacing", 0);
|
|
if (data.spacingMode == 0 /* Length */ || data.spacingMode == 1 /* Fixed */)
|
|
data.spacing *= scale;
|
|
data.mixRotate = getValue(constraintMap, "mixRotate", 1);
|
|
data.mixX = getValue(constraintMap, "mixX", 1);
|
|
data.mixY = getValue(constraintMap, "mixY", data.mixX);
|
|
skeletonData.pathConstraints.push(data);
|
|
}
|
|
}
|
|
if (root.skins) {
|
|
for (let i = 0; i < root.skins.length; i++) {
|
|
let skinMap = root.skins[i];
|
|
let skin = new Skin(skinMap.name);
|
|
if (skinMap.bones) {
|
|
for (let ii = 0; ii < skinMap.bones.length; ii++) {
|
|
let boneName = skinMap.bones[ii];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error(`Couldn't find bone ${boneName} for skin ${skinMap.name}.`);
|
|
skin.bones.push(bone);
|
|
}
|
|
}
|
|
if (skinMap.ik) {
|
|
for (let ii = 0; ii < skinMap.ik.length; ii++) {
|
|
let constraintName = skinMap.ik[ii];
|
|
let constraint = skeletonData.findIkConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error(`Couldn't find IK constraint ${constraintName} for skin ${skinMap.name}.`);
|
|
skin.constraints.push(constraint);
|
|
}
|
|
}
|
|
if (skinMap.transform) {
|
|
for (let ii = 0; ii < skinMap.transform.length; ii++) {
|
|
let constraintName = skinMap.transform[ii];
|
|
let constraint = skeletonData.findTransformConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error(`Couldn't find transform constraint ${constraintName} for skin ${skinMap.name}.`);
|
|
skin.constraints.push(constraint);
|
|
}
|
|
}
|
|
if (skinMap.path) {
|
|
for (let ii = 0; ii < skinMap.path.length; ii++) {
|
|
let constraintName = skinMap.path[ii];
|
|
let constraint = skeletonData.findPathConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error(`Couldn't find path constraint ${constraintName} for skin ${skinMap.name}.`);
|
|
skin.constraints.push(constraint);
|
|
}
|
|
}
|
|
for (let slotName in skinMap.attachments) {
|
|
let slot = skeletonData.findSlot(slotName);
|
|
if (!slot)
|
|
throw new Error(`Couldn't find slot ${slotName} for skin ${skinMap.name}.`);
|
|
let slotMap = skinMap.attachments[slotName];
|
|
for (let entryName in slotMap) {
|
|
let attachment = this.readAttachment(slotMap[entryName], skin, slot.index, entryName, skeletonData);
|
|
if (attachment)
|
|
skin.setAttachment(slot.index, entryName, attachment);
|
|
}
|
|
}
|
|
skeletonData.skins.push(skin);
|
|
if (skin.name == "default")
|
|
skeletonData.defaultSkin = skin;
|
|
}
|
|
}
|
|
for (let i = 0, n = this.linkedMeshes.length; i < n; i++) {
|
|
let linkedMesh = this.linkedMeshes[i];
|
|
let skin = !linkedMesh.skin ? skeletonData.defaultSkin : skeletonData.findSkin(linkedMesh.skin);
|
|
if (!skin)
|
|
throw new Error(`Skin not found: ${linkedMesh.skin}`);
|
|
let parent = skin.getAttachment(linkedMesh.slotIndex, linkedMesh.parent);
|
|
if (!parent)
|
|
throw new Error(`Parent mesh not found: ${linkedMesh.parent}`);
|
|
linkedMesh.mesh.timelineAttachment = linkedMesh.inheritTimeline ? parent : linkedMesh.mesh;
|
|
linkedMesh.mesh.setParentMesh(parent);
|
|
if (linkedMesh.mesh.region != null)
|
|
linkedMesh.mesh.updateRegion();
|
|
}
|
|
this.linkedMeshes.length = 0;
|
|
if (root.events) {
|
|
for (let eventName in root.events) {
|
|
let eventMap = root.events[eventName];
|
|
let data = new EventData(eventName);
|
|
data.intValue = getValue(eventMap, "int", 0);
|
|
data.floatValue = getValue(eventMap, "float", 0);
|
|
data.stringValue = getValue(eventMap, "string", "");
|
|
data.audioPath = getValue(eventMap, "audio", null);
|
|
if (data.audioPath) {
|
|
data.volume = getValue(eventMap, "volume", 1);
|
|
data.balance = getValue(eventMap, "balance", 0);
|
|
}
|
|
skeletonData.events.push(data);
|
|
}
|
|
}
|
|
if (root.animations) {
|
|
for (let animationName in root.animations) {
|
|
let animationMap = root.animations[animationName];
|
|
this.readAnimation(animationMap, animationName, skeletonData);
|
|
}
|
|
}
|
|
return skeletonData;
|
|
}
|
|
readAttachment(map, skin, slotIndex, name, skeletonData) {
|
|
let scale = this.scale;
|
|
name = getValue(map, "name", name);
|
|
switch (getValue(map, "type", "region")) {
|
|
case "region": {
|
|
let path = getValue(map, "path", name);
|
|
let sequence = this.readSequence(getValue(map, "sequence", null));
|
|
let region = this.attachmentLoader.newRegionAttachment(skin, name, path, sequence);
|
|
if (!region)
|
|
return null;
|
|
region.path = path;
|
|
region.x = getValue(map, "x", 0) * scale;
|
|
region.y = getValue(map, "y", 0) * scale;
|
|
region.scaleX = getValue(map, "scaleX", 1);
|
|
region.scaleY = getValue(map, "scaleY", 1);
|
|
region.rotation = getValue(map, "rotation", 0);
|
|
region.width = map.width * scale;
|
|
region.height = map.height * scale;
|
|
region.sequence = sequence;
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
region.color.setFromString(color);
|
|
if (region.region != null)
|
|
region.updateRegion();
|
|
return region;
|
|
}
|
|
case "boundingbox": {
|
|
let box = this.attachmentLoader.newBoundingBoxAttachment(skin, name);
|
|
if (!box)
|
|
return null;
|
|
this.readVertices(map, box, map.vertexCount << 1);
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
box.color.setFromString(color);
|
|
return box;
|
|
}
|
|
case "mesh":
|
|
case "linkedmesh": {
|
|
let path = getValue(map, "path", name);
|
|
let sequence = this.readSequence(getValue(map, "sequence", null));
|
|
let mesh = this.attachmentLoader.newMeshAttachment(skin, name, path, sequence);
|
|
if (!mesh)
|
|
return null;
|
|
mesh.path = path;
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
mesh.color.setFromString(color);
|
|
mesh.width = getValue(map, "width", 0) * scale;
|
|
mesh.height = getValue(map, "height", 0) * scale;
|
|
mesh.sequence = sequence;
|
|
let parent = getValue(map, "parent", null);
|
|
if (parent) {
|
|
this.linkedMeshes.push(new LinkedMesh2(mesh, getValue(map, "skin", null), slotIndex, parent, getValue(map, "timelines", true)));
|
|
return mesh;
|
|
}
|
|
let uvs = map.uvs;
|
|
this.readVertices(map, mesh, uvs.length);
|
|
mesh.triangles = map.triangles;
|
|
mesh.regionUVs = uvs;
|
|
if (mesh.region != null)
|
|
mesh.updateRegion();
|
|
mesh.edges = getValue(map, "edges", null);
|
|
mesh.hullLength = getValue(map, "hull", 0) * 2;
|
|
return mesh;
|
|
}
|
|
case "path": {
|
|
let path = this.attachmentLoader.newPathAttachment(skin, name);
|
|
if (!path)
|
|
return null;
|
|
path.closed = getValue(map, "closed", false);
|
|
path.constantSpeed = getValue(map, "constantSpeed", true);
|
|
let vertexCount = map.vertexCount;
|
|
this.readVertices(map, path, vertexCount << 1);
|
|
let lengths = Utils.newArray(vertexCount / 3, 0);
|
|
for (let i = 0; i < map.lengths.length; i++)
|
|
lengths[i] = map.lengths[i] * scale;
|
|
path.lengths = lengths;
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
path.color.setFromString(color);
|
|
return path;
|
|
}
|
|
case "point": {
|
|
let point = this.attachmentLoader.newPointAttachment(skin, name);
|
|
if (!point)
|
|
return null;
|
|
point.x = getValue(map, "x", 0) * scale;
|
|
point.y = getValue(map, "y", 0) * scale;
|
|
point.rotation = getValue(map, "rotation", 0);
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
point.color.setFromString(color);
|
|
return point;
|
|
}
|
|
case "clipping": {
|
|
let clip = this.attachmentLoader.newClippingAttachment(skin, name);
|
|
if (!clip)
|
|
return null;
|
|
let end = getValue(map, "end", null);
|
|
if (end)
|
|
clip.endSlot = skeletonData.findSlot(end);
|
|
let vertexCount = map.vertexCount;
|
|
this.readVertices(map, clip, vertexCount << 1);
|
|
let color = getValue(map, "color", null);
|
|
if (color)
|
|
clip.color.setFromString(color);
|
|
return clip;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
readSequence(map) {
|
|
if (map == null)
|
|
return null;
|
|
let sequence = new Sequence(getValue(map, "count", 0));
|
|
sequence.start = getValue(map, "start", 1);
|
|
sequence.digits = getValue(map, "digits", 0);
|
|
sequence.setupIndex = getValue(map, "setup", 0);
|
|
return sequence;
|
|
}
|
|
readVertices(map, attachment, verticesLength) {
|
|
let scale = this.scale;
|
|
attachment.worldVerticesLength = verticesLength;
|
|
let vertices = map.vertices;
|
|
if (verticesLength == vertices.length) {
|
|
let scaledVertices = Utils.toFloatArray(vertices);
|
|
if (scale != 1) {
|
|
for (let i = 0, n = vertices.length; i < n; i++)
|
|
scaledVertices[i] *= scale;
|
|
}
|
|
attachment.vertices = scaledVertices;
|
|
return;
|
|
}
|
|
let weights = new Array();
|
|
let bones = new Array();
|
|
for (let i = 0, n = vertices.length; i < n; ) {
|
|
let boneCount = vertices[i++];
|
|
bones.push(boneCount);
|
|
for (let nn = i + boneCount * 4; i < nn; i += 4) {
|
|
bones.push(vertices[i]);
|
|
weights.push(vertices[i + 1] * scale);
|
|
weights.push(vertices[i + 2] * scale);
|
|
weights.push(vertices[i + 3]);
|
|
}
|
|
}
|
|
attachment.bones = bones;
|
|
attachment.vertices = Utils.toFloatArray(weights);
|
|
}
|
|
readAnimation(map, name, skeletonData) {
|
|
let scale = this.scale;
|
|
let timelines = new Array();
|
|
if (map.slots) {
|
|
for (let slotName in map.slots) {
|
|
let slotMap = map.slots[slotName];
|
|
let slot = skeletonData.findSlot(slotName);
|
|
if (!slot)
|
|
throw new Error("Slot not found: " + slotName);
|
|
let slotIndex = slot.index;
|
|
for (let timelineName in slotMap) {
|
|
let timelineMap = slotMap[timelineName];
|
|
if (!timelineMap)
|
|
continue;
|
|
let frames = timelineMap.length;
|
|
if (timelineName == "attachment") {
|
|
let timeline = new AttachmentTimeline(frames, slotIndex);
|
|
for (let frame = 0; frame < frames; frame++) {
|
|
let keyMap = timelineMap[frame];
|
|
timeline.setFrame(frame, getValue(keyMap, "time", 0), getValue(keyMap, "name", null));
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "rgba") {
|
|
let timeline = new RGBATimeline(frames, frames << 2, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.color);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b, color.a);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.color);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "rgb") {
|
|
let timeline = new RGBTimeline(frames, frames * 3, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.color);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.color);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "alpha") {
|
|
timelines.push(readTimeline12(timelineMap, new AlphaTimeline(frames, frames, slotIndex), 0, 1));
|
|
} else if (timelineName == "rgba2") {
|
|
let timeline = new RGBA2Timeline(frames, frames * 7, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.light);
|
|
let color2 = Color.fromString(keyMap.dark);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b, color.a, color2.r, color2.g, color2.b);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.light);
|
|
let newColor2 = Color.fromString(nextMap.dark);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color.a, newColor.a, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.r, newColor2.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.g, newColor2.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 6, time, time2, color2.b, newColor2.b, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
color2 = newColor2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineName == "rgb2") {
|
|
let timeline = new RGB2Timeline(frames, frames * 6, slotIndex);
|
|
let keyMap = timelineMap[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let color = Color.fromString(keyMap.light);
|
|
let color2 = Color.fromString(keyMap.dark);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, color.r, color.g, color.b, color2.r, color2.g, color2.b);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let newColor = Color.fromString(nextMap.light);
|
|
let newColor2 = Color.fromString(nextMap.dark);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, color.r, newColor.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, color.g, newColor.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, color.b, newColor.b, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, color2.r, newColor2.r, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, color2.g, newColor2.g, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, color2.b, newColor2.b, 1);
|
|
}
|
|
time = time2;
|
|
color = newColor;
|
|
color2 = newColor2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.bones) {
|
|
for (let boneName in map.bones) {
|
|
let boneMap = map.bones[boneName];
|
|
let bone = skeletonData.findBone(boneName);
|
|
if (!bone)
|
|
throw new Error("Bone not found: " + boneName);
|
|
let boneIndex = bone.index;
|
|
for (let timelineName in boneMap) {
|
|
let timelineMap = boneMap[timelineName];
|
|
let frames = timelineMap.length;
|
|
if (frames == 0)
|
|
continue;
|
|
if (timelineName === "rotate") {
|
|
timelines.push(readTimeline12(timelineMap, new RotateTimeline(frames, frames, boneIndex), 0, 1));
|
|
} else if (timelineName === "translate") {
|
|
let timeline = new TranslateTimeline(frames, frames << 1, boneIndex);
|
|
timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, scale));
|
|
} else if (timelineName === "translatex") {
|
|
let timeline = new TranslateXTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, scale));
|
|
} else if (timelineName === "translatey") {
|
|
let timeline = new TranslateYTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, scale));
|
|
} else if (timelineName === "scale") {
|
|
let timeline = new ScaleTimeline(frames, frames << 1, boneIndex);
|
|
timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 1, 1));
|
|
} else if (timelineName === "scalex") {
|
|
let timeline = new ScaleXTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 1, 1));
|
|
} else if (timelineName === "scaley") {
|
|
let timeline = new ScaleYTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 1, 1));
|
|
} else if (timelineName === "shear") {
|
|
let timeline = new ShearTimeline(frames, frames << 1, boneIndex);
|
|
timelines.push(readTimeline22(timelineMap, timeline, "x", "y", 0, 1));
|
|
} else if (timelineName === "shearx") {
|
|
let timeline = new ShearXTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, 1));
|
|
} else if (timelineName === "sheary") {
|
|
let timeline = new ShearYTimeline(frames, frames, boneIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, 1));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.ik) {
|
|
for (let constraintName in map.ik) {
|
|
let constraintMap = map.ik[constraintName];
|
|
let keyMap = constraintMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
let constraint = skeletonData.findIkConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error("IK Constraint not found: " + constraintName);
|
|
let constraintIndex = skeletonData.ikConstraints.indexOf(constraint);
|
|
let timeline = new IkConstraintTimeline(constraintMap.length, constraintMap.length << 1, constraintIndex);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mix = getValue(keyMap, "mix", 1);
|
|
let softness = getValue(keyMap, "softness", 0) * scale;
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mix, softness, getValue(keyMap, "bendPositive", true) ? 1 : -1, getValue(keyMap, "compress", false), getValue(keyMap, "stretch", false));
|
|
let nextMap = constraintMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let mix2 = getValue(nextMap, "mix", 1);
|
|
let softness2 = getValue(nextMap, "softness", 0) * scale;
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mix, mix2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, softness, softness2, scale);
|
|
}
|
|
time = time2;
|
|
mix = mix2;
|
|
softness = softness2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
if (map.transform) {
|
|
for (let constraintName in map.transform) {
|
|
let timelineMap = map.transform[constraintName];
|
|
let keyMap = timelineMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
let constraint = skeletonData.findTransformConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error("Transform constraint not found: " + constraintName);
|
|
let constraintIndex = skeletonData.transformConstraints.indexOf(constraint);
|
|
let timeline = new TransformConstraintTimeline(timelineMap.length, timelineMap.length * 6, constraintIndex);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mixRotate = getValue(keyMap, "mixRotate", 1);
|
|
let mixX = getValue(keyMap, "mixX", 1);
|
|
let mixY = getValue(keyMap, "mixY", mixX);
|
|
let mixScaleX = getValue(keyMap, "mixScaleX", 1);
|
|
let mixScaleY = getValue(keyMap, "mixScaleY", mixScaleX);
|
|
let mixShearY = getValue(keyMap, "mixShearY", 1);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY, mixScaleX, mixScaleY, mixShearY);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let mixRotate2 = getValue(nextMap, "mixRotate", 1);
|
|
let mixX2 = getValue(nextMap, "mixX", 1);
|
|
let mixY2 = getValue(nextMap, "mixY", mixX2);
|
|
let mixScaleX2 = getValue(nextMap, "mixScaleX", 1);
|
|
let mixScaleY2 = getValue(nextMap, "mixScaleY", mixScaleX2);
|
|
let mixShearY2 = getValue(nextMap, "mixShearY", 1);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 3, time, time2, mixScaleX, mixScaleX2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 4, time, time2, mixScaleY, mixScaleY2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 5, time, time2, mixShearY, mixShearY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
mixScaleX = mixScaleX2;
|
|
mixScaleY = mixScaleY2;
|
|
mixScaleX = mixScaleX2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
if (map.path) {
|
|
for (let constraintName in map.path) {
|
|
let constraintMap = map.path[constraintName];
|
|
let constraint = skeletonData.findPathConstraint(constraintName);
|
|
if (!constraint)
|
|
throw new Error("Path constraint not found: " + constraintName);
|
|
let constraintIndex = skeletonData.pathConstraints.indexOf(constraint);
|
|
for (let timelineName in constraintMap) {
|
|
let timelineMap = constraintMap[timelineName];
|
|
let keyMap = timelineMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
let frames = timelineMap.length;
|
|
if (timelineName === "position") {
|
|
let timeline = new PathConstraintPositionTimeline(frames, frames, constraintIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.positionMode == 0 /* Fixed */ ? scale : 1));
|
|
} else if (timelineName === "spacing") {
|
|
let timeline = new PathConstraintSpacingTimeline(frames, frames, constraintIndex);
|
|
timelines.push(readTimeline12(timelineMap, timeline, 0, constraint.spacingMode == 0 /* Length */ || constraint.spacingMode == 1 /* Fixed */ ? scale : 1));
|
|
} else if (timelineName === "mix") {
|
|
let timeline = new PathConstraintMixTimeline(frames, frames * 3, constraintIndex);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mixRotate = getValue(keyMap, "mixRotate", 1);
|
|
let mixX = getValue(keyMap, "mixX", 1);
|
|
let mixY = getValue(keyMap, "mixY", mixX);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, mixRotate, mixX, mixY);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let mixRotate2 = getValue(nextMap, "mixRotate", 1);
|
|
let mixX2 = getValue(nextMap, "mixX", 1);
|
|
let mixY2 = getValue(nextMap, "mixY", mixX2);
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, mixRotate, mixRotate2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, mixX, mixX2, 1);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 2, time, time2, mixY, mixY2, 1);
|
|
}
|
|
time = time2;
|
|
mixRotate = mixRotate2;
|
|
mixX = mixX2;
|
|
mixY = mixY2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.attachments) {
|
|
for (let attachmentsName in map.attachments) {
|
|
let attachmentsMap = map.attachments[attachmentsName];
|
|
let skin = skeletonData.findSkin(attachmentsName);
|
|
if (!skin)
|
|
throw new Error("Skin not found: " + attachmentsName);
|
|
for (let slotMapName in attachmentsMap) {
|
|
let slotMap = attachmentsMap[slotMapName];
|
|
let slot = skeletonData.findSlot(slotMapName);
|
|
if (!slot)
|
|
throw new Error("Slot not found: " + slotMapName);
|
|
let slotIndex = slot.index;
|
|
for (let attachmentMapName in slotMap) {
|
|
let attachmentMap = slotMap[attachmentMapName];
|
|
let attachment = skin.getAttachment(slotIndex, attachmentMapName);
|
|
for (let timelineMapName in attachmentMap) {
|
|
let timelineMap = attachmentMap[timelineMapName];
|
|
let keyMap = timelineMap[0];
|
|
if (!keyMap)
|
|
continue;
|
|
if (timelineMapName == "deform") {
|
|
let weighted = attachment.bones;
|
|
let vertices = attachment.vertices;
|
|
let deformLength = weighted ? vertices.length / 3 * 2 : vertices.length;
|
|
let timeline = new DeformTimeline(timelineMap.length, timelineMap.length, slotIndex, attachment);
|
|
let time = getValue(keyMap, "time", 0);
|
|
for (let frame = 0, bezier = 0; ; frame++) {
|
|
let deform;
|
|
let verticesValue = getValue(keyMap, "vertices", null);
|
|
if (!verticesValue)
|
|
deform = weighted ? Utils.newFloatArray(deformLength) : vertices;
|
|
else {
|
|
deform = Utils.newFloatArray(deformLength);
|
|
let start = getValue(keyMap, "offset", 0);
|
|
Utils.arrayCopy(verticesValue, 0, deform, start, verticesValue.length);
|
|
if (scale != 1) {
|
|
for (let i = start, n = i + verticesValue.length; i < n; i++)
|
|
deform[i] *= scale;
|
|
}
|
|
if (!weighted) {
|
|
for (let i = 0; i < deformLength; i++)
|
|
deform[i] += vertices[i];
|
|
}
|
|
}
|
|
timeline.setFrame(frame, time, deform);
|
|
let nextMap = timelineMap[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
break;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let curve = keyMap.curve;
|
|
if (curve)
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, 0, 1, 1);
|
|
time = time2;
|
|
keyMap = nextMap;
|
|
}
|
|
timelines.push(timeline);
|
|
} else if (timelineMapName == "sequence") {
|
|
let timeline = new SequenceTimeline(timelineMap.length, slotIndex, attachment);
|
|
let lastDelay = 0;
|
|
for (let frame = 0; frame < timelineMap.length; frame++) {
|
|
let delay = getValue(keyMap, "delay", lastDelay);
|
|
let time = getValue(keyMap, "time", 0);
|
|
let mode = SequenceMode[getValue(keyMap, "mode", "hold")];
|
|
let index = getValue(keyMap, "index", 0);
|
|
timeline.setFrame(frame, time, mode, index, delay);
|
|
lastDelay = delay;
|
|
keyMap = timelineMap[frame + 1];
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (map.drawOrder) {
|
|
let timeline = new DrawOrderTimeline(map.drawOrder.length);
|
|
let slotCount = skeletonData.slots.length;
|
|
let frame = 0;
|
|
for (let i = 0; i < map.drawOrder.length; i++, frame++) {
|
|
let drawOrderMap = map.drawOrder[i];
|
|
let drawOrder = null;
|
|
let offsets = getValue(drawOrderMap, "offsets", null);
|
|
if (offsets) {
|
|
drawOrder = Utils.newArray(slotCount, -1);
|
|
let unchanged = Utils.newArray(slotCount - offsets.length, 0);
|
|
let originalIndex = 0, unchangedIndex = 0;
|
|
for (let ii = 0; ii < offsets.length; ii++) {
|
|
let offsetMap = offsets[ii];
|
|
let slot = skeletonData.findSlot(offsetMap.slot);
|
|
if (!slot)
|
|
throw new Error("Slot not found: " + slot);
|
|
let slotIndex = slot.index;
|
|
while (originalIndex != slotIndex)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
drawOrder[originalIndex + offsetMap.offset] = originalIndex++;
|
|
}
|
|
while (originalIndex < slotCount)
|
|
unchanged[unchangedIndex++] = originalIndex++;
|
|
for (let ii = slotCount - 1; ii >= 0; ii--)
|
|
if (drawOrder[ii] == -1)
|
|
drawOrder[ii] = unchanged[--unchangedIndex];
|
|
}
|
|
timeline.setFrame(frame, getValue(drawOrderMap, "time", 0), drawOrder);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
if (map.events) {
|
|
let timeline = new EventTimeline(map.events.length);
|
|
let frame = 0;
|
|
for (let i = 0; i < map.events.length; i++, frame++) {
|
|
let eventMap = map.events[i];
|
|
let eventData = skeletonData.findEvent(eventMap.name);
|
|
if (!eventData)
|
|
throw new Error("Event not found: " + eventMap.name);
|
|
let event = new Event(Utils.toSinglePrecision(getValue(eventMap, "time", 0)), eventData);
|
|
event.intValue = getValue(eventMap, "int", eventData.intValue);
|
|
event.floatValue = getValue(eventMap, "float", eventData.floatValue);
|
|
event.stringValue = getValue(eventMap, "string", eventData.stringValue);
|
|
if (event.data.audioPath) {
|
|
event.volume = getValue(eventMap, "volume", 1);
|
|
event.balance = getValue(eventMap, "balance", 0);
|
|
}
|
|
timeline.setFrame(frame, event);
|
|
}
|
|
timelines.push(timeline);
|
|
}
|
|
let duration = 0;
|
|
for (let i = 0, n = timelines.length; i < n; i++)
|
|
duration = Math.max(duration, timelines[i].getDuration());
|
|
skeletonData.animations.push(new Animation(name, timelines, duration));
|
|
}
|
|
};
|
|
var LinkedMesh2 = class {
|
|
constructor(mesh, skin, slotIndex, parent, inheritDeform) {
|
|
this.mesh = mesh;
|
|
this.skin = skin;
|
|
this.slotIndex = slotIndex;
|
|
this.parent = parent;
|
|
this.inheritTimeline = inheritDeform;
|
|
}
|
|
};
|
|
function readTimeline12(keys, timeline, defaultValue, scale) {
|
|
let keyMap = keys[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let value = getValue(keyMap, "value", defaultValue) * scale;
|
|
let bezier = 0;
|
|
for (let frame = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, value);
|
|
let nextMap = keys[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
return timeline;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let value2 = getValue(nextMap, "value", defaultValue) * scale;
|
|
if (keyMap.curve)
|
|
bezier = readCurve(keyMap.curve, timeline, bezier, frame, 0, time, time2, value, value2, scale);
|
|
time = time2;
|
|
value = value2;
|
|
keyMap = nextMap;
|
|
}
|
|
}
|
|
function readTimeline22(keys, timeline, name1, name2, defaultValue, scale) {
|
|
let keyMap = keys[0];
|
|
let time = getValue(keyMap, "time", 0);
|
|
let value1 = getValue(keyMap, name1, defaultValue) * scale;
|
|
let value2 = getValue(keyMap, name2, defaultValue) * scale;
|
|
let bezier = 0;
|
|
for (let frame = 0; ; frame++) {
|
|
timeline.setFrame(frame, time, value1, value2);
|
|
let nextMap = keys[frame + 1];
|
|
if (!nextMap) {
|
|
timeline.shrink(bezier);
|
|
return timeline;
|
|
}
|
|
let time2 = getValue(nextMap, "time", 0);
|
|
let nvalue1 = getValue(nextMap, name1, defaultValue) * scale;
|
|
let nvalue2 = getValue(nextMap, name2, defaultValue) * scale;
|
|
let curve = keyMap.curve;
|
|
if (curve) {
|
|
bezier = readCurve(curve, timeline, bezier, frame, 0, time, time2, value1, nvalue1, scale);
|
|
bezier = readCurve(curve, timeline, bezier, frame, 1, time, time2, value2, nvalue2, scale);
|
|
}
|
|
time = time2;
|
|
value1 = nvalue1;
|
|
value2 = nvalue2;
|
|
keyMap = nextMap;
|
|
}
|
|
}
|
|
function readCurve(curve, timeline, bezier, frame, value, time1, time2, value1, value2, scale) {
|
|
if (curve == "stepped") {
|
|
timeline.setStepped(frame);
|
|
return bezier;
|
|
}
|
|
let i = value << 2;
|
|
let cx1 = curve[i];
|
|
let cy1 = curve[i + 1] * scale;
|
|
let cx2 = curve[i + 2];
|
|
let cy2 = curve[i + 3] * scale;
|
|
timeline.setBezier(bezier, frame, value, time1, value1, cx1, cy1, cx2, cy2, time2, value2);
|
|
return bezier + 1;
|
|
}
|
|
function getValue(map, property, defaultValue) {
|
|
return map[property] !== void 0 ? map[property] : defaultValue;
|
|
}
|
|
|
|
// spine-core/src/polyfills.ts
|
|
(() => {
|
|
if (typeof Math.fround === "undefined") {
|
|
Math.fround = function(array) {
|
|
return function(x) {
|
|
return array[0] = x, array[0];
|
|
};
|
|
}(new Float32Array(1));
|
|
}
|
|
})();
|
|
|
|
// spine-webgl/src/WebGL.ts
|
|
var ManagedWebGLRenderingContext = class {
|
|
constructor(canvasOrContext, contextConfig = { alpha: "true" }) {
|
|
this.restorables = new Array();
|
|
if (!(canvasOrContext instanceof WebGLRenderingContext || typeof WebGL2RenderingContext !== "undefined" && canvasOrContext instanceof WebGL2RenderingContext)) {
|
|
let canvas = canvasOrContext;
|
|
this.gl = canvas.getContext("webgl2", contextConfig) || canvas.getContext("webgl", contextConfig);
|
|
this.canvas = canvas;
|
|
canvas.addEventListener("webglcontextlost", (e) => {
|
|
let event = e;
|
|
if (e)
|
|
e.preventDefault();
|
|
});
|
|
canvas.addEventListener("webglcontextrestored", (e) => {
|
|
for (let i = 0, n = this.restorables.length; i < n; i++)
|
|
this.restorables[i].restore();
|
|
});
|
|
} else {
|
|
this.gl = canvasOrContext;
|
|
this.canvas = this.gl.canvas;
|
|
}
|
|
}
|
|
addRestorable(restorable) {
|
|
this.restorables.push(restorable);
|
|
}
|
|
removeRestorable(restorable) {
|
|
let index = this.restorables.indexOf(restorable);
|
|
if (index > -1)
|
|
this.restorables.splice(index, 1);
|
|
}
|
|
};
|
|
var ONE = 1;
|
|
var ONE_MINUS_SRC_COLOR = 769;
|
|
var SRC_ALPHA = 770;
|
|
var ONE_MINUS_SRC_ALPHA = 771;
|
|
var DST_COLOR = 774;
|
|
var WebGLBlendModeConverter = class {
|
|
static getDestGLBlendMode(blendMode) {
|
|
switch (blendMode) {
|
|
case 0 /* Normal */:
|
|
return ONE_MINUS_SRC_ALPHA;
|
|
case 1 /* Additive */:
|
|
return ONE;
|
|
case 2 /* Multiply */:
|
|
return ONE_MINUS_SRC_ALPHA;
|
|
case 3 /* Screen */:
|
|
return ONE_MINUS_SRC_ALPHA;
|
|
default:
|
|
throw new Error("Unknown blend mode: " + blendMode);
|
|
}
|
|
}
|
|
static getSourceColorGLBlendMode(blendMode, premultipliedAlpha = false) {
|
|
switch (blendMode) {
|
|
case 0 /* Normal */:
|
|
return premultipliedAlpha ? ONE : SRC_ALPHA;
|
|
case 1 /* Additive */:
|
|
return premultipliedAlpha ? ONE : SRC_ALPHA;
|
|
case 2 /* Multiply */:
|
|
return DST_COLOR;
|
|
case 3 /* Screen */:
|
|
return ONE;
|
|
default:
|
|
throw new Error("Unknown blend mode: " + blendMode);
|
|
}
|
|
}
|
|
static getSourceAlphaGLBlendMode(blendMode) {
|
|
switch (blendMode) {
|
|
case 0 /* Normal */:
|
|
return ONE;
|
|
case 1 /* Additive */:
|
|
return ONE;
|
|
case 2 /* Multiply */:
|
|
return ONE_MINUS_SRC_ALPHA;
|
|
case 3 /* Screen */:
|
|
return ONE_MINUS_SRC_COLOR;
|
|
default:
|
|
throw new Error("Unknown blend mode: " + blendMode);
|
|
}
|
|
}
|
|
};
|
|
|
|
// spine-webgl/src/GLTexture.ts
|
|
var _GLTexture = class extends Texture {
|
|
constructor(context, image, useMipMaps = false) {
|
|
super(image);
|
|
this.texture = null;
|
|
this.boundUnit = 0;
|
|
this.useMipMaps = false;
|
|
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
|
|
this.useMipMaps = useMipMaps;
|
|
this.restore();
|
|
this.context.addRestorable(this);
|
|
}
|
|
setFilters(minFilter, magFilter) {
|
|
let gl = this.context.gl;
|
|
this.bind();
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, minFilter);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, _GLTexture.validateMagFilter(magFilter));
|
|
this.useMipMaps = _GLTexture.usesMipMaps(minFilter);
|
|
if (this.useMipMaps)
|
|
gl.generateMipmap(gl.TEXTURE_2D);
|
|
}
|
|
static validateMagFilter(magFilter) {
|
|
switch (magFilter) {
|
|
case 9987 /* MipMap */:
|
|
case 9987 /* MipMapLinearLinear */:
|
|
case 9985 /* MipMapLinearNearest */:
|
|
case 9986 /* MipMapNearestLinear */:
|
|
case 9984 /* MipMapNearestNearest */:
|
|
return 9729 /* Linear */;
|
|
default:
|
|
return magFilter;
|
|
}
|
|
}
|
|
static usesMipMaps(filter) {
|
|
switch (filter) {
|
|
case 9987 /* MipMap */:
|
|
case 9987 /* MipMapLinearLinear */:
|
|
case 9985 /* MipMapLinearNearest */:
|
|
case 9986 /* MipMapNearestLinear */:
|
|
case 9984 /* MipMapNearestNearest */:
|
|
return true;
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
setWraps(uWrap, vWrap) {
|
|
let gl = this.context.gl;
|
|
this.bind();
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, uWrap);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, vWrap);
|
|
}
|
|
update(useMipMaps) {
|
|
let gl = this.context.gl;
|
|
if (!this.texture)
|
|
this.texture = this.context.gl.createTexture();
|
|
this.bind();
|
|
if (_GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL)
|
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._image);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, useMipMaps ? gl.LINEAR_MIPMAP_LINEAR : gl.LINEAR);
|
|
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 (useMipMaps)
|
|
gl.generateMipmap(gl.TEXTURE_2D);
|
|
}
|
|
restore() {
|
|
this.texture = null;
|
|
this.update(this.useMipMaps);
|
|
}
|
|
bind(unit = 0) {
|
|
let gl = this.context.gl;
|
|
this.boundUnit = unit;
|
|
gl.activeTexture(gl.TEXTURE0 + unit);
|
|
gl.bindTexture(gl.TEXTURE_2D, this.texture);
|
|
}
|
|
unbind() {
|
|
let gl = this.context.gl;
|
|
gl.activeTexture(gl.TEXTURE0 + this.boundUnit);
|
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
}
|
|
dispose() {
|
|
this.context.removeRestorable(this);
|
|
let gl = this.context.gl;
|
|
gl.deleteTexture(this.texture);
|
|
}
|
|
};
|
|
var GLTexture = _GLTexture;
|
|
GLTexture.DISABLE_UNPACK_PREMULTIPLIED_ALPHA_WEBGL = false;
|
|
|
|
// spine-webgl/src/AssetManager.ts
|
|
var AssetManager = class extends AssetManagerBase {
|
|
constructor(context, pathPrefix = "", downloader = new Downloader()) {
|
|
super((image) => {
|
|
return new GLTexture(context, image);
|
|
}, pathPrefix, downloader);
|
|
}
|
|
};
|
|
|
|
// spine-webgl/src/Vector3.ts
|
|
var Vector3 = class {
|
|
constructor(x = 0, y = 0, z = 0) {
|
|
this.x = 0;
|
|
this.y = 0;
|
|
this.z = 0;
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
}
|
|
setFrom(v) {
|
|
this.x = v.x;
|
|
this.y = v.y;
|
|
this.z = v.z;
|
|
return this;
|
|
}
|
|
set(x, y, z) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.z = z;
|
|
return this;
|
|
}
|
|
add(v) {
|
|
this.x += v.x;
|
|
this.y += v.y;
|
|
this.z += v.z;
|
|
return this;
|
|
}
|
|
sub(v) {
|
|
this.x -= v.x;
|
|
this.y -= v.y;
|
|
this.z -= v.z;
|
|
return this;
|
|
}
|
|
scale(s) {
|
|
this.x *= s;
|
|
this.y *= s;
|
|
this.z *= s;
|
|
return this;
|
|
}
|
|
normalize() {
|
|
let len = this.length();
|
|
if (len == 0)
|
|
return this;
|
|
len = 1 / len;
|
|
this.x *= len;
|
|
this.y *= len;
|
|
this.z *= len;
|
|
return this;
|
|
}
|
|
cross(v) {
|
|
return this.set(this.y * v.z - this.z * v.y, this.z * v.x - this.x * v.z, this.x * v.y - this.y * v.x);
|
|
}
|
|
multiply(matrix) {
|
|
let l_mat = matrix.values;
|
|
return this.set(
|
|
this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03],
|
|
this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13],
|
|
this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]
|
|
);
|
|
}
|
|
project(matrix) {
|
|
let l_mat = matrix.values;
|
|
let l_w = 1 / (this.x * l_mat[M30] + this.y * l_mat[M31] + this.z * l_mat[M32] + l_mat[M33]);
|
|
return this.set(
|
|
(this.x * l_mat[M00] + this.y * l_mat[M01] + this.z * l_mat[M02] + l_mat[M03]) * l_w,
|
|
(this.x * l_mat[M10] + this.y * l_mat[M11] + this.z * l_mat[M12] + l_mat[M13]) * l_w,
|
|
(this.x * l_mat[M20] + this.y * l_mat[M21] + this.z * l_mat[M22] + l_mat[M23]) * l_w
|
|
);
|
|
}
|
|
dot(v) {
|
|
return this.x * v.x + this.y * v.y + this.z * v.z;
|
|
}
|
|
length() {
|
|
return Math.sqrt(this.x * this.x + this.y * this.y + this.z * this.z);
|
|
}
|
|
distance(v) {
|
|
let a = v.x - this.x;
|
|
let b = v.y - this.y;
|
|
let c = v.z - this.z;
|
|
return Math.sqrt(a * a + b * b + c * c);
|
|
}
|
|
};
|
|
|
|
// spine-webgl/src/Matrix4.ts
|
|
var M00 = 0;
|
|
var M01 = 4;
|
|
var M02 = 8;
|
|
var M03 = 12;
|
|
var M10 = 1;
|
|
var M11 = 5;
|
|
var M12 = 9;
|
|
var M13 = 13;
|
|
var M20 = 2;
|
|
var M21 = 6;
|
|
var M22 = 10;
|
|
var M23 = 14;
|
|
var M30 = 3;
|
|
var M31 = 7;
|
|
var M32 = 11;
|
|
var M33 = 15;
|
|
var _Matrix4 = class {
|
|
constructor() {
|
|
this.temp = new Float32Array(16);
|
|
this.values = new Float32Array(16);
|
|
let v = this.values;
|
|
v[M00] = 1;
|
|
v[M11] = 1;
|
|
v[M22] = 1;
|
|
v[M33] = 1;
|
|
}
|
|
set(values) {
|
|
this.values.set(values);
|
|
return this;
|
|
}
|
|
transpose() {
|
|
let t = this.temp;
|
|
let v = this.values;
|
|
t[M00] = v[M00];
|
|
t[M01] = v[M10];
|
|
t[M02] = v[M20];
|
|
t[M03] = v[M30];
|
|
t[M10] = v[M01];
|
|
t[M11] = v[M11];
|
|
t[M12] = v[M21];
|
|
t[M13] = v[M31];
|
|
t[M20] = v[M02];
|
|
t[M21] = v[M12];
|
|
t[M22] = v[M22];
|
|
t[M23] = v[M32];
|
|
t[M30] = v[M03];
|
|
t[M31] = v[M13];
|
|
t[M32] = v[M23];
|
|
t[M33] = v[M33];
|
|
return this.set(t);
|
|
}
|
|
identity() {
|
|
let v = this.values;
|
|
v[M00] = 1;
|
|
v[M01] = 0;
|
|
v[M02] = 0;
|
|
v[M03] = 0;
|
|
v[M10] = 0;
|
|
v[M11] = 1;
|
|
v[M12] = 0;
|
|
v[M13] = 0;
|
|
v[M20] = 0;
|
|
v[M21] = 0;
|
|
v[M22] = 1;
|
|
v[M23] = 0;
|
|
v[M30] = 0;
|
|
v[M31] = 0;
|
|
v[M32] = 0;
|
|
v[M33] = 1;
|
|
return this;
|
|
}
|
|
invert() {
|
|
let v = this.values;
|
|
let t = this.temp;
|
|
let l_det = v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33];
|
|
if (l_det == 0)
|
|
throw new Error("non-invertible matrix");
|
|
let inv_det = 1 / l_det;
|
|
t[M00] = v[M12] * v[M23] * v[M31] - v[M13] * v[M22] * v[M31] + v[M13] * v[M21] * v[M32] - v[M11] * v[M23] * v[M32] - v[M12] * v[M21] * v[M33] + v[M11] * v[M22] * v[M33];
|
|
t[M01] = v[M03] * v[M22] * v[M31] - v[M02] * v[M23] * v[M31] - v[M03] * v[M21] * v[M32] + v[M01] * v[M23] * v[M32] + v[M02] * v[M21] * v[M33] - v[M01] * v[M22] * v[M33];
|
|
t[M02] = v[M02] * v[M13] * v[M31] - v[M03] * v[M12] * v[M31] + v[M03] * v[M11] * v[M32] - v[M01] * v[M13] * v[M32] - v[M02] * v[M11] * v[M33] + v[M01] * v[M12] * v[M33];
|
|
t[M03] = v[M03] * v[M12] * v[M21] - v[M02] * v[M13] * v[M21] - v[M03] * v[M11] * v[M22] + v[M01] * v[M13] * v[M22] + v[M02] * v[M11] * v[M23] - v[M01] * v[M12] * v[M23];
|
|
t[M10] = v[M13] * v[M22] * v[M30] - v[M12] * v[M23] * v[M30] - v[M13] * v[M20] * v[M32] + v[M10] * v[M23] * v[M32] + v[M12] * v[M20] * v[M33] - v[M10] * v[M22] * v[M33];
|
|
t[M11] = v[M02] * v[M23] * v[M30] - v[M03] * v[M22] * v[M30] + v[M03] * v[M20] * v[M32] - v[M00] * v[M23] * v[M32] - v[M02] * v[M20] * v[M33] + v[M00] * v[M22] * v[M33];
|
|
t[M12] = v[M03] * v[M12] * v[M30] - v[M02] * v[M13] * v[M30] - v[M03] * v[M10] * v[M32] + v[M00] * v[M13] * v[M32] + v[M02] * v[M10] * v[M33] - v[M00] * v[M12] * v[M33];
|
|
t[M13] = v[M02] * v[M13] * v[M20] - v[M03] * v[M12] * v[M20] + v[M03] * v[M10] * v[M22] - v[M00] * v[M13] * v[M22] - v[M02] * v[M10] * v[M23] + v[M00] * v[M12] * v[M23];
|
|
t[M20] = v[M11] * v[M23] * v[M30] - v[M13] * v[M21] * v[M30] + v[M13] * v[M20] * v[M31] - v[M10] * v[M23] * v[M31] - v[M11] * v[M20] * v[M33] + v[M10] * v[M21] * v[M33];
|
|
t[M21] = v[M03] * v[M21] * v[M30] - v[M01] * v[M23] * v[M30] - v[M03] * v[M20] * v[M31] + v[M00] * v[M23] * v[M31] + v[M01] * v[M20] * v[M33] - v[M00] * v[M21] * v[M33];
|
|
t[M22] = v[M01] * v[M13] * v[M30] - v[M03] * v[M11] * v[M30] + v[M03] * v[M10] * v[M31] - v[M00] * v[M13] * v[M31] - v[M01] * v[M10] * v[M33] + v[M00] * v[M11] * v[M33];
|
|
t[M23] = v[M03] * v[M11] * v[M20] - v[M01] * v[M13] * v[M20] - v[M03] * v[M10] * v[M21] + v[M00] * v[M13] * v[M21] + v[M01] * v[M10] * v[M23] - v[M00] * v[M11] * v[M23];
|
|
t[M30] = v[M12] * v[M21] * v[M30] - v[M11] * v[M22] * v[M30] - v[M12] * v[M20] * v[M31] + v[M10] * v[M22] * v[M31] + v[M11] * v[M20] * v[M32] - v[M10] * v[M21] * v[M32];
|
|
t[M31] = v[M01] * v[M22] * v[M30] - v[M02] * v[M21] * v[M30] + v[M02] * v[M20] * v[M31] - v[M00] * v[M22] * v[M31] - v[M01] * v[M20] * v[M32] + v[M00] * v[M21] * v[M32];
|
|
t[M32] = v[M02] * v[M11] * v[M30] - v[M01] * v[M12] * v[M30] - v[M02] * v[M10] * v[M31] + v[M00] * v[M12] * v[M31] + v[M01] * v[M10] * v[M32] - v[M00] * v[M11] * v[M32];
|
|
t[M33] = v[M01] * v[M12] * v[M20] - v[M02] * v[M11] * v[M20] + v[M02] * v[M10] * v[M21] - v[M00] * v[M12] * v[M21] - v[M01] * v[M10] * v[M22] + v[M00] * v[M11] * v[M22];
|
|
v[M00] = t[M00] * inv_det;
|
|
v[M01] = t[M01] * inv_det;
|
|
v[M02] = t[M02] * inv_det;
|
|
v[M03] = t[M03] * inv_det;
|
|
v[M10] = t[M10] * inv_det;
|
|
v[M11] = t[M11] * inv_det;
|
|
v[M12] = t[M12] * inv_det;
|
|
v[M13] = t[M13] * inv_det;
|
|
v[M20] = t[M20] * inv_det;
|
|
v[M21] = t[M21] * inv_det;
|
|
v[M22] = t[M22] * inv_det;
|
|
v[M23] = t[M23] * inv_det;
|
|
v[M30] = t[M30] * inv_det;
|
|
v[M31] = t[M31] * inv_det;
|
|
v[M32] = t[M32] * inv_det;
|
|
v[M33] = t[M33] * inv_det;
|
|
return this;
|
|
}
|
|
determinant() {
|
|
let v = this.values;
|
|
return v[M30] * v[M21] * v[M12] * v[M03] - v[M20] * v[M31] * v[M12] * v[M03] - v[M30] * v[M11] * v[M22] * v[M03] + v[M10] * v[M31] * v[M22] * v[M03] + v[M20] * v[M11] * v[M32] * v[M03] - v[M10] * v[M21] * v[M32] * v[M03] - v[M30] * v[M21] * v[M02] * v[M13] + v[M20] * v[M31] * v[M02] * v[M13] + v[M30] * v[M01] * v[M22] * v[M13] - v[M00] * v[M31] * v[M22] * v[M13] - v[M20] * v[M01] * v[M32] * v[M13] + v[M00] * v[M21] * v[M32] * v[M13] + v[M30] * v[M11] * v[M02] * v[M23] - v[M10] * v[M31] * v[M02] * v[M23] - v[M30] * v[M01] * v[M12] * v[M23] + v[M00] * v[M31] * v[M12] * v[M23] + v[M10] * v[M01] * v[M32] * v[M23] - v[M00] * v[M11] * v[M32] * v[M23] - v[M20] * v[M11] * v[M02] * v[M33] + v[M10] * v[M21] * v[M02] * v[M33] + v[M20] * v[M01] * v[M12] * v[M33] - v[M00] * v[M21] * v[M12] * v[M33] - v[M10] * v[M01] * v[M22] * v[M33] + v[M00] * v[M11] * v[M22] * v[M33];
|
|
}
|
|
translate(x, y, z) {
|
|
let v = this.values;
|
|
v[M03] += x;
|
|
v[M13] += y;
|
|
v[M23] += z;
|
|
return this;
|
|
}
|
|
copy() {
|
|
return new _Matrix4().set(this.values);
|
|
}
|
|
projection(near, far, fovy, aspectRatio) {
|
|
this.identity();
|
|
let l_fd = 1 / Math.tan(fovy * (Math.PI / 180) / 2);
|
|
let l_a1 = (far + near) / (near - far);
|
|
let l_a2 = 2 * far * near / (near - far);
|
|
let v = this.values;
|
|
v[M00] = l_fd / aspectRatio;
|
|
v[M10] = 0;
|
|
v[M20] = 0;
|
|
v[M30] = 0;
|
|
v[M01] = 0;
|
|
v[M11] = l_fd;
|
|
v[M21] = 0;
|
|
v[M31] = 0;
|
|
v[M02] = 0;
|
|
v[M12] = 0;
|
|
v[M22] = l_a1;
|
|
v[M32] = -1;
|
|
v[M03] = 0;
|
|
v[M13] = 0;
|
|
v[M23] = l_a2;
|
|
v[M33] = 0;
|
|
return this;
|
|
}
|
|
ortho2d(x, y, width, height) {
|
|
return this.ortho(x, x + width, y, y + height, 0, 1);
|
|
}
|
|
ortho(left, right, bottom, top, near, far) {
|
|
this.identity();
|
|
let x_orth = 2 / (right - left);
|
|
let y_orth = 2 / (top - bottom);
|
|
let z_orth = -2 / (far - near);
|
|
let tx = -(right + left) / (right - left);
|
|
let ty = -(top + bottom) / (top - bottom);
|
|
let tz = -(far + near) / (far - near);
|
|
let v = this.values;
|
|
v[M00] = x_orth;
|
|
v[M10] = 0;
|
|
v[M20] = 0;
|
|
v[M30] = 0;
|
|
v[M01] = 0;
|
|
v[M11] = y_orth;
|
|
v[M21] = 0;
|
|
v[M31] = 0;
|
|
v[M02] = 0;
|
|
v[M12] = 0;
|
|
v[M22] = z_orth;
|
|
v[M32] = 0;
|
|
v[M03] = tx;
|
|
v[M13] = ty;
|
|
v[M23] = tz;
|
|
v[M33] = 1;
|
|
return this;
|
|
}
|
|
multiply(matrix) {
|
|
let t = this.temp;
|
|
let v = this.values;
|
|
let m = matrix.values;
|
|
t[M00] = v[M00] * m[M00] + v[M01] * m[M10] + v[M02] * m[M20] + v[M03] * m[M30];
|
|
t[M01] = v[M00] * m[M01] + v[M01] * m[M11] + v[M02] * m[M21] + v[M03] * m[M31];
|
|
t[M02] = v[M00] * m[M02] + v[M01] * m[M12] + v[M02] * m[M22] + v[M03] * m[M32];
|
|
t[M03] = v[M00] * m[M03] + v[M01] * m[M13] + v[M02] * m[M23] + v[M03] * m[M33];
|
|
t[M10] = v[M10] * m[M00] + v[M11] * m[M10] + v[M12] * m[M20] + v[M13] * m[M30];
|
|
t[M11] = v[M10] * m[M01] + v[M11] * m[M11] + v[M12] * m[M21] + v[M13] * m[M31];
|
|
t[M12] = v[M10] * m[M02] + v[M11] * m[M12] + v[M12] * m[M22] + v[M13] * m[M32];
|
|
t[M13] = v[M10] * m[M03] + v[M11] * m[M13] + v[M12] * m[M23] + v[M13] * m[M33];
|
|
t[M20] = v[M20] * m[M00] + v[M21] * m[M10] + v[M22] * m[M20] + v[M23] * m[M30];
|
|
t[M21] = v[M20] * m[M01] + v[M21] * m[M11] + v[M22] * m[M21] + v[M23] * m[M31];
|
|
t[M22] = v[M20] * m[M02] + v[M21] * m[M12] + v[M22] * m[M22] + v[M23] * m[M32];
|
|
t[M23] = v[M20] * m[M03] + v[M21] * m[M13] + v[M22] * m[M23] + v[M23] * m[M33];
|
|
t[M30] = v[M30] * m[M00] + v[M31] * m[M10] + v[M32] * m[M20] + v[M33] * m[M30];
|
|
t[M31] = v[M30] * m[M01] + v[M31] * m[M11] + v[M32] * m[M21] + v[M33] * m[M31];
|
|
t[M32] = v[M30] * m[M02] + v[M31] * m[M12] + v[M32] * m[M22] + v[M33] * m[M32];
|
|
t[M33] = v[M30] * m[M03] + v[M31] * m[M13] + v[M32] * m[M23] + v[M33] * m[M33];
|
|
return this.set(this.temp);
|
|
}
|
|
multiplyLeft(matrix) {
|
|
let t = this.temp;
|
|
let v = this.values;
|
|
let m = matrix.values;
|
|
t[M00] = m[M00] * v[M00] + m[M01] * v[M10] + m[M02] * v[M20] + m[M03] * v[M30];
|
|
t[M01] = m[M00] * v[M01] + m[M01] * v[M11] + m[M02] * v[M21] + m[M03] * v[M31];
|
|
t[M02] = m[M00] * v[M02] + m[M01] * v[M12] + m[M02] * v[M22] + m[M03] * v[M32];
|
|
t[M03] = m[M00] * v[M03] + m[M01] * v[M13] + m[M02] * v[M23] + m[M03] * v[M33];
|
|
t[M10] = m[M10] * v[M00] + m[M11] * v[M10] + m[M12] * v[M20] + m[M13] * v[M30];
|
|
t[M11] = m[M10] * v[M01] + m[M11] * v[M11] + m[M12] * v[M21] + m[M13] * v[M31];
|
|
t[M12] = m[M10] * v[M02] + m[M11] * v[M12] + m[M12] * v[M22] + m[M13] * v[M32];
|
|
t[M13] = m[M10] * v[M03] + m[M11] * v[M13] + m[M12] * v[M23] + m[M13] * v[M33];
|
|
t[M20] = m[M20] * v[M00] + m[M21] * v[M10] + m[M22] * v[M20] + m[M23] * v[M30];
|
|
t[M21] = m[M20] * v[M01] + m[M21] * v[M11] + m[M22] * v[M21] + m[M23] * v[M31];
|
|
t[M22] = m[M20] * v[M02] + m[M21] * v[M12] + m[M22] * v[M22] + m[M23] * v[M32];
|
|
t[M23] = m[M20] * v[M03] + m[M21] * v[M13] + m[M22] * v[M23] + m[M23] * v[M33];
|
|
t[M30] = m[M30] * v[M00] + m[M31] * v[M10] + m[M32] * v[M20] + m[M33] * v[M30];
|
|
t[M31] = m[M30] * v[M01] + m[M31] * v[M11] + m[M32] * v[M21] + m[M33] * v[M31];
|
|
t[M32] = m[M30] * v[M02] + m[M31] * v[M12] + m[M32] * v[M22] + m[M33] * v[M32];
|
|
t[M33] = m[M30] * v[M03] + m[M31] * v[M13] + m[M32] * v[M23] + m[M33] * v[M33];
|
|
return this.set(this.temp);
|
|
}
|
|
lookAt(position, direction, up) {
|
|
let xAxis = _Matrix4.xAxis, yAxis = _Matrix4.yAxis, zAxis = _Matrix4.zAxis;
|
|
zAxis.setFrom(direction).normalize();
|
|
xAxis.setFrom(direction).normalize();
|
|
xAxis.cross(up).normalize();
|
|
yAxis.setFrom(xAxis).cross(zAxis).normalize();
|
|
this.identity();
|
|
let val = this.values;
|
|
val[M00] = xAxis.x;
|
|
val[M01] = xAxis.y;
|
|
val[M02] = xAxis.z;
|
|
val[M10] = yAxis.x;
|
|
val[M11] = yAxis.y;
|
|
val[M12] = yAxis.z;
|
|
val[M20] = -zAxis.x;
|
|
val[M21] = -zAxis.y;
|
|
val[M22] = -zAxis.z;
|
|
_Matrix4.tmpMatrix.identity();
|
|
_Matrix4.tmpMatrix.values[M03] = -position.x;
|
|
_Matrix4.tmpMatrix.values[M13] = -position.y;
|
|
_Matrix4.tmpMatrix.values[M23] = -position.z;
|
|
this.multiply(_Matrix4.tmpMatrix);
|
|
return this;
|
|
}
|
|
};
|
|
var Matrix42 = _Matrix4;
|
|
Matrix42.xAxis = new Vector3();
|
|
Matrix42.yAxis = new Vector3();
|
|
Matrix42.zAxis = new Vector3();
|
|
Matrix42.tmpMatrix = new _Matrix4();
|
|
|
|
// spine-webgl/src/Camera.ts
|
|
var OrthoCamera = class {
|
|
constructor(viewportWidth, viewportHeight) {
|
|
this.position = new Vector3(0, 0, 0);
|
|
this.direction = new Vector3(0, 0, -1);
|
|
this.up = new Vector3(0, 1, 0);
|
|
this.near = 0;
|
|
this.far = 100;
|
|
this.zoom = 1;
|
|
this.viewportWidth = 0;
|
|
this.viewportHeight = 0;
|
|
this.projectionView = new Matrix42();
|
|
this.inverseProjectionView = new Matrix42();
|
|
this.projection = new Matrix42();
|
|
this.view = new Matrix42();
|
|
this.viewportWidth = viewportWidth;
|
|
this.viewportHeight = viewportHeight;
|
|
this.update();
|
|
}
|
|
update() {
|
|
let projection = this.projection;
|
|
let view = this.view;
|
|
let projectionView = this.projectionView;
|
|
let inverseProjectionView = this.inverseProjectionView;
|
|
let zoom = this.zoom, viewportWidth = this.viewportWidth, viewportHeight = this.viewportHeight;
|
|
projection.ortho(
|
|
zoom * (-viewportWidth / 2),
|
|
zoom * (viewportWidth / 2),
|
|
zoom * (-viewportHeight / 2),
|
|
zoom * (viewportHeight / 2),
|
|
this.near,
|
|
this.far
|
|
);
|
|
view.lookAt(this.position, this.direction, this.up);
|
|
projectionView.set(projection.values);
|
|
projectionView.multiply(view);
|
|
inverseProjectionView.set(projectionView.values).invert();
|
|
}
|
|
screenToWorld(screenCoords, screenWidth, screenHeight) {
|
|
let x = screenCoords.x, y = screenHeight - screenCoords.y - 1;
|
|
screenCoords.x = 2 * x / screenWidth - 1;
|
|
screenCoords.y = 2 * y / screenHeight - 1;
|
|
screenCoords.z = 2 * screenCoords.z - 1;
|
|
screenCoords.project(this.inverseProjectionView);
|
|
return screenCoords;
|
|
}
|
|
worldToScreen(worldCoords, screenWidth, screenHeight) {
|
|
worldCoords.project(this.projectionView);
|
|
worldCoords.x = screenWidth * (worldCoords.x + 1) / 2;
|
|
worldCoords.y = screenHeight * (worldCoords.y + 1) / 2;
|
|
worldCoords.z = (worldCoords.z + 1) / 2;
|
|
return worldCoords;
|
|
}
|
|
setViewport(viewportWidth, viewportHeight) {
|
|
this.viewportWidth = viewportWidth;
|
|
this.viewportHeight = viewportHeight;
|
|
}
|
|
};
|
|
|
|
// spine-webgl/src/Input.ts
|
|
var Input = class {
|
|
constructor(element) {
|
|
this.mouseX = 0;
|
|
this.mouseY = 0;
|
|
this.buttonDown = false;
|
|
this.touch0 = null;
|
|
this.touch1 = null;
|
|
this.initialPinchDistance = 0;
|
|
this.listeners = new Array();
|
|
this.eventListeners = [];
|
|
this.element = element;
|
|
this.setupCallbacks(element);
|
|
}
|
|
setupCallbacks(element) {
|
|
let mouseDown = (ev) => {
|
|
if (ev instanceof MouseEvent) {
|
|
let rect = element.getBoundingClientRect();
|
|
this.mouseX = ev.clientX - rect.left;
|
|
;
|
|
this.mouseY = ev.clientY - rect.top;
|
|
this.buttonDown = true;
|
|
this.listeners.map((listener) => {
|
|
if (listener.down)
|
|
listener.down(this.mouseX, this.mouseY);
|
|
});
|
|
document.addEventListener("mousemove", mouseMove);
|
|
document.addEventListener("mouseup", mouseUp);
|
|
}
|
|
};
|
|
let mouseMove = (ev) => {
|
|
if (ev instanceof MouseEvent) {
|
|
let rect = element.getBoundingClientRect();
|
|
this.mouseX = ev.clientX - rect.left;
|
|
;
|
|
this.mouseY = ev.clientY - rect.top;
|
|
this.listeners.map((listener) => {
|
|
if (this.buttonDown) {
|
|
if (listener.dragged)
|
|
listener.dragged(this.mouseX, this.mouseY);
|
|
} else {
|
|
if (listener.moved)
|
|
listener.moved(this.mouseX, this.mouseY);
|
|
}
|
|
});
|
|
}
|
|
};
|
|
let mouseUp = (ev) => {
|
|
if (ev instanceof MouseEvent) {
|
|
let rect = element.getBoundingClientRect();
|
|
this.mouseX = ev.clientX - rect.left;
|
|
;
|
|
this.mouseY = ev.clientY - rect.top;
|
|
this.buttonDown = false;
|
|
this.listeners.map((listener) => {
|
|
if (listener.up)
|
|
listener.up(this.mouseX, this.mouseY);
|
|
});
|
|
document.removeEventListener("mousemove", mouseMove);
|
|
document.removeEventListener("mouseup", mouseUp);
|
|
}
|
|
};
|
|
let mouseWheel = (e) => {
|
|
e.preventDefault();
|
|
let deltaY = e.deltaY;
|
|
if (e.deltaMode == WheelEvent.DOM_DELTA_LINE)
|
|
deltaY *= 8;
|
|
if (e.deltaMode == WheelEvent.DOM_DELTA_PAGE)
|
|
deltaY *= 24;
|
|
this.listeners.map((listener) => {
|
|
if (listener.wheel)
|
|
listener.wheel(e.deltaY);
|
|
});
|
|
};
|
|
element.addEventListener("mousedown", mouseDown, true);
|
|
element.addEventListener("mousemove", mouseMove, true);
|
|
element.addEventListener("mouseup", mouseUp, true);
|
|
element.addEventListener("wheel", mouseWheel, true);
|
|
element.addEventListener("touchstart", (ev) => {
|
|
if (!this.touch0 || !this.touch1) {
|
|
var touches = ev.changedTouches;
|
|
let nativeTouch = touches.item(0);
|
|
if (!nativeTouch)
|
|
return;
|
|
let rect = element.getBoundingClientRect();
|
|
let x = nativeTouch.clientX - rect.left;
|
|
let y = nativeTouch.clientY - rect.top;
|
|
let touch = new Touch(nativeTouch.identifier, x, y);
|
|
this.mouseX = x;
|
|
this.mouseY = y;
|
|
this.buttonDown = true;
|
|
if (!this.touch0) {
|
|
this.touch0 = touch;
|
|
this.listeners.map((listener) => {
|
|
if (listener.down)
|
|
listener.down(touch.x, touch.y);
|
|
});
|
|
} else if (!this.touch1) {
|
|
this.touch1 = touch;
|
|
let dx = this.touch1.x - this.touch0.x;
|
|
let dy = this.touch1.x - this.touch0.x;
|
|
this.initialPinchDistance = Math.sqrt(dx * dx + dy * dy);
|
|
this.listeners.map((listener) => {
|
|
if (listener.zoom)
|
|
listener.zoom(this.initialPinchDistance, this.initialPinchDistance);
|
|
});
|
|
}
|
|
}
|
|
ev.preventDefault();
|
|
}, false);
|
|
element.addEventListener("touchmove", (ev) => {
|
|
if (this.touch0) {
|
|
var touches = ev.changedTouches;
|
|
let rect = element.getBoundingClientRect();
|
|
for (var i = 0; i < touches.length; i++) {
|
|
var nativeTouch = touches[i];
|
|
let x = nativeTouch.clientX - rect.left;
|
|
let y = nativeTouch.clientY - rect.top;
|
|
if (this.touch0.identifier === nativeTouch.identifier) {
|
|
this.touch0.x = this.mouseX = x;
|
|
this.touch0.y = this.mouseY = y;
|
|
this.listeners.map((listener) => {
|
|
if (listener.dragged)
|
|
listener.dragged(x, y);
|
|
});
|
|
}
|
|
if (this.touch1 && this.touch1.identifier === nativeTouch.identifier) {
|
|
this.touch1.x = this.mouseX = x;
|
|
this.touch1.y = this.mouseY = y;
|
|
}
|
|
}
|
|
if (this.touch0 && this.touch1) {
|
|
let dx = this.touch1.x - this.touch0.x;
|
|
let dy = this.touch1.x - this.touch0.x;
|
|
let distance = Math.sqrt(dx * dx + dy * dy);
|
|
this.listeners.map((listener) => {
|
|
if (listener.zoom)
|
|
listener.zoom(this.initialPinchDistance, distance);
|
|
});
|
|
}
|
|
}
|
|
ev.preventDefault();
|
|
}, false);
|
|
let touchEnd = (ev) => {
|
|
if (this.touch0) {
|
|
var touches = ev.changedTouches;
|
|
let rect = element.getBoundingClientRect();
|
|
for (var i = 0; i < touches.length; i++) {
|
|
var nativeTouch = touches[i];
|
|
let x = nativeTouch.clientX - rect.left;
|
|
let y = nativeTouch.clientY - rect.top;
|
|
if (this.touch0.identifier === nativeTouch.identifier) {
|
|
this.touch0 = null;
|
|
this.mouseX = x;
|
|
this.mouseY = y;
|
|
this.listeners.map((listener) => {
|
|
if (listener.up)
|
|
listener.up(x, y);
|
|
});
|
|
if (!this.touch1) {
|
|
this.buttonDown = false;
|
|
break;
|
|
} else {
|
|
this.touch0 = this.touch1;
|
|
this.touch1 = null;
|
|
this.mouseX = this.touch0.x;
|
|
this.mouseX = this.touch0.x;
|
|
this.buttonDown = true;
|
|
this.listeners.map((listener) => {
|
|
if (listener.down)
|
|
listener.down(this.touch0.x, this.touch0.y);
|
|
});
|
|
}
|
|
}
|
|
if (this.touch1 && this.touch1.identifier) {
|
|
this.touch1 = null;
|
|
}
|
|
}
|
|
}
|
|
ev.preventDefault();
|
|
};
|
|
element.addEventListener("touchend", touchEnd, false);
|
|
element.addEventListener("touchcancel", touchEnd);
|
|
}
|
|
addListener(listener) {
|
|
this.listeners.push(listener);
|
|
}
|
|
removeListener(listener) {
|
|
let idx = this.listeners.indexOf(listener);
|
|
if (idx > -1) {
|
|
this.listeners.splice(idx, 1);
|
|
}
|
|
}
|
|
};
|
|
var Touch = class {
|
|
constructor(identifier, x, y) {
|
|
this.identifier = identifier;
|
|
this.x = x;
|
|
this.y = y;
|
|
}
|
|
};
|
|
|
|
// spine-webgl/src/CameraController.ts
|
|
var CameraController = class {
|
|
constructor(canvas, camera) {
|
|
this.canvas = canvas;
|
|
this.camera = camera;
|
|
let cameraX = 0, cameraY = 0, cameraZoom = 0;
|
|
let mouseX = 0, mouseY = 0;
|
|
let lastX = 0, lastY = 0;
|
|
let initialZoom = 0;
|
|
new Input(canvas).addListener({
|
|
down: (x, y) => {
|
|
cameraX = camera.position.x;
|
|
cameraY = camera.position.y;
|
|
mouseX = lastX = x;
|
|
mouseY = lastY = y;
|
|
initialZoom = camera.zoom;
|
|
},
|
|
dragged: (x, y) => {
|
|
let deltaX = x - mouseX;
|
|
let deltaY = y - mouseY;
|
|
let originWorld = camera.screenToWorld(new Vector3(0, 0), canvas.clientWidth, canvas.clientHeight);
|
|
let deltaWorld = camera.screenToWorld(new Vector3(deltaX, deltaY), canvas.clientWidth, canvas.clientHeight).sub(originWorld);
|
|
camera.position.set(cameraX - deltaWorld.x, cameraY - deltaWorld.y, 0);
|
|
camera.update();
|
|
lastX = x;
|
|
lastY = y;
|
|
},
|
|
wheel: (delta) => {
|
|
let zoomAmount = delta / 200 * camera.zoom;
|
|
let newZoom = camera.zoom + zoomAmount;
|
|
if (newZoom > 0) {
|
|
let x = 0, y = 0;
|
|
if (delta < 0) {
|
|
x = lastX;
|
|
y = lastY;
|
|
} else {
|
|
let viewCenter = new Vector3(canvas.clientWidth / 2 + 15, canvas.clientHeight / 2);
|
|
let mouseToCenterX = lastX - viewCenter.x;
|
|
let mouseToCenterY = canvas.clientHeight - 1 - lastY - viewCenter.y;
|
|
x = viewCenter.x - mouseToCenterX;
|
|
y = canvas.clientHeight - 1 - viewCenter.y + mouseToCenterY;
|
|
}
|
|
let oldDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight);
|
|
camera.zoom = newZoom;
|
|
camera.update();
|
|
let newDistance = camera.screenToWorld(new Vector3(x, y), canvas.clientWidth, canvas.clientHeight);
|
|
camera.position.add(oldDistance.sub(newDistance));
|
|
camera.update();
|
|
}
|
|
},
|
|
zoom: (initialDistance, distance) => {
|
|
let newZoom = initialDistance / distance;
|
|
camera.zoom = initialZoom * newZoom;
|
|
},
|
|
up: (x, y) => {
|
|
lastX = x;
|
|
lastY = y;
|
|
},
|
|
moved: (x, y) => {
|
|
lastX = x;
|
|
lastY = y;
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
// spine-webgl/src/Shader.ts
|
|
var _Shader = class {
|
|
constructor(context, vertexShader, fragmentShader) {
|
|
this.vertexShader = vertexShader;
|
|
this.fragmentShader = fragmentShader;
|
|
this.vs = null;
|
|
this.fs = null;
|
|
this.program = null;
|
|
this.tmp2x2 = new Float32Array(2 * 2);
|
|
this.tmp3x3 = new Float32Array(3 * 3);
|
|
this.tmp4x4 = new Float32Array(4 * 4);
|
|
this.vsSource = vertexShader;
|
|
this.fsSource = fragmentShader;
|
|
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
|
|
this.context.addRestorable(this);
|
|
this.compile();
|
|
}
|
|
getProgram() {
|
|
return this.program;
|
|
}
|
|
getVertexShader() {
|
|
return this.vertexShader;
|
|
}
|
|
getFragmentShader() {
|
|
return this.fragmentShader;
|
|
}
|
|
getVertexShaderSource() {
|
|
return this.vsSource;
|
|
}
|
|
getFragmentSource() {
|
|
return this.fsSource;
|
|
}
|
|
compile() {
|
|
let gl = this.context.gl;
|
|
try {
|
|
this.vs = this.compileShader(gl.VERTEX_SHADER, this.vertexShader);
|
|
if (!this.vs)
|
|
throw new Error("Couldn't compile vertex shader.");
|
|
this.fs = this.compileShader(gl.FRAGMENT_SHADER, this.fragmentShader);
|
|
if (!this.fs)
|
|
throw new Error("Couldn#t compile fragment shader.");
|
|
this.program = this.compileProgram(this.vs, this.fs);
|
|
} catch (e) {
|
|
this.dispose();
|
|
throw e;
|
|
}
|
|
}
|
|
compileShader(type, source) {
|
|
let gl = this.context.gl;
|
|
let shader = gl.createShader(type);
|
|
if (!shader)
|
|
throw new Error("Couldn't create shader.");
|
|
gl.shaderSource(shader, source);
|
|
gl.compileShader(shader);
|
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
let error = "Couldn't compile shader: " + gl.getShaderInfoLog(shader);
|
|
gl.deleteShader(shader);
|
|
if (!gl.isContextLost())
|
|
throw new Error(error);
|
|
}
|
|
return shader;
|
|
}
|
|
compileProgram(vs, fs) {
|
|
let gl = this.context.gl;
|
|
let program = gl.createProgram();
|
|
if (!program)
|
|
throw new Error("Couldn't compile program.");
|
|
gl.attachShader(program, vs);
|
|
gl.attachShader(program, fs);
|
|
gl.linkProgram(program);
|
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
let error = "Couldn't compile shader program: " + gl.getProgramInfoLog(program);
|
|
gl.deleteProgram(program);
|
|
if (!gl.isContextLost())
|
|
throw new Error(error);
|
|
}
|
|
return program;
|
|
}
|
|
restore() {
|
|
this.compile();
|
|
}
|
|
bind() {
|
|
this.context.gl.useProgram(this.program);
|
|
}
|
|
unbind() {
|
|
this.context.gl.useProgram(null);
|
|
}
|
|
setUniformi(uniform, value) {
|
|
this.context.gl.uniform1i(this.getUniformLocation(uniform), value);
|
|
}
|
|
setUniformf(uniform, value) {
|
|
this.context.gl.uniform1f(this.getUniformLocation(uniform), value);
|
|
}
|
|
setUniform2f(uniform, value, value2) {
|
|
this.context.gl.uniform2f(this.getUniformLocation(uniform), value, value2);
|
|
}
|
|
setUniform3f(uniform, value, value2, value3) {
|
|
this.context.gl.uniform3f(this.getUniformLocation(uniform), value, value2, value3);
|
|
}
|
|
setUniform4f(uniform, value, value2, value3, value4) {
|
|
this.context.gl.uniform4f(this.getUniformLocation(uniform), value, value2, value3, value4);
|
|
}
|
|
setUniform2x2f(uniform, value) {
|
|
let gl = this.context.gl;
|
|
this.tmp2x2.set(value);
|
|
gl.uniformMatrix2fv(this.getUniformLocation(uniform), false, this.tmp2x2);
|
|
}
|
|
setUniform3x3f(uniform, value) {
|
|
let gl = this.context.gl;
|
|
this.tmp3x3.set(value);
|
|
gl.uniformMatrix3fv(this.getUniformLocation(uniform), false, this.tmp3x3);
|
|
}
|
|
setUniform4x4f(uniform, value) {
|
|
let gl = this.context.gl;
|
|
this.tmp4x4.set(value);
|
|
gl.uniformMatrix4fv(this.getUniformLocation(uniform), false, this.tmp4x4);
|
|
}
|
|
getUniformLocation(uniform) {
|
|
let gl = this.context.gl;
|
|
if (!this.program)
|
|
throw new Error("Shader not compiled.");
|
|
let location = gl.getUniformLocation(this.program, uniform);
|
|
if (!location && !gl.isContextLost())
|
|
throw new Error(`Couldn't find location for uniform ${uniform}`);
|
|
return location;
|
|
}
|
|
getAttributeLocation(attribute) {
|
|
let gl = this.context.gl;
|
|
if (!this.program)
|
|
throw new Error("Shader not compiled.");
|
|
let location = gl.getAttribLocation(this.program, attribute);
|
|
if (location == -1 && !gl.isContextLost())
|
|
throw new Error(`Couldn't find location for attribute ${attribute}`);
|
|
return location;
|
|
}
|
|
dispose() {
|
|
this.context.removeRestorable(this);
|
|
let gl = this.context.gl;
|
|
if (this.vs) {
|
|
gl.deleteShader(this.vs);
|
|
this.vs = null;
|
|
}
|
|
if (this.fs) {
|
|
gl.deleteShader(this.fs);
|
|
this.fs = null;
|
|
}
|
|
if (this.program) {
|
|
gl.deleteProgram(this.program);
|
|
this.program = null;
|
|
}
|
|
}
|
|
static newColoredTextured(context) {
|
|
let vs = `
|
|
attribute vec4 ${_Shader.POSITION};
|
|
attribute vec4 ${_Shader.COLOR};
|
|
attribute vec2 ${_Shader.TEXCOORDS};
|
|
uniform mat4 ${_Shader.MVP_MATRIX};
|
|
varying vec4 v_color;
|
|
varying vec2 v_texCoords;
|
|
|
|
void main () {
|
|
v_color = ${_Shader.COLOR};
|
|
v_texCoords = ${_Shader.TEXCOORDS};
|
|
gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION};
|
|
}
|
|
`;
|
|
let fs = `
|
|
#ifdef GL_ES
|
|
#define LOWP lowp
|
|
precision mediump float;
|
|
#else
|
|
#define LOWP
|
|
#endif
|
|
varying LOWP vec4 v_color;
|
|
varying vec2 v_texCoords;
|
|
uniform sampler2D u_texture;
|
|
|
|
void main () {
|
|
gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
|
|
}
|
|
`;
|
|
return new _Shader(context, vs, fs);
|
|
}
|
|
static newTwoColoredTextured(context) {
|
|
let vs = `
|
|
attribute vec4 ${_Shader.POSITION};
|
|
attribute vec4 ${_Shader.COLOR};
|
|
attribute vec4 ${_Shader.COLOR2};
|
|
attribute vec2 ${_Shader.TEXCOORDS};
|
|
uniform mat4 ${_Shader.MVP_MATRIX};
|
|
varying vec4 v_light;
|
|
varying vec4 v_dark;
|
|
varying vec2 v_texCoords;
|
|
|
|
void main () {
|
|
v_light = ${_Shader.COLOR};
|
|
v_dark = ${_Shader.COLOR2};
|
|
v_texCoords = ${_Shader.TEXCOORDS};
|
|
gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION};
|
|
}
|
|
`;
|
|
let fs = `
|
|
#ifdef GL_ES
|
|
#define LOWP lowp
|
|
precision mediump float;
|
|
#else
|
|
#define LOWP
|
|
#endif
|
|
varying LOWP vec4 v_light;
|
|
varying LOWP vec4 v_dark;
|
|
varying vec2 v_texCoords;
|
|
uniform sampler2D u_texture;
|
|
|
|
void main () {
|
|
vec4 texColor = texture2D(u_texture, v_texCoords);
|
|
gl_FragColor.a = texColor.a * v_light.a;
|
|
gl_FragColor.rgb = ((texColor.a - 1.0) * v_dark.a + 1.0 - texColor.rgb) * v_dark.rgb + texColor.rgb * v_light.rgb;
|
|
}
|
|
`;
|
|
return new _Shader(context, vs, fs);
|
|
}
|
|
static newColored(context) {
|
|
let vs = `
|
|
attribute vec4 ${_Shader.POSITION};
|
|
attribute vec4 ${_Shader.COLOR};
|
|
uniform mat4 ${_Shader.MVP_MATRIX};
|
|
varying vec4 v_color;
|
|
|
|
void main () {
|
|
v_color = ${_Shader.COLOR};
|
|
gl_Position = ${_Shader.MVP_MATRIX} * ${_Shader.POSITION};
|
|
}
|
|
`;
|
|
let fs = `
|
|
#ifdef GL_ES
|
|
#define LOWP lowp
|
|
precision mediump float;
|
|
#else
|
|
#define LOWP
|
|
#endif
|
|
varying LOWP vec4 v_color;
|
|
|
|
void main () {
|
|
gl_FragColor = v_color;
|
|
}
|
|
`;
|
|
return new _Shader(context, vs, fs);
|
|
}
|
|
};
|
|
var Shader = _Shader;
|
|
Shader.MVP_MATRIX = "u_projTrans";
|
|
Shader.POSITION = "a_position";
|
|
Shader.COLOR = "a_color";
|
|
Shader.COLOR2 = "a_color2";
|
|
Shader.TEXCOORDS = "a_texCoords";
|
|
Shader.SAMPLER = "u_texture";
|
|
|
|
// spine-webgl/src/Mesh.ts
|
|
var Mesh = class {
|
|
constructor(context, attributes, maxVertices, maxIndices) {
|
|
this.attributes = attributes;
|
|
this.verticesBuffer = null;
|
|
this.verticesLength = 0;
|
|
this.dirtyVertices = false;
|
|
this.indicesBuffer = null;
|
|
this.indicesLength = 0;
|
|
this.dirtyIndices = false;
|
|
this.elementsPerVertex = 0;
|
|
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
|
|
this.elementsPerVertex = 0;
|
|
for (let i = 0; i < attributes.length; i++) {
|
|
this.elementsPerVertex += attributes[i].numElements;
|
|
}
|
|
this.vertices = new Float32Array(maxVertices * this.elementsPerVertex);
|
|
this.indices = new Uint16Array(maxIndices);
|
|
this.context.addRestorable(this);
|
|
}
|
|
getAttributes() {
|
|
return this.attributes;
|
|
}
|
|
maxVertices() {
|
|
return this.vertices.length / this.elementsPerVertex;
|
|
}
|
|
numVertices() {
|
|
return this.verticesLength / this.elementsPerVertex;
|
|
}
|
|
setVerticesLength(length) {
|
|
this.dirtyVertices = true;
|
|
this.verticesLength = length;
|
|
}
|
|
getVertices() {
|
|
return this.vertices;
|
|
}
|
|
maxIndices() {
|
|
return this.indices.length;
|
|
}
|
|
numIndices() {
|
|
return this.indicesLength;
|
|
}
|
|
setIndicesLength(length) {
|
|
this.dirtyIndices = true;
|
|
this.indicesLength = length;
|
|
}
|
|
getIndices() {
|
|
return this.indices;
|
|
}
|
|
getVertexSizeInFloats() {
|
|
let size = 0;
|
|
for (var i = 0; i < this.attributes.length; i++) {
|
|
let attribute = this.attributes[i];
|
|
size += attribute.numElements;
|
|
}
|
|
return size;
|
|
}
|
|
setVertices(vertices) {
|
|
this.dirtyVertices = true;
|
|
if (vertices.length > this.vertices.length)
|
|
throw Error("Mesh can't store more than " + this.maxVertices() + " vertices");
|
|
this.vertices.set(vertices, 0);
|
|
this.verticesLength = vertices.length;
|
|
}
|
|
setIndices(indices) {
|
|
this.dirtyIndices = true;
|
|
if (indices.length > this.indices.length)
|
|
throw Error("Mesh can't store more than " + this.maxIndices() + " indices");
|
|
this.indices.set(indices, 0);
|
|
this.indicesLength = indices.length;
|
|
}
|
|
draw(shader, primitiveType) {
|
|
this.drawWithOffset(shader, primitiveType, 0, this.indicesLength > 0 ? this.indicesLength : this.verticesLength / this.elementsPerVertex);
|
|
}
|
|
drawWithOffset(shader, primitiveType, offset, count) {
|
|
let gl = this.context.gl;
|
|
if (this.dirtyVertices || this.dirtyIndices)
|
|
this.update();
|
|
this.bind(shader);
|
|
if (this.indicesLength > 0) {
|
|
gl.drawElements(primitiveType, count, gl.UNSIGNED_SHORT, offset * 2);
|
|
} else {
|
|
gl.drawArrays(primitiveType, offset, count);
|
|
}
|
|
this.unbind(shader);
|
|
}
|
|
bind(shader) {
|
|
let gl = this.context.gl;
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
|
|
let offset = 0;
|
|
for (let i = 0; i < this.attributes.length; i++) {
|
|
let attrib = this.attributes[i];
|
|
let location = shader.getAttributeLocation(attrib.name);
|
|
gl.enableVertexAttribArray(location);
|
|
gl.vertexAttribPointer(location, attrib.numElements, gl.FLOAT, false, this.elementsPerVertex * 4, offset * 4);
|
|
offset += attrib.numElements;
|
|
}
|
|
if (this.indicesLength > 0)
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
|
|
}
|
|
unbind(shader) {
|
|
let gl = this.context.gl;
|
|
for (let i = 0; i < this.attributes.length; i++) {
|
|
let attrib = this.attributes[i];
|
|
let location = shader.getAttributeLocation(attrib.name);
|
|
gl.disableVertexAttribArray(location);
|
|
}
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
if (this.indicesLength > 0)
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, null);
|
|
}
|
|
update() {
|
|
let gl = this.context.gl;
|
|
if (this.dirtyVertices) {
|
|
if (!this.verticesBuffer) {
|
|
this.verticesBuffer = gl.createBuffer();
|
|
}
|
|
gl.bindBuffer(gl.ARRAY_BUFFER, this.verticesBuffer);
|
|
gl.bufferData(gl.ARRAY_BUFFER, this.vertices.subarray(0, this.verticesLength), gl.DYNAMIC_DRAW);
|
|
this.dirtyVertices = false;
|
|
}
|
|
if (this.dirtyIndices) {
|
|
if (!this.indicesBuffer) {
|
|
this.indicesBuffer = gl.createBuffer();
|
|
}
|
|
gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.indicesBuffer);
|
|
gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, this.indices.subarray(0, this.indicesLength), gl.DYNAMIC_DRAW);
|
|
this.dirtyIndices = false;
|
|
}
|
|
}
|
|
restore() {
|
|
this.verticesBuffer = null;
|
|
this.indicesBuffer = null;
|
|
this.update();
|
|
}
|
|
dispose() {
|
|
this.context.removeRestorable(this);
|
|
let gl = this.context.gl;
|
|
gl.deleteBuffer(this.verticesBuffer);
|
|
gl.deleteBuffer(this.indicesBuffer);
|
|
}
|
|
};
|
|
var VertexAttribute = class {
|
|
constructor(name, type, numElements) {
|
|
this.name = name;
|
|
this.type = type;
|
|
this.numElements = numElements;
|
|
}
|
|
};
|
|
var Position2Attribute = class extends VertexAttribute {
|
|
constructor() {
|
|
super(Shader.POSITION, VertexAttributeType.Float, 2);
|
|
}
|
|
};
|
|
var Position3Attribute = class extends VertexAttribute {
|
|
constructor() {
|
|
super(Shader.POSITION, VertexAttributeType.Float, 3);
|
|
}
|
|
};
|
|
var TexCoordAttribute = class extends VertexAttribute {
|
|
constructor(unit = 0) {
|
|
super(Shader.TEXCOORDS + (unit == 0 ? "" : unit), VertexAttributeType.Float, 2);
|
|
}
|
|
};
|
|
var ColorAttribute = class extends VertexAttribute {
|
|
constructor() {
|
|
super(Shader.COLOR, VertexAttributeType.Float, 4);
|
|
}
|
|
};
|
|
var Color2Attribute = class extends VertexAttribute {
|
|
constructor() {
|
|
super(Shader.COLOR2, VertexAttributeType.Float, 4);
|
|
}
|
|
};
|
|
var VertexAttributeType = /* @__PURE__ */ ((VertexAttributeType2) => {
|
|
VertexAttributeType2[VertexAttributeType2["Float"] = 0] = "Float";
|
|
return VertexAttributeType2;
|
|
})(VertexAttributeType || {});
|
|
|
|
// spine-webgl/src/PolygonBatcher.ts
|
|
var _PolygonBatcher = class {
|
|
constructor(context, twoColorTint = true, maxVertices = 10920) {
|
|
this.drawCalls = 0;
|
|
this.isDrawing = false;
|
|
this.shader = null;
|
|
this.lastTexture = null;
|
|
this.verticesLength = 0;
|
|
this.indicesLength = 0;
|
|
this.cullWasEnabled = false;
|
|
if (maxVertices > 10920)
|
|
throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
|
|
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
|
|
let attributes = twoColorTint ? [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute(), new Color2Attribute()] : [new Position2Attribute(), new ColorAttribute(), new TexCoordAttribute()];
|
|
this.mesh = new Mesh(context, attributes, maxVertices, maxVertices * 3);
|
|
let gl = this.context.gl;
|
|
this.srcColorBlend = gl.SRC_ALPHA;
|
|
this.srcAlphaBlend = gl.ONE;
|
|
this.dstBlend = gl.ONE_MINUS_SRC_ALPHA;
|
|
}
|
|
begin(shader) {
|
|
if (this.isDrawing)
|
|
throw new Error("PolygonBatch is already drawing. Call PolygonBatch.end() before calling PolygonBatch.begin()");
|
|
this.drawCalls = 0;
|
|
this.shader = shader;
|
|
this.lastTexture = null;
|
|
this.isDrawing = true;
|
|
let gl = this.context.gl;
|
|
gl.enable(gl.BLEND);
|
|
gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);
|
|
this.cullWasEnabled = gl.isEnabled(gl.CULL_FACE);
|
|
if (this.cullWasEnabled)
|
|
gl.disable(gl.CULL_FACE);
|
|
}
|
|
setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) {
|
|
if (this.srcColorBlend == srcColorBlend && this.srcAlphaBlend == srcAlphaBlend && this.dstBlend == dstBlend)
|
|
return;
|
|
this.srcColorBlend = srcColorBlend;
|
|
this.srcAlphaBlend = srcAlphaBlend;
|
|
this.dstBlend = dstBlend;
|
|
if (this.isDrawing) {
|
|
this.flush();
|
|
let gl = this.context.gl;
|
|
gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
|
|
}
|
|
}
|
|
draw(texture, vertices, indices) {
|
|
if (texture != this.lastTexture) {
|
|
this.flush();
|
|
this.lastTexture = texture;
|
|
} else if (this.verticesLength + vertices.length > this.mesh.getVertices().length || this.indicesLength + indices.length > this.mesh.getIndices().length) {
|
|
this.flush();
|
|
}
|
|
let indexStart = this.mesh.numVertices();
|
|
this.mesh.getVertices().set(vertices, this.verticesLength);
|
|
this.verticesLength += vertices.length;
|
|
this.mesh.setVerticesLength(this.verticesLength);
|
|
let indicesArray = this.mesh.getIndices();
|
|
for (let i = this.indicesLength, j = 0; j < indices.length; i++, j++)
|
|
indicesArray[i] = indices[j] + indexStart;
|
|
this.indicesLength += indices.length;
|
|
this.mesh.setIndicesLength(this.indicesLength);
|
|
}
|
|
flush() {
|
|
if (this.verticesLength == 0)
|
|
return;
|
|
if (!this.lastTexture)
|
|
throw new Error("No texture set.");
|
|
if (!this.shader)
|
|
throw new Error("No shader set.");
|
|
this.lastTexture.bind();
|
|
this.mesh.draw(this.shader, this.context.gl.TRIANGLES);
|
|
this.verticesLength = 0;
|
|
this.indicesLength = 0;
|
|
this.mesh.setVerticesLength(0);
|
|
this.mesh.setIndicesLength(0);
|
|
this.drawCalls++;
|
|
_PolygonBatcher.globalDrawCalls++;
|
|
}
|
|
end() {
|
|
if (!this.isDrawing)
|
|
throw new Error("PolygonBatch is not drawing. Call PolygonBatch.begin() before calling PolygonBatch.end()");
|
|
if (this.verticesLength > 0 || this.indicesLength > 0)
|
|
this.flush();
|
|
this.shader = null;
|
|
this.lastTexture = null;
|
|
this.isDrawing = false;
|
|
let gl = this.context.gl;
|
|
gl.disable(gl.BLEND);
|
|
if (this.cullWasEnabled)
|
|
gl.enable(gl.CULL_FACE);
|
|
}
|
|
getDrawCalls() {
|
|
return this.drawCalls;
|
|
}
|
|
static getAndResetGlobalDrawCalls() {
|
|
let result = _PolygonBatcher.globalDrawCalls;
|
|
_PolygonBatcher.globalDrawCalls = 0;
|
|
return result;
|
|
}
|
|
dispose() {
|
|
this.mesh.dispose();
|
|
}
|
|
};
|
|
var PolygonBatcher = _PolygonBatcher;
|
|
PolygonBatcher.globalDrawCalls = 0;
|
|
|
|
// spine-webgl/src/ShapeRenderer.ts
|
|
var ShapeRenderer = class {
|
|
constructor(context, maxVertices = 10920) {
|
|
this.isDrawing = false;
|
|
this.shapeType = ShapeType.Filled;
|
|
this.color = new Color(1, 1, 1, 1);
|
|
this.shader = null;
|
|
this.vertexIndex = 0;
|
|
this.tmp = new Vector2();
|
|
if (maxVertices > 10920)
|
|
throw new Error("Can't have more than 10920 triangles per batch: " + maxVertices);
|
|
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
|
|
this.mesh = new Mesh(context, [new Position2Attribute(), new ColorAttribute()], maxVertices, 0);
|
|
let gl = this.context.gl;
|
|
this.srcColorBlend = gl.SRC_ALPHA;
|
|
this.srcAlphaBlend = gl.ONE;
|
|
this.dstBlend = gl.ONE_MINUS_SRC_ALPHA;
|
|
}
|
|
begin(shader) {
|
|
if (this.isDrawing)
|
|
throw new Error("ShapeRenderer.begin() has already been called");
|
|
this.shader = shader;
|
|
this.vertexIndex = 0;
|
|
this.isDrawing = true;
|
|
let gl = this.context.gl;
|
|
gl.enable(gl.BLEND);
|
|
gl.blendFuncSeparate(this.srcColorBlend, this.dstBlend, this.srcAlphaBlend, this.dstBlend);
|
|
}
|
|
setBlendMode(srcColorBlend, srcAlphaBlend, dstBlend) {
|
|
this.srcColorBlend = srcColorBlend;
|
|
this.srcAlphaBlend = srcAlphaBlend;
|
|
this.dstBlend = dstBlend;
|
|
if (this.isDrawing) {
|
|
this.flush();
|
|
let gl = this.context.gl;
|
|
gl.blendFuncSeparate(srcColorBlend, dstBlend, srcAlphaBlend, dstBlend);
|
|
}
|
|
}
|
|
setColor(color) {
|
|
this.color.setFromColor(color);
|
|
}
|
|
setColorWith(r, g, b, a) {
|
|
this.color.set(r, g, b, a);
|
|
}
|
|
point(x, y, color) {
|
|
this.check(ShapeType.Point, 1);
|
|
if (!color)
|
|
color = this.color;
|
|
this.vertex(x, y, color);
|
|
}
|
|
line(x, y, x2, y2, color) {
|
|
this.check(ShapeType.Line, 2);
|
|
let vertices = this.mesh.getVertices();
|
|
let idx = this.vertexIndex;
|
|
if (!color)
|
|
color = this.color;
|
|
this.vertex(x, y, color);
|
|
this.vertex(x2, y2, color);
|
|
}
|
|
triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) {
|
|
this.check(filled ? ShapeType.Filled : ShapeType.Line, 3);
|
|
let vertices = this.mesh.getVertices();
|
|
let idx = this.vertexIndex;
|
|
if (!color)
|
|
color = this.color;
|
|
if (!color2)
|
|
color2 = this.color;
|
|
if (!color3)
|
|
color3 = this.color;
|
|
if (filled) {
|
|
this.vertex(x, y, color);
|
|
this.vertex(x2, y2, color2);
|
|
this.vertex(x3, y3, color3);
|
|
} else {
|
|
this.vertex(x, y, color);
|
|
this.vertex(x2, y2, color2);
|
|
this.vertex(x2, y2, color);
|
|
this.vertex(x3, y3, color2);
|
|
this.vertex(x3, y3, color);
|
|
this.vertex(x, y, color2);
|
|
}
|
|
}
|
|
quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) {
|
|
this.check(filled ? ShapeType.Filled : ShapeType.Line, 3);
|
|
let vertices = this.mesh.getVertices();
|
|
let idx = this.vertexIndex;
|
|
if (!color)
|
|
color = this.color;
|
|
if (!color2)
|
|
color2 = this.color;
|
|
if (!color3)
|
|
color3 = this.color;
|
|
if (!color4)
|
|
color4 = this.color;
|
|
if (filled) {
|
|
this.vertex(x, y, color);
|
|
this.vertex(x2, y2, color2);
|
|
this.vertex(x3, y3, color3);
|
|
this.vertex(x3, y3, color3);
|
|
this.vertex(x4, y4, color4);
|
|
this.vertex(x, y, color);
|
|
} else {
|
|
this.vertex(x, y, color);
|
|
this.vertex(x2, y2, color2);
|
|
this.vertex(x2, y2, color2);
|
|
this.vertex(x3, y3, color3);
|
|
this.vertex(x3, y3, color3);
|
|
this.vertex(x4, y4, color4);
|
|
this.vertex(x4, y4, color4);
|
|
this.vertex(x, y, color);
|
|
}
|
|
}
|
|
rect(filled, x, y, width, height, color) {
|
|
this.quad(filled, x, y, x + width, y, x + width, y + height, x, y + height, color, color, color, color);
|
|
}
|
|
rectLine(filled, x1, y1, x2, y2, width, color) {
|
|
this.check(filled ? ShapeType.Filled : ShapeType.Line, 8);
|
|
if (!color)
|
|
color = this.color;
|
|
let t = this.tmp.set(y2 - y1, x1 - x2);
|
|
t.normalize();
|
|
width *= 0.5;
|
|
let tx = t.x * width;
|
|
let ty = t.y * width;
|
|
if (!filled) {
|
|
this.vertex(x1 + tx, y1 + ty, color);
|
|
this.vertex(x1 - tx, y1 - ty, color);
|
|
this.vertex(x2 + tx, y2 + ty, color);
|
|
this.vertex(x2 - tx, y2 - ty, color);
|
|
this.vertex(x2 + tx, y2 + ty, color);
|
|
this.vertex(x1 + tx, y1 + ty, color);
|
|
this.vertex(x2 - tx, y2 - ty, color);
|
|
this.vertex(x1 - tx, y1 - ty, color);
|
|
} else {
|
|
this.vertex(x1 + tx, y1 + ty, color);
|
|
this.vertex(x1 - tx, y1 - ty, color);
|
|
this.vertex(x2 + tx, y2 + ty, color);
|
|
this.vertex(x2 - tx, y2 - ty, color);
|
|
this.vertex(x2 + tx, y2 + ty, color);
|
|
this.vertex(x1 - tx, y1 - ty, color);
|
|
}
|
|
}
|
|
x(x, y, size) {
|
|
this.line(x - size, y - size, x + size, y + size);
|
|
this.line(x - size, y + size, x + size, y - size);
|
|
}
|
|
polygon(polygonVertices, offset, count, color) {
|
|
if (count < 3)
|
|
throw new Error("Polygon must contain at least 3 vertices");
|
|
this.check(ShapeType.Line, count * 2);
|
|
if (!color)
|
|
color = this.color;
|
|
let vertices = this.mesh.getVertices();
|
|
let idx = this.vertexIndex;
|
|
offset <<= 1;
|
|
count <<= 1;
|
|
let firstX = polygonVertices[offset];
|
|
let firstY = polygonVertices[offset + 1];
|
|
let last = offset + count;
|
|
for (let i = offset, n = offset + count - 2; i < n; i += 2) {
|
|
let x1 = polygonVertices[i];
|
|
let y1 = polygonVertices[i + 1];
|
|
let x2 = 0;
|
|
let y2 = 0;
|
|
if (i + 2 >= last) {
|
|
x2 = firstX;
|
|
y2 = firstY;
|
|
} else {
|
|
x2 = polygonVertices[i + 2];
|
|
y2 = polygonVertices[i + 3];
|
|
}
|
|
this.vertex(x1, y1, color);
|
|
this.vertex(x2, y2, color);
|
|
}
|
|
}
|
|
circle(filled, x, y, radius, color, segments = 0) {
|
|
if (segments == 0)
|
|
segments = Math.max(1, 6 * MathUtils.cbrt(radius) | 0);
|
|
if (segments <= 0)
|
|
throw new Error("segments must be > 0.");
|
|
if (!color)
|
|
color = this.color;
|
|
let angle = 2 * MathUtils.PI / segments;
|
|
let cos = Math.cos(angle);
|
|
let sin = Math.sin(angle);
|
|
let cx = radius, cy = 0;
|
|
if (!filled) {
|
|
this.check(ShapeType.Line, segments * 2 + 2);
|
|
for (let i = 0; i < segments; i++) {
|
|
this.vertex(x + cx, y + cy, color);
|
|
let temp2 = cx;
|
|
cx = cos * cx - sin * cy;
|
|
cy = sin * temp2 + cos * cy;
|
|
this.vertex(x + cx, y + cy, color);
|
|
}
|
|
this.vertex(x + cx, y + cy, color);
|
|
} else {
|
|
this.check(ShapeType.Filled, segments * 3 + 3);
|
|
segments--;
|
|
for (let i = 0; i < segments; i++) {
|
|
this.vertex(x, y, color);
|
|
this.vertex(x + cx, y + cy, color);
|
|
let temp2 = cx;
|
|
cx = cos * cx - sin * cy;
|
|
cy = sin * temp2 + cos * cy;
|
|
this.vertex(x + cx, y + cy, color);
|
|
}
|
|
this.vertex(x, y, color);
|
|
this.vertex(x + cx, y + cy, color);
|
|
}
|
|
let temp = cx;
|
|
cx = radius;
|
|
cy = 0;
|
|
this.vertex(x + cx, y + cy, color);
|
|
}
|
|
curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) {
|
|
this.check(ShapeType.Line, segments * 2 + 2);
|
|
if (!color)
|
|
color = this.color;
|
|
let subdiv_step = 1 / segments;
|
|
let subdiv_step2 = subdiv_step * subdiv_step;
|
|
let subdiv_step3 = subdiv_step * subdiv_step * subdiv_step;
|
|
let pre1 = 3 * subdiv_step;
|
|
let pre2 = 3 * subdiv_step2;
|
|
let pre4 = 6 * subdiv_step2;
|
|
let pre5 = 6 * subdiv_step3;
|
|
let tmp1x = x1 - cx1 * 2 + cx2;
|
|
let tmp1y = y1 - cy1 * 2 + cy2;
|
|
let tmp2x = (cx1 - cx2) * 3 - x1 + x2;
|
|
let tmp2y = (cy1 - cy2) * 3 - y1 + y2;
|
|
let fx = x1;
|
|
let fy = y1;
|
|
let dfx = (cx1 - x1) * pre1 + tmp1x * pre2 + tmp2x * subdiv_step3;
|
|
let dfy = (cy1 - y1) * pre1 + tmp1y * pre2 + tmp2y * subdiv_step3;
|
|
let ddfx = tmp1x * pre4 + tmp2x * pre5;
|
|
let ddfy = tmp1y * pre4 + tmp2y * pre5;
|
|
let dddfx = tmp2x * pre5;
|
|
let dddfy = tmp2y * pre5;
|
|
while (segments-- > 0) {
|
|
this.vertex(fx, fy, color);
|
|
fx += dfx;
|
|
fy += dfy;
|
|
dfx += ddfx;
|
|
dfy += ddfy;
|
|
ddfx += dddfx;
|
|
ddfy += dddfy;
|
|
this.vertex(fx, fy, color);
|
|
}
|
|
this.vertex(fx, fy, color);
|
|
this.vertex(x2, y2, color);
|
|
}
|
|
vertex(x, y, color) {
|
|
let idx = this.vertexIndex;
|
|
let vertices = this.mesh.getVertices();
|
|
vertices[idx++] = x;
|
|
vertices[idx++] = y;
|
|
vertices[idx++] = color.r;
|
|
vertices[idx++] = color.g;
|
|
vertices[idx++] = color.b;
|
|
vertices[idx++] = color.a;
|
|
this.vertexIndex = idx;
|
|
}
|
|
end() {
|
|
if (!this.isDrawing)
|
|
throw new Error("ShapeRenderer.begin() has not been called");
|
|
this.flush();
|
|
let gl = this.context.gl;
|
|
gl.disable(gl.BLEND);
|
|
this.isDrawing = false;
|
|
}
|
|
flush() {
|
|
if (this.vertexIndex == 0)
|
|
return;
|
|
if (!this.shader)
|
|
throw new Error("No shader set.");
|
|
this.mesh.setVerticesLength(this.vertexIndex);
|
|
this.mesh.draw(this.shader, this.shapeType);
|
|
this.vertexIndex = 0;
|
|
}
|
|
check(shapeType, numVertices) {
|
|
if (!this.isDrawing)
|
|
throw new Error("ShapeRenderer.begin() has not been called");
|
|
if (this.shapeType == shapeType) {
|
|
if (this.mesh.maxVertices() - this.mesh.numVertices() < numVertices)
|
|
this.flush();
|
|
else
|
|
return;
|
|
} else {
|
|
this.flush();
|
|
this.shapeType = shapeType;
|
|
}
|
|
}
|
|
dispose() {
|
|
this.mesh.dispose();
|
|
}
|
|
};
|
|
var ShapeType = /* @__PURE__ */ ((ShapeType2) => {
|
|
ShapeType2[ShapeType2["Point"] = 0] = "Point";
|
|
ShapeType2[ShapeType2["Line"] = 1] = "Line";
|
|
ShapeType2[ShapeType2["Filled"] = 4] = "Filled";
|
|
return ShapeType2;
|
|
})(ShapeType || {});
|
|
|
|
// spine-webgl/src/SkeletonDebugRenderer.ts
|
|
var _SkeletonDebugRenderer = class {
|
|
constructor(context) {
|
|
this.boneLineColor = new Color(1, 0, 0, 1);
|
|
this.boneOriginColor = new Color(0, 1, 0, 1);
|
|
this.attachmentLineColor = new Color(0, 0, 1, 0.5);
|
|
this.triangleLineColor = new Color(1, 0.64, 0, 0.5);
|
|
this.pathColor = new Color().setFromString("FF7F00");
|
|
this.clipColor = new Color(0.8, 0, 0, 2);
|
|
this.aabbColor = new Color(0, 1, 0, 0.5);
|
|
this.drawBones = true;
|
|
this.drawRegionAttachments = true;
|
|
this.drawBoundingBoxes = true;
|
|
this.drawMeshHull = true;
|
|
this.drawMeshTriangles = true;
|
|
this.drawPaths = true;
|
|
this.drawSkeletonXY = false;
|
|
this.drawClipping = true;
|
|
this.premultipliedAlpha = false;
|
|
this.scale = 1;
|
|
this.boneWidth = 2;
|
|
this.bounds = new SkeletonBounds();
|
|
this.temp = new Array();
|
|
this.vertices = Utils.newFloatArray(2 * 1024);
|
|
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
|
|
}
|
|
draw(shapes, skeleton, ignoredBones) {
|
|
let skeletonX = skeleton.x;
|
|
let skeletonY = skeleton.y;
|
|
let gl = this.context.gl;
|
|
let srcFunc = this.premultipliedAlpha ? gl.ONE : gl.SRC_ALPHA;
|
|
shapes.setBlendMode(srcFunc, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
let bones = skeleton.bones;
|
|
if (this.drawBones) {
|
|
shapes.setColor(this.boneLineColor);
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1)
|
|
continue;
|
|
if (!bone.parent)
|
|
continue;
|
|
let x = bone.data.length * bone.a + bone.worldX;
|
|
let y = bone.data.length * bone.c + bone.worldY;
|
|
shapes.rectLine(true, bone.worldX, bone.worldY, x, y, this.boneWidth * this.scale);
|
|
}
|
|
if (this.drawSkeletonXY)
|
|
shapes.x(skeletonX, skeletonY, 4 * this.scale);
|
|
}
|
|
if (this.drawRegionAttachments) {
|
|
shapes.setColor(this.attachmentLineColor);
|
|
let slots = skeleton.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
let attachment = slot.getAttachment();
|
|
if (attachment instanceof RegionAttachment) {
|
|
let regionAttachment = attachment;
|
|
let vertices = this.vertices;
|
|
regionAttachment.computeWorldVertices(slot, vertices, 0, 2);
|
|
shapes.line(vertices[0], vertices[1], vertices[2], vertices[3]);
|
|
shapes.line(vertices[2], vertices[3], vertices[4], vertices[5]);
|
|
shapes.line(vertices[4], vertices[5], vertices[6], vertices[7]);
|
|
shapes.line(vertices[6], vertices[7], vertices[0], vertices[1]);
|
|
}
|
|
}
|
|
}
|
|
if (this.drawMeshHull || this.drawMeshTriangles) {
|
|
let slots = skeleton.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (!slot.bone.active)
|
|
continue;
|
|
let attachment = slot.getAttachment();
|
|
if (!(attachment instanceof MeshAttachment))
|
|
continue;
|
|
let mesh = attachment;
|
|
let vertices = this.vertices;
|
|
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, vertices, 0, 2);
|
|
let triangles = mesh.triangles;
|
|
let hullLength = mesh.hullLength;
|
|
if (this.drawMeshTriangles) {
|
|
shapes.setColor(this.triangleLineColor);
|
|
for (let ii = 0, nn = triangles.length; ii < nn; ii += 3) {
|
|
let v1 = triangles[ii] * 2, v2 = triangles[ii + 1] * 2, v3 = triangles[ii + 2] * 2;
|
|
shapes.triangle(
|
|
false,
|
|
vertices[v1],
|
|
vertices[v1 + 1],
|
|
vertices[v2],
|
|
vertices[v2 + 1],
|
|
vertices[v3],
|
|
vertices[v3 + 1]
|
|
);
|
|
}
|
|
}
|
|
if (this.drawMeshHull && hullLength > 0) {
|
|
shapes.setColor(this.attachmentLineColor);
|
|
hullLength = (hullLength >> 1) * 2;
|
|
let lastX = vertices[hullLength - 2], lastY = vertices[hullLength - 1];
|
|
for (let ii = 0, nn = hullLength; ii < nn; ii += 2) {
|
|
let x = vertices[ii], y = vertices[ii + 1];
|
|
shapes.line(x, y, lastX, lastY);
|
|
lastX = x;
|
|
lastY = y;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (this.drawBoundingBoxes) {
|
|
let bounds = this.bounds;
|
|
bounds.update(skeleton, true);
|
|
shapes.setColor(this.aabbColor);
|
|
shapes.rect(false, bounds.minX, bounds.minY, bounds.getWidth(), bounds.getHeight());
|
|
let polygons = bounds.polygons;
|
|
let boxes = bounds.boundingBoxes;
|
|
for (let i = 0, n = polygons.length; i < n; i++) {
|
|
let polygon = polygons[i];
|
|
shapes.setColor(boxes[i].color);
|
|
shapes.polygon(polygon, 0, polygon.length);
|
|
}
|
|
}
|
|
if (this.drawPaths) {
|
|
let slots = skeleton.slots;
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (!slot.bone.active)
|
|
continue;
|
|
let attachment = slot.getAttachment();
|
|
if (!(attachment instanceof PathAttachment))
|
|
continue;
|
|
let path = attachment;
|
|
let nn = path.worldVerticesLength;
|
|
let world = this.temp = Utils.setArraySize(this.temp, nn, 0);
|
|
path.computeWorldVertices(slot, 0, nn, world, 0, 2);
|
|
let color = this.pathColor;
|
|
let x1 = world[2], y1 = world[3], x2 = 0, y2 = 0;
|
|
if (path.closed) {
|
|
shapes.setColor(color);
|
|
let cx1 = world[0], cy1 = world[1], cx2 = world[nn - 2], cy2 = world[nn - 1];
|
|
x2 = world[nn - 4];
|
|
y2 = world[nn - 3];
|
|
shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);
|
|
shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY);
|
|
shapes.line(x1, y1, cx1, cy1);
|
|
shapes.line(x2, y2, cx2, cy2);
|
|
}
|
|
nn -= 4;
|
|
for (let ii = 4; ii < nn; ii += 6) {
|
|
let cx1 = world[ii], cy1 = world[ii + 1], cx2 = world[ii + 2], cy2 = world[ii + 3];
|
|
x2 = world[ii + 4];
|
|
y2 = world[ii + 5];
|
|
shapes.setColor(color);
|
|
shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, 32);
|
|
shapes.setColor(_SkeletonDebugRenderer.LIGHT_GRAY);
|
|
shapes.line(x1, y1, cx1, cy1);
|
|
shapes.line(x2, y2, cx2, cy2);
|
|
x1 = x2;
|
|
y1 = y2;
|
|
}
|
|
}
|
|
}
|
|
if (this.drawBones) {
|
|
shapes.setColor(this.boneOriginColor);
|
|
for (let i = 0, n = bones.length; i < n; i++) {
|
|
let bone = bones[i];
|
|
if (ignoredBones && ignoredBones.indexOf(bone.data.name) > -1)
|
|
continue;
|
|
shapes.circle(true, bone.worldX, bone.worldY, 3 * this.scale, this.boneOriginColor, 8);
|
|
}
|
|
}
|
|
if (this.drawClipping) {
|
|
let slots = skeleton.slots;
|
|
shapes.setColor(this.clipColor);
|
|
for (let i = 0, n = slots.length; i < n; i++) {
|
|
let slot = slots[i];
|
|
if (!slot.bone.active)
|
|
continue;
|
|
let attachment = slot.getAttachment();
|
|
if (!(attachment instanceof ClippingAttachment))
|
|
continue;
|
|
let clip = attachment;
|
|
let nn = clip.worldVerticesLength;
|
|
let world = this.temp = Utils.setArraySize(this.temp, nn, 0);
|
|
clip.computeWorldVertices(slot, 0, nn, world, 0, 2);
|
|
for (let i2 = 0, n2 = world.length; i2 < n2; i2 += 2) {
|
|
let x = world[i2];
|
|
let y = world[i2 + 1];
|
|
let x2 = world[(i2 + 2) % world.length];
|
|
let y2 = world[(i2 + 3) % world.length];
|
|
shapes.line(x, y, x2, y2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
dispose() {
|
|
}
|
|
};
|
|
var SkeletonDebugRenderer = _SkeletonDebugRenderer;
|
|
SkeletonDebugRenderer.LIGHT_GRAY = new Color(192 / 255, 192 / 255, 192 / 255, 1);
|
|
SkeletonDebugRenderer.GREEN = new Color(0, 1, 0, 1);
|
|
|
|
// spine-webgl/src/SkeletonRenderer.ts
|
|
var Renderable = class {
|
|
constructor(vertices, numVertices, numFloats) {
|
|
this.vertices = vertices;
|
|
this.numVertices = numVertices;
|
|
this.numFloats = numFloats;
|
|
}
|
|
};
|
|
var _SkeletonRenderer = class {
|
|
constructor(context, twoColorTint = true) {
|
|
this.premultipliedAlpha = false;
|
|
this.tempColor = new Color();
|
|
this.tempColor2 = new Color();
|
|
this.vertexSize = 2 + 2 + 4;
|
|
this.twoColorTint = false;
|
|
this.renderable = new Renderable([], 0, 0);
|
|
this.clipper = new SkeletonClipping();
|
|
this.temp = new Vector2();
|
|
this.temp2 = new Vector2();
|
|
this.temp3 = new Color();
|
|
this.temp4 = new Color();
|
|
this.twoColorTint = twoColorTint;
|
|
if (twoColorTint)
|
|
this.vertexSize += 4;
|
|
this.vertices = Utils.newFloatArray(this.vertexSize * 1024);
|
|
}
|
|
draw(batcher, skeleton, slotRangeStart = -1, slotRangeEnd = -1, transformer = null) {
|
|
let clipper = this.clipper;
|
|
let premultipliedAlpha = this.premultipliedAlpha;
|
|
let twoColorTint = this.twoColorTint;
|
|
let blendMode = null;
|
|
let tempPos = this.temp;
|
|
let tempUv = this.temp2;
|
|
let tempLight = this.temp3;
|
|
let tempDark = this.temp4;
|
|
let renderable = this.renderable;
|
|
let uvs;
|
|
let triangles;
|
|
let drawOrder = skeleton.drawOrder;
|
|
let attachmentColor;
|
|
let skeletonColor = skeleton.color;
|
|
let vertexSize = twoColorTint ? 12 : 8;
|
|
let inRange = false;
|
|
if (slotRangeStart == -1)
|
|
inRange = true;
|
|
for (let i = 0, n = drawOrder.length; i < n; i++) {
|
|
let clippedVertexSize = clipper.isClipping() ? 2 : vertexSize;
|
|
let slot = drawOrder[i];
|
|
if (!slot.bone.active) {
|
|
clipper.clipEndWithSlot(slot);
|
|
continue;
|
|
}
|
|
if (slotRangeStart >= 0 && slotRangeStart == slot.data.index) {
|
|
inRange = true;
|
|
}
|
|
if (!inRange) {
|
|
clipper.clipEndWithSlot(slot);
|
|
continue;
|
|
}
|
|
if (slotRangeEnd >= 0 && slotRangeEnd == slot.data.index) {
|
|
inRange = false;
|
|
}
|
|
let attachment = slot.getAttachment();
|
|
let texture;
|
|
if (attachment instanceof RegionAttachment) {
|
|
let region = attachment;
|
|
renderable.vertices = this.vertices;
|
|
renderable.numVertices = 4;
|
|
renderable.numFloats = clippedVertexSize << 2;
|
|
region.computeWorldVertices(slot, renderable.vertices, 0, clippedVertexSize);
|
|
triangles = _SkeletonRenderer.QUAD_TRIANGLES;
|
|
uvs = region.uvs;
|
|
texture = region.region.renderObject.page.texture;
|
|
attachmentColor = region.color;
|
|
} else if (attachment instanceof MeshAttachment) {
|
|
let mesh = attachment;
|
|
renderable.vertices = this.vertices;
|
|
renderable.numVertices = mesh.worldVerticesLength >> 1;
|
|
renderable.numFloats = renderable.numVertices * clippedVertexSize;
|
|
if (renderable.numFloats > renderable.vertices.length) {
|
|
renderable.vertices = this.vertices = Utils.newFloatArray(renderable.numFloats);
|
|
}
|
|
mesh.computeWorldVertices(slot, 0, mesh.worldVerticesLength, renderable.vertices, 0, clippedVertexSize);
|
|
triangles = mesh.triangles;
|
|
texture = mesh.region.renderObject.page.texture;
|
|
uvs = mesh.uvs;
|
|
attachmentColor = mesh.color;
|
|
} else if (attachment instanceof ClippingAttachment) {
|
|
let clip = attachment;
|
|
clipper.clipStart(slot, clip);
|
|
continue;
|
|
} else {
|
|
clipper.clipEndWithSlot(slot);
|
|
continue;
|
|
}
|
|
if (texture) {
|
|
let slotColor = slot.color;
|
|
let finalColor = this.tempColor;
|
|
finalColor.r = skeletonColor.r * slotColor.r * attachmentColor.r;
|
|
finalColor.g = skeletonColor.g * slotColor.g * attachmentColor.g;
|
|
finalColor.b = skeletonColor.b * slotColor.b * attachmentColor.b;
|
|
finalColor.a = skeletonColor.a * slotColor.a * attachmentColor.a;
|
|
if (premultipliedAlpha) {
|
|
finalColor.r *= finalColor.a;
|
|
finalColor.g *= finalColor.a;
|
|
finalColor.b *= finalColor.a;
|
|
}
|
|
let darkColor = this.tempColor2;
|
|
if (!slot.darkColor)
|
|
darkColor.set(0, 0, 0, 1);
|
|
else {
|
|
if (premultipliedAlpha) {
|
|
darkColor.r = slot.darkColor.r * finalColor.a;
|
|
darkColor.g = slot.darkColor.g * finalColor.a;
|
|
darkColor.b = slot.darkColor.b * finalColor.a;
|
|
} else {
|
|
darkColor.setFromColor(slot.darkColor);
|
|
}
|
|
darkColor.a = premultipliedAlpha ? 1 : 0;
|
|
}
|
|
let slotBlendMode = slot.data.blendMode;
|
|
if (slotBlendMode != blendMode) {
|
|
blendMode = slotBlendMode;
|
|
batcher.setBlendMode(
|
|
WebGLBlendModeConverter.getSourceColorGLBlendMode(blendMode, premultipliedAlpha),
|
|
WebGLBlendModeConverter.getSourceAlphaGLBlendMode(blendMode),
|
|
WebGLBlendModeConverter.getDestGLBlendMode(blendMode)
|
|
);
|
|
}
|
|
if (clipper.isClipping()) {
|
|
clipper.clipTriangles(renderable.vertices, renderable.numFloats, triangles, triangles.length, uvs, finalColor, darkColor, twoColorTint);
|
|
let clippedVertices = new Float32Array(clipper.clippedVertices);
|
|
let clippedTriangles = clipper.clippedTriangles;
|
|
if (transformer)
|
|
transformer(renderable.vertices, renderable.numFloats, vertexSize);
|
|
batcher.draw(texture, clippedVertices, clippedTriangles);
|
|
} else {
|
|
let verts = renderable.vertices;
|
|
if (!twoColorTint) {
|
|
for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) {
|
|
verts[v] = finalColor.r;
|
|
verts[v + 1] = finalColor.g;
|
|
verts[v + 2] = finalColor.b;
|
|
verts[v + 3] = finalColor.a;
|
|
verts[v + 4] = uvs[u];
|
|
verts[v + 5] = uvs[u + 1];
|
|
}
|
|
} else {
|
|
for (let v = 2, u = 0, n2 = renderable.numFloats; v < n2; v += vertexSize, u += 2) {
|
|
verts[v] = finalColor.r;
|
|
verts[v + 1] = finalColor.g;
|
|
verts[v + 2] = finalColor.b;
|
|
verts[v + 3] = finalColor.a;
|
|
verts[v + 4] = uvs[u];
|
|
verts[v + 5] = uvs[u + 1];
|
|
verts[v + 6] = darkColor.r;
|
|
verts[v + 7] = darkColor.g;
|
|
verts[v + 8] = darkColor.b;
|
|
verts[v + 9] = darkColor.a;
|
|
}
|
|
}
|
|
let view = renderable.vertices.subarray(0, renderable.numFloats);
|
|
if (transformer)
|
|
transformer(renderable.vertices, renderable.numFloats, vertexSize);
|
|
batcher.draw(texture, view, triangles);
|
|
}
|
|
}
|
|
clipper.clipEndWithSlot(slot);
|
|
}
|
|
clipper.clipEnd();
|
|
}
|
|
};
|
|
var SkeletonRenderer = _SkeletonRenderer;
|
|
SkeletonRenderer.QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
|
|
|
|
// spine-webgl/src/SceneRenderer.ts
|
|
var quad = [
|
|
0,
|
|
0,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
1,
|
|
1,
|
|
1,
|
|
1,
|
|
0,
|
|
0
|
|
];
|
|
var QUAD_TRIANGLES = [0, 1, 2, 2, 3, 0];
|
|
var WHITE = new Color(1, 1, 1, 1);
|
|
var SceneRenderer = class {
|
|
constructor(canvas, context, twoColorTint = true) {
|
|
this.twoColorTint = false;
|
|
this.activeRenderer = null;
|
|
this.canvas = canvas;
|
|
this.context = context instanceof ManagedWebGLRenderingContext ? context : new ManagedWebGLRenderingContext(context);
|
|
this.twoColorTint = twoColorTint;
|
|
this.camera = new OrthoCamera(canvas.width, canvas.height);
|
|
this.batcherShader = twoColorTint ? Shader.newTwoColoredTextured(this.context) : Shader.newColoredTextured(this.context);
|
|
this.batcher = new PolygonBatcher(this.context, twoColorTint);
|
|
this.shapesShader = Shader.newColored(this.context);
|
|
this.shapes = new ShapeRenderer(this.context);
|
|
this.skeletonRenderer = new SkeletonRenderer(this.context, twoColorTint);
|
|
this.skeletonDebugRenderer = new SkeletonDebugRenderer(this.context);
|
|
}
|
|
dispose() {
|
|
this.batcher.dispose();
|
|
this.batcherShader.dispose();
|
|
this.shapes.dispose();
|
|
this.shapesShader.dispose();
|
|
this.skeletonDebugRenderer.dispose();
|
|
}
|
|
begin() {
|
|
this.camera.update();
|
|
this.enableRenderer(this.batcher);
|
|
}
|
|
drawSkeleton(skeleton, premultipliedAlpha = false, slotRangeStart = -1, slotRangeEnd = -1, transform = null) {
|
|
this.enableRenderer(this.batcher);
|
|
this.skeletonRenderer.premultipliedAlpha = premultipliedAlpha;
|
|
this.skeletonRenderer.draw(this.batcher, skeleton, slotRangeStart, slotRangeEnd, transform);
|
|
}
|
|
drawSkeletonDebug(skeleton, premultipliedAlpha = false, ignoredBones) {
|
|
this.enableRenderer(this.shapes);
|
|
this.skeletonDebugRenderer.premultipliedAlpha = premultipliedAlpha;
|
|
this.skeletonDebugRenderer.draw(this.shapes, skeleton, ignoredBones);
|
|
}
|
|
drawTexture(texture, x, y, width, height, color) {
|
|
this.enableRenderer(this.batcher);
|
|
if (!color)
|
|
color = WHITE;
|
|
var i = 0;
|
|
quad[i++] = x;
|
|
quad[i++] = y;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 0;
|
|
quad[i++] = 1;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x + width;
|
|
quad[i++] = y;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 1;
|
|
quad[i++] = 1;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x + width;
|
|
quad[i++] = y + height;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 1;
|
|
quad[i++] = 0;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x;
|
|
quad[i++] = y + height;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i] = 0;
|
|
}
|
|
this.batcher.draw(texture, quad, QUAD_TRIANGLES);
|
|
}
|
|
drawTextureUV(texture, x, y, width, height, u, v, u2, v2, color) {
|
|
this.enableRenderer(this.batcher);
|
|
if (!color)
|
|
color = WHITE;
|
|
var i = 0;
|
|
quad[i++] = x;
|
|
quad[i++] = y;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = u;
|
|
quad[i++] = v;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x + width;
|
|
quad[i++] = y;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = u2;
|
|
quad[i++] = v;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x + width;
|
|
quad[i++] = y + height;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = u2;
|
|
quad[i++] = v2;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x;
|
|
quad[i++] = y + height;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = u;
|
|
quad[i++] = v2;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i] = 0;
|
|
}
|
|
this.batcher.draw(texture, quad, QUAD_TRIANGLES);
|
|
}
|
|
drawTextureRotated(texture, x, y, width, height, pivotX, pivotY, angle, color) {
|
|
this.enableRenderer(this.batcher);
|
|
if (!color)
|
|
color = WHITE;
|
|
let worldOriginX = x + pivotX;
|
|
let worldOriginY = y + pivotY;
|
|
let fx = -pivotX;
|
|
let fy = -pivotY;
|
|
let fx2 = width - pivotX;
|
|
let fy2 = height - pivotY;
|
|
let p1x = fx;
|
|
let p1y = fy;
|
|
let p2x = fx;
|
|
let p2y = fy2;
|
|
let p3x = fx2;
|
|
let p3y = fy2;
|
|
let p4x = fx2;
|
|
let p4y = fy;
|
|
let x1 = 0;
|
|
let y1 = 0;
|
|
let x2 = 0;
|
|
let y2 = 0;
|
|
let x3 = 0;
|
|
let y3 = 0;
|
|
let x4 = 0;
|
|
let y4 = 0;
|
|
if (angle != 0) {
|
|
let cos = MathUtils.cosDeg(angle);
|
|
let sin = MathUtils.sinDeg(angle);
|
|
x1 = cos * p1x - sin * p1y;
|
|
y1 = sin * p1x + cos * p1y;
|
|
x4 = cos * p2x - sin * p2y;
|
|
y4 = sin * p2x + cos * p2y;
|
|
x3 = cos * p3x - sin * p3y;
|
|
y3 = sin * p3x + cos * p3y;
|
|
x2 = x3 + (x1 - x4);
|
|
y2 = y3 + (y1 - y4);
|
|
} else {
|
|
x1 = p1x;
|
|
y1 = p1y;
|
|
x4 = p2x;
|
|
y4 = p2y;
|
|
x3 = p3x;
|
|
y3 = p3y;
|
|
x2 = p4x;
|
|
y2 = p4y;
|
|
}
|
|
x1 += worldOriginX;
|
|
y1 += worldOriginY;
|
|
x2 += worldOriginX;
|
|
y2 += worldOriginY;
|
|
x3 += worldOriginX;
|
|
y3 += worldOriginY;
|
|
x4 += worldOriginX;
|
|
y4 += worldOriginY;
|
|
var i = 0;
|
|
quad[i++] = x1;
|
|
quad[i++] = y1;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 0;
|
|
quad[i++] = 1;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x2;
|
|
quad[i++] = y2;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 1;
|
|
quad[i++] = 1;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x3;
|
|
quad[i++] = y3;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 1;
|
|
quad[i++] = 0;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x4;
|
|
quad[i++] = y4;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i] = 0;
|
|
}
|
|
this.batcher.draw(texture, quad, QUAD_TRIANGLES);
|
|
}
|
|
drawRegion(region, x, y, width, height, color) {
|
|
this.enableRenderer(this.batcher);
|
|
if (!color)
|
|
color = WHITE;
|
|
var i = 0;
|
|
quad[i++] = x;
|
|
quad[i++] = y;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = region.u;
|
|
quad[i++] = region.v2;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x + width;
|
|
quad[i++] = y;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = region.u2;
|
|
quad[i++] = region.v2;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x + width;
|
|
quad[i++] = y + height;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = region.u2;
|
|
quad[i++] = region.v;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
}
|
|
quad[i++] = x;
|
|
quad[i++] = y + height;
|
|
quad[i++] = color.r;
|
|
quad[i++] = color.g;
|
|
quad[i++] = color.b;
|
|
quad[i++] = color.a;
|
|
quad[i++] = region.u;
|
|
quad[i++] = region.v;
|
|
if (this.twoColorTint) {
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i++] = 0;
|
|
quad[i] = 0;
|
|
}
|
|
this.batcher.draw(region.page.texture, quad, QUAD_TRIANGLES);
|
|
}
|
|
line(x, y, x2, y2, color, color2) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.line(x, y, x2, y2, color);
|
|
}
|
|
triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.triangle(filled, x, y, x2, y2, x3, y3, color, color2, color3);
|
|
}
|
|
quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.quad(filled, x, y, x2, y2, x3, y3, x4, y4, color, color2, color3, color4);
|
|
}
|
|
rect(filled, x, y, width, height, color) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.rect(filled, x, y, width, height, color);
|
|
}
|
|
rectLine(filled, x1, y1, x2, y2, width, color) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.rectLine(filled, x1, y1, x2, y2, width, color);
|
|
}
|
|
polygon(polygonVertices, offset, count, color) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.polygon(polygonVertices, offset, count, color);
|
|
}
|
|
circle(filled, x, y, radius, color, segments = 0) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.circle(filled, x, y, radius, color, segments);
|
|
}
|
|
curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color) {
|
|
this.enableRenderer(this.shapes);
|
|
this.shapes.curve(x1, y1, cx1, cy1, cx2, cy2, x2, y2, segments, color);
|
|
}
|
|
end() {
|
|
if (this.activeRenderer === this.batcher)
|
|
this.batcher.end();
|
|
else if (this.activeRenderer === this.shapes)
|
|
this.shapes.end();
|
|
this.activeRenderer = null;
|
|
}
|
|
resize(resizeMode) {
|
|
let canvas = this.canvas;
|
|
var dpr = window.devicePixelRatio || 1;
|
|
var w = Math.round(canvas.clientWidth * dpr);
|
|
var h = Math.round(canvas.clientHeight * dpr);
|
|
if (canvas.width != w || canvas.height != h) {
|
|
canvas.width = w;
|
|
canvas.height = h;
|
|
}
|
|
this.context.gl.viewport(0, 0, canvas.width, canvas.height);
|
|
if (resizeMode === ResizeMode.Expand)
|
|
this.camera.setViewport(w, h);
|
|
else if (resizeMode === ResizeMode.Fit) {
|
|
let sourceWidth = canvas.width, sourceHeight = canvas.height;
|
|
let targetWidth = this.camera.viewportWidth, targetHeight = this.camera.viewportHeight;
|
|
let targetRatio = targetHeight / targetWidth;
|
|
let sourceRatio = sourceHeight / sourceWidth;
|
|
let scale = targetRatio < sourceRatio ? targetWidth / sourceWidth : targetHeight / sourceHeight;
|
|
this.camera.setViewport(sourceWidth * scale, sourceHeight * scale);
|
|
}
|
|
this.camera.update();
|
|
}
|
|
enableRenderer(renderer) {
|
|
if (this.activeRenderer === renderer)
|
|
return;
|
|
this.end();
|
|
if (renderer instanceof PolygonBatcher) {
|
|
this.batcherShader.bind();
|
|
this.batcherShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values);
|
|
this.batcherShader.setUniformi("u_texture", 0);
|
|
this.batcher.begin(this.batcherShader);
|
|
this.activeRenderer = this.batcher;
|
|
} else if (renderer instanceof ShapeRenderer) {
|
|
this.shapesShader.bind();
|
|
this.shapesShader.setUniform4x4f(Shader.MVP_MATRIX, this.camera.projectionView.values);
|
|
this.shapes.begin(this.shapesShader);
|
|
this.activeRenderer = this.shapes;
|
|
} else
|
|
this.activeRenderer = this.skeletonDebugRenderer;
|
|
}
|
|
};
|
|
var ResizeMode = /* @__PURE__ */ ((ResizeMode2) => {
|
|
ResizeMode2[ResizeMode2["Stretch"] = 0] = "Stretch";
|
|
ResizeMode2[ResizeMode2["Expand"] = 1] = "Expand";
|
|
ResizeMode2[ResizeMode2["Fit"] = 2] = "Fit";
|
|
return ResizeMode2;
|
|
})(ResizeMode || {});
|
|
|
|
// spine-webgl/src/LoadingScreen.ts
|
|
var spinnerImage;
|
|
var logoImage;
|
|
var loaded = 0;
|
|
var FADE_IN = 1;
|
|
var FADE_OUT = 1;
|
|
var logoWidth = 165;
|
|
var logoHeight = 108;
|
|
var spinnerSize = 163;
|
|
var LoadingScreen = class {
|
|
constructor(renderer) {
|
|
this.logo = null;
|
|
this.spinner = null;
|
|
this.angle = 0;
|
|
this.fadeOut = 0;
|
|
this.fadeIn = 0;
|
|
this.timeKeeper = new TimeKeeper();
|
|
this.backgroundColor = new Color(0.135, 0.135, 0.135, 1);
|
|
this.tempColor = new Color();
|
|
this.renderer = renderer;
|
|
this.timeKeeper.maxDelta = 9;
|
|
if (!logoImage) {
|
|
let isSafari = navigator.userAgent.indexOf("Safari") > -1;
|
|
let onload = () => loaded++;
|
|
logoImage = new Image();
|
|
logoImage.src = SPINE_LOGO_DATA;
|
|
if (!isSafari)
|
|
logoImage.crossOrigin = "anonymous";
|
|
logoImage.onload = onload;
|
|
spinnerImage = new Image();
|
|
spinnerImage.src = SPINNER_DATA;
|
|
if (!isSafari)
|
|
spinnerImage.crossOrigin = "anonymous";
|
|
spinnerImage.onload = onload;
|
|
}
|
|
}
|
|
dispose() {
|
|
var _a, _b;
|
|
(_a = this.logo) == null ? void 0 : _a.dispose();
|
|
(_b = this.spinner) == null ? void 0 : _b.dispose();
|
|
}
|
|
draw(complete = false) {
|
|
if (loaded < 2 || complete && this.fadeOut > FADE_OUT)
|
|
return;
|
|
this.timeKeeper.update();
|
|
let a = Math.abs(Math.sin(this.timeKeeper.totalTime + 0.25));
|
|
this.angle -= this.timeKeeper.delta * 200 * (1 + 1.5 * Math.pow(a, 5));
|
|
let tempColor = this.tempColor;
|
|
let renderer = this.renderer;
|
|
let canvas = renderer.canvas;
|
|
let gl = renderer.context.gl;
|
|
renderer.resize(1 /* Expand */);
|
|
renderer.camera.position.set(canvas.width / 2, canvas.height / 2, 0);
|
|
renderer.batcher.setBlendMode(gl.ONE, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
|
|
if (complete) {
|
|
this.fadeOut += this.timeKeeper.delta * (this.timeKeeper.totalTime < 1 ? 2 : 1);
|
|
if (this.fadeOut > FADE_OUT)
|
|
return;
|
|
tempColor.setFromColor(this.backgroundColor);
|
|
a = 1 - this.fadeOut / FADE_OUT;
|
|
a = 1 - (a - 1) * (a - 1);
|
|
tempColor.a *= a;
|
|
if (tempColor.a > 0) {
|
|
renderer.camera.zoom = 1;
|
|
renderer.begin();
|
|
renderer.quad(
|
|
true,
|
|
0,
|
|
0,
|
|
canvas.width,
|
|
0,
|
|
canvas.width,
|
|
canvas.height,
|
|
0,
|
|
canvas.height,
|
|
tempColor,
|
|
tempColor,
|
|
tempColor,
|
|
tempColor
|
|
);
|
|
renderer.end();
|
|
}
|
|
} else {
|
|
this.fadeIn += this.timeKeeper.delta;
|
|
if (this.backgroundColor.a > 0) {
|
|
gl.clearColor(this.backgroundColor.r, this.backgroundColor.g, this.backgroundColor.b, this.backgroundColor.a);
|
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
}
|
|
a = 1;
|
|
}
|
|
a *= Math.min(this.fadeIn / FADE_IN, 1);
|
|
tempColor.set(a, a, a, a);
|
|
if (!this.logo) {
|
|
this.logo = new GLTexture(renderer.context, logoImage);
|
|
this.spinner = new GLTexture(renderer.context, spinnerImage);
|
|
}
|
|
renderer.camera.zoom = Math.max(1, spinnerSize / canvas.height);
|
|
renderer.begin();
|
|
renderer.drawTexture(this.logo, (canvas.width - logoWidth) / 2, (canvas.height - logoHeight) / 2, logoWidth, logoHeight, tempColor);
|
|
if (this.spinner)
|
|
renderer.drawTextureRotated(this.spinner, (canvas.width - spinnerSize) / 2, (canvas.height - spinnerSize) / 2, spinnerSize, spinnerSize, spinnerSize / 2, spinnerSize / 2, this.angle, tempColor);
|
|
renderer.end();
|
|
}
|
|
};
|
|
var SPINNER_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKMAAACjCAYAAADmbK6AAAALKElEQVR42u2de2iW5R/GPzuqcwfnnKfNmafl5tTNHWzqNi3DEMQykcAoJSsySkspjSIk0iD/07Kf4R+FnVBDUTshZGpWUEJaaiWFgZlUFmXmIe3HNXthyebeZ77P9H13ffBG8Y8H7ut7vff93N/7fu4vGGPiFZiez/Qtw9lytJajfzfw9z/j+efPOv7cV8W+lUNY2a8T/ayTCRsWFLJA5rtUO1LLkV5p9LJeJizQiHeqnlOtmVFtdTGrrZkJCxYXsTgaI6r9MY4/UpNItW4mFDaXsTlaM6qVZlBq3UwofFrJp0HMWJ9DvXUzobCznJ1BzFjWlTLrZkJh/TDWBzFjTgo51s2EgnKI0Rrx+FiOWzNzVaym91Syx5qZsGBWb2ZFa0ZN6dbMhAWTcpkUrRmXD2K5NTNhgVbH0Zpxbl/mWjMTFvRIo0e0ZpzcncnWzISKtvmiMWNRJ4qslwmVXRXsas2Ix8ZwzFqZsGFREYtaM+Oaa1ljrUzYkJ9G/ok6TlzKjJWZVFor0y7c1Zu7WjLiqiGsskamXdHopyT4vALmzS9k/t19uHtKHlOSIMn6xAtARjIZ1sFcUSZ0Y4La+G6M18hS2IlCn4a+WoC0JNL0d/dUupdnUj40g6EJ2VEdMnhrOG/p5f/jUXz8SgmvaGU6KpNRNsLVQV0OdXf24s63h/P2gWoOrBjMCr2GJFQnnxnIM3q5P1PPmaYv+4ev4/C6UtbpV2gzXCkgL5W8Bwt48OIc6ul6Tp+s4+SyASxLiI4+PYCn1bHzDZxvaQW6vZzto7MYnQIpNkf7kp5EuozYUroqEjcNKHHd0Tl9mBPN1pk+hFeieGBnBtog7UXjsj9pWg+m6duecw2cay1OC/uxMC47KmP9OIYfoz1YoC20J/rzRG4quTZK2EAyJGs20qwUbYw0aNRmUxtvfUW/uEtNzc1NB1/X8LVyd15hh82F43AvD+VlXcsSJEZa1CQ3ejleAO7oxR3RDP0XN91X4+NXYb8nkv7UNTwV7e0YTdu7I3g33t7tuaEbNwSZpps2fSyvs4M2Tjhot+jb0Xzbltj8r5j/xVt/6Z1Ob93U1ZYO691EhhzchcHeXosVjcNZysyezLw4xRZt05R+fTeuj8vOj+zKyG0j2aZcVVs6v+QalnjrMFZASQYl2nBoSyz06e3j/Xk8rgWYmMvEICu2pm1HOTuc7okV8FgRj0XukwzanhvCc/F+72TjoQjdObN1OFuDLmh0xP+WHtxiI10ukJlCprb4guiv1fP+avZrS1C7NAkliHZjDtZwMMgqbukAltpMlwuMy2FcEBPqvfLLar5Uqi0hBdEwryy+Mv5n6zkbjTBa+dlMlwvUZFETZKGiFM7tvbhdJ3gSVRO0wzIjnxmvl/J6a6JsGMYGrahtpssFeqbR841S3mhN80OjOaSDEdqd6SjaMKgzgzRK7q1ib3PT9sYyNo7JZoyNFNvRcVMZmy7WOvIuryv/Zvdmdt90+nY0bRp3AvROohFwdwW7dTG7RFlbwlqdrbOBYg005NAQmZU0HWt1rXMBH1Xw0dQ8pmqzoaPmdhun7bHZjNVe9qP9eFQfO1VkUmHjhAVUZ1GtnKFSbjrkrPfy4i4UW5t/6ZxM54J0CqxFe81KpGsQyE4h23oYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjLna+bdOy+IiFquIpGq16Pb79cNYv3IIK/X/ugx+Ui6TVKvYVU9Nc8gX8od8Ir/IN/KPfCQ/yVfyl/6/pfJvLChkQdD6wyqntquCXYuKWJSfRr6D0dEAxV3xlw/khyD+kd/ku/88cHo+09tS3LBpO1HHCVUqcIA6CqB4K+6X6x35L/JM2loXurlWmUmlA5XogOIcK8/If5HncrSWo7F6cKIWPjT/RXGOlWfkv8hzaWsN4uaaysE6WIkOKM6x8oz8F3kusXqo2vxC5jtYiQ4ozrH0TeS5qIZcrB7qkrwdA8U5Vp6R/yLPZV8V+2L14Cl5THGwEh1QnGPlGfkv8lyUlIzFQ1cNYVVHrcjZ0VCcFe9Y+Eb+izy3ceclUl43aFN52DXXssYpnY6a4qFS8ZcP2uIf+e7inRh6pdFrdTGrm8uiHx/L8T2V7NGWzvJBLJ/bl7mTuzO5qBNFDoiJID/IF/KHfCK/yDfyT3O7d/KbfNfS80hNIrU0g9L6HOq1x5iTQo6FNpeLfCQ/yVfyl3xmXYwxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHGGGOMMcYYY4wxxhhjjDHNk9z4JwJ0SqKTdQkbyEwhU393T6V7zzR6pieR3tE1ITeVXImhe6BXDGZFdRbVeank2TBhcaEMr0rwbixj49IBLL2/L/ffmMuNHfqO9tFZjJYBd1ewO3Lx+IcVfKhqna5nHZYR6XFPH+5R3eeI5t9fx/fvjeC9Jdew5OKZKqFR/RDVKL6vL/f9PJafmyvHsL+a/ff24V6NmjZQbGchVbY6UM2BluqHv1rCqzVZ1KQlkZboepCdQvacPsz5bjTfXao+yMEaDt7Wk9tSIMVGig3TejCtJSM2bSpkPjWPqd1S6Zao+lORSYWmgkOjORRNwZqd5ezMSiHLRooNr5XwWjS6/1XHX9vL2T67N7M1iyXa9JCrYjVrS1gbpJyw6hBfsmiNCYT0P9/A+Wj1/6qGr5YNYFlJBiWJogEzezLz/ZG8/9s4fgtSyuvNYbyp1IONFBtu7sHNv4/j9yAxUHWrdaWsG9+N8XHd+YxkMpSy+aySz841cC5oXbmHCnnI74yxAgZ3YbDeB4PEQCOpBpFNZWwa2ZWRcdnxLsl00crtRB0n2lLg8JNRfDKoM4NsolgBSmw/UMADba1+qpmqfyf6x1u/0a/og3I+aEunP6/i86osqmygcGarF4p54dex/Bo0LqfqOfVwIQ/HW5/RSkwV1oN2WLlHTc82TljAwM4M1O5LWwYKZTjibYXNS0N5KcjKTe10PadfLObFuJwK4ozp+UzXDBTUjL+M5ZcBnRkQV53dMIwNQTu6bSTbVEzbi5awuVByd2E/FgaN0Tc1fKOzBHHV2aAdVSdv6s5NNkp7cSH/++xAng2yyHx+CM/H21YhfdPp+0U1X0TbSZnXx8faG9Aop0MS0cToh1p+iLcpOkLj9t/JOk5eqoPHxnDsyf486an5yqCDK7XZ1O4oZ4dWyy3FSXHUAYq47uyYbMZoGmhpG3DlEFb6uNiVBhpyaHhnBO8oJmfqOROJjzIiP43hJ8UxITqqX56S2Hur2KsOnq3nrE6PPNKPRwrSKbAZrjTQNZmuE7oxYXMZmxWbw9dxWFu4W4ezVedOE6qzI7oyYkY+M7TPeWsPbk2UX1qioSN+E3OZqOR2cReKE+qQRFN0Pi7y73g/UawU1KzezJpXwLz5hczX1ueUPKYkNb6GJQZ+j7/aAfRZREsv+quGsMoamXZBW2Gt5eU0alorEzYsKmJRa/m4NdeyxlqZsCGa84DKnVorEzboC7podis69DfIJmwufHMc7famvvmxZiYsKOtKWbRm1OcW1syEBboSJFozLh/EcmtmwgIluaM14/phrLdmJixYXMTiaM24p5I91syEBTphFOR7Y2tmwgJNvUFOr+tov3UzoaAv44KYUatv62ZCoemdhtG0+hzqrZsJBR08DWLG0gxKrZu50qvpxos3U5NItW4mFPp1ot+lPlpq2lYXs9qamVBZUMiC1ox4pJYjvlfStAu6GmTLcLboMtPIV4/6im5fFfuUi9QIap2MiWP+D96R1vPmsD/fAAAAAElFTkSuQmCC";
|
|
var SPINE_LOGO_DATA = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKUAAABsCAYAAAALzHKmAAAQ7klEQVR42u3da4xdVRUA4D0zd2Y6nZY59DVtZ1puS9+lzC0YAi2UQ8AAQczFpPgA9VIeIQbirRqJ0cBUBVGjDr/QCKSNRSMmpuODxAdxqhgwxkhFjf6Sxh/+UUNVNGJCzR7uTvas7LXX2q9zzp3em6y0gTN3Zu75utZe5+yztxC9V+/Ve5X9En1Vjd7J6SFbLNF7naPw+l2jh7YHMBWssqMHtlsRdim4qsLtIawaPiHEQOLoNrA9iIkQDnRrVA1qD2LZ8ISoxYqKo13sQAtBWBayQWZUAXGRQM9JjCngDVY0UqJNDbQrMcaGmArdUKpIjbYiQLsCZCyIMQBy8QwnilR4Q5AuCpxFYvRFmBLbEiwKwpsSaWycVQGZBKMrwBjA9BhxDe57u2L2hOoKNCbOrgAZitEVYUxoKSMErQvSxYIzCkguRg5EF4AUhqUlhy/YUKSxcRaKsioYOQhD4I0yYxkR3PcJBcuFysmgsXAWBTMJyBCMIQh9kGGxXIXvexCQXbHGAMrBWTbM2CCpMSMLIxehC77lSJwXGth7M0FzoVJIXXDWQnGmhOkL0ic7YhhtWdGGkAuPAjUWGoF4faCmwBkbZmyUqUCyMqMLRA4+E6IsdTjidUHKBYrh9CnpRcH0ypKxsyOGEYNIIeTCOz91OIJ1QYoB5eAMyZo+MFNnyVTZ0YiRC9EGEMOyAgshxErHsL2XK1gOUgwohtM1a5YNM7Rsu4K0ZkcbRm4mpPBRwFZ5hg9eCqkrUB+csWGGogzNkqEgrdnRhpGLkINudaLgwvVB6oqzCjCTZElb2Y4B0gUjBtEG0ARnDRLjjoG9DwcshtQGlIPTljVjwUySLWNkyRCQVHa0ZUUTRAwgF91a33BEy0VKAcVwwqwZC2bqbOlUurllOxQkJzNyINoAYqjWhYYjWg5SCiiG05Q1U8FMjTIoS8YE6YORi1BHtJ4KIcQEEtTXUWAxpK44YVlPBdO1jCdFWTZIE8bVGEYMIRPcZGBw4HKQcoBiOE1ZMzbMgVQwU6JMAdKEEcuIJogUvg1YCCE2gsCO42DlIIVAKZwpYJaSLVNnSU6XjYHUmxhTmXaFaMO3EYkLqMC+FsLlIoVAKZzMrEnBhJeLfLNlKMrYWRIDCbOkFSSVHbHM6AKRC6/ODUewNqQ+OLlZkxpjUmV8MBbMUJSxyzY3Q1IgTRgxiBRCHdem0KDAUkBh9sRwwjEnAXMMgTnKhFlUtiwkS5rGka4g9SaGgxFmRC7AzTCEEBcyA36dDSsXqAtOLkysjGMwY5XxVChjZ0kuSCo7YlkRQsQQYtDEFsegsLoCxUp7Kpgps2UslFGzJGccSYHUmxhOZqwzEZqAbfUMCisHKIZzgsCpl3MTzMwTpi1bYp2477gyFKUxS7qWbdjY2EBS2dGE0QQRA7gNCyHEdhjE8RhUDlBT9tzgmjWZMFNlSy+Urk1OzCyJlW0XkK4YOQh1cDtcgwBrQmoDWkdgboBZE8mYsJSHlnFbJ+5bwmOPJ7lZkirbC8aRsMvmgtTHjBhGE0QbwJ2egUE1ITVlUC5OmDVdYNrKuN70xM6WoShjlW4464dbtiFIWK6x7GjESEHUUe0iYncnbMdQSE0Z1ITTNOb0hRmjjLtmS9dmJ2rp1jtuKktyyrb6YLEMCUHq2dGG0QQRQ7f72kzc+cJecerne8Wvv7JNPHPvenEkz8Sh3UtFc92QyGt9Yko/HgOLAIUZlItTz5ouMF3KuE+2jFLCQ1D6lm6fLMkBacuOJowYRBUXyfjuHjF3NhdnsfjvAfH6E9vFt9XxKgikEKgJZyyYalzOLeMu2bLbULI6bh+QGwmQ+rgRlumdGEQAao+K56bEL2woVUwOiev0r8OAUjiJrMmFCbvykGxZRAmPitK1dHM7bohyMsuyi/I8f0+e57fJYIKEZXpXo9E4mOf5XTKyLLvCBLETF8uY2SKepkC+dpX4T02Ivepr4HvZcOZ5fmee54fyPL+DmTUhzAs6n4n8bN5dr9f3YdkSg8nsxG0lPBVKVpNjG0/aGhzfLDmRZdnumZmZp8+c+cdZPV555fSr7Xb7s0jJ3i5Pcue4MxKkPPkvvXTqz/B92u32l0wYOzG1fkhcd/py8Rcbyq/vFM/KY1WA95h/3zzP71bfU6JsNpsfgj+P/FlbrdaDGExYyuXvLz8H+DudODH700ajcSM3W6Yu4alQ1spCOTd38jcKocTZbh9+9NixY99XJ8AEUkcpo9W64yH197m5k7+bnZ19QT+J09NHntQhwji/Jg58qi6++ofLxJ8gSFneVw2Ka4QQDfh1Ok4dZavVmtZ/nrm5k7/Vf55O1tRhboUw5+ZOvqyOl5+R/FyOHj32PYVU/tloNG5IXcKrhJIzngwp3fNjomazea/64BuNxts646f50lWv169utw9/DmtqdJQyZFaSJVuV6nq9fqMEof5/vV6/CYBqgJDlee+yAbF/+4i4ZWqZeNfaIfHWzn+Hx0KcEuU9+s8jv3ej0bhVlXOZydX/k0iRMeb8P0D5e6tj8zy/Xb9UJIc56h/yqVOnXul8lmuZ2bJslKmbHG7XrbpCmCXFRLvdfqQD6jTS3Jiy5I4OykM6ADV+1Eu1DmV6evopBORexzDi1L+X/HnGxsb2w3Hm9PSRJ9QxWPOTZdmlKht2hi+w6dkox5bqffI8fye3hDteGqKaHVsHXihKl0tB+h0cY+lute54AGRKDCW89LNTRynHb7ChUWVVjetOnJh9EYBUyPZeNCoOtsbFQwdXi4/esELcd+tq8cCHJ8UXp+viy9efLz7AgamjlKXc1AA1m83DoIRDlFubzeb96hhZLVTlgJ24gttutx+ONa50bHZKRenaeTs1OfpAfnr6yOOdE7EZdNwmlKocntXLNkA5JTGq47Ds+Lf94lWsyfnXleLfnIwJUN4DOnNYwuUxh2A3Ln9XULrfK8t3J27Tu3BVwiOjXJqoAy8UZej1yclGo3GTLN+gu3w+z/P3YaWbQqk3Ne12e4ZC+c8rxWsYytcPiP9RpZxCqWDKnxOiBNlyAUpOnGsoh4tA2Rm8X9xqtT6md5wyZmYe+0YRKL+1S/wYQ3n8zctBl5SBUv5djivfjMOPduIzcizeiYfr9foVvUwZG+XCuzibZKnSceZ5/v4QlKp8y7ElhnJlTeTP7BI/kllRYfzrfvHqFy4UX1vaL/aVlSmROzwbwdS29T2UcEwZF+V8ozM2lu1VY812u/15akypGh3TmFJesJbHHD167IdUxz3YJy5bNySuX1mbvy55CbMLtzU6tjGlsdFptVqfUMc0Go23F4wy1l2dSnbfvpMwVPe9WWVLDsrOJaF9MFu2Wq1PqmNkGce67xiXhTjdNwdlvV6/BgxfbPfBfVCetxi6b9/rlCup65QzM48dl2OjLMv26CibzeZ96sTIzEFdpwQXz9U1yrtVlpR/Zll2Fec65Y6l4pbbx8XHH9kknvzJlPjlHy8Tp29eKT5ou0aJoIT3w3dBlLDzVpfAJEZ1XOdaJZxnOSlvPMjPzxFljIvng914RwebsjYO7uhMyHu46sOfnf3Oz2TXDW6vvYxdFoIXz3Wc8J5zs9n8iOn2IrxTc2BM3Glqdp7dI553uaOjxrhwcob+MyuUpjs6WZZdon8OcigjPx8V+u+GTWFTSWEx3WYcdJ225jNDSE4q0GHCzlueHOyujn6bUWYgeb9ZZUaQPe+GzQ+Gc8+oOGhC+c1d4gfI16n3XDAhQ7+9qE9l01E2Go132GYKyXE1NiFDTcpoNpv3LOYJGWXNErJNW9sEp63p2RKiVPMn1bS1DgxsyhoGdGpmizj+xtXiDYnx7/vFmce3iWdW1cTVGEY4hQ2ZW0nNq8Qm/M6XbXm3S100lwGedFybuvNOibLI+ZS2ceU4eAxiEuvCkfmU8ycToDxETe6FgCBQHeqyAbFvfEhcO7BwDuXFCEbTZF840XeHK0jYcbs2OIGle0mVJ/mmnClEPQqxyTY5I8/zFhif7fSZee4bnrPOU4AssnRXHaVTCTd14dRDY3UbTIiSeFhsN/aMjgnqthFx880rxX3yATL5p3y4LPXzOaBkUyBjZMlYpbtQlIOBD475ZEusjMNSvkXe6VEoJVDkeZ2dzIfIFsRzU+JF2OyM9M9fTC/6SUYOyFQPjQ2nWiUjxnPfw5EeHqMWIqAeIFsAU847lJM2JM6xsewt1OIDLs99P7ZFHNdB/upS8XtPiD7PfLuCXJNolYyyFiNI/Zit65ItrOVafFbHcFohY7hPTN21Tjz4uc3iqfsnxKdX1MTl1OoYRFaMsToGB6Trw2JFP/OdZC2hJZ7ZkrMoAbbSGmelDJ91hFKuJeS7jlBMkJnrAqqJlgMUZS/dArPlGHNdSg5M3xXXtvquuEatvIYtDRhpxbUJuIgqsU5lGWtUploK0KuEU9mSW8YpmFQ556xNuYW7NiW13B+FkMiKHIy+C6eGgBxJvMR0oSv5hi6+z4HJyZoU0M2RVvDlrOQbcxVfX5AhZbuqy0v7ZstYMLHlAVlLTF9ALLbvu9Y5Zylpn/XOsd0ibIvxr2KCLHpp6SCUIdnSZSF+WzfOhem6GD+1KwR3Z4jNjrtDpNoZwmWd8yrupZN6Hx3fbMmFSe0Swdq2ZIPjxk1112Duo8OBGLrBkw/IoncdK2XHsdC9dHz204m50xh3tzFq1zFqtzHXrfCw7OgDsqyNnZLszVijsmXgrmNcmGtS78lIoMX2aJz03fKO2sDJddPQSCDPiQ1DfWBycY6XtXstc2PQKuxgG2McmXTPb9/9vmuJYXKyJrWjbeg+3xPM4O73nWqvbyw7xgZZSJbEUBa157cNJjdr2vb+5iA1YV3HxYscj30PDCEHIgcjtfm8K8hSsmRotkwFk5s1TTghUAopB6xrjHMBBkI0YYTZ0dZlxwLpkiWDULpmy5gwqayZgZNkA7oKQQCxctByYg0XIIEQQuRitGVHblMTA2ShKGPDpC6wu+DEgJqg2rDGDBtAF4Q6RAojp1xXGmSMbImVcR+YWNY04eQCtUG1ofUJ2/uvcETIgUhhdAE5GAlkKShjwHTNmhhODKgJqQ2sC14uOgyfD0IbRF+MlQaZAiZWyn2yJsTJATqGnHQO2Jhh+xlsACFCG0QbRtdyzQFZCZSxYPpmTS7Q5cjJHYNBYIkZpu99HoUQ/o4QIYSIZUZfjJ4ZMjZI32wZBDMU5yhy8pZTULl4XYP5fagMyEVoy4oupTpGduwnkloSlKEwY+AcQU4MhRTD6ovXBRwFzwWgCSEF0QVjJUGmgEllTS5OLlCIlIN1mS9mx/cZ5eLDALpCTI2RAhkTZQqYoTgpoCPECbaBHQ2ETL3PUl98ECAXYijG0OyYAmQoTG7W5ODkAF1CnVgm2JQx4okPA+gCMTbGskBGgRmaOblAh5GTORIrfKFx4VH4EIAxIXIxlg2SBbMvECY3e7oApbDaIgQu5/2HmeEKEINYiwSRi7EQkLFgumZOCuggctKGI4ULZN/vMeSLj0AYMytWEqMLzFg4fYDaoKaC6wvOFR4FkIPQFaILxrJAOsHsc/zlfYDWXE8qF22s8Pz5KHxcgEVALBtjJXBSSEOwFhk1Zgy4hitCT4hVw+gFs8/zwxqIBbUgyK7fcyA0PD9XX4iVxhiC0xdof6STWCsoBmKF7+cVCWFXQYyBMxRpf+STX1b0x45AhN0OMSrOGEirhrY/dfQAdjvS7oy+WCF6r1RIFxXWvlTRg1YVqFWBmxZbD99ig9pt0YPQw9rD1nstVri9V+/Ve3XrS/wfim4P5fIFxLoAAAAASUVORK5CYII=";
|
|
|
|
// spine-webgl/src/SpineCanvas.ts
|
|
var SpineCanvas = class {
|
|
constructor(canvas, config) {
|
|
this.time = new TimeKeeper();
|
|
if (!config.pathPrefix)
|
|
config.pathPrefix = "";
|
|
if (!config.app)
|
|
config.app = {
|
|
loadAssets: () => {
|
|
},
|
|
initialize: () => {
|
|
},
|
|
update: () => {
|
|
},
|
|
render: () => {
|
|
},
|
|
error: () => {
|
|
}
|
|
};
|
|
if (config.webglConfig)
|
|
config.webglConfig = { alpha: true };
|
|
this.htmlCanvas = canvas;
|
|
this.context = new ManagedWebGLRenderingContext(canvas, config.webglConfig);
|
|
this.renderer = new SceneRenderer(canvas, this.context);
|
|
this.gl = this.context.gl;
|
|
this.assetManager = new AssetManager(this.context, config.pathPrefix);
|
|
this.input = new Input(canvas);
|
|
if (config.app.loadAssets)
|
|
config.app.loadAssets(this);
|
|
let loop = () => {
|
|
requestAnimationFrame(loop);
|
|
this.time.update();
|
|
if (config.app.update)
|
|
config.app.update(this, this.time.delta);
|
|
if (config.app.render)
|
|
config.app.render(this);
|
|
};
|
|
let waitForAssets = () => {
|
|
if (this.assetManager.isLoadingComplete()) {
|
|
if (this.assetManager.hasErrors()) {
|
|
if (config.app.error)
|
|
config.app.error(this, this.assetManager.getErrors());
|
|
} else {
|
|
if (config.app.initialize)
|
|
config.app.initialize(this);
|
|
loop();
|
|
}
|
|
return;
|
|
}
|
|
requestAnimationFrame(waitForAssets);
|
|
};
|
|
requestAnimationFrame(waitForAssets);
|
|
}
|
|
clear(r, g, b, a) {
|
|
this.gl.clearColor(r, g, b, a);
|
|
this.gl.clear(this.gl.COLOR_BUFFER_BIT);
|
|
}
|
|
};
|
|
return __toCommonJS(src_exports);
|
|
})();
|
|
//# sourceMappingURL=spine-webgl.js.map
|
|
|
|
/*** EXPORTS FROM exports-loader ***/
|
|
module.exports = spine;
|
|
|
|
}.call(window));
|
|
|
|
|
|
/***/ }),
|
|
/* 211 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var GetFastValue = __webpack_require__(11);
|
|
var ImageFile = __webpack_require__(212);
|
|
var IsPlainObject = __webpack_require__(7);
|
|
var JSONFile = __webpack_require__(224);
|
|
var MultiFile = __webpack_require__(225);
|
|
var TextFile = __webpack_require__(226);
|
|
|
|
/**
|
|
* @typedef {object} Phaser.Loader.FileTypes.SpineFileConfig
|
|
*
|
|
* @property {string} key - The key of the file. Must be unique within both the Loader and the Texture Manager.
|
|
* @property {string|string[]} [jsonURL] - The absolute or relative URL to load the JSON file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json".
|
|
* @property {string} [atlasURL] - The absolute or relative URL to load the texture atlas data file from. If undefined or `null` it will be set to `<key>.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt".
|
|
* @property {boolean} [preMultipliedAlpha=false] - Do the textures contain pre-multiplied alpha or not?
|
|
* @property {XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json file. Used in replacement of the Loaders default XHR Settings.
|
|
* @property {XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings.
|
|
*/
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Spine File suitable for loading by the Loader.
|
|
*
|
|
* These are created when you use the Phaser.Loader.LoaderPlugin#spine method and are not typically created directly.
|
|
*
|
|
* For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#spine.
|
|
*
|
|
* @class SpineFile
|
|
* @extends Phaser.Loader.MultiFile
|
|
* @memberof Phaser.Loader.FileTypes
|
|
* @constructor
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file.
|
|
* @param {(string|Phaser.Loader.FileTypes.SpineFileConfig)} key - The key to use for this file, or a file configuration object.
|
|
* @param {string|string[]} [jsonURL] - The absolute or relative URL to load the JSON file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json".
|
|
* @param {string} [atlasURL] - The absolute or relative URL to load the texture atlas data file from. If undefined or `null` it will be set to `<key>.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt".
|
|
* @param {boolean} [preMultipliedAlpha=false] - Do the textures contain pre-multiplied alpha or not?
|
|
* @param {XHRSettingsObject} [jsonXhrSettings] - An XHR Settings configuration object for the json file. Used in replacement of the Loaders default XHR Settings.
|
|
* @param {XHRSettingsObject} [atlasXhrSettings] - An XHR Settings configuration object for the atlas data file. Used in replacement of the Loaders default XHR Settings.
|
|
*/
|
|
var SpineFile = new Class({
|
|
|
|
Extends: MultiFile,
|
|
|
|
initialize:
|
|
|
|
function SpineFile (loader, key, jsonURL, atlasURL, preMultipliedAlpha, jsonXhrSettings, atlasXhrSettings)
|
|
{
|
|
var i;
|
|
var json;
|
|
var atlas;
|
|
var files = [];
|
|
var cache = loader.cacheManager.custom.spine;
|
|
|
|
// atlas can be an array of atlas files, not just a single one
|
|
|
|
if (IsPlainObject(key))
|
|
{
|
|
var config = key;
|
|
|
|
key = GetFastValue(config, 'key');
|
|
|
|
json = new JSONFile(loader, {
|
|
key: key,
|
|
url: GetFastValue(config, 'jsonURL'),
|
|
extension: GetFastValue(config, 'jsonExtension', 'json'),
|
|
xhrSettings: GetFastValue(config, 'jsonXhrSettings')
|
|
});
|
|
|
|
atlasURL = GetFastValue(config, 'atlasURL');
|
|
preMultipliedAlpha = GetFastValue(config, 'preMultipliedAlpha');
|
|
|
|
if (!Array.isArray(atlasURL))
|
|
{
|
|
atlasURL = [ atlasURL ];
|
|
}
|
|
|
|
for (i = 0; i < atlasURL.length; i++)
|
|
{
|
|
atlas = new TextFile(loader, {
|
|
key: key + '!' + i,
|
|
url: atlasURL[i],
|
|
extension: GetFastValue(config, 'atlasExtension', 'atlas'),
|
|
xhrSettings: GetFastValue(config, 'atlasXhrSettings')
|
|
});
|
|
|
|
atlas.cache = cache;
|
|
|
|
files.push(atlas);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
json = new JSONFile(loader, key, jsonURL, jsonXhrSettings);
|
|
|
|
if (!Array.isArray(atlasURL))
|
|
{
|
|
atlasURL = [ atlasURL ];
|
|
}
|
|
|
|
for (i = 0; i < atlasURL.length; i++)
|
|
{
|
|
atlas = new TextFile(loader, key + '!' + i, atlasURL[i], atlasXhrSettings);
|
|
atlas.cache = cache;
|
|
|
|
files.push(atlas);
|
|
}
|
|
}
|
|
|
|
files.unshift(json);
|
|
|
|
MultiFile.call(this, loader, 'spine', key, files);
|
|
|
|
this.config.preMultipliedAlpha = preMultipliedAlpha;
|
|
},
|
|
|
|
/**
|
|
* Called by each File when it finishes loading.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.SpineFile#onFileComplete
|
|
* @since 3.19.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - The File that has completed processing.
|
|
*/
|
|
onFileComplete: function (file)
|
|
{
|
|
var index = this.files.indexOf(file);
|
|
|
|
if (index !== -1)
|
|
{
|
|
this.pending--;
|
|
|
|
if (file.type === 'text')
|
|
{
|
|
// Inspect the data for the files to now load
|
|
var content = file.data.split('\n');
|
|
|
|
// Extract the textures
|
|
var textures = [ content[0] ];
|
|
|
|
for (var t = 0; t < content.length; t++)
|
|
{
|
|
var line = content[t];
|
|
|
|
if (line.trim() === '' && t < content.length - 1)
|
|
{
|
|
line = content[t + 1];
|
|
|
|
textures.push(line);
|
|
}
|
|
}
|
|
|
|
var config = this.config;
|
|
var loader = this.loader;
|
|
|
|
var currentBaseURL = loader.baseURL;
|
|
var currentPath = loader.path;
|
|
var currentPrefix = loader.prefix;
|
|
|
|
var baseURL = GetFastValue(config, 'baseURL', this.baseURL);
|
|
var path = GetFastValue(config, 'path', file.src.match(/^.*\//))[0];
|
|
var prefix = GetFastValue(config, 'prefix', this.prefix);
|
|
var textureXhrSettings = GetFastValue(config, 'textureXhrSettings');
|
|
|
|
loader.setBaseURL(baseURL);
|
|
loader.setPath(path);
|
|
loader.setPrefix(prefix);
|
|
|
|
for (var i = 0; i < textures.length; i++)
|
|
{
|
|
var textureURL = textures[i];
|
|
|
|
var key = textureURL;
|
|
|
|
var image = new ImageFile(loader, key, textureURL, textureXhrSettings);
|
|
|
|
if (!loader.keyExists(image))
|
|
{
|
|
this.addToMultiFile(image);
|
|
|
|
loader.addFile(image);
|
|
}
|
|
}
|
|
|
|
// Reset the loader settings
|
|
loader.setBaseURL(currentBaseURL);
|
|
loader.setPath(currentPath);
|
|
loader.setPrefix(currentPrefix);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds this file to its target cache upon successful loading and processing.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.SpineFile#addToCache
|
|
* @since 3.19.0
|
|
*/
|
|
addToCache: function ()
|
|
{
|
|
if (this.isReadyToProcess())
|
|
{
|
|
var fileJSON = this.files[0];
|
|
|
|
fileJSON.addToCache();
|
|
|
|
var atlasCache;
|
|
var atlasKey = '';
|
|
var combinedAtlasData = '';
|
|
var preMultipliedAlpha = (this.config.preMultipliedAlpha) ? true : false;
|
|
var textureManager = this.loader.textureManager;
|
|
|
|
for (var i = 1; i < this.files.length; i++)
|
|
{
|
|
var file = this.files[i];
|
|
|
|
if (file.type === 'text')
|
|
{
|
|
atlasKey = file.key.replace(/![\d]$/, '');
|
|
|
|
atlasCache = file.cache;
|
|
|
|
combinedAtlasData = combinedAtlasData.concat(file.data);
|
|
}
|
|
else
|
|
{
|
|
var src = file.key.trim();
|
|
var pos = src.indexOf('!');
|
|
var key = src.substr(pos + 1);
|
|
|
|
if (!textureManager.exists(key))
|
|
{
|
|
textureManager.addImage(key, file.data);
|
|
}
|
|
}
|
|
|
|
file.pendingDestroy();
|
|
}
|
|
|
|
atlasCache.add(atlasKey, { preMultipliedAlpha: preMultipliedAlpha, data: combinedAtlasData, prefix: this.prefix });
|
|
|
|
this.complete = true;
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = SpineFile;
|
|
|
|
|
|
/***/ }),
|
|
/* 212 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var CONST = __webpack_require__(12);
|
|
var File = __webpack_require__(24);
|
|
var FileTypesManager = __webpack_require__(25);
|
|
var GetFastValue = __webpack_require__(11);
|
|
var IsPlainObject = __webpack_require__(7);
|
|
var GetURL = __webpack_require__(48);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A single Image File suitable for loading by the Loader.
|
|
*
|
|
* These are created when you use the Phaser.Loader.LoaderPlugin#image method and are not typically created directly.
|
|
*
|
|
* For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#image.
|
|
*
|
|
* @class ImageFile
|
|
* @extends Phaser.Loader.File
|
|
* @memberof Phaser.Loader.FileTypes
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file.
|
|
* @param {(string|Phaser.Types.Loader.FileTypes.ImageFileConfig)} key - The key to use for this file, or a file configuration object.
|
|
* @param {string|string[]} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.png`, i.e. if `key` was "alien" then the URL will be "alien.png".
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file.
|
|
* @param {Phaser.Types.Loader.FileTypes.ImageFrameConfig} [frameConfig] - The frame configuration object. Only provided for, and used by, Sprite Sheets.
|
|
*/
|
|
var ImageFile = new Class({
|
|
|
|
Extends: File,
|
|
|
|
initialize:
|
|
|
|
function ImageFile (loader, key, url, xhrSettings, frameConfig)
|
|
{
|
|
var extension = 'png';
|
|
var normalMapURL;
|
|
|
|
if (IsPlainObject(key))
|
|
{
|
|
var config = key;
|
|
|
|
key = GetFastValue(config, 'key');
|
|
url = GetFastValue(config, 'url');
|
|
normalMapURL = GetFastValue(config, 'normalMap');
|
|
xhrSettings = GetFastValue(config, 'xhrSettings');
|
|
extension = GetFastValue(config, 'extension', extension);
|
|
frameConfig = GetFastValue(config, 'frameConfig');
|
|
}
|
|
|
|
if (Array.isArray(url))
|
|
{
|
|
normalMapURL = url[1];
|
|
url = url[0];
|
|
}
|
|
|
|
var fileConfig = {
|
|
type: 'image',
|
|
cache: loader.textureManager,
|
|
extension: extension,
|
|
responseType: 'blob',
|
|
key: key,
|
|
url: url,
|
|
xhrSettings: xhrSettings,
|
|
config: frameConfig
|
|
};
|
|
|
|
File.call(this, loader, fileConfig);
|
|
|
|
// Do we have a normal map to load as well?
|
|
if (normalMapURL)
|
|
{
|
|
var normalMap = new ImageFile(loader, this.key, normalMapURL, xhrSettings, frameConfig);
|
|
|
|
normalMap.type = 'normalMap';
|
|
|
|
this.setLink(normalMap);
|
|
|
|
loader.addFile(normalMap);
|
|
}
|
|
|
|
this.useImageElementLoad = loader.imageLoadType === 'HTMLImageElement';
|
|
|
|
if (this.useImageElementLoad)
|
|
{
|
|
this.load = this.loadImage;
|
|
this.onProcess = this.onProcessImage;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called automatically by Loader.nextFile.
|
|
* This method controls what extra work this File does with its loaded data.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.ImageFile#onProcess
|
|
* @since 3.7.0
|
|
*/
|
|
onProcess: function ()
|
|
{
|
|
this.state = CONST.FILE_PROCESSING;
|
|
|
|
this.data = new Image();
|
|
|
|
this.data.crossOrigin = this.crossOrigin;
|
|
|
|
var _this = this;
|
|
|
|
this.data.onload = function ()
|
|
{
|
|
File.revokeObjectURL(_this.data);
|
|
|
|
_this.onProcessComplete();
|
|
};
|
|
|
|
this.data.onerror = function ()
|
|
{
|
|
File.revokeObjectURL(_this.data);
|
|
|
|
_this.onProcessError();
|
|
};
|
|
|
|
File.createObjectURL(this.data, this.xhrLoader.response, 'image/png');
|
|
},
|
|
|
|
/**
|
|
* Handles image load processing.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.ImageFile#onProcessImage
|
|
* @private
|
|
* @since 3.60.0
|
|
*/
|
|
onProcessImage: function ()
|
|
{
|
|
var result = this.state;
|
|
|
|
this.state = CONST.FILE_PROCESSING;
|
|
|
|
if (result === CONST.FILE_LOADED)
|
|
{
|
|
this.onProcessComplete();
|
|
}
|
|
else
|
|
{
|
|
this.onProcessError();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Loads the image using either XHR or an Image tag.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.ImageFile#loadImage
|
|
* @private
|
|
* @since 3.60.0
|
|
*/
|
|
loadImage: function ()
|
|
{
|
|
this.state = CONST.FILE_LOADING;
|
|
|
|
this.src = GetURL(this, this.loader.baseURL);
|
|
|
|
if (this.src.indexOf('data:') === 0)
|
|
{
|
|
console.warn('Local data URIs are not supported: ' + this.key);
|
|
}
|
|
else
|
|
{
|
|
this.data = new Image();
|
|
|
|
this.data.crossOrigin = this.crossOrigin;
|
|
|
|
var _this = this;
|
|
|
|
this.data.onload = function ()
|
|
{
|
|
_this.state = CONST.FILE_LOADED;
|
|
|
|
_this.loader.nextFile(_this, true);
|
|
};
|
|
|
|
this.data.onerror = function ()
|
|
{
|
|
_this.loader.nextFile(_this, false);
|
|
};
|
|
|
|
this.data.src = this.src;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds this file to its target cache upon successful loading and processing.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.ImageFile#addToCache
|
|
* @since 3.7.0
|
|
*/
|
|
addToCache: function ()
|
|
{
|
|
// Check if we have a linked normal map
|
|
var linkFile = this.linkFile;
|
|
|
|
if (linkFile)
|
|
{
|
|
// We do, but has it loaded?
|
|
if (linkFile.state >= CONST.FILE_COMPLETE)
|
|
{
|
|
// Both files have loaded
|
|
if (this.type === 'normalMap')
|
|
{
|
|
// linkFile.data = Image
|
|
// this.data = Normal Map
|
|
this.cache.addImage(this.key, linkFile.data, this.data);
|
|
}
|
|
else
|
|
{
|
|
// linkFile.data = Normal Map
|
|
// this.data = Image
|
|
this.cache.addImage(this.key, this.data, linkFile.data);
|
|
}
|
|
}
|
|
|
|
// Nothing to do here, we'll use the linkFile `addToCache` call
|
|
// to process this pair
|
|
}
|
|
else
|
|
{
|
|
this.cache.addImage(this.key, this.data);
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* Adds an Image, or array of Images, to the current load queue.
|
|
*
|
|
* You can call this method from within your Scene's `preload`, along with any other files you wish to load:
|
|
*
|
|
* ```javascript
|
|
* function preload ()
|
|
* {
|
|
* this.load.image('logo', 'images/phaserLogo.png');
|
|
* }
|
|
* ```
|
|
*
|
|
* The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts,
|
|
* or if it's already running, when the next free load slot becomes available. This happens automatically if you
|
|
* are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued
|
|
* it means you cannot use the file immediately after calling this method, but must wait for the file to complete.
|
|
* The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the
|
|
* Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been
|
|
* loaded.
|
|
*
|
|
* Phaser can load all common image types: png, jpg, gif and any other format the browser can natively handle.
|
|
* If you try to load an animated gif only the first frame will be rendered. Browsers do not natively support playback
|
|
* of animated gifs to Canvas elements.
|
|
*
|
|
* The key must be a unique String. It is used to add the file to the global Texture Manager upon a successful load.
|
|
* The key should be unique both in terms of files being loaded and files already present in the Texture Manager.
|
|
* Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file
|
|
* then remove it from the Texture Manager first, before loading a new one.
|
|
*
|
|
* Instead of passing arguments you can pass a configuration object, such as:
|
|
*
|
|
* ```javascript
|
|
* this.load.image({
|
|
* key: 'logo',
|
|
* url: 'images/AtariLogo.png'
|
|
* });
|
|
* ```
|
|
*
|
|
* See the documentation for `Phaser.Types.Loader.FileTypes.ImageFileConfig` for more details.
|
|
*
|
|
* Once the file has finished loading you can use it as a texture for a Game Object by referencing its key:
|
|
*
|
|
* ```javascript
|
|
* this.load.image('logo', 'images/AtariLogo.png');
|
|
* // and later in your game ...
|
|
* this.add.image(x, y, 'logo');
|
|
* ```
|
|
*
|
|
* If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files
|
|
* key. For example, if the prefix was `MENU.` and the key was `Background` the final key will be `MENU.Background` and
|
|
* this is what you would use to retrieve the image from the Texture Manager.
|
|
*
|
|
* The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it.
|
|
*
|
|
* If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "alien"
|
|
* and no URL is given then the Loader will set the URL to be "alien.png". It will always add `.png` as the extension, although
|
|
* this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL.
|
|
*
|
|
* Phaser also supports the automatic loading of associated normal maps. If you have a normal map to go with this image,
|
|
* then you can specify it by providing an array as the `url` where the second element is the normal map:
|
|
*
|
|
* ```javascript
|
|
* this.load.image('logo', [ 'images/AtariLogo.png', 'images/AtariLogo-n.png' ]);
|
|
* ```
|
|
*
|
|
* Or, if you are using a config object use the `normalMap` property:
|
|
*
|
|
* ```javascript
|
|
* this.load.image({
|
|
* key: 'logo',
|
|
* url: 'images/AtariLogo.png',
|
|
* normalMap: 'images/AtariLogo-n.png'
|
|
* });
|
|
* ```
|
|
*
|
|
* The normal map file is subject to the same conditions as the image file with regard to the path, baseURL, CORs and XHR Settings.
|
|
* Normal maps are a WebGL only feature.
|
|
*
|
|
* In Phaser 3.60 a new property was added that allows you to control how images are loaded. By default, images are loaded via XHR as Blobs.
|
|
* However, you can set `loader.imageLoadType: "HTMLImageElement"` in the Game Configuration and instead, the Loader will load all images
|
|
* via the Image tag instead.
|
|
*
|
|
* Note: The ability to load this type of file will only be available if the Image File type has been built into Phaser.
|
|
* It is available in the default build but can be excluded from custom builds.
|
|
*
|
|
* @method Phaser.Loader.LoaderPlugin#image
|
|
* @fires Phaser.Loader.LoaderPlugin#ADD
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|Phaser.Types.Loader.FileTypes.ImageFileConfig|Phaser.Types.Loader.FileTypes.ImageFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them.
|
|
* @param {string|string[]} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.png`, i.e. if `key` was "alien" then the URL will be "alien.png".
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings.
|
|
*
|
|
* @return {this} The Loader instance.
|
|
*/
|
|
FileTypesManager.register('image', function (key, url, xhrSettings)
|
|
{
|
|
if (Array.isArray(key))
|
|
{
|
|
for (var i = 0; i < key.length; i++)
|
|
{
|
|
// If it's an array it has to be an array of Objects, so we get everything out of the 'key' object
|
|
this.addFile(new ImageFile(this, key[i]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.addFile(new ImageFile(this, key, url, xhrSettings));
|
|
}
|
|
|
|
return this;
|
|
});
|
|
|
|
module.exports = ImageFile;
|
|
|
|
|
|
/***/ }),
|
|
/* 213 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Loader Plugin Add File Event.
|
|
*
|
|
* This event is dispatched when a new file is successfully added to the Loader and placed into the load queue.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('addfile', listener)`.
|
|
*
|
|
* If you add lots of files to a Loader from a `preload` method, it will dispatch this event for each one of them.
|
|
*
|
|
* @event Phaser.Loader.Events#ADD
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} key - The unique key of the file that was added to the Loader.
|
|
* @param {string} type - The [file type]{@link Phaser.Loader.File#type} string of the file that was added to the Loader, i.e. `image`.
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event.
|
|
* @param {Phaser.Loader.File} file - A reference to the File which was added to the Loader.
|
|
*/
|
|
module.exports = 'addfile';
|
|
|
|
|
|
/***/ }),
|
|
/* 214 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Loader Plugin Complete Event.
|
|
*
|
|
* This event is dispatched when the Loader has fully processed everything in the load queue.
|
|
* By this point every loaded file will now be in its associated cache and ready for use.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('complete', listener)`.
|
|
*
|
|
* @event Phaser.Loader.Events#COMPLETE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event.
|
|
* @param {number} totalComplete - The total number of files that successfully loaded.
|
|
* @param {number} totalFailed - The total number of files that failed to load.
|
|
*/
|
|
module.exports = 'complete';
|
|
|
|
|
|
/***/ }),
|
|
/* 215 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The File Load Complete Event.
|
|
*
|
|
* This event is dispatched by the Loader Plugin when _any_ file in the queue finishes loading.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('filecomplete', listener)`.
|
|
*
|
|
* Make sure you remove this listener when you have finished, or it will continue to fire if the Scene reloads.
|
|
*
|
|
* You can also listen for the completion of a specific file. See the [FILE_KEY_COMPLETE]{@linkcode Phaser.Loader.Events#event:FILE_KEY_COMPLETE} event.
|
|
*
|
|
* @event Phaser.Loader.Events#FILE_COMPLETE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} key - The key of the file that just loaded and finished processing.
|
|
* @param {string} type - The [file type]{@link Phaser.Loader.File#type} of the file that just loaded, i.e. `image`.
|
|
* @param {any} [data] - The raw data the file contained. If the file was a multi-file, like an atlas or bitmap font, this parameter will be undefined.
|
|
*/
|
|
module.exports = 'filecomplete';
|
|
|
|
|
|
/***/ }),
|
|
/* 216 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The File Load Complete Event.
|
|
*
|
|
* This event is dispatched by the Loader Plugin when any file in the queue finishes loading.
|
|
*
|
|
* It uses a special dynamic event name constructed from the key and type of the file.
|
|
*
|
|
* For example, if you have loaded an `image` with a key of `monster`, you can listen for it
|
|
* using the following:
|
|
*
|
|
* ```javascript
|
|
* this.load.on('filecomplete-image-monster', function (key, type, data) {
|
|
* // Your handler code
|
|
* });
|
|
* ```
|
|
*
|
|
* Or, if you have loaded a texture `atlas` with a key of `Level1`:
|
|
*
|
|
* ```javascript
|
|
* this.load.on('filecomplete-atlasjson-Level1', function (key, type, data) {
|
|
* // Your handler code
|
|
* });
|
|
* ```
|
|
*
|
|
* Or, if you have loaded a sprite sheet with a key of `Explosion` and a prefix of `GAMEOVER`:
|
|
*
|
|
* ```javascript
|
|
* this.load.on('filecomplete-spritesheet-GAMEOVERExplosion', function (key, type, data) {
|
|
* // Your handler code
|
|
* });
|
|
* ```
|
|
*
|
|
* Make sure you remove your listeners when you have finished, or they will continue to fire if the Scene reloads.
|
|
*
|
|
* You can also listen for the generic completion of files. See the [FILE_COMPLETE]{@linkcode Phaser.Loader.Events#event:FILE_COMPLETE} event.
|
|
*
|
|
* @event Phaser.Loader.Events#FILE_KEY_COMPLETE
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} key - The key of the file that just loaded and finished processing.
|
|
* @param {string} type - The [file type]{@link Phaser.Loader.File#type} of the file that just loaded, i.e. `image`.
|
|
* @param {any} [data] - The raw data the file contained. If the file was a multi-file, like an atlas or bitmap font, this parameter will be undefined.
|
|
*/
|
|
module.exports = 'filecomplete-';
|
|
|
|
|
|
/***/ }),
|
|
/* 217 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The File Load Error Event.
|
|
*
|
|
* This event is dispatched by the Loader Plugin when a file fails to load.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('loaderror', listener)`.
|
|
*
|
|
* @event Phaser.Loader.Events#FILE_LOAD_ERROR
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - A reference to the File which errored during load.
|
|
*/
|
|
module.exports = 'loaderror';
|
|
|
|
|
|
/***/ }),
|
|
/* 218 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The File Load Event.
|
|
*
|
|
* This event is dispatched by the Loader Plugin when a file finishes loading,
|
|
* but _before_ it is processed and added to the internal Phaser caches.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('load', listener)`.
|
|
*
|
|
* @event Phaser.Loader.Events#FILE_LOAD
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - A reference to the File which just finished loading.
|
|
*/
|
|
module.exports = 'load';
|
|
|
|
|
|
/***/ }),
|
|
/* 219 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The File Load Progress Event.
|
|
*
|
|
* This event is dispatched by the Loader Plugin during the load of a file, if the browser receives a DOM ProgressEvent and
|
|
* the `lengthComputable` event property is true. Depending on the size of the file and browser in use, this may, or may not happen.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('fileprogress', listener)`.
|
|
*
|
|
* @event Phaser.Loader.Events#FILE_PROGRESS
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - A reference to the File which errored during load.
|
|
* @param {number} percentComplete - A value between 0 and 1 indicating how 'complete' this file is.
|
|
*/
|
|
module.exports = 'fileprogress';
|
|
|
|
|
|
/***/ }),
|
|
/* 220 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Loader Plugin Post Process Event.
|
|
*
|
|
* This event is dispatched by the Loader Plugin when the Loader has finished loading everything in the load queue.
|
|
* It is dispatched before the internal lists are cleared and each File is destroyed.
|
|
*
|
|
* Use this hook to perform any last minute processing of files that can only happen once the
|
|
* Loader has completed, but prior to it emitting the `complete` event.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('postprocess', listener)`.
|
|
*
|
|
* @event Phaser.Loader.Events#POST_PROCESS
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event.
|
|
*/
|
|
module.exports = 'postprocess';
|
|
|
|
|
|
/***/ }),
|
|
/* 221 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Loader Plugin Progress Event.
|
|
*
|
|
* This event is dispatched when the Loader updates its load progress, typically as a result of a file having completed loading.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('progress', listener)`.
|
|
*
|
|
* @event Phaser.Loader.Events#PROGRESS
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} progress - The current progress of the load. A value between 0 and 1.
|
|
*/
|
|
module.exports = 'progress';
|
|
|
|
|
|
/***/ }),
|
|
/* 222 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Loader Plugin Start Event.
|
|
*
|
|
* This event is dispatched when the Loader starts running. At this point load progress is zero.
|
|
*
|
|
* This event is dispatched even if there aren't any files in the load queue.
|
|
*
|
|
* Listen to it from a Scene using: `this.load.on('start', listener)`.
|
|
*
|
|
* @event Phaser.Loader.Events#START
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader Plugin that dispatched this event.
|
|
*/
|
|
module.exports = 'start';
|
|
|
|
|
|
/***/ }),
|
|
/* 223 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var MergeXHRSettings = __webpack_require__(49);
|
|
|
|
/**
|
|
* Creates a new XMLHttpRequest (xhr) object based on the given File and XHRSettings
|
|
* and starts the download of it. It uses the Files own XHRSettings and merges them
|
|
* with the global XHRSettings object to set the xhr values before download.
|
|
*
|
|
* @function Phaser.Loader.XHRLoader
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - The File to download.
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} globalXHRSettings - The global XHRSettings object.
|
|
*
|
|
* @return {XMLHttpRequest} The XHR object.
|
|
*/
|
|
var XHRLoader = function (file, globalXHRSettings)
|
|
{
|
|
var config = MergeXHRSettings(globalXHRSettings, file.xhrSettings);
|
|
|
|
var xhr = new XMLHttpRequest();
|
|
|
|
xhr.open('GET', file.src, config.async, config.user, config.password);
|
|
|
|
xhr.responseType = file.xhrSettings.responseType;
|
|
xhr.timeout = config.timeout;
|
|
|
|
if (config.headers)
|
|
{
|
|
for (var key in config.headers)
|
|
{
|
|
xhr.setRequestHeader(key, config.headers[key]);
|
|
}
|
|
}
|
|
|
|
if (config.header && config.headerValue)
|
|
{
|
|
xhr.setRequestHeader(config.header, config.headerValue);
|
|
}
|
|
|
|
if (config.requestedWith)
|
|
{
|
|
xhr.setRequestHeader('X-Requested-With', config.requestedWith);
|
|
}
|
|
|
|
if (config.overrideMimeType)
|
|
{
|
|
xhr.overrideMimeType(config.overrideMimeType);
|
|
}
|
|
|
|
if (config.withCredentials)
|
|
{
|
|
xhr.withCredentials = true;
|
|
}
|
|
|
|
// After a successful request, the xhr.response property will contain the requested data as a DOMString, ArrayBuffer, Blob, or Document (depending on what was set for responseType.)
|
|
|
|
xhr.onload = file.onLoad.bind(file, xhr);
|
|
xhr.onerror = file.onError.bind(file, xhr);
|
|
xhr.onprogress = file.onProgress.bind(file);
|
|
|
|
// This is the only standard method, the ones above are browser additions (maybe not universal?)
|
|
// xhr.onreadystatechange
|
|
|
|
xhr.send();
|
|
|
|
return xhr;
|
|
};
|
|
|
|
module.exports = XHRLoader;
|
|
|
|
|
|
/***/ }),
|
|
/* 224 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var CONST = __webpack_require__(12);
|
|
var File = __webpack_require__(24);
|
|
var FileTypesManager = __webpack_require__(25);
|
|
var GetFastValue = __webpack_require__(11);
|
|
var GetValue = __webpack_require__(10);
|
|
var IsPlainObject = __webpack_require__(7);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A single JSON File suitable for loading by the Loader.
|
|
*
|
|
* These are created when you use the Phaser.Loader.LoaderPlugin#json method and are not typically created directly.
|
|
*
|
|
* For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#json.
|
|
*
|
|
* @class JSONFile
|
|
* @extends Phaser.Loader.File
|
|
* @memberof Phaser.Loader.FileTypes
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file.
|
|
* @param {(string|Phaser.Types.Loader.FileTypes.JSONFileConfig)} key - The key to use for this file, or a file configuration object.
|
|
* @param {(object|string)} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, can be a fully formed JSON Object.
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file.
|
|
* @param {string} [dataKey] - When the JSON file loads only this property will be stored in the Cache.
|
|
*/
|
|
var JSONFile = new Class({
|
|
|
|
Extends: File,
|
|
|
|
initialize:
|
|
|
|
// url can either be a string, in which case it is treated like a proper url, or an object, in which case it is treated as a ready-made JS Object
|
|
// dataKey allows you to pluck a specific object out of the JSON and put just that into the cache, rather than the whole thing
|
|
|
|
function JSONFile (loader, key, url, xhrSettings, dataKey)
|
|
{
|
|
var extension = 'json';
|
|
|
|
if (IsPlainObject(key))
|
|
{
|
|
var config = key;
|
|
|
|
key = GetFastValue(config, 'key');
|
|
url = GetFastValue(config, 'url');
|
|
xhrSettings = GetFastValue(config, 'xhrSettings');
|
|
extension = GetFastValue(config, 'extension', extension);
|
|
dataKey = GetFastValue(config, 'dataKey', dataKey);
|
|
}
|
|
|
|
var fileConfig = {
|
|
type: 'json',
|
|
cache: loader.cacheManager.json,
|
|
extension: extension,
|
|
responseType: 'text',
|
|
key: key,
|
|
url: url,
|
|
xhrSettings: xhrSettings,
|
|
config: dataKey
|
|
};
|
|
|
|
File.call(this, loader, fileConfig);
|
|
|
|
// A JSON object has been provided (instead of a URL), so we'll use it directly as the File.data. No need to load it.
|
|
if (IsPlainObject(url))
|
|
{
|
|
if (dataKey)
|
|
{
|
|
this.data = GetValue(url, dataKey);
|
|
}
|
|
else
|
|
{
|
|
this.data = url;
|
|
}
|
|
|
|
this.state = CONST.FILE_POPULATED;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called automatically by Loader.nextFile.
|
|
* This method controls what extra work this File does with its loaded data.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.JSONFile#onProcess
|
|
* @since 3.7.0
|
|
*/
|
|
onProcess: function ()
|
|
{
|
|
if (this.state !== CONST.FILE_POPULATED)
|
|
{
|
|
this.state = CONST.FILE_PROCESSING;
|
|
|
|
try
|
|
{
|
|
var json = JSON.parse(this.xhrLoader.responseText);
|
|
}
|
|
catch (e)
|
|
{
|
|
this.onProcessError();
|
|
|
|
throw e;
|
|
}
|
|
|
|
var key = this.config;
|
|
|
|
if (typeof key === 'string')
|
|
{
|
|
this.data = GetValue(json, key, json);
|
|
}
|
|
else
|
|
{
|
|
this.data = json;
|
|
}
|
|
}
|
|
|
|
this.onProcessComplete();
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* Adds a JSON file, or array of JSON files, to the current load queue.
|
|
*
|
|
* You can call this method from within your Scene's `preload`, along with any other files you wish to load:
|
|
*
|
|
* ```javascript
|
|
* function preload ()
|
|
* {
|
|
* this.load.json('wavedata', 'files/AlienWaveData.json');
|
|
* }
|
|
* ```
|
|
*
|
|
* The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts,
|
|
* or if it's already running, when the next free load slot becomes available. This happens automatically if you
|
|
* are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued
|
|
* it means you cannot use the file immediately after calling this method, but must wait for the file to complete.
|
|
* The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the
|
|
* Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been
|
|
* loaded.
|
|
*
|
|
* The key must be a unique String. It is used to add the file to the global JSON Cache upon a successful load.
|
|
* The key should be unique both in terms of files being loaded and files already present in the JSON Cache.
|
|
* Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file
|
|
* then remove it from the JSON Cache first, before loading a new one.
|
|
*
|
|
* Instead of passing arguments you can pass a configuration object, such as:
|
|
*
|
|
* ```javascript
|
|
* this.load.json({
|
|
* key: 'wavedata',
|
|
* url: 'files/AlienWaveData.json'
|
|
* });
|
|
* ```
|
|
*
|
|
* See the documentation for `Phaser.Types.Loader.FileTypes.JSONFileConfig` for more details.
|
|
*
|
|
* Once the file has finished loading you can access it from its Cache using its key:
|
|
*
|
|
* ```javascript
|
|
* this.load.json('wavedata', 'files/AlienWaveData.json');
|
|
* // and later in your game ...
|
|
* var data = this.cache.json.get('wavedata');
|
|
* ```
|
|
*
|
|
* If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files
|
|
* key. For example, if the prefix was `LEVEL1.` and the key was `Waves` the final key will be `LEVEL1.Waves` and
|
|
* this is what you would use to retrieve the text from the JSON Cache.
|
|
*
|
|
* The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it.
|
|
*
|
|
* If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "data"
|
|
* and no URL is given then the Loader will set the URL to be "data.json". It will always add `.json` as the extension, although
|
|
* this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL.
|
|
*
|
|
* You can also optionally provide a `dataKey` to use. This allows you to extract only a part of the JSON and store it in the Cache,
|
|
* rather than the whole file. For example, if your JSON data had a structure like this:
|
|
*
|
|
* ```json
|
|
* {
|
|
* "level1": {
|
|
* "baddies": {
|
|
* "aliens": {},
|
|
* "boss": {}
|
|
* }
|
|
* },
|
|
* "level2": {},
|
|
* "level3": {}
|
|
* }
|
|
* ```
|
|
*
|
|
* And you only wanted to store the `boss` data in the Cache, then you could pass `level1.baddies.boss`as the `dataKey`.
|
|
*
|
|
* Note: The ability to load this type of file will only be available if the JSON File type has been built into Phaser.
|
|
* It is available in the default build but can be excluded from custom builds.
|
|
*
|
|
* @method Phaser.Loader.LoaderPlugin#json
|
|
* @fires Phaser.Loader.LoaderPlugin#ADD
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|Phaser.Types.Loader.FileTypes.JSONFileConfig|Phaser.Types.Loader.FileTypes.JSONFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them.
|
|
* @param {(object|string)} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.json`, i.e. if `key` was "alien" then the URL will be "alien.json". Or, can be a fully formed JSON Object.
|
|
* @param {string} [dataKey] - When the JSON file loads only this property will be stored in the Cache.
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings.
|
|
*
|
|
* @return {this} The Loader instance.
|
|
*/
|
|
FileTypesManager.register('json', function (key, url, dataKey, xhrSettings)
|
|
{
|
|
if (Array.isArray(key))
|
|
{
|
|
for (var i = 0; i < key.length; i++)
|
|
{
|
|
// If it's an array it has to be an array of Objects, so we get everything out of the 'key' object
|
|
this.addFile(new JSONFile(this, key[i]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.addFile(new JSONFile(this, key, url, xhrSettings, dataKey));
|
|
}
|
|
|
|
return this;
|
|
});
|
|
|
|
module.exports = JSONFile;
|
|
|
|
|
|
/***/ }),
|
|
/* 225 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var CONST = __webpack_require__(12);
|
|
var Events = __webpack_require__(47);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A MultiFile is a special kind of parent that contains two, or more, Files as children and looks after
|
|
* the loading and processing of them all. It is commonly extended and used as a base class for file types such as AtlasJSON or BitmapFont.
|
|
*
|
|
* You shouldn't create an instance of a MultiFile directly, but should extend it with your own class, setting a custom type and processing methods.
|
|
*
|
|
* @class MultiFile
|
|
* @memberof Phaser.Loader
|
|
* @constructor
|
|
* @since 3.7.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - The Loader that is going to load this File.
|
|
* @param {string} type - The file type string for sorting within the Loader.
|
|
* @param {string} key - The key of the file within the loader.
|
|
* @param {Phaser.Loader.File[]} files - An array of Files that make-up this MultiFile.
|
|
*/
|
|
var MultiFile = new Class({
|
|
|
|
initialize:
|
|
|
|
function MultiFile (loader, type, key, files)
|
|
{
|
|
var finalFiles = [];
|
|
|
|
// Clean out any potential 'null' or 'undefined' file entries
|
|
files.forEach(function (file)
|
|
{
|
|
if (file)
|
|
{
|
|
finalFiles.push(file);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* A reference to the Loader that is going to load this file.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#loader
|
|
* @type {Phaser.Loader.LoaderPlugin}
|
|
* @since 3.7.0
|
|
*/
|
|
this.loader = loader;
|
|
|
|
/**
|
|
* The file type string for sorting within the Loader.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#type
|
|
* @type {string}
|
|
* @since 3.7.0
|
|
*/
|
|
this.type = type;
|
|
|
|
/**
|
|
* Unique cache key (unique within its file type)
|
|
*
|
|
* @name Phaser.Loader.MultiFile#key
|
|
* @type {string}
|
|
* @since 3.7.0
|
|
*/
|
|
this.key = key;
|
|
|
|
/**
|
|
* The current index being used by multi-file loaders to avoid key clashes.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#multiKeyIndex
|
|
* @type {number}
|
|
* @private
|
|
* @since 3.20.0
|
|
*/
|
|
this.multiKeyIndex = loader.multiKeyIndex++;
|
|
|
|
/**
|
|
* Array of files that make up this MultiFile.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#files
|
|
* @type {Phaser.Loader.File[]}
|
|
* @since 3.7.0
|
|
*/
|
|
this.files = finalFiles;
|
|
|
|
/**
|
|
* The current state of the file. One of the FILE_CONST values.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#state
|
|
* @type {number}
|
|
* @since 3.60.0
|
|
*/
|
|
this.state = CONST.FILE_PENDING;
|
|
|
|
/**
|
|
* The completion status of this MultiFile.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#complete
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.7.0
|
|
*/
|
|
this.complete = false;
|
|
|
|
/**
|
|
* The number of files to load.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#pending
|
|
* @type {number}
|
|
* @since 3.7.0
|
|
*/
|
|
|
|
this.pending = finalFiles.length;
|
|
|
|
/**
|
|
* The number of files that failed to load.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#failed
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.7.0
|
|
*/
|
|
this.failed = 0;
|
|
|
|
/**
|
|
* A storage container for transient data that the loading files need.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#config
|
|
* @type {any}
|
|
* @since 3.7.0
|
|
*/
|
|
this.config = {};
|
|
|
|
/**
|
|
* A reference to the Loaders baseURL at the time this MultiFile was created.
|
|
* Used to populate child-files.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#baseURL
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*/
|
|
this.baseURL = loader.baseURL;
|
|
|
|
/**
|
|
* A reference to the Loaders path at the time this MultiFile was created.
|
|
* Used to populate child-files.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#path
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*/
|
|
this.path = loader.path;
|
|
|
|
/**
|
|
* A reference to the Loaders prefix at the time this MultiFile was created.
|
|
* Used to populate child-files.
|
|
*
|
|
* @name Phaser.Loader.MultiFile#prefix
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*/
|
|
this.prefix = loader.prefix;
|
|
|
|
// Link the files
|
|
for (var i = 0; i < finalFiles.length; i++)
|
|
{
|
|
finalFiles[i].multiFile = this;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Checks if this MultiFile is ready to process its children or not.
|
|
*
|
|
* @method Phaser.Loader.MultiFile#isReadyToProcess
|
|
* @since 3.7.0
|
|
*
|
|
* @return {boolean} `true` if all children of this MultiFile have loaded, otherwise `false`.
|
|
*/
|
|
isReadyToProcess: function ()
|
|
{
|
|
return (this.pending === 0 && this.failed === 0 && !this.complete);
|
|
},
|
|
|
|
/**
|
|
* Adds another child to this MultiFile, increases the pending count and resets the completion status.
|
|
*
|
|
* @method Phaser.Loader.MultiFile#addToMultiFile
|
|
* @since 3.7.0
|
|
*
|
|
* @param {Phaser.Loader.File} files - The File to add to this MultiFile.
|
|
*
|
|
* @return {Phaser.Loader.MultiFile} This MultiFile instance.
|
|
*/
|
|
addToMultiFile: function (file)
|
|
{
|
|
this.files.push(file);
|
|
|
|
file.multiFile = this;
|
|
|
|
this.pending++;
|
|
|
|
this.complete = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Called by each File when it finishes loading.
|
|
*
|
|
* @method Phaser.Loader.MultiFile#onFileComplete
|
|
* @since 3.7.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - The File that has completed processing.
|
|
*/
|
|
onFileComplete: function (file)
|
|
{
|
|
var index = this.files.indexOf(file);
|
|
|
|
if (index !== -1)
|
|
{
|
|
this.pending--;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called by each File that fails to load.
|
|
*
|
|
* @method Phaser.Loader.MultiFile#onFileFailed
|
|
* @since 3.7.0
|
|
*
|
|
* @param {Phaser.Loader.File} file - The File that has failed to load.
|
|
*/
|
|
onFileFailed: function (file)
|
|
{
|
|
var index = this.files.indexOf(file);
|
|
|
|
if (index !== -1)
|
|
{
|
|
this.failed++;
|
|
|
|
// eslint-disable-next-line no-console
|
|
console.error('File failed: %s "%s" (via %s "%s")', this.type, this.key, file.type, file.key);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called once all children of this multi file have been added to their caches and is now
|
|
* ready for deletion from the Loader.
|
|
*
|
|
* It will emit a `filecomplete` event from the LoaderPlugin.
|
|
*
|
|
* @method Phaser.Loader.MultiFile#pendingDestroy
|
|
* @fires Phaser.Loader.Events#FILE_COMPLETE
|
|
* @fires Phaser.Loader.Events#FILE_KEY_COMPLETE
|
|
* @since 3.60.0
|
|
*/
|
|
pendingDestroy: function ()
|
|
{
|
|
if (this.state === CONST.FILE_PENDING_DESTROY)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var key = this.key;
|
|
var type = this.type;
|
|
|
|
this.loader.emit(Events.FILE_COMPLETE, key, type);
|
|
this.loader.emit(Events.FILE_KEY_COMPLETE + type + '-' + key, key, type);
|
|
|
|
this.loader.flagForRemoval(this);
|
|
|
|
for (var i = 0; i < this.files.length; i++)
|
|
{
|
|
this.files[i].pendingDestroy();
|
|
}
|
|
|
|
this.state = CONST.FILE_PENDING_DESTROY;
|
|
},
|
|
|
|
/**
|
|
* Destroy this Multi File and any references it holds.
|
|
*
|
|
* @method Phaser.Loader.MultiFile#destroy
|
|
* @since 3.60.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.loader = null;
|
|
this.files = null;
|
|
this.config = null;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = MultiFile;
|
|
|
|
|
|
/***/ }),
|
|
/* 226 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var CONST = __webpack_require__(12);
|
|
var File = __webpack_require__(24);
|
|
var FileTypesManager = __webpack_require__(25);
|
|
var GetFastValue = __webpack_require__(11);
|
|
var IsPlainObject = __webpack_require__(7);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A single Text File suitable for loading by the Loader.
|
|
*
|
|
* These are created when you use the Phaser.Loader.LoaderPlugin#text method and are not typically created directly.
|
|
*
|
|
* For documentation about what all the arguments and configuration options mean please see Phaser.Loader.LoaderPlugin#text.
|
|
*
|
|
* @class TextFile
|
|
* @extends Phaser.Loader.File
|
|
* @memberof Phaser.Loader.FileTypes
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Loader.LoaderPlugin} loader - A reference to the Loader that is responsible for this file.
|
|
* @param {(string|Phaser.Types.Loader.FileTypes.TextFileConfig)} key - The key to use for this file, or a file configuration object.
|
|
* @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt".
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - Extra XHR Settings specifically for this file.
|
|
*/
|
|
var TextFile = new Class({
|
|
|
|
Extends: File,
|
|
|
|
initialize:
|
|
|
|
function TextFile (loader, key, url, xhrSettings)
|
|
{
|
|
var type = 'text';
|
|
var extension = 'txt';
|
|
var cache = loader.cacheManager.text;
|
|
|
|
if (IsPlainObject(key))
|
|
{
|
|
var config = key;
|
|
|
|
key = GetFastValue(config, 'key');
|
|
url = GetFastValue(config, 'url');
|
|
xhrSettings = GetFastValue(config, 'xhrSettings');
|
|
extension = GetFastValue(config, 'extension', extension);
|
|
type = GetFastValue(config, 'type', type);
|
|
cache = GetFastValue(config, 'cache', cache);
|
|
}
|
|
|
|
var fileConfig = {
|
|
type: type,
|
|
cache: cache,
|
|
extension: extension,
|
|
responseType: 'text',
|
|
key: key,
|
|
url: url,
|
|
xhrSettings: xhrSettings
|
|
};
|
|
|
|
File.call(this, loader, fileConfig);
|
|
},
|
|
|
|
/**
|
|
* Called automatically by Loader.nextFile.
|
|
* This method controls what extra work this File does with its loaded data.
|
|
*
|
|
* @method Phaser.Loader.FileTypes.TextFile#onProcess
|
|
* @since 3.7.0
|
|
*/
|
|
onProcess: function ()
|
|
{
|
|
this.state = CONST.FILE_PROCESSING;
|
|
|
|
this.data = this.xhrLoader.responseText;
|
|
|
|
this.onProcessComplete();
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* Adds a Text file, or array of Text files, to the current load queue.
|
|
*
|
|
* You can call this method from within your Scene's `preload`, along with any other files you wish to load:
|
|
*
|
|
* ```javascript
|
|
* function preload ()
|
|
* {
|
|
* this.load.text('story', 'files/IntroStory.txt');
|
|
* }
|
|
* ```
|
|
*
|
|
* The file is **not** loaded right away. It is added to a queue ready to be loaded either when the loader starts,
|
|
* or if it's already running, when the next free load slot becomes available. This happens automatically if you
|
|
* are calling this from within the Scene's `preload` method, or a related callback. Because the file is queued
|
|
* it means you cannot use the file immediately after calling this method, but must wait for the file to complete.
|
|
* The typical flow for a Phaser Scene is that you load assets in the Scene's `preload` method and then when the
|
|
* Scene's `create` method is called you are guaranteed that all of those assets are ready for use and have been
|
|
* loaded.
|
|
*
|
|
* The key must be a unique String. It is used to add the file to the global Text Cache upon a successful load.
|
|
* The key should be unique both in terms of files being loaded and files already present in the Text Cache.
|
|
* Loading a file using a key that is already taken will result in a warning. If you wish to replace an existing file
|
|
* then remove it from the Text Cache first, before loading a new one.
|
|
*
|
|
* Instead of passing arguments you can pass a configuration object, such as:
|
|
*
|
|
* ```javascript
|
|
* this.load.text({
|
|
* key: 'story',
|
|
* url: 'files/IntroStory.txt'
|
|
* });
|
|
* ```
|
|
*
|
|
* See the documentation for `Phaser.Types.Loader.FileTypes.TextFileConfig` for more details.
|
|
*
|
|
* Once the file has finished loading you can access it from its Cache using its key:
|
|
*
|
|
* ```javascript
|
|
* this.load.text('story', 'files/IntroStory.txt');
|
|
* // and later in your game ...
|
|
* var data = this.cache.text.get('story');
|
|
* ```
|
|
*
|
|
* If you have specified a prefix in the loader, via `Loader.setPrefix` then this value will be prepended to this files
|
|
* key. For example, if the prefix was `LEVEL1.` and the key was `Story` the final key will be `LEVEL1.Story` and
|
|
* this is what you would use to retrieve the text from the Text Cache.
|
|
*
|
|
* The URL can be relative or absolute. If the URL is relative the `Loader.baseURL` and `Loader.path` values will be prepended to it.
|
|
*
|
|
* If the URL isn't specified the Loader will take the key and create a filename from that. For example if the key is "story"
|
|
* and no URL is given then the Loader will set the URL to be "story.txt". It will always add `.txt` as the extension, although
|
|
* this can be overridden if using an object instead of method arguments. If you do not desire this action then provide a URL.
|
|
*
|
|
* Note: The ability to load this type of file will only be available if the Text File type has been built into Phaser.
|
|
* It is available in the default build but can be excluded from custom builds.
|
|
*
|
|
* @method Phaser.Loader.LoaderPlugin#text
|
|
* @fires Phaser.Loader.LoaderPlugin#ADD
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|Phaser.Types.Loader.FileTypes.TextFileConfig|Phaser.Types.Loader.FileTypes.TextFileConfig[])} key - The key to use for this file, or a file configuration object, or array of them.
|
|
* @param {string} [url] - The absolute or relative URL to load this file from. If undefined or `null` it will be set to `<key>.txt`, i.e. if `key` was "alien" then the URL will be "alien.txt".
|
|
* @param {Phaser.Types.Loader.XHRSettingsObject} [xhrSettings] - An XHR Settings configuration object. Used in replacement of the Loaders default XHR Settings.
|
|
*
|
|
* @return {this} The Loader instance.
|
|
*/
|
|
FileTypesManager.register('text', function (key, url, xhrSettings)
|
|
{
|
|
if (Array.isArray(key))
|
|
{
|
|
for (var i = 0; i < key.length; i++)
|
|
{
|
|
// If it's an array it has to be an array of Objects, so we get everything out of the 'key' object
|
|
this.addFile(new TextFile(this, key[i]));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.addFile(new TextFile(this, key, url, xhrSettings));
|
|
}
|
|
|
|
return this;
|
|
});
|
|
|
|
module.exports = TextFile;
|
|
|
|
|
|
/***/ }),
|
|
/* 227 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var AngleBetween = __webpack_require__(31);
|
|
var Clamp = __webpack_require__(1);
|
|
var Class = __webpack_require__(0);
|
|
var ComponentsComputedSize = __webpack_require__(51);
|
|
var ComponentsDepth = __webpack_require__(52);
|
|
var ComponentsFlip = __webpack_require__(53);
|
|
var ComponentsScrollFactor = __webpack_require__(54);
|
|
var ComponentsTransform = __webpack_require__(55);
|
|
var ComponentsVisible = __webpack_require__(56);
|
|
var CounterClockwise = __webpack_require__(8);
|
|
var DegToRad = __webpack_require__(21);
|
|
var GameObject = __webpack_require__(57);
|
|
var RadToDeg = __webpack_require__(9);
|
|
var SpineEvents = __webpack_require__(249);
|
|
var SpineGameObjectRender = __webpack_require__(256);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Spine Game Object is a Phaser level object that can be added to your Phaser Scenes. It encapsulates
|
|
* a Spine Skeleton with Spine Animation Data and Animation State, with helper methods to allow you to
|
|
* easily change the skin, slot attachment, bone positions and more.
|
|
*
|
|
* Spine Game Objects can be created via the Game Object Factory, Game Object Creator, or directly.
|
|
* You can only create them if the Spine plugin has been loaded into Phaser.
|
|
*
|
|
* The quickest way is the Game Object Factory:
|
|
*
|
|
* ```javascript
|
|
* let jelly = this.add.spine(512, 550, 'jelly', 'jelly-think', true);
|
|
* ```
|
|
*
|
|
* Here we are creating a new Spine Game Object positioned at 512 x 550. It's using the `jelly`
|
|
* Spine data, which has previously been loaded into your Scene. The `jelly-think` argument is
|
|
* an optional animation to start playing on the skeleton. The final argument `true` sets the
|
|
* animation to loop. Look at the documentation for further details on each of these options.
|
|
*
|
|
* For more control, you can use the Game Object Creator, passing in a Spine Game Object
|
|
* Configuration object:
|
|
*
|
|
* ```javascript
|
|
* let jelly = this.make.spine({
|
|
* x: 512, y: 550, key: 'jelly',
|
|
* scale: 1.5,
|
|
* skinName: 'square_Green',
|
|
* animationName: 'jelly-think', loop: true,
|
|
* slotName: 'hat', attachmentName: 'images/La_14'
|
|
* });
|
|
* ```
|
|
*
|
|
* Here, you've got the ability to specify extra details, such as the slot name, attachments or
|
|
* overall scale.
|
|
*
|
|
* If you wish to instantiate a Spine Game Object directly you can do so, but in order for it to
|
|
* update and render, it must be added to the display and update lists of your Scene:
|
|
*
|
|
* ```javascript
|
|
* let jelly = new SpineGameObject(this, this.spine, 512, 550, 'jelly', 'jelly-think', true);
|
|
* this.sys.displayList.add(jelly);
|
|
* this.sys.updateList.add(jelly);
|
|
* ```
|
|
*
|
|
* It's possible to enable Spine Game Objects for input, but you should be aware that it will use
|
|
* the bounds of the skeletons current pose to create the hit area from. Ensure that your setup
|
|
* post in the Spine Editor does _not_ have everything turned off, or the runtimes will be unable
|
|
* to get an accurate bounds. You can make use of the `InputPlugin.enableDebug` method to view the
|
|
* input shape being created. If it's not suitable, provide your own shape to the `setInteractive` method.
|
|
*
|
|
* Due to the way Spine handles scaling, it's not recommended to enable a Spine Game Object for
|
|
* physics directly. Instead, you should look at creating a proxy body and syncing the Spine Game
|
|
* Object position with it. See the examples for further details.
|
|
*
|
|
* If your Spine Game Object has black outlines around the different parts of the texture when it
|
|
* renders then you have exported the files from Spine with pre-multiplied alpha enabled, but have
|
|
* forgotten to set that flag when loading the Spine data. Please see the loader docs for more details.
|
|
*
|
|
* @class SpineGameObject
|
|
* @extends Phaser.GameObjects.GameObject
|
|
* @constructor
|
|
* @since 3.19.0
|
|
*
|
|
* @param {Phaser.Scene} scene - A reference to the Scene that this Game Object belongs to.
|
|
* @param {SpinePlugin} pluginManager - A reference to the Phaser Spine Plugin.
|
|
* @param {number} x - The horizontal position of this Game Object in the world.
|
|
* @param {number} y - The vertical position of this Game Object in the world.
|
|
* @param {string} [key] - The key of the Spine Skeleton this Game Object will use, as stored in the Spine Plugin.
|
|
* @param {string} [animationName] - The name of the animation to set on this Skeleton.
|
|
* @param {boolean} [loop=false] - Should the animation playback be looped or not?
|
|
*/
|
|
var SpineGameObject = new Class({
|
|
|
|
Extends: GameObject,
|
|
|
|
Mixins: [
|
|
ComponentsComputedSize,
|
|
ComponentsDepth,
|
|
ComponentsFlip,
|
|
ComponentsScrollFactor,
|
|
ComponentsTransform,
|
|
ComponentsVisible,
|
|
SpineGameObjectRender
|
|
],
|
|
|
|
initialize:
|
|
|
|
function SpineGameObject (scene, plugin, x, y, key, animationName, loop)
|
|
{
|
|
GameObject.call(this, scene, 'Spine');
|
|
|
|
/**
|
|
* A reference to the Spine Plugin.
|
|
*
|
|
* @name SpineGameObject#plugin
|
|
* @type {SpinePlugin}
|
|
* @since 3.19.0
|
|
*/
|
|
this.plugin = plugin;
|
|
|
|
/**
|
|
* The Spine Skeleton this Game Object is using.
|
|
*
|
|
* @name SpineGameObject#skeleton
|
|
* @type {spine.Skeleton}
|
|
* @since 3.19.0
|
|
*/
|
|
this.skeleton = null;
|
|
|
|
/**
|
|
* The Spine Skeleton Data associated with the Skeleton this Game Object is using.
|
|
*
|
|
* @name SpineGameObject#skeletonData
|
|
* @type {spine.SkeletonData}
|
|
* @since 3.19.0
|
|
*/
|
|
this.skeletonData = null;
|
|
|
|
/**
|
|
* The Spine Animation State this Game Object is using.
|
|
*
|
|
* @name SpineGameObject#state
|
|
* @type {spine.AnimationState}
|
|
* @since 3.19.0
|
|
*/
|
|
this.state = null;
|
|
|
|
/**
|
|
* The Spine Animation State Data associated with the Animation State this Game Object is using.
|
|
*
|
|
* @name SpineGameObject#stateData
|
|
* @type {spine.AnimationStateData}
|
|
* @since 3.19.0
|
|
*/
|
|
this.stateData = null;
|
|
|
|
/**
|
|
* A reference to the root bone of the Skeleton.
|
|
*
|
|
* @name SpineGameObject#root
|
|
* @type {spine.Bone}
|
|
* @since 3.19.0
|
|
*/
|
|
this.root = null;
|
|
|
|
/**
|
|
* This object holds the calculated bounds of the current
|
|
* pose, as set when a new Skeleton is applied.
|
|
*
|
|
* @name SpineGameObject#bounds
|
|
* @type {any}
|
|
* @since 3.19.0
|
|
*/
|
|
this.bounds = null;
|
|
|
|
/**
|
|
* A Game Object level flag that allows you to enable debug drawing
|
|
* to the Skeleton Debug Renderer by toggling it.
|
|
*
|
|
* @name SpineGameObject#drawDebug
|
|
* @type {boolean}
|
|
* @since 3.19.0
|
|
*/
|
|
this.drawDebug = false;
|
|
|
|
/**
|
|
* The factor to scale the Animation update time by.
|
|
*
|
|
* @name SpineGameObject#timeScale
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
this.timeScale = 1;
|
|
|
|
/**
|
|
* The calculated Display Origin of this Game Object.
|
|
*
|
|
* @name SpineGameObject#displayOriginX
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
this.displayOriginX = 0;
|
|
|
|
/**
|
|
* The calculated Display Origin of this Game Object.
|
|
*
|
|
* @name SpineGameObject#displayOriginY
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
this.displayOriginY = 0;
|
|
|
|
/**
|
|
* A flag that stores if the texture associated with the current
|
|
* Skin being used by this Game Object, has its alpha pre-multiplied
|
|
* into it, or not.
|
|
*
|
|
* @name SpineGameObject#preMultipliedAlpha
|
|
* @type {boolean}
|
|
* @since 3.19.0
|
|
*/
|
|
this.preMultipliedAlpha = false;
|
|
|
|
/**
|
|
* A default Blend Mode. You cannot change the blend mode of a
|
|
* Spine Game Object.
|
|
*
|
|
* @name SpineGameObject#blendMode
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.19.0
|
|
*/
|
|
this.blendMode = -1;
|
|
|
|
this.setPosition(x, y);
|
|
|
|
if (key)
|
|
{
|
|
this.setSkeleton(key, animationName, loop);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Returns `true` if this Spine Game Object both has a skeleton and
|
|
* also passes the render tests for the given Camera.
|
|
*
|
|
* @method SpineGameObject#willRender
|
|
* @since 3.19.0
|
|
*
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {SpineContainer} [container] - If this Spine object is in a Spine Container, this is a reference to it.
|
|
*
|
|
* @return {boolean} `true` if this Game Object should be rendered, otherwise `false`.
|
|
*/
|
|
willRender: function (camera, container)
|
|
{
|
|
var GameObjectRenderMask = 15;
|
|
|
|
var result = (!this.skeleton || !(GameObjectRenderMask !== this.renderFlags || (this.cameraFilter !== 0 && (this.cameraFilter & camera.id))));
|
|
|
|
if (!container && !result && this.parentContainer)
|
|
{
|
|
var plugin = this.plugin;
|
|
var sceneRenderer = plugin.sceneRenderer;
|
|
|
|
if (plugin.gl && sceneRenderer.batcher.isDrawing)
|
|
{
|
|
sceneRenderer.end();
|
|
|
|
plugin.renderer.pipelines.rebind();
|
|
}
|
|
}
|
|
|
|
return result;
|
|
},
|
|
|
|
/**
|
|
* Set the Alpha level for the whole Skeleton of this Game Object.
|
|
*
|
|
* The alpha controls the opacity of the Game Object as it renders.
|
|
*
|
|
* Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque.
|
|
*
|
|
* @method SpineGameObject#setAlpha
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} [value=1] - The alpha value used for the whole Skeleton.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setAlpha: function (value, slotName)
|
|
{
|
|
if (value === undefined) { value = 1; }
|
|
|
|
if (slotName)
|
|
{
|
|
var slot = this.findSlot(slotName);
|
|
|
|
if (slot)
|
|
{
|
|
slot.color.a = Clamp(value, 0, 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.alpha = value;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* The alpha value of the Skeleton.
|
|
*
|
|
* A value between 0 and 1.
|
|
*
|
|
* This is a global value, impacting the entire Skeleton, not just a region of it.
|
|
*
|
|
* @name SpineGameObject#alpha
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
alpha: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.skeleton.color.a;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
if (this.skeleton)
|
|
{
|
|
this.skeleton.color.a = v;
|
|
}
|
|
|
|
if (v === 0)
|
|
{
|
|
this.renderFlags &= ~2;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= 2;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The amount of red used when rendering the Skeleton.
|
|
*
|
|
* A value between 0 and 1.
|
|
*
|
|
* This is a global value, impacting the entire Skeleton, not just a region of it.
|
|
*
|
|
* @name SpineGameObject#red
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
red: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.skeleton.color.r;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
if (this.skeleton)
|
|
{
|
|
this.skeleton.color.r = v;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The amount of green used when rendering the Skeleton.
|
|
*
|
|
* A value between 0 and 1.
|
|
*
|
|
* This is a global value, impacting the entire Skeleton, not just a region of it.
|
|
*
|
|
* @name SpineGameObject#green
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
green: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.skeleton.color.g;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
if (this.skeleton)
|
|
{
|
|
this.skeleton.color.g = v;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The amount of blue used when rendering the Skeleton.
|
|
*
|
|
* A value between 0 and 1.
|
|
*
|
|
* This is a global value, impacting the entire Skeleton, not just a region of it.
|
|
*
|
|
* @name SpineGameObject#blue
|
|
* @type {number}
|
|
* @since 3.19.0
|
|
*/
|
|
blue: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.skeleton.color.b;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
if (this.skeleton)
|
|
{
|
|
this.skeleton.color.b = v;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Sets the color on the given attachment slot. Or, if no slot is given, on the whole skeleton.
|
|
*
|
|
* @method SpineGameObject#setColor
|
|
* @since 3.19.0
|
|
*
|
|
* @param {integer} [color=0xffffff] - The color being applied to the Skeleton or named Slot. Set to white to disable any previously set color.
|
|
* @param {string} [slotName] - The name of the slot to set the color on. If not give, will be set on the whole skeleton.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setColor: function (color, slotName)
|
|
{
|
|
if (color === undefined) { color = 0xffffff; }
|
|
|
|
var red = (color >> 16 & 0xFF) / 255;
|
|
var green = (color >> 8 & 0xFF) / 255;
|
|
var blue = (color & 0xFF) / 255;
|
|
var alpha = (color > 16777215) ? (color >>> 24) / 255 : null;
|
|
|
|
var target = this.skeleton;
|
|
|
|
if (slotName)
|
|
{
|
|
var slot = this.findSlot(slotName);
|
|
|
|
if (slot)
|
|
{
|
|
target = slot;
|
|
}
|
|
}
|
|
|
|
target.color.r = red;
|
|
target.color.g = green;
|
|
target.color.b = blue;
|
|
|
|
if (alpha !== null)
|
|
{
|
|
target.color.a = alpha;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets this Game Object to use the given Skeleton based on the Atlas Data Key and a provided JSON object
|
|
* that contains the Skeleton data.
|
|
*
|
|
* @method SpineGameObject#setSkeletonFromJSON
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} atlasDataKey - The key of the Spine data to use for this Skeleton.
|
|
* @param {object} skeletonJSON - The JSON data for the Skeleton.
|
|
* @param {string} [animationName] - Optional name of the animation to set on the Skeleton.
|
|
* @param {boolean} [loop=false] - Should the animation, if set, loop or not?
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setSkeletonFromJSON: function (atlasDataKey, skeletonJSON, animationName, loop)
|
|
{
|
|
return this.setSkeleton(atlasDataKey, skeletonJSON, animationName, loop);
|
|
},
|
|
|
|
/**
|
|
* Sets this Game Object to use the given Skeleton based on its cache key.
|
|
*
|
|
* Typically, once set, the Skeleton doesn't change. Instead, you change the skin,
|
|
* or slot attachment, or any other property to adjust it.
|
|
*
|
|
* @method SpineGameObject#setSkeleton
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} atlasDataKey - The key of the Spine data to use for this Skeleton.
|
|
* @param {string} [animationName] - Optional name of the animation to set on the Skeleton.
|
|
* @param {boolean} [loop=false] - Should the animation, if set, loop or not?
|
|
* @param {object} [skeletonJSON] - The JSON data for the Skeleton.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setSkeleton: function (atlasDataKey, animationName, loop, skeletonJSON)
|
|
{
|
|
if (this.state)
|
|
{
|
|
this.state.clearListeners();
|
|
this.state.clearListenerNotifications();
|
|
}
|
|
|
|
var data = this.plugin.createSkeleton(atlasDataKey, skeletonJSON);
|
|
|
|
this.skeletonData = data.skeletonData;
|
|
|
|
this.preMultipliedAlpha = data.preMultipliedAlpha;
|
|
|
|
var skeleton = data.skeleton;
|
|
|
|
skeleton.setSkin();
|
|
skeleton.setToSetupPose();
|
|
|
|
this.skeleton = skeleton;
|
|
|
|
// AnimationState
|
|
data = this.plugin.createAnimationState(skeleton);
|
|
|
|
if (this.state)
|
|
{
|
|
this.state.clearListeners();
|
|
this.state.clearListenerNotifications();
|
|
}
|
|
|
|
this.state = data.state;
|
|
this.stateData = data.stateData;
|
|
|
|
this.state.addListener({
|
|
event: this.onEvent.bind(this),
|
|
complete: this.onComplete.bind(this),
|
|
start: this.onStart.bind(this),
|
|
end: this.onEnd.bind(this),
|
|
dispose: this.onDispose.bind(this),
|
|
interrupted: this.onInterrupted.bind(this)
|
|
});
|
|
|
|
if (animationName)
|
|
{
|
|
this.setAnimation(0, animationName, loop);
|
|
}
|
|
|
|
this.root = this.getRootBone();
|
|
|
|
if (this.root)
|
|
{
|
|
// +90 degrees to account for the difference in Spine vs. Phaser rotation
|
|
this.root.rotation = RadToDeg(CounterClockwise(this.rotation)) + 90;
|
|
}
|
|
|
|
this.state.apply(skeleton);
|
|
|
|
skeleton.updateCache();
|
|
|
|
return this.updateSize();
|
|
},
|
|
|
|
/**
|
|
* Internal event handler that emits the Spine onComplete event via this Game Object.
|
|
*
|
|
* @method SpineGameObject#onComplete
|
|
* @fires SpinePluginEvents#COMPLETE
|
|
* @private
|
|
* @since 3.19.0
|
|
*
|
|
* @param {any} entry - The event data from Spine.
|
|
*/
|
|
onComplete: function (entry)
|
|
{
|
|
this.emit(SpineEvents.COMPLETE, entry);
|
|
},
|
|
|
|
/**
|
|
* Internal event handler that emits the Spine onDispose event via this Game Object.
|
|
*
|
|
* @method SpineGameObject#onDispose
|
|
* @fires SpinePluginEvents#DISPOSE
|
|
* @private
|
|
* @since 3.19.0
|
|
*
|
|
* @param {any} entry - The event data from Spine.
|
|
*/
|
|
onDispose: function (entry)
|
|
{
|
|
this.emit(SpineEvents.DISPOSE, entry);
|
|
},
|
|
|
|
/**
|
|
* Internal event handler that emits the Spine onEnd event via this Game Object.
|
|
*
|
|
* @method SpineGameObject#onEnd
|
|
* @fires SpinePluginEvents#END
|
|
* @private
|
|
* @since 3.19.0
|
|
*
|
|
* @param {any} entry - The event data from Spine.
|
|
*/
|
|
onEnd: function (entry)
|
|
{
|
|
this.emit(SpineEvents.END, entry);
|
|
},
|
|
|
|
/**
|
|
* Internal event handler that emits the Spine Event event via this Game Object.
|
|
*
|
|
* @method SpineGameObject#onEvent
|
|
* @fires SpinePluginEvents#EVENT
|
|
* @private
|
|
* @since 3.19.0
|
|
*
|
|
* @param {any} entry - The event data from Spine.
|
|
* @param {spine.Event} event - The Spine event.
|
|
*/
|
|
onEvent: function (entry, event)
|
|
{
|
|
this.emit(SpineEvents.EVENT, entry, event);
|
|
},
|
|
|
|
/**
|
|
* Internal event handler that emits the Spine onInterrupted event via this Game Object.
|
|
*
|
|
* @method SpineGameObject#onInterrupted
|
|
* @fires SpinePluginEvents#INTERRUPTED
|
|
* @private
|
|
* @since 3.19.0
|
|
*
|
|
* @param {any} entry - The event data from Spine.
|
|
*/
|
|
onInterrupted: function (entry)
|
|
{
|
|
this.emit(SpineEvents.INTERRUPTED, entry);
|
|
},
|
|
|
|
/**
|
|
* Internal event handler that emits the Spine onStart event via this Game Object.
|
|
*
|
|
* @method SpineGameObject#onStart
|
|
* @fires SpinePluginEvents#START
|
|
* @private
|
|
* @since 3.19.0
|
|
*
|
|
* @param {any} entry - The event data from Spine.
|
|
*/
|
|
onStart: function (entry)
|
|
{
|
|
this.emit(SpineEvents.START, entry);
|
|
},
|
|
|
|
/**
|
|
* Refreshes the data about the current Skeleton.
|
|
*
|
|
* This will reset the rotation, position and size of the Skeleton to match this Game Object.
|
|
*
|
|
* Call this method if you need to access the Skeleton data directly, and it may have changed
|
|
* recently.
|
|
*
|
|
* @method SpineGameObject#refresh
|
|
* @since 3.19.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
refresh: function ()
|
|
{
|
|
if (this.root)
|
|
{
|
|
// +90 degrees to account for the difference in Spine vs. Phaser rotation
|
|
this.root.rotation = RadToDeg(CounterClockwise(this.rotation)) + 90;
|
|
}
|
|
|
|
this.updateSize();
|
|
|
|
this.skeleton.updateCache();
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the size of this Game Object.
|
|
*
|
|
* If no arguments are given it uses the current skeleton data dimensions.
|
|
*
|
|
* You can use this method to set a fixed size of this Game Object, such as for input detection,
|
|
* when the skeleton data doesn't match what is required in-game.
|
|
*
|
|
* @method SpineGameObject#setSize
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} [width] - The width of the Skeleton. If not given it defaults to the Skeleton Data width.
|
|
* @param {number} [height] - The height of the Skeleton. If not given it defaults to the Skeleton Data height.
|
|
* @param {number} [offsetX=0] - The horizontal offset of the Skeleton from its x and y coordinate.
|
|
* @param {number} [offsetY=0] - The vertical offset of the Skeleton from its x and y coordinate.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setSize: function (width, height, offsetX, offsetY)
|
|
{
|
|
var skeleton = this.skeleton;
|
|
|
|
if (width === undefined) { width = skeleton.data.width; }
|
|
if (height === undefined) { height = skeleton.data.height; }
|
|
if (offsetX === undefined) { offsetX = 0; }
|
|
if (offsetY === undefined) { offsetY = 0; }
|
|
|
|
this.width = width;
|
|
this.height = height;
|
|
|
|
this.displayOriginX = skeleton.x - offsetX;
|
|
this.displayOriginY = skeleton.y - offsetY;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the offset of this Game Object from the Skeleton position.
|
|
*
|
|
* You can use this method to adjust how the position of this Game Object relates to the Skeleton it is using.
|
|
*
|
|
* @method SpineGameObject#setOffset
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} [offsetX=0] - The horizontal offset of the Skeleton from its x and y coordinate.
|
|
* @param {number} [offsetY=0] - The vertical offset of the Skeleton from its x and y coordinate.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setOffset: function (offsetX, offsetY)
|
|
{
|
|
var skeleton = this.skeleton;
|
|
|
|
if (offsetX === undefined) { offsetX = 0; }
|
|
if (offsetY === undefined) { offsetY = 0; }
|
|
|
|
this.displayOriginX = skeleton.x - offsetX;
|
|
this.displayOriginY = skeleton.y - offsetY;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Internal method that syncs all of the Game Object position and scale data to the Skeleton.
|
|
* It then syncs the skeleton bounds back to this Game Object.
|
|
*
|
|
* This method is called automatically as needed internally, however, it's also exposed should
|
|
* you require overriding the size settings.
|
|
*
|
|
* @method SpineGameObject#updateSize
|
|
* @since 3.19.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
updateSize: function ()
|
|
{
|
|
var skeleton = this.skeleton;
|
|
var renderer = this.plugin.renderer;
|
|
|
|
var height = renderer.height;
|
|
|
|
var oldScaleX = this.scaleX;
|
|
var oldScaleY = this.scaleY;
|
|
|
|
skeleton.x = this.x;
|
|
skeleton.y = height - this.y;
|
|
skeleton.scaleX = 1;
|
|
skeleton.scaleY = 1;
|
|
|
|
skeleton.updateWorldTransform();
|
|
|
|
var bounds = this.getBounds();
|
|
|
|
this.width = bounds.size.x;
|
|
this.height = bounds.size.y;
|
|
|
|
this.displayOriginX = this.x - bounds.offset.x;
|
|
this.displayOriginY = this.y - (height - (this.height + bounds.offset.y));
|
|
|
|
skeleton.scaleX = oldScaleX;
|
|
skeleton.scaleY = oldScaleY;
|
|
|
|
skeleton.updateWorldTransform();
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* The horizontal scale of this Game Object, as applied to the Skeleton it is using.
|
|
*
|
|
* @name SpineGameObject#scaleX
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.19.0
|
|
*/
|
|
scaleX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._scaleX;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._scaleX = value;
|
|
|
|
this.refresh();
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The vertical scale of this Game Object, as applied to the Skeleton it is using.
|
|
*
|
|
* @name SpineGameObject#scaleY
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.19.0
|
|
*/
|
|
scaleY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._scaleY;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._scaleY = value;
|
|
|
|
this.refresh();
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Returns an array containing the names of all the bones in the Skeleton Data.
|
|
*
|
|
* @method SpineGameObject#getBoneList
|
|
* @since 3.19.0
|
|
*
|
|
* @return {string[]} An array containing the names of all the bones in the Skeleton Data.
|
|
*/
|
|
getBoneList: function ()
|
|
{
|
|
var output = [];
|
|
|
|
var skeletonData = this.skeletonData;
|
|
|
|
if (skeletonData)
|
|
{
|
|
for (var i = 0; i < skeletonData.bones.length; i++)
|
|
{
|
|
output.push(skeletonData.bones[i].name);
|
|
}
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Returns an array containing the names of all the skins in the Skeleton Data.
|
|
*
|
|
* @method SpineGameObject#getSkinList
|
|
* @since 3.19.0
|
|
*
|
|
* @return {string[]} An array containing the names of all the skins in the Skeleton Data.
|
|
*/
|
|
getSkinList: function ()
|
|
{
|
|
var output = [];
|
|
|
|
var skeletonData = this.skeletonData;
|
|
|
|
if (skeletonData)
|
|
{
|
|
for (var i = 0; i < skeletonData.skins.length; i++)
|
|
{
|
|
output.push(skeletonData.skins[i].name);
|
|
}
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Returns an array containing the names of all the slots in the Skeleton.
|
|
*
|
|
* @method SpineGameObject#getSlotList
|
|
* @since 3.19.0
|
|
*
|
|
* @return {string[]} An array containing the names of all the slots in the Skeleton.
|
|
*/
|
|
getSlotList: function ()
|
|
{
|
|
var output = [];
|
|
|
|
var skeleton = this.skeleton;
|
|
|
|
for (var i = 0; i < skeleton.slots.length; i++)
|
|
{
|
|
output.push(skeleton.slots[i].data.name);
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Returns an array containing the names of all the animations in the Skeleton Data.
|
|
*
|
|
* @method SpineGameObject#getAnimationList
|
|
* @since 3.19.0
|
|
*
|
|
* @return {string[]} An array containing the names of all the animations in the Skeleton Data.
|
|
*/
|
|
getAnimationList: function ()
|
|
{
|
|
var output = [];
|
|
|
|
var skeletonData = this.skeletonData;
|
|
|
|
if (skeletonData)
|
|
{
|
|
for (var i = 0; i < skeletonData.animations.length; i++)
|
|
{
|
|
output.push(skeletonData.animations[i].name);
|
|
}
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Returns the current animation being played on the given track, if any.
|
|
*
|
|
* @method SpineGameObject#getCurrentAnimation
|
|
* @since 3.19.0
|
|
*
|
|
* @param {integer} [trackIndex=0] - The track to return the current animation on.
|
|
*
|
|
* @return {?spine.Animation} The current Animation on the given track, or `undefined` if there is no current animation.
|
|
*/
|
|
getCurrentAnimation: function (trackIndex)
|
|
{
|
|
if (trackIndex === undefined) { trackIndex = 0; }
|
|
|
|
var current = this.state.getCurrent(trackIndex);
|
|
|
|
if (current)
|
|
{
|
|
return current.animation;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sets the current animation for a track, discarding any queued animations.
|
|
* If the formerly current track entry was never applied to a skeleton, it is replaced (not mixed from).
|
|
*
|
|
* Animations are referenced by a unique string-based key, as defined in the Spine software.
|
|
*
|
|
* @method SpineGameObject#play
|
|
* @fires SpinePluginEvents#START
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} animationName - The string-based key of the animation to play.
|
|
* @param {boolean} [loop=false] - Should the animation be looped when played?
|
|
* @param {boolean} [ignoreIfPlaying=false] - If this animation is already playing then ignore this call.
|
|
*
|
|
* @return {this} This Game Object. If you need the TrackEntry, see `setAnimation` instead.
|
|
*/
|
|
play: function (animationName, loop, ignoreIfPlaying)
|
|
{
|
|
this.setAnimation(0, animationName, loop, ignoreIfPlaying);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the current animation for a track, discarding any queued animations.
|
|
* If the formerly current track entry was never applied to a skeleton, it is replaced (not mixed from).
|
|
*
|
|
* Animations are referenced by a unique string-based key, as defined in the Spine software.
|
|
*
|
|
* @method SpineGameObject#setAnimation
|
|
* @fires SpinePluginEvents#START
|
|
* @since 3.19.0
|
|
*
|
|
* @param {integer} trackIndex - The track index to play the animation on.
|
|
* @param {string} animationName - The string-based key of the animation to play.
|
|
* @param {boolean} [loop=false] - Should the animation be looped when played?
|
|
* @param {boolean} [ignoreIfPlaying=false] - If the animation specified by the track index is already playing then ignore this call.
|
|
*
|
|
* @return {spine.TrackEntry} A track entry to allow further customization of animation playback.
|
|
*/
|
|
setAnimation: function (trackIndex, animationName, loop, ignoreIfPlaying)
|
|
{
|
|
if (loop === undefined) { loop = false; }
|
|
if (ignoreIfPlaying === undefined) { ignoreIfPlaying = false; }
|
|
|
|
if (ignoreIfPlaying && this.state)
|
|
{
|
|
var currentTrack = this.state.getCurrent(trackIndex);
|
|
|
|
if (currentTrack && currentTrack.animation.name === animationName && !currentTrack.isComplete())
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (this.findAnimation(animationName))
|
|
{
|
|
return this.state.setAnimation(trackIndex, animationName, loop);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Adds an animation to be played after the current or last queued animation for a track.
|
|
* If the track is empty, it is equivalent to calling setAnimation.
|
|
*
|
|
* Animations are referenced by a unique string-based key, as defined in the Spine software.
|
|
*
|
|
* The delay is a float. If > 0, sets delay. If <= 0, the delay set is the duration of the previous
|
|
* track entry minus any mix duration (from the AnimationStateData) plus the specified delay
|
|
* (ie the mix ends at (delay = 0) or before (delay < 0) the previous track entry duration).
|
|
* If the previous entry is looping, its next loop completion is used instead of its duration.
|
|
*
|
|
* @method SpineGameObject#addAnimation
|
|
* @since 3.19.0
|
|
*
|
|
* @param {integer} trackIndex - The track index to add the animation to.
|
|
* @param {string} animationName - The string-based key of the animation to add.
|
|
* @param {boolean} [loop=false] - Should the animation be looped when played?
|
|
* @param {integer} [delay=0] - A delay, in ms, before which this animation will start when played.
|
|
*
|
|
* @return {spine.TrackEntry} A track entry to allow further customization of animation playback.
|
|
*/
|
|
addAnimation: function (trackIndex, animationName, loop, delay)
|
|
{
|
|
if (loop === undefined) { loop = false; }
|
|
if (delay === undefined) { delay = 0; }
|
|
|
|
return this.state.addAnimation(trackIndex, animationName, loop, delay);
|
|
},
|
|
|
|
/**
|
|
* Sets an empty animation for a track, discarding any queued animations, and sets the track
|
|
* entry's mixDuration. An empty animation has no timelines and serves as a placeholder for mixing in or out.
|
|
*
|
|
* Mixing out is done by setting an empty animation with a mix duration using either setEmptyAnimation,
|
|
* setEmptyAnimations, or addEmptyAnimation. Mixing to an empty animation causes the previous animation to be
|
|
* applied less and less over the mix duration. Properties keyed in the previous animation transition to
|
|
* the value from lower tracks or to the setup pose value if no lower tracks key the property.
|
|
* A mix duration of 0 still mixes out over one frame.
|
|
*
|
|
* Mixing in is done by first setting an empty animation, then adding an animation using addAnimation
|
|
* and on the returned track entry, set the mixDuration. Mixing from an empty animation causes the new
|
|
* animation to be applied more and more over the mix duration. Properties keyed in the new animation
|
|
* transition from the value from lower tracks or from the setup pose value if no lower tracks key the
|
|
* property to the value keyed in the new animation.
|
|
*
|
|
* @method SpineGameObject#setEmptyAnimation
|
|
* @since 3.19.0
|
|
*
|
|
* @param {integer} trackIndex - The track index to add the animation to.
|
|
* @param {integer} [mixDuration] - Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData getMix based on the animation before this animation (if any).
|
|
*
|
|
* @return {spine.TrackEntry} The returned Track Entry.
|
|
*/
|
|
setEmptyAnimation: function (trackIndex, mixDuration)
|
|
{
|
|
return this.state.setEmptyAnimation(trackIndex, mixDuration);
|
|
},
|
|
|
|
/**
|
|
* Removes all animations from the track, leaving skeletons in their current pose.
|
|
*
|
|
* It may be desired to use setEmptyAnimation to mix the skeletons back to the setup pose,
|
|
* rather than leaving them in their current pose.
|
|
*
|
|
* @method SpineGameObject#clearTrack
|
|
* @since 3.19.0
|
|
*
|
|
* @param {integer} trackIndex - The track index to add the animation to.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
clearTrack: function (trackIndex)
|
|
{
|
|
this.state.clearTrack(trackIndex);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes all animations from all tracks, leaving skeletons in their current pose.
|
|
*
|
|
* It may be desired to use setEmptyAnimation to mix the skeletons back to the setup pose,
|
|
* rather than leaving them in their current pose.
|
|
*
|
|
* @method SpineGameObject#clearTracks
|
|
* @since 3.19.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
clearTracks: function ()
|
|
{
|
|
this.state.clearTracks();
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the skin used to look up attachments before looking in the defaultSkin.
|
|
*
|
|
* Attachments from the new skin are attached if the corresponding attachment from the
|
|
* old skin was attached. If there was no old skin, each slot's setup mode attachment is
|
|
* attached from the new skin.
|
|
*
|
|
* After changing the skin, the visible attachments can be reset to those attached in the
|
|
* setup pose by calling setSlotsToSetupPose. Also, often apply is called before the next time
|
|
* the skeleton is rendered to allow any attachment keys in the current animation(s) to hide
|
|
* or show attachments from the new skin.
|
|
*
|
|
* @method SpineGameObject#setSkinByName
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} skinName - The name of the skin to set.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setSkinByName: function (skinName)
|
|
{
|
|
var skeleton = this.skeleton;
|
|
|
|
skeleton.setSkinByName(skinName);
|
|
|
|
skeleton.setSlotsToSetupPose();
|
|
|
|
this.state.apply(skeleton);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the skin used to look up attachments before looking in the defaultSkin.
|
|
*
|
|
* Attachments from the new skin are attached if the corresponding attachment from the
|
|
* old skin was attached. If there was no old skin, each slot's setup mode attachment is
|
|
* attached from the new skin.
|
|
*
|
|
* After changing the skin, the visible attachments can be reset to those attached in the
|
|
* setup pose by calling setSlotsToSetupPose. Also, often apply is called before the next time
|
|
* the skeleton is rendered to allow any attachment keys in the current animation(s) to hide
|
|
* or show attachments from the new skin.
|
|
*
|
|
* @method SpineGameObject#setSkin
|
|
* @since 3.19.0
|
|
*
|
|
* @param {?spine.Skin} newSkin - The Skin to set. May be `null`.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setSkin: function (newSkin)
|
|
{
|
|
var skeleton = this.skeleton;
|
|
|
|
skeleton.setSkin(newSkin);
|
|
|
|
skeleton.setSlotsToSetupPose();
|
|
|
|
this.state.apply(skeleton);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the mix duration when changing from the specified animation to the other.
|
|
*
|
|
* @method SpineGameObject#setMix
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} fromName - The animation to mix from.
|
|
* @param {string} toName - The animation to mix to.
|
|
* @param {number} [duration] - Seconds for mixing from the previous animation to this animation. Defaults to the value provided by AnimationStateData getMix based on the animation before this animation (if any).
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setMix: function (fromName, toName, duration)
|
|
{
|
|
this.stateData.setMix(fromName, toName, duration);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Finds an attachment by looking in the skin and defaultSkin using the slot
|
|
* index and attachment name. First the skin is checked and if the attachment was not found,
|
|
* the default skin is checked.
|
|
*
|
|
* @method SpineGameObject#getAttachment
|
|
* @since 3.19.0
|
|
*
|
|
* @param {integer} slotIndex - The slot index to search.
|
|
* @param {string} attachmentName - The attachment name to look for.
|
|
*
|
|
* @return {?spine.Attachment} The Attachment, if found. May be null.
|
|
*/
|
|
getAttachment: function (slotIndex, attachmentName)
|
|
{
|
|
return this.skeleton.getAttachment(slotIndex, attachmentName);
|
|
},
|
|
|
|
/**
|
|
* Finds an attachment by looking in the skin and defaultSkin using the slot name and attachment name.
|
|
*
|
|
* @method SpineGameObject#getAttachmentByName
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} slotName - The slot name to search.
|
|
* @param {string} attachmentName - The attachment name to look for.
|
|
*
|
|
* @return {?spine.Attachment} The Attachment, if found. May be null.
|
|
*/
|
|
getAttachmentByName: function (slotName, attachmentName)
|
|
{
|
|
return this.skeleton.getAttachmentByName(slotName, attachmentName);
|
|
},
|
|
|
|
/**
|
|
* A convenience method to set an attachment by finding the slot with findSlot,
|
|
* finding the attachment with getAttachment, then setting the slot's attachment.
|
|
*
|
|
* @method SpineGameObject#setAttachment
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} slotName - The slot name to add the attachment to.
|
|
* @param {string} attachmentName - The attachment name to add.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setAttachment: function (slotName, attachmentName)
|
|
{
|
|
if (Array.isArray(slotName) && Array.isArray(attachmentName) && slotName.length === attachmentName.length)
|
|
{
|
|
for (var i = 0; i < slotName.length; i++)
|
|
{
|
|
this.skeleton.setAttachment(slotName[i], attachmentName[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.skeleton.setAttachment(slotName, attachmentName);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the bones, constraints, slots, and draw order to their setup pose values.
|
|
*
|
|
* @method SpineGameObject#setToSetupPose
|
|
* @since 3.19.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setToSetupPose: function ()
|
|
{
|
|
this.skeleton.setToSetupPose();
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the slots and draw order to their setup pose values.
|
|
*
|
|
* @method SpineGameObject#setSlotsToSetupPose
|
|
* @since 3.19.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setSlotsToSetupPose: function ()
|
|
{
|
|
this.skeleton.setSlotsToSetupPose();
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the bones and constraints to their setup pose values.
|
|
*
|
|
* @method SpineGameObject#setBonesToSetupPose
|
|
* @since 3.19.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setBonesToSetupPose: function ()
|
|
{
|
|
this.skeleton.setBonesToSetupPose();
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Gets the root bone, or null.
|
|
*
|
|
* @method SpineGameObject#getRootBone
|
|
* @since 3.19.0
|
|
*
|
|
* @return {spine.Bone} The root bone, or null.
|
|
*/
|
|
getRootBone: function ()
|
|
{
|
|
return this.skeleton.getRootBone();
|
|
},
|
|
|
|
/**
|
|
* Takes a Bone object and a position in world space and rotates the Bone so it is angled
|
|
* towards the given position. You can set an optional angle offset, should the bone be
|
|
* designed at a specific angle already. You can also set a minimum and maximum range for the angle.
|
|
*
|
|
* @method SpineGameObject#angleBoneToXY
|
|
* @since 3.19.0
|
|
*
|
|
* @param {spine.Bone} bone - The bone to rotate towards the world position.
|
|
* @param {number} worldX - The world x coordinate to rotate the bone towards.
|
|
* @param {number} worldY - The world y coordinate to rotate the bone towards.
|
|
* @param {number} [offset=0] - An offset to add to the rotation angle.
|
|
* @param {number} [minAngle=0] - The minimum range of the rotation angle.
|
|
* @param {number} [maxAngle=360] - The maximum range of the rotation angle.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
angleBoneToXY: function (bone, worldX, worldY, offset, minAngle, maxAngle)
|
|
{
|
|
if (offset === undefined) { offset = 0; }
|
|
if (minAngle === undefined) { minAngle = 0; }
|
|
if (maxAngle === undefined) { maxAngle = 360; }
|
|
|
|
var renderer = this.plugin.renderer;
|
|
var height = renderer.height;
|
|
|
|
var angle = CounterClockwise(AngleBetween(bone.worldX, height - bone.worldY, worldX, worldY) + DegToRad(offset));
|
|
|
|
bone.rotation = Clamp(RadToDeg(angle), minAngle, maxAngle);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Finds a bone by comparing each bone's name. It is more efficient to cache the results
|
|
* of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findBone
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} boneName - The name of the bone to find.
|
|
*
|
|
* @return {spine.Bone} The bone, or null.
|
|
*/
|
|
findBone: function (boneName)
|
|
{
|
|
return this.skeleton.findBone(boneName);
|
|
},
|
|
|
|
/**
|
|
* Finds the index of a bone by comparing each bone's name. It is more efficient to cache the results
|
|
* of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findBoneIndex
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} boneName - The name of the bone to find.
|
|
*
|
|
* @return {integer} The bone index. Or -1 if the bone was not found.
|
|
*/
|
|
findBoneIndex: function (boneName)
|
|
{
|
|
return this.skeleton.findBoneIndex(boneName);
|
|
},
|
|
|
|
/**
|
|
* Finds a slot by comparing each slot's name. It is more efficient to cache the results
|
|
* of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findSlot
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} slotName - The name of the slot to find.
|
|
*
|
|
* @return {spine.Slot} The Slot. May be null.
|
|
*/
|
|
findSlot: function (slotName)
|
|
{
|
|
return this.skeleton.findSlot(slotName);
|
|
},
|
|
|
|
/**
|
|
* Finds the index of a slot by comparing each slot's name. It is more efficient to cache the results
|
|
* of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findSlotIndex
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} slotName - The name of the slot to find.
|
|
*
|
|
* @return {integer} The slot index. Or -1 if the Slot was not found.
|
|
*/
|
|
findSlotIndex: function (slotName)
|
|
{
|
|
return this.skeleton.findSlotIndex(slotName);
|
|
},
|
|
|
|
/**
|
|
* Finds a skin by comparing each skin's name. It is more efficient to cache the results of
|
|
* this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findSkin
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} skinName - The name of the skin to find.
|
|
*
|
|
* @return {spine.Skin} The Skin. May be null.
|
|
*/
|
|
findSkin: function (skinName)
|
|
{
|
|
return this.skeletonData.findSkin(skinName);
|
|
},
|
|
|
|
/**
|
|
* Finds an event by comparing each events's name. It is more efficient to cache the results
|
|
* of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findEvent
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} eventDataName - The name of the event to find.
|
|
*
|
|
* @return {spine.EventData} The Event Data. May be null.
|
|
*/
|
|
findEvent: function (eventDataName)
|
|
{
|
|
return this.skeletonData.findEvent(eventDataName);
|
|
},
|
|
|
|
/**
|
|
* Finds an animation by comparing each animation's name. It is more efficient to cache the results
|
|
* of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findAnimation
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} animationName - The name of the animation to find.
|
|
*
|
|
* @return {spine.Animation} The Animation. May be null.
|
|
*/
|
|
findAnimation: function (animationName)
|
|
{
|
|
return this.skeletonData.findAnimation(animationName);
|
|
},
|
|
|
|
/**
|
|
* Finds an IK constraint by comparing each IK constraint's name. It is more efficient to cache the results
|
|
* of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findIkConstraint
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} constraintName - The name of the constraint to find.
|
|
*
|
|
* @return {spine.IkConstraintData} The IK constraint. May be null.
|
|
*/
|
|
findIkConstraint: function (constraintName)
|
|
{
|
|
return this.skeletonData.findIkConstraint(constraintName);
|
|
},
|
|
|
|
/**
|
|
* Finds an transform constraint by comparing each transform constraint's name.
|
|
* It is more efficient to cache the results of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findTransformConstraint
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} constraintName - The name of the constraint to find.
|
|
*
|
|
* @return {spine.TransformConstraintData} The transform constraint. May be null.
|
|
*/
|
|
findTransformConstraint: function (constraintName)
|
|
{
|
|
return this.skeletonData.findTransformConstraint(constraintName);
|
|
},
|
|
|
|
/**
|
|
* Finds a path constraint by comparing each path constraint's name.
|
|
* It is more efficient to cache the results of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findPathConstraint
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} constraintName - The name of the constraint to find.
|
|
*
|
|
* @return {spine.PathConstraintData} The path constraint. May be null.
|
|
*/
|
|
findPathConstraint: function (constraintName)
|
|
{
|
|
return this.skeletonData.findPathConstraint(constraintName);
|
|
},
|
|
|
|
/**
|
|
* Finds the index of a path constraint by comparing each path constraint's name.
|
|
* It is more efficient to cache the results of this method than to call it multiple times.
|
|
*
|
|
* @method SpineGameObject#findPathConstraintIndex
|
|
* @since 3.19.0
|
|
*
|
|
* @param {string} constraintName - The name of the constraint to find.
|
|
*
|
|
* @return {integer} The constraint index. Or -1 if the constraint was not found.
|
|
*/
|
|
findPathConstraintIndex: function (constraintName)
|
|
{
|
|
return this.skeletonData.findPathConstraintIndex(constraintName);
|
|
},
|
|
|
|
/**
|
|
* Returns the axis aligned bounding box (AABB) of the region and mesh attachments for the current pose.
|
|
*
|
|
* The returned object contains two properties: `offset` and `size`:
|
|
*
|
|
* `offset` - The distance from the skeleton origin to the bottom left corner of the AABB.
|
|
* `size` - The width and height of the AABB.
|
|
*
|
|
* @method SpineGameObject#getBounds
|
|
* @since 3.19.0
|
|
*
|
|
* @return {any} The bounds object.
|
|
*/
|
|
getBounds: function ()
|
|
{
|
|
return this.plugin.getBounds(this.skeleton);
|
|
},
|
|
|
|
/**
|
|
* Internal update handler.
|
|
*
|
|
* @method SpineGameObject#preUpdate
|
|
* @protected
|
|
* @since 3.19.0
|
|
*
|
|
* @param {number} time - The current timestamp.
|
|
* @param {number} delta - The delta time, in ms, elapsed since the last frame.
|
|
*/
|
|
preUpdate: function (time, delta)
|
|
{
|
|
var skeleton = this.skeleton;
|
|
|
|
this.state.update((delta / 1000) * this.timeScale);
|
|
|
|
this.state.apply(skeleton);
|
|
},
|
|
|
|
/**
|
|
* Internal destroy handler, called as part of the destroy process.
|
|
*
|
|
* @method SpineGameObject#preDestroy
|
|
* @protected
|
|
* @since 3.19.0
|
|
*/
|
|
preDestroy: function ()
|
|
{
|
|
if (this.state)
|
|
{
|
|
this.state.clearListeners();
|
|
this.state.clearListenerNotifications();
|
|
}
|
|
|
|
this.plugin = null;
|
|
|
|
this.skeleton = null;
|
|
this.skeletonData = null;
|
|
|
|
this.state = null;
|
|
this.stateData = null;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = SpineGameObject;
|
|
|
|
|
|
/***/ }),
|
|
/* 228 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var Events = __webpack_require__(229);
|
|
|
|
/**
|
|
* @callback DataEachCallback
|
|
*
|
|
* @param {*} parent - The parent object of the DataManager.
|
|
* @param {string} key - The key of the value.
|
|
* @param {*} value - The value.
|
|
* @param {...*} [args] - Additional arguments that will be passed to the callback, after the game object, key, and data.
|
|
*/
|
|
|
|
/**
|
|
* @classdesc
|
|
* The Data Manager Component features a means to store pieces of data specific to a Game Object, System or Plugin.
|
|
* You can then search, query it, and retrieve the data. The parent must either extend EventEmitter,
|
|
* or have a property called `events` that is an instance of it.
|
|
*
|
|
* @class DataManager
|
|
* @memberof Phaser.Data
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {object} parent - The object that this DataManager belongs to.
|
|
* @param {Phaser.Events.EventEmitter} [eventEmitter] - The DataManager's event emitter.
|
|
*/
|
|
var DataManager = new Class({
|
|
|
|
initialize:
|
|
|
|
function DataManager (parent, eventEmitter)
|
|
{
|
|
/**
|
|
* The object that this DataManager belongs to.
|
|
*
|
|
* @name Phaser.Data.DataManager#parent
|
|
* @type {*}
|
|
* @since 3.0.0
|
|
*/
|
|
this.parent = parent;
|
|
|
|
/**
|
|
* The DataManager's event emitter.
|
|
*
|
|
* @name Phaser.Data.DataManager#events
|
|
* @type {Phaser.Events.EventEmitter}
|
|
* @since 3.0.0
|
|
*/
|
|
this.events = eventEmitter;
|
|
|
|
if (!eventEmitter)
|
|
{
|
|
this.events = (parent.events) ? parent.events : parent;
|
|
}
|
|
|
|
/**
|
|
* The data list.
|
|
*
|
|
* @name Phaser.Data.DataManager#list
|
|
* @type {Object.<string, *>}
|
|
* @default {}
|
|
* @since 3.0.0
|
|
*/
|
|
this.list = {};
|
|
|
|
/**
|
|
* The public values list. You can use this to access anything you have stored
|
|
* in this Data Manager. For example, if you set a value called `gold` you can
|
|
* access it via:
|
|
*
|
|
* ```javascript
|
|
* this.data.values.gold;
|
|
* ```
|
|
*
|
|
* You can also modify it directly:
|
|
*
|
|
* ```javascript
|
|
* this.data.values.gold += 1000;
|
|
* ```
|
|
*
|
|
* Doing so will emit a `setdata` event from the parent of this Data Manager.
|
|
*
|
|
* Do not modify this object directly. Adding properties directly to this object will not
|
|
* emit any events. Always use `DataManager.set` to create new items the first time around.
|
|
*
|
|
* @name Phaser.Data.DataManager#values
|
|
* @type {Object.<string, *>}
|
|
* @default {}
|
|
* @since 3.10.0
|
|
*/
|
|
this.values = {};
|
|
|
|
/**
|
|
* Whether setting data is frozen for this DataManager.
|
|
*
|
|
* @name Phaser.Data.DataManager#_frozen
|
|
* @type {boolean}
|
|
* @private
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
this._frozen = false;
|
|
|
|
if (!parent.hasOwnProperty('sys') && this.events)
|
|
{
|
|
this.events.once(Events.DESTROY, this.destroy, this);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Retrieves the value for the given key, or undefined if it doesn't exist.
|
|
*
|
|
* You can also access values via the `values` object. For example, if you had a key called `gold` you can do either:
|
|
*
|
|
* ```javascript
|
|
* this.data.get('gold');
|
|
* ```
|
|
*
|
|
* Or access the value directly:
|
|
*
|
|
* ```javascript
|
|
* this.data.values.gold;
|
|
* ```
|
|
*
|
|
* You can also pass in an array of keys, in which case an array of values will be returned:
|
|
*
|
|
* ```javascript
|
|
* this.data.get([ 'gold', 'armor', 'health' ]);
|
|
* ```
|
|
*
|
|
* This approach is useful for destructuring arrays in ES6.
|
|
*
|
|
* @method Phaser.Data.DataManager#get
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|string[])} key - The key of the value to retrieve, or an array of keys.
|
|
*
|
|
* @return {*} The value belonging to the given key, or an array of values, the order of which will match the input array.
|
|
*/
|
|
get: function (key)
|
|
{
|
|
var list = this.list;
|
|
|
|
if (Array.isArray(key))
|
|
{
|
|
var output = [];
|
|
|
|
for (var i = 0; i < key.length; i++)
|
|
{
|
|
output.push(list[key[i]]);
|
|
}
|
|
|
|
return output;
|
|
}
|
|
else
|
|
{
|
|
return list[key];
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Retrieves all data values in a new object.
|
|
*
|
|
* @method Phaser.Data.DataManager#getAll
|
|
* @since 3.0.0
|
|
*
|
|
* @return {Object.<string, *>} All data values.
|
|
*/
|
|
getAll: function ()
|
|
{
|
|
var results = {};
|
|
|
|
for (var key in this.list)
|
|
{
|
|
if (this.list.hasOwnProperty(key))
|
|
{
|
|
results[key] = this.list[key];
|
|
}
|
|
}
|
|
|
|
return results;
|
|
},
|
|
|
|
/**
|
|
* Queries the DataManager for the values of keys matching the given regular expression.
|
|
*
|
|
* @method Phaser.Data.DataManager#query
|
|
* @since 3.0.0
|
|
*
|
|
* @param {RegExp} search - A regular expression object. If a non-RegExp object obj is passed, it is implicitly converted to a RegExp by using new RegExp(obj).
|
|
*
|
|
* @return {Object.<string, *>} The values of the keys matching the search string.
|
|
*/
|
|
query: function (search)
|
|
{
|
|
var results = {};
|
|
|
|
for (var key in this.list)
|
|
{
|
|
if (this.list.hasOwnProperty(key) && key.match(search))
|
|
{
|
|
results[key] = this.list[key];
|
|
}
|
|
}
|
|
|
|
return results;
|
|
},
|
|
|
|
/**
|
|
* Sets a value for the given key. If the key doesn't already exist in the Data Manager then it is created.
|
|
*
|
|
* ```javascript
|
|
* data.set('name', 'Red Gem Stone');
|
|
* ```
|
|
*
|
|
* You can also pass in an object of key value pairs as the first argument:
|
|
*
|
|
* ```javascript
|
|
* data.set({ name: 'Red Gem Stone', level: 2, owner: 'Link', gold: 50 });
|
|
* ```
|
|
*
|
|
* To get a value back again you can call `get`:
|
|
*
|
|
* ```javascript
|
|
* data.get('gold');
|
|
* ```
|
|
*
|
|
* Or you can access the value directly via the `values` property, where it works like any other variable:
|
|
*
|
|
* ```javascript
|
|
* data.values.gold += 50;
|
|
* ```
|
|
*
|
|
* When the value is first set, a `setdata` event is emitted.
|
|
*
|
|
* If the key already exists, a `changedata` event is emitted instead, along an event named after the key.
|
|
* For example, if you updated an existing key called `PlayerLives` then it would emit the event `changedata-PlayerLives`.
|
|
* These events will be emitted regardless if you use this method to set the value, or the direct `values` setter.
|
|
*
|
|
* Please note that the data keys are case-sensitive and must be valid JavaScript Object property strings.
|
|
* This means the keys `gold` and `Gold` are treated as two unique values within the Data Manager.
|
|
*
|
|
* @method Phaser.Data.DataManager#set
|
|
* @fires Phaser.Data.Events#SET_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA_KEY
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {any} T
|
|
* @genericUse {(string|T)} - [key]
|
|
*
|
|
* @param {(string|object)} key - The key to set the value for. Or an object or key value pairs. If an object the `data` argument is ignored.
|
|
* @param {*} data - The value to set for the given key. If an object is provided as the key this argument is ignored.
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
set: function (key, data)
|
|
{
|
|
if (this._frozen)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
if (typeof key === 'string')
|
|
{
|
|
return this.setValue(key, data);
|
|
}
|
|
else
|
|
{
|
|
for (var entry in key)
|
|
{
|
|
this.setValue(entry, key[entry]);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Increase a value for the given key. If the key doesn't already exist in the Data Manager then it is increased from 0.
|
|
*
|
|
* When the value is first set, a `setdata` event is emitted.
|
|
*
|
|
* @method Phaser.Data.DataManager#inc
|
|
* @fires Phaser.Data.Events#SET_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA_KEY
|
|
* @since 3.23.0
|
|
*
|
|
* @generic {any} T
|
|
* @genericUse {(string|T)} - [key]
|
|
*
|
|
* @param {(string|object)} key - The key to increase the value for.
|
|
* @param {*} [data] - The value to increase for the given key.
|
|
*
|
|
* @return {Phaser.Data.DataManager} This DataManager object.
|
|
*/
|
|
inc: function (key, data)
|
|
{
|
|
if (this._frozen)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
if (data === undefined)
|
|
{
|
|
data = 1;
|
|
}
|
|
|
|
var value = this.get(key);
|
|
if (value === undefined)
|
|
{
|
|
value = 0;
|
|
}
|
|
|
|
this.set(key, (value + data));
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Toggle a boolean value for the given key. If the key doesn't already exist in the Data Manager then it is toggled from false.
|
|
*
|
|
* When the value is first set, a `setdata` event is emitted.
|
|
*
|
|
* @method Phaser.Data.DataManager#toggle
|
|
* @fires Phaser.Data.Events#SET_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA_KEY
|
|
* @since 3.23.0
|
|
*
|
|
* @generic {any} T
|
|
* @genericUse {(string|T)} - [key]
|
|
*
|
|
* @param {(string|object)} key - The key to toggle the value for.
|
|
*
|
|
* @return {Phaser.Data.DataManager} This DataManager object.
|
|
*/
|
|
toggle: function (key)
|
|
{
|
|
if (this._frozen)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
this.set(key, !this.get(key));
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Internal value setter, called automatically by the `set` method.
|
|
*
|
|
* @method Phaser.Data.DataManager#setValue
|
|
* @fires Phaser.Data.Events#SET_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA_KEY
|
|
* @private
|
|
* @since 3.10.0
|
|
*
|
|
* @param {string} key - The key to set the value for.
|
|
* @param {*} data - The value to set.
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
setValue: function (key, data)
|
|
{
|
|
if (this._frozen)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
if (this.has(key))
|
|
{
|
|
// Hit the key getter, which will in turn emit the events.
|
|
this.values[key] = data;
|
|
}
|
|
else
|
|
{
|
|
var _this = this;
|
|
var list = this.list;
|
|
var events = this.events;
|
|
var parent = this.parent;
|
|
|
|
Object.defineProperty(this.values, key, {
|
|
|
|
enumerable: true,
|
|
|
|
configurable: true,
|
|
|
|
get: function ()
|
|
{
|
|
return list[key];
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (!_this._frozen)
|
|
{
|
|
var previousValue = list[key];
|
|
list[key] = value;
|
|
|
|
events.emit(Events.CHANGE_DATA, parent, key, value, previousValue);
|
|
events.emit(Events.CHANGE_DATA_KEY + key, parent, value, previousValue);
|
|
}
|
|
}
|
|
|
|
});
|
|
|
|
list[key] = data;
|
|
|
|
events.emit(Events.SET_DATA, parent, key, data);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Passes all data entries to the given callback.
|
|
*
|
|
* @method Phaser.Data.DataManager#each
|
|
* @since 3.0.0
|
|
*
|
|
* @param {DataEachCallback} callback - The function to call.
|
|
* @param {*} [context] - Value to use as `this` when executing callback.
|
|
* @param {...*} [args] - Additional arguments that will be passed to the callback, after the game object, key, and data.
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
each: function (callback, context)
|
|
{
|
|
var args = [ this.parent, null, undefined ];
|
|
|
|
for (var i = 1; i < arguments.length; i++)
|
|
{
|
|
args.push(arguments[i]);
|
|
}
|
|
|
|
for (var key in this.list)
|
|
{
|
|
args[1] = key;
|
|
args[2] = this.list[key];
|
|
|
|
callback.apply(context, args);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Merge the given object of key value pairs into this DataManager.
|
|
*
|
|
* Any newly created values will emit a `setdata` event. Any updated values (see the `overwrite` argument)
|
|
* will emit a `changedata` event.
|
|
*
|
|
* @method Phaser.Data.DataManager#merge
|
|
* @fires Phaser.Data.Events#SET_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA
|
|
* @fires Phaser.Data.Events#CHANGE_DATA_KEY
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Object.<string, *>} data - The data to merge.
|
|
* @param {boolean} [overwrite=true] - Whether to overwrite existing data. Defaults to true.
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
merge: function (data, overwrite)
|
|
{
|
|
if (overwrite === undefined) { overwrite = true; }
|
|
|
|
// Merge data from another component into this one
|
|
for (var key in data)
|
|
{
|
|
if (data.hasOwnProperty(key) && (overwrite || (!overwrite && !this.has(key))))
|
|
{
|
|
this.setValue(key, data[key]);
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Remove the value for the given key.
|
|
*
|
|
* If the key is found in this Data Manager it is removed from the internal lists and a
|
|
* `removedata` event is emitted.
|
|
*
|
|
* You can also pass in an array of keys, in which case all keys in the array will be removed:
|
|
*
|
|
* ```javascript
|
|
* this.data.remove([ 'gold', 'armor', 'health' ]);
|
|
* ```
|
|
*
|
|
* @method Phaser.Data.DataManager#remove
|
|
* @fires Phaser.Data.Events#REMOVE_DATA
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|string[])} key - The key to remove, or an array of keys to remove.
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
remove: function (key)
|
|
{
|
|
if (this._frozen)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
if (Array.isArray(key))
|
|
{
|
|
for (var i = 0; i < key.length; i++)
|
|
{
|
|
this.removeValue(key[i]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return this.removeValue(key);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Internal value remover, called automatically by the `remove` method.
|
|
*
|
|
* @method Phaser.Data.DataManager#removeValue
|
|
* @private
|
|
* @fires Phaser.Data.Events#REMOVE_DATA
|
|
* @since 3.10.0
|
|
*
|
|
* @param {string} key - The key to set the value for.
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
removeValue: function (key)
|
|
{
|
|
if (this.has(key))
|
|
{
|
|
var data = this.list[key];
|
|
|
|
delete this.list[key];
|
|
delete this.values[key];
|
|
|
|
this.events.emit(Events.REMOVE_DATA, this.parent, key, data);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Retrieves the data associated with the given 'key', deletes it from this Data Manager, then returns it.
|
|
*
|
|
* @method Phaser.Data.DataManager#pop
|
|
* @fires Phaser.Data.Events#REMOVE_DATA
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} key - The key of the value to retrieve and delete.
|
|
*
|
|
* @return {*} The value of the given key.
|
|
*/
|
|
pop: function (key)
|
|
{
|
|
var data = undefined;
|
|
|
|
if (!this._frozen && this.has(key))
|
|
{
|
|
data = this.list[key];
|
|
|
|
delete this.list[key];
|
|
delete this.values[key];
|
|
|
|
this.events.emit(Events.REMOVE_DATA, this.parent, key, data);
|
|
}
|
|
|
|
return data;
|
|
},
|
|
|
|
/**
|
|
* Determines whether the given key is set in this Data Manager.
|
|
*
|
|
* Please note that the keys are case-sensitive and must be valid JavaScript Object property strings.
|
|
* This means the keys `gold` and `Gold` are treated as two unique values within the Data Manager.
|
|
*
|
|
* @method Phaser.Data.DataManager#has
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} key - The key to check.
|
|
*
|
|
* @return {boolean} Returns `true` if the key exists, otherwise `false`.
|
|
*/
|
|
has: function (key)
|
|
{
|
|
return this.list.hasOwnProperty(key);
|
|
},
|
|
|
|
/**
|
|
* Freeze or unfreeze this Data Manager. A frozen Data Manager will block all attempts
|
|
* to create new values or update existing ones.
|
|
*
|
|
* @method Phaser.Data.DataManager#setFreeze
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} value - Whether to freeze or unfreeze the Data Manager.
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
setFreeze: function (value)
|
|
{
|
|
this._frozen = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Delete all data in this Data Manager and unfreeze it.
|
|
*
|
|
* @method Phaser.Data.DataManager#reset
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This DataManager object.
|
|
*/
|
|
reset: function ()
|
|
{
|
|
for (var key in this.list)
|
|
{
|
|
delete this.list[key];
|
|
delete this.values[key];
|
|
}
|
|
|
|
this._frozen = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Destroy this data manager.
|
|
*
|
|
* @method Phaser.Data.DataManager#destroy
|
|
* @since 3.0.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.reset();
|
|
|
|
this.events.off(Events.CHANGE_DATA);
|
|
this.events.off(Events.SET_DATA);
|
|
this.events.off(Events.REMOVE_DATA);
|
|
|
|
this.parent = null;
|
|
},
|
|
|
|
/**
|
|
* Gets or sets the frozen state of this Data Manager.
|
|
* A frozen Data Manager will block all attempts to create new values or update existing ones.
|
|
*
|
|
* @name Phaser.Data.DataManager#freeze
|
|
* @type {boolean}
|
|
* @since 3.0.0
|
|
*/
|
|
freeze: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._frozen;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._frozen = (value) ? true : false;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Return the total number of entries in this Data Manager.
|
|
*
|
|
* @name Phaser.Data.DataManager#count
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
count: {
|
|
|
|
get: function ()
|
|
{
|
|
var i = 0;
|
|
|
|
for (var key in this.list)
|
|
{
|
|
if (this.list[key] !== undefined)
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = DataManager;
|
|
|
|
|
|
/***/ }),
|
|
/* 229 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Data.Events
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
CHANGE_DATA: __webpack_require__(230),
|
|
CHANGE_DATA_KEY: __webpack_require__(231),
|
|
DESTROY: __webpack_require__(232),
|
|
REMOVE_DATA: __webpack_require__(233),
|
|
SET_DATA: __webpack_require__(234)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 230 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Change Data Event.
|
|
*
|
|
* This event is dispatched by a Data Manager when an item in the data store is changed.
|
|
*
|
|
* Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for
|
|
* a change data event from a Game Object you would use: `sprite.on('changedata', listener)`.
|
|
*
|
|
* This event is dispatched for all items that change in the Data Manager.
|
|
* To listen for the change of a specific item, use the `CHANGE_DATA_KEY_EVENT` event.
|
|
*
|
|
* @event Phaser.Data.Events#CHANGE_DATA
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {any} parent - A reference to the object that the Data Manager responsible for this event belongs to.
|
|
* @param {string} key - The unique key of the data item within the Data Manager.
|
|
* @param {any} value - The new value of the item in the Data Manager.
|
|
* @param {any} previousValue - The previous value of the item in the Data Manager.
|
|
*/
|
|
module.exports = 'changedata';
|
|
|
|
|
|
/***/ }),
|
|
/* 231 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Change Data Key Event.
|
|
*
|
|
* This event is dispatched by a Data Manager when an item in the data store is changed.
|
|
*
|
|
* Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for
|
|
* the change of a specific data item from a Game Object you would use: `sprite.on('changedata-key', listener)`,
|
|
* where `key` is the unique string key of the data item. For example, if you have a data item stored called `gold`
|
|
* then you can listen for `sprite.on('changedata-gold')`.
|
|
*
|
|
* @event Phaser.Data.Events#CHANGE_DATA_KEY
|
|
* @type {string}
|
|
* @since 3.16.1
|
|
*
|
|
* @param {any} parent - A reference to the object that owns the instance of the Data Manager responsible for this event.
|
|
* @param {any} value - The item that was updated in the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance.
|
|
* @param {any} previousValue - The previous item that was updated in the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance.
|
|
*/
|
|
module.exports = 'changedata-';
|
|
|
|
|
|
/***/ }),
|
|
/* 232 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Data Manager Destroy Event.
|
|
*
|
|
* The Data Manager will listen for the destroy event from its parent, and then close itself down.
|
|
*
|
|
* @event Phaser.Data.Events#DESTROY
|
|
* @type {string}
|
|
* @since 3.50.0
|
|
*/
|
|
module.exports = 'destroy';
|
|
|
|
|
|
/***/ }),
|
|
/* 233 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Remove Data Event.
|
|
*
|
|
* This event is dispatched by a Data Manager when an item is removed from it.
|
|
*
|
|
* Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for
|
|
* the removal of a data item on a Game Object you would use: `sprite.on('removedata', listener)`.
|
|
*
|
|
* @event Phaser.Data.Events#REMOVE_DATA
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {any} parent - A reference to the object that owns the instance of the Data Manager responsible for this event.
|
|
* @param {string} key - The unique key of the data item within the Data Manager.
|
|
* @param {any} data - The item that was removed from the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance.
|
|
*/
|
|
module.exports = 'removedata';
|
|
|
|
|
|
/***/ }),
|
|
/* 234 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Set Data Event.
|
|
*
|
|
* This event is dispatched by a Data Manager when a new item is added to the data store.
|
|
*
|
|
* Game Objects with data enabled have an instance of a Data Manager under the `data` property. So, to listen for
|
|
* the addition of a new data item on a Game Object you would use: `sprite.on('setdata', listener)`.
|
|
*
|
|
* @event Phaser.Data.Events#SET_DATA
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {any} parent - A reference to the object that owns the instance of the Data Manager responsible for this event.
|
|
* @param {string} key - The unique key of the data item within the Data Manager.
|
|
* @param {any} data - The item that was added to the Data Manager. This can be of any data type, i.e. a string, boolean, number, object or instance.
|
|
*/
|
|
module.exports = 'setdata';
|
|
|
|
|
|
/***/ }),
|
|
/* 235 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
"use strict";
|
|
|
|
|
|
var has = Object.prototype.hasOwnProperty
|
|
, prefix = '~';
|
|
|
|
/**
|
|
* Constructor to create a storage for our `EE` objects.
|
|
* An `Events` instance is a plain object whose properties are event names.
|
|
*
|
|
* @constructor
|
|
* @private
|
|
*/
|
|
function Events() {}
|
|
|
|
//
|
|
// We try to not inherit from `Object.prototype`. In some engines creating an
|
|
// instance in this way is faster than calling `Object.create(null)` directly.
|
|
// If `Object.create(null)` is not supported we prefix the event names with a
|
|
// character to make sure that the built-in object properties are not
|
|
// overridden or used as an attack vector.
|
|
//
|
|
if (Object.create) {
|
|
Events.prototype = Object.create(null);
|
|
|
|
//
|
|
// This hack is needed because the `__proto__` property is still inherited in
|
|
// some old browsers like Android 4, iPhone 5.1, Opera 11 and Safari 5.
|
|
//
|
|
if (!new Events().__proto__) prefix = false;
|
|
}
|
|
|
|
/**
|
|
* Representation of a single event listener.
|
|
*
|
|
* @param {Function} fn The listener function.
|
|
* @param {*} context The context to invoke the listener with.
|
|
* @param {Boolean} [once=false] Specify if the listener is a one-time listener.
|
|
* @constructor
|
|
* @private
|
|
*/
|
|
function EE(fn, context, once) {
|
|
this.fn = fn;
|
|
this.context = context;
|
|
this.once = once || false;
|
|
}
|
|
|
|
/**
|
|
* Add a listener for a given event.
|
|
*
|
|
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
* @param {(String|Symbol)} event The event name.
|
|
* @param {Function} fn The listener function.
|
|
* @param {*} context The context to invoke the listener with.
|
|
* @param {Boolean} once Specify if the listener is a one-time listener.
|
|
* @returns {EventEmitter}
|
|
* @private
|
|
*/
|
|
function addListener(emitter, event, fn, context, once) {
|
|
if (typeof fn !== 'function') {
|
|
throw new TypeError('The listener must be a function');
|
|
}
|
|
|
|
var listener = new EE(fn, context || emitter, once)
|
|
, evt = prefix ? prefix + event : event;
|
|
|
|
if (!emitter._events[evt]) emitter._events[evt] = listener, emitter._eventsCount++;
|
|
else if (!emitter._events[evt].fn) emitter._events[evt].push(listener);
|
|
else emitter._events[evt] = [emitter._events[evt], listener];
|
|
|
|
return emitter;
|
|
}
|
|
|
|
/**
|
|
* Clear event by name.
|
|
*
|
|
* @param {EventEmitter} emitter Reference to the `EventEmitter` instance.
|
|
* @param {(String|Symbol)} evt The Event name.
|
|
* @private
|
|
*/
|
|
function clearEvent(emitter, evt) {
|
|
if (--emitter._eventsCount === 0) emitter._events = new Events();
|
|
else delete emitter._events[evt];
|
|
}
|
|
|
|
/**
|
|
* Minimal `EventEmitter` interface that is molded against the Node.js
|
|
* `EventEmitter` interface.
|
|
*
|
|
* @constructor
|
|
* @public
|
|
*/
|
|
function EventEmitter() {
|
|
this._events = new Events();
|
|
this._eventsCount = 0;
|
|
}
|
|
|
|
/**
|
|
* Return an array listing the events for which the emitter has registered
|
|
* listeners.
|
|
*
|
|
* @returns {Array}
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.eventNames = function eventNames() {
|
|
var names = []
|
|
, events
|
|
, name;
|
|
|
|
if (this._eventsCount === 0) return names;
|
|
|
|
for (name in (events = this._events)) {
|
|
if (has.call(events, name)) names.push(prefix ? name.slice(1) : name);
|
|
}
|
|
|
|
if (Object.getOwnPropertySymbols) {
|
|
return names.concat(Object.getOwnPropertySymbols(events));
|
|
}
|
|
|
|
return names;
|
|
};
|
|
|
|
/**
|
|
* Return the listeners registered for a given event.
|
|
*
|
|
* @param {(String|Symbol)} event The event name.
|
|
* @returns {Array} The registered listeners.
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.listeners = function listeners(event) {
|
|
var evt = prefix ? prefix + event : event
|
|
, handlers = this._events[evt];
|
|
|
|
if (!handlers) return [];
|
|
if (handlers.fn) return [handlers.fn];
|
|
|
|
for (var i = 0, l = handlers.length, ee = new Array(l); i < l; i++) {
|
|
ee[i] = handlers[i].fn;
|
|
}
|
|
|
|
return ee;
|
|
};
|
|
|
|
/**
|
|
* Return the number of listeners listening to a given event.
|
|
*
|
|
* @param {(String|Symbol)} event The event name.
|
|
* @returns {Number} The number of listeners.
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.listenerCount = function listenerCount(event) {
|
|
var evt = prefix ? prefix + event : event
|
|
, listeners = this._events[evt];
|
|
|
|
if (!listeners) return 0;
|
|
if (listeners.fn) return 1;
|
|
return listeners.length;
|
|
};
|
|
|
|
/**
|
|
* Calls each of the listeners registered for a given event.
|
|
*
|
|
* @param {(String|Symbol)} event The event name.
|
|
* @returns {Boolean} `true` if the event had listeners, else `false`.
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.emit = function emit(event, a1, a2, a3, a4, a5) {
|
|
var evt = prefix ? prefix + event : event;
|
|
|
|
if (!this._events[evt]) return false;
|
|
|
|
var listeners = this._events[evt]
|
|
, len = arguments.length
|
|
, args
|
|
, i;
|
|
|
|
if (listeners.fn) {
|
|
if (listeners.once) this.removeListener(event, listeners.fn, undefined, true);
|
|
|
|
switch (len) {
|
|
case 1: return listeners.fn.call(listeners.context), true;
|
|
case 2: return listeners.fn.call(listeners.context, a1), true;
|
|
case 3: return listeners.fn.call(listeners.context, a1, a2), true;
|
|
case 4: return listeners.fn.call(listeners.context, a1, a2, a3), true;
|
|
case 5: return listeners.fn.call(listeners.context, a1, a2, a3, a4), true;
|
|
case 6: return listeners.fn.call(listeners.context, a1, a2, a3, a4, a5), true;
|
|
}
|
|
|
|
for (i = 1, args = new Array(len -1); i < len; i++) {
|
|
args[i - 1] = arguments[i];
|
|
}
|
|
|
|
listeners.fn.apply(listeners.context, args);
|
|
} else {
|
|
var length = listeners.length
|
|
, j;
|
|
|
|
for (i = 0; i < length; i++) {
|
|
if (listeners[i].once) this.removeListener(event, listeners[i].fn, undefined, true);
|
|
|
|
switch (len) {
|
|
case 1: listeners[i].fn.call(listeners[i].context); break;
|
|
case 2: listeners[i].fn.call(listeners[i].context, a1); break;
|
|
case 3: listeners[i].fn.call(listeners[i].context, a1, a2); break;
|
|
case 4: listeners[i].fn.call(listeners[i].context, a1, a2, a3); break;
|
|
default:
|
|
if (!args) for (j = 1, args = new Array(len -1); j < len; j++) {
|
|
args[j - 1] = arguments[j];
|
|
}
|
|
|
|
listeners[i].fn.apply(listeners[i].context, args);
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* Add a listener for a given event.
|
|
*
|
|
* @param {(String|Symbol)} event The event name.
|
|
* @param {Function} fn The listener function.
|
|
* @param {*} [context=this] The context to invoke the listener with.
|
|
* @returns {EventEmitter} `this`.
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.on = function on(event, fn, context) {
|
|
return addListener(this, event, fn, context, false);
|
|
};
|
|
|
|
/**
|
|
* Add a one-time listener for a given event.
|
|
*
|
|
* @param {(String|Symbol)} event The event name.
|
|
* @param {Function} fn The listener function.
|
|
* @param {*} [context=this] The context to invoke the listener with.
|
|
* @returns {EventEmitter} `this`.
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.once = function once(event, fn, context) {
|
|
return addListener(this, event, fn, context, true);
|
|
};
|
|
|
|
/**
|
|
* Remove the listeners of a given event.
|
|
*
|
|
* @param {(String|Symbol)} event The event name.
|
|
* @param {Function} fn Only remove the listeners that match this function.
|
|
* @param {*} context Only remove the listeners that have this context.
|
|
* @param {Boolean} once Only remove one-time listeners.
|
|
* @returns {EventEmitter} `this`.
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.removeListener = function removeListener(event, fn, context, once) {
|
|
var evt = prefix ? prefix + event : event;
|
|
|
|
if (!this._events[evt]) return this;
|
|
if (!fn) {
|
|
clearEvent(this, evt);
|
|
return this;
|
|
}
|
|
|
|
var listeners = this._events[evt];
|
|
|
|
if (listeners.fn) {
|
|
if (
|
|
listeners.fn === fn &&
|
|
(!once || listeners.once) &&
|
|
(!context || listeners.context === context)
|
|
) {
|
|
clearEvent(this, evt);
|
|
}
|
|
} else {
|
|
for (var i = 0, events = [], length = listeners.length; i < length; i++) {
|
|
if (
|
|
listeners[i].fn !== fn ||
|
|
(once && !listeners[i].once) ||
|
|
(context && listeners[i].context !== context)
|
|
) {
|
|
events.push(listeners[i]);
|
|
}
|
|
}
|
|
|
|
//
|
|
// Reset the array, or remove it completely if we have no more listeners.
|
|
//
|
|
if (events.length) this._events[evt] = events.length === 1 ? events[0] : events;
|
|
else clearEvent(this, evt);
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Remove all listeners, or those of the specified event.
|
|
*
|
|
* @param {(String|Symbol)} [event] The event name.
|
|
* @returns {EventEmitter} `this`.
|
|
* @public
|
|
*/
|
|
EventEmitter.prototype.removeAllListeners = function removeAllListeners(event) {
|
|
var evt;
|
|
|
|
if (event) {
|
|
evt = prefix ? prefix + event : event;
|
|
if (this._events[evt]) clearEvent(this, evt);
|
|
} else {
|
|
this._events = new Events();
|
|
this._eventsCount = 0;
|
|
}
|
|
|
|
return this;
|
|
};
|
|
|
|
//
|
|
// Alias methods names because people roll like that.
|
|
//
|
|
EventEmitter.prototype.off = EventEmitter.prototype.removeListener;
|
|
EventEmitter.prototype.addListener = EventEmitter.prototype.on;
|
|
|
|
//
|
|
// Expose the prefix.
|
|
//
|
|
EventEmitter.prefixed = prefix;
|
|
|
|
//
|
|
// Allow `EventEmitter` to be imported as module namespace.
|
|
//
|
|
EventEmitter.EventEmitter = EventEmitter;
|
|
|
|
//
|
|
// Expose the module.
|
|
//
|
|
if (true) {
|
|
module.exports = EventEmitter;
|
|
}
|
|
|
|
|
|
/***/ }),
|
|
/* 236 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Game Object Added to Scene Event.
|
|
*
|
|
* This event is dispatched when a Game Object is added to a Scene.
|
|
*
|
|
* Listen for it on a Game Object instance using `GameObject.on('addedtoscene', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#ADDED_TO_SCENE
|
|
* @type {string}
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was added to the Scene.
|
|
* @param {Phaser.Scene} scene - The Scene to which the Game Object was added.
|
|
*/
|
|
module.exports = 'addedtoscene';
|
|
|
|
|
|
/***/ }),
|
|
/* 237 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Game Object Destroy Event.
|
|
*
|
|
* This event is dispatched when a Game Object instance is being destroyed.
|
|
*
|
|
* Listen for it on a Game Object instance using `GameObject.on('destroy', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#DESTROY
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object which is being destroyed.
|
|
* @param {boolean} fromScene - `True` if this Game Object is being destroyed by the Scene, `false` if not.
|
|
*/
|
|
module.exports = 'destroy';
|
|
|
|
|
|
/***/ }),
|
|
/* 238 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Game Object Removed from Scene Event.
|
|
*
|
|
* This event is dispatched when a Game Object is removed from a Scene.
|
|
*
|
|
* Listen for it on a Game Object instance using `GameObject.on('removedfromscene', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#REMOVED_FROM_SCENE
|
|
* @type {string}
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was removed from the Scene.
|
|
* @param {Phaser.Scene} scene - The Scene from which the Game Object was removed.
|
|
*/
|
|
module.exports = 'removedfromscene';
|
|
|
|
|
|
/***/ }),
|
|
/* 239 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Complete Event.
|
|
*
|
|
* This event is dispatched when a Video finishes playback by reaching the end of its duration. It
|
|
* is also dispatched if a video marker sequence is being played and reaches the end.
|
|
*
|
|
* Note that not all videos can fire this event. Live streams, for example, have no fixed duration,
|
|
* so never technically 'complete'.
|
|
*
|
|
* If a video is stopped from playback, via the `Video.stop` method, it will emit the
|
|
* `VIDEO_STOP` event instead of this one.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('complete', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_COMPLETE
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which completed playback.
|
|
*/
|
|
module.exports = 'complete';
|
|
|
|
|
|
/***/ }),
|
|
/* 240 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Created Event.
|
|
*
|
|
* This event is dispatched when the texture for a Video has been created. This happens
|
|
* when enough of the video source has been loaded that the browser is able to render a
|
|
* frame from it.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('created', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_CREATED
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which raised the event.
|
|
* @param {number} width - The width of the video.
|
|
* @param {number} height - The height of the video.
|
|
*/
|
|
module.exports = 'created';
|
|
|
|
|
|
/***/ }),
|
|
/* 241 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Error Event.
|
|
*
|
|
* This event is dispatched when a Video tries to play a source that does not exist, or is the wrong file type.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('error', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_ERROR
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which threw the error.
|
|
* @param {Event} event - The native DOM event the browser raised during playback.
|
|
*/
|
|
module.exports = 'error';
|
|
|
|
|
|
/***/ }),
|
|
/* 242 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Loop Event.
|
|
*
|
|
* This event is dispatched when a Video that is currently playing has looped. This only
|
|
* happens if the `loop` parameter was specified, or the `setLoop` method was called,
|
|
* and if the video has a fixed duration. Video streams, for example, cannot loop, as
|
|
* they have no duration.
|
|
*
|
|
* Looping is based on the result of the Video `timeupdate` event. This event is not
|
|
* frame-accurate, due to the way browsers work, so please do not rely on this loop
|
|
* event to be time or frame precise.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('loop', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_LOOP
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which has looped.
|
|
*/
|
|
module.exports = 'loop';
|
|
|
|
|
|
/***/ }),
|
|
/* 243 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Play Event.
|
|
*
|
|
* This event is dispatched when a Video begins playback. For videos that do not require
|
|
* interaction unlocking, this is usually as soon as the `Video.play` method is called.
|
|
* However, for videos that require unlocking, it is fired once playback begins after
|
|
* they've been unlocked.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('play', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_PLAY
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which started playback.
|
|
*/
|
|
module.exports = 'play';
|
|
|
|
|
|
/***/ }),
|
|
/* 244 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Seeked Event.
|
|
*
|
|
* This event is dispatched when a Video completes seeking to a new point in its timeline.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('seeked', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_SEEKED
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which completed seeking.
|
|
*/
|
|
module.exports = 'seeked';
|
|
|
|
|
|
/***/ }),
|
|
/* 245 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Seeking Event.
|
|
*
|
|
* This event is dispatched when a Video _begins_ seeking to a new point in its timeline.
|
|
* When the seek is complete, it will dispatch the `VIDEO_SEEKED` event to conclude.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('seeking', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_SEEKING
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which started seeking.
|
|
*/
|
|
module.exports = 'seeking';
|
|
|
|
|
|
/***/ }),
|
|
/* 246 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Stopped Event.
|
|
*
|
|
* This event is dispatched when a Video is stopped from playback via a call to the `Video.stop` method,
|
|
* either directly via game code, or indirectly as the result of changing a video source or destroying it.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('stop', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_STOP
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which stopped playback.
|
|
*/
|
|
module.exports = 'stop';
|
|
|
|
|
|
/***/ }),
|
|
/* 247 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Timeout Event.
|
|
*
|
|
* This event is dispatched when a Video has exhausted its allocated time while trying to connect to a video
|
|
* source to start playback.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('timeout', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_TIMEOUT
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which timed out.
|
|
*/
|
|
module.exports = 'timeout';
|
|
|
|
|
|
/***/ }),
|
|
/* 248 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Video Game Object Unlocked Event.
|
|
*
|
|
* This event is dispatched when a Video that was prevented from playback due to the browsers
|
|
* Media Engagement Interaction policy, is unlocked by a user gesture.
|
|
*
|
|
* Listen for it from a Video Game Object instance using `Video.on('unlocked', listener)`.
|
|
*
|
|
* @event Phaser.GameObjects.Events#VIDEO_UNLOCKED
|
|
* @type {string}
|
|
* @since 3.20.0
|
|
*
|
|
* @param {Phaser.GameObjects.Video} video - The Video Game Object which raised the event.
|
|
*/
|
|
module.exports = 'unlocked';
|
|
|
|
|
|
/***/ }),
|
|
/* 249 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace SpinePluginEvents
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
COMPLETE: __webpack_require__(250),
|
|
DISPOSE: __webpack_require__(251),
|
|
END: __webpack_require__(252),
|
|
EVENT: __webpack_require__(253),
|
|
INTERRUPTED: __webpack_require__(254),
|
|
START: __webpack_require__(255)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 250 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Complete Event.
|
|
*
|
|
* @event SpinePluginEvents#COMPLETE
|
|
* @since 3.19.0
|
|
*/
|
|
module.exports = 'complete';
|
|
|
|
|
|
/***/ }),
|
|
/* 251 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Dispose Event.
|
|
*
|
|
* @event SpinePluginEvents#DISPOSE
|
|
* @since 3.19.0
|
|
*/
|
|
module.exports = 'dispose';
|
|
|
|
|
|
/***/ }),
|
|
/* 252 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The End Event.
|
|
*
|
|
* @event SpinePluginEvents#END
|
|
* @since 3.19.0
|
|
*/
|
|
module.exports = 'end';
|
|
|
|
|
|
/***/ }),
|
|
/* 253 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Custom Event Event.
|
|
*
|
|
* @event SpinePluginEvents#EVENT
|
|
* @since 3.19.0
|
|
*/
|
|
module.exports = 'event';
|
|
|
|
|
|
/***/ }),
|
|
/* 254 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Interrupted Event.
|
|
*
|
|
* @event SpinePluginEvents#INTERRUPTED
|
|
* @since 3.19.0
|
|
*/
|
|
module.exports = 'interrupted';
|
|
|
|
|
|
/***/ }),
|
|
/* 255 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* The Start Event.
|
|
*
|
|
* @event SpinePluginEvents#START
|
|
* @since 3.19.0
|
|
*/
|
|
module.exports = 'start';
|
|
|
|
|
|
/***/ }),
|
|
/* 256 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var renderWebGL = __webpack_require__(2);
|
|
var renderCanvas = __webpack_require__(2);
|
|
var renderDirect = __webpack_require__(2);
|
|
|
|
if (true)
|
|
{
|
|
renderWebGL = __webpack_require__(257);
|
|
renderDirect = __webpack_require__(258);
|
|
}
|
|
|
|
if (true)
|
|
{
|
|
renderCanvas = __webpack_require__(259);
|
|
}
|
|
|
|
module.exports = {
|
|
|
|
renderWebGL: renderWebGL,
|
|
renderCanvas: renderCanvas,
|
|
renderDirect: renderDirect
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 257 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var Clamp = __webpack_require__(1);
|
|
var CounterClockwise = __webpack_require__(8);
|
|
var GetCalcMatrix = __webpack_require__(60);
|
|
var RadToDeg = __webpack_require__(9);
|
|
var Wrap = __webpack_require__(6);
|
|
|
|
/**
|
|
* Renders this Game Object with the WebGL Renderer to the given Camera.
|
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
|
* This method should not be called directly. It is a utility function of the Render module.
|
|
*
|
|
* @method SpineGameObject#renderWebGL
|
|
* @since 3.19.0
|
|
* @private
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
|
|
* @param {SpineGameObject} src - The Game Object being rendered in this call.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
|
* @param {SpineContainer} [container] - If this Spine object is in a Spine Container, this is a reference to it.
|
|
*/
|
|
var SpineGameObjectWebGLRenderer = function (renderer, src, camera, parentMatrix, container)
|
|
{
|
|
var plugin = src.plugin;
|
|
var skeleton = src.skeleton;
|
|
var sceneRenderer = plugin.sceneRenderer;
|
|
|
|
if (renderer.newType)
|
|
{
|
|
// flush + clear previous pipeline if this is a new type
|
|
renderer.pipelines.clear();
|
|
|
|
sceneRenderer.begin();
|
|
}
|
|
|
|
var scrollFactorX = src.scrollFactorX;
|
|
var scrollFactorY = src.scrollFactorY;
|
|
var alpha = skeleton.color.a;
|
|
|
|
if (container)
|
|
{
|
|
src.scrollFactorX = container.scrollFactorX;
|
|
src.scrollFactorY = container.scrollFactorY;
|
|
|
|
skeleton.color.a = Clamp(alpha * container.alpha, 0, 1);
|
|
}
|
|
|
|
camera.addToRenderList(src);
|
|
|
|
var calcMatrix = GetCalcMatrix(src, camera, parentMatrix).calc;
|
|
|
|
var viewportHeight = renderer.height;
|
|
|
|
skeleton.x = calcMatrix.tx;
|
|
skeleton.y = viewportHeight - calcMatrix.ty;
|
|
|
|
skeleton.scaleX = calcMatrix.scaleX;
|
|
skeleton.scaleY = calcMatrix.scaleY;
|
|
|
|
if (src.scaleX < 0)
|
|
{
|
|
skeleton.scaleX *= -1;
|
|
|
|
// -180 degrees to account for the difference in Spine vs. Phaser rotation when inversely scaled
|
|
src.root.rotation = Wrap(RadToDeg(calcMatrix.rotationNormalized) - 180, 0, 360);
|
|
}
|
|
else
|
|
{
|
|
// +90 degrees to account for the difference in Spine vs. Phaser rotation
|
|
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
|
|
}
|
|
|
|
if (src.scaleY < 0)
|
|
{
|
|
skeleton.scaleY *= -1;
|
|
|
|
if (src.scaleX < 0)
|
|
{
|
|
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
|
|
}
|
|
else
|
|
{
|
|
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (renderer.currentFramebuffer !== null)
|
|
{
|
|
skeleton.y = calcMatrix.ty;
|
|
skeleton.scaleY *= -1;
|
|
}
|
|
*/
|
|
|
|
skeleton.updateWorldTransform();
|
|
|
|
// Draw the current skeleton
|
|
|
|
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
|
|
|
|
if (container)
|
|
{
|
|
src.scrollFactorX = scrollFactorX;
|
|
src.scrollFactorY = scrollFactorY;
|
|
skeleton.color.a = alpha;
|
|
}
|
|
|
|
if (plugin.drawDebug || src.drawDebug)
|
|
{
|
|
// Because if we don't, the bones render positions are completely wrong (*sigh*)
|
|
var oldX = skeleton.x;
|
|
var oldY = skeleton.y;
|
|
|
|
skeleton.x = 0;
|
|
skeleton.y = 0;
|
|
|
|
sceneRenderer.drawSkeletonDebug(skeleton, src.preMultipliedAlpha);
|
|
|
|
skeleton.x = oldX;
|
|
skeleton.y = oldY;
|
|
}
|
|
|
|
if (!renderer.nextTypeMatch)
|
|
{
|
|
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
|
|
sceneRenderer.end();
|
|
|
|
// And rebind the previous pipeline
|
|
renderer.pipelines.rebind();
|
|
}
|
|
};
|
|
|
|
module.exports = SpineGameObjectWebGLRenderer;
|
|
|
|
|
|
/***/ }),
|
|
/* 258 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var Clamp = __webpack_require__(1);
|
|
var CounterClockwise = __webpack_require__(8);
|
|
var GetCalcMatrix = __webpack_require__(60);
|
|
var RadToDeg = __webpack_require__(9);
|
|
var Wrap = __webpack_require__(6);
|
|
|
|
/**
|
|
* Directly renders this Game Object with the WebGL Renderer to the given Camera.
|
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
|
* This method should not be called directly. It is a utility function of the Render module.
|
|
*
|
|
* @method SpineGameObject#renderDirect
|
|
* @since 3.50.0
|
|
* @private
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
|
|
* @param {SpineGameObject} src - The Game Object being rendered in this call.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
|
* @param {SpineContainer} [container] - If this Spine object is in a Spine Container, this is a reference to it.
|
|
*/
|
|
var SpineGameObjectWebGLDirect = function (renderer, src, camera, parentMatrix, container)
|
|
{
|
|
var plugin = src.plugin;
|
|
var skeleton = src.skeleton;
|
|
var sceneRenderer = plugin.sceneRenderer;
|
|
|
|
// flush + clear previous pipeline if this is a new type
|
|
renderer.pipelines.clear();
|
|
|
|
sceneRenderer.begin();
|
|
|
|
var scrollFactorX = src.scrollFactorX;
|
|
var scrollFactorY = src.scrollFactorY;
|
|
var alpha = skeleton.color.a;
|
|
|
|
if (container)
|
|
{
|
|
src.scrollFactorX = container.scrollFactorX;
|
|
src.scrollFactorY = container.scrollFactorY;
|
|
|
|
skeleton.color.a = Clamp(alpha * container.alpha, 0, 1);
|
|
}
|
|
|
|
camera.addToRenderList(src);
|
|
|
|
var calcMatrix = GetCalcMatrix(src, camera, parentMatrix).calc;
|
|
|
|
var viewportHeight = renderer.height;
|
|
|
|
skeleton.x = calcMatrix.tx;
|
|
skeleton.y = viewportHeight - calcMatrix.ty;
|
|
|
|
skeleton.scaleX = calcMatrix.scaleX;
|
|
skeleton.scaleY = calcMatrix.scaleY;
|
|
|
|
if (src.scaleX < 0)
|
|
{
|
|
skeleton.scaleX *= -1;
|
|
|
|
// -180 degrees to account for the difference in Spine vs. Phaser rotation when inversely scaled
|
|
src.root.rotation = Wrap(RadToDeg(calcMatrix.rotationNormalized) - 180, 0, 360);
|
|
}
|
|
else
|
|
{
|
|
// +90 degrees to account for the difference in Spine vs. Phaser rotation
|
|
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
|
|
}
|
|
|
|
if (src.scaleY < 0)
|
|
{
|
|
skeleton.scaleY *= -1;
|
|
|
|
if (src.scaleX < 0)
|
|
{
|
|
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
|
|
}
|
|
else
|
|
{
|
|
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
|
|
}
|
|
}
|
|
|
|
/*
|
|
if (renderer.currentFramebuffer !== null)
|
|
{
|
|
skeleton.y = calcMatrix.ty;
|
|
skeleton.scaleY *= -1;
|
|
}
|
|
*/
|
|
|
|
skeleton.updateWorldTransform();
|
|
|
|
// Draw the current skeleton
|
|
|
|
sceneRenderer.drawSkeleton(skeleton, src.preMultipliedAlpha);
|
|
|
|
if (container)
|
|
{
|
|
src.scrollFactorX = scrollFactorX;
|
|
src.scrollFactorY = scrollFactorY;
|
|
skeleton.color.a = alpha;
|
|
}
|
|
|
|
if (plugin.drawDebug || src.drawDebug)
|
|
{
|
|
// Because if we don't, the bones render positions are completely wrong (*sigh*)
|
|
var oldX = skeleton.x;
|
|
var oldY = skeleton.y;
|
|
|
|
skeleton.x = 0;
|
|
skeleton.y = 0;
|
|
|
|
sceneRenderer.drawSkeletonDebug(skeleton, src.preMultipliedAlpha);
|
|
|
|
skeleton.x = oldX;
|
|
skeleton.y = oldY;
|
|
}
|
|
|
|
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
|
|
sceneRenderer.end();
|
|
|
|
// And rebind the previous pipeline
|
|
renderer.pipelines.rebind();
|
|
};
|
|
|
|
module.exports = SpineGameObjectWebGLDirect;
|
|
|
|
|
|
/***/ }),
|
|
/* 259 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var CounterClockwise = __webpack_require__(8);
|
|
var RadToDeg = __webpack_require__(9);
|
|
var Wrap = __webpack_require__(6);
|
|
|
|
/**
|
|
* Renders this Game Object with the Canvas Renderer to the given Camera.
|
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
|
* This method should not be called directly. It is a utility function of the Render module.
|
|
*
|
|
* @method SpineGameObject#renderCanvas
|
|
* @since 3.19.0
|
|
* @private
|
|
*
|
|
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
|
|
* @param {SpineGameObject} src - The Game Object being rendered in this call.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
|
*/
|
|
var SpineGameObjectCanvasRenderer = function (renderer, src, camera, parentMatrix)
|
|
{
|
|
var context = renderer.currentContext;
|
|
|
|
var plugin = src.plugin;
|
|
var skeleton = src.skeleton;
|
|
var skeletonRenderer = plugin.skeletonRenderer;
|
|
|
|
var camMatrix = renderer._tempMatrix1;
|
|
var spriteMatrix = renderer._tempMatrix2;
|
|
var calcMatrix = renderer._tempMatrix3;
|
|
|
|
camera.addToRenderList(src);
|
|
|
|
spriteMatrix.applyITRS(src.x, src.y, src.rotation, Math.abs(src.scaleX), Math.abs(src.scaleY));
|
|
|
|
camMatrix.copyFrom(camera.matrix);
|
|
|
|
if (parentMatrix)
|
|
{
|
|
// Multiply the camera by the parent matrix
|
|
camMatrix.multiplyWithOffset(parentMatrix, -camera.scrollX * src.scrollFactorX, -camera.scrollY * src.scrollFactorY);
|
|
|
|
// Undo the camera scroll
|
|
spriteMatrix.e = src.x;
|
|
spriteMatrix.f = src.y;
|
|
|
|
// Multiply by the Sprite matrix, store result in calcMatrix
|
|
camMatrix.multiply(spriteMatrix, calcMatrix);
|
|
}
|
|
else
|
|
{
|
|
spriteMatrix.e -= camera.scrollX * src.scrollFactorX;
|
|
spriteMatrix.f -= camera.scrollY * src.scrollFactorY;
|
|
|
|
// Multiply by the Sprite matrix, store result in calcMatrix
|
|
camMatrix.multiply(spriteMatrix, calcMatrix);
|
|
}
|
|
|
|
skeleton.x = calcMatrix.tx;
|
|
skeleton.y = calcMatrix.ty;
|
|
|
|
skeleton.scaleX = calcMatrix.scaleX;
|
|
|
|
// Inverse or we get upside-down skeletons
|
|
skeleton.scaleY = calcMatrix.scaleY * -1;
|
|
|
|
if (src.scaleX < 0)
|
|
{
|
|
skeleton.scaleX *= -1;
|
|
|
|
src.root.rotation = RadToDeg(calcMatrix.rotationNormalized);
|
|
}
|
|
else
|
|
{
|
|
// +90 degrees to account for the difference in Spine vs. Phaser rotation
|
|
src.root.rotation = Wrap(RadToDeg(CounterClockwise(calcMatrix.rotationNormalized)) + 90, 0, 360);
|
|
}
|
|
|
|
if (src.scaleY < 0)
|
|
{
|
|
skeleton.scaleY *= -1;
|
|
|
|
if (src.scaleX < 0)
|
|
{
|
|
src.root.rotation -= (RadToDeg(calcMatrix.rotationNormalized) * 2);
|
|
}
|
|
else
|
|
{
|
|
src.root.rotation += (RadToDeg(calcMatrix.rotationNormalized) * 2);
|
|
}
|
|
}
|
|
|
|
if (camera.renderToTexture)
|
|
{
|
|
skeleton.y = calcMatrix.ty;
|
|
skeleton.scaleY *= -1;
|
|
}
|
|
|
|
skeleton.updateWorldTransform();
|
|
|
|
skeletonRenderer.ctx = context;
|
|
skeletonRenderer.debugRendering = (plugin.drawDebug || src.drawDebug);
|
|
|
|
context.save();
|
|
|
|
skeletonRenderer.draw(skeleton);
|
|
|
|
context.restore();
|
|
};
|
|
|
|
module.exports = SpineGameObjectCanvasRenderer;
|
|
|
|
|
|
/***/ }),
|
|
/* 260 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var Container = __webpack_require__(261);
|
|
var SpineContainerRender = __webpack_require__(347);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Spine Container is a special kind of Container created specifically for Spine Game Objects.
|
|
*
|
|
* You have all of the same features of a standard Container, but the rendering functions are optimized specifically
|
|
* for Spine Game Objects. You must only add ever Spine Game Objects, or other Spine Containers, to this type of Container.
|
|
* Although Phaser will not prevent you from adding other types, they will not render and are likely to throw runtime errors.
|
|
*
|
|
* To create one in a Scene, use the factory methods:
|
|
*
|
|
* ```javascript
|
|
* this.add.spineContainer();
|
|
* ```
|
|
*
|
|
* or
|
|
*
|
|
* ```javascript
|
|
* this.make.spineContainer();
|
|
* ```
|
|
*
|
|
* Note that you should not nest Spine Containers inside regular Containers if you wish to use masks on the
|
|
* container children. You can, however, mask children of Spine Containers if they are embedded within other
|
|
* Spine Containers. In short, if you need masking, don't mix and match the types.
|
|
*
|
|
* See the Container documentation for further details about what Containers can do.
|
|
*
|
|
* @class SpineContainer
|
|
* @extends Phaser.GameObjects.Container
|
|
* @constructor
|
|
* @since 3.50.0
|
|
*
|
|
* @param {Phaser.Scene} scene - A reference to the Scene that this Game Object belongs to.
|
|
* @param {SpinePlugin} pluginManager - A reference to the Phaser Spine Plugin.
|
|
* @param {number} x - The horizontal position of this Game Object in the world.
|
|
* @param {number} y - The vertical position of this Game Object in the world.
|
|
* @param {SpineGameObject[]} [children] - An optional array of Spine Game Objects to add to this Container.
|
|
*/
|
|
var SpineContainer = new Class({
|
|
|
|
Extends: Container,
|
|
|
|
Mixins: [
|
|
SpineContainerRender
|
|
],
|
|
|
|
initialize:
|
|
|
|
function SpineContainer (scene, plugin, x, y, children)
|
|
{
|
|
Container.call(this, scene, x, y, children);
|
|
|
|
// Same as SpineGameObject, to prevent the renderer from mis-typing it when batching
|
|
this.type = 'Spine';
|
|
|
|
/**
|
|
* A reference to the Spine Plugin.
|
|
*
|
|
* @name SpineContainer#plugin
|
|
* @type {SpinePlugin}
|
|
* @since 3.50.0
|
|
*/
|
|
this.plugin = plugin;
|
|
},
|
|
|
|
/**
|
|
* Internal destroy handler, called as part of the destroy process.
|
|
*
|
|
* @method SpineContainer#preDestroy
|
|
* @protected
|
|
* @since 3.50.0
|
|
*/
|
|
preDestroy: function ()
|
|
{
|
|
this.removeAll(!!this.exclusive);
|
|
|
|
this.localTransform.destroy();
|
|
this.tempTransformMatrix.destroy();
|
|
|
|
this.list = [];
|
|
this._displayList = null;
|
|
this.plugin = null;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = SpineContainer;
|
|
|
|
|
|
/***/ }),
|
|
/* 261 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author Felipe Alfonso <@bitnenfer>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var ArrayUtils = __webpack_require__(262);
|
|
var BlendModes = __webpack_require__(15);
|
|
var Class = __webpack_require__(0);
|
|
var Components = __webpack_require__(313);
|
|
var Events = __webpack_require__(59);
|
|
var GameObject = __webpack_require__(57);
|
|
var Rectangle = __webpack_require__(29);
|
|
var Render = __webpack_require__(343);
|
|
var Union = __webpack_require__(346);
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Container Game Object.
|
|
*
|
|
* A Container, as the name implies, can 'contain' other types of Game Object.
|
|
* When a Game Object is added to a Container, the Container becomes responsible for the rendering of it.
|
|
* By default it will be removed from the Display List and instead added to the Containers own internal list.
|
|
*
|
|
* The position of the Game Object automatically becomes relative to the position of the Container.
|
|
*
|
|
* The transform point of a Container is 0x0 (in local space) and that cannot be changed. The children you add to the
|
|
* Container should be positioned with this value in mind. I.e. you should treat 0x0 as being the center of
|
|
* the Container, and position children positively and negative around it as required.
|
|
*
|
|
* When the Container is rendered, all of its children are rendered as well, in the order in which they exist
|
|
* within the Container. Container children can be repositioned using methods such as `MoveUp`, `MoveDown` and `SendToBack`.
|
|
*
|
|
* If you modify a transform property of the Container, such as `Container.x` or `Container.rotation` then it will
|
|
* automatically influence all children as well.
|
|
*
|
|
* Containers can include other Containers for deeply nested transforms.
|
|
*
|
|
* Containers can have masks set on them and can be used as a mask too. However, Container children cannot be masked.
|
|
* The masks do not 'stack up'. Only a Container on the root of the display list will use its mask.
|
|
*
|
|
* Containers can be enabled for input. Because they do not have a texture you need to provide a shape for them
|
|
* to use as their hit area. Container children can also be enabled for input, independent of the Container.
|
|
*
|
|
* If input enabling a _child_ you should not set both the `origin` and a **negative** scale factor on the child,
|
|
* or the input area will become misaligned.
|
|
*
|
|
* Containers can be given a physics body for either Arcade Physics, Impact Physics or Matter Physics. However,
|
|
* if Container _children_ are enabled for physics you may get unexpected results, such as offset bodies,
|
|
* if the Container itself, or any of its ancestors, is positioned anywhere other than at 0 x 0. Container children
|
|
* with physics do not factor in the Container due to the excessive extra calculations needed. Please structure
|
|
* your game to work around this.
|
|
*
|
|
* It's important to understand the impact of using Containers. They add additional processing overhead into
|
|
* every one of their children. The deeper you nest them, the more the cost escalates. This is especially true
|
|
* for input events. You also loose the ability to set the display depth of Container children in the same
|
|
* flexible manner as those not within them. In short, don't use them for the sake of it. You pay a small cost
|
|
* every time you create one, try to structure your game around avoiding that where possible.
|
|
*
|
|
* @class Container
|
|
* @extends Phaser.GameObjects.GameObject
|
|
* @memberof Phaser.GameObjects
|
|
* @constructor
|
|
* @since 3.4.0
|
|
*
|
|
* @extends Phaser.GameObjects.Components.AlphaSingle
|
|
* @extends Phaser.GameObjects.Components.BlendMode
|
|
* @extends Phaser.GameObjects.Components.ComputedSize
|
|
* @extends Phaser.GameObjects.Components.Depth
|
|
* @extends Phaser.GameObjects.Components.Mask
|
|
* @extends Phaser.GameObjects.Components.Pipeline
|
|
* @extends Phaser.GameObjects.Components.Transform
|
|
* @extends Phaser.GameObjects.Components.Visible
|
|
*
|
|
* @param {Phaser.Scene} scene - The Scene to which this Game Object belongs. A Game Object can only belong to one Scene at a time.
|
|
* @param {number} [x=0] - The horizontal position of this Game Object in the world.
|
|
* @param {number} [y=0] - The vertical position of this Game Object in the world.
|
|
* @param {Phaser.GameObjects.GameObject[]} [children] - An optional array of Game Objects to add to this Container.
|
|
*/
|
|
var Container = new Class({
|
|
|
|
Extends: GameObject,
|
|
|
|
Mixins: [
|
|
Components.AlphaSingle,
|
|
Components.BlendMode,
|
|
Components.ComputedSize,
|
|
Components.Depth,
|
|
Components.Mask,
|
|
Components.Pipeline,
|
|
Components.Transform,
|
|
Components.Visible,
|
|
Render
|
|
],
|
|
|
|
initialize:
|
|
|
|
function Container (scene, x, y, children)
|
|
{
|
|
GameObject.call(this, scene, 'Container');
|
|
|
|
/**
|
|
* An array holding the children of this Container.
|
|
*
|
|
* @name Phaser.GameObjects.Container#list
|
|
* @type {Phaser.GameObjects.GameObject[]}
|
|
* @since 3.4.0
|
|
*/
|
|
this.list = [];
|
|
|
|
/**
|
|
* Does this Container exclusively manage its children?
|
|
*
|
|
* The default is `true` which means a child added to this Container cannot
|
|
* belong in another Container, which includes the Scene display list.
|
|
*
|
|
* If you disable this then this Container will no longer exclusively manage its children.
|
|
* This allows you to create all kinds of interesting graphical effects, such as replicating
|
|
* Game Objects without reparenting them all over the Scene.
|
|
* However, doing so will prevent children from receiving any kind of input event or have
|
|
* their physics bodies work by default, as they're no longer a single entity on the
|
|
* display list, but are being replicated where-ever this Container is.
|
|
*
|
|
* @name Phaser.GameObjects.Container#exclusive
|
|
* @type {boolean}
|
|
* @default true
|
|
* @since 3.4.0
|
|
*/
|
|
this.exclusive = true;
|
|
|
|
/**
|
|
* Containers can have an optional maximum size. If set to anything above 0 it
|
|
* will constrict the addition of new Game Objects into the Container, capping off
|
|
* the maximum limit the Container can grow in size to.
|
|
*
|
|
* @name Phaser.GameObjects.Container#maxSize
|
|
* @type {number}
|
|
* @default -1
|
|
* @since 3.4.0
|
|
*/
|
|
this.maxSize = -1;
|
|
|
|
/**
|
|
* The cursor position.
|
|
*
|
|
* @name Phaser.GameObjects.Container#position
|
|
* @type {number}
|
|
* @since 3.4.0
|
|
*/
|
|
this.position = 0;
|
|
|
|
/**
|
|
* Internal Transform Matrix used for local space conversion.
|
|
*
|
|
* @name Phaser.GameObjects.Container#localTransform
|
|
* @type {Phaser.GameObjects.Components.TransformMatrix}
|
|
* @since 3.4.0
|
|
*/
|
|
this.localTransform = new Components.TransformMatrix();
|
|
|
|
/**
|
|
* Internal temporary Transform Matrix used to avoid object creation.
|
|
*
|
|
* @name Phaser.GameObjects.Container#tempTransformMatrix
|
|
* @type {Phaser.GameObjects.Components.TransformMatrix}
|
|
* @private
|
|
* @since 3.4.0
|
|
*/
|
|
this.tempTransformMatrix = new Components.TransformMatrix();
|
|
|
|
/**
|
|
* The property key to sort by.
|
|
*
|
|
* @name Phaser.GameObjects.Container#_sortKey
|
|
* @type {string}
|
|
* @private
|
|
* @since 3.4.0
|
|
*/
|
|
this._sortKey = '';
|
|
|
|
/**
|
|
* A reference to the Scene Systems Event Emitter.
|
|
*
|
|
* @name Phaser.GameObjects.Container#_sysEvents
|
|
* @type {Phaser.Events.EventEmitter}
|
|
* @private
|
|
* @since 3.9.0
|
|
*/
|
|
this._sysEvents = scene.sys.events;
|
|
|
|
/**
|
|
* The horizontal scroll factor of this Container.
|
|
*
|
|
* The scroll factor controls the influence of the movement of a Camera upon this Container.
|
|
*
|
|
* When a camera scrolls it will change the location at which this Container is rendered on-screen.
|
|
* It does not change the Containers actual position values.
|
|
*
|
|
* For a Container, setting this value will only update the Container itself, not its children.
|
|
* If you wish to change the scrollFactor of the children as well, use the `setScrollFactor` method.
|
|
*
|
|
* A value of 1 means it will move exactly in sync with a camera.
|
|
* A value of 0 means it will not move at all, even if the camera moves.
|
|
* Other values control the degree to which the camera movement is mapped to this Container.
|
|
*
|
|
* Please be aware that scroll factor values other than 1 are not taken in to consideration when
|
|
* calculating physics collisions. Bodies always collide based on their world position, but changing
|
|
* the scroll factor is a visual adjustment to where the textures are rendered, which can offset
|
|
* them from physics bodies if not accounted for in your code.
|
|
*
|
|
* @name Phaser.GameObjects.Container#scrollFactorX
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.4.0
|
|
*/
|
|
this.scrollFactorX = 1;
|
|
|
|
/**
|
|
* The vertical scroll factor of this Container.
|
|
*
|
|
* The scroll factor controls the influence of the movement of a Camera upon this Container.
|
|
*
|
|
* When a camera scrolls it will change the location at which this Container is rendered on-screen.
|
|
* It does not change the Containers actual position values.
|
|
*
|
|
* For a Container, setting this value will only update the Container itself, not its children.
|
|
* If you wish to change the scrollFactor of the children as well, use the `setScrollFactor` method.
|
|
*
|
|
* A value of 1 means it will move exactly in sync with a camera.
|
|
* A value of 0 means it will not move at all, even if the camera moves.
|
|
* Other values control the degree to which the camera movement is mapped to this Container.
|
|
*
|
|
* Please be aware that scroll factor values other than 1 are not taken in to consideration when
|
|
* calculating physics collisions. Bodies always collide based on their world position, but changing
|
|
* the scroll factor is a visual adjustment to where the textures are rendered, which can offset
|
|
* them from physics bodies if not accounted for in your code.
|
|
*
|
|
* @name Phaser.GameObjects.Container#scrollFactorY
|
|
* @type {number}
|
|
* @default 1
|
|
* @since 3.4.0
|
|
*/
|
|
this.scrollFactorY = 1;
|
|
|
|
this.initPipeline();
|
|
|
|
this.setPosition(x, y);
|
|
|
|
this.clearAlpha();
|
|
|
|
this.setBlendMode(BlendModes.SKIP_CHECK);
|
|
|
|
if (children)
|
|
{
|
|
this.add(children);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Internal value to allow Containers to be used for input and physics.
|
|
* Do not change this value. It has no effect other than to break things.
|
|
*
|
|
* @name Phaser.GameObjects.Container#originX
|
|
* @type {number}
|
|
* @readonly
|
|
* @override
|
|
* @since 3.4.0
|
|
*/
|
|
originX: {
|
|
|
|
get: function ()
|
|
{
|
|
return 0.5;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Internal value to allow Containers to be used for input and physics.
|
|
* Do not change this value. It has no effect other than to break things.
|
|
*
|
|
* @name Phaser.GameObjects.Container#originY
|
|
* @type {number}
|
|
* @readonly
|
|
* @override
|
|
* @since 3.4.0
|
|
*/
|
|
originY: {
|
|
|
|
get: function ()
|
|
{
|
|
return 0.5;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Internal value to allow Containers to be used for input and physics.
|
|
* Do not change this value. It has no effect other than to break things.
|
|
*
|
|
* @name Phaser.GameObjects.Container#displayOriginX
|
|
* @type {number}
|
|
* @readonly
|
|
* @override
|
|
* @since 3.4.0
|
|
*/
|
|
displayOriginX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.width * 0.5;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Internal value to allow Containers to be used for input and physics.
|
|
* Do not change this value. It has no effect other than to break things.
|
|
*
|
|
* @name Phaser.GameObjects.Container#displayOriginY
|
|
* @type {number}
|
|
* @readonly
|
|
* @override
|
|
* @since 3.4.0
|
|
*/
|
|
displayOriginY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.height * 0.5;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Does this Container exclusively manage its children?
|
|
*
|
|
* The default is `true` which means a child added to this Container cannot
|
|
* belong in another Container, which includes the Scene display list.
|
|
*
|
|
* If you disable this then this Container will no longer exclusively manage its children.
|
|
* This allows you to create all kinds of interesting graphical effects, such as replicating
|
|
* Game Objects without reparenting them all over the Scene.
|
|
* However, doing so will prevent children from receiving any kind of input event or have
|
|
* their physics bodies work by default, as they're no longer a single entity on the
|
|
* display list, but are being replicated where-ever this Container is.
|
|
*
|
|
* @method Phaser.GameObjects.Container#setExclusive
|
|
* @since 3.4.0
|
|
*
|
|
* @param {boolean} [value=true] - The exclusive state of this Container.
|
|
*
|
|
* @return {this} This Container.
|
|
*/
|
|
setExclusive: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.exclusive = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Gets the bounds of this Container. It works by iterating all children of the Container,
|
|
* getting their respective bounds, and then working out a min-max rectangle from that.
|
|
* It does not factor in if the children render or not, all are included.
|
|
*
|
|
* Some children are unable to return their bounds, such as Graphics objects, in which case
|
|
* they are skipped.
|
|
*
|
|
* Depending on the quantity of children in this Container it could be a really expensive call,
|
|
* so cache it and only poll it as needed.
|
|
*
|
|
* The values are stored and returned in a Rectangle object.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getBounds
|
|
* @since 3.4.0
|
|
*
|
|
* @param {Phaser.Geom.Rectangle} [output] - A Geom.Rectangle object to store the values in. If not provided a new Rectangle will be created.
|
|
*
|
|
* @return {Phaser.Geom.Rectangle} The values stored in the output object.
|
|
*/
|
|
getBounds: function (output)
|
|
{
|
|
if (output === undefined) { output = new Rectangle(); }
|
|
|
|
output.setTo(this.x, this.y, 0, 0);
|
|
|
|
if (this.parentContainer)
|
|
{
|
|
var parentMatrix = this.parentContainer.getBoundsTransformMatrix();
|
|
var transformedPosition = parentMatrix.transformPoint(this.x, this.y);
|
|
|
|
output.setTo(transformedPosition.x, transformedPosition.y, 0, 0);
|
|
}
|
|
|
|
if (this.list.length > 0)
|
|
{
|
|
var children = this.list;
|
|
var tempRect = new Rectangle();
|
|
var hasSetFirst = false;
|
|
|
|
output.setEmpty();
|
|
|
|
for (var i = 0; i < children.length; i++)
|
|
{
|
|
var entry = children[i];
|
|
|
|
if (entry.getBounds)
|
|
{
|
|
entry.getBounds(tempRect);
|
|
|
|
if (!hasSetFirst)
|
|
{
|
|
output.setTo(tempRect.x, tempRect.y, tempRect.width, tempRect.height);
|
|
hasSetFirst = true;
|
|
}
|
|
else
|
|
{
|
|
Union(tempRect, output, output);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Internal add handler.
|
|
*
|
|
* @method Phaser.GameObjects.Container#addHandler
|
|
* @private
|
|
* @since 3.4.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just added to this Container.
|
|
*/
|
|
addHandler: function (gameObject)
|
|
{
|
|
gameObject.once(Events.DESTROY, this.remove, this);
|
|
|
|
if (this.exclusive)
|
|
{
|
|
if (gameObject.parentContainer)
|
|
{
|
|
gameObject.parentContainer.remove(gameObject);
|
|
}
|
|
|
|
gameObject.parentContainer = this;
|
|
|
|
gameObject.removeFromDisplayList();
|
|
|
|
gameObject.addedToScene();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Internal remove handler.
|
|
*
|
|
* @method Phaser.GameObjects.Container#removeHandler
|
|
* @private
|
|
* @since 3.4.0
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} gameObject - The Game Object that was just removed from this Container.
|
|
*/
|
|
removeHandler: function (gameObject)
|
|
{
|
|
gameObject.off(Events.DESTROY, this.remove, this);
|
|
|
|
if (this.exclusive)
|
|
{
|
|
gameObject.parentContainer = null;
|
|
|
|
gameObject.removedFromScene();
|
|
|
|
gameObject.addToDisplayList();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Takes a Point-like object, such as a Vector2, Geom.Point or object with public x and y properties,
|
|
* and transforms it into the space of this Container, then returns it in the output object.
|
|
*
|
|
* @method Phaser.GameObjects.Container#pointToContainer
|
|
* @since 3.4.0
|
|
*
|
|
* @param {Phaser.Types.Math.Vector2Like} source - The Source Point to be transformed.
|
|
* @param {Phaser.Types.Math.Vector2Like} [output] - A destination object to store the transformed point in. If none given a Vector2 will be created and returned.
|
|
*
|
|
* @return {Phaser.Types.Math.Vector2Like} The transformed point.
|
|
*/
|
|
pointToContainer: function (source, output)
|
|
{
|
|
if (output === undefined) { output = new Vector2(); }
|
|
|
|
if (this.parentContainer)
|
|
{
|
|
this.parentContainer.pointToContainer(source, output);
|
|
}
|
|
else
|
|
{
|
|
output.x = source.x;
|
|
output.y = source.y;
|
|
}
|
|
|
|
var tempMatrix = this.tempTransformMatrix;
|
|
|
|
// No need to loadIdentity because applyITRS overwrites every value anyway
|
|
tempMatrix.applyITRS(this.x, this.y, this.rotation, this.scaleX, this.scaleY);
|
|
|
|
tempMatrix.invert();
|
|
|
|
tempMatrix.transformPoint(source.x, source.y, output);
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Returns the world transform matrix as used for Bounds checks.
|
|
*
|
|
* The returned matrix is temporal and shouldn't be stored.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getBoundsTransformMatrix
|
|
* @since 3.4.0
|
|
*
|
|
* @return {Phaser.GameObjects.Components.TransformMatrix} The world transform matrix.
|
|
*/
|
|
getBoundsTransformMatrix: function ()
|
|
{
|
|
return this.getWorldTransformMatrix(this.tempTransformMatrix, this.localTransform);
|
|
},
|
|
|
|
/**
|
|
* Adds the given Game Object, or array of Game Objects, to this Container.
|
|
*
|
|
* Each Game Object must be unique within the Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#add
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {(T|T[])} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to add to the Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
add: function (child)
|
|
{
|
|
ArrayUtils.Add(this.list, child, this.maxSize, this.addHandler, this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds the given Game Object, or array of Game Objects, to this Container at the specified position.
|
|
*
|
|
* Existing Game Objects in the Container are shifted up.
|
|
*
|
|
* Each Game Object must be unique within the Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#addAt
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {(T|T[])} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to add to the Container.
|
|
* @param {number} [index=0] - The position to insert the Game Object/s at.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
addAt: function (child, index)
|
|
{
|
|
ArrayUtils.AddAt(this.list, child, index, this.maxSize, this.addHandler, this);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Returns the Game Object at the given position in this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getAt
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [$return]
|
|
*
|
|
* @param {number} index - The position to get the Game Object from.
|
|
*
|
|
* @return {?Phaser.GameObjects.GameObject} The Game Object at the specified index, or `null` if none found.
|
|
*/
|
|
getAt: function (index)
|
|
{
|
|
return this.list[index];
|
|
},
|
|
|
|
/**
|
|
* Returns the index of the given Game Object in this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getIndex
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object to search for in this Container.
|
|
*
|
|
* @return {number} The index of the Game Object in this Container, or -1 if not found.
|
|
*/
|
|
getIndex: function (child)
|
|
{
|
|
return this.list.indexOf(child);
|
|
},
|
|
|
|
/**
|
|
* Sort the contents of this Container so the items are in order based on the given property.
|
|
* For example: `sort('alpha')` would sort the elements based on the value of their `alpha` property.
|
|
*
|
|
* @method Phaser.GameObjects.Container#sort
|
|
* @since 3.4.0
|
|
*
|
|
* @param {string} property - The property to lexically sort by.
|
|
* @param {function} [handler] - Provide your own custom handler function. Will receive 2 children which it should compare and return a boolean.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
sort: function (property, handler)
|
|
{
|
|
if (!property)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
if (handler === undefined)
|
|
{
|
|
handler = function (childA, childB)
|
|
{
|
|
return childA[property] - childB[property];
|
|
};
|
|
}
|
|
|
|
ArrayUtils.StableSort(this.list, handler);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Searches for the first instance of a child with its `name` property matching the given argument.
|
|
* Should more than one child have the same name only the first is returned.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getByName
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [$return]
|
|
*
|
|
* @param {string} name - The name to search for.
|
|
*
|
|
* @return {?Phaser.GameObjects.GameObject} The first child with a matching name, or `null` if none were found.
|
|
*/
|
|
getByName: function (name)
|
|
{
|
|
return ArrayUtils.GetFirst(this.list, 'name', name);
|
|
},
|
|
|
|
/**
|
|
* Returns a random Game Object from this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getRandom
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [$return]
|
|
*
|
|
* @param {number} [startIndex=0] - An optional start index.
|
|
* @param {number} [length] - An optional length, the total number of elements (from the startIndex) to choose from.
|
|
*
|
|
* @return {?Phaser.GameObjects.GameObject} A random child from the Container, or `null` if the Container is empty.
|
|
*/
|
|
getRandom: function (startIndex, length)
|
|
{
|
|
return ArrayUtils.GetRandom(this.list, startIndex, length);
|
|
},
|
|
|
|
/**
|
|
* Gets the first Game Object in this Container.
|
|
*
|
|
* You can also specify a property and value to search for, in which case it will return the first
|
|
* Game Object in this Container with a matching property and / or value.
|
|
*
|
|
* For example: `getFirst('visible', true)` would return the first Game Object that had its `visible` property set.
|
|
*
|
|
* You can limit the search to the `startIndex` - `endIndex` range.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getFirst
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [$return]
|
|
*
|
|
* @param {string} property - The property to test on each Game Object in the Container.
|
|
* @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check.
|
|
* @param {number} [startIndex=0] - An optional start index to search from.
|
|
* @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included)
|
|
*
|
|
* @return {?Phaser.GameObjects.GameObject} The first matching Game Object, or `null` if none was found.
|
|
*/
|
|
getFirst: function (property, value, startIndex, endIndex)
|
|
{
|
|
return ArrayUtils.GetFirst(this.list, property, value, startIndex, endIndex);
|
|
},
|
|
|
|
/**
|
|
* Returns all Game Objects in this Container.
|
|
*
|
|
* You can optionally specify a matching criteria using the `property` and `value` arguments.
|
|
*
|
|
* For example: `getAll('body')` would return only Game Objects that have a body property.
|
|
*
|
|
* You can also specify a value to compare the property to:
|
|
*
|
|
* `getAll('visible', true)` would return only Game Objects that have their visible property set to `true`.
|
|
*
|
|
* Optionally you can specify a start and end index. For example if this Container had 100 Game Objects,
|
|
* and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only
|
|
* the first 50 Game Objects.
|
|
*
|
|
* @method Phaser.GameObjects.Container#getAll
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T[]} - [$return]
|
|
*
|
|
* @param {string} [property] - The property to test on each Game Object in the Container.
|
|
* @param {any} [value] - If property is set then the `property` must strictly equal this value to be included in the results.
|
|
* @param {number} [startIndex=0] - An optional start index to search from.
|
|
* @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included)
|
|
*
|
|
* @return {Phaser.GameObjects.GameObject[]} An array of matching Game Objects from this Container.
|
|
*/
|
|
getAll: function (property, value, startIndex, endIndex)
|
|
{
|
|
return ArrayUtils.GetAll(this.list, property, value, startIndex, endIndex);
|
|
},
|
|
|
|
/**
|
|
* Returns the total number of Game Objects in this Container that have a property
|
|
* matching the given value.
|
|
*
|
|
* For example: `count('visible', true)` would count all the elements that have their visible property set.
|
|
*
|
|
* You can optionally limit the operation to the `startIndex` - `endIndex` range.
|
|
*
|
|
* @method Phaser.GameObjects.Container#count
|
|
* @since 3.4.0
|
|
*
|
|
* @param {string} property - The property to check.
|
|
* @param {any} value - The value to check.
|
|
* @param {number} [startIndex=0] - An optional start index to search from.
|
|
* @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included)
|
|
*
|
|
* @return {number} The total number of Game Objects in this Container with a property matching the given value.
|
|
*/
|
|
count: function (property, value, startIndex, endIndex)
|
|
{
|
|
return ArrayUtils.CountAllMatching(this.list, property, value, startIndex, endIndex);
|
|
},
|
|
|
|
/**
|
|
* Swaps the position of two Game Objects in this Container.
|
|
* Both Game Objects must belong to this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#swap
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child1,child2]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child1 - The first Game Object to swap.
|
|
* @param {Phaser.GameObjects.GameObject} child2 - The second Game Object to swap.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
swap: function (child1, child2)
|
|
{
|
|
ArrayUtils.Swap(this.list, child1, child2);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Moves a Game Object to a new position within this Container.
|
|
*
|
|
* The Game Object must already be a child of this Container.
|
|
*
|
|
* The Game Object is removed from its old position and inserted into the new one.
|
|
* Therefore the Container size does not change. Other children will change position accordingly.
|
|
*
|
|
* @method Phaser.GameObjects.Container#moveTo
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object to move.
|
|
* @param {number} index - The new position of the Game Object in this Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
moveTo: function (child, index)
|
|
{
|
|
ArrayUtils.MoveTo(this.list, child, index);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Moves a Game Object above another one within this Container.
|
|
*
|
|
* These 2 Game Objects must already be children of this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#moveAbove
|
|
* @since 3.55.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child1,child2]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child1 - The Game Object to move above base Game Object.
|
|
* @param {Phaser.GameObjects.GameObject} child2 - The base Game Object.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
moveAbove: function (child1, child2)
|
|
{
|
|
ArrayUtils.MoveAbove(this.list, child1, child2);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Moves a Game Object below another one within this Container.
|
|
*
|
|
* These 2 Game Objects must already be children of this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#moveBelow
|
|
* @since 3.55.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child1,child2]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child1 - The Game Object to move below base Game Object.
|
|
* @param {Phaser.GameObjects.GameObject} child2 - The base Game Object.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
moveBelow: function (child1, child2)
|
|
{
|
|
ArrayUtils.MoveBelow(this.list, child1, child2);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes the given Game Object, or array of Game Objects, from this Container.
|
|
*
|
|
* The Game Objects must already be children of this Container.
|
|
*
|
|
* You can also optionally call `destroy` on each Game Object that is removed from the Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#remove
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {(T|T[])} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject|Phaser.GameObjects.GameObject[]} child - The Game Object, or array of Game Objects, to be removed from the Container.
|
|
* @param {boolean} [destroyChild=false] - Optionally call `destroy` on each child successfully removed from this Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
remove: function (child, destroyChild)
|
|
{
|
|
var removed = ArrayUtils.Remove(this.list, child, this.removeHandler, this);
|
|
|
|
if (destroyChild && removed)
|
|
{
|
|
if (!Array.isArray(removed))
|
|
{
|
|
removed = [ removed ];
|
|
}
|
|
|
|
for (var i = 0; i < removed.length; i++)
|
|
{
|
|
removed[i].destroy();
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes the Game Object at the given position in this Container.
|
|
*
|
|
* You can also optionally call `destroy` on the Game Object, if one is found.
|
|
*
|
|
* @method Phaser.GameObjects.Container#removeAt
|
|
* @since 3.4.0
|
|
*
|
|
* @param {number} index - The index of the Game Object to be removed.
|
|
* @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
removeAt: function (index, destroyChild)
|
|
{
|
|
var removed = ArrayUtils.RemoveAt(this.list, index, this.removeHandler, this);
|
|
|
|
if (destroyChild && removed)
|
|
{
|
|
removed.destroy();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes the Game Objects between the given positions in this Container.
|
|
*
|
|
* You can also optionally call `destroy` on each Game Object that is removed from the Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#removeBetween
|
|
* @since 3.4.0
|
|
*
|
|
* @param {number} [startIndex=0] - An optional start index to search from.
|
|
* @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included)
|
|
* @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
removeBetween: function (startIndex, endIndex, destroyChild)
|
|
{
|
|
var removed = ArrayUtils.RemoveBetween(this.list, startIndex, endIndex, this.removeHandler, this);
|
|
|
|
if (destroyChild)
|
|
{
|
|
for (var i = 0; i < removed.length; i++)
|
|
{
|
|
removed[i].destroy();
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Removes all Game Objects from this Container.
|
|
*
|
|
* You can also optionally call `destroy` on each Game Object that is removed from the Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#removeAll
|
|
* @since 3.4.0
|
|
*
|
|
* @param {boolean} [destroyChild=false] - Optionally call `destroy` on each Game Object successfully removed from this Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
removeAll: function (destroyChild)
|
|
{
|
|
var list = this.list;
|
|
|
|
if (destroyChild)
|
|
{
|
|
for (var i = 0; i < list.length; i++)
|
|
{
|
|
if (list[i] && list[i].scene)
|
|
{
|
|
list[i].off(Events.DESTROY, this.remove, this);
|
|
|
|
list[i].destroy();
|
|
}
|
|
}
|
|
|
|
this.list = [];
|
|
}
|
|
else
|
|
{
|
|
ArrayUtils.RemoveBetween(list, 0, list.length, this.removeHandler, this);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Brings the given Game Object to the top of this Container.
|
|
* This will cause it to render on-top of any other objects in the Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#bringToTop
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object to bring to the top of the Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
bringToTop: function (child)
|
|
{
|
|
ArrayUtils.BringToTop(this.list, child);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sends the given Game Object to the bottom of this Container.
|
|
* This will cause it to render below any other objects in the Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#sendToBack
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object to send to the bottom of the Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
sendToBack: function (child)
|
|
{
|
|
ArrayUtils.SendToBack(this.list, child);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Moves the given Game Object up one place in this Container, unless it's already at the top.
|
|
*
|
|
* @method Phaser.GameObjects.Container#moveUp
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
moveUp: function (child)
|
|
{
|
|
ArrayUtils.MoveUp(this.list, child);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Moves the given Game Object down one place in this Container, unless it's already at the bottom.
|
|
*
|
|
* @method Phaser.GameObjects.Container#moveDown
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object to be moved in the Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
moveDown: function (child)
|
|
{
|
|
ArrayUtils.MoveDown(this.list, child);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Reverses the order of all Game Objects in this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#reverse
|
|
* @since 3.4.0
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
reverse: function ()
|
|
{
|
|
this.list.reverse();
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Shuffles the all Game Objects in this Container using the Fisher-Yates implementation.
|
|
*
|
|
* @method Phaser.GameObjects.Container#shuffle
|
|
* @since 3.4.0
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
shuffle: function ()
|
|
{
|
|
ArrayUtils.Shuffle(this.list);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Replaces a Game Object in this Container with the new Game Object.
|
|
* The new Game Object cannot already be a child of this Container.
|
|
*
|
|
* @method Phaser.GameObjects.Container#replace
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [oldChild,newChild]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} oldChild - The Game Object in this Container that will be replaced.
|
|
* @param {Phaser.GameObjects.GameObject} newChild - The Game Object to be added to this Container.
|
|
* @param {boolean} [destroyChild=false] - Optionally call `destroy` on the Game Object if successfully removed from this Container.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
replace: function (oldChild, newChild, destroyChild)
|
|
{
|
|
var moved = ArrayUtils.Replace(this.list, oldChild, newChild);
|
|
|
|
if (moved)
|
|
{
|
|
this.addHandler(newChild);
|
|
this.removeHandler(oldChild);
|
|
|
|
if (destroyChild)
|
|
{
|
|
oldChild.destroy();
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Returns `true` if the given Game Object is a direct child of this Container.
|
|
*
|
|
* This check does not scan nested Containers.
|
|
*
|
|
* @method Phaser.GameObjects.Container#exists
|
|
* @since 3.4.0
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} T
|
|
* @genericUse {T} - [child]
|
|
*
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object to check for within this Container.
|
|
*
|
|
* @return {boolean} True if the Game Object is an immediate child of this Container, otherwise false.
|
|
*/
|
|
exists: function (child)
|
|
{
|
|
return (this.list.indexOf(child) > -1);
|
|
},
|
|
|
|
/**
|
|
* Sets the property to the given value on all Game Objects in this Container.
|
|
*
|
|
* Optionally you can specify a start and end index. For example if this Container had 100 Game Objects,
|
|
* and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only
|
|
* the first 50 Game Objects.
|
|
*
|
|
* @method Phaser.GameObjects.Container#setAll
|
|
* @since 3.4.0
|
|
*
|
|
* @param {string} property - The property that must exist on the Game Object.
|
|
* @param {any} value - The value to get the property to.
|
|
* @param {number} [startIndex=0] - An optional start index to search from.
|
|
* @param {number} [endIndex=Container.length] - An optional end index to search up to (but not included)
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
setAll: function (property, value, startIndex, endIndex)
|
|
{
|
|
ArrayUtils.SetAll(this.list, property, value, startIndex, endIndex);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* @callback EachContainerCallback
|
|
* @generic I - [item]
|
|
*
|
|
* @param {*} item - The child Game Object of the Container.
|
|
* @param {...*} [args] - Additional arguments that will be passed to the callback, after the child.
|
|
*/
|
|
|
|
/**
|
|
* Passes all Game Objects in this Container to the given callback.
|
|
*
|
|
* A copy of the Container is made before passing each entry to your callback.
|
|
* This protects against the callback itself modifying the Container.
|
|
*
|
|
* If you know for sure that the callback will not change the size of this Container
|
|
* then you can use the more performant `Container.iterate` method instead.
|
|
*
|
|
* @method Phaser.GameObjects.Container#each
|
|
* @since 3.4.0
|
|
*
|
|
* @param {function} callback - The function to call.
|
|
* @param {object} [context] - Value to use as `this` when executing callback.
|
|
* @param {...*} [args] - Additional arguments that will be passed to the callback, after the child.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
each: function (callback, context)
|
|
{
|
|
var args = [ null ];
|
|
var i;
|
|
var temp = this.list.slice();
|
|
var len = temp.length;
|
|
|
|
for (i = 2; i < arguments.length; i++)
|
|
{
|
|
args.push(arguments[i]);
|
|
}
|
|
|
|
for (i = 0; i < len; i++)
|
|
{
|
|
args[0] = temp[i];
|
|
|
|
callback.apply(context, args);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Passes all Game Objects in this Container to the given callback.
|
|
*
|
|
* Only use this method when you absolutely know that the Container will not be modified during
|
|
* the iteration, i.e. by removing or adding to its contents.
|
|
*
|
|
* @method Phaser.GameObjects.Container#iterate
|
|
* @since 3.4.0
|
|
*
|
|
* @param {function} callback - The function to call.
|
|
* @param {object} [context] - Value to use as `this` when executing callback.
|
|
* @param {...*} [args] - Additional arguments that will be passed to the callback, after the child.
|
|
*
|
|
* @return {this} This Container instance.
|
|
*/
|
|
iterate: function (callback, context)
|
|
{
|
|
var args = [ null ];
|
|
var i;
|
|
|
|
for (i = 2; i < arguments.length; i++)
|
|
{
|
|
args.push(arguments[i]);
|
|
}
|
|
|
|
for (i = 0; i < this.list.length; i++)
|
|
{
|
|
args[0] = this.list[i];
|
|
|
|
callback.apply(context, args);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the scroll factor of this Container and optionally all of its children.
|
|
*
|
|
* The scroll factor controls the influence of the movement of a Camera upon this Game Object.
|
|
*
|
|
* When a camera scrolls it will change the location at which this Game Object is rendered on-screen.
|
|
* It does not change the Game Objects actual position values.
|
|
*
|
|
* A value of 1 means it will move exactly in sync with a camera.
|
|
* A value of 0 means it will not move at all, even if the camera moves.
|
|
* Other values control the degree to which the camera movement is mapped to this Game Object.
|
|
*
|
|
* Please be aware that scroll factor values other than 1 are not taken in to consideration when
|
|
* calculating physics collisions. Bodies always collide based on their world position, but changing
|
|
* the scroll factor is a visual adjustment to where the textures are rendered, which can offset
|
|
* them from physics bodies if not accounted for in your code.
|
|
*
|
|
* @method Phaser.GameObjects.Container#setScrollFactor
|
|
* @since 3.4.0
|
|
*
|
|
* @param {number} x - The horizontal scroll factor of this Game Object.
|
|
* @param {number} [y=x] - The vertical scroll factor of this Game Object. If not set it will use the `x` value.
|
|
* @param {boolean} [updateChildren=false] - Apply this scrollFactor to all Container children as well?
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setScrollFactor: function (x, y, updateChildren)
|
|
{
|
|
if (y === undefined) { y = x; }
|
|
if (updateChildren === undefined) { updateChildren = false; }
|
|
|
|
this.scrollFactorX = x;
|
|
this.scrollFactorY = y;
|
|
|
|
if (updateChildren)
|
|
{
|
|
ArrayUtils.SetAll(this.list, 'scrollFactorX', x);
|
|
ArrayUtils.SetAll(this.list, 'scrollFactorY', y);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* The number of Game Objects inside this Container.
|
|
*
|
|
* @name Phaser.GameObjects.Container#length
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
length: {
|
|
|
|
get: function ()
|
|
{
|
|
return this.list.length;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Returns the first Game Object within the Container, or `null` if it is empty.
|
|
*
|
|
* You can move the cursor by calling `Container.next` and `Container.previous`.
|
|
*
|
|
* @name Phaser.GameObjects.Container#first
|
|
* @type {?Phaser.GameObjects.GameObject}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
first: {
|
|
|
|
get: function ()
|
|
{
|
|
this.position = 0;
|
|
|
|
if (this.list.length > 0)
|
|
{
|
|
return this.list[0];
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Returns the last Game Object within the Container, or `null` if it is empty.
|
|
*
|
|
* You can move the cursor by calling `Container.next` and `Container.previous`.
|
|
*
|
|
* @name Phaser.GameObjects.Container#last
|
|
* @type {?Phaser.GameObjects.GameObject}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
last: {
|
|
|
|
get: function ()
|
|
{
|
|
if (this.list.length > 0)
|
|
{
|
|
this.position = this.list.length - 1;
|
|
|
|
return this.list[this.position];
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Returns the next Game Object within the Container, or `null` if it is empty.
|
|
*
|
|
* You can move the cursor by calling `Container.next` and `Container.previous`.
|
|
*
|
|
* @name Phaser.GameObjects.Container#next
|
|
* @type {?Phaser.GameObjects.GameObject}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
next: {
|
|
|
|
get: function ()
|
|
{
|
|
if (this.position < this.list.length)
|
|
{
|
|
this.position++;
|
|
|
|
return this.list[this.position];
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Returns the previous Game Object within the Container, or `null` if it is empty.
|
|
*
|
|
* You can move the cursor by calling `Container.next` and `Container.previous`.
|
|
*
|
|
* @name Phaser.GameObjects.Container#previous
|
|
* @type {?Phaser.GameObjects.GameObject}
|
|
* @readonly
|
|
* @since 3.4.0
|
|
*/
|
|
previous: {
|
|
|
|
get: function ()
|
|
{
|
|
if (this.position > 0)
|
|
{
|
|
this.position--;
|
|
|
|
return this.list[this.position];
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Internal destroy handler, called as part of the destroy process.
|
|
*
|
|
* @method Phaser.GameObjects.Container#preDestroy
|
|
* @protected
|
|
* @since 3.9.0
|
|
*/
|
|
preDestroy: function ()
|
|
{
|
|
this.removeAll(!!this.exclusive);
|
|
|
|
this.localTransform.destroy();
|
|
this.tempTransformMatrix.destroy();
|
|
|
|
this.list = [];
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = Container;
|
|
|
|
|
|
/***/ }),
|
|
/* 262 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Utils.Array
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Matrix: __webpack_require__(263),
|
|
|
|
Add: __webpack_require__(272),
|
|
AddAt: __webpack_require__(273),
|
|
BringToTop: __webpack_require__(274),
|
|
CountAllMatching: __webpack_require__(275),
|
|
Each: __webpack_require__(276),
|
|
EachInRange: __webpack_require__(277),
|
|
FindClosestInSorted: __webpack_require__(278),
|
|
Flatten: __webpack_require__(279),
|
|
GetAll: __webpack_require__(280),
|
|
GetFirst: __webpack_require__(281),
|
|
GetRandom: __webpack_require__(282),
|
|
MoveDown: __webpack_require__(283),
|
|
MoveTo: __webpack_require__(284),
|
|
MoveUp: __webpack_require__(285),
|
|
MoveAbove: __webpack_require__(286),
|
|
MoveBelow: __webpack_require__(287),
|
|
NumberArray: __webpack_require__(288),
|
|
NumberArrayStep: __webpack_require__(289),
|
|
QuickSelect: __webpack_require__(290),
|
|
Range: __webpack_require__(291),
|
|
Remove: __webpack_require__(292),
|
|
RemoveAt: __webpack_require__(293),
|
|
RemoveBetween: __webpack_require__(294),
|
|
RemoveRandomElement: __webpack_require__(295),
|
|
Replace: __webpack_require__(296),
|
|
RotateLeft: __webpack_require__(62),
|
|
RotateRight: __webpack_require__(63),
|
|
SafeRange: __webpack_require__(5),
|
|
SendToBack: __webpack_require__(297),
|
|
SetAll: __webpack_require__(298),
|
|
Shuffle: __webpack_require__(64),
|
|
SortByDigits: __webpack_require__(299),
|
|
SpliceOne: __webpack_require__(13),
|
|
StableSort: __webpack_require__(300),
|
|
Swap: __webpack_require__(312)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 263 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.Utils.Array.Matrix
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
CheckMatrix: __webpack_require__(27),
|
|
MatrixToString: __webpack_require__(264),
|
|
ReverseColumns: __webpack_require__(266),
|
|
ReverseRows: __webpack_require__(267),
|
|
Rotate180: __webpack_require__(268),
|
|
RotateLeft: __webpack_require__(269),
|
|
RotateMatrix: __webpack_require__(17),
|
|
RotateRight: __webpack_require__(270),
|
|
Translate: __webpack_require__(271),
|
|
TransposeMatrix: __webpack_require__(61)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 264 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Pad = __webpack_require__(265);
|
|
var CheckMatrix = __webpack_require__(27);
|
|
|
|
/**
|
|
* Generates a string (which you can pass to console.log) from the given Array Matrix.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.MatrixToString
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix]
|
|
*
|
|
* @param {T[][]} [matrix] - A 2-dimensional array.
|
|
*
|
|
* @return {string} A string representing the matrix.
|
|
*/
|
|
var MatrixToString = function (matrix)
|
|
{
|
|
var str = '';
|
|
|
|
if (!CheckMatrix(matrix))
|
|
{
|
|
return str;
|
|
}
|
|
|
|
for (var r = 0; r < matrix.length; r++)
|
|
{
|
|
for (var c = 0; c < matrix[r].length; c++)
|
|
{
|
|
var cell = matrix[r][c].toString();
|
|
|
|
if (cell !== 'undefined')
|
|
{
|
|
str += Pad(cell, 2);
|
|
}
|
|
else
|
|
{
|
|
str += '?';
|
|
}
|
|
|
|
if (c < matrix[r].length - 1)
|
|
{
|
|
str += ' |';
|
|
}
|
|
}
|
|
|
|
if (r < matrix.length - 1)
|
|
{
|
|
str += '\n';
|
|
|
|
for (var i = 0; i < matrix[r].length; i++)
|
|
{
|
|
str += '---';
|
|
|
|
if (i < matrix[r].length - 1)
|
|
{
|
|
str += '+';
|
|
}
|
|
}
|
|
|
|
str += '\n';
|
|
}
|
|
|
|
}
|
|
|
|
return str;
|
|
};
|
|
|
|
module.exports = MatrixToString;
|
|
|
|
|
|
/***/ }),
|
|
/* 265 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Takes the given string and pads it out, to the length required, using the character
|
|
* specified. For example if you need a string to be 6 characters long, you can call:
|
|
*
|
|
* `pad('bob', 6, '-', 2)`
|
|
*
|
|
* This would return: `bob---` as it has padded it out to 6 characters, using the `-` on the right.
|
|
*
|
|
* You can also use it to pad numbers (they are always returned as strings):
|
|
*
|
|
* `pad(512, 6, '0', 1)`
|
|
*
|
|
* Would return: `000512` with the string padded to the left.
|
|
*
|
|
* If you don't specify a direction it'll pad to both sides:
|
|
*
|
|
* `pad('c64', 7, '*')`
|
|
*
|
|
* Would return: `**c64**`
|
|
*
|
|
* @function Phaser.Utils.String.Pad
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string|number|object} str - The target string. `toString()` will be called on the string, which means you can also pass in common data types like numbers.
|
|
* @param {number} [len=0] - The number of characters to be added.
|
|
* @param {string} [pad=" "] - The string to pad it out with (defaults to a space).
|
|
* @param {number} [dir=3] - The direction dir = 1 (left), 2 (right), 3 (both).
|
|
*
|
|
* @return {string} The padded string.
|
|
*/
|
|
var Pad = function (str, len, pad, dir)
|
|
{
|
|
if (len === undefined) { len = 0; }
|
|
if (pad === undefined) { pad = ' '; }
|
|
if (dir === undefined) { dir = 3; }
|
|
|
|
str = str.toString();
|
|
|
|
var padlen = 0;
|
|
|
|
if (len + 1 >= str.length)
|
|
{
|
|
switch (dir)
|
|
{
|
|
case 1:
|
|
str = new Array(len + 1 - str.length).join(pad) + str;
|
|
break;
|
|
|
|
case 3:
|
|
var right = Math.ceil((padlen = len - str.length) / 2);
|
|
var left = padlen - right;
|
|
str = new Array(left + 1).join(pad) + str + new Array(right + 1).join(pad);
|
|
break;
|
|
|
|
default:
|
|
str = str + new Array(len + 1 - str.length).join(pad);
|
|
break;
|
|
}
|
|
}
|
|
|
|
return str;
|
|
};
|
|
|
|
module.exports = Pad;
|
|
|
|
|
|
/***/ }),
|
|
/* 266 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Reverses the columns in the given Array Matrix.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.ReverseColumns
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix,$return]
|
|
*
|
|
* @param {T[][]} [matrix] - The array matrix to reverse the columns for.
|
|
*
|
|
* @return {T[][]} The column reversed matrix.
|
|
*/
|
|
var ReverseColumns = function (matrix)
|
|
{
|
|
return matrix.reverse();
|
|
};
|
|
|
|
module.exports = ReverseColumns;
|
|
|
|
|
|
/***/ }),
|
|
/* 267 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Reverses the rows in the given Array Matrix.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.ReverseRows
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix,$return]
|
|
*
|
|
* @param {T[][]} [matrix] - The array matrix to reverse the rows for.
|
|
*
|
|
* @return {T[][]} The column reversed matrix.
|
|
*/
|
|
var ReverseRows = function (matrix)
|
|
{
|
|
for (var i = 0; i < matrix.length; i++)
|
|
{
|
|
matrix[i].reverse();
|
|
}
|
|
|
|
return matrix;
|
|
};
|
|
|
|
module.exports = ReverseRows;
|
|
|
|
|
|
/***/ }),
|
|
/* 268 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var RotateMatrix = __webpack_require__(17);
|
|
|
|
/**
|
|
* Rotates the array matrix 180 degrees.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.Rotate180
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix,$return]
|
|
*
|
|
* @param {T[][]} [matrix] - The array to rotate.
|
|
*
|
|
* @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix.
|
|
*/
|
|
var Rotate180 = function (matrix)
|
|
{
|
|
return RotateMatrix(matrix, 180);
|
|
};
|
|
|
|
module.exports = Rotate180;
|
|
|
|
|
|
/***/ }),
|
|
/* 269 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var RotateMatrix = __webpack_require__(17);
|
|
|
|
/**
|
|
* Rotates the array matrix to the left (or 90 degrees)
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.RotateLeft
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix,$return]
|
|
*
|
|
* @param {T[][]} [matrix] - The array to rotate.
|
|
*
|
|
* @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix.
|
|
*/
|
|
var RotateLeft = function (matrix)
|
|
{
|
|
return RotateMatrix(matrix, 90);
|
|
};
|
|
|
|
module.exports = RotateLeft;
|
|
|
|
|
|
/***/ }),
|
|
/* 270 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var RotateMatrix = __webpack_require__(17);
|
|
|
|
/**
|
|
* Rotates the array matrix to the left (or -90 degrees)
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.RotateRight
|
|
* @since 3.0.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix,$return]
|
|
*
|
|
* @param {T[][]} [matrix] - The array to rotate.
|
|
*
|
|
* @return {T[][]} The rotated matrix array. The source matrix should be discard for the returned matrix.
|
|
*/
|
|
var RotateRight = function (matrix)
|
|
{
|
|
return RotateMatrix(matrix, -90);
|
|
};
|
|
|
|
module.exports = RotateRight;
|
|
|
|
|
|
/***/ }),
|
|
/* 271 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var RotateLeft = __webpack_require__(62);
|
|
var RotateRight = __webpack_require__(63);
|
|
|
|
/**
|
|
* Translates the given Array Matrix by shifting each column and row the
|
|
* amount specified.
|
|
*
|
|
* A matrix is a two-dimensional array (array of arrays), where all sub-arrays (rows)
|
|
* have the same length. There must be at least two rows. This is an example matrix:
|
|
*
|
|
* ```
|
|
* [
|
|
* [ 1, 1, 1, 1, 1, 1 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 2, 0, 1, 2, 0, 4 ],
|
|
* [ 2, 0, 3, 4, 0, 4 ],
|
|
* [ 2, 0, 0, 0, 0, 4 ],
|
|
* [ 3, 3, 3, 3, 3, 3 ]
|
|
* ]
|
|
* ```
|
|
*
|
|
* @function Phaser.Utils.Array.Matrix.Translate
|
|
* @since 3.50.0
|
|
*
|
|
* @generic T
|
|
* @genericUse {T[][]} - [matrix,$return]
|
|
*
|
|
* @param {T[][]} [matrix] - The array matrix to translate.
|
|
* @param {number} [x=0] - The amount to horizontally translate the matrix by.
|
|
* @param {number} [y=0] - The amount to vertically translate the matrix by.
|
|
*
|
|
* @return {T[][]} The translated matrix.
|
|
*/
|
|
var TranslateMatrix = function (matrix, x, y)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = 0; }
|
|
|
|
// Vertical translation
|
|
|
|
if (y !== 0)
|
|
{
|
|
if (y < 0)
|
|
{
|
|
// Shift Up
|
|
RotateLeft(matrix, Math.abs(y));
|
|
}
|
|
else
|
|
{
|
|
// Shift Down
|
|
RotateRight(matrix, y);
|
|
}
|
|
}
|
|
|
|
// Horizontal translation
|
|
|
|
if (x !== 0)
|
|
{
|
|
for (var i = 0; i < matrix.length; i++)
|
|
{
|
|
var row = matrix[i];
|
|
|
|
if (x < 0)
|
|
{
|
|
RotateLeft(row, Math.abs(x));
|
|
}
|
|
else
|
|
{
|
|
RotateRight(row, x);
|
|
}
|
|
}
|
|
}
|
|
|
|
return matrix;
|
|
};
|
|
|
|
module.exports = TranslateMatrix;
|
|
|
|
|
|
/***/ }),
|
|
/* 272 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Adds the given item, or array of items, to the array.
|
|
*
|
|
* Each item must be unique within the array.
|
|
*
|
|
* The array is modified in-place and returned.
|
|
*
|
|
* You can optionally specify a limit to the maximum size of the array. If the quantity of items being
|
|
* added will take the array length over this limit, it will stop adding once the limit is reached.
|
|
*
|
|
* You can optionally specify a callback to be invoked for each item successfully added to the array.
|
|
*
|
|
* @function Phaser.Utils.Array.Add
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to be added to.
|
|
* @param {any|any[]} item - The item, or array of items, to add to the array. Each item must be unique within the array.
|
|
* @param {number} [limit] - Optional limit which caps the size of the array.
|
|
* @param {function} [callback] - A callback to be invoked for each item successfully added to the array.
|
|
* @param {object} [context] - The context in which the callback is invoked.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var Add = function (array, item, limit, callback, context)
|
|
{
|
|
if (context === undefined) { context = array; }
|
|
|
|
if (limit > 0)
|
|
{
|
|
var remaining = limit - array.length;
|
|
|
|
// There's nothing more we can do here, the array is full
|
|
if (remaining <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Fast path to avoid array mutation and iteration
|
|
if (!Array.isArray(item))
|
|
{
|
|
if (array.indexOf(item) === -1)
|
|
{
|
|
array.push(item);
|
|
|
|
if (callback)
|
|
{
|
|
callback.call(context, item);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// If we got this far, we have an array of items to insert
|
|
|
|
// Ensure all the items are unique
|
|
var itemLength = item.length - 1;
|
|
|
|
while (itemLength >= 0)
|
|
{
|
|
if (array.indexOf(item[itemLength]) !== -1)
|
|
{
|
|
// Already exists in array, so remove it
|
|
item.splice(itemLength, 1);
|
|
}
|
|
|
|
itemLength--;
|
|
}
|
|
|
|
// Anything left?
|
|
itemLength = item.length;
|
|
|
|
if (itemLength === 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
if (limit > 0 && itemLength > remaining)
|
|
{
|
|
item.splice(remaining);
|
|
|
|
itemLength = remaining;
|
|
}
|
|
|
|
for (var i = 0; i < itemLength; i++)
|
|
{
|
|
var entry = item[i];
|
|
|
|
array.push(entry);
|
|
|
|
if (callback)
|
|
{
|
|
callback.call(context, entry);
|
|
}
|
|
}
|
|
|
|
return item;
|
|
};
|
|
|
|
module.exports = Add;
|
|
|
|
|
|
/***/ }),
|
|
/* 273 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Adds the given item, or array of items, to the array starting at the index specified.
|
|
*
|
|
* Each item must be unique within the array.
|
|
*
|
|
* Existing elements in the array are shifted up.
|
|
*
|
|
* The array is modified in-place and returned.
|
|
*
|
|
* You can optionally specify a limit to the maximum size of the array. If the quantity of items being
|
|
* added will take the array length over this limit, it will stop adding once the limit is reached.
|
|
*
|
|
* You can optionally specify a callback to be invoked for each item successfully added to the array.
|
|
*
|
|
* @function Phaser.Utils.Array.AddAt
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to be added to.
|
|
* @param {any|any[]} item - The item, or array of items, to add to the array.
|
|
* @param {number} [index=0] - The index in the array where the item will be inserted.
|
|
* @param {number} [limit] - Optional limit which caps the size of the array.
|
|
* @param {function} [callback] - A callback to be invoked for each item successfully added to the array.
|
|
* @param {object} [context] - The context in which the callback is invoked.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var AddAt = function (array, item, index, limit, callback, context)
|
|
{
|
|
if (index === undefined) { index = 0; }
|
|
if (context === undefined) { context = array; }
|
|
|
|
if (limit > 0)
|
|
{
|
|
var remaining = limit - array.length;
|
|
|
|
// There's nothing more we can do here, the array is full
|
|
if (remaining <= 0)
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// Fast path to avoid array mutation and iteration
|
|
if (!Array.isArray(item))
|
|
{
|
|
if (array.indexOf(item) === -1)
|
|
{
|
|
array.splice(index, 0, item);
|
|
|
|
if (callback)
|
|
{
|
|
callback.call(context, item);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// If we got this far, we have an array of items to insert
|
|
|
|
// Ensure all the items are unique
|
|
var itemLength = item.length - 1;
|
|
|
|
while (itemLength >= 0)
|
|
{
|
|
if (array.indexOf(item[itemLength]) !== -1)
|
|
{
|
|
// Already exists in array, so remove it
|
|
item.pop();
|
|
}
|
|
|
|
itemLength--;
|
|
}
|
|
|
|
// Anything left?
|
|
itemLength = item.length;
|
|
|
|
if (itemLength === 0)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
// Truncate to the limit
|
|
if (limit > 0 && itemLength > remaining)
|
|
{
|
|
item.splice(remaining);
|
|
|
|
itemLength = remaining;
|
|
}
|
|
|
|
for (var i = itemLength - 1; i >= 0; i--)
|
|
{
|
|
var entry = item[i];
|
|
|
|
array.splice(index, 0, entry);
|
|
|
|
if (callback)
|
|
{
|
|
callback.call(context, entry);
|
|
}
|
|
}
|
|
|
|
return item;
|
|
};
|
|
|
|
module.exports = AddAt;
|
|
|
|
|
|
/***/ }),
|
|
/* 274 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the given element to the top of the array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.BringToTop
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array.
|
|
* @param {*} item - The element to move.
|
|
*
|
|
* @return {*} The element that was moved.
|
|
*/
|
|
var BringToTop = function (array, item)
|
|
{
|
|
var currentIndex = array.indexOf(item);
|
|
|
|
if (currentIndex !== -1 && currentIndex < array.length)
|
|
{
|
|
array.splice(currentIndex, 1);
|
|
array.push(item);
|
|
}
|
|
|
|
return item;
|
|
};
|
|
|
|
module.exports = BringToTop;
|
|
|
|
|
|
/***/ }),
|
|
/* 275 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SafeRange = __webpack_require__(5);
|
|
|
|
/**
|
|
* Returns the total number of elements in the array which have a property matching the given value.
|
|
*
|
|
* @function Phaser.Utils.Array.CountAllMatching
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to search.
|
|
* @param {string} property - The property to test on each array element.
|
|
* @param {*} value - The value to test the property against. Must pass a strict (`===`) comparison check.
|
|
* @param {number} [startIndex] - An optional start index to search from.
|
|
* @param {number} [endIndex] - An optional end index to search to.
|
|
*
|
|
* @return {number} The total number of elements with properties matching the given value.
|
|
*/
|
|
var CountAllMatching = function (array, property, value, startIndex, endIndex)
|
|
{
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (endIndex === undefined) { endIndex = array.length; }
|
|
|
|
var total = 0;
|
|
|
|
if (SafeRange(array, startIndex, endIndex))
|
|
{
|
|
for (var i = startIndex; i < endIndex; i++)
|
|
{
|
|
var child = array[i];
|
|
|
|
if (child[property] === value)
|
|
{
|
|
total++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return total;
|
|
};
|
|
|
|
module.exports = CountAllMatching;
|
|
|
|
|
|
/***/ }),
|
|
/* 276 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Passes each element in the array to the given callback.
|
|
*
|
|
* @function Phaser.Utils.Array.Each
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to search.
|
|
* @param {function} callback - A callback to be invoked for each item in the array.
|
|
* @param {object} context - The context in which the callback is invoked.
|
|
* @param {...*} [args] - Additional arguments that will be passed to the callback, after the current array item.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var Each = function (array, callback, context)
|
|
{
|
|
var i;
|
|
var args = [ null ];
|
|
|
|
for (i = 3; i < arguments.length; i++)
|
|
{
|
|
args.push(arguments[i]);
|
|
}
|
|
|
|
for (i = 0; i < array.length; i++)
|
|
{
|
|
args[0] = array[i];
|
|
|
|
callback.apply(context, args);
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = Each;
|
|
|
|
|
|
/***/ }),
|
|
/* 277 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SafeRange = __webpack_require__(5);
|
|
|
|
/**
|
|
* Passes each element in the array, between the start and end indexes, to the given callback.
|
|
*
|
|
* @function Phaser.Utils.Array.EachInRange
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to search.
|
|
* @param {function} callback - A callback to be invoked for each item in the array.
|
|
* @param {object} context - The context in which the callback is invoked.
|
|
* @param {number} startIndex - The start index to search from.
|
|
* @param {number} endIndex - The end index to search to.
|
|
* @param {...*} [args] - Additional arguments that will be passed to the callback, after the child.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var EachInRange = function (array, callback, context, startIndex, endIndex)
|
|
{
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (endIndex === undefined) { endIndex = array.length; }
|
|
|
|
if (SafeRange(array, startIndex, endIndex))
|
|
{
|
|
var i;
|
|
var args = [ null ];
|
|
|
|
for (i = 5; i < arguments.length; i++)
|
|
{
|
|
args.push(arguments[i]);
|
|
}
|
|
|
|
for (i = startIndex; i < endIndex; i++)
|
|
{
|
|
args[0] = array[i];
|
|
|
|
callback.apply(context, args);
|
|
}
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = EachInRange;
|
|
|
|
|
|
/***/ }),
|
|
/* 278 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Searches a pre-sorted array for the closet value to the given number.
|
|
*
|
|
* If the `key` argument is given it will assume the array contains objects that all have the required `key` property name,
|
|
* and will check for the closest value of those to the given number.
|
|
*
|
|
* @function Phaser.Utils.Array.FindClosestInSorted
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} value - The value to search for in the array.
|
|
* @param {array} array - The array to search, which must be sorted.
|
|
* @param {string} [key] - An optional property key. If specified the array elements property will be checked against value.
|
|
*
|
|
* @return {(number|any)} The nearest value found in the array, or if a `key` was given, the nearest object with the matching property value.
|
|
*/
|
|
var FindClosestInSorted = function (value, array, key)
|
|
{
|
|
if (!array.length)
|
|
{
|
|
return NaN;
|
|
}
|
|
else if (array.length === 1)
|
|
{
|
|
return array[0];
|
|
}
|
|
|
|
var i = 1;
|
|
var low;
|
|
var high;
|
|
|
|
if (key)
|
|
{
|
|
if (value < array[0][key])
|
|
{
|
|
return array[0];
|
|
}
|
|
|
|
while (array[i][key] < value)
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
while (array[i] < value)
|
|
{
|
|
i++;
|
|
}
|
|
}
|
|
|
|
if (i > array.length)
|
|
{
|
|
i = array.length;
|
|
}
|
|
|
|
if (key)
|
|
{
|
|
low = array[i - 1][key];
|
|
high = array[i][key];
|
|
|
|
return ((high - value) <= (value - low)) ? array[i] : array[i - 1];
|
|
}
|
|
else
|
|
{
|
|
low = array[i - 1];
|
|
high = array[i];
|
|
|
|
return ((high - value) <= (value - low)) ? high : low;
|
|
}
|
|
};
|
|
|
|
module.exports = FindClosestInSorted;
|
|
|
|
|
|
/***/ }),
|
|
/* 279 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Takes an array and flattens it, returning a shallow-copy flattened array.
|
|
*
|
|
* @function Phaser.Utils.Array.Flatten
|
|
* @since 3.60.0
|
|
*
|
|
* @param {array} array - The array to flatten.
|
|
* @param {array} [output] - An array to hold the results in.
|
|
*
|
|
* @return {array} The flattened output array.
|
|
*/
|
|
var Flatten = function (array, output)
|
|
{
|
|
if (output === undefined) { output = []; }
|
|
|
|
for (var i = 0; i < array.length; i++)
|
|
{
|
|
if (Array.isArray(array[i]))
|
|
{
|
|
Flatten(array[i], output);
|
|
}
|
|
else
|
|
{
|
|
output.push(array[i]);
|
|
}
|
|
}
|
|
|
|
return output;
|
|
};
|
|
|
|
module.exports = Flatten;
|
|
|
|
|
|
/***/ }),
|
|
/* 280 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SafeRange = __webpack_require__(5);
|
|
|
|
/**
|
|
* Returns all elements in the array.
|
|
*
|
|
* You can optionally specify a matching criteria using the `property` and `value` arguments.
|
|
*
|
|
* For example: `getAll('visible', true)` would return only elements that have their visible property set.
|
|
*
|
|
* Optionally you can specify a start and end index. For example if the array had 100 elements,
|
|
* and you set `startIndex` to 0 and `endIndex` to 50, it would return matches from only
|
|
* the first 50 elements.
|
|
*
|
|
* @function Phaser.Utils.Array.GetAll
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to search.
|
|
* @param {string} [property] - The property to test on each array element.
|
|
* @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check.
|
|
* @param {number} [startIndex] - An optional start index to search from.
|
|
* @param {number} [endIndex] - An optional end index to search to.
|
|
*
|
|
* @return {array} All matching elements from the array.
|
|
*/
|
|
var GetAll = function (array, property, value, startIndex, endIndex)
|
|
{
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (endIndex === undefined) { endIndex = array.length; }
|
|
|
|
var output = [];
|
|
|
|
if (SafeRange(array, startIndex, endIndex))
|
|
{
|
|
for (var i = startIndex; i < endIndex; i++)
|
|
{
|
|
var child = array[i];
|
|
|
|
if (!property ||
|
|
(property && value === undefined && child.hasOwnProperty(property)) ||
|
|
(property && value !== undefined && child[property] === value))
|
|
{
|
|
output.push(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
return output;
|
|
};
|
|
|
|
module.exports = GetAll;
|
|
|
|
|
|
/***/ }),
|
|
/* 281 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SafeRange = __webpack_require__(5);
|
|
|
|
/**
|
|
* Returns the first element in the array.
|
|
*
|
|
* You can optionally specify a matching criteria using the `property` and `value` arguments.
|
|
*
|
|
* For example: `getAll('visible', true)` would return the first element that had its `visible` property set.
|
|
*
|
|
* Optionally you can specify a start and end index. For example if the array had 100 elements,
|
|
* and you set `startIndex` to 0 and `endIndex` to 50, it would search only the first 50 elements.
|
|
*
|
|
* @function Phaser.Utils.Array.GetFirst
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to search.
|
|
* @param {string} [property] - The property to test on each array element.
|
|
* @param {*} [value] - The value to test the property against. Must pass a strict (`===`) comparison check.
|
|
* @param {number} [startIndex=0] - An optional start index to search from.
|
|
* @param {number} [endIndex=array.length] - An optional end index to search up to (but not included)
|
|
*
|
|
* @return {object} The first matching element from the array, or `null` if no element could be found in the range given.
|
|
*/
|
|
var GetFirst = function (array, property, value, startIndex, endIndex)
|
|
{
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (endIndex === undefined) { endIndex = array.length; }
|
|
|
|
if (SafeRange(array, startIndex, endIndex))
|
|
{
|
|
for (var i = startIndex; i < endIndex; i++)
|
|
{
|
|
var child = array[i];
|
|
|
|
if (!property ||
|
|
(property && value === undefined && child.hasOwnProperty(property)) ||
|
|
(property && value !== undefined && child[property] === value))
|
|
{
|
|
return child;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
module.exports = GetFirst;
|
|
|
|
|
|
/***/ }),
|
|
/* 282 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Returns a Random element from the array.
|
|
*
|
|
* @function Phaser.Utils.Array.GetRandom
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} array - The array to select the random entry from.
|
|
* @param {number} [startIndex=0] - An optional start index.
|
|
* @param {number} [length=array.length] - An optional length, the total number of elements (from the startIndex) to choose from.
|
|
*
|
|
* @return {*} A random element from the array, or `null` if no element could be found in the range given.
|
|
*/
|
|
var GetRandom = function (array, startIndex, length)
|
|
{
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (length === undefined) { length = array.length; }
|
|
|
|
var randomIndex = startIndex + Math.floor(Math.random() * length);
|
|
|
|
return (array[randomIndex] === undefined) ? null : array[randomIndex];
|
|
};
|
|
|
|
module.exports = GetRandom;
|
|
|
|
|
|
/***/ }),
|
|
/* 283 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the given array element down one place in the array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.MoveDown
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The input array.
|
|
* @param {*} item - The element to move down the array.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var MoveDown = function (array, item)
|
|
{
|
|
var currentIndex = array.indexOf(item);
|
|
|
|
if (currentIndex > 0)
|
|
{
|
|
var item2 = array[currentIndex - 1];
|
|
|
|
var index2 = array.indexOf(item2);
|
|
|
|
array[currentIndex] = item2;
|
|
array[index2] = item;
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = MoveDown;
|
|
|
|
|
|
/***/ }),
|
|
/* 284 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves an element in an array to a new position within the same array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.MoveTo
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array.
|
|
* @param {*} item - The element to move.
|
|
* @param {number} index - The new index that the element will be moved to.
|
|
*
|
|
* @return {*} The element that was moved.
|
|
*/
|
|
var MoveTo = function (array, item, index)
|
|
{
|
|
var currentIndex = array.indexOf(item);
|
|
|
|
if (currentIndex === -1 || index < 0 || index >= array.length)
|
|
{
|
|
throw new Error('Supplied index out of bounds');
|
|
}
|
|
|
|
if (currentIndex !== index)
|
|
{
|
|
// Remove
|
|
array.splice(currentIndex, 1);
|
|
|
|
// Add in new location
|
|
array.splice(index, 0, item);
|
|
}
|
|
|
|
return item;
|
|
};
|
|
|
|
module.exports = MoveTo;
|
|
|
|
|
|
/***/ }),
|
|
/* 285 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the given array element up one place in the array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.MoveUp
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The input array.
|
|
* @param {*} item - The element to move up the array.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var MoveUp = function (array, item)
|
|
{
|
|
var currentIndex = array.indexOf(item);
|
|
|
|
if (currentIndex !== -1 && currentIndex < array.length - 1)
|
|
{
|
|
// The element one above `item` in the array
|
|
var item2 = array[currentIndex + 1];
|
|
var index2 = array.indexOf(item2);
|
|
|
|
array[currentIndex] = item2;
|
|
array[index2] = item;
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = MoveUp;
|
|
|
|
|
|
/***/ }),
|
|
/* 286 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the given array element above another one in the array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.MoveAbove
|
|
* @since 3.55.0
|
|
*
|
|
* @param {array} array - The input array.
|
|
* @param {*} item1 - The element to move above base element.
|
|
* @param {*} item2 - The base element.
|
|
*
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var MoveAbove = function (array, item1, item2)
|
|
{
|
|
if (item1 === item2)
|
|
{
|
|
return array;
|
|
}
|
|
|
|
var currentIndex = array.indexOf(item1);
|
|
var baseIndex = array.indexOf(item2);
|
|
|
|
if (currentIndex < 0 || baseIndex < 0)
|
|
{
|
|
throw new Error('Supplied items must be elements of the same array');
|
|
}
|
|
|
|
if (currentIndex > baseIndex)
|
|
{
|
|
// item1 is already above item2
|
|
return array;
|
|
}
|
|
|
|
// Remove
|
|
array.splice(currentIndex, 1);
|
|
|
|
// Add in new location
|
|
if (baseIndex === array.length - 1)
|
|
{
|
|
array.push(item1);
|
|
}
|
|
else
|
|
{
|
|
array.splice(baseIndex, 0, item1);
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = MoveAbove;
|
|
|
|
|
|
/***/ }),
|
|
/* 287 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the given array element below another one in the array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.MoveBelow
|
|
* @since 3.55.0
|
|
*
|
|
* @param {array} array - The input array.
|
|
* @param {*} item1 - The element to move below base element.
|
|
* @param {*} item2 - The base element.
|
|
*
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var MoveBelow = function (array, item1, item2)
|
|
{
|
|
if (item1 === item2)
|
|
{
|
|
return array;
|
|
}
|
|
|
|
var currentIndex = array.indexOf(item1);
|
|
var baseIndex = array.indexOf(item2);
|
|
|
|
if (currentIndex < 0 || baseIndex < 0)
|
|
{
|
|
throw new Error('Supplied items must be elements of the same array');
|
|
}
|
|
|
|
if (currentIndex < baseIndex)
|
|
{
|
|
// item1 is already below item2
|
|
return array;
|
|
}
|
|
|
|
// Remove
|
|
array.splice(currentIndex, 1);
|
|
|
|
// Add in new location
|
|
if (baseIndex === 0)
|
|
{
|
|
array.unshift(item1);
|
|
}
|
|
else
|
|
{
|
|
array.splice(baseIndex, 0, item1);
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = MoveBelow;
|
|
|
|
|
|
/***/ }),
|
|
/* 288 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Create an array representing the range of numbers (usually integers), between, and inclusive of,
|
|
* the given `start` and `end` arguments. For example:
|
|
*
|
|
* `var array = Phaser.Utils.Array.NumberArray(2, 4); // array = [2, 3, 4]`
|
|
* `var array = Phaser.Utils.Array.NumberArray(0, 9); // array = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]`
|
|
* `var array = Phaser.Utils.Array.NumberArray(8, 2); // array = [8, 7, 6, 5, 4, 3, 2]`
|
|
*
|
|
* This is equivalent to `Phaser.Utils.Array.NumberArrayStep(start, end, 1)`.
|
|
*
|
|
* You can optionally provide a prefix and / or suffix string. If given the array will contain
|
|
* strings, not integers. For example:
|
|
*
|
|
* `var array = Phaser.Utils.Array.NumberArray(1, 4, 'Level '); // array = ["Level 1", "Level 2", "Level 3", "Level 4"]`
|
|
* `var array = Phaser.Utils.Array.NumberArray(5, 7, 'HD-', '.png'); // array = ["HD-5.png", "HD-6.png", "HD-7.png"]`
|
|
*
|
|
* @function Phaser.Utils.Array.NumberArray
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} start - The minimum value the array starts with.
|
|
* @param {number} end - The maximum value the array contains.
|
|
* @param {string} [prefix] - Optional prefix to place before the number. If provided the array will contain strings, not integers.
|
|
* @param {string} [suffix] - Optional suffix to place after the number. If provided the array will contain strings, not integers.
|
|
*
|
|
* @return {(number[]|string[])} The array of number values, or strings if a prefix or suffix was provided.
|
|
*/
|
|
var NumberArray = function (start, end, prefix, suffix)
|
|
{
|
|
var result = [];
|
|
|
|
var i;
|
|
var asString = false;
|
|
|
|
if (prefix || suffix)
|
|
{
|
|
asString = true;
|
|
|
|
if (!prefix)
|
|
{
|
|
prefix = '';
|
|
}
|
|
|
|
if (!suffix)
|
|
{
|
|
suffix = '';
|
|
}
|
|
}
|
|
|
|
if (end < start)
|
|
{
|
|
for (i = start; i >= end; i--)
|
|
{
|
|
if (asString)
|
|
{
|
|
result.push(prefix + i.toString() + suffix);
|
|
}
|
|
else
|
|
{
|
|
result.push(i);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (i = start; i <= end; i++)
|
|
{
|
|
if (asString)
|
|
{
|
|
result.push(prefix + i.toString() + suffix);
|
|
}
|
|
else
|
|
{
|
|
result.push(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
module.exports = NumberArray;
|
|
|
|
|
|
/***/ }),
|
|
/* 289 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var RoundAwayFromZero = __webpack_require__(43);
|
|
|
|
/**
|
|
* Create an array of numbers (positive and/or negative) progressing from `start`
|
|
* up to but not including `end` by advancing by `step`.
|
|
*
|
|
* If `start` is less than `end` a zero-length range is created unless a negative `step` is specified.
|
|
*
|
|
* Certain values for `start` and `end` (eg. NaN/undefined/null) are currently coerced to 0;
|
|
* for forward compatibility make sure to pass in actual numbers.
|
|
*
|
|
* @example
|
|
* NumberArrayStep(4);
|
|
* // => [0, 1, 2, 3]
|
|
*
|
|
* NumberArrayStep(1, 5);
|
|
* // => [1, 2, 3, 4]
|
|
*
|
|
* NumberArrayStep(0, 20, 5);
|
|
* // => [0, 5, 10, 15]
|
|
*
|
|
* NumberArrayStep(0, -4, -1);
|
|
* // => [0, -1, -2, -3]
|
|
*
|
|
* NumberArrayStep(1, 4, 0);
|
|
* // => [1, 1, 1]
|
|
*
|
|
* NumberArrayStep(0);
|
|
* // => []
|
|
*
|
|
* @function Phaser.Utils.Array.NumberArrayStep
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [start=0] - The start of the range.
|
|
* @param {number} [end=null] - The end of the range.
|
|
* @param {number} [step=1] - The value to increment or decrement by.
|
|
*
|
|
* @return {number[]} The array of number values.
|
|
*/
|
|
var NumberArrayStep = function (start, end, step)
|
|
{
|
|
if (start === undefined) { start = 0; }
|
|
if (end === undefined) { end = null; }
|
|
if (step === undefined) { step = 1; }
|
|
|
|
if (end === null)
|
|
{
|
|
end = start;
|
|
start = 0;
|
|
}
|
|
|
|
var result = [];
|
|
|
|
var total = Math.max(RoundAwayFromZero((end - start) / (step || 1)), 0);
|
|
|
|
for (var i = 0; i < total; i++)
|
|
{
|
|
result.push(start);
|
|
start += step;
|
|
}
|
|
|
|
return result;
|
|
};
|
|
|
|
module.exports = NumberArrayStep;
|
|
|
|
|
|
/***/ }),
|
|
/* 290 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function swap (arr, i, j)
|
|
{
|
|
var tmp = arr[i];
|
|
arr[i] = arr[j];
|
|
arr[j] = tmp;
|
|
}
|
|
|
|
/**
|
|
* @ignore
|
|
*/
|
|
function defaultCompare (a, b)
|
|
{
|
|
return a < b ? -1 : a > b ? 1 : 0;
|
|
}
|
|
|
|
/**
|
|
* A [Floyd-Rivest](https://en.wikipedia.org/wiki/Floyd%E2%80%93Rivest_algorithm) quick selection algorithm.
|
|
*
|
|
* Rearranges the array items so that all items in the [left, k] range are smaller than all items in [k, right];
|
|
* The k-th element will have the (k - left + 1)th smallest value in [left, right].
|
|
*
|
|
* The array is modified in-place.
|
|
*
|
|
* Based on code by [Vladimir Agafonkin](https://www.npmjs.com/~mourner)
|
|
*
|
|
* @function Phaser.Utils.Array.QuickSelect
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} arr - The array to sort.
|
|
* @param {number} k - The k-th element index.
|
|
* @param {number} [left=0] - The index of the left part of the range.
|
|
* @param {number} [right] - The index of the right part of the range.
|
|
* @param {function} [compare] - An optional comparison function. Is passed two elements and should return 0, 1 or -1.
|
|
*/
|
|
var QuickSelect = function (arr, k, left, right, compare)
|
|
{
|
|
if (left === undefined) { left = 0; }
|
|
if (right === undefined) { right = arr.length - 1; }
|
|
if (compare === undefined) { compare = defaultCompare; }
|
|
|
|
while (right > left)
|
|
{
|
|
if (right - left > 600)
|
|
{
|
|
var n = right - left + 1;
|
|
var m = k - left + 1;
|
|
var z = Math.log(n);
|
|
var s = 0.5 * Math.exp(2 * z / 3);
|
|
var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
|
|
var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
|
|
var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
|
|
|
|
QuickSelect(arr, k, newLeft, newRight, compare);
|
|
}
|
|
|
|
var t = arr[k];
|
|
var i = left;
|
|
var j = right;
|
|
|
|
swap(arr, left, k);
|
|
|
|
if (compare(arr[right], t) > 0)
|
|
{
|
|
swap(arr, left, right);
|
|
}
|
|
|
|
while (i < j)
|
|
{
|
|
swap(arr, i, j);
|
|
|
|
i++;
|
|
j--;
|
|
|
|
while (compare(arr[i], t) < 0)
|
|
{
|
|
i++;
|
|
}
|
|
|
|
while (compare(arr[j], t) > 0)
|
|
{
|
|
j--;
|
|
}
|
|
}
|
|
|
|
if (compare(arr[left], t) === 0)
|
|
{
|
|
swap(arr, left, j);
|
|
}
|
|
else
|
|
{
|
|
j++;
|
|
swap(arr, j, right);
|
|
}
|
|
|
|
if (j <= k)
|
|
{
|
|
left = j + 1;
|
|
}
|
|
|
|
if (k <= j)
|
|
{
|
|
right = j - 1;
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = QuickSelect;
|
|
|
|
|
|
/***/ }),
|
|
/* 291 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var GetValue = __webpack_require__(10);
|
|
var Shuffle = __webpack_require__(64);
|
|
|
|
var BuildChunk = function (a, b, qty)
|
|
{
|
|
var out = [];
|
|
|
|
for (var aIndex = 0; aIndex < a.length; aIndex++)
|
|
{
|
|
for (var bIndex = 0; bIndex < b.length; bIndex++)
|
|
{
|
|
for (var i = 0; i < qty; i++)
|
|
{
|
|
out.push({ a: a[aIndex], b: b[bIndex] });
|
|
}
|
|
}
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
/**
|
|
* Creates an array populated with a range of values, based on the given arguments and configuration object.
|
|
*
|
|
* Range ([a,b,c], [1,2,3]) =
|
|
* a1, a2, a3, b1, b2, b3, c1, c2, c3
|
|
*
|
|
* Range ([a,b], [1,2,3], qty = 3) =
|
|
* a1, a1, a1, a2, a2, a2, a3, a3, a3, b1, b1, b1, b2, b2, b2, b3, b3, b3
|
|
*
|
|
* Range ([a,b,c], [1,2,3], repeat x1) =
|
|
* a1, a2, a3, b1, b2, b3, c1, c2, c3, a1, a2, a3, b1, b2, b3, c1, c2, c3
|
|
*
|
|
* Range ([a,b], [1,2], repeat -1 = endless, max = 14) =
|
|
* Maybe if max is set then repeat goes to -1 automatically?
|
|
* a1, a2, b1, b2, a1, a2, b1, b2, a1, a2, b1, b2, a1, a2 (capped at 14 elements)
|
|
*
|
|
* Range ([a], [1,2,3,4,5], random = true) =
|
|
* a4, a1, a5, a2, a3
|
|
*
|
|
* Range ([a, b], [1,2,3], random = true) =
|
|
* b3, a2, a1, b1, a3, b2
|
|
*
|
|
* Range ([a, b, c], [1,2,3], randomB = true) =
|
|
* a3, a1, a2, b2, b3, b1, c1, c3, c2
|
|
*
|
|
* Range ([a], [1,2,3,4,5], yoyo = true) =
|
|
* a1, a2, a3, a4, a5, a5, a4, a3, a2, a1
|
|
*
|
|
* Range ([a, b], [1,2,3], yoyo = true) =
|
|
* a1, a2, a3, b1, b2, b3, b3, b2, b1, a3, a2, a1
|
|
*
|
|
* @function Phaser.Utils.Array.Range
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} a - The first array of range elements.
|
|
* @param {array} b - The second array of range elements.
|
|
* @param {object} [options] - A range configuration object. Can contain: repeat, random, randomB, yoyo, max, qty.
|
|
*
|
|
* @return {array} An array of arranged elements.
|
|
*/
|
|
var Range = function (a, b, options)
|
|
{
|
|
var max = GetValue(options, 'max', 0);
|
|
var qty = GetValue(options, 'qty', 1);
|
|
var random = GetValue(options, 'random', false);
|
|
var randomB = GetValue(options, 'randomB', false);
|
|
var repeat = GetValue(options, 'repeat', 0);
|
|
var yoyo = GetValue(options, 'yoyo', false);
|
|
|
|
var out = [];
|
|
|
|
if (randomB)
|
|
{
|
|
Shuffle(b);
|
|
}
|
|
|
|
// Endless repeat, so limit by max
|
|
if (repeat === -1)
|
|
{
|
|
if (max === 0)
|
|
{
|
|
repeat = 0;
|
|
}
|
|
else
|
|
{
|
|
// Work out how many repeats we need
|
|
var total = (a.length * b.length) * qty;
|
|
|
|
if (yoyo)
|
|
{
|
|
total *= 2;
|
|
}
|
|
|
|
repeat = Math.ceil(max / total);
|
|
}
|
|
}
|
|
|
|
for (var i = 0; i <= repeat; i++)
|
|
{
|
|
var chunk = BuildChunk(a, b, qty);
|
|
|
|
if (random)
|
|
{
|
|
Shuffle(chunk);
|
|
}
|
|
|
|
out = out.concat(chunk);
|
|
|
|
if (yoyo)
|
|
{
|
|
chunk.reverse();
|
|
|
|
out = out.concat(chunk);
|
|
}
|
|
}
|
|
|
|
if (max)
|
|
{
|
|
out.splice(max);
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = Range;
|
|
|
|
|
|
/***/ }),
|
|
/* 292 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SpliceOne = __webpack_require__(13);
|
|
|
|
/**
|
|
* Removes the given item, or array of items, from the array.
|
|
*
|
|
* The array is modified in-place.
|
|
*
|
|
* You can optionally specify a callback to be invoked for each item successfully removed from the array.
|
|
*
|
|
* @function Phaser.Utils.Array.Remove
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to be modified.
|
|
* @param {*|Array.<*>} item - The item, or array of items, to be removed from the array.
|
|
* @param {function} [callback] - A callback to be invoked for each item successfully removed from the array.
|
|
* @param {object} [context] - The context in which the callback is invoked.
|
|
*
|
|
* @return {*|Array.<*>} The item, or array of items, that were successfully removed from the array.
|
|
*/
|
|
var Remove = function (array, item, callback, context)
|
|
{
|
|
if (context === undefined) { context = array; }
|
|
|
|
var index;
|
|
|
|
// Fast path to avoid array mutation and iteration
|
|
if (!Array.isArray(item))
|
|
{
|
|
index = array.indexOf(item);
|
|
|
|
if (index !== -1)
|
|
{
|
|
SpliceOne(array, index);
|
|
|
|
if (callback)
|
|
{
|
|
callback.call(context, item);
|
|
}
|
|
|
|
return item;
|
|
}
|
|
else
|
|
{
|
|
return null;
|
|
}
|
|
}
|
|
|
|
// If we got this far, we have an array of items to remove
|
|
|
|
var itemLength = item.length - 1;
|
|
var removed = [];
|
|
|
|
while (itemLength >= 0)
|
|
{
|
|
var entry = item[itemLength];
|
|
|
|
index = array.indexOf(entry);
|
|
|
|
if (index !== -1)
|
|
{
|
|
SpliceOne(array, index);
|
|
|
|
removed.push(entry);
|
|
|
|
if (callback)
|
|
{
|
|
callback.call(context, entry);
|
|
}
|
|
}
|
|
|
|
itemLength--;
|
|
}
|
|
|
|
return removed;
|
|
};
|
|
|
|
module.exports = Remove;
|
|
|
|
|
|
/***/ }),
|
|
/* 293 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SpliceOne = __webpack_require__(13);
|
|
|
|
/**
|
|
* Removes the item from the given position in the array.
|
|
*
|
|
* The array is modified in-place.
|
|
*
|
|
* You can optionally specify a callback to be invoked for the item if it is successfully removed from the array.
|
|
*
|
|
* @function Phaser.Utils.Array.RemoveAt
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to be modified.
|
|
* @param {number} index - The array index to remove the item from. The index must be in bounds or it will throw an error.
|
|
* @param {function} [callback] - A callback to be invoked for the item removed from the array.
|
|
* @param {object} [context] - The context in which the callback is invoked.
|
|
*
|
|
* @return {*} The item that was removed.
|
|
*/
|
|
var RemoveAt = function (array, index, callback, context)
|
|
{
|
|
if (context === undefined) { context = array; }
|
|
|
|
if (index < 0 || index > array.length - 1)
|
|
{
|
|
throw new Error('Index out of bounds');
|
|
}
|
|
|
|
var item = SpliceOne(array, index);
|
|
|
|
if (callback)
|
|
{
|
|
callback.call(context, item);
|
|
}
|
|
|
|
return item;
|
|
};
|
|
|
|
module.exports = RemoveAt;
|
|
|
|
|
|
/***/ }),
|
|
/* 294 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SafeRange = __webpack_require__(5);
|
|
|
|
/**
|
|
* Removes the item within the given range in the array.
|
|
*
|
|
* The array is modified in-place.
|
|
*
|
|
* You can optionally specify a callback to be invoked for the item/s successfully removed from the array.
|
|
*
|
|
* @function Phaser.Utils.Array.RemoveBetween
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to be modified.
|
|
* @param {number} startIndex - The start index to remove from.
|
|
* @param {number} endIndex - The end index to remove to.
|
|
* @param {function} [callback] - A callback to be invoked for the item removed from the array.
|
|
* @param {object} [context] - The context in which the callback is invoked.
|
|
*
|
|
* @return {Array.<*>} An array of items that were removed.
|
|
*/
|
|
var RemoveBetween = function (array, startIndex, endIndex, callback, context)
|
|
{
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (endIndex === undefined) { endIndex = array.length; }
|
|
if (context === undefined) { context = array; }
|
|
|
|
if (SafeRange(array, startIndex, endIndex))
|
|
{
|
|
var size = endIndex - startIndex;
|
|
|
|
var removed = array.splice(startIndex, size);
|
|
|
|
if (callback)
|
|
{
|
|
for (var i = 0; i < removed.length; i++)
|
|
{
|
|
var entry = removed[i];
|
|
|
|
callback.call(context, entry);
|
|
}
|
|
}
|
|
|
|
return removed;
|
|
}
|
|
else
|
|
{
|
|
return [];
|
|
}
|
|
};
|
|
|
|
module.exports = RemoveBetween;
|
|
|
|
|
|
/***/ }),
|
|
/* 295 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SpliceOne = __webpack_require__(13);
|
|
|
|
/**
|
|
* Removes a random object from the given array and returns it.
|
|
* Will return null if there are no array items that fall within the specified range or if there is no item for the randomly chosen index.
|
|
*
|
|
* @function Phaser.Utils.Array.RemoveRandomElement
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} array - The array to removed a random element from.
|
|
* @param {number} [start=0] - The array index to start the search from.
|
|
* @param {number} [length=array.length] - Optional restriction on the number of elements to randomly select from.
|
|
*
|
|
* @return {object} The random element that was removed, or `null` if there were no array elements that fell within the given range.
|
|
*/
|
|
var RemoveRandomElement = function (array, start, length)
|
|
{
|
|
if (start === undefined) { start = 0; }
|
|
if (length === undefined) { length = array.length; }
|
|
|
|
var randomIndex = start + Math.floor(Math.random() * length);
|
|
|
|
return SpliceOne(array, randomIndex);
|
|
};
|
|
|
|
module.exports = RemoveRandomElement;
|
|
|
|
|
|
/***/ }),
|
|
/* 296 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Replaces an element of the array with the new element.
|
|
* The new element cannot already be a member of the array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.Replace
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to search within.
|
|
* @param {*} oldChild - The element in the array that will be replaced.
|
|
* @param {*} newChild - The element to be inserted into the array at the position of `oldChild`.
|
|
*
|
|
* @return {boolean} Returns true if the oldChild was successfully replaced, otherwise returns false.
|
|
*/
|
|
var Replace = function (array, oldChild, newChild)
|
|
{
|
|
var index1 = array.indexOf(oldChild);
|
|
var index2 = array.indexOf(newChild);
|
|
|
|
if (index1 !== -1 && index2 === -1)
|
|
{
|
|
array[index1] = newChild;
|
|
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
return false;
|
|
}
|
|
};
|
|
|
|
module.exports = Replace;
|
|
|
|
|
|
/***/ }),
|
|
/* 297 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Moves the given element to the bottom of the array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.SendToBack
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array.
|
|
* @param {*} item - The element to move.
|
|
*
|
|
* @return {*} The element that was moved.
|
|
*/
|
|
var SendToBack = function (array, item)
|
|
{
|
|
var currentIndex = array.indexOf(item);
|
|
|
|
if (currentIndex !== -1 && currentIndex > 0)
|
|
{
|
|
array.splice(currentIndex, 1);
|
|
array.unshift(item);
|
|
}
|
|
|
|
return item;
|
|
};
|
|
|
|
module.exports = SendToBack;
|
|
|
|
|
|
/***/ }),
|
|
/* 298 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var SafeRange = __webpack_require__(5);
|
|
|
|
/**
|
|
* Scans the array for elements with the given property. If found, the property is set to the `value`.
|
|
*
|
|
* For example: `SetAll('visible', true)` would set all elements that have a `visible` property to `false`.
|
|
*
|
|
* Optionally you can specify a start and end index. For example if the array had 100 elements,
|
|
* and you set `startIndex` to 0 and `endIndex` to 50, it would update only the first 50 elements.
|
|
*
|
|
* @function Phaser.Utils.Array.SetAll
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The array to search.
|
|
* @param {string} property - The property to test for on each array element.
|
|
* @param {*} value - The value to set the property to.
|
|
* @param {number} [startIndex] - An optional start index to search from.
|
|
* @param {number} [endIndex] - An optional end index to search to.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var SetAll = function (array, property, value, startIndex, endIndex)
|
|
{
|
|
if (startIndex === undefined) { startIndex = 0; }
|
|
if (endIndex === undefined) { endIndex = array.length; }
|
|
|
|
if (SafeRange(array, startIndex, endIndex))
|
|
{
|
|
for (var i = startIndex; i < endIndex; i++)
|
|
{
|
|
var entry = array[i];
|
|
|
|
if (entry.hasOwnProperty(property))
|
|
{
|
|
entry[property] = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = SetAll;
|
|
|
|
|
|
/***/ }),
|
|
/* 299 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Takes the given array and runs a numeric sort on it, ignoring any non-digits that
|
|
* may be in the entries.
|
|
*
|
|
* You should only run this on arrays containing strings.
|
|
*
|
|
* @function Phaser.Utils.Array.SortByDigits
|
|
* @since 3.50.0
|
|
*
|
|
* @param {string[]} array - The input array of strings.
|
|
*
|
|
* @return {string[]} The sorted input array.
|
|
*/
|
|
var SortByDigits = function (array)
|
|
{
|
|
var re = /\D/g;
|
|
|
|
array.sort(function (a, b)
|
|
{
|
|
return (parseInt(a.replace(re, ''), 10) - parseInt(b.replace(re, ''), 10));
|
|
});
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = SortByDigits;
|
|
|
|
|
|
/***/ }),
|
|
/* 300 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author Angry Bytes (and contributors)
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Device = __webpack_require__(301);
|
|
|
|
/**
|
|
* The comparator function.
|
|
*
|
|
* @ignore
|
|
*
|
|
* @param {*} a - The first item to test.
|
|
* @param {*} b - The second itemt to test.
|
|
*
|
|
* @return {boolean} True if they localCompare, otherwise false.
|
|
*/
|
|
function Compare (a, b)
|
|
{
|
|
return String(a).localeCompare(b);
|
|
}
|
|
|
|
/**
|
|
* Process the array contents.
|
|
*
|
|
* @ignore
|
|
*
|
|
* @param {array} array - The array to process.
|
|
* @param {function} compare - The comparison function.
|
|
*
|
|
* @return {array} - The processed array.
|
|
*/
|
|
function Process (array, compare)
|
|
{
|
|
// Short-circuit when there's nothing to sort.
|
|
var len = array.length;
|
|
|
|
if (len <= 1)
|
|
{
|
|
return array;
|
|
}
|
|
|
|
// Rather than dividing input, simply iterate chunks of 1, 2, 4, 8, etc.
|
|
// Chunks are the size of the left or right hand in merge sort.
|
|
// Stop when the left-hand covers all of the array.
|
|
var buffer = new Array(len);
|
|
|
|
for (var chk = 1; chk < len; chk *= 2)
|
|
{
|
|
RunPass(array, compare, chk, buffer);
|
|
|
|
var tmp = array;
|
|
|
|
array = buffer;
|
|
|
|
buffer = tmp;
|
|
}
|
|
|
|
return array;
|
|
}
|
|
|
|
/**
|
|
* Run a single pass with the given chunk size.
|
|
*
|
|
* @ignore
|
|
*
|
|
* @param {array} arr - The array to run the pass on.
|
|
* @param {function} comp - The comparison function.
|
|
* @param {number} chk - The number of iterations.
|
|
* @param {array} result - The array to store the result in.
|
|
*/
|
|
function RunPass (arr, comp, chk, result)
|
|
{
|
|
var len = arr.length;
|
|
var i = 0;
|
|
|
|
// Step size / double chunk size.
|
|
var dbl = chk * 2;
|
|
|
|
// Bounds of the left and right chunks.
|
|
var l, r, e;
|
|
|
|
// Iterators over the left and right chunk.
|
|
var li, ri;
|
|
|
|
// Iterate over pairs of chunks.
|
|
for (l = 0; l < len; l += dbl)
|
|
{
|
|
r = l + chk;
|
|
e = r + chk;
|
|
|
|
if (r > len)
|
|
{
|
|
r = len;
|
|
}
|
|
|
|
if (e > len)
|
|
{
|
|
e = len;
|
|
}
|
|
|
|
// Iterate both chunks in parallel.
|
|
li = l;
|
|
ri = r;
|
|
|
|
while (true)
|
|
{
|
|
// Compare the chunks.
|
|
if (li < r && ri < e)
|
|
{
|
|
// This works for a regular `sort()` compatible comparator,
|
|
// but also for a simple comparator like: `a > b`
|
|
if (comp(arr[li], arr[ri]) <= 0)
|
|
{
|
|
result[i++] = arr[li++];
|
|
}
|
|
else
|
|
{
|
|
result[i++] = arr[ri++];
|
|
}
|
|
}
|
|
else if (li < r)
|
|
{
|
|
// Nothing to compare, just flush what's left.
|
|
result[i++] = arr[li++];
|
|
}
|
|
else if (ri < e)
|
|
{
|
|
result[i++] = arr[ri++];
|
|
}
|
|
else
|
|
{
|
|
// Both iterators are at the chunk ends.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* An in-place stable array sort, because `Array#sort()` is not guaranteed stable.
|
|
*
|
|
* This is an implementation of merge sort, without recursion.
|
|
*
|
|
* Function based on the Two-Screen/stable sort 0.1.8 from https://github.com/Two-Screen/stable
|
|
*
|
|
* @function Phaser.Utils.Array.StableSort
|
|
* @since 3.0.0
|
|
*
|
|
* @param {array} array - The input array to be sorted.
|
|
* @param {function} [compare] - The comparison function.
|
|
*
|
|
* @return {array} The sorted result.
|
|
*/
|
|
var StableSort = function (array, compare)
|
|
{
|
|
if (compare === undefined) { compare = Compare; }
|
|
|
|
// Short-circuit when there's nothing to sort.
|
|
if (!array || array.length < 2)
|
|
{
|
|
return array;
|
|
}
|
|
|
|
if (Device.features.stableSort)
|
|
{
|
|
return array.sort(compare);
|
|
}
|
|
|
|
var result = Process(array, compare);
|
|
|
|
// This simply copies back if the result isn't in the original array, which happens on an odd number of passes.
|
|
if (result !== array)
|
|
{
|
|
RunPass(result, null, array.length, array);
|
|
}
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = StableSort;
|
|
|
|
|
|
/***/ }),
|
|
/* 301 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// This singleton is instantiated as soon as Phaser loads,
|
|
// before a Phaser.Game instance has even been created.
|
|
// Which means all instances of Phaser Games can share it,
|
|
// without having to re-poll the device all over again
|
|
|
|
/**
|
|
* @namespace Phaser.Device
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
/**
|
|
* @typedef {object} Phaser.DeviceConf
|
|
*
|
|
* @property {Phaser.Device.OS} os - The OS Device functions.
|
|
* @property {Phaser.Device.Browser} browser - The Browser Device functions.
|
|
* @property {Phaser.Device.Features} features - The Features Device functions.
|
|
* @property {Phaser.Device.Input} input - The Input Device functions.
|
|
* @property {Phaser.Device.Audio} audio - The Audio Device functions.
|
|
* @property {Phaser.Device.Video} video - The Video Device functions.
|
|
* @property {Phaser.Device.Fullscreen} fullscreen - The Fullscreen Device functions.
|
|
* @property {Phaser.Device.CanvasFeatures} canvasFeatures - The Canvas Device functions.
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
os: __webpack_require__(28),
|
|
browser: __webpack_require__(18),
|
|
features: __webpack_require__(303),
|
|
input: __webpack_require__(307),
|
|
audio: __webpack_require__(308),
|
|
video: __webpack_require__(309),
|
|
fullscreen: __webpack_require__(310),
|
|
canvasFeatures: __webpack_require__(311)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 302 */
|
|
/***/ (function(module, exports) {
|
|
|
|
// shim for using process in browser
|
|
var process = module.exports = {};
|
|
|
|
// cached from whatever global is present so that test runners that stub it
|
|
// don't break things. But we need to wrap it in a try catch in case it is
|
|
// wrapped in strict mode code which doesn't define any globals. It's inside a
|
|
// function because try/catches deoptimize in certain engines.
|
|
|
|
var cachedSetTimeout;
|
|
var cachedClearTimeout;
|
|
|
|
function defaultSetTimout() {
|
|
throw new Error('setTimeout has not been defined');
|
|
}
|
|
function defaultClearTimeout () {
|
|
throw new Error('clearTimeout has not been defined');
|
|
}
|
|
(function () {
|
|
try {
|
|
if (typeof setTimeout === 'function') {
|
|
cachedSetTimeout = setTimeout;
|
|
} else {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
} catch (e) {
|
|
cachedSetTimeout = defaultSetTimout;
|
|
}
|
|
try {
|
|
if (typeof clearTimeout === 'function') {
|
|
cachedClearTimeout = clearTimeout;
|
|
} else {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} catch (e) {
|
|
cachedClearTimeout = defaultClearTimeout;
|
|
}
|
|
} ())
|
|
function runTimeout(fun) {
|
|
if (cachedSetTimeout === setTimeout) {
|
|
//normal enviroments in sane situations
|
|
return setTimeout(fun, 0);
|
|
}
|
|
// if setTimeout wasn't available but was latter defined
|
|
if ((cachedSetTimeout === defaultSetTimout || !cachedSetTimeout) && setTimeout) {
|
|
cachedSetTimeout = setTimeout;
|
|
return setTimeout(fun, 0);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedSetTimeout(fun, 0);
|
|
} catch(e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedSetTimeout.call(null, fun, 0);
|
|
} catch(e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error
|
|
return cachedSetTimeout.call(this, fun, 0);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
function runClearTimeout(marker) {
|
|
if (cachedClearTimeout === clearTimeout) {
|
|
//normal enviroments in sane situations
|
|
return clearTimeout(marker);
|
|
}
|
|
// if clearTimeout wasn't available but was latter defined
|
|
if ((cachedClearTimeout === defaultClearTimeout || !cachedClearTimeout) && clearTimeout) {
|
|
cachedClearTimeout = clearTimeout;
|
|
return clearTimeout(marker);
|
|
}
|
|
try {
|
|
// when when somebody has screwed with setTimeout but no I.E. maddness
|
|
return cachedClearTimeout(marker);
|
|
} catch (e){
|
|
try {
|
|
// When we are in I.E. but the script has been evaled so I.E. doesn't trust the global object when called normally
|
|
return cachedClearTimeout.call(null, marker);
|
|
} catch (e){
|
|
// same as above but when it's a version of I.E. that must have the global object for 'this', hopfully our context correct otherwise it will throw a global error.
|
|
// Some versions of I.E. have different rules for clearTimeout vs setTimeout
|
|
return cachedClearTimeout.call(this, marker);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
}
|
|
var queue = [];
|
|
var draining = false;
|
|
var currentQueue;
|
|
var queueIndex = -1;
|
|
|
|
function cleanUpNextTick() {
|
|
if (!draining || !currentQueue) {
|
|
return;
|
|
}
|
|
draining = false;
|
|
if (currentQueue.length) {
|
|
queue = currentQueue.concat(queue);
|
|
} else {
|
|
queueIndex = -1;
|
|
}
|
|
if (queue.length) {
|
|
drainQueue();
|
|
}
|
|
}
|
|
|
|
function drainQueue() {
|
|
if (draining) {
|
|
return;
|
|
}
|
|
var timeout = runTimeout(cleanUpNextTick);
|
|
draining = true;
|
|
|
|
var len = queue.length;
|
|
while(len) {
|
|
currentQueue = queue;
|
|
queue = [];
|
|
while (++queueIndex < len) {
|
|
if (currentQueue) {
|
|
currentQueue[queueIndex].run();
|
|
}
|
|
}
|
|
queueIndex = -1;
|
|
len = queue.length;
|
|
}
|
|
currentQueue = null;
|
|
draining = false;
|
|
runClearTimeout(timeout);
|
|
}
|
|
|
|
process.nextTick = function (fun) {
|
|
var args = new Array(arguments.length - 1);
|
|
if (arguments.length > 1) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
args[i - 1] = arguments[i];
|
|
}
|
|
}
|
|
queue.push(new Item(fun, args));
|
|
if (queue.length === 1 && !draining) {
|
|
runTimeout(drainQueue);
|
|
}
|
|
};
|
|
|
|
// v8 likes predictible objects
|
|
function Item(fun, array) {
|
|
this.fun = fun;
|
|
this.array = array;
|
|
}
|
|
Item.prototype.run = function () {
|
|
this.fun.apply(null, this.array);
|
|
};
|
|
process.title = 'browser';
|
|
process.browser = true;
|
|
process.env = {};
|
|
process.argv = [];
|
|
process.version = ''; // empty string to avoid regexp issues
|
|
process.versions = {};
|
|
|
|
function noop() {}
|
|
|
|
process.on = noop;
|
|
process.addListener = noop;
|
|
process.once = noop;
|
|
process.off = noop;
|
|
process.removeListener = noop;
|
|
process.removeAllListeners = noop;
|
|
process.emit = noop;
|
|
process.prependListener = noop;
|
|
process.prependOnceListener = noop;
|
|
|
|
process.listeners = function (name) { return [] }
|
|
|
|
process.binding = function (name) {
|
|
throw new Error('process.binding is not supported');
|
|
};
|
|
|
|
process.cwd = function () { return '/' };
|
|
process.chdir = function (dir) {
|
|
throw new Error('process.chdir is not supported');
|
|
};
|
|
process.umask = function() { return 0; };
|
|
|
|
|
|
/***/ }),
|
|
/* 303 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var OS = __webpack_require__(28);
|
|
var Browser = __webpack_require__(18);
|
|
var CanvasPool = __webpack_require__(65);
|
|
|
|
/**
|
|
* Determines the features of the browser running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.features` from within any Scene.
|
|
*
|
|
* @typedef {object} Phaser.Device.Features
|
|
* @since 3.0.0
|
|
*
|
|
* @property {boolean} canvas - Is canvas available?
|
|
* @property {?boolean} canvasBitBltShift - True if canvas supports a 'copy' bitblt onto itself when the source and destination regions overlap.
|
|
* @property {boolean} file - Is file available?
|
|
* @property {boolean} fileSystem - Is fileSystem available?
|
|
* @property {boolean} getUserMedia - Does the device support the getUserMedia API?
|
|
* @property {boolean} littleEndian - Is the device big or little endian? (only detected if the browser supports TypedArrays)
|
|
* @property {boolean} localStorage - Is localStorage available?
|
|
* @property {boolean} pointerLock - Is Pointer Lock available?
|
|
* @property {boolean} stableSort - Is Array.sort stable?
|
|
* @property {boolean} support32bit - Does the device context support 32bit pixel manipulation using array buffer views?
|
|
* @property {boolean} vibration - Does the device support the Vibration API?
|
|
* @property {boolean} webGL - Is webGL available?
|
|
* @property {boolean} worker - Is worker available?
|
|
*/
|
|
var Features = {
|
|
|
|
canvas: false,
|
|
canvasBitBltShift: null,
|
|
file: false,
|
|
fileSystem: false,
|
|
getUserMedia: true,
|
|
littleEndian: false,
|
|
localStorage: false,
|
|
pointerLock: false,
|
|
stableSort: false,
|
|
support32bit: false,
|
|
vibration: false,
|
|
webGL: false,
|
|
worker: false
|
|
|
|
};
|
|
|
|
// Check Little or Big Endian system.
|
|
// @author Matt DesLauriers (@mattdesl)
|
|
function checkIsLittleEndian ()
|
|
{
|
|
var a = new ArrayBuffer(4);
|
|
var b = new Uint8Array(a);
|
|
var c = new Uint32Array(a);
|
|
|
|
b[0] = 0xa1;
|
|
b[1] = 0xb2;
|
|
b[2] = 0xc3;
|
|
b[3] = 0xd4;
|
|
|
|
if (c[0] === 0xd4c3b2a1)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (c[0] === 0xa1b2c3d4)
|
|
{
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
// Could not determine endianness
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function init ()
|
|
{
|
|
if (typeof importScripts === 'function')
|
|
{
|
|
return Features;
|
|
}
|
|
|
|
Features.canvas = !!window['CanvasRenderingContext2D'];
|
|
|
|
try
|
|
{
|
|
Features.localStorage = !!localStorage.getItem;
|
|
}
|
|
catch (error)
|
|
{
|
|
Features.localStorage = false;
|
|
}
|
|
|
|
Features.file = !!window['File'] && !!window['FileReader'] && !!window['FileList'] && !!window['Blob'];
|
|
Features.fileSystem = !!window['requestFileSystem'];
|
|
|
|
var isUint8 = false;
|
|
|
|
var testWebGL = function ()
|
|
{
|
|
if (window['WebGLRenderingContext'])
|
|
{
|
|
try
|
|
{
|
|
var canvas = CanvasPool.createWebGL(this);
|
|
|
|
var ctx = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
|
|
|
var canvas2D = CanvasPool.create2D(this);
|
|
|
|
var ctx2D = canvas2D.getContext('2d', { willReadFrequently: true });
|
|
|
|
// Can't be done on a webgl context
|
|
var image = ctx2D.createImageData(1, 1);
|
|
|
|
// Test to see if ImageData uses CanvasPixelArray or Uint8ClampedArray.
|
|
// @author Matt DesLauriers (@mattdesl)
|
|
isUint8 = image.data instanceof Uint8ClampedArray;
|
|
|
|
CanvasPool.remove(canvas);
|
|
CanvasPool.remove(canvas2D);
|
|
|
|
return !!ctx;
|
|
}
|
|
catch (e)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
|
|
Features.webGL = testWebGL();
|
|
|
|
Features.worker = !!window['Worker'];
|
|
|
|
Features.pointerLock = 'pointerLockElement' in document || 'mozPointerLockElement' in document || 'webkitPointerLockElement' in document;
|
|
|
|
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;
|
|
|
|
window.URL = window.URL || window.webkitURL || window.mozURL || window.msURL;
|
|
|
|
Features.getUserMedia = Features.getUserMedia && !!navigator.getUserMedia && !!window.URL;
|
|
|
|
// Older versions of firefox (< 21) apparently claim support but user media does not actually work
|
|
if (Browser.firefox && Browser.firefoxVersion < 21)
|
|
{
|
|
Features.getUserMedia = false;
|
|
}
|
|
|
|
// Excludes iOS versions as they generally wrap UIWebView (eg. Safari WebKit) and it
|
|
// is safer to not try and use the fast copy-over method.
|
|
if (!OS.iOS && (Browser.ie || Browser.firefox || Browser.chrome))
|
|
{
|
|
Features.canvasBitBltShift = true;
|
|
}
|
|
|
|
// Known not to work
|
|
if (Browser.safari || Browser.mobileSafari)
|
|
{
|
|
Features.canvasBitBltShift = false;
|
|
}
|
|
|
|
navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate || navigator.msVibrate;
|
|
|
|
if (navigator.vibrate)
|
|
{
|
|
Features.vibration = true;
|
|
}
|
|
|
|
if (typeof ArrayBuffer !== 'undefined' && typeof Uint8Array !== 'undefined' && typeof Uint32Array !== 'undefined')
|
|
{
|
|
Features.littleEndian = checkIsLittleEndian();
|
|
}
|
|
|
|
Features.support32bit = (
|
|
typeof ArrayBuffer !== 'undefined' &&
|
|
typeof Uint8ClampedArray !== 'undefined' &&
|
|
typeof Int32Array !== 'undefined' &&
|
|
Features.littleEndian !== null &&
|
|
isUint8
|
|
);
|
|
|
|
return Features;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
|
|
/***/ }),
|
|
/* 304 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Global constants.
|
|
*
|
|
* @ignore
|
|
*/
|
|
|
|
var CONST = {
|
|
|
|
/**
|
|
* Phaser Release Version
|
|
*
|
|
* @name Phaser.VERSION
|
|
* @const
|
|
* @type {string}
|
|
* @since 3.0.0
|
|
*/
|
|
VERSION: '3.60.0-beta.18',
|
|
|
|
BlendModes: __webpack_require__(15),
|
|
|
|
ScaleModes: __webpack_require__(305),
|
|
|
|
/**
|
|
* This setting will auto-detect if the browser is capable of suppporting WebGL.
|
|
* If it is, it will use the WebGL Renderer. If not, it will fall back to the Canvas Renderer.
|
|
*
|
|
* @name Phaser.AUTO
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
AUTO: 0,
|
|
|
|
/**
|
|
* Forces Phaser to only use the Canvas Renderer, regardless if the browser supports
|
|
* WebGL or not.
|
|
*
|
|
* @name Phaser.CANVAS
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
CANVAS: 1,
|
|
|
|
/**
|
|
* Forces Phaser to use the WebGL Renderer. If the browser does not support it, there is
|
|
* no fallback to Canvas with this setting, so you should trap it and display a suitable
|
|
* message to the user.
|
|
*
|
|
* @name Phaser.WEBGL
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
WEBGL: 2,
|
|
|
|
/**
|
|
* A Headless Renderer doesn't create either a Canvas or WebGL Renderer. However, it still
|
|
* absolutely relies on the DOM being present and available. This mode is meant for unit testing,
|
|
* not for running Phaser on the server, which is something you really shouldn't do.
|
|
*
|
|
* @name Phaser.HEADLESS
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
HEADLESS: 3,
|
|
|
|
/**
|
|
* In Phaser the value -1 means 'forever' in lots of cases, this const allows you to use it instead
|
|
* to help you remember what the value is doing in your code.
|
|
*
|
|
* @name Phaser.FOREVER
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
FOREVER: -1,
|
|
|
|
/**
|
|
* Direction constant.
|
|
*
|
|
* @name Phaser.NONE
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
NONE: 4,
|
|
|
|
/**
|
|
* Direction constant.
|
|
*
|
|
* @name Phaser.UP
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
UP: 5,
|
|
|
|
/**
|
|
* Direction constant.
|
|
*
|
|
* @name Phaser.DOWN
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
DOWN: 6,
|
|
|
|
/**
|
|
* Direction constant.
|
|
*
|
|
* @name Phaser.LEFT
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
LEFT: 7,
|
|
|
|
/**
|
|
* Direction constant.
|
|
*
|
|
* @name Phaser.RIGHT
|
|
* @const
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
RIGHT: 8
|
|
|
|
};
|
|
|
|
module.exports = CONST;
|
|
|
|
|
|
/***/ }),
|
|
/* 305 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Phaser Scale Modes.
|
|
*
|
|
* @namespace Phaser.ScaleModes
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var ScaleModes = {
|
|
|
|
/**
|
|
* Default Scale Mode (Linear).
|
|
*
|
|
* @name Phaser.ScaleModes.DEFAULT
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
DEFAULT: 0,
|
|
|
|
/**
|
|
* Linear Scale Mode.
|
|
*
|
|
* @name Phaser.ScaleModes.LINEAR
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
LINEAR: 0,
|
|
|
|
/**
|
|
* Nearest Scale Mode.
|
|
*
|
|
* @name Phaser.ScaleModes.NEAREST
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.0.0
|
|
*/
|
|
NEAREST: 1
|
|
|
|
};
|
|
|
|
module.exports = ScaleModes;
|
|
|
|
|
|
/***/ }),
|
|
/* 306 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Browser specific prefix, so not going to change between contexts, only between browsers
|
|
var prefix = '';
|
|
|
|
/**
|
|
* @namespace Phaser.Display.Canvas.Smoothing
|
|
* @since 3.0.0
|
|
*/
|
|
var Smoothing = function ()
|
|
{
|
|
/**
|
|
* Gets the Smoothing Enabled vendor prefix being used on the given context, or null if not set.
|
|
*
|
|
* @function Phaser.Display.Canvas.Smoothing.getPrefix
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The canvas context to check.
|
|
*
|
|
* @return {string} The name of the property on the context which controls image smoothing (either `imageSmoothingEnabled` or a vendor-prefixed version thereof), or `null` if not supported.
|
|
*/
|
|
var getPrefix = function (context)
|
|
{
|
|
var vendors = [ 'i', 'webkitI', 'msI', 'mozI', 'oI' ];
|
|
|
|
for (var i = 0; i < vendors.length; i++)
|
|
{
|
|
var s = vendors[i] + 'mageSmoothingEnabled';
|
|
|
|
if (s in context)
|
|
{
|
|
return s;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
};
|
|
|
|
/**
|
|
* Sets the Image Smoothing property on the given context. Set to false to disable image smoothing.
|
|
* By default browsers have image smoothing enabled, which isn't always what you visually want, especially
|
|
* when using pixel art in a game. Note that this sets the property on the context itself, so that any image
|
|
* drawn to the context will be affected. This sets the property across all current browsers but support is
|
|
* patchy on earlier browsers, especially on mobile.
|
|
*
|
|
* @function Phaser.Display.Canvas.Smoothing.enable
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The context on which to enable smoothing.
|
|
*
|
|
* @return {(CanvasRenderingContext2D|WebGLRenderingContext)} The provided context.
|
|
*/
|
|
var enable = function (context)
|
|
{
|
|
if (prefix === '')
|
|
{
|
|
prefix = getPrefix(context);
|
|
}
|
|
|
|
if (prefix)
|
|
{
|
|
context[prefix] = true;
|
|
}
|
|
|
|
return context;
|
|
};
|
|
|
|
/**
|
|
* Sets the Image Smoothing property on the given context. Set to false to disable image smoothing.
|
|
* By default browsers have image smoothing enabled, which isn't always what you visually want, especially
|
|
* when using pixel art in a game. Note that this sets the property on the context itself, so that any image
|
|
* drawn to the context will be affected. This sets the property across all current browsers but support is
|
|
* patchy on earlier browsers, especially on mobile.
|
|
*
|
|
* @function Phaser.Display.Canvas.Smoothing.disable
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The context on which to disable smoothing.
|
|
*
|
|
* @return {(CanvasRenderingContext2D|WebGLRenderingContext)} The provided context.
|
|
*/
|
|
var disable = function (context)
|
|
{
|
|
if (prefix === '')
|
|
{
|
|
prefix = getPrefix(context);
|
|
}
|
|
|
|
if (prefix)
|
|
{
|
|
context[prefix] = false;
|
|
}
|
|
|
|
return context;
|
|
};
|
|
|
|
/**
|
|
* Returns `true` if the given context has image smoothing enabled, otherwise returns `false`.
|
|
* Returns null if no smoothing prefix is available.
|
|
*
|
|
* @function Phaser.Display.Canvas.Smoothing.isEnabled
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(CanvasRenderingContext2D|WebGLRenderingContext)} context - The context to check.
|
|
*
|
|
* @return {?boolean} `true` if smoothing is enabled on the context, otherwise `false`. `null` if not supported.
|
|
*/
|
|
var isEnabled = function (context)
|
|
{
|
|
return (prefix !== null) ? context[prefix] : null;
|
|
};
|
|
|
|
return {
|
|
disable: disable,
|
|
enable: enable,
|
|
getPrefix: getPrefix,
|
|
isEnabled: isEnabled
|
|
};
|
|
|
|
};
|
|
|
|
module.exports = Smoothing();
|
|
|
|
|
|
/***/ }),
|
|
/* 307 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Browser = __webpack_require__(18);
|
|
|
|
/**
|
|
* Determines the input support of the browser running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.input` from within any Scene.
|
|
*
|
|
* @typedef {object} Phaser.Device.Input
|
|
* @since 3.0.0
|
|
*
|
|
* @property {?string} wheelType - The newest type of Wheel/Scroll event supported: 'wheel', 'mousewheel', 'DOMMouseScroll'
|
|
* @property {boolean} gamepads - Is navigator.getGamepads available?
|
|
* @property {boolean} mspointer - Is mspointer available?
|
|
* @property {boolean} touch - Is touch available?
|
|
*/
|
|
var Input = {
|
|
|
|
gamepads: false,
|
|
mspointer: false,
|
|
touch: false,
|
|
wheelEvent: null
|
|
|
|
};
|
|
|
|
function init ()
|
|
{
|
|
if (typeof importScripts === 'function')
|
|
{
|
|
return Input;
|
|
}
|
|
|
|
if ('ontouchstart' in document.documentElement || (navigator.maxTouchPoints && navigator.maxTouchPoints >= 1))
|
|
{
|
|
Input.touch = true;
|
|
}
|
|
|
|
if (navigator.msPointerEnabled || navigator.pointerEnabled)
|
|
{
|
|
Input.mspointer = true;
|
|
}
|
|
|
|
if (navigator.getGamepads)
|
|
{
|
|
Input.gamepads = true;
|
|
}
|
|
|
|
// See https://developer.mozilla.org/en-US/docs/Web/Events/wheel
|
|
if ('onwheel' in window || (Browser.ie && 'WheelEvent' in window))
|
|
{
|
|
// DOM3 Wheel Event: FF 17+, IE 9+, Chrome 31+, Safari 7+
|
|
Input.wheelEvent = 'wheel';
|
|
}
|
|
else if ('onmousewheel' in window)
|
|
{
|
|
// Non-FF legacy: IE 6-9, Chrome 1-31, Safari 5-7.
|
|
Input.wheelEvent = 'mousewheel';
|
|
}
|
|
else if (Browser.firefox && 'MouseScrollEvent' in window)
|
|
{
|
|
// FF prior to 17. This should probably be scrubbed.
|
|
Input.wheelEvent = 'DOMMouseScroll';
|
|
}
|
|
|
|
return Input;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
|
|
/***/ }),
|
|
/* 308 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Browser = __webpack_require__(18);
|
|
|
|
/**
|
|
* Determines the audio playback capabilities of the device running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.audio` from within any Scene.
|
|
*
|
|
* @typedef {object} Phaser.Device.Audio
|
|
* @since 3.0.0
|
|
*
|
|
* @property {boolean} audioData - Can this device play HTML Audio tags?
|
|
* @property {boolean} dolby - Can this device play EC-3 Dolby Digital Plus files?
|
|
* @property {boolean} m4a - Can this device can play m4a files.
|
|
* @property {boolean} aac - Can this device can play aac files.
|
|
* @property {boolean} flac - Can this device can play flac files.
|
|
* @property {boolean} mp3 - Can this device play mp3 files?
|
|
* @property {boolean} ogg - Can this device play ogg files?
|
|
* @property {boolean} opus - Can this device play opus files?
|
|
* @property {boolean} wav - Can this device play wav files?
|
|
* @property {boolean} webAudio - Does this device have the Web Audio API?
|
|
* @property {boolean} webm - Can this device play webm files?
|
|
*/
|
|
var Audio = {
|
|
|
|
flac: false,
|
|
aac: false,
|
|
audioData: false,
|
|
dolby: false,
|
|
m4a: false,
|
|
mp3: false,
|
|
ogg: false,
|
|
opus: false,
|
|
wav: false,
|
|
webAudio: false,
|
|
webm: false
|
|
|
|
};
|
|
|
|
function init ()
|
|
{
|
|
if (typeof importScripts === 'function')
|
|
{
|
|
return Audio;
|
|
}
|
|
|
|
Audio.audioData = !!(window['Audio']);
|
|
|
|
Audio.webAudio = !!(window['AudioContext'] || window['webkitAudioContext']);
|
|
|
|
var audioElement = document.createElement('audio');
|
|
var result = !!audioElement.canPlayType;
|
|
|
|
try
|
|
{
|
|
if (result)
|
|
{
|
|
var CanPlay = function (type1, type2)
|
|
{
|
|
var canPlayType1 = audioElement.canPlayType('audio/' + type1).replace(/^no$/, '');
|
|
|
|
if (type2)
|
|
{
|
|
return Boolean(canPlayType1 || audioElement.canPlayType('audio/' + type2).replace(/^no$/, ''));
|
|
}
|
|
else
|
|
{
|
|
return Boolean(canPlayType1);
|
|
}
|
|
};
|
|
|
|
// wav Mimetypes accepted:
|
|
// developer.mozilla.org/En/Media_formats_supported_by_the_audio_and_video_elements
|
|
|
|
Audio.ogg = CanPlay('ogg; codecs="vorbis"');
|
|
Audio.opus = CanPlay('ogg; codecs="opus"', 'opus');
|
|
Audio.mp3 = CanPlay('mpeg');
|
|
Audio.wav = CanPlay('wav');
|
|
Audio.m4a = CanPlay('x-m4a');
|
|
Audio.aac = CanPlay('aac');
|
|
Audio.flac = CanPlay('flac', 'x-flac');
|
|
Audio.webm = CanPlay('webm; codecs="vorbis"');
|
|
|
|
if (audioElement.canPlayType('audio/mp4; codecs="ec-3"') !== '')
|
|
{
|
|
if (Browser.edge)
|
|
{
|
|
Audio.dolby = true;
|
|
}
|
|
else if (Browser.safari && Browser.safariVersion >= 9)
|
|
{
|
|
if ((/Mac OS X (\d+)_(\d+)/).test(navigator.userAgent))
|
|
{
|
|
var major = parseInt(RegExp.$1, 10);
|
|
var minor = parseInt(RegExp.$2, 10);
|
|
|
|
if ((major === 10 && minor >= 11) || major > 10)
|
|
{
|
|
Audio.dolby = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
// Nothing to do here
|
|
}
|
|
|
|
return Audio;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
|
|
/***/ }),
|
|
/* 309 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Determines the video support of the browser running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.video` from within any Scene.
|
|
*
|
|
* In Phaser 3.20 the properties were renamed to drop the 'Video' suffix.
|
|
*
|
|
* @typedef {object} Phaser.Device.Video
|
|
* @since 3.0.0
|
|
*
|
|
* @property {boolean} h264 - Can this device play h264 mp4 video files?
|
|
* @property {boolean} hls - Can this device play hls video files?
|
|
* @property {boolean} mp4 - Can this device play h264 mp4 video files?
|
|
* @property {boolean} m4v - Can this device play m4v (typically mp4) video files?
|
|
* @property {boolean} ogg - Can this device play ogg video files?
|
|
* @property {boolean} vp9 - Can this device play vp9 video files?
|
|
* @property {boolean} webm - Can this device play webm video files?
|
|
*/
|
|
var Video = {
|
|
|
|
h264: false,
|
|
hls: false,
|
|
mp4: false,
|
|
m4v: false,
|
|
ogg: false,
|
|
vp9: false,
|
|
webm: false
|
|
|
|
};
|
|
|
|
function init ()
|
|
{
|
|
if (typeof importScripts === 'function')
|
|
{
|
|
return Video;
|
|
}
|
|
|
|
var videoElement = document.createElement('video');
|
|
var result = !!videoElement.canPlayType;
|
|
var no = /^no$/;
|
|
|
|
try
|
|
{
|
|
if (result)
|
|
{
|
|
if (videoElement.canPlayType('video/ogg; codecs="theora"').replace(no, ''))
|
|
{
|
|
Video.ogg = true;
|
|
}
|
|
|
|
if (videoElement.canPlayType('video/mp4; codecs="avc1.42E01E"').replace(no, ''))
|
|
{
|
|
// Without QuickTime, this value will be `undefined`. github.com/Modernizr/Modernizr/issues/546
|
|
Video.h264 = true;
|
|
Video.mp4 = true;
|
|
}
|
|
|
|
if (videoElement.canPlayType('video/x-m4v').replace(no, ''))
|
|
{
|
|
Video.m4v = true;
|
|
}
|
|
|
|
if (videoElement.canPlayType('video/webm; codecs="vp8, vorbis"').replace(no, ''))
|
|
{
|
|
Video.webm = true;
|
|
}
|
|
|
|
if (videoElement.canPlayType('video/webm; codecs="vp9"').replace(no, ''))
|
|
{
|
|
Video.vp9 = true;
|
|
}
|
|
|
|
if (videoElement.canPlayType('application/x-mpegURL; codecs="avc1.42E01E"').replace(no, ''))
|
|
{
|
|
Video.hls = true;
|
|
}
|
|
}
|
|
}
|
|
catch (e)
|
|
{
|
|
// Nothing to do
|
|
}
|
|
|
|
return Video;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
|
|
/***/ }),
|
|
/* 310 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Determines the full screen support of the browser running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.fullscreen` from within any Scene.
|
|
*
|
|
* @typedef {object} Phaser.Device.Fullscreen
|
|
* @since 3.0.0
|
|
*
|
|
* @property {boolean} available - Does the browser support the Full Screen API?
|
|
* @property {boolean} keyboard - Does the browser support access to the Keyboard during Full Screen mode?
|
|
* @property {string} cancel - If the browser supports the Full Screen API this holds the call you need to use to cancel it.
|
|
* @property {string} request - If the browser supports the Full Screen API this holds the call you need to use to activate it.
|
|
*/
|
|
var Fullscreen = {
|
|
|
|
available: false,
|
|
cancel: '',
|
|
keyboard: false,
|
|
request: ''
|
|
|
|
};
|
|
|
|
/**
|
|
* Checks for support of the Full Screen API.
|
|
*
|
|
* @ignore
|
|
*/
|
|
function init ()
|
|
{
|
|
if (typeof importScripts === 'function')
|
|
{
|
|
return Fullscreen;
|
|
}
|
|
|
|
var i;
|
|
|
|
var suffix1 = 'Fullscreen';
|
|
var suffix2 = 'FullScreen';
|
|
|
|
var fs = [
|
|
'request' + suffix1,
|
|
'request' + suffix2,
|
|
'webkitRequest' + suffix1,
|
|
'webkitRequest' + suffix2,
|
|
'msRequest' + suffix1,
|
|
'msRequest' + suffix2,
|
|
'mozRequest' + suffix2,
|
|
'mozRequest' + suffix1
|
|
];
|
|
|
|
for (i = 0; i < fs.length; i++)
|
|
{
|
|
if (document.documentElement[fs[i]])
|
|
{
|
|
Fullscreen.available = true;
|
|
Fullscreen.request = fs[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
var cfs = [
|
|
'cancel' + suffix2,
|
|
'exit' + suffix1,
|
|
'webkitCancel' + suffix2,
|
|
'webkitExit' + suffix1,
|
|
'msCancel' + suffix2,
|
|
'msExit' + suffix1,
|
|
'mozCancel' + suffix2,
|
|
'mozExit' + suffix1
|
|
];
|
|
|
|
if (Fullscreen.available)
|
|
{
|
|
for (i = 0; i < cfs.length; i++)
|
|
{
|
|
if (document[cfs[i]])
|
|
{
|
|
Fullscreen.cancel = cfs[i];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Keyboard Input?
|
|
// Safari 5.1 says it supports fullscreen keyboard, but is lying.
|
|
if (window['Element'] && Element['ALLOW_KEYBOARD_INPUT'] && !(/ Version\/5\.1(?:\.\d+)? Safari\//).test(navigator.userAgent))
|
|
{
|
|
Fullscreen.keyboard = true;
|
|
}
|
|
|
|
Object.defineProperty(Fullscreen, 'active', { get: function () { return !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement); } });
|
|
|
|
return Fullscreen;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
|
|
/***/ }),
|
|
/* 311 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var CanvasPool = __webpack_require__(65);
|
|
|
|
/**
|
|
* Determines the canvas features of the browser running this Phaser Game instance.
|
|
* These values are read-only and populated during the boot sequence of the game.
|
|
* They are then referenced by internal game systems and are available for you to access
|
|
* via `this.sys.game.device.canvasFeatures` from within any Scene.
|
|
*
|
|
* @typedef {object} Phaser.Device.CanvasFeatures
|
|
* @since 3.0.0
|
|
*
|
|
* @property {boolean} supportInverseAlpha - Set to true if the browser supports inversed alpha.
|
|
* @property {boolean} supportNewBlendModes - Set to true if the browser supports new canvas blend modes.
|
|
*/
|
|
var CanvasFeatures = {
|
|
|
|
supportInverseAlpha: false,
|
|
supportNewBlendModes: false
|
|
|
|
};
|
|
|
|
function checkBlendMode ()
|
|
{
|
|
var pngHead = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAQAAAABAQMAAADD8p2OAAAAA1BMVEX/';
|
|
var pngEnd = 'AAAACklEQVQI12NgAAAAAgAB4iG8MwAAAABJRU5ErkJggg==';
|
|
|
|
var magenta = new Image();
|
|
|
|
magenta.onload = function ()
|
|
{
|
|
var yellow = new Image();
|
|
|
|
yellow.onload = function ()
|
|
{
|
|
var canvas = CanvasPool.create2D(yellow, 6);
|
|
var context = canvas.getContext('2d', { willReadFrequently: true });
|
|
|
|
context.globalCompositeOperation = 'multiply';
|
|
|
|
context.drawImage(magenta, 0, 0);
|
|
context.drawImage(yellow, 2, 0);
|
|
|
|
if (!context.getImageData(2, 0, 1, 1))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var data = context.getImageData(2, 0, 1, 1).data;
|
|
|
|
CanvasPool.remove(yellow);
|
|
|
|
CanvasFeatures.supportNewBlendModes = (data[0] === 255 && data[1] === 0 && data[2] === 0);
|
|
};
|
|
|
|
yellow.src = pngHead + '/wCKxvRF' + pngEnd;
|
|
};
|
|
|
|
magenta.src = pngHead + 'AP804Oa6' + pngEnd;
|
|
|
|
return false;
|
|
}
|
|
|
|
function checkInverseAlpha ()
|
|
{
|
|
var canvas = CanvasPool.create2D(this, 2);
|
|
var context = canvas.getContext('2d', { willReadFrequently: true });
|
|
|
|
context.fillStyle = 'rgba(10, 20, 30, 0.5)';
|
|
|
|
// Draw a single pixel
|
|
context.fillRect(0, 0, 1, 1);
|
|
|
|
// Get the color values
|
|
var s1 = context.getImageData(0, 0, 1, 1);
|
|
|
|
if (s1 === null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Plot them to x2
|
|
context.putImageData(s1, 1, 0);
|
|
|
|
// Get those values
|
|
var s2 = context.getImageData(1, 0, 1, 1);
|
|
|
|
var result = (s2.data[0] === s1.data[0] && s2.data[1] === s1.data[1] && s2.data[2] === s1.data[2] && s2.data[3] === s1.data[3]);
|
|
|
|
CanvasPool.remove(this);
|
|
|
|
// Compare and return
|
|
return result;
|
|
}
|
|
|
|
function init ()
|
|
{
|
|
if (typeof importScripts !== 'function' && document !== undefined)
|
|
{
|
|
CanvasFeatures.supportNewBlendModes = checkBlendMode();
|
|
CanvasFeatures.supportInverseAlpha = checkInverseAlpha();
|
|
}
|
|
|
|
return CanvasFeatures;
|
|
}
|
|
|
|
module.exports = init();
|
|
|
|
|
|
/***/ }),
|
|
/* 312 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Swaps the position of two elements in the given array.
|
|
* The elements must exist in the same array.
|
|
* The array is modified in-place.
|
|
*
|
|
* @function Phaser.Utils.Array.Swap
|
|
* @since 3.4.0
|
|
*
|
|
* @param {array} array - The input array.
|
|
* @param {*} item1 - The first element to swap.
|
|
* @param {*} item2 - The second element to swap.
|
|
*
|
|
* @return {array} The input array.
|
|
*/
|
|
var Swap = function (array, item1, item2)
|
|
{
|
|
if (item1 === item2)
|
|
{
|
|
return array;
|
|
}
|
|
|
|
var index1 = array.indexOf(item1);
|
|
var index2 = array.indexOf(item2);
|
|
|
|
if (index1 < 0 || index2 < 0)
|
|
{
|
|
throw new Error('Supplied items must be elements of the same array');
|
|
}
|
|
|
|
array[index1] = item2;
|
|
array[index2] = item1;
|
|
|
|
return array;
|
|
};
|
|
|
|
module.exports = Swap;
|
|
|
|
|
|
/***/ }),
|
|
/* 313 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* @namespace Phaser.GameObjects.Components
|
|
*/
|
|
|
|
module.exports = {
|
|
|
|
Alpha: __webpack_require__(314),
|
|
AlphaSingle: __webpack_require__(315),
|
|
BlendMode: __webpack_require__(316),
|
|
ComputedSize: __webpack_require__(51),
|
|
Crop: __webpack_require__(317),
|
|
Depth: __webpack_require__(52),
|
|
Flip: __webpack_require__(53),
|
|
FX: __webpack_require__(318),
|
|
GetBounds: __webpack_require__(319),
|
|
Mask: __webpack_require__(328),
|
|
Origin: __webpack_require__(333),
|
|
PathFollower: __webpack_require__(334),
|
|
Pipeline: __webpack_require__(337),
|
|
ScrollFactor: __webpack_require__(54),
|
|
Size: __webpack_require__(339),
|
|
Texture: __webpack_require__(340),
|
|
TextureCrop: __webpack_require__(341),
|
|
Tint: __webpack_require__(342),
|
|
ToJSON: __webpack_require__(58),
|
|
Transform: __webpack_require__(55),
|
|
TransformMatrix: __webpack_require__(26),
|
|
Visible: __webpack_require__(56)
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 314 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Clamp = __webpack_require__(1);
|
|
|
|
// bitmask flag for GameObject.renderMask
|
|
var _FLAG = 2; // 0010
|
|
|
|
/**
|
|
* Provides methods used for setting the alpha properties of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Alpha
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Alpha = {
|
|
|
|
/**
|
|
* Private internal value. Holds the global alpha value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#_alpha
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_alpha: 1,
|
|
|
|
/**
|
|
* Private internal value. Holds the top-left alpha value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#_alphaTL
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_alphaTL: 1,
|
|
|
|
/**
|
|
* Private internal value. Holds the top-right alpha value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#_alphaTR
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_alphaTR: 1,
|
|
|
|
/**
|
|
* Private internal value. Holds the bottom-left alpha value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#_alphaBL
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_alphaBL: 1,
|
|
|
|
/**
|
|
* Private internal value. Holds the bottom-right alpha value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#_alphaBR
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_alphaBR: 1,
|
|
|
|
/**
|
|
* Clears all alpha values associated with this Game Object.
|
|
*
|
|
* Immediately sets the alpha levels back to 1 (fully opaque).
|
|
*
|
|
* @method Phaser.GameObjects.Components.Alpha#clearAlpha
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
clearAlpha: function ()
|
|
{
|
|
return this.setAlpha(1);
|
|
},
|
|
|
|
/**
|
|
* Set the Alpha level of this Game Object. The alpha controls the opacity of the Game Object as it renders.
|
|
* Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque.
|
|
*
|
|
* If your game is running under WebGL you can optionally specify four different alpha values, each of which
|
|
* correspond to the four corners of the Game Object. Under Canvas only the `topLeft` value given is used.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Alpha#setAlpha
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [topLeft=1] - The alpha value used for the top-left of the Game Object. If this is the only value given it's applied across the whole Game Object.
|
|
* @param {number} [topRight] - The alpha value used for the top-right of the Game Object. WebGL only.
|
|
* @param {number} [bottomLeft] - The alpha value used for the bottom-left of the Game Object. WebGL only.
|
|
* @param {number} [bottomRight] - The alpha value used for the bottom-right of the Game Object. WebGL only.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setAlpha: function (topLeft, topRight, bottomLeft, bottomRight)
|
|
{
|
|
if (topLeft === undefined) { topLeft = 1; }
|
|
|
|
// Treat as if there is only one alpha value for the whole Game Object
|
|
if (topRight === undefined)
|
|
{
|
|
this.alpha = topLeft;
|
|
}
|
|
else
|
|
{
|
|
this._alphaTL = Clamp(topLeft, 0, 1);
|
|
this._alphaTR = Clamp(topRight, 0, 1);
|
|
this._alphaBL = Clamp(bottomLeft, 0, 1);
|
|
this._alphaBR = Clamp(bottomRight, 0, 1);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* The alpha value of the Game Object.
|
|
*
|
|
* This is a global value, impacting the entire Game Object, not just a region of it.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#alpha
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
alpha: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._alpha;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
this._alpha = v;
|
|
this._alphaTL = v;
|
|
this._alphaTR = v;
|
|
this._alphaBL = v;
|
|
this._alphaBR = v;
|
|
|
|
if (v === 0)
|
|
{
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The alpha value starting from the top-left of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#alphaTopLeft
|
|
* @type {number}
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
alphaTopLeft: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._alphaTL;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
this._alphaTL = v;
|
|
|
|
if (v !== 0)
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The alpha value starting from the top-right of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#alphaTopRight
|
|
* @type {number}
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
alphaTopRight: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._alphaTR;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
this._alphaTR = v;
|
|
|
|
if (v !== 0)
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The alpha value starting from the bottom-left of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#alphaBottomLeft
|
|
* @type {number}
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
alphaBottomLeft: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._alphaBL;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
this._alphaBL = v;
|
|
|
|
if (v !== 0)
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The alpha value starting from the bottom-right of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Alpha#alphaBottomRight
|
|
* @type {number}
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
alphaBottomRight: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._alphaBR;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
this._alphaBR = v;
|
|
|
|
if (v !== 0)
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Alpha;
|
|
|
|
|
|
/***/ }),
|
|
/* 315 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Clamp = __webpack_require__(1);
|
|
|
|
// bitmask flag for GameObject.renderMask
|
|
var _FLAG = 2; // 0010
|
|
|
|
/**
|
|
* Provides methods used for setting the alpha property of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.AlphaSingle
|
|
* @since 3.22.0
|
|
*/
|
|
|
|
var AlphaSingle = {
|
|
|
|
/**
|
|
* Private internal value. Holds the global alpha value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.AlphaSingle#_alpha
|
|
* @type {number}
|
|
* @private
|
|
* @default 1
|
|
* @since 3.0.0
|
|
*/
|
|
_alpha: 1,
|
|
|
|
/**
|
|
* Clears all alpha values associated with this Game Object.
|
|
*
|
|
* Immediately sets the alpha levels back to 1 (fully opaque).
|
|
*
|
|
* @method Phaser.GameObjects.Components.AlphaSingle#clearAlpha
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
clearAlpha: function ()
|
|
{
|
|
return this.setAlpha(1);
|
|
},
|
|
|
|
/**
|
|
* Set the Alpha level of this Game Object. The alpha controls the opacity of the Game Object as it renders.
|
|
* Alpha values are provided as a float between 0, fully transparent, and 1, fully opaque.
|
|
*
|
|
* @method Phaser.GameObjects.Components.AlphaSingle#setAlpha
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [value=1] - The alpha value applied across the whole Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setAlpha: function (value)
|
|
{
|
|
if (value === undefined) { value = 1; }
|
|
|
|
this.alpha = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* The alpha value of the Game Object.
|
|
*
|
|
* This is a global value, impacting the entire Game Object, not just a region of it.
|
|
*
|
|
* @name Phaser.GameObjects.Components.AlphaSingle#alpha
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
alpha: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._alpha;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
var v = Clamp(value, 0, 1);
|
|
|
|
this._alpha = v;
|
|
|
|
if (v === 0)
|
|
{
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = AlphaSingle;
|
|
|
|
|
|
/***/ }),
|
|
/* 316 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var BlendModes = __webpack_require__(15);
|
|
|
|
/**
|
|
* Provides methods used for setting the blend mode of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.BlendMode
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var BlendMode = {
|
|
|
|
/**
|
|
* Private internal value. Holds the current blend mode.
|
|
*
|
|
* @name Phaser.GameObjects.Components.BlendMode#_blendMode
|
|
* @type {number}
|
|
* @private
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
_blendMode: BlendModes.NORMAL,
|
|
|
|
/**
|
|
* Sets the Blend Mode being used by this Game Object.
|
|
*
|
|
* This can be a const, such as `Phaser.BlendModes.SCREEN`, or an integer, such as 4 (for Overlay)
|
|
*
|
|
* Under WebGL only the following Blend Modes are available:
|
|
*
|
|
* * NORMAL
|
|
* * ADD
|
|
* * MULTIPLY
|
|
* * SCREEN
|
|
* * ERASE
|
|
*
|
|
* Canvas has more available depending on browser support.
|
|
*
|
|
* You can also create your own custom Blend Modes in WebGL.
|
|
*
|
|
* Blend modes have different effects under Canvas and WebGL, and from browser to browser, depending
|
|
* on support. Blend Modes also cause a WebGL batch flush should it encounter a new blend mode. For these
|
|
* reasons try to be careful about the construction of your Scene and the frequency of which blend modes
|
|
* are used.
|
|
*
|
|
* @name Phaser.GameObjects.Components.BlendMode#blendMode
|
|
* @type {(Phaser.BlendModes|string|number)}
|
|
* @since 3.0.0
|
|
*/
|
|
blendMode: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._blendMode;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (typeof value === 'string')
|
|
{
|
|
value = BlendModes[value];
|
|
}
|
|
|
|
value |= 0;
|
|
|
|
if (value >= -1)
|
|
{
|
|
this._blendMode = value;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Sets the Blend Mode being used by this Game Object.
|
|
*
|
|
* This can be a const, such as `Phaser.BlendModes.SCREEN`, or an integer, such as 4 (for Overlay)
|
|
*
|
|
* Under WebGL only the following Blend Modes are available:
|
|
*
|
|
* * NORMAL
|
|
* * ADD
|
|
* * MULTIPLY
|
|
* * SCREEN
|
|
* * ERASE (only works when rendering to a framebuffer, like a Render Texture)
|
|
*
|
|
* Canvas has more available depending on browser support.
|
|
*
|
|
* You can also create your own custom Blend Modes in WebGL.
|
|
*
|
|
* Blend modes have different effects under Canvas and WebGL, and from browser to browser, depending
|
|
* on support. Blend Modes also cause a WebGL batch flush should it encounter a new blend mode. For these
|
|
* reasons try to be careful about the construction of your Scene and the frequency in which blend modes
|
|
* are used.
|
|
*
|
|
* @method Phaser.GameObjects.Components.BlendMode#setBlendMode
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|Phaser.BlendModes|number)} value - The BlendMode value. Either a string, a CONST or a number.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setBlendMode: function (value)
|
|
{
|
|
this.blendMode = value;
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = BlendMode;
|
|
|
|
|
|
/***/ }),
|
|
/* 317 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the texture of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Crop
|
|
* @since 3.12.0
|
|
*/
|
|
|
|
var Crop = {
|
|
|
|
/**
|
|
* The Texture this Game Object is using to render with.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Crop#texture
|
|
* @type {Phaser.Textures.Texture|Phaser.Textures.CanvasTexture}
|
|
* @since 3.0.0
|
|
*/
|
|
texture: null,
|
|
|
|
/**
|
|
* The Texture Frame this Game Object is using to render with.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Crop#frame
|
|
* @type {Phaser.Textures.Frame}
|
|
* @since 3.0.0
|
|
*/
|
|
frame: null,
|
|
|
|
/**
|
|
* A boolean flag indicating if this Game Object is being cropped or not.
|
|
* You can toggle this at any time after `setCrop` has been called, to turn cropping on or off.
|
|
* Equally, calling `setCrop` with no arguments will reset the crop and disable it.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Crop#isCropped
|
|
* @type {boolean}
|
|
* @since 3.11.0
|
|
*/
|
|
isCropped: false,
|
|
|
|
/**
|
|
* Applies a crop to a texture based Game Object, such as a Sprite or Image.
|
|
*
|
|
* The crop is a rectangle that limits the area of the texture frame that is visible during rendering.
|
|
*
|
|
* Cropping a Game Object does not change its size, dimensions, physics body or hit area, it just
|
|
* changes what is shown when rendered.
|
|
*
|
|
* The crop coordinates are relative to the texture frame, not the Game Object, meaning 0 x 0 is the top-left.
|
|
*
|
|
* Therefore, if you had a Game Object that had an 800x600 sized texture, and you wanted to show only the left
|
|
* half of it, you could call `setCrop(0, 0, 400, 600)`.
|
|
*
|
|
* It is also scaled to match the Game Object scale automatically. Therefore a crop rect of 100x50 would crop
|
|
* an area of 200x100 when applied to a Game Object that had a scale factor of 2.
|
|
*
|
|
* You can either pass in numeric values directly, or you can provide a single Rectangle object as the first argument.
|
|
*
|
|
* Call this method with no arguments at all to reset the crop, or toggle the property `isCropped` to `false`.
|
|
*
|
|
* You should do this if the crop rectangle becomes the same size as the frame itself, as it will allow
|
|
* the renderer to skip several internal calculations.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Crop#setCrop
|
|
* @since 3.11.0
|
|
*
|
|
* @param {(number|Phaser.Geom.Rectangle)} [x] - The x coordinate to start the crop from. Or a Phaser.Geom.Rectangle object, in which case the rest of the arguments are ignored.
|
|
* @param {number} [y] - The y coordinate to start the crop from.
|
|
* @param {number} [width] - The width of the crop rectangle in pixels.
|
|
* @param {number} [height] - The height of the crop rectangle in pixels.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setCrop: function (x, y, width, height)
|
|
{
|
|
if (x === undefined)
|
|
{
|
|
this.isCropped = false;
|
|
}
|
|
else if (this.frame)
|
|
{
|
|
if (typeof x === 'number')
|
|
{
|
|
this.frame.setCropUVs(this._crop, x, y, width, height, this.flipX, this.flipY);
|
|
}
|
|
else
|
|
{
|
|
var rect = x;
|
|
|
|
this.frame.setCropUVs(this._crop, rect.x, rect.y, rect.width, rect.height, this.flipX, this.flipY);
|
|
}
|
|
|
|
this.isCropped = true;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Internal method that returns a blank, well-formed crop object for use by a Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Crop#resetCropObject
|
|
* @private
|
|
* @since 3.12.0
|
|
*
|
|
* @return {object} The crop object.
|
|
*/
|
|
resetCropObject: function ()
|
|
{
|
|
return { u0: 0, v0: 0, u1: 0, v1: 0, width: 0, height: 0, x: 0, y: 0, flipX: false, flipY: false, cx: 0, cy: 0, cw: 0, ch: 0 };
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Crop;
|
|
|
|
|
|
/***/ }),
|
|
/* 318 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for setting the FX values of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.FX
|
|
* @webglOnly
|
|
* @since 3.60.0
|
|
*/
|
|
|
|
var FX = {
|
|
|
|
/**
|
|
* The amount of extra padding to be applied to this Game Object
|
|
* when it is being rendered by a SpriteFX Pipeline.
|
|
*
|
|
* Lots of FX require additional spacing added to the texture the
|
|
* Game Object uses, for example a glow or shadow effect, and this
|
|
* method allows you to control how much extra padding is included
|
|
* in addition to the texture size.
|
|
*
|
|
* @name Phaser.GameObjects.Components.FX#fxPadding
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.60.0
|
|
*/
|
|
fxPadding: 0,
|
|
|
|
/**
|
|
* Sets the amount of extra padding to be applied to this Game Object
|
|
* when it is being rendered by a SpriteFX Pipeline.
|
|
*
|
|
* Lots of FX require additional spacing added to the texture the
|
|
* Game Object uses, for example a glow or shadow effect, and this
|
|
* method allows you to control how much extra padding is included
|
|
* in addition to the texture size.
|
|
*
|
|
* @method Phaser.GameObjects.Components.FX#setFXPadding
|
|
* @webglOnly
|
|
* @since 3.60.0
|
|
*
|
|
* @param {number} [padding=0] - The amount of padding to add to the texture.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setFXPadding: function (padding)
|
|
{
|
|
if (padding === undefined) { padding = 0; }
|
|
|
|
this.fxPadding = padding;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* This callback is invoked when this Game Object is copied by a SpriteFX Pipeline.
|
|
*
|
|
* This happens when the pipeline uses its `copySprite` method.
|
|
*
|
|
* It's invoked prior to the copy, allowing you to set shader uniforms, etc on the pipeline.
|
|
*
|
|
* @method Phaser.GameObjects.Components.FX#onFXCopy
|
|
* @webglOnly
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.Pipelines.SpriteFXPipeline} pipeline - The SpriteFX Pipeline that invoked this callback.
|
|
*/
|
|
onFXCopy: function ()
|
|
{
|
|
},
|
|
|
|
/**
|
|
* This callback is invoked when this Game Object is rendered by a SpriteFX Pipeline.
|
|
*
|
|
* This happens when the pipeline uses its `drawSprite` method.
|
|
*
|
|
* It's invoked prior to the draw, allowing you to set shader uniforms, etc on the pipeline.
|
|
*
|
|
* @method Phaser.GameObjects.Components.FX#onFX
|
|
* @webglOnly
|
|
* @since 3.60.0
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.Pipelines.SpriteFXPipeline} pipeline - The SpriteFX Pipeline that invoked this callback.
|
|
*/
|
|
onFX: function ()
|
|
{
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = FX;
|
|
|
|
|
|
/***/ }),
|
|
/* 319 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Rectangle = __webpack_require__(29);
|
|
var RotateAround = __webpack_require__(42);
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
/**
|
|
* Provides methods used for obtaining the bounds of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.GetBounds
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var GetBounds = {
|
|
|
|
/**
|
|
* Processes the bounds output vector before returning it.
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#prepareBoundsOutput
|
|
* @private
|
|
* @since 3.18.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} output - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
prepareBoundsOutput: function (output, includeParent)
|
|
{
|
|
if (includeParent === undefined) { includeParent = false; }
|
|
|
|
if (this.rotation !== 0)
|
|
{
|
|
RotateAround(output, this.x, this.y, this.rotation);
|
|
}
|
|
|
|
if (includeParent && this.parentContainer)
|
|
{
|
|
var parentMatrix = this.parentContainer.getBoundsTransformMatrix();
|
|
|
|
parentMatrix.transformPoint(output.x, output.y, output);
|
|
}
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Gets the center coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getCenter
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getCenter: function (output)
|
|
{
|
|
if (output === undefined) { output = new Vector2(); }
|
|
|
|
output.x = this.x - (this.displayWidth * this.originX) + (this.displayWidth / 2);
|
|
output.y = this.y - (this.displayHeight * this.originY) + (this.displayHeight / 2);
|
|
|
|
return output;
|
|
},
|
|
|
|
/**
|
|
* Gets the top-left corner coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getTopLeft
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getTopLeft: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = this.x - (this.displayWidth * this.originX);
|
|
output.y = this.y - (this.displayHeight * this.originY);
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the top-center coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getTopCenter
|
|
* @since 3.18.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getTopCenter: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = (this.x - (this.displayWidth * this.originX)) + (this.displayWidth / 2);
|
|
output.y = this.y - (this.displayHeight * this.originY);
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the top-right corner coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getTopRight
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getTopRight: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = (this.x - (this.displayWidth * this.originX)) + this.displayWidth;
|
|
output.y = this.y - (this.displayHeight * this.originY);
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the left-center coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getLeftCenter
|
|
* @since 3.18.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getLeftCenter: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = this.x - (this.displayWidth * this.originX);
|
|
output.y = (this.y - (this.displayHeight * this.originY)) + (this.displayHeight / 2);
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the right-center coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getRightCenter
|
|
* @since 3.18.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getRightCenter: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = (this.x - (this.displayWidth * this.originX)) + this.displayWidth;
|
|
output.y = (this.y - (this.displayHeight * this.originY)) + (this.displayHeight / 2);
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the bottom-left corner coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getBottomLeft
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getBottomLeft: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = this.x - (this.displayWidth * this.originX);
|
|
output.y = (this.y - (this.displayHeight * this.originY)) + this.displayHeight;
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the bottom-center coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getBottomCenter
|
|
* @since 3.18.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getBottomCenter: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = (this.x - (this.displayWidth * this.originX)) + (this.displayWidth / 2);
|
|
output.y = (this.y - (this.displayHeight * this.originY)) + this.displayHeight;
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the bottom-right corner coordinate of this Game Object, regardless of origin.
|
|
* The returned point is calculated in local space and does not factor in any parent containers
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getBottomRight
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Math.Vector2|object)} [output] - An object to store the values in. If not provided a new Vector2 will be created.
|
|
* @param {boolean} [includeParent=false] - If this Game Object has a parent Container, include it (and all other ancestors) in the resulting vector?
|
|
*
|
|
* @return {(Phaser.Math.Vector2|object)} The values stored in the output object.
|
|
*/
|
|
getBottomRight: function (output, includeParent)
|
|
{
|
|
if (!output) { output = new Vector2(); }
|
|
|
|
output.x = (this.x - (this.displayWidth * this.originX)) + this.displayWidth;
|
|
output.y = (this.y - (this.displayHeight * this.originY)) + this.displayHeight;
|
|
|
|
return this.prepareBoundsOutput(output, includeParent);
|
|
},
|
|
|
|
/**
|
|
* Gets the bounds of this Game Object, regardless of origin.
|
|
* The values are stored and returned in a Rectangle, or Rectangle-like, object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.GetBounds#getBounds
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Rectangle} O - [output,$return]
|
|
*
|
|
* @param {(Phaser.Geom.Rectangle|object)} [output] - An object to store the values in. If not provided a new Rectangle will be created.
|
|
*
|
|
* @return {(Phaser.Geom.Rectangle|object)} The values stored in the output object.
|
|
*/
|
|
getBounds: function (output)
|
|
{
|
|
if (output === undefined) { output = new Rectangle(); }
|
|
|
|
// We can use the output object to temporarily store the x/y coords in:
|
|
|
|
var TLx, TLy, TRx, TRy, BLx, BLy, BRx, BRy;
|
|
|
|
// Instead of doing a check if parent container is
|
|
// defined per corner we only do it once.
|
|
if (this.parentContainer)
|
|
{
|
|
var parentMatrix = this.parentContainer.getBoundsTransformMatrix();
|
|
|
|
this.getTopLeft(output);
|
|
parentMatrix.transformPoint(output.x, output.y, output);
|
|
|
|
TLx = output.x;
|
|
TLy = output.y;
|
|
|
|
this.getTopRight(output);
|
|
parentMatrix.transformPoint(output.x, output.y, output);
|
|
|
|
TRx = output.x;
|
|
TRy = output.y;
|
|
|
|
this.getBottomLeft(output);
|
|
parentMatrix.transformPoint(output.x, output.y, output);
|
|
|
|
BLx = output.x;
|
|
BLy = output.y;
|
|
|
|
this.getBottomRight(output);
|
|
parentMatrix.transformPoint(output.x, output.y, output);
|
|
|
|
BRx = output.x;
|
|
BRy = output.y;
|
|
}
|
|
else
|
|
{
|
|
this.getTopLeft(output);
|
|
|
|
TLx = output.x;
|
|
TLy = output.y;
|
|
|
|
this.getTopRight(output);
|
|
|
|
TRx = output.x;
|
|
TRy = output.y;
|
|
|
|
this.getBottomLeft(output);
|
|
|
|
BLx = output.x;
|
|
BLy = output.y;
|
|
|
|
this.getBottomRight(output);
|
|
|
|
BRx = output.x;
|
|
BRy = output.y;
|
|
}
|
|
|
|
output.x = Math.min(TLx, TRx, BLx, BRx);
|
|
output.y = Math.min(TLy, TRy, BLy, BRy);
|
|
output.width = Math.max(TLx, TRx, BLx, BRx) - output.x;
|
|
output.height = Math.max(TLy, TRy, BLy, BRy) - output.y;
|
|
|
|
return output;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = GetBounds;
|
|
|
|
|
|
/***/ }),
|
|
/* 320 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Checks if a given point is inside a Rectangle's bounds.
|
|
*
|
|
* @function Phaser.Geom.Rectangle.Contains
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Geom.Rectangle} rect - The Rectangle to check.
|
|
* @param {number} x - The X coordinate of the point to check.
|
|
* @param {number} y - The Y coordinate of the point to check.
|
|
*
|
|
* @return {boolean} `true` if the point is within the Rectangle's bounds, otherwise `false`.
|
|
*/
|
|
var Contains = function (rect, x, y)
|
|
{
|
|
if (rect.width <= 0 || rect.height <= 0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return (rect.x <= x && rect.x + rect.width >= x && rect.y <= y && rect.y + rect.height >= y);
|
|
};
|
|
|
|
module.exports = Contains;
|
|
|
|
|
|
/***/ }),
|
|
/* 321 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var GetPoint = __webpack_require__(66);
|
|
var Perimeter = __webpack_require__(67);
|
|
|
|
/**
|
|
* Return an array of points from the perimeter of the rectangle, each spaced out based on the quantity or step required.
|
|
*
|
|
* @function Phaser.Geom.Rectangle.GetPoints
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point[]} O - [out,$return]
|
|
*
|
|
* @param {Phaser.Geom.Rectangle} rectangle - The Rectangle object to get the points from.
|
|
* @param {number} step - Step between points. Used to calculate the number of points to return when quantity is falsey. Ignored if quantity is positive.
|
|
* @param {number} quantity - The number of evenly spaced points from the rectangles perimeter to return. If falsey, step param will be used to calculate the number of points.
|
|
* @param {(array|Phaser.Geom.Point[])} [out] - An optional array to store the points in.
|
|
*
|
|
* @return {(array|Phaser.Geom.Point[])} An array of Points from the perimeter of the rectangle.
|
|
*/
|
|
var GetPoints = function (rectangle, quantity, stepRate, out)
|
|
{
|
|
if (out === undefined) { out = []; }
|
|
|
|
// If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead.
|
|
if (!quantity && stepRate > 0)
|
|
{
|
|
quantity = Perimeter(rectangle) / stepRate;
|
|
}
|
|
|
|
for (var i = 0; i < quantity; i++)
|
|
{
|
|
var position = i / quantity;
|
|
|
|
out.push(GetPoint(rectangle, position));
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = GetPoints;
|
|
|
|
|
|
/***/ }),
|
|
/* 322 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var GetPoint = __webpack_require__(323);
|
|
var GetPoints = __webpack_require__(324);
|
|
var GEOM_CONST = __webpack_require__(30);
|
|
var Random = __webpack_require__(326);
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
/**
|
|
* @classdesc
|
|
* Defines a Line segment, a part of a line between two endpoints.
|
|
*
|
|
* @class Line
|
|
* @memberof Phaser.Geom
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x1=0] - The x coordinate of the lines starting point.
|
|
* @param {number} [y1=0] - The y coordinate of the lines starting point.
|
|
* @param {number} [x2=0] - The x coordinate of the lines ending point.
|
|
* @param {number} [y2=0] - The y coordinate of the lines ending point.
|
|
*/
|
|
var Line = new Class({
|
|
|
|
initialize:
|
|
|
|
function Line (x1, y1, x2, y2)
|
|
{
|
|
if (x1 === undefined) { x1 = 0; }
|
|
if (y1 === undefined) { y1 = 0; }
|
|
if (x2 === undefined) { x2 = 0; }
|
|
if (y2 === undefined) { y2 = 0; }
|
|
|
|
/**
|
|
* The geometry constant type of this object: `GEOM_CONST.LINE`.
|
|
* Used for fast type comparisons.
|
|
*
|
|
* @name Phaser.Geom.Line#type
|
|
* @type {number}
|
|
* @readonly
|
|
* @since 3.19.0
|
|
*/
|
|
this.type = GEOM_CONST.LINE;
|
|
|
|
/**
|
|
* The x coordinate of the lines starting point.
|
|
*
|
|
* @name Phaser.Geom.Line#x1
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.x1 = x1;
|
|
|
|
/**
|
|
* The y coordinate of the lines starting point.
|
|
*
|
|
* @name Phaser.Geom.Line#y1
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.y1 = y1;
|
|
|
|
/**
|
|
* The x coordinate of the lines ending point.
|
|
*
|
|
* @name Phaser.Geom.Line#x2
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.x2 = x2;
|
|
|
|
/**
|
|
* The y coordinate of the lines ending point.
|
|
*
|
|
* @name Phaser.Geom.Line#y2
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
this.y2 = y2;
|
|
},
|
|
|
|
/**
|
|
* Get a point on a line that's a given percentage along its length.
|
|
*
|
|
* @method Phaser.Geom.Line#getPoint
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [output,$return]
|
|
*
|
|
* @param {number} position - A value between 0 and 1, where 0 is the start, 0.5 is the middle and 1 is the end of the line.
|
|
* @param {(Phaser.Geom.Point|object)} [output] - An optional point, or point-like object, to store the coordinates of the point on the line.
|
|
*
|
|
* @return {(Phaser.Geom.Point|object)} A Point, or point-like object, containing the coordinates of the point on the line.
|
|
*/
|
|
getPoint: function (position, output)
|
|
{
|
|
return GetPoint(this, position, output);
|
|
},
|
|
|
|
/**
|
|
* Get a number of points along a line's length.
|
|
*
|
|
* Provide a `quantity` to get an exact number of points along the line.
|
|
*
|
|
* Provide a `stepRate` to ensure a specific distance between each point on the line. Set `quantity` to `0` when
|
|
* providing a `stepRate`.
|
|
*
|
|
* @method Phaser.Geom.Line#getPoints
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point[]} O - [output,$return]
|
|
*
|
|
* @param {number} quantity - The number of points to place on the line. Set to `0` to use `stepRate` instead.
|
|
* @param {number} [stepRate] - The distance between each point on the line. When set, `quantity` is implied and should be set to `0`.
|
|
* @param {(array|Phaser.Geom.Point[])} [output] - An optional array of Points, or point-like objects, to store the coordinates of the points on the line.
|
|
*
|
|
* @return {(array|Phaser.Geom.Point[])} An array of Points, or point-like objects, containing the coordinates of the points on the line.
|
|
*/
|
|
getPoints: function (quantity, stepRate, output)
|
|
{
|
|
return GetPoints(this, quantity, stepRate, output);
|
|
},
|
|
|
|
/**
|
|
* Get a random Point on the Line.
|
|
*
|
|
* @method Phaser.Geom.Line#getRandomPoint
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [point,$return]
|
|
*
|
|
* @param {(Phaser.Geom.Point|object)} [point] - An instance of a Point to be modified.
|
|
*
|
|
* @return {Phaser.Geom.Point} A random Point on the Line.
|
|
*/
|
|
getRandomPoint: function (point)
|
|
{
|
|
return Random(this, point);
|
|
},
|
|
|
|
/**
|
|
* Set new coordinates for the line endpoints.
|
|
*
|
|
* @method Phaser.Geom.Line#setTo
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x1=0] - The x coordinate of the lines starting point.
|
|
* @param {number} [y1=0] - The y coordinate of the lines starting point.
|
|
* @param {number} [x2=0] - The x coordinate of the lines ending point.
|
|
* @param {number} [y2=0] - The y coordinate of the lines ending point.
|
|
*
|
|
* @return {this} This Line object.
|
|
*/
|
|
setTo: function (x1, y1, x2, y2)
|
|
{
|
|
if (x1 === undefined) { x1 = 0; }
|
|
if (y1 === undefined) { y1 = 0; }
|
|
if (x2 === undefined) { x2 = 0; }
|
|
if (y2 === undefined) { y2 = 0; }
|
|
|
|
this.x1 = x1;
|
|
this.y1 = y1;
|
|
|
|
this.x2 = x2;
|
|
this.y2 = y2;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Returns a Vector2 object that corresponds to the start of this Line.
|
|
*
|
|
* @method Phaser.Geom.Line#getPointA
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [vec2,$return]
|
|
*
|
|
* @param {Phaser.Math.Vector2} [vec2] - A Vector2 object to set the results in. If `undefined` a new Vector2 will be created.
|
|
*
|
|
* @return {Phaser.Math.Vector2} A Vector2 object that corresponds to the start of this Line.
|
|
*/
|
|
getPointA: function (vec2)
|
|
{
|
|
if (vec2 === undefined) { vec2 = new Vector2(); }
|
|
|
|
vec2.set(this.x1, this.y1);
|
|
|
|
return vec2;
|
|
},
|
|
|
|
/**
|
|
* Returns a Vector2 object that corresponds to the end of this Line.
|
|
*
|
|
* @method Phaser.Geom.Line#getPointB
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Math.Vector2} O - [vec2,$return]
|
|
*
|
|
* @param {Phaser.Math.Vector2} [vec2] - A Vector2 object to set the results in. If `undefined` a new Vector2 will be created.
|
|
*
|
|
* @return {Phaser.Math.Vector2} A Vector2 object that corresponds to the end of this Line.
|
|
*/
|
|
getPointB: function (vec2)
|
|
{
|
|
if (vec2 === undefined) { vec2 = new Vector2(); }
|
|
|
|
vec2.set(this.x2, this.y2);
|
|
|
|
return vec2;
|
|
},
|
|
|
|
/**
|
|
* The left position of the Line.
|
|
*
|
|
* @name Phaser.Geom.Line#left
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
left: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.min(this.x1, this.x2);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (this.x1 <= this.x2)
|
|
{
|
|
this.x1 = value;
|
|
}
|
|
else
|
|
{
|
|
this.x2 = value;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The right position of the Line.
|
|
*
|
|
* @name Phaser.Geom.Line#right
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
right: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.max(this.x1, this.x2);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (this.x1 > this.x2)
|
|
{
|
|
this.x1 = value;
|
|
}
|
|
else
|
|
{
|
|
this.x2 = value;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The top position of the Line.
|
|
*
|
|
* @name Phaser.Geom.Line#top
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
top: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.min(this.y1, this.y2);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (this.y1 <= this.y2)
|
|
{
|
|
this.y1 = value;
|
|
}
|
|
else
|
|
{
|
|
this.y2 = value;
|
|
}
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The bottom position of the Line.
|
|
*
|
|
* @name Phaser.Geom.Line#bottom
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
bottom: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.max(this.y1, this.y2);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
if (this.y1 > this.y2)
|
|
{
|
|
this.y1 = value;
|
|
}
|
|
else
|
|
{
|
|
this.y2 = value;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = Line;
|
|
|
|
|
|
/***/ }),
|
|
/* 323 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Point = __webpack_require__(14);
|
|
|
|
/**
|
|
* Get a point on a line that's a given percentage along its length.
|
|
*
|
|
* @function Phaser.Geom.Line.GetPoint
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [out,$return]
|
|
*
|
|
* @param {Phaser.Geom.Line} line - The line.
|
|
* @param {number} position - A value between 0 and 1, where 0 is the start, 0.5 is the middle and 1 is the end of the line.
|
|
* @param {(Phaser.Geom.Point|object)} [out] - An optional point, or point-like object, to store the coordinates of the point on the line.
|
|
*
|
|
* @return {(Phaser.Geom.Point|object)} The point on the line.
|
|
*/
|
|
var GetPoint = function (line, position, out)
|
|
{
|
|
if (out === undefined) { out = new Point(); }
|
|
|
|
out.x = line.x1 + (line.x2 - line.x1) * position;
|
|
out.y = line.y1 + (line.y2 - line.y1) * position;
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = GetPoint;
|
|
|
|
|
|
/***/ }),
|
|
/* 324 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Length = __webpack_require__(325);
|
|
var Point = __webpack_require__(14);
|
|
|
|
/**
|
|
* Get a number of points along a line's length.
|
|
*
|
|
* Provide a `quantity` to get an exact number of points along the line.
|
|
*
|
|
* Provide a `stepRate` to ensure a specific distance between each point on the line. Set `quantity` to `0` when
|
|
* providing a `stepRate`.
|
|
*
|
|
* @function Phaser.Geom.Line.GetPoints
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point[]} O - [out,$return]
|
|
*
|
|
* @param {Phaser.Geom.Line} line - The line.
|
|
* @param {number} quantity - The number of points to place on the line. Set to `0` to use `stepRate` instead.
|
|
* @param {number} [stepRate] - The distance between each point on the line. When set, `quantity` is implied and should be set to `0`.
|
|
* @param {(array|Phaser.Geom.Point[])} [out] - An optional array of Points, or point-like objects, to store the coordinates of the points on the line.
|
|
*
|
|
* @return {(array|Phaser.Geom.Point[])} An array of Points, or point-like objects, containing the coordinates of the points on the line.
|
|
*/
|
|
var GetPoints = function (line, quantity, stepRate, out)
|
|
{
|
|
if (out === undefined) { out = []; }
|
|
|
|
// If quantity is a falsey value (false, null, 0, undefined, etc) then we calculate it based on the stepRate instead.
|
|
if (!quantity && stepRate > 0)
|
|
{
|
|
quantity = Length(line) / stepRate;
|
|
}
|
|
|
|
var x1 = line.x1;
|
|
var y1 = line.y1;
|
|
|
|
var x2 = line.x2;
|
|
var y2 = line.y2;
|
|
|
|
for (var i = 0; i < quantity; i++)
|
|
{
|
|
var position = i / quantity;
|
|
|
|
var x = x1 + (x2 - x1) * position;
|
|
var y = y1 + (y2 - y1) * position;
|
|
|
|
out.push(new Point(x, y));
|
|
}
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = GetPoints;
|
|
|
|
|
|
/***/ }),
|
|
/* 325 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Calculate the length of the given line.
|
|
*
|
|
* @function Phaser.Geom.Line.Length
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Geom.Line} line - The line to calculate the length of.
|
|
*
|
|
* @return {number} The length of the line.
|
|
*/
|
|
var Length = function (line)
|
|
{
|
|
return Math.sqrt((line.x2 - line.x1) * (line.x2 - line.x1) + (line.y2 - line.y1) * (line.y2 - line.y1));
|
|
};
|
|
|
|
module.exports = Length;
|
|
|
|
|
|
/***/ }),
|
|
/* 326 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Point = __webpack_require__(14);
|
|
|
|
/**
|
|
* Returns a random point on a given Line.
|
|
*
|
|
* @function Phaser.Geom.Line.Random
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [out,$return]
|
|
*
|
|
* @param {Phaser.Geom.Line} line - The Line to calculate the random Point on.
|
|
* @param {(Phaser.Geom.Point|object)} [out] - An instance of a Point to be modified.
|
|
*
|
|
* @return {(Phaser.Geom.Point|object)} A random Point on the Line.
|
|
*/
|
|
var Random = function (line, out)
|
|
{
|
|
if (out === undefined) { out = new Point(); }
|
|
|
|
var t = Math.random();
|
|
|
|
out.x = line.x1 + t * (line.x2 - line.x1);
|
|
out.y = line.y1 + t * (line.y2 - line.y1);
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = Random;
|
|
|
|
|
|
/***/ }),
|
|
/* 327 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Point = __webpack_require__(14);
|
|
|
|
/**
|
|
* Returns a random point within a Rectangle.
|
|
*
|
|
* @function Phaser.Geom.Rectangle.Random
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Point} O - [out,$return]
|
|
*
|
|
* @param {Phaser.Geom.Rectangle} rect - The Rectangle to return a point from.
|
|
* @param {Phaser.Geom.Point} out - The object to update with the point's coordinates.
|
|
*
|
|
* @return {Phaser.Geom.Point} The modified `out` object, or a new Point if none was provided.
|
|
*/
|
|
var Random = function (rect, out)
|
|
{
|
|
if (out === undefined) { out = new Point(); }
|
|
|
|
out.x = rect.x + (Math.random() * rect.width);
|
|
out.y = rect.y + (Math.random() * rect.height);
|
|
|
|
return out;
|
|
};
|
|
|
|
module.exports = Random;
|
|
|
|
|
|
/***/ }),
|
|
/* 328 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var BitmapMask = __webpack_require__(329);
|
|
var GeometryMask = __webpack_require__(332);
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the mask of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Mask
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Mask = {
|
|
|
|
/**
|
|
* The Mask this Game Object is using during render.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Mask#mask
|
|
* @type {Phaser.Display.Masks.BitmapMask|Phaser.Display.Masks.GeometryMask}
|
|
* @since 3.0.0
|
|
*/
|
|
mask: null,
|
|
|
|
/**
|
|
* Sets the mask that this Game Object will use to render with.
|
|
*
|
|
* The mask must have been previously created and can be either a GeometryMask or a BitmapMask.
|
|
* Note: Bitmap Masks only work on WebGL. Geometry Masks work on both WebGL and Canvas.
|
|
*
|
|
* If a mask is already set on this Game Object it will be immediately replaced.
|
|
*
|
|
* Masks are positioned in global space and are not relative to the Game Object to which they
|
|
* are applied. The reason for this is that multiple Game Objects can all share the same mask.
|
|
*
|
|
* Masks have no impact on physics or input detection. They are purely a rendering component
|
|
* that allows you to limit what is visible during the render pass.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Mask#setMask
|
|
* @since 3.6.2
|
|
*
|
|
* @param {Phaser.Display.Masks.BitmapMask|Phaser.Display.Masks.GeometryMask} mask - The mask this Game Object will use when rendering.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setMask: function (mask)
|
|
{
|
|
this.mask = mask;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Clears the mask that this Game Object was using.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Mask#clearMask
|
|
* @since 3.6.2
|
|
*
|
|
* @param {boolean} [destroyMask=false] - Destroy the mask before clearing it?
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
clearMask: function (destroyMask)
|
|
{
|
|
if (destroyMask === undefined) { destroyMask = false; }
|
|
|
|
if (destroyMask && this.mask)
|
|
{
|
|
this.mask.destroy();
|
|
}
|
|
|
|
this.mask = null;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Creates and returns a Bitmap Mask. This mask can be used by any Game Object,
|
|
* including this one, or a Dynamic Texture.
|
|
*
|
|
* Note: Bitmap Masks only work on WebGL. Geometry Masks work on both WebGL and Canvas.
|
|
*
|
|
* To create the mask you need to pass in a reference to a renderable Game Object.
|
|
* A renderable Game Object is one that uses a texture to render with, such as an
|
|
* Image, Sprite, Render Texture or BitmapText.
|
|
*
|
|
* If you do not provide a renderable object, and this Game Object has a texture,
|
|
* it will use itself as the object. This means you can call this method to create
|
|
* a Bitmap Mask from any renderable texture-based Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Mask#createBitmapMask
|
|
* @since 3.6.2
|
|
*
|
|
* @generic {Phaser.GameObjects.GameObject} G
|
|
* @generic {Phaser.Textures.DynamicTexture} T
|
|
* @genericUse {(G|T|null)} [maskObject]
|
|
*
|
|
* @param {(Phaser.GameObjects.GameObject|Phaser.Textures.DynamicTexture)} [maskObject] - The Game Object or Dynamic Texture that will be used as the mask. If `null` it will generate an Image Game Object using the rest of the arguments.
|
|
* @param {number} [x] - If creating a Game Object, the horizontal position in the world.
|
|
* @param {number} [y] - If creating a Game Object, the vertical position in the world.
|
|
* @param {(string|Phaser.Textures.Texture)} [texture] - If creating a Game Object, the key, or instance of the Texture it will use to render with, as stored in the Texture Manager.
|
|
* @param {(string|number|Phaser.Textures.Frame)} [frame] - If creating a Game Object, an optional frame from the Texture this Game Object is rendering with.
|
|
*
|
|
* @return {Phaser.Display.Masks.BitmapMask} This Bitmap Mask that was created.
|
|
*/
|
|
createBitmapMask: function (maskObject, x, y, texture, frame)
|
|
{
|
|
if (maskObject === undefined && (this.texture || this.shader || this.geom))
|
|
{
|
|
// eslint-disable-next-line consistent-this
|
|
maskObject = this;
|
|
}
|
|
|
|
return new BitmapMask(this.scene, maskObject, x, y, texture, frame);
|
|
},
|
|
|
|
/**
|
|
* Creates and returns a Geometry Mask. This mask can be used by any Game Object,
|
|
* including this one.
|
|
*
|
|
* To create the mask you need to pass in a reference to a Graphics Game Object.
|
|
*
|
|
* If you do not provide a graphics object, and this Game Object is an instance
|
|
* of a Graphics object, then it will use itself to create the mask.
|
|
*
|
|
* This means you can call this method to create a Geometry Mask from any Graphics Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Mask#createGeometryMask
|
|
* @since 3.6.2
|
|
*
|
|
* @generic {Phaser.GameObjects.Graphics} G
|
|
* @generic {Phaser.GameObjects.Shape} S
|
|
* @genericUse {(G|S)} [graphics]
|
|
*
|
|
* @param {Phaser.GameObjects.Graphics|Phaser.GameObjects.Shape} [graphics] - A Graphics Game Object, or any kind of Shape Game Object. The geometry within it will be used as the mask.
|
|
*
|
|
* @return {Phaser.Display.Masks.GeometryMask} This Geometry Mask that was created.
|
|
*/
|
|
createGeometryMask: function (graphics)
|
|
{
|
|
if (graphics === undefined && (this.type === 'Graphics' || this.geom))
|
|
{
|
|
// eslint-disable-next-line consistent-this
|
|
graphics = this;
|
|
}
|
|
|
|
return new GeometryMask(this.scene, graphics);
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Mask;
|
|
|
|
|
|
/***/ }),
|
|
/* 329 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var GameObjectFactory = __webpack_require__(330);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Bitmap Mask combines the alpha (opacity) of a masked pixel with the alpha of another pixel.
|
|
* Unlike the Geometry Mask, which is a clipping path, a Bitmap Mask behaves like an alpha mask,
|
|
* not a clipping path. It is only available when using the WebGL Renderer.
|
|
*
|
|
* A Bitmap Mask can use any Game Object or Dynamic Texture to determine the alpha of each pixel of the masked Game Object(s).
|
|
* For any given point of a masked Game Object's texture, the pixel's alpha will be multiplied by the alpha
|
|
* of the pixel at the same position in the Bitmap Mask's Game Object. The color of the pixel from the
|
|
* Bitmap Mask doesn't matter.
|
|
*
|
|
* For example, if a pure blue pixel with an alpha of 0.95 is masked with a pure red pixel with an
|
|
* alpha of 0.5, the resulting pixel will be pure blue with an alpha of 0.475. Naturally, this means
|
|
* that a pixel in the mask with an alpha of 0 will hide the corresponding pixel in all masked Game Objects
|
|
* A pixel with an alpha of 1 in the masked Game Object will receive the same alpha as the
|
|
* corresponding pixel in the mask.
|
|
*
|
|
* Note: You cannot combine Bitmap Masks and Blend Modes on the same Game Object. You can, however,
|
|
* combine Geometry Masks and Blend Modes together.
|
|
*
|
|
* The Bitmap Mask's location matches the location of its Game Object, not the location of the
|
|
* masked objects. Moving or transforming the underlying Game Object will change the mask
|
|
* (and affect the visibility of any masked objects), whereas moving or transforming a masked object
|
|
* will not affect the mask.
|
|
*
|
|
* The Bitmap Mask will not render its Game Object by itself. If the Game Object is not in a
|
|
* Scene's display list, it will only be used for the mask and its full texture will not be directly
|
|
* visible. Adding the underlying Game Object to a Scene will not cause any problems - it will
|
|
* render as a normal Game Object and will also serve as a mask.
|
|
*
|
|
* @class BitmapMask
|
|
* @memberof Phaser.Display.Masks
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scene} scene - The Scene to which this mask is being added.
|
|
* @param {(Phaser.GameObjects.GameObject|Phaser.Textures.DynamicTexture)} [maskObject] - The Game Object or Dynamic Texture that will be used as the mask. If `null` it will generate an Image Game Object using the rest of the arguments.
|
|
* @param {number} [x] - If creating a Game Object, the horizontal position in the world.
|
|
* @param {number} [y] - If creating a Game Object, the vertical position in the world.
|
|
* @param {(string|Phaser.Textures.Texture)} [texture] - If creating a Game Object, the key, or instance of the Texture it will use to render with, as stored in the Texture Manager.
|
|
* @param {(string|number|Phaser.Textures.Frame)} [frame] - If creating a Game Object, an optional frame from the Texture this Game Object is rendering with.
|
|
*/
|
|
var BitmapMask = new Class({
|
|
|
|
initialize:
|
|
|
|
function BitmapMask (scene, maskObject, x, y, texture, frame)
|
|
{
|
|
if (!maskObject)
|
|
{
|
|
maskObject = scene.sys.make.image({ x: x, y: y, key: texture, frame: frame, add: false });
|
|
}
|
|
|
|
/**
|
|
* The Game Object that is used as the mask. Must use a texture, such as a Sprite.
|
|
*
|
|
* @name Phaser.Display.Masks.BitmapMask#bitmapMask
|
|
* @type {(Phaser.GameObjects.GameObject|Phaser.Textures.DynamicTexture)}
|
|
* @since 3.0.0
|
|
*/
|
|
this.bitmapMask = maskObject;
|
|
|
|
/**
|
|
* Whether to invert the masks alpha.
|
|
*
|
|
* If `true`, the alpha of the masking pixel will be inverted before it's multiplied with the masked pixel.
|
|
*
|
|
* Essentially, this means that a masked area will be visible only if the corresponding area in the mask is invisible.
|
|
*
|
|
* @name Phaser.Display.Masks.BitmapMask#invertAlpha
|
|
* @type {boolean}
|
|
* @since 3.1.2
|
|
*/
|
|
this.invertAlpha = false;
|
|
|
|
/**
|
|
* Is this mask a stencil mask? This is false by default and should not be changed.
|
|
*
|
|
* @name Phaser.Display.Masks.BitmapMask#isStencil
|
|
* @type {boolean}
|
|
* @readonly
|
|
* @since 3.17.0
|
|
*/
|
|
this.isStencil = false;
|
|
},
|
|
|
|
/**
|
|
* Sets a new Game Object or Dynamic Texture for this Bitmap Mask to use.
|
|
*
|
|
* If a Game Object it must have a texture, such as a Sprite.
|
|
*
|
|
* You can update the source of the mask as often as you like.
|
|
*
|
|
* @method Phaser.Display.Masks.BitmapMask#setBitmap
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.GameObjects.GameObject|Phaser.Textures.DynamicTexture)} maskObject - The Game Object or Dynamic Texture that will be used as the mask. If a Game Object, it must have a texture, such as a Sprite.
|
|
*/
|
|
setBitmap: function (maskObject)
|
|
{
|
|
this.bitmapMask = maskObject;
|
|
},
|
|
|
|
/**
|
|
* Prepares the WebGL Renderer to render a Game Object with this mask applied.
|
|
*
|
|
* This renders the masking Game Object to the mask framebuffer and switches to the main framebuffer so that the masked Game Object will be rendered to it instead of being rendered directly to the frame.
|
|
*
|
|
* @method Phaser.Display.Masks.BitmapMask#preRenderWebGL
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The WebGL Renderer to prepare.
|
|
* @param {Phaser.GameObjects.GameObject} maskedObject - The masked Game Object which will be drawn.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to render to.
|
|
*/
|
|
preRenderWebGL: function (renderer, maskedObject, camera)
|
|
{
|
|
renderer.pipelines.BITMAPMASK_PIPELINE.beginMask(this, maskedObject, camera);
|
|
},
|
|
|
|
/**
|
|
* Finalizes rendering of a masked Game Object.
|
|
*
|
|
* This resets the previously bound framebuffer and switches the WebGL Renderer to the Bitmap Mask Pipeline, which uses a special fragment shader to apply the masking effect.
|
|
*
|
|
* @method Phaser.Display.Masks.BitmapMask#postRenderWebGL
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The WebGL Renderer to clean up.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to render to.
|
|
* @param {Phaser.Renderer.WebGL.RenderTarget} [renderTarget] - Optional WebGL RenderTarget.
|
|
*/
|
|
postRenderWebGL: function (renderer, camera, renderTarget)
|
|
{
|
|
renderer.pipelines.BITMAPMASK_PIPELINE.endMask(this, camera, renderTarget);
|
|
},
|
|
|
|
/**
|
|
* This is a NOOP method. Bitmap Masks are not supported by the Canvas Renderer.
|
|
*
|
|
* @method Phaser.Display.Masks.BitmapMask#preRenderCanvas
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The Canvas Renderer which would be rendered to.
|
|
* @param {Phaser.GameObjects.GameObject} mask - The masked Game Object which would be rendered.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera to render to.
|
|
*/
|
|
preRenderCanvas: function ()
|
|
{
|
|
// NOOP
|
|
},
|
|
|
|
/**
|
|
* This is a NOOP method. Bitmap Masks are not supported by the Canvas Renderer.
|
|
*
|
|
* @method Phaser.Display.Masks.BitmapMask#postRenderCanvas
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(Phaser.Renderer.Canvas.CanvasRenderer|Phaser.Renderer.WebGL.WebGLRenderer)} renderer - The Canvas Renderer which would be rendered to.
|
|
*/
|
|
postRenderCanvas: function ()
|
|
{
|
|
// NOOP
|
|
},
|
|
|
|
/**
|
|
* Destroys this BitmapMask and nulls any references it holds.
|
|
*
|
|
* Note that if a Game Object is currently using this mask it will _not_ automatically detect you have destroyed it,
|
|
* so be sure to call `clearMask` on any Game Object using it, before destroying it.
|
|
*
|
|
* @method Phaser.Display.Masks.BitmapMask#destroy
|
|
* @since 3.7.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.bitmapMask = null;
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* A Bitmap Mask combines the alpha (opacity) of a masked pixel with the alpha of another pixel.
|
|
* Unlike the Geometry Mask, which is a clipping path, a Bitmap Mask behaves like an alpha mask,
|
|
* not a clipping path. It is only available when using the WebGL Renderer.
|
|
*
|
|
* A Bitmap Mask can use any Game Object, or Dynamic Texture, to determine the alpha of each pixel of the masked Game Object(s).
|
|
* For any given point of a masked Game Object's texture, the pixel's alpha will be multiplied by the alpha
|
|
* of the pixel at the same position in the Bitmap Mask's Game Object. The color of the pixel from the
|
|
* Bitmap Mask doesn't matter.
|
|
*
|
|
* For example, if a pure blue pixel with an alpha of 0.95 is masked with a pure red pixel with an
|
|
* alpha of 0.5, the resulting pixel will be pure blue with an alpha of 0.475. Naturally, this means
|
|
* that a pixel in the mask with an alpha of 0 will hide the corresponding pixel in all masked Game Objects
|
|
* A pixel with an alpha of 1 in the masked Game Object will receive the same alpha as the
|
|
* corresponding pixel in the mask.
|
|
*
|
|
* Note: You cannot combine Bitmap Masks and Blend Modes on the same Game Object. You can, however,
|
|
* combine Geometry Masks and Blend Modes together.
|
|
*
|
|
* The Bitmap Mask's location matches the location of its Game Object, not the location of the
|
|
* masked objects. Moving or transforming the underlying Game Object will change the mask
|
|
* (and affect the visibility of any masked objects), whereas moving or transforming a masked object
|
|
* will not affect the mask.
|
|
*
|
|
* The Bitmap Mask will not render its Game Object by itself. If the Game Object is not in a
|
|
* Scene's display list, it will only be used for the mask and its full texture will not be directly
|
|
* visible. Adding the underlying Game Object to a Scene will not cause any problems - it will
|
|
* render as a normal Game Object and will also serve as a mask.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory#bitmapMask
|
|
* @since 3.60.0
|
|
*
|
|
* @param {(Phaser.GameObjects.GameObject|Phaser.Textures.DynamicTexture)} [maskObject] - The Game Object or Texture that will be used as the mask. If `null` it will generate an Image Game Object using the rest of the arguments.
|
|
* @param {number} [x] - If creating a Game Object, the horizontal position in the world.
|
|
* @param {number} [y] - If creating a Game Object, the vertical position in the world.
|
|
* @param {(string|Phaser.Textures.Texture)} [texture] - If creating a Game Object, the key, or instance of the Texture it will use to render with, as stored in the Texture Manager.
|
|
* @param {(string|number|Phaser.Textures.Frame)} [frame] - If creating a Game Object, an optional frame from the Texture this Game Object is rendering with.
|
|
*
|
|
* @return {Phaser.Display.Masks.BitmapMask} The Bitmap Mask that was created.
|
|
*/
|
|
GameObjectFactory.register('bitmapMask', function (maskObject, x, y, key, frame)
|
|
{
|
|
return new BitmapMask(this.scene, maskObject, x, y, key, frame);
|
|
});
|
|
|
|
module.exports = BitmapMask;
|
|
|
|
|
|
/***/ }),
|
|
/* 330 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
var PluginCache = __webpack_require__(331);
|
|
var SceneEvents = __webpack_require__(23);
|
|
|
|
/**
|
|
* @classdesc
|
|
* The Game Object Factory is a Scene plugin that allows you to quickly create many common
|
|
* types of Game Objects and have them automatically registered with the Scene.
|
|
*
|
|
* Game Objects directly register themselves with the Factory and inject their own creation
|
|
* methods into the class.
|
|
*
|
|
* @class GameObjectFactory
|
|
* @memberof Phaser.GameObjects
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scene} scene - The Scene to which this Game Object Factory belongs.
|
|
*/
|
|
var GameObjectFactory = new Class({
|
|
|
|
initialize:
|
|
|
|
function GameObjectFactory (scene)
|
|
{
|
|
/**
|
|
* The Scene to which this Game Object Factory belongs.
|
|
*
|
|
* @name Phaser.GameObjects.GameObjectFactory#scene
|
|
* @type {Phaser.Scene}
|
|
* @protected
|
|
* @since 3.0.0
|
|
*/
|
|
this.scene = scene;
|
|
|
|
/**
|
|
* A reference to the Scene.Systems.
|
|
*
|
|
* @name Phaser.GameObjects.GameObjectFactory#systems
|
|
* @type {Phaser.Scenes.Systems}
|
|
* @protected
|
|
* @since 3.0.0
|
|
*/
|
|
this.systems = scene.sys;
|
|
|
|
/**
|
|
* A reference to the Scene Event Emitter.
|
|
*
|
|
* @name Phaser.GameObjects.GameObjectFactory#events
|
|
* @type {Phaser.Events.EventEmitter}
|
|
* @protected
|
|
* @since 3.50.0
|
|
*/
|
|
this.events = scene.sys.events;
|
|
|
|
/**
|
|
* A reference to the Scene Display List.
|
|
*
|
|
* @name Phaser.GameObjects.GameObjectFactory#displayList
|
|
* @type {Phaser.GameObjects.DisplayList}
|
|
* @protected
|
|
* @since 3.0.0
|
|
*/
|
|
this.displayList;
|
|
|
|
/**
|
|
* A reference to the Scene Update List.
|
|
*
|
|
* @name Phaser.GameObjects.GameObjectFactory#updateList
|
|
* @type {Phaser.GameObjects.UpdateList}
|
|
* @protected
|
|
* @since 3.0.0
|
|
*/
|
|
this.updateList;
|
|
|
|
this.events.once(SceneEvents.BOOT, this.boot, this);
|
|
this.events.on(SceneEvents.START, this.start, this);
|
|
},
|
|
|
|
/**
|
|
* This method is called automatically, only once, when the Scene is first created.
|
|
* Do not invoke it directly.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory#boot
|
|
* @private
|
|
* @since 3.5.1
|
|
*/
|
|
boot: function ()
|
|
{
|
|
this.displayList = this.systems.displayList;
|
|
this.updateList = this.systems.updateList;
|
|
|
|
this.events.once(SceneEvents.DESTROY, this.destroy, this);
|
|
},
|
|
|
|
/**
|
|
* This method is called automatically by the Scene when it is starting up.
|
|
* It is responsible for creating local systems, properties and listening for Scene events.
|
|
* Do not invoke it directly.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory#start
|
|
* @private
|
|
* @since 3.5.0
|
|
*/
|
|
start: function ()
|
|
{
|
|
this.events.once(SceneEvents.SHUTDOWN, this.shutdown, this);
|
|
},
|
|
|
|
/**
|
|
* Adds an existing Game Object to this Scene.
|
|
*
|
|
* If the Game Object renders, it will be added to the Display List.
|
|
* If it has a `preUpdate` method, it will be added to the Update List.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory#existing
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {(Phaser.GameObjects.GameObject|Phaser.GameObjects.Group|Phaser.GameObjects.Layer)} G - [child,$return]
|
|
*
|
|
* @param {(Phaser.GameObjects.GameObject|Phaser.GameObjects.Group|Phaser.GameObjects.Layer)} child - The child to be added to this Scene.
|
|
*
|
|
* @return {Phaser.GameObjects.GameObject} The Game Object that was added.
|
|
*/
|
|
existing: function (child)
|
|
{
|
|
if (child.renderCanvas || child.renderWebGL)
|
|
{
|
|
this.displayList.add(child);
|
|
}
|
|
|
|
// For when custom objects have overridden `preUpdate` but don't hook into the ADDED_TO_SCENE event:
|
|
// Adding to the list multiple times is safe, as it won't add duplicates into the list anyway.
|
|
if (child.preUpdate)
|
|
{
|
|
this.updateList.add(child);
|
|
}
|
|
|
|
return child;
|
|
},
|
|
|
|
/**
|
|
* The Scene that owns this plugin is shutting down.
|
|
* We need to kill and reset all internal properties as well as stop listening to Scene events.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory#shutdown
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
shutdown: function ()
|
|
{
|
|
this.events.off(SceneEvents.SHUTDOWN, this.shutdown, this);
|
|
},
|
|
|
|
/**
|
|
* The Scene that owns this plugin is being destroyed.
|
|
* We need to shutdown and then kill off all external references.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory#destroy
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.shutdown();
|
|
|
|
this.events.off(SceneEvents.START, this.start, this);
|
|
|
|
this.scene = null;
|
|
this.systems = null;
|
|
this.events = null;
|
|
|
|
this.displayList = null;
|
|
this.updateList = null;
|
|
}
|
|
|
|
});
|
|
|
|
/**
|
|
* Static method called directly by the Game Object factory functions.
|
|
* With this method you can register a custom GameObject factory in the GameObjectFactory,
|
|
* providing a name (`factoryType`) and the constructor (`factoryFunction`) in order
|
|
* to be called when you call to Phaser.Scene.add[ factoryType ] method.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory.register
|
|
* @static
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} factoryType - The key of the factory that you will use to call to Phaser.Scene.add[ factoryType ] method.
|
|
* @param {function} factoryFunction - The constructor function to be called when you invoke to the Phaser.Scene.add method.
|
|
*/
|
|
GameObjectFactory.register = function (factoryType, factoryFunction)
|
|
{
|
|
if (!GameObjectFactory.prototype.hasOwnProperty(factoryType))
|
|
{
|
|
GameObjectFactory.prototype[factoryType] = factoryFunction;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Static method called directly by the Game Object factory functions.
|
|
* With this method you can remove a custom GameObject factory registered in the GameObjectFactory,
|
|
* providing a its `factoryType`.
|
|
*
|
|
* @method Phaser.GameObjects.GameObjectFactory.remove
|
|
* @static
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} factoryType - The key of the factory that you want to remove from the GameObjectFactory.
|
|
*/
|
|
GameObjectFactory.remove = function (factoryType)
|
|
{
|
|
if (GameObjectFactory.prototype.hasOwnProperty(factoryType))
|
|
{
|
|
delete GameObjectFactory.prototype[factoryType];
|
|
}
|
|
};
|
|
|
|
PluginCache.register('GameObjectFactory', GameObjectFactory, 'add');
|
|
|
|
module.exports = GameObjectFactory;
|
|
|
|
|
|
/***/ }),
|
|
/* 331 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
// Contains the plugins that Phaser uses globally and locally.
|
|
// These are the source objects, not instantiated.
|
|
var corePlugins = {};
|
|
|
|
// Contains the plugins that the dev has loaded into their game
|
|
// These are the source objects, not instantiated.
|
|
var customPlugins = {};
|
|
|
|
var PluginCache = {};
|
|
|
|
/**
|
|
* @namespace Phaser.Plugins.PluginCache
|
|
*/
|
|
|
|
/**
|
|
* Static method called directly by the Core internal Plugins.
|
|
* Key is a reference used to get the plugin from the plugins object (i.e. InputPlugin)
|
|
* Plugin is the object to instantiate to create the plugin
|
|
* Mapping is what the plugin is injected into the Scene.Systems as (i.e. input)
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.register
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - A reference used to get this plugin from the plugin cache.
|
|
* @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated.
|
|
* @param {string} mapping - If this plugin is to be injected into the Scene Systems, this is the property key map used.
|
|
* @param {boolean} [custom=false] - Core Scene plugin or a Custom Scene plugin?
|
|
*/
|
|
PluginCache.register = function (key, plugin, mapping, custom)
|
|
{
|
|
if (custom === undefined) { custom = false; }
|
|
|
|
corePlugins[key] = { plugin: plugin, mapping: mapping, custom: custom };
|
|
};
|
|
|
|
/**
|
|
* Stores a custom plugin in the global plugin cache.
|
|
* The key must be unique, within the scope of the cache.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.registerCustom
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - A reference used to get this plugin from the plugin cache.
|
|
* @param {function} plugin - The plugin to be stored. Should be the core object, not instantiated.
|
|
* @param {string} mapping - If this plugin is to be injected into the Scene Systems, this is the property key map used.
|
|
* @param {?any} data - A value to be passed to the plugin's `init` method.
|
|
*/
|
|
PluginCache.registerCustom = function (key, plugin, mapping, data)
|
|
{
|
|
customPlugins[key] = { plugin: plugin, mapping: mapping, data: data };
|
|
};
|
|
|
|
/**
|
|
* Checks if the given key is already being used in the core plugin cache.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.hasCore
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - The key to check for.
|
|
*
|
|
* @return {boolean} `true` if the key is already in use in the core cache, otherwise `false`.
|
|
*/
|
|
PluginCache.hasCore = function (key)
|
|
{
|
|
return corePlugins.hasOwnProperty(key);
|
|
};
|
|
|
|
/**
|
|
* Checks if the given key is already being used in the custom plugin cache.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.hasCustom
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - The key to check for.
|
|
*
|
|
* @return {boolean} `true` if the key is already in use in the custom cache, otherwise `false`.
|
|
*/
|
|
PluginCache.hasCustom = function (key)
|
|
{
|
|
return customPlugins.hasOwnProperty(key);
|
|
};
|
|
|
|
/**
|
|
* Returns the core plugin object from the cache based on the given key.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.getCore
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - The key of the core plugin to get.
|
|
*
|
|
* @return {Phaser.Types.Plugins.CorePluginContainer} The core plugin object.
|
|
*/
|
|
PluginCache.getCore = function (key)
|
|
{
|
|
return corePlugins[key];
|
|
};
|
|
|
|
/**
|
|
* Returns the custom plugin object from the cache based on the given key.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.getCustom
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - The key of the custom plugin to get.
|
|
*
|
|
* @return {Phaser.Types.Plugins.CustomPluginContainer} The custom plugin object.
|
|
*/
|
|
PluginCache.getCustom = function (key)
|
|
{
|
|
return customPlugins[key];
|
|
};
|
|
|
|
/**
|
|
* Returns an object from the custom cache based on the given key that can be instantiated.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.getCustomClass
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - The key of the custom plugin to get.
|
|
*
|
|
* @return {function} The custom plugin object.
|
|
*/
|
|
PluginCache.getCustomClass = function (key)
|
|
{
|
|
return (customPlugins.hasOwnProperty(key)) ? customPlugins[key].plugin : null;
|
|
};
|
|
|
|
/**
|
|
* Removes a core plugin based on the given key.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.remove
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - The key of the core plugin to remove.
|
|
*/
|
|
PluginCache.remove = function (key)
|
|
{
|
|
if (corePlugins.hasOwnProperty(key))
|
|
{
|
|
delete corePlugins[key];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Removes a custom plugin based on the given key.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.removeCustom
|
|
* @since 3.8.0
|
|
*
|
|
* @param {string} key - The key of the custom plugin to remove.
|
|
*/
|
|
PluginCache.removeCustom = function (key)
|
|
{
|
|
if (customPlugins.hasOwnProperty(key))
|
|
{
|
|
delete customPlugins[key];
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Removes all Core Plugins.
|
|
*
|
|
* This includes all of the internal system plugins that Phaser needs, like the Input Plugin and Loader Plugin.
|
|
* So be sure you only call this if you do not wish to run Phaser again.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.destroyCorePlugins
|
|
* @since 3.12.0
|
|
*/
|
|
PluginCache.destroyCorePlugins = function ()
|
|
{
|
|
for (var key in corePlugins)
|
|
{
|
|
if (corePlugins.hasOwnProperty(key))
|
|
{
|
|
delete corePlugins[key];
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Removes all Custom Plugins.
|
|
*
|
|
* @method Phaser.Plugins.PluginCache.destroyCustomPlugins
|
|
* @since 3.12.0
|
|
*/
|
|
PluginCache.destroyCustomPlugins = function ()
|
|
{
|
|
for (var key in customPlugins)
|
|
{
|
|
if (customPlugins.hasOwnProperty(key))
|
|
{
|
|
delete customPlugins[key];
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = PluginCache;
|
|
|
|
|
|
/***/ }),
|
|
/* 332 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Class = __webpack_require__(0);
|
|
|
|
/**
|
|
* @classdesc
|
|
* A Geometry Mask can be applied to a Game Object to hide any pixels of it which don't intersect
|
|
* a visible pixel from the geometry mask. The mask is essentially a clipping path which can only
|
|
* make a masked pixel fully visible or fully invisible without changing its alpha (opacity).
|
|
*
|
|
* A Geometry Mask uses a Graphics Game Object to determine which pixels of the masked Game Object(s)
|
|
* should be clipped. For any given point of a masked Game Object's texture, the pixel will only be displayed
|
|
* if the Graphics Game Object of the Geometry Mask has a visible pixel at the same position. The color and
|
|
* alpha of the pixel from the Geometry Mask do not matter.
|
|
*
|
|
* The Geometry Mask's location matches the location of its Graphics object, not the location of the masked objects.
|
|
* Moving or transforming the underlying Graphics object will change the mask (and affect the visibility
|
|
* of any masked objects), whereas moving or transforming a masked object will not affect the mask.
|
|
* You can think of the Geometry Mask (or rather, of its Graphics object) as an invisible curtain placed
|
|
* in front of all masked objects which has its own visual properties and, naturally, respects the camera's
|
|
* visual properties, but isn't affected by and doesn't follow the masked objects by itself.
|
|
*
|
|
* @class GeometryMask
|
|
* @memberof Phaser.Display.Masks
|
|
* @constructor
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Scene} scene - This parameter is not used.
|
|
* @param {Phaser.GameObjects.Graphics} graphicsGeometry - The Graphics Game Object to use for the Geometry Mask. Doesn't have to be in the Display List.
|
|
*/
|
|
var GeometryMask = new Class({
|
|
|
|
initialize:
|
|
|
|
function GeometryMask (scene, graphicsGeometry)
|
|
{
|
|
/**
|
|
* The Graphics object which describes the Geometry Mask.
|
|
*
|
|
* @name Phaser.Display.Masks.GeometryMask#geometryMask
|
|
* @type {Phaser.GameObjects.Graphics}
|
|
* @since 3.0.0
|
|
*/
|
|
this.geometryMask = graphicsGeometry;
|
|
|
|
/**
|
|
* Similar to the BitmapMasks invertAlpha setting this to true will then hide all pixels
|
|
* drawn to the Geometry Mask.
|
|
*
|
|
* This is a WebGL only feature.
|
|
*
|
|
* @name Phaser.Display.Masks.GeometryMask#invertAlpha
|
|
* @type {boolean}
|
|
* @since 3.16.0
|
|
*/
|
|
this.invertAlpha = false;
|
|
|
|
/**
|
|
* Is this mask a stencil mask?
|
|
*
|
|
* @name Phaser.Display.Masks.GeometryMask#isStencil
|
|
* @type {boolean}
|
|
* @readonly
|
|
* @since 3.17.0
|
|
*/
|
|
this.isStencil = true;
|
|
|
|
/**
|
|
* The current stencil level.
|
|
*
|
|
* @name Phaser.Display.Masks.GeometryMask#level
|
|
* @type {boolean}
|
|
* @private
|
|
* @since 3.17.0
|
|
*/
|
|
this.level = 0;
|
|
},
|
|
|
|
/**
|
|
* Sets a new Graphics object for the Geometry Mask.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#setShape
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.GameObjects.Graphics} graphicsGeometry - The Graphics object which will be used for the Geometry Mask.
|
|
*
|
|
* @return {this} This Geometry Mask
|
|
*/
|
|
setShape: function (graphicsGeometry)
|
|
{
|
|
this.geometryMask = graphicsGeometry;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the `invertAlpha` property of this Geometry Mask.
|
|
*
|
|
* Inverting the alpha essentially flips the way the mask works.
|
|
*
|
|
* This is a WebGL only feature.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#setInvertAlpha
|
|
* @since 3.17.0
|
|
*
|
|
* @param {boolean} [value=true] - Invert the alpha of this mask?
|
|
*
|
|
* @return {this} This Geometry Mask
|
|
*/
|
|
setInvertAlpha: function (value)
|
|
{
|
|
if (value === undefined) { value = true; }
|
|
|
|
this.invertAlpha = value;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Renders the Geometry Mask's underlying Graphics object to the OpenGL stencil buffer and enables the stencil test, which clips rendered pixels according to the mask.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#preRenderWebGL
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGL Renderer instance to draw to.
|
|
* @param {Phaser.GameObjects.GameObject} child - The Game Object being rendered.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera the Game Object is being rendered through.
|
|
*/
|
|
preRenderWebGL: function (renderer, child, camera)
|
|
{
|
|
var gl = renderer.gl;
|
|
|
|
// Force flushing before drawing to stencil buffer
|
|
renderer.flush();
|
|
|
|
if (renderer.maskStack.length === 0)
|
|
{
|
|
gl.enable(gl.STENCIL_TEST);
|
|
gl.clear(gl.STENCIL_BUFFER_BIT);
|
|
|
|
renderer.maskCount = 0;
|
|
}
|
|
|
|
if (renderer.currentCameraMask.mask !== this)
|
|
{
|
|
renderer.currentMask.mask = this;
|
|
}
|
|
|
|
renderer.maskStack.push({ mask: this, camera: camera });
|
|
|
|
this.applyStencil(renderer, camera, true);
|
|
|
|
renderer.maskCount++;
|
|
},
|
|
|
|
/**
|
|
* Applies the current stencil mask to the renderer.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#applyStencil
|
|
* @since 3.17.0
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGL Renderer instance to draw to.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera the Game Object is being rendered through.
|
|
* @param {boolean} inc - Is this an INCR stencil or a DECR stencil?
|
|
*/
|
|
applyStencil: function (renderer, camera, inc)
|
|
{
|
|
var gl = renderer.gl;
|
|
var geometryMask = this.geometryMask;
|
|
var level = renderer.maskCount;
|
|
|
|
gl.colorMask(false, false, false, false);
|
|
|
|
if (inc)
|
|
{
|
|
gl.stencilFunc(gl.EQUAL, level, 0xFF);
|
|
gl.stencilOp(gl.KEEP, gl.KEEP, gl.INCR);
|
|
}
|
|
else
|
|
{
|
|
gl.stencilFunc(gl.EQUAL, level + 1, 0xFF);
|
|
gl.stencilOp(gl.KEEP, gl.KEEP, gl.DECR);
|
|
}
|
|
|
|
// Write stencil buffer
|
|
geometryMask.renderWebGL(renderer, geometryMask, camera);
|
|
|
|
renderer.flush();
|
|
|
|
gl.colorMask(true, true, true, true);
|
|
gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
|
|
|
|
if (inc)
|
|
{
|
|
if (this.invertAlpha)
|
|
{
|
|
gl.stencilFunc(gl.NOTEQUAL, level + 1, 0xFF);
|
|
}
|
|
else
|
|
{
|
|
gl.stencilFunc(gl.EQUAL, level + 1, 0xFF);
|
|
}
|
|
}
|
|
else if (this.invertAlpha)
|
|
{
|
|
gl.stencilFunc(gl.NOTEQUAL, level, 0xFF);
|
|
}
|
|
else
|
|
{
|
|
gl.stencilFunc(gl.EQUAL, level, 0xFF);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Flushes all rendered pixels and disables the stencil test of a WebGL context, thus disabling the mask for it.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#postRenderWebGL
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - The WebGL Renderer instance to draw flush.
|
|
*/
|
|
postRenderWebGL: function (renderer)
|
|
{
|
|
var gl = renderer.gl;
|
|
|
|
renderer.maskStack.pop();
|
|
|
|
renderer.maskCount--;
|
|
|
|
// Force flush before disabling stencil test
|
|
renderer.flush();
|
|
|
|
var current = renderer.currentMask;
|
|
|
|
if (renderer.maskStack.length === 0)
|
|
{
|
|
// If this is the only mask in the stack, flush and disable
|
|
current.mask = null;
|
|
|
|
gl.disable(gl.STENCIL_TEST);
|
|
}
|
|
else
|
|
{
|
|
var prev = renderer.maskStack[renderer.maskStack.length - 1];
|
|
|
|
prev.mask.applyStencil(renderer, prev.camera, false);
|
|
|
|
if (renderer.currentCameraMask.mask !== prev.mask)
|
|
{
|
|
current.mask = prev.mask;
|
|
current.camera = prev.camera;
|
|
}
|
|
else
|
|
{
|
|
current.mask = null;
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Sets the clipping path of a 2D canvas context to the Geometry Mask's underlying Graphics object.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#preRenderCanvas
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - The Canvas Renderer instance to set the clipping path on.
|
|
* @param {Phaser.GameObjects.GameObject} mask - The Game Object being rendered.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The camera the Game Object is being rendered through.
|
|
*/
|
|
preRenderCanvas: function (renderer, mask, camera)
|
|
{
|
|
var geometryMask = this.geometryMask;
|
|
|
|
renderer.currentContext.save();
|
|
|
|
geometryMask.renderCanvas(renderer, geometryMask, camera, null, null, true);
|
|
|
|
renderer.currentContext.clip();
|
|
},
|
|
|
|
/**
|
|
* Restore the canvas context's previous clipping path, thus turning off the mask for it.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#postRenderCanvas
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - The Canvas Renderer instance being restored.
|
|
*/
|
|
postRenderCanvas: function (renderer)
|
|
{
|
|
renderer.currentContext.restore();
|
|
},
|
|
|
|
/**
|
|
* Destroys this GeometryMask and nulls any references it holds.
|
|
*
|
|
* Note that if a Game Object is currently using this mask it will _not_ automatically detect you have destroyed it,
|
|
* so be sure to call `clearMask` on any Game Object using it, before destroying it.
|
|
*
|
|
* @method Phaser.Display.Masks.GeometryMask#destroy
|
|
* @since 3.7.0
|
|
*/
|
|
destroy: function ()
|
|
{
|
|
this.geometryMask = null;
|
|
}
|
|
|
|
});
|
|
|
|
module.exports = GeometryMask;
|
|
|
|
|
|
/***/ }),
|
|
/* 333 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the origin of a Game Object.
|
|
* Values are normalized, given in the range 0 to 1.
|
|
* Display values contain the calculated pixel values.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Origin
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Origin = {
|
|
|
|
/**
|
|
* A property indicating that a Game Object has this component.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Origin#_originComponent
|
|
* @type {boolean}
|
|
* @private
|
|
* @default true
|
|
* @since 3.2.0
|
|
*/
|
|
_originComponent: true,
|
|
|
|
/**
|
|
* The horizontal origin of this Game Object.
|
|
* The origin maps the relationship between the size and position of the Game Object.
|
|
* The default value is 0.5, meaning all Game Objects are positioned based on their center.
|
|
* Setting the value to 0 means the position now relates to the left of the Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Origin#originX
|
|
* @type {number}
|
|
* @default 0.5
|
|
* @since 3.0.0
|
|
*/
|
|
originX: 0.5,
|
|
|
|
/**
|
|
* The vertical origin of this Game Object.
|
|
* The origin maps the relationship between the size and position of the Game Object.
|
|
* The default value is 0.5, meaning all Game Objects are positioned based on their center.
|
|
* Setting the value to 0 means the position now relates to the top of the Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Origin#originY
|
|
* @type {number}
|
|
* @default 0.5
|
|
* @since 3.0.0
|
|
*/
|
|
originY: 0.5,
|
|
|
|
// private + read only
|
|
_displayOriginX: 0,
|
|
_displayOriginY: 0,
|
|
|
|
/**
|
|
* The horizontal display origin of this Game Object.
|
|
* The origin is a normalized value between 0 and 1.
|
|
* The displayOrigin is a pixel value, based on the size of the Game Object combined with the origin.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Origin#displayOriginX
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
displayOriginX: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._displayOriginX;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._displayOriginX = value;
|
|
this.originX = value / this.width;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The vertical display origin of this Game Object.
|
|
* The origin is a normalized value between 0 and 1.
|
|
* The displayOrigin is a pixel value, based on the size of the Game Object combined with the origin.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Origin#displayOriginY
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
displayOriginY: {
|
|
|
|
get: function ()
|
|
{
|
|
return this._displayOriginY;
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this._displayOriginY = value;
|
|
this.originY = value / this.height;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Sets the origin of this Game Object.
|
|
*
|
|
* The values are given in the range 0 to 1.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Origin#setOrigin
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=0.5] - The horizontal origin value.
|
|
* @param {number} [y=x] - The vertical origin value. If not defined it will be set to the value of `x`.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setOrigin: function (x, y)
|
|
{
|
|
if (x === undefined) { x = 0.5; }
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.originX = x;
|
|
this.originY = y;
|
|
|
|
return this.updateDisplayOrigin();
|
|
},
|
|
|
|
/**
|
|
* Sets the origin of this Game Object based on the Pivot values in its Frame.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Origin#setOriginFromFrame
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setOriginFromFrame: function ()
|
|
{
|
|
if (!this.frame || !this.frame.customPivot)
|
|
{
|
|
return this.setOrigin();
|
|
}
|
|
else
|
|
{
|
|
this.originX = this.frame.pivotX;
|
|
this.originY = this.frame.pivotY;
|
|
}
|
|
|
|
return this.updateDisplayOrigin();
|
|
},
|
|
|
|
/**
|
|
* Sets the display origin of this Game Object.
|
|
* The difference between this and setting the origin is that you can use pixel values for setting the display origin.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Origin#setDisplayOrigin
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [x=0] - The horizontal display origin value.
|
|
* @param {number} [y=x] - The vertical display origin value. If not defined it will be set to the value of `x`.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setDisplayOrigin: function (x, y)
|
|
{
|
|
if (x === undefined) { x = 0; }
|
|
if (y === undefined) { y = x; }
|
|
|
|
this.displayOriginX = x;
|
|
this.displayOriginY = y;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Updates the Display Origin cached values internally stored on this Game Object.
|
|
* You don't usually call this directly, but it is exposed for edge-cases where you may.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Origin#updateDisplayOrigin
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
updateDisplayOrigin: function ()
|
|
{
|
|
this._displayOriginX = this.originX * this.width;
|
|
this._displayOriginY = this.originY * this.height;
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Origin;
|
|
|
|
|
|
/***/ }),
|
|
/* 334 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var DegToRad = __webpack_require__(21);
|
|
var GetBoolean = __webpack_require__(335);
|
|
var GetValue = __webpack_require__(10);
|
|
var TWEEN_CONST = __webpack_require__(336);
|
|
var Vector2 = __webpack_require__(3);
|
|
|
|
/**
|
|
* Provides methods used for managing a Game Object following a Path.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.PathFollower
|
|
* @since 3.17.0
|
|
*/
|
|
|
|
var PathFollower = {
|
|
|
|
/**
|
|
* The Path this PathFollower is following. It can only follow one Path at a time.
|
|
*
|
|
* @name Phaser.GameObjects.Components.PathFollower#path
|
|
* @type {Phaser.Curves.Path}
|
|
* @since 3.0.0
|
|
*/
|
|
path: null,
|
|
|
|
/**
|
|
* Should the PathFollower automatically rotate to point in the direction of the Path?
|
|
*
|
|
* @name Phaser.GameObjects.Components.PathFollower#rotateToPath
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.0.0
|
|
*/
|
|
rotateToPath: false,
|
|
|
|
/**
|
|
* If the PathFollower is rotating to match the Path (@see Phaser.GameObjects.PathFollower#rotateToPath)
|
|
* this value is added to the rotation value. This allows you to rotate objects to a path but control
|
|
* the angle of the rotation as well.
|
|
*
|
|
* @name Phaser.GameObjects.PathFollower#pathRotationOffset
|
|
* @type {number}
|
|
* @default 0
|
|
* @since 3.0.0
|
|
*/
|
|
pathRotationOffset: 0,
|
|
|
|
/**
|
|
* An additional vector to add to the PathFollowers position, allowing you to offset it from the
|
|
* Path coordinates.
|
|
*
|
|
* @name Phaser.GameObjects.PathFollower#pathOffset
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.0.0
|
|
*/
|
|
pathOffset: null,
|
|
|
|
/**
|
|
* A Vector2 that stores the current point of the path the follower is on.
|
|
*
|
|
* @name Phaser.GameObjects.PathFollower#pathVector
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.0.0
|
|
*/
|
|
pathVector: null,
|
|
|
|
/**
|
|
* The distance the follower has traveled from the previous point to the current one, at the last update.
|
|
*
|
|
* @name Phaser.GameObjects.PathFollower#pathDelta
|
|
* @type {Phaser.Math.Vector2}
|
|
* @since 3.23.0
|
|
*/
|
|
pathDelta: null,
|
|
|
|
/**
|
|
* The Tween used for following the Path.
|
|
*
|
|
* @name Phaser.GameObjects.PathFollower#pathTween
|
|
* @type {Phaser.Tweens.Tween}
|
|
* @since 3.0.0
|
|
*/
|
|
pathTween: null,
|
|
|
|
/**
|
|
* Settings for the PathFollower.
|
|
*
|
|
* @name Phaser.GameObjects.PathFollower#pathConfig
|
|
* @type {?Phaser.Types.GameObjects.PathFollower.PathConfig}
|
|
* @default null
|
|
* @since 3.0.0
|
|
*/
|
|
pathConfig: null,
|
|
|
|
/**
|
|
* Records the direction of the follower so it can change direction.
|
|
*
|
|
* @name Phaser.GameObjects.PathFollower#_prevDirection
|
|
* @type {number}
|
|
* @private
|
|
* @since 3.0.0
|
|
*/
|
|
_prevDirection: TWEEN_CONST.PLAYING_FORWARD,
|
|
|
|
/**
|
|
* Set the Path that this PathFollower should follow.
|
|
*
|
|
* Optionally accepts {@link Phaser.Types.GameObjects.PathFollower.PathConfig} settings.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#setPath
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Curves.Path} path - The Path this PathFollower is following. It can only follow one Path at a time.
|
|
* @param {(number|Phaser.Types.GameObjects.PathFollower.PathConfig|Phaser.Types.Tweens.NumberTweenBuilderConfig)} [config] - Settings for the PathFollower.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setPath: function (path, config)
|
|
{
|
|
if (config === undefined) { config = this.pathConfig; }
|
|
|
|
var tween = this.pathTween;
|
|
|
|
if (tween && tween.isPlaying())
|
|
{
|
|
tween.stop();
|
|
}
|
|
|
|
this.path = path;
|
|
|
|
if (config)
|
|
{
|
|
this.startFollow(config);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Set whether the PathFollower should automatically rotate to point in the direction of the Path.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#setRotateToPath
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} value - Whether the PathFollower should automatically rotate to point in the direction of the Path.
|
|
* @param {number} [offset=0] - Rotation offset in degrees.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
setRotateToPath: function (value, offset)
|
|
{
|
|
if (offset === undefined) { offset = 0; }
|
|
|
|
this.rotateToPath = value;
|
|
|
|
this.pathRotationOffset = offset;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Is this PathFollower actively following a Path or not?
|
|
*
|
|
* To be considered as `isFollowing` it must be currently moving on a Path, and not paused.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#isFollowing
|
|
* @since 3.0.0
|
|
*
|
|
* @return {boolean} `true` is this PathFollower is actively following a Path, otherwise `false`.
|
|
*/
|
|
isFollowing: function ()
|
|
{
|
|
var tween = this.pathTween;
|
|
|
|
return (tween && tween.isPlaying());
|
|
},
|
|
|
|
/**
|
|
* Starts this PathFollower following its given Path.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#startFollow
|
|
* @since 3.3.0
|
|
*
|
|
* @param {(number|Phaser.Types.GameObjects.PathFollower.PathConfig|Phaser.Types.Tweens.NumberTweenBuilderConfig)} [config={}] - The duration of the follow, or a PathFollower config object.
|
|
* @param {number} [startAt=0] - Optional start position of the follow, between 0 and 1.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
startFollow: function (config, startAt)
|
|
{
|
|
if (config === undefined) { config = {}; }
|
|
if (startAt === undefined) { startAt = 0; }
|
|
|
|
var tween = this.pathTween;
|
|
|
|
if (tween && tween.isPlaying())
|
|
{
|
|
tween.stop();
|
|
}
|
|
|
|
if (typeof config === 'number')
|
|
{
|
|
config = { duration: config };
|
|
}
|
|
|
|
// Override in case they've been specified in the config
|
|
config.from = GetValue(config, 'from', 0);
|
|
config.to = GetValue(config, 'to', 1);
|
|
|
|
var positionOnPath = GetBoolean(config, 'positionOnPath', false);
|
|
|
|
this.rotateToPath = GetBoolean(config, 'rotateToPath', false);
|
|
this.pathRotationOffset = GetValue(config, 'rotationOffset', 0);
|
|
|
|
// This works, but it's not an ideal way of doing it as the follower jumps position
|
|
var seek = GetValue(config, 'startAt', startAt);
|
|
|
|
if (seek)
|
|
{
|
|
config.onStart = function (tween)
|
|
{
|
|
var tweenData = tween.data[0];
|
|
tweenData.progress = seek;
|
|
tweenData.elapsed = tweenData.duration * seek;
|
|
var v = tweenData.ease(tweenData.progress);
|
|
tweenData.current = tweenData.start + ((tweenData.end - tweenData.start) * v);
|
|
tweenData.setTargetValue();
|
|
};
|
|
}
|
|
|
|
if (!this.pathOffset)
|
|
{
|
|
this.pathOffset = new Vector2(this.x, this.y);
|
|
}
|
|
|
|
if (!this.pathVector)
|
|
{
|
|
this.pathVector = new Vector2();
|
|
}
|
|
|
|
if (!this.pathDelta)
|
|
{
|
|
this.pathDelta = new Vector2();
|
|
}
|
|
|
|
this.pathDelta.reset();
|
|
|
|
config.persist = true;
|
|
|
|
this.pathTween = this.scene.sys.tweens.addCounter(config);
|
|
|
|
// The starting point of the path, relative to this follower
|
|
this.path.getStartPoint(this.pathOffset);
|
|
|
|
if (positionOnPath)
|
|
{
|
|
this.x = this.pathOffset.x;
|
|
this.y = this.pathOffset.y;
|
|
}
|
|
|
|
this.pathOffset.x = this.x - this.pathOffset.x;
|
|
this.pathOffset.y = this.y - this.pathOffset.y;
|
|
|
|
this._prevDirection = TWEEN_CONST.PLAYING_FORWARD;
|
|
|
|
if (this.rotateToPath)
|
|
{
|
|
// Set the rotation now (in case the tween has a delay on it, etc)
|
|
var nextPoint = this.path.getPoint(0.1);
|
|
|
|
this.rotation = Math.atan2(nextPoint.y - this.y, nextPoint.x - this.x) + DegToRad(this.pathRotationOffset);
|
|
}
|
|
|
|
this.pathConfig = config;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Pauses this PathFollower. It will still continue to render, but it will remain motionless at the
|
|
* point on the Path at which you paused it.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#pauseFollow
|
|
* @since 3.3.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
pauseFollow: function ()
|
|
{
|
|
var tween = this.pathTween;
|
|
|
|
if (tween && tween.isPlaying())
|
|
{
|
|
tween.pause();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Resumes a previously paused PathFollower.
|
|
*
|
|
* If the PathFollower was not paused this has no effect.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#resumeFollow
|
|
* @since 3.3.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
resumeFollow: function ()
|
|
{
|
|
var tween = this.pathTween;
|
|
|
|
if (tween && tween.isPaused())
|
|
{
|
|
tween.resume();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Stops this PathFollower from following the path any longer.
|
|
*
|
|
* This will invoke any 'stop' conditions that may exist on the Path, or for the follower.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#stopFollow
|
|
* @since 3.3.0
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
stopFollow: function ()
|
|
{
|
|
var tween = this.pathTween;
|
|
|
|
if (tween && tween.isPlaying())
|
|
{
|
|
tween.stop();
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Internal update handler that advances this PathFollower along the path.
|
|
*
|
|
* Called automatically by the Scene step, should not typically be called directly.
|
|
*
|
|
* @method Phaser.GameObjects.Components.PathFollower#pathUpdate
|
|
* @since 3.17.0
|
|
*/
|
|
pathUpdate: function ()
|
|
{
|
|
var tween = this.pathTween;
|
|
|
|
if (tween)
|
|
{
|
|
var tweenData = tween.data[0];
|
|
var pathDelta = this.pathDelta;
|
|
var pathVector = this.pathVector;
|
|
|
|
pathDelta.copy(pathVector).negate();
|
|
|
|
if (tweenData.state === TWEEN_CONST.COMPLETE)
|
|
{
|
|
this.path.getPoint(tweenData.end, pathVector);
|
|
|
|
pathDelta.add(pathVector);
|
|
pathVector.add(this.pathOffset);
|
|
|
|
this.setPosition(pathVector.x, pathVector.y);
|
|
|
|
return;
|
|
}
|
|
else if (tweenData.state !== TWEEN_CONST.PLAYING_FORWARD && tweenData.state !== TWEEN_CONST.PLAYING_BACKWARD)
|
|
{
|
|
// If delayed, etc then bail out
|
|
return;
|
|
}
|
|
|
|
this.path.getPoint(tween.getValue(), pathVector);
|
|
|
|
pathDelta.add(pathVector);
|
|
pathVector.add(this.pathOffset);
|
|
|
|
var oldX = this.x;
|
|
var oldY = this.y;
|
|
|
|
this.setPosition(pathVector.x, pathVector.y);
|
|
|
|
var speedX = this.x - oldX;
|
|
var speedY = this.y - oldY;
|
|
|
|
if (speedX === 0 && speedY === 0)
|
|
{
|
|
// Bail out early
|
|
return;
|
|
}
|
|
|
|
if (tweenData.state !== this._prevDirection)
|
|
{
|
|
// We've changed direction, so don't do a rotate this frame
|
|
this._prevDirection = tweenData.state;
|
|
|
|
return;
|
|
}
|
|
|
|
if (this.rotateToPath)
|
|
{
|
|
this.rotation = Math.atan2(speedY, speedX) + DegToRad(this.pathRotationOffset);
|
|
}
|
|
}
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = PathFollower;
|
|
|
|
|
|
/***/ }),
|
|
/* 335 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Retrieves the value of the given key from an object.
|
|
*
|
|
* @function Phaser.Tweens.Builders.GetBoolean
|
|
* @since 3.0.0
|
|
*
|
|
* @param {object} source - The object to retrieve the value from.
|
|
* @param {string} key - The key to look for in the `source` object.
|
|
* @param {boolean} defaultValue - The default value to return if the `key` doesn't exist or if no `source` object is provided.
|
|
*
|
|
* @return {boolean} The retrieved value.
|
|
*/
|
|
var GetBoolean = function (source, key, defaultValue)
|
|
{
|
|
if (!source)
|
|
{
|
|
return defaultValue;
|
|
}
|
|
else if (source.hasOwnProperty(key))
|
|
{
|
|
return source[key];
|
|
}
|
|
else
|
|
{
|
|
return defaultValue;
|
|
}
|
|
};
|
|
|
|
module.exports = GetBoolean;
|
|
|
|
|
|
/***/ }),
|
|
/* 336 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Phaser Tween States.
|
|
*
|
|
* @namespace Phaser.Tweens.States
|
|
* @memberof Phaser.Tweens
|
|
* @since 3.60.0
|
|
*/
|
|
|
|
/**
|
|
* Phaser Tween state constants.
|
|
*
|
|
* @typedef {Phaser.Tweens.States} Phaser.Tweens.StateType
|
|
* @memberof Phaser.Tweens
|
|
* @since 3.60.0
|
|
*/
|
|
|
|
var TWEEN_CONST = {
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.CREATED
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
CREATED: 0,
|
|
|
|
// 1 used to be INIT prior to 3.60
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.DELAY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
DELAY: 2,
|
|
|
|
// 3 used to be OFFSET_DELAY prior to 3.60
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.PENDING_RENDER
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
PENDING_RENDER: 4,
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.PLAYING_FORWARD
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
PLAYING_FORWARD: 5,
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.PLAYING_BACKWARD
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
PLAYING_BACKWARD: 6,
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.HOLD_DELAY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
HOLD_DELAY: 7,
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.REPEAT_DELAY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
REPEAT_DELAY: 8,
|
|
|
|
/**
|
|
* TweenData state.
|
|
*
|
|
* @name Phaser.Tweens.States.COMPLETE
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
COMPLETE: 9,
|
|
|
|
// Tween specific (starts from 20 to cleanly allow extra TweenData consts in the future)
|
|
|
|
/**
|
|
* Tween state. The Tween has been created but has not yet been added to the Tween Manager.
|
|
*
|
|
* @name Phaser.Tweens.States.PENDING
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
PENDING: 20,
|
|
|
|
/**
|
|
* Tween state. The Tween is active within the Tween Manager. This means it is either playing,
|
|
* or was playing and is currently paused, but in both cases it's still being processed by
|
|
* the Tween Manager, so is considered 'active'.
|
|
*
|
|
* @name Phaser.Tweens.States.ACTIVE
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
ACTIVE: 21,
|
|
|
|
/**
|
|
* Tween state. The Tween is waiting for a loop countdown to elapse.
|
|
*
|
|
* @name Phaser.Tweens.States.LOOP_DELAY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
LOOP_DELAY: 22,
|
|
|
|
/**
|
|
* Tween state. The Tween is waiting for a complete delay to elapse.
|
|
*
|
|
* @name Phaser.Tweens.States.COMPLETE_DELAY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
COMPLETE_DELAY: 23,
|
|
|
|
/**
|
|
* Tween state. The Tween is waiting for a starting delay to elapse.
|
|
*
|
|
* @name Phaser.Tweens.States.START_DELAY
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
START_DELAY: 24,
|
|
|
|
/**
|
|
* Tween state. The Tween has finished playback and is waiting to be removed from the Tween Manager.
|
|
*
|
|
* @name Phaser.Tweens.States.PENDING_REMOVE
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
PENDING_REMOVE: 25,
|
|
|
|
/**
|
|
* Tween state. The Tween has been removed from the Tween Manager.
|
|
*
|
|
* @name Phaser.Tweens.States.REMOVED
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.0.0
|
|
*/
|
|
REMOVED: 26,
|
|
|
|
/**
|
|
* Tween state. The Tween has finished playback but was flagged as 'persistent' during creation,
|
|
* so will not be automatically removed by the Tween Manager.
|
|
*
|
|
* @name Phaser.Tweens.States.FINISHED
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.60.0
|
|
*/
|
|
FINISHED: 27,
|
|
|
|
/**
|
|
* Tween state. The Tween has been destroyed and can no longer be played by a Tween Manager.
|
|
*
|
|
* @name Phaser.Tweens.States.DESTROYED
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.60.0
|
|
*/
|
|
DESTROYED: 28,
|
|
|
|
/**
|
|
* A large integer value used for 'infinite' style countdowns.
|
|
*
|
|
* Similar use-case to Number.MAX_SAFE_INTEGER but we cannot use that because it's not
|
|
* supported on IE.
|
|
*
|
|
* @name Phaser.Tweens.States.MAX
|
|
* @type {number}
|
|
* @const
|
|
* @since 3.60.0
|
|
*/
|
|
MAX: 999999999999
|
|
|
|
};
|
|
|
|
module.exports = TWEEN_CONST;
|
|
|
|
|
|
/***/ }),
|
|
/* 337 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var DeepCopy = __webpack_require__(338);
|
|
var SpliceOne = __webpack_require__(13);
|
|
|
|
/**
|
|
* Provides methods used for setting the WebGL rendering pipeline of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Pipeline
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Pipeline = {
|
|
|
|
/**
|
|
* The initial WebGL pipeline of this Game Object.
|
|
*
|
|
* If you call `resetPipeline` on this Game Object, the pipeline is reset to this default.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Pipeline#defaultPipeline
|
|
* @type {Phaser.Renderer.WebGL.WebGLPipeline}
|
|
* @default null
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
defaultPipeline: null,
|
|
|
|
/**
|
|
* The current WebGL pipeline of this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Pipeline#pipeline
|
|
* @type {Phaser.Renderer.WebGL.WebGLPipeline}
|
|
* @default null
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
pipeline: null,
|
|
|
|
/**
|
|
* Does this Game Object have any Post Pipelines set?
|
|
*
|
|
* @name Phaser.GameObjects.Components.Pipeline#hasPostPipeline
|
|
* @type {boolean}
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*/
|
|
hasPostPipeline: false,
|
|
|
|
/**
|
|
* The WebGL Post FX Pipelines this Game Object uses for post-render effects.
|
|
*
|
|
* The pipelines are processed in the order in which they appear in this array.
|
|
*
|
|
* If you modify this array directly, be sure to set the
|
|
* `hasPostPipeline` property accordingly.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Pipeline#postPipelines
|
|
* @type {Phaser.Renderer.WebGL.Pipelines.PostFXPipeline[]}
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*/
|
|
postPipelines: null,
|
|
|
|
/**
|
|
* An object to store pipeline specific data in, to be read by the pipelines this Game Object uses.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Pipeline#pipelineData
|
|
* @type {object}
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*/
|
|
pipelineData: null,
|
|
|
|
/**
|
|
* Sets the initial WebGL Pipeline of this Game Object.
|
|
*
|
|
* This should only be called during the instantiation of the Game Object. After that, use `setPipeline`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#initPipeline
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|Phaser.Renderer.WebGL.WebGLPipeline)} [pipeline] - Either the string-based name of the pipeline, or a pipeline instance to set.
|
|
*
|
|
* @return {boolean} `true` if the pipeline was set successfully, otherwise `false`.
|
|
*/
|
|
initPipeline: function (pipeline)
|
|
{
|
|
var renderer = this.scene.sys.renderer;
|
|
|
|
if (!renderer)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
var pipelines = renderer.pipelines;
|
|
|
|
this.postPipelines = [];
|
|
this.pipelineData = {};
|
|
|
|
if (pipelines)
|
|
{
|
|
if (pipeline === undefined)
|
|
{
|
|
pipeline = pipelines.default;
|
|
}
|
|
|
|
var instance = pipelines.get(pipeline);
|
|
|
|
if (instance)
|
|
{
|
|
this.defaultPipeline = instance;
|
|
this.pipeline = instance;
|
|
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
},
|
|
|
|
/**
|
|
* Sets the main WebGL Pipeline of this Game Object.
|
|
*
|
|
* Also sets the `pipelineData` property, if the parameter is given.
|
|
*
|
|
* Both the pipeline and post pipelines share the same pipeline data object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#setPipeline
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|Phaser.Renderer.WebGL.WebGLPipeline)} pipeline - Either the string-based name of the pipeline, or a pipeline instance to set.
|
|
* @param {object} [pipelineData] - Optional pipeline data object that is _deep copied_ into the `pipelineData` property of this Game Object.
|
|
* @param {boolean} [copyData=true] - Should the pipeline data object be _deep copied_ into the `pipelineData` property of this Game Object? If `false` it will be set by reference instead.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setPipeline: function (pipeline, pipelineData, copyData)
|
|
{
|
|
var renderer = this.scene.sys.renderer;
|
|
|
|
if (!renderer)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
var pipelines = renderer.pipelines;
|
|
|
|
if (pipelines)
|
|
{
|
|
var instance = pipelines.get(pipeline);
|
|
|
|
if (instance)
|
|
{
|
|
this.pipeline = instance;
|
|
}
|
|
|
|
if (pipelineData)
|
|
{
|
|
this.pipelineData = (copyData) ? DeepCopy(pipelineData) : pipelineData;
|
|
}
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets one, or more, Post Pipelines on this Game Object.
|
|
*
|
|
* Post Pipelines are invoked after this Game Object has rendered to its target and
|
|
* are commonly used for post-fx.
|
|
*
|
|
* The post pipelines are appended to the `postPipelines` array belonging to this
|
|
* Game Object. When the renderer processes this Game Object, it iterates through the post
|
|
* pipelines in the order in which they appear in the array. If you are stacking together
|
|
* multiple effects, be aware that the order is important.
|
|
*
|
|
* If you call this method multiple times, the new pipelines will be appended to any existing
|
|
* post pipelines already set. Use the `resetPostPipeline` method to clear them first, if required.
|
|
*
|
|
* You can optionally also set the `pipelineData` property, if the parameter is given.
|
|
*
|
|
* Both the pipeline and post pipelines share the pipeline data object together.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#setPostPipeline
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*
|
|
* @param {(string|string[]|function|function[]|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline[])} pipelines - Either the string-based name of the pipeline, or a pipeline instance, or class, or an array of them.
|
|
* @param {object} [pipelineData] - Optional pipeline data object that is _deep copied_ into the `pipelineData` property of this Game Object.
|
|
* @param {boolean} [copyData=true] - Should the pipeline data object be _deep copied_ into the `pipelineData` property of this Game Object? If `false` it will be set by reference instead.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setPostPipeline: function (pipelines, pipelineData, copyData)
|
|
{
|
|
var renderer = this.scene.sys.renderer;
|
|
|
|
if (!renderer)
|
|
{
|
|
return this;
|
|
}
|
|
|
|
var pipelineManager = renderer.pipelines;
|
|
|
|
if (pipelineManager)
|
|
{
|
|
if (!Array.isArray(pipelines))
|
|
{
|
|
pipelines = [ pipelines ];
|
|
}
|
|
|
|
for (var i = 0; i < pipelines.length; i++)
|
|
{
|
|
var instance = pipelineManager.getPostPipeline(pipelines[i], this);
|
|
|
|
if (instance)
|
|
{
|
|
this.postPipelines.push(instance);
|
|
}
|
|
}
|
|
|
|
if (pipelineData)
|
|
{
|
|
this.pipelineData = (copyData) ? DeepCopy(pipelineData) : pipelineData;
|
|
}
|
|
}
|
|
|
|
this.hasPostPipeline = (this.postPipelines.length > 0);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Adds an entry to the `pipelineData` object belonging to this Game Object.
|
|
*
|
|
* If the 'key' already exists, its value is updated. If it doesn't exist, it is created.
|
|
*
|
|
* If `value` is undefined, and `key` exists, `key` is removed from the data object.
|
|
*
|
|
* Both the pipeline and post pipelines share the pipeline data object together.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#setPipelineData
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*
|
|
* @param {string} key - The key of the pipeline data to set, update, or delete.
|
|
* @param {any} [value] - The value to be set with the key. If `undefined` then `key` will be deleted from the object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setPipelineData: function (key, value)
|
|
{
|
|
var data = this.pipelineData;
|
|
|
|
if (value === undefined)
|
|
{
|
|
delete data[key];
|
|
}
|
|
else
|
|
{
|
|
data[key] = value;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Gets a Post Pipeline instance from this Game Object, based on the given name, and returns it.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#getPostPipeline
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*
|
|
* @param {(string|function|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline)} pipeline - The string-based name of the pipeline, or a pipeline class.
|
|
*
|
|
* @return {(Phaser.Renderer.WebGL.Pipelines.PostFXPipeline|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline[])} The Post Pipeline/s matching the name, or undefined if no match. If more than one match they are returned in an array.
|
|
*/
|
|
getPostPipeline: function (pipeline)
|
|
{
|
|
var isString = (typeof pipeline === 'string');
|
|
|
|
var pipelines = this.postPipelines;
|
|
|
|
var results = [];
|
|
|
|
for (var i = 0; i < pipelines.length; i++)
|
|
{
|
|
var instance = pipelines[i];
|
|
|
|
if ((isString && instance.name === pipeline) || (!isString && instance instanceof pipeline))
|
|
{
|
|
results.push(instance);
|
|
}
|
|
}
|
|
|
|
return (results.length === 1) ? results[0] : results;
|
|
},
|
|
|
|
/**
|
|
* Resets the WebGL Pipeline of this Game Object back to the default it was created with.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#resetPipeline
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*
|
|
* @param {boolean} [resetPostPipelines=false] - Reset all of the post pipelines?
|
|
* @param {boolean} [resetData=false] - Reset the `pipelineData` object to being an empty object?
|
|
*
|
|
* @return {boolean} `true` if the pipeline was reset successfully, otherwise `false`.
|
|
*/
|
|
resetPipeline: function (resetPostPipelines, resetData)
|
|
{
|
|
if (resetPostPipelines === undefined) { resetPostPipelines = false; }
|
|
if (resetData === undefined) { resetData = false; }
|
|
|
|
this.pipeline = this.defaultPipeline;
|
|
|
|
if (resetPostPipelines)
|
|
{
|
|
this.postPipelines = [];
|
|
this.hasPostPipeline = false;
|
|
}
|
|
|
|
if (resetData)
|
|
{
|
|
this.pipelineData = {};
|
|
}
|
|
|
|
return (this.pipeline !== null);
|
|
},
|
|
|
|
/**
|
|
* Resets the WebGL Post Pipelines of this Game Object. It does this by calling
|
|
* the `destroy` method on each post pipeline and then clearing the local array.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#resetPostPipeline
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*
|
|
* @param {boolean} [resetData=false] - Reset the `pipelineData` object to being an empty object?
|
|
*/
|
|
resetPostPipeline: function (resetData)
|
|
{
|
|
if (resetData === undefined) { resetData = false; }
|
|
|
|
var pipelines = this.postPipelines;
|
|
|
|
for (var i = 0; i < pipelines.length; i++)
|
|
{
|
|
pipelines[i].destroy();
|
|
}
|
|
|
|
this.postPipelines = [];
|
|
this.hasPostPipeline = false;
|
|
|
|
if (resetData)
|
|
{
|
|
this.pipelineData = {};
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Removes a type of Post Pipeline instances from this Game Object, based on the given name, and destroys them.
|
|
*
|
|
* If you wish to remove all Post Pipelines use the `resetPostPipeline` method instead.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#removePostPipeline
|
|
* @webglOnly
|
|
* @since 3.50.0
|
|
*
|
|
* @param {string|Phaser.Renderer.WebGL.Pipelines.PostFXPipeline} pipeline - The string-based name of the pipeline, or a pipeline class.
|
|
*
|
|
* @return {this} This Game Object.
|
|
*/
|
|
removePostPipeline: function (pipeline)
|
|
{
|
|
var pipelines = this.postPipelines;
|
|
|
|
for (var i = pipelines.length - 1; i >= 0; i--)
|
|
{
|
|
var instance = pipelines[i];
|
|
|
|
if (
|
|
(typeof pipeline === 'string' && instance.name === pipeline) ||
|
|
(typeof pipeline !== 'string' && instance instanceof pipeline))
|
|
{
|
|
instance.destroy();
|
|
|
|
SpliceOne(pipelines, i);
|
|
}
|
|
}
|
|
|
|
this.hasPostPipeline = (this.postPipelines.length > 0);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Gets the name of the WebGL Pipeline this Game Object is currently using.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Pipeline#getPipelineName
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*
|
|
* @return {string} The string-based name of the pipeline being used by this Game Object.
|
|
*/
|
|
getPipelineName: function ()
|
|
{
|
|
return this.pipeline.name;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Pipeline;
|
|
|
|
|
|
/***/ }),
|
|
/* 338 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Deep Copy the given object or array.
|
|
*
|
|
* @function Phaser.Utils.Objects.DeepCopy
|
|
* @since 3.50.0
|
|
*
|
|
* @param {object} obj - The object to deep copy.
|
|
*
|
|
* @return {object} A deep copy of the original object.
|
|
*/
|
|
var DeepCopy = function (inObject)
|
|
{
|
|
var outObject;
|
|
var value;
|
|
var key;
|
|
|
|
if (typeof inObject !== 'object' || inObject === null)
|
|
{
|
|
// inObject is not an object
|
|
return inObject;
|
|
}
|
|
|
|
// Create an array or object to hold the values
|
|
outObject = Array.isArray(inObject) ? [] : {};
|
|
|
|
for (key in inObject)
|
|
{
|
|
value = inObject[key];
|
|
|
|
// Recursively (deep) copy for nested objects, including arrays
|
|
outObject[key] = DeepCopy(value);
|
|
}
|
|
|
|
return outObject;
|
|
};
|
|
|
|
module.exports = DeepCopy;
|
|
|
|
|
|
/***/ }),
|
|
/* 339 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the size of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Size
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Size = {
|
|
|
|
/**
|
|
* A property indicating that a Game Object has this component.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Size#_sizeComponent
|
|
* @type {boolean}
|
|
* @private
|
|
* @default true
|
|
* @since 3.2.0
|
|
*/
|
|
_sizeComponent: true,
|
|
|
|
/**
|
|
* The native (un-scaled) width of this Game Object.
|
|
*
|
|
* Changing this value will not change the size that the Game Object is rendered in-game.
|
|
* For that you need to either set the scale of the Game Object (`setScale`) or use
|
|
* the `displayWidth` property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Size#width
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
width: 0,
|
|
|
|
/**
|
|
* The native (un-scaled) height of this Game Object.
|
|
*
|
|
* Changing this value will not change the size that the Game Object is rendered in-game.
|
|
* For that you need to either set the scale of the Game Object (`setScale`) or use
|
|
* the `displayHeight` property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Size#height
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
height: 0,
|
|
|
|
/**
|
|
* The displayed width of this Game Object.
|
|
*
|
|
* This value takes into account the scale factor.
|
|
*
|
|
* Setting this value will adjust the Game Object's scale property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Size#displayWidth
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
displayWidth: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.abs(this.scaleX * this.frame.realWidth);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.scaleX = value / this.frame.realWidth;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* The displayed height of this Game Object.
|
|
*
|
|
* This value takes into account the scale factor.
|
|
*
|
|
* Setting this value will adjust the Game Object's scale property.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Size#displayHeight
|
|
* @type {number}
|
|
* @since 3.0.0
|
|
*/
|
|
displayHeight: {
|
|
|
|
get: function ()
|
|
{
|
|
return Math.abs(this.scaleY * this.frame.realHeight);
|
|
},
|
|
|
|
set: function (value)
|
|
{
|
|
this.scaleY = value / this.frame.realHeight;
|
|
}
|
|
|
|
},
|
|
|
|
/**
|
|
* Sets the size of this Game Object to be that of the given Frame.
|
|
*
|
|
* This will not change the size that the Game Object is rendered in-game.
|
|
* For that you need to either set the scale of the Game Object (`setScale`) or call the
|
|
* `setDisplaySize` method, which is the same thing as changing the scale but allows you
|
|
* to do so by giving pixel values.
|
|
*
|
|
* If you have enabled this Game Object for input, changing the size will _not_ change the
|
|
* size of the hit area. To do this you should adjust the `input.hitArea` object directly.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Size#setSizeToFrame
|
|
* @since 3.0.0
|
|
*
|
|
* @param {Phaser.Textures.Frame} frame - The frame to base the size of this Game Object on.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setSizeToFrame: function (frame)
|
|
{
|
|
if (frame === undefined) { frame = this.frame; }
|
|
|
|
this.width = frame.realWidth;
|
|
this.height = frame.realHeight;
|
|
|
|
var input = this.input;
|
|
|
|
if (input && !input.customHitArea)
|
|
{
|
|
input.hitArea.width = this.width;
|
|
input.hitArea.height = this.height;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the internal size of this Game Object, as used for frame or physics body creation.
|
|
*
|
|
* This will not change the size that the Game Object is rendered in-game.
|
|
* For that you need to either set the scale of the Game Object (`setScale`) or call the
|
|
* `setDisplaySize` method, which is the same thing as changing the scale but allows you
|
|
* to do so by giving pixel values.
|
|
*
|
|
* If you have enabled this Game Object for input, changing the size will _not_ change the
|
|
* size of the hit area. To do this you should adjust the `input.hitArea` object directly.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Size#setSize
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} width - The width of this Game Object.
|
|
* @param {number} height - The height of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setSize: function (width, height)
|
|
{
|
|
this.width = width;
|
|
this.height = height;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the display size of this Game Object.
|
|
*
|
|
* Calling this will adjust the scale.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Size#setDisplaySize
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} width - The width of this Game Object.
|
|
* @param {number} height - The height of this Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setDisplaySize: function (width, height)
|
|
{
|
|
this.displayWidth = width;
|
|
this.displayHeight = height;
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Size;
|
|
|
|
|
|
/***/ }),
|
|
/* 340 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Frame = __webpack_require__(68);
|
|
|
|
// bitmask flag for GameObject.renderMask
|
|
var _FLAG = 8; // 1000
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the texture of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Texture
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Texture = {
|
|
|
|
/**
|
|
* The Texture this Game Object is using to render with.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Texture#texture
|
|
* @type {Phaser.Textures.Texture|Phaser.Textures.CanvasTexture}
|
|
* @since 3.0.0
|
|
*/
|
|
texture: null,
|
|
|
|
/**
|
|
* The Texture Frame this Game Object is using to render with.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Texture#frame
|
|
* @type {Phaser.Textures.Frame}
|
|
* @since 3.0.0
|
|
*/
|
|
frame: null,
|
|
|
|
/**
|
|
* Internal flag. Not to be set by this Game Object.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Texture#isCropped
|
|
* @type {boolean}
|
|
* @private
|
|
* @since 3.11.0
|
|
*/
|
|
isCropped: false,
|
|
|
|
/**
|
|
* Sets the texture and frame this Game Object will use to render with.
|
|
*
|
|
* Textures are referenced by their string-based keys, as stored in the Texture Manager.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Texture#setTexture
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|Phaser.Textures.Texture)} key - The key of the texture to be used, as stored in the Texture Manager, or a Texture instance.
|
|
* @param {(string|number)} [frame] - The name or index of the frame within the Texture.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setTexture: function (key, frame)
|
|
{
|
|
this.texture = this.scene.sys.textures.get(key);
|
|
|
|
return this.setFrame(frame);
|
|
},
|
|
|
|
/**
|
|
* Sets the frame this Game Object will use to render with.
|
|
*
|
|
* If you pass a string or index then the Frame has to belong to the current Texture being used
|
|
* by this Game Object.
|
|
*
|
|
* If you pass a Frame instance, then the Texture being used by this Game Object will also be updated.
|
|
*
|
|
* Calling `setFrame` will modify the `width` and `height` properties of your Game Object.
|
|
*
|
|
* It will also change the `origin` if the Frame has a custom pivot point, as exported from packages like Texture Packer.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Texture#setFrame
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|number|Phaser.Textures.Frame)} frame - The name or index of the frame within the Texture, or a Frame instance.
|
|
* @param {boolean} [updateSize=true] - Should this call adjust the size of the Game Object?
|
|
* @param {boolean} [updateOrigin=true] - Should this call adjust the origin of the Game Object?
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setFrame: function (frame, updateSize, updateOrigin)
|
|
{
|
|
if (updateSize === undefined) { updateSize = true; }
|
|
if (updateOrigin === undefined) { updateOrigin = true; }
|
|
|
|
if (frame instanceof Frame)
|
|
{
|
|
this.texture = this.scene.sys.textures.get(frame.texture.key);
|
|
|
|
this.frame = frame;
|
|
}
|
|
else
|
|
{
|
|
this.frame = this.texture.get(frame);
|
|
}
|
|
|
|
if (!this.frame.cutWidth || !this.frame.cutHeight)
|
|
{
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
|
|
if (this._sizeComponent && updateSize)
|
|
{
|
|
this.setSizeToFrame();
|
|
}
|
|
|
|
if (this._originComponent && updateOrigin)
|
|
{
|
|
if (this.frame.customPivot)
|
|
{
|
|
this.setOrigin(this.frame.pivotX, this.frame.pivotY);
|
|
}
|
|
else
|
|
{
|
|
this.updateDisplayOrigin();
|
|
}
|
|
}
|
|
|
|
return this;
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Texture;
|
|
|
|
|
|
/***/ }),
|
|
/* 341 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Frame = __webpack_require__(68);
|
|
|
|
// bitmask flag for GameObject.renderMask
|
|
var _FLAG = 8; // 1000
|
|
|
|
/**
|
|
* Provides methods used for getting and setting the texture of a Game Object.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.TextureCrop
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var TextureCrop = {
|
|
|
|
/**
|
|
* The Texture this Game Object is using to render with.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TextureCrop#texture
|
|
* @type {Phaser.Textures.Texture|Phaser.Textures.CanvasTexture}
|
|
* @since 3.0.0
|
|
*/
|
|
texture: null,
|
|
|
|
/**
|
|
* The Texture Frame this Game Object is using to render with.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TextureCrop#frame
|
|
* @type {Phaser.Textures.Frame}
|
|
* @since 3.0.0
|
|
*/
|
|
frame: null,
|
|
|
|
/**
|
|
* A boolean flag indicating if this Game Object is being cropped or not.
|
|
* You can toggle this at any time after `setCrop` has been called, to turn cropping on or off.
|
|
* Equally, calling `setCrop` with no arguments will reset the crop and disable it.
|
|
*
|
|
* @name Phaser.GameObjects.Components.TextureCrop#isCropped
|
|
* @type {boolean}
|
|
* @since 3.11.0
|
|
*/
|
|
isCropped: false,
|
|
|
|
/**
|
|
* Applies a crop to a texture based Game Object, such as a Sprite or Image.
|
|
*
|
|
* The crop is a rectangle that limits the area of the texture frame that is visible during rendering.
|
|
*
|
|
* Cropping a Game Object does not change its size, dimensions, physics body or hit area, it just
|
|
* changes what is shown when rendered.
|
|
*
|
|
* The crop coordinates are relative to the texture frame, not the Game Object, meaning 0 x 0 is the top-left.
|
|
*
|
|
* Therefore, if you had a Game Object that had an 800x600 sized texture, and you wanted to show only the left
|
|
* half of it, you could call `setCrop(0, 0, 400, 600)`.
|
|
*
|
|
* It is also scaled to match the Game Object scale automatically. Therefore a crop rect of 100x50 would crop
|
|
* an area of 200x100 when applied to a Game Object that had a scale factor of 2.
|
|
*
|
|
* You can either pass in numeric values directly, or you can provide a single Rectangle object as the first argument.
|
|
*
|
|
* Call this method with no arguments at all to reset the crop, or toggle the property `isCropped` to `false`.
|
|
*
|
|
* You should do this if the crop rectangle becomes the same size as the frame itself, as it will allow
|
|
* the renderer to skip several internal calculations.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TextureCrop#setCrop
|
|
* @since 3.11.0
|
|
*
|
|
* @param {(number|Phaser.Geom.Rectangle)} [x] - The x coordinate to start the crop from. Or a Phaser.Geom.Rectangle object, in which case the rest of the arguments are ignored.
|
|
* @param {number} [y] - The y coordinate to start the crop from.
|
|
* @param {number} [width] - The width of the crop rectangle in pixels.
|
|
* @param {number} [height] - The height of the crop rectangle in pixels.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setCrop: function (x, y, width, height)
|
|
{
|
|
if (x === undefined)
|
|
{
|
|
this.isCropped = false;
|
|
}
|
|
else if (this.frame)
|
|
{
|
|
if (typeof x === 'number')
|
|
{
|
|
this.frame.setCropUVs(this._crop, x, y, width, height, this.flipX, this.flipY);
|
|
}
|
|
else
|
|
{
|
|
var rect = x;
|
|
|
|
this.frame.setCropUVs(this._crop, rect.x, rect.y, rect.width, rect.height, this.flipX, this.flipY);
|
|
}
|
|
|
|
this.isCropped = true;
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets the texture and frame this Game Object will use to render with.
|
|
*
|
|
* Textures are referenced by their string-based keys, as stored in the Texture Manager.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TextureCrop#setTexture
|
|
* @since 3.0.0
|
|
*
|
|
* @param {string} key - The key of the texture to be used, as stored in the Texture Manager.
|
|
* @param {(string|number)} [frame] - The name or index of the frame within the Texture.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setTexture: function (key, frame)
|
|
{
|
|
this.texture = this.scene.sys.textures.get(key);
|
|
|
|
return this.setFrame(frame);
|
|
},
|
|
|
|
/**
|
|
* Sets the frame this Game Object will use to render with.
|
|
*
|
|
* If you pass a string or index then the Frame has to belong to the current Texture being used
|
|
* by this Game Object.
|
|
*
|
|
* If you pass a Frame instance, then the Texture being used by this Game Object will also be updated.
|
|
*
|
|
* Calling `setFrame` will modify the `width` and `height` properties of your Game Object.
|
|
*
|
|
* It will also change the `origin` if the Frame has a custom pivot point, as exported from packages like Texture Packer.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TextureCrop#setFrame
|
|
* @since 3.0.0
|
|
*
|
|
* @param {(string|number|Phaser.Textures.Frame)} frame - The name or index of the frame within the Texture, or a Frame instance.
|
|
* @param {boolean} [updateSize=true] - Should this call adjust the size of the Game Object?
|
|
* @param {boolean} [updateOrigin=true] - Should this call adjust the origin of the Game Object?
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setFrame: function (frame, updateSize, updateOrigin)
|
|
{
|
|
if (updateSize === undefined) { updateSize = true; }
|
|
if (updateOrigin === undefined) { updateOrigin = true; }
|
|
|
|
if (frame instanceof Frame)
|
|
{
|
|
this.texture = this.scene.sys.textures.get(frame.texture.key);
|
|
|
|
this.frame = frame;
|
|
}
|
|
else
|
|
{
|
|
this.frame = this.texture.get(frame);
|
|
}
|
|
|
|
if (!this.frame.cutWidth || !this.frame.cutHeight)
|
|
{
|
|
this.renderFlags &= ~_FLAG;
|
|
}
|
|
else
|
|
{
|
|
this.renderFlags |= _FLAG;
|
|
}
|
|
|
|
if (this._sizeComponent && updateSize)
|
|
{
|
|
this.setSizeToFrame();
|
|
}
|
|
|
|
if (this._originComponent && updateOrigin)
|
|
{
|
|
if (this.frame.customPivot)
|
|
{
|
|
this.setOrigin(this.frame.pivotX, this.frame.pivotY);
|
|
}
|
|
else
|
|
{
|
|
this.updateDisplayOrigin();
|
|
}
|
|
}
|
|
|
|
if (this.isCropped)
|
|
{
|
|
this.frame.updateCropUVs(this._crop, this.flipX, this.flipY);
|
|
}
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Internal method that returns a blank, well-formed crop object for use by a Game Object.
|
|
*
|
|
* @method Phaser.GameObjects.Components.TextureCrop#resetCropObject
|
|
* @private
|
|
* @since 3.12.0
|
|
*
|
|
* @return {object} The crop object.
|
|
*/
|
|
resetCropObject: function ()
|
|
{
|
|
return { u0: 0, v0: 0, u1: 0, v1: 0, width: 0, height: 0, x: 0, y: 0, flipX: false, flipY: false, cx: 0, cy: 0, cw: 0, ch: 0 };
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = TextureCrop;
|
|
|
|
|
|
/***/ }),
|
|
/* 342 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Provides methods used for setting the tint of a Game Object.
|
|
* Should be applied as a mixin and not used directly.
|
|
*
|
|
* @namespace Phaser.GameObjects.Components.Tint
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
|
|
var Tint = {
|
|
|
|
/**
|
|
* The tint value being applied to the top-left vertice of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
* The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Tint#tintTopLeft
|
|
* @type {number}
|
|
* @default 0xffffff
|
|
* @since 3.0.0
|
|
*/
|
|
tintTopLeft: 0xffffff,
|
|
|
|
/**
|
|
* The tint value being applied to the top-right vertice of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
* The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Tint#tintTopRight
|
|
* @type {number}
|
|
* @default 0xffffff
|
|
* @since 3.0.0
|
|
*/
|
|
tintTopRight: 0xffffff,
|
|
|
|
/**
|
|
* The tint value being applied to the bottom-left vertice of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
* The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Tint#tintBottomLeft
|
|
* @type {number}
|
|
* @default 0xffffff
|
|
* @since 3.0.0
|
|
*/
|
|
tintBottomLeft: 0xffffff,
|
|
|
|
/**
|
|
* The tint value being applied to the bottom-right vertice of the Game Object.
|
|
* This value is interpolated from the corner to the center of the Game Object.
|
|
* The value should be set as a hex number, i.e. 0xff0000 for red, or 0xff00ff for purple.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Tint#tintBottomRight
|
|
* @type {number}
|
|
* @default 0xffffff
|
|
* @since 3.0.0
|
|
*/
|
|
tintBottomRight: 0xffffff,
|
|
|
|
/**
|
|
* The tint fill mode.
|
|
*
|
|
* `false` = An additive tint (the default), where vertices colors are blended with the texture.
|
|
* `true` = A fill tint, where the vertices colors replace the texture, but respects texture alpha.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Tint#tintFill
|
|
* @type {boolean}
|
|
* @default false
|
|
* @since 3.11.0
|
|
*/
|
|
tintFill: false,
|
|
|
|
/**
|
|
* Clears all tint values associated with this Game Object.
|
|
*
|
|
* Immediately sets the color values back to 0xffffff and the tint type to 'additive',
|
|
* which results in no visible change to the texture.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Tint#clearTint
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
clearTint: function ()
|
|
{
|
|
this.setTint(0xffffff);
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets an additive tint on this Game Object.
|
|
*
|
|
* The tint works by taking the pixel color values from the Game Objects texture, and then
|
|
* multiplying it by the color value of the tint. You can provide either one color value,
|
|
* in which case the whole Game Object will be tinted in that color. Or you can provide a color
|
|
* per corner. The colors are blended together across the extent of the Game Object.
|
|
*
|
|
* To modify the tint color once set, either call this method again with new values or use the
|
|
* `tint` property to set all colors at once. Or, use the properties `tintTopLeft`, `tintTopRight,
|
|
* `tintBottomLeft` and `tintBottomRight` to set the corner color values independently.
|
|
*
|
|
* To remove a tint call `clearTint`.
|
|
*
|
|
* To swap this from being an additive tint to a fill based tint set the property `tintFill` to `true`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Tint#setTint
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*
|
|
* @param {number} [topLeft=0xffffff] - The tint being applied to the top-left of the Game Object. If no other values are given this value is applied evenly, tinting the whole Game Object.
|
|
* @param {number} [topRight] - The tint being applied to the top-right of the Game Object.
|
|
* @param {number} [bottomLeft] - The tint being applied to the bottom-left of the Game Object.
|
|
* @param {number} [bottomRight] - The tint being applied to the bottom-right of the Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setTint: function (topLeft, topRight, bottomLeft, bottomRight)
|
|
{
|
|
if (topLeft === undefined) { topLeft = 0xffffff; }
|
|
|
|
if (topRight === undefined)
|
|
{
|
|
topRight = topLeft;
|
|
bottomLeft = topLeft;
|
|
bottomRight = topLeft;
|
|
}
|
|
|
|
this.tintTopLeft = topLeft;
|
|
this.tintTopRight = topRight;
|
|
this.tintBottomLeft = bottomLeft;
|
|
this.tintBottomRight = bottomRight;
|
|
|
|
this.tintFill = false;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* Sets a fill-based tint on this Game Object.
|
|
*
|
|
* Unlike an additive tint, a fill-tint literally replaces the pixel colors from the texture
|
|
* with those in the tint. You can use this for effects such as making a player flash 'white'
|
|
* if hit by something. You can provide either one color value, in which case the whole
|
|
* Game Object will be rendered in that color. Or you can provide a color per corner. The colors
|
|
* are blended together across the extent of the Game Object.
|
|
*
|
|
* To modify the tint color once set, either call this method again with new values or use the
|
|
* `tint` property to set all colors at once. Or, use the properties `tintTopLeft`, `tintTopRight,
|
|
* `tintBottomLeft` and `tintBottomRight` to set the corner color values independently.
|
|
*
|
|
* To remove a tint call `clearTint`.
|
|
*
|
|
* To swap this from being a fill-tint to an additive tint set the property `tintFill` to `false`.
|
|
*
|
|
* @method Phaser.GameObjects.Components.Tint#setTintFill
|
|
* @webglOnly
|
|
* @since 3.11.0
|
|
*
|
|
* @param {number} [topLeft=0xffffff] - The tint being applied to the top-left of the Game Object. If not other values are given this value is applied evenly, tinting the whole Game Object.
|
|
* @param {number} [topRight] - The tint being applied to the top-right of the Game Object.
|
|
* @param {number} [bottomLeft] - The tint being applied to the bottom-left of the Game Object.
|
|
* @param {number} [bottomRight] - The tint being applied to the bottom-right of the Game Object.
|
|
*
|
|
* @return {this} This Game Object instance.
|
|
*/
|
|
setTintFill: function (topLeft, topRight, bottomLeft, bottomRight)
|
|
{
|
|
this.setTint(topLeft, topRight, bottomLeft, bottomRight);
|
|
|
|
this.tintFill = true;
|
|
|
|
return this;
|
|
},
|
|
|
|
/**
|
|
* The tint value being applied to the whole of the Game Object.
|
|
* This property is a setter-only. Use the properties `tintTopLeft` etc to read the current tint value.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Tint#tint
|
|
* @type {number}
|
|
* @webglOnly
|
|
* @since 3.0.0
|
|
*/
|
|
tint: {
|
|
|
|
set: function (value)
|
|
{
|
|
this.setTint(value, value, value, value);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Does this Game Object have a tint applied?
|
|
*
|
|
* It checks to see if the 4 tint properties are set to the value 0xffffff
|
|
* and that the `tintFill` property is `false`. This indicates that a Game Object isn't tinted.
|
|
*
|
|
* @name Phaser.GameObjects.Components.Tint#isTinted
|
|
* @type {boolean}
|
|
* @webglOnly
|
|
* @readonly
|
|
* @since 3.11.0
|
|
*/
|
|
isTinted: {
|
|
|
|
get: function ()
|
|
{
|
|
var white = 0xffffff;
|
|
|
|
return (
|
|
this.tintFill ||
|
|
this.tintTopLeft !== white ||
|
|
this.tintTopRight !== white ||
|
|
this.tintBottomLeft !== white ||
|
|
this.tintBottomRight !== white
|
|
);
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
module.exports = Tint;
|
|
|
|
|
|
/***/ }),
|
|
/* 343 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author Felipe Alfonso <@bitnenfer>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var NOOP = __webpack_require__(2);
|
|
var renderWebGL = NOOP;
|
|
var renderCanvas = NOOP;
|
|
|
|
if (true)
|
|
{
|
|
renderWebGL = __webpack_require__(344);
|
|
}
|
|
|
|
if (true)
|
|
{
|
|
renderCanvas = __webpack_require__(345);
|
|
}
|
|
|
|
module.exports = {
|
|
|
|
renderWebGL: renderWebGL,
|
|
renderCanvas: renderCanvas
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 344 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author Felipe Alfonso <@bitnenfer>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Renders this Game Object with the WebGL Renderer to the given Camera.
|
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
|
* This method should not be called directly. It is a utility function of the Render module.
|
|
*
|
|
* @method Phaser.GameObjects.Container#renderWebGL
|
|
* @since 3.4.0
|
|
* @private
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
|
|
* @param {Phaser.GameObjects.Container} container - The Game Object being rendered in this call.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
|
*/
|
|
var ContainerWebGLRenderer = function (renderer, container, camera, parentMatrix)
|
|
{
|
|
camera.addToRenderList(container);
|
|
|
|
var children = container.list;
|
|
var childCount = children.length;
|
|
|
|
if (childCount === 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var transformMatrix = container.localTransform;
|
|
|
|
if (parentMatrix)
|
|
{
|
|
transformMatrix.loadIdentity();
|
|
transformMatrix.multiply(parentMatrix);
|
|
transformMatrix.translate(container.x, container.y);
|
|
transformMatrix.rotate(container.rotation);
|
|
transformMatrix.scale(container.scaleX, container.scaleY);
|
|
}
|
|
else
|
|
{
|
|
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
|
|
}
|
|
|
|
renderer.pipelines.preBatch(container);
|
|
|
|
var containerHasBlendMode = (container.blendMode !== -1);
|
|
|
|
if (!containerHasBlendMode)
|
|
{
|
|
// If Container is SKIP_TEST then set blend mode to be Normal
|
|
renderer.setBlendMode(0);
|
|
}
|
|
|
|
var alpha = container.alpha;
|
|
|
|
var scrollFactorX = container.scrollFactorX;
|
|
var scrollFactorY = container.scrollFactorY;
|
|
|
|
for (var i = 0; i < childCount; i++)
|
|
{
|
|
var child = children[i];
|
|
|
|
if (!child.willRender(camera))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var childAlphaTopLeft;
|
|
var childAlphaTopRight;
|
|
var childAlphaBottomLeft;
|
|
var childAlphaBottomRight;
|
|
|
|
if (child.alphaTopLeft !== undefined)
|
|
{
|
|
childAlphaTopLeft = child.alphaTopLeft;
|
|
childAlphaTopRight = child.alphaTopRight;
|
|
childAlphaBottomLeft = child.alphaBottomLeft;
|
|
childAlphaBottomRight = child.alphaBottomRight;
|
|
}
|
|
else
|
|
{
|
|
var childAlpha = child.alpha;
|
|
|
|
childAlphaTopLeft = childAlpha;
|
|
childAlphaTopRight = childAlpha;
|
|
childAlphaBottomLeft = childAlpha;
|
|
childAlphaBottomRight = childAlpha;
|
|
}
|
|
|
|
var childScrollFactorX = child.scrollFactorX;
|
|
var childScrollFactorY = child.scrollFactorY;
|
|
|
|
if (!containerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
|
|
{
|
|
// If Container doesn't have its own blend mode, then a child can have one
|
|
renderer.setBlendMode(child.blendMode);
|
|
}
|
|
|
|
var mask = child.mask;
|
|
|
|
if (mask)
|
|
{
|
|
mask.preRenderWebGL(renderer, child, camera);
|
|
}
|
|
|
|
var type = child.type;
|
|
|
|
if (type !== renderer.currentType)
|
|
{
|
|
renderer.newType = true;
|
|
renderer.currentType = type;
|
|
}
|
|
|
|
renderer.nextTypeMatch = (i < childCount - 1) ? (children[i + 1].type === renderer.currentType) : false;
|
|
|
|
// Set parent values
|
|
child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY);
|
|
|
|
child.setAlpha(childAlphaTopLeft * alpha, childAlphaTopRight * alpha, childAlphaBottomLeft * alpha, childAlphaBottomRight * alpha);
|
|
|
|
// Render
|
|
child.renderWebGL(renderer, child, camera, transformMatrix, container);
|
|
|
|
// Restore original values
|
|
|
|
child.setAlpha(childAlphaTopLeft, childAlphaTopRight, childAlphaBottomLeft, childAlphaBottomRight);
|
|
|
|
child.setScrollFactor(childScrollFactorX, childScrollFactorY);
|
|
|
|
if (mask)
|
|
{
|
|
mask.postRenderWebGL(renderer, camera);
|
|
}
|
|
|
|
renderer.newType = false;
|
|
}
|
|
|
|
renderer.pipelines.postBatch(container);
|
|
};
|
|
|
|
module.exports = ContainerWebGLRenderer;
|
|
|
|
|
|
/***/ }),
|
|
/* 345 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @author Felipe Alfonso <@bitnenfer>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Renders this Game Object with the Canvas Renderer to the given Camera.
|
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
|
* This method should not be called directly. It is a utility function of the Render module.
|
|
*
|
|
* @method Phaser.GameObjects.Container#renderCanvas
|
|
* @since 3.4.0
|
|
* @private
|
|
*
|
|
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
|
|
* @param {Phaser.GameObjects.Container} container - The Game Object being rendered in this call.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
|
*/
|
|
var ContainerCanvasRenderer = function (renderer, container, camera, parentMatrix)
|
|
{
|
|
camera.addToRenderList(container);
|
|
|
|
var children = container.list;
|
|
|
|
if (children.length === 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var transformMatrix = container.localTransform;
|
|
|
|
if (parentMatrix)
|
|
{
|
|
transformMatrix.loadIdentity();
|
|
transformMatrix.multiply(parentMatrix);
|
|
transformMatrix.translate(container.x, container.y);
|
|
transformMatrix.rotate(container.rotation);
|
|
transformMatrix.scale(container.scaleX, container.scaleY);
|
|
}
|
|
else
|
|
{
|
|
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
|
|
}
|
|
|
|
var containerHasBlendMode = (container.blendMode !== -1);
|
|
|
|
if (!containerHasBlendMode)
|
|
{
|
|
// If Container is SKIP_TEST then set blend mode to be Normal
|
|
renderer.setBlendMode(0);
|
|
}
|
|
|
|
var alpha = container._alpha;
|
|
var scrollFactorX = container.scrollFactorX;
|
|
var scrollFactorY = container.scrollFactorY;
|
|
|
|
if (container.mask)
|
|
{
|
|
container.mask.preRenderCanvas(renderer, null, camera);
|
|
}
|
|
|
|
for (var i = 0; i < children.length; i++)
|
|
{
|
|
var child = children[i];
|
|
|
|
if (!child.willRender(camera))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var childAlpha = child.alpha;
|
|
var childScrollFactorX = child.scrollFactorX;
|
|
var childScrollFactorY = child.scrollFactorY;
|
|
|
|
if (!containerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
|
|
{
|
|
// If Container doesn't have its own blend mode, then a child can have one
|
|
renderer.setBlendMode(child.blendMode);
|
|
}
|
|
|
|
// Set parent values
|
|
child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY);
|
|
child.setAlpha(childAlpha * alpha);
|
|
|
|
// Render
|
|
child.renderCanvas(renderer, child, camera, transformMatrix);
|
|
|
|
// Restore original values
|
|
child.setAlpha(childAlpha);
|
|
child.setScrollFactor(childScrollFactorX, childScrollFactorY);
|
|
}
|
|
|
|
if (container.mask)
|
|
{
|
|
container.mask.postRenderCanvas(renderer);
|
|
}
|
|
};
|
|
|
|
module.exports = ContainerCanvasRenderer;
|
|
|
|
|
|
/***/ }),
|
|
/* 346 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2013-2023 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var Rectangle = __webpack_require__(29);
|
|
|
|
/**
|
|
* Creates a new Rectangle or repositions and/or resizes an existing Rectangle so that it encompasses the two given Rectangles, i.e. calculates their union.
|
|
*
|
|
* @function Phaser.Geom.Rectangle.Union
|
|
* @since 3.0.0
|
|
*
|
|
* @generic {Phaser.Geom.Rectangle} O - [out,$return]
|
|
*
|
|
* @param {Phaser.Geom.Rectangle} rectA - The first Rectangle to use.
|
|
* @param {Phaser.Geom.Rectangle} rectB - The second Rectangle to use.
|
|
* @param {Phaser.Geom.Rectangle} [out] - The Rectangle to store the union in.
|
|
*
|
|
* @return {Phaser.Geom.Rectangle} The modified `out` Rectangle, or a new Rectangle if none was provided.
|
|
*/
|
|
var Union = function (rectA, rectB, out)
|
|
{
|
|
if (out === undefined) { out = new Rectangle(); }
|
|
|
|
// Cache vars so we can use one of the input rects as the output rect
|
|
var x = Math.min(rectA.x, rectB.x);
|
|
var y = Math.min(rectA.y, rectB.y);
|
|
var w = Math.max(rectA.right, rectB.right) - x;
|
|
var h = Math.max(rectA.bottom, rectB.bottom) - y;
|
|
|
|
return out.setTo(x, y, w, h);
|
|
};
|
|
|
|
module.exports = Union;
|
|
|
|
|
|
/***/ }),
|
|
/* 347 */
|
|
/***/ (function(module, exports, __webpack_require__) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
var renderWebGL = __webpack_require__(2);
|
|
var renderCanvas = __webpack_require__(2);
|
|
|
|
if (true)
|
|
{
|
|
renderWebGL = __webpack_require__(348);
|
|
}
|
|
|
|
if (true)
|
|
{
|
|
renderCanvas = __webpack_require__(349);
|
|
}
|
|
|
|
module.exports = {
|
|
|
|
renderWebGL: renderWebGL,
|
|
renderCanvas: renderCanvas
|
|
|
|
};
|
|
|
|
|
|
/***/ }),
|
|
/* 348 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Renders this Game Object with the WebGL Renderer to the given Camera.
|
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
|
* This method should not be called directly. It is a utility function of the Render module.
|
|
*
|
|
* @method SpineContainerWebGLRenderer#renderWebGL
|
|
* @since 3.50.0
|
|
* @private
|
|
*
|
|
* @param {Phaser.Renderer.WebGL.WebGLRenderer} renderer - A reference to the current active WebGL renderer.
|
|
* @param {SpineContainer} container - The Game Object being rendered in this call.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
|
*/
|
|
var SpineContainerWebGLRenderer = function (renderer, container, camera, parentMatrix)
|
|
{
|
|
var plugin = container.plugin;
|
|
var sceneRenderer = plugin.sceneRenderer;
|
|
var children = container.list;
|
|
|
|
if (children.length === 0)
|
|
{
|
|
if (sceneRenderer.batcher.isDrawing && renderer.finalType)
|
|
{
|
|
sceneRenderer.end();
|
|
|
|
renderer.pipelines.rebind();
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
camera.addToRenderList(container);
|
|
|
|
var transformMatrix = container.localTransform;
|
|
|
|
if (parentMatrix)
|
|
{
|
|
transformMatrix.loadIdentity();
|
|
transformMatrix.multiply(parentMatrix);
|
|
transformMatrix.translate(container.x, container.y);
|
|
transformMatrix.rotate(container.rotation);
|
|
transformMatrix.scale(container.scaleX, container.scaleY);
|
|
}
|
|
else
|
|
{
|
|
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
|
|
}
|
|
|
|
if (renderer.newType)
|
|
{
|
|
// flush + clear if this is a new type
|
|
renderer.pipelines.clear();
|
|
|
|
sceneRenderer.begin();
|
|
}
|
|
|
|
var rendererNextType = renderer.nextTypeMatch;
|
|
|
|
// Force these to avoid batch flushing during SpineGameObject.renderWebGL
|
|
renderer.nextTypeMatch = true;
|
|
renderer.newType = false;
|
|
|
|
for (var i = 0; i < children.length; i++)
|
|
{
|
|
var child = children[i];
|
|
|
|
if (child.willRender(camera, container))
|
|
{
|
|
var mask = child.mask;
|
|
|
|
if (mask)
|
|
{
|
|
sceneRenderer.end();
|
|
|
|
renderer.pipelines.rebind();
|
|
|
|
mask.preRenderWebGL(renderer, child, camera);
|
|
|
|
renderer.pipelines.clear();
|
|
|
|
sceneRenderer.begin();
|
|
}
|
|
|
|
child.renderWebGL(renderer, child, camera, transformMatrix, container);
|
|
|
|
if (mask)
|
|
{
|
|
sceneRenderer.end();
|
|
|
|
renderer.pipelines.rebind();
|
|
|
|
mask.postRenderWebGL(renderer, camera);
|
|
|
|
renderer.pipelines.clear();
|
|
|
|
sceneRenderer.begin();
|
|
}
|
|
}
|
|
}
|
|
|
|
renderer.nextTypeMatch = rendererNextType;
|
|
|
|
if (!rendererNextType)
|
|
{
|
|
// The next object in the display list is not a Spine Game Object or Spine Container, so we end the batch
|
|
sceneRenderer.end();
|
|
|
|
// And rebind the previous pipeline
|
|
renderer.pipelines.rebind();
|
|
}
|
|
};
|
|
|
|
module.exports = SpineContainerWebGLRenderer;
|
|
|
|
|
|
/***/ }),
|
|
/* 349 */
|
|
/***/ (function(module, exports) {
|
|
|
|
/**
|
|
* @author Richard Davey <rich@photonstorm.com>
|
|
* @copyright 2022 Photon Storm Ltd.
|
|
* @license {@link https://opensource.org/licenses/MIT|MIT License}
|
|
*/
|
|
|
|
/**
|
|
* Renders this Game Object with the Canvas Renderer to the given Camera.
|
|
* The object will not render if any of its renderFlags are set or it is being actively filtered out by the Camera.
|
|
* This method should not be called directly. It is a utility function of the Render module.
|
|
*
|
|
* @method Phaser.GameObjects.Container#renderCanvas
|
|
* @since 3.4.0
|
|
* @private
|
|
*
|
|
* @param {Phaser.Renderer.Canvas.CanvasRenderer} renderer - A reference to the current active Canvas renderer.
|
|
* @param {Phaser.GameObjects.Container} container - The Game Object being rendered in this call.
|
|
* @param {Phaser.Cameras.Scene2D.Camera} camera - The Camera that is rendering the Game Object.
|
|
* @param {Phaser.GameObjects.Components.TransformMatrix} parentMatrix - This transform matrix is defined if the game object is nested
|
|
*/
|
|
var SpineContainerCanvasRenderer = function (renderer, container, camera, parentMatrix)
|
|
{
|
|
var children = container.list;
|
|
|
|
if (children.length === 0)
|
|
{
|
|
return;
|
|
}
|
|
|
|
camera.addToRenderList(container);
|
|
|
|
var transformMatrix = container.localTransform;
|
|
|
|
if (parentMatrix)
|
|
{
|
|
transformMatrix.loadIdentity();
|
|
transformMatrix.multiply(parentMatrix);
|
|
transformMatrix.translate(container.x, container.y);
|
|
transformMatrix.rotate(container.rotation);
|
|
transformMatrix.scale(container.scaleX, container.scaleY);
|
|
}
|
|
else
|
|
{
|
|
transformMatrix.applyITRS(container.x, container.y, container.rotation, container.scaleX, container.scaleY);
|
|
}
|
|
|
|
var containerHasBlendMode = (container.blendMode !== -1);
|
|
|
|
if (!containerHasBlendMode)
|
|
{
|
|
// If Container is SKIP_TEST then set blend mode to be Normal
|
|
renderer.setBlendMode(0);
|
|
}
|
|
|
|
var alpha = container._alpha;
|
|
var scrollFactorX = container.scrollFactorX;
|
|
var scrollFactorY = container.scrollFactorY;
|
|
|
|
if (container.mask)
|
|
{
|
|
container.mask.preRenderCanvas(renderer, null, camera);
|
|
}
|
|
|
|
for (var i = 0; i < children.length; i++)
|
|
{
|
|
var child = children[i];
|
|
|
|
if (!child.willRender(camera))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var childAlpha = child.alpha;
|
|
var childScrollFactorX = child.scrollFactorX;
|
|
var childScrollFactorY = child.scrollFactorY;
|
|
|
|
if (!containerHasBlendMode && child.blendMode !== renderer.currentBlendMode)
|
|
{
|
|
// If Container doesn't have its own blend mode, then a child can have one
|
|
renderer.setBlendMode(child.blendMode);
|
|
}
|
|
|
|
// Set parent values
|
|
child.setScrollFactor(childScrollFactorX * scrollFactorX, childScrollFactorY * scrollFactorY);
|
|
child.setAlpha(childAlpha * alpha);
|
|
|
|
// Render
|
|
child.renderCanvas(renderer, child, camera, transformMatrix);
|
|
|
|
// Restore original values
|
|
child.setAlpha(childAlpha);
|
|
child.setScrollFactor(childScrollFactorX, childScrollFactorY);
|
|
}
|
|
|
|
if (container.mask)
|
|
{
|
|
container.mask.postRenderCanvas(renderer);
|
|
}
|
|
};
|
|
|
|
module.exports = SpineContainerCanvasRenderer;
|
|
|
|
|
|
/***/ })
|
|
/******/ ]); |