phaser4-rex-plugins
Version:
726 lines (622 loc) • 21.2 kB
JavaScript
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
typeof define === 'function' && define.amd ? define(factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.rexuniqueitemlistplugin = factory());
})(this, (function () { 'use strict';
var IsPlainObject = function (obj)
{
// Not plain objects:
// - Any object or value whose internal [[Class]] property is not "[object Object]"
// - DOM nodes
// - window
if (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;
};
var GetValue = function (source, key, defaultValue) {
if (!source || typeof source === 'number') {
return defaultValue;
}
if (typeof (key) === 'string') {
if (source.hasOwnProperty(key)) {
return source[key];
}
if (key.indexOf('.') !== -1) {
key = key.split('.');
} else {
return defaultValue;
}
}
var keys = key;
var parent = source;
var value = defaultValue;
// Use for loop here so we can break early
for (var i = 0; i < keys.length; i++) {
key = keys[i];
if (parent.hasOwnProperty(key)) {
// Yes it has a key property, let's carry on down
value = parent[key];
parent = value;
}
else {
// Can't go any further, so reset to default
value = defaultValue;
break;
}
}
return value;
};
var IsArray = function(obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
};
var DestroyCallbackMethods = {
setAutoCleanupEnable(enabled) {
if (enabled === undefined) {
enabled = true;
}
this.autoCleanupEnable = enabled;
return this;
},
addDestroyCallback(gameObject) {
if ((!gameObject) || (!this.autoCleanupEnable)) {
return this;
}
if (IsArray(gameObject)) {
var gameObjects = gameObject;
for (var i = 0, cnt = gameObjects.length; i < cnt; i++) {
this.addDestroyCallback(gameObjects[i]);
}
return this;
}
if (gameObject.on) {
gameObject.once('destroy', this.onChildDestroy, this);
}
return this;
},
removeDestroyCallback(gameObject) {
if ((!gameObject) || (!this.autoCleanupEnable)) {
return this;
}
if (IsArray(gameObject)) {
var gameObjects = gameObject;
for (var i = 0, cnt = gameObjects.length; i < cnt; i++) {
this.removeDestroyCallback(gameObjects[i]);
}
return this;
}
if (gameObject.off) {
gameObject.off('destroy', this.onChildDestroy, this);
}
return this;
}
};
var ContainMethods = {
contains(item) {
return (this.items.indexOf(item) !== -1);
},
any(listB) {
var items = (this.isList(listB)) ? listB.items : listB;
for (var i = 0, cnt = items; i < cnt; i++) {
if (this.contains(items[i])) {
return true;
}
}
return false;
},
all(listB) {
var items = (this.isList(listB)) ? listB.items : listB;
for (var i = 0, cnt = items; i < cnt; i++) {
if (!this.contains(items[i])) {
return false;
}
}
return true;
}
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|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 {integer} 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;
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|MIT License}
*/
/**
* Compute a random integer between the `min` and `max` values, inclusive.
*
* @function Phaser.Math.Between
* @since 3.0.0
*
* @param {integer} min - The minimum value.
* @param {integer} max - The maximum value.
*
* @return {integer} The random integer.
*/
var Between = function (min, max)
{
return Math.floor(Math.random() * (max - min + 1) + min);
};
/**
* @author Richard Davey <rich@photonstorm.com>
* @copyright 2018 Photon Storm Ltd.
* @license {@link https://github.com/photonstorm/phaser/blob/master/license.txt|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
*
* @param {array} array - The array to shuffle. This array is modified in place.
*
* @return {array} 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;
};
var Clear = function (obj) {
if ((typeof (obj) !== 'object') || (obj === null)) {
return obj;
}
if (Array.isArray(obj)) {
obj.length = 0;
} else {
for (var key in obj) {
delete obj[key];
}
}
return obj;
};
/**
* Shallow Object Clone. Will not out nested objects.
* @param {object} obj JSON object
* @param {object} ret JSON object to return, set null to return a new object
* @returns {object} this object
*/
var Clone = function (obj, out) {
var objIsArray = Array.isArray(obj);
if (out === undefined) {
out = (objIsArray) ? [] : {};
} else {
Clear(out);
}
if (objIsArray) {
out.length = obj.length;
for (var i = 0, cnt = obj.length; i < cnt; i++) {
out[i] = obj[i];
}
} else {
for (var key in obj) {
out[key] = obj[key];
}
}
return out;
};
var ArrayMethods = {
isEmpty() {
return (this.items.length === 0);
},
get(index) {
return this.items[index];
},
getFirst() {
return this.items[0];
},
getLast() {
return this.items[this.items.length - 1];
},
getRandom() {
var index = Between(0, this.items.length - 1);
return this.items[index];
},
add(item, index, moveToNewPosition) {
var currentIndex = this.items.indexOf(item);
if (currentIndex !== -1) {
if (moveToNewPosition && (index !== currentIndex)) {
this.remove(undefined, currentIndex);
this.add(item, index);
}
return this;
}
if ((index === undefined) || (index >= this.items.length)) {
this.items.push(item);
} else {
this.items.splice(index, 0, item);
}
this.addDestroyCallback(item);
return this;
},
addFirst(item, moveToNewPosition) {
this.add(item, 0, moveToNewPosition);
return this;
},
addLast(item, moveToNewPosition) {
this.add(item, undefined, moveToNewPosition);
return this;
},
addMultiple(items, index, moveToNewPosition) {
if (index === undefined) {
for (var i = 0, cnt = items.length; i < cnt; i++) {
this.add(items[i]);
}
} else {
for (var i = 0, cnt = items.length; i < cnt; i++) {
if (this.contains(items[i])) {
continue;
}
this.add(items[i], index, moveToNewPosition);
index++;
}
}
return this;
},
remove(item, index) {
if (item) {
index = this.items.indexOf(item);
if (index === -1) {
return this;
}
} else {
item = this.items[index];
if (!item) {
return this;
}
}
if (index === (this.items.length - 1)) {
this.items.length -= 1;
} else {
SpliceOne(this.items, index);
}
this.removeDestroyCallback(item);
return this;
},
onChildDestroy(child, fromScene) {
this.remove(child);
},
removeFirst() {
this.remove(undefined, 0);
return this;
},
removeLast() {
this.remove(undefined, (this.item.length - 1));
return this;
},
removeMultiple(items) {
for (var i = items.length; i > 0; i--) {
this.remove(items[i - 1]);
}
return this;
},
clear(destroyItems) {
var items;
if (destroyItems) {
items = this.cloneItems();
}
this.removeDestroyCallback(this.items);
this.items.length = 0;
if (destroyItems) {
for (var i = items.length; i > 0; i--) {
items[i].destroy();
}
}
return this;
},
clone(out) {
if (out === this) {
return this;
} else if (out === undefined) {
out = this.newList();
}
out.clear();
Clone(this.items, out.items);
out.addDestroyCallback(out.items);
return out;
},
pop(index) {
if (index === undefined) {
index = 0;
}
var item = this.items[index];
this.remove(undefined, index);
return item;
},
popFirst() {
return this.pop(0);
},
popLast() {
return this.pop(this.items.length - 1);
},
popRandom() {
var index = Between(0, this.items.length - 1);
return this.pop(index);
},
slice(start, end, out) {
var result = this.items.slice(start, (end + 1));
if (out === undefined) {
out = this.newList();
}
out.clear();
Clone(result, out.items);
out.addDestroyCallback(out.items);
return out;
},
reverse() {
this.items.reverse();
return this;
},
sort(callback) {
this.items.sort(callback);
return this;
},
shuffle() {
Shuffle(this.items);
return this;
}
};
var SetMethods = {
union(listB, out) {
if (this === listB) {
if (this !== out) {
out = this.clone(out);
}
} else if (this === out) {
this.addMultiple(listB.items);
} else if (listB === out) {
listB.addMultiple(this.items);
} else {
if (this.items.length >= listB.items.length) {
out = this.clone(out);
out.addMultiple(listB.items);
} else {
out = listB.clone(out);
out.addMultiple(this.items);
}
}
return out;
},
intersect(listB, out) {
if (this === listB) {
if (this !== out) {
out = this.clone(out);
}
} else if (this === out) {
var itemsA = Clone(this.items);
this.clear();
var item;
for (var i = 0, cnt = itemsA.length; i < cnt; i++) {
item = itemsA[i];
if (listB.contains(item)) {
this.add(item);
}
}
} else if (listB === out) {
var itemsB = Clone(listB.items);
listB.clear();
var item;
for (var i = 0, cnt = itemsA.length; i < cnt; i++) {
item = itemsB[i];
if (this.contains(item)) {
listB.add(item);
}
}
} else {
out = this.newList();
if (this.items.length >= listB.items.length) {
var itemsB = listB.items, item;
for (var i = 0, cnt = itemsB.length; i < cnt; i++) {
item = itemsB[i];
if (this.contains(item)) {
out.add(item);
}
}
} else {
var itemsA = this.items, item;
for (var i = 0, cnt = itemsA.length; i < cnt; i++) {
item = itemsA[i];
if (listB.contains(item)) {
out.add(item);
}
}
}
}
return out;
},
difference(listB, out) {
if (this === listB) {
if (this === out) {
this.clear();
} else {
out = this.newList();
}
} else if (this === out) {
var itemsA = Clone(this.items);
this.clear();
var item;
for (var i = 0, cnt = itemsA.length; i < cnt; i++) {
item = itemsA[i];
if (!listB.contains(item)) {
this.add(item);
}
}
} else if (listB === out) {
var itemsB = Clone(listB.items);
listB.clear();
var item;
for (var i = 0, cnt = itemsA.length; i < cnt; i++) {
item = itemsB[i];
if (!this.contains(item)) {
listB.add(item);
}
}
} else {
out = this.newList();
if (this.items.length >= listB.items.length) {
var itemsB = listB.items, item;
for (var i = 0, cnt = itemsB.length; i < cnt; i++) {
item = itemsB[i];
if (!this.contains(item)) {
out.add(item);
}
}
} else {
var itemsA = this.items, item;
for (var i = 0, cnt = itemsA.length; i < cnt; i++) {
item = itemsA[i];
if (!listB.contains(item)) {
out.add(item);
}
}
}
}
return out;
},
};
var Copy = function (dest, src, startIdx, endIdx) {
if (startIdx === undefined) {
startIdx = 0;
} if (endIdx === undefined) {
endIdx = src.length;
}
dest.length = endIdx - startIdx;
for (var i = 0, len = dest.length; i < len; i++) {
dest[i] = src[i + startIdx];
}
return dest;
};
class UniqueItemList {
constructor(items, config) {
if (IsPlainObject(items)) {
config = items;
items = GetValue(config, 'items', undefined);
}
this.items = [];
this.setAutoCleanupEnable(GetValue(config, 'autoCleanup', true));
if (items) {
this.addMultiple(items);
}
}
destroy(destroyItems) {
this.clear(destroyItems);
this.items = undefined;
}
getItems() {
return this.items;
}
cloneItems(out) {
return Clone(this.items, out);
}
isList(item) {
return (item instanceof UniqueItemList);
}
newList(items) {
var config = {
autoCleanup: this.autoCleanupEnable
};
return new UniqueItemList(items, config);
}
get length() {
return this.items.length;
}
call(callback, scope) {
if (this.items.length === 0) {
return this;
}
if (typeof (callback) === 'string') {
var fnName = callback;
Copy(ARGS, arguments, 1);
var item;
for (var i = 0, cnt = this.items.length; i < cnt; i++) {
item = this.items[i];
item[fnName].apply(item, ARGS);
}
ARGS.length = 0;
} else {
for (var i = 0, cnt = this.items.length; i < cnt; i++) {
if (scope) {
callback.call(scope, this.items[i], i);
} else {
callback(this.items[i], i);
}
}
}
return this;
}
}
var ARGS = []; // reuse this array
Object.assign(
UniqueItemList.prototype,
DestroyCallbackMethods,
ContainMethods,
ArrayMethods,
SetMethods
);
class UniqueItemListPlugin extends Phaser.Plugins.BasePlugin {
constructor(pluginManager) {
super(pluginManager);
}
start() {
var eventEmitter = this.game.events;
eventEmitter.on('destroy', this.destroy, this);
}
add(config) {
return new UniqueItemList(config);
}
}
return UniqueItemListPlugin;
}));