arcade-physics
Version:
Use Arcade Physics without Phaser.
181 lines • 6.33 kB
JavaScript
;
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2020 Photon Storm Ltd.
* @license {@link https://opensource.org/licenses/MIT|MIT License}
*/
Object.defineProperty(exports, "__esModule", { value: true });
// 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.
let 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) {
let 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 (const k in definition) {
if (!definition.hasOwnProperty(k)) {
continue;
}
const def = getProperty(definition, k, isClassDescriptor);
if (def !== false) {
// If Extends is used, we will check its prototype to see if the final variable exists.
const 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 (let 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
let initialize;
let 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) {
const base = definition.Extends;
initialize = function () {
base.apply(this, arguments);
};
}
else {
initialize = () => { };
}
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...
let 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;
exports.default = Class;
//# sourceMappingURL=Class.js.map