diff --git a/docs/Frame.html b/docs/Frame.html index 16e92d0..952de20 100644 --- a/docs/Frame.html +++ b/docs/Frame.html @@ -24,7 +24,7 @@
@@ -285,7 +285,7 @@

getDataURL<
Source:
@@ -393,7 +393,7 @@

getDelaySource:
@@ -451,6 +451,114 @@
Returns:
+

+ + +
+ + + +

getHeight() → {number}

+ + + + + +
+ Gets the height of the frame. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +number + + +
+
+ + +
+ The height of the frame. +
+ + +
+ + +
@@ -501,7 +609,7 @@

getParentSource:
@@ -559,6 +667,114 @@
Returns:
+ + + +
+ + + +

getSize() → {Object}

+ + + + + +
+ Gets the width and height of this frame and returns it. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +Object + + +
+
+ + +
+ An object with the width and height of this frame. +
+ + +
+ + +
@@ -609,7 +825,7 @@

getVyiSource:
@@ -667,6 +883,114 @@
Returns:
+ + + +
+ + + +

getWidth() → {number}

+ + + + + +
+ Gets the width of the frame. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +number + + +
+
+ + +
+ The width of the frame. +
+ + +
+ + +
@@ -717,7 +1041,7 @@

setDataURL<
Source:
@@ -877,7 +1201,7 @@

setDelaySource:
@@ -1006,7 +1330,7 @@
Returns:

- Generated by JSDoc 4.0.3 on Mon Sep 23 2024 13:14:46 GMT-0500 (Central Daylight Time) using the Minami theme. + Generated by JSDoc 4.0.3 on Wed Sep 25 2024 15:51:20 GMT-0500 (Central Daylight Time) using the Minami theme.
diff --git a/docs/Icon.html b/docs/Icon.html index 5119e24..9f87813 100644 --- a/docs/Icon.html +++ b/docs/Icon.html @@ -24,7 +24,7 @@
@@ -56,7 +56,7 @@

-

new Icon(pIconData, pVYI)

+

new Icon(pIconData)

@@ -149,7 +149,7 @@
Parameters:
-Object +Array @@ -166,32 +166,6 @@
Parameters:
- - - - pVYI - - - - - -VYI - - - - - - - - - - - The vyi this icon | state belongs to. - - - - - @@ -285,7 +259,7 @@

addFrameSource:
@@ -335,6 +309,9 @@
Parameters:
+Frame +| + Array @@ -448,7 +425,7 @@

addStateSource:
@@ -498,7 +475,7 @@
Parameters:
-Object +Array @@ -611,7 +588,7 @@

getDataURL<
Source:
@@ -719,7 +696,7 @@

getDelaySource:
@@ -827,7 +804,7 @@

getFrameSource:
@@ -990,7 +967,7 @@

getFramesSource:
@@ -1055,7 +1032,115 @@
Returns:
-

getID() → {string}

+

getHeight() → {number}

+ + + + + +
+ Gets the height of the icon. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +number + + +
+
+ + +
+ The height of the icon. +
+ + +
+ + + +

+ + +
+ + + +

getId() → {string}

@@ -1098,7 +1183,7 @@

getIDSource:
@@ -1206,7 +1291,7 @@

getNameSource:
@@ -1314,7 +1399,7 @@

getParentSource:
@@ -1425,7 +1510,7 @@

getSizeSource:
@@ -1497,7 +1582,7 @@

getState - Gets the state that has the name pName. + Gets the state that has the name pName. The LAST defined state that has the passed name will be returned.

@@ -1533,7 +1618,7 @@

getStateSource:
@@ -1693,7 +1778,7 @@

getStatesSource:
@@ -1801,7 +1886,7 @@

getVyiSource:
@@ -1866,14 +1951,14 @@
Returns:
-

removeFrame(pFrame, pIndex) → {self}

+

getWidth() → {number}

- Removes the frame passed or the frame that exists at pIndex. + Gets the width of the icon.
@@ -1909,7 +1994,7 @@

removeFram
Source:
@@ -1928,84 +2013,6 @@

removeFram -

Parameters:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
NameTypeDescription
pFrame - - -Frame - - - - - The frame to remove from this icon. pIndex should be not be used in tandem with this method of removing. - -
pIndex - - -number - - - - - The index of the frame to remove. pFrame must be undefined to use this method for removing. - -
- - @@ -2029,7 +2036,7 @@
Returns:
-self +number
@@ -2037,7 +2044,7 @@
Returns:
- This icon instance. + The width of the icon.
@@ -2052,14 +2059,14 @@
Returns:
-

removeState(pState, pName) → {self}

+

parse(pIconData)

- Removes the state passed or the state with the name pName. + Parses through the icon data and adds data to this icon.
@@ -2095,7 +2102,7 @@

removeStat
Source:
@@ -2139,13 +2146,13 @@

Parameters:
- pState + pIconData -Icon +Array @@ -2156,40 +2163,22 @@
Parameters:
- The state to remove from this icon. pName should be not be used in tandem with this method of removing. + The icon data that is used to build this icon. + + - - - pName - - - - -string - - - - - - The name of the state to remove. pState must be undefined to use this method for removing. - - - - - - @@ -2198,21 +2187,788 @@
Parameters:
+ + + +
+ +

removeFrame(pFrame) → {self}

+ -
-
Returns:
+
+ Removes the frame passed. +
- -
-
- Type: -
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pFrame + + +Frame + + + + + The frame to remove from this icon. + +
+ + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +self + + +
+
+ + +
+ This icon instance. +
+ + +
+ + + +
+ + +
+ + + +

removeFrameByIndex(pIndex) → {self}

+ + + + + +
+ Removes the frame via it's index. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pIndex + + +number + + + + + The index of the frame to remove. + +
+ + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +self + + +
+
+ + +
+ This icon instance. +
+ + +
+ + + +
+ + +
+ + + +

removeState(pState) → {self}

+ + + + + +
+ Removes the state passed. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pState + + +Icon + + + + + The state to remove from this icon. + +
+ + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +self + + +
+
+ + +
+ This icon instance. +
+ + +
+ + + +
+ + +
+ + + +

removeStateById(pName) → {self}

+ + + + + +
+ Removes the state via it's id. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pName + + +string + + + + + The id to use to find the state. + +
+ + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +self + + +
+
+ + +
+ This icon instance. +
+ + +
+ + + +
+ + +
+ + + +

removeStateByName(pName) → {self}

+ + + + + +
+ Removes the state via it's name. The LAST defined icon that has the passed name will be removed. As names are not unique. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pName + + +string + + + + + The name to use to find the state. + +
+ + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
self @@ -2281,7 +3037,7 @@

renameSource:
@@ -2441,7 +3197,7 @@

reorderFr
Source:
@@ -2627,7 +3383,7 @@

setA
Source:
@@ -2787,7 +3543,7 @@

setDataURL<
Source:
@@ -2947,7 +3703,7 @@

setDelaySource:
@@ -3107,7 +3863,7 @@

setSizeSource:
@@ -3262,7 +4018,7 @@
Returns:

- Generated by JSDoc 4.0.3 on Mon Sep 23 2024 13:14:46 GMT-0500 (Central Daylight Time) using the Minami theme. + Generated by JSDoc 4.0.3 on Wed Sep 25 2024 15:51:20 GMT-0500 (Central Daylight Time) using the Minami theme.
diff --git a/docs/VYI.html b/docs/VYI.html index 5fa1845..0c7e82e 100644 --- a/docs/VYI.html +++ b/docs/VYI.html @@ -24,7 +24,7 @@
@@ -99,7 +99,7 @@

new VYISource:
@@ -193,13 +193,6 @@
Parameters:
-

Classes

- -
-
VYI
-
-
- @@ -253,7 +246,7 @@

versionSource:
@@ -327,7 +320,7 @@

addIconSource:
@@ -377,7 +370,10 @@
Parameters:
-Object +Icon +| + +Array @@ -490,7 +486,7 @@

exportSource:
@@ -562,7 +558,7 @@

getIcon - Gets the icon that has the name pName. + Gets the icon that has the name pName. The LAST defined icon that has the passed name will be returned.

@@ -598,7 +594,7 @@

getIconSource:
@@ -711,6 +707,166 @@
Returns:
+

+ + +
+ + + +

getIconById(pId) → {Icon}

+ + + + + +
+ Gets an icon by the id provided. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pId + + +string + + + + + The id of the icon. + +
+ + + + + + + + + + + + + + +
+
Returns:
+ + + +
+
+ Type: +
+
+ +Icon + + +
+
+ + +
+ The icon that has the id that was passed. +
+ + +
+ + +
@@ -761,7 +917,7 @@

getIconNa
Source:
@@ -869,7 +1025,7 @@

getIconsSource:
@@ -973,7 +1129,7 @@

getNameSource:
@@ -1081,7 +1237,7 @@

(async) parseSource:
@@ -1239,14 +1395,14 @@
Returns:
-

removeIcon(pIcon, pName)

+

removeIcon(pIcon)

- Removes the icon passed or the icon with the name pName. + Removes the icon passed.
@@ -1282,7 +1438,7 @@

removeIcon<
Source:
@@ -1343,12 +1499,256 @@

Parameters:
- The state to remove from this icon. pName should be not be used in tandem with this method of removing. + The icon to remove from this vyi. + + + + + + + + + + + + + + + + + + + + + + + +

+ + +
+ + + +

removeIconById(pName)

+ + + + + +
+ Removes the icon via it's id. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
pName + + +string + + + + + The id to use to find the icon.
+ + + + + + + + + + + + + + + + +
+ + +
+ + + +

removeIconByName(pName)

+ + + + + +
+ Removes the icon via it's name. The LAST defined icon that has the passed name will be removed. As names are not unique. +
+ + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Source:
+
+ + + + + + + +
+ + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + @@ -1369,7 +1769,7 @@
Parameters:
@@ -1443,7 +1843,7 @@

renameSource:
@@ -1547,7 +1947,7 @@
Parameters:

- Generated by JSDoc 4.0.3 on Mon Sep 23 2024 13:14:46 GMT-0500 (Central Daylight Time) using the Minami theme. + Generated by JSDoc 4.0.3 on Wed Sep 25 2024 15:51:20 GMT-0500 (Central Daylight Time) using the Minami theme.
diff --git a/docs/frame.mjs.html b/docs/frame.mjs.html index c7d5fa2..6dffc57 100644 --- a/docs/frame.mjs.html +++ b/docs/frame.mjs.html @@ -24,7 +24,7 @@
@@ -39,7 +39,7 @@

frame.mjs

-
import { VYI } from './vyi.mjs';
+            
import { VYI, Icon } from './vyi.mjs';
 
 /**
  * @public
@@ -50,7 +50,7 @@ 

frame.mjs

* @private * @type {number} */ - delay = 100; + delay; /** * The data URL of the sprite in this frame. * @private @@ -71,7 +71,6 @@

frame.mjs

parent; /** * The vyi this frame belongs to. - * * @private * @type {VYI} */ @@ -88,24 +87,53 @@

frame.mjs

* @param {Icon} pParentIcon - The icon that created this frame. * @private */ - constructor(pFrameData, pParentIcon) { - this.vyi = pParentIcon.vyi; - this.parent = pParentIcon; + constructor(pFrameData) { this.parse(pFrameData); } /** - * parses through the icon data and adds data to this frame. + * Parses through the icon data and adds data to this frame. * @param {Array} pFrameData - The frame data that is used to build this frame. * @private */ parse(pFrameData) { + if (!pFrameData) return; // Loop through frame data and build frame. const dataURL = pFrameData[0]; - const frameDelay = pFrameData[1] ? pFrameData[1] : this.parent.getDelay(); - // Set the data url + const frameDelay = pFrameData[1] + ? pFrameData[1] + : this.parent + ? this.parent.getDelay() + : null; + this.setDataURL(dataURL); - // Set the frame delay - this.setDelay(frameDelay); + // A frame delay may not be passed. So we await for a parent to default this frame's delay to. + if (frameDelay) { + this.setDelay(frameDelay); + } + } + /** + * Sets the parent for this frame. + * @private + * @param {Icon} pParent - The parent icon of this frame. + */ + setParent(pParent) { + if (!pParent || this.parent) return; + if (pParent instanceof Icon) { + this.parent = pParent; + this.vyi = pParent.vyi; + // If no delay is found, get it from the parent. + if (!this.getDelay()) { + this.setDelay(this.parent.getDelay()); + } + } + } + /** + * Removes the parent and vyi from this frame. + * @private + */ + removeParent() { + this.parent = null; + this.vyi = null; } /** * Sets the delay of this frame in ms. @@ -113,12 +141,10 @@

frame.mjs

* @returns {self} This frame instance. */ setDelay(pDelay) { - if (pDelay) { - if (typeof(pDelay) === 'number') { - this.delay = pDelay; - } else { - VYI.logger.prefix('VYI-module').error('Invalid delay type!'); - } + if (typeof pDelay === 'number') { + this.delay = pDelay; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid delay type!'); } return this; } @@ -135,12 +161,10 @@

frame.mjs

* @returns {self} This frame instance. */ setDataURL(pDataURL) { - if (pDataURL) { - if (typeof(pDataURL) === 'string') { - this.dataURL = pDataURL; - } else { - VYI.logger.prefix('VYI-module').error('Invalid data url type!'); - } + if (typeof pDataURL === 'string') { + this.dataURL = pDataURL; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid data url type!'); } return this; } @@ -151,9 +175,32 @@

frame.mjs

getDataURL() { return this.dataURL; } + /** + * Gets the width of the frame. + * @returns {number} The width of the frame. + */ + getWidth() { + if (!this.parent) return; + return this.parent.width; + } + /** + * Gets the height of the frame. + * @returns {number} The height of the frame. + */ + getHeight() { + if (!this.parent) return; + return this.parent.height; + } + /** + * Gets the width and height of this frame and returns it. + * @returns {Object} An object with the width and height of this frame. + */ + getSize() { + if (!this.parent) return; + return { width: this.parent.width, height: this.parent.height }; + } /** * Gets the vyi this frame belongs to. - * * @returns {VYI} The vyi this frame belongs to. */ getVyi() { @@ -161,7 +208,6 @@

frame.mjs

} /** * Gets the icon this frame belongs to. - * * @returns {Icon} The icon this frame belongs to. */ getParent() { @@ -173,14 +219,10 @@

frame.mjs

* @returns {Array} An array of data related to this frame in the proper vyi format. */ export() { - const frameData = []; - // frame dataURL - frameData[0] = this.getDataURL(); - // We do not have to store the delay if it is the default value of 100. This will save data. + const frameData = [this.getDataURL()]; const delayIsDefault = this.getDelay() === Frame.defaultDelay; if (!delayIsDefault) { - // frame delay - frameData[1] = this.getDelay(); + frameData[1] = this.getDelay() || Frame.defaultDelay; } return frameData; } @@ -196,7 +238,7 @@

frame.mjs


- Generated by JSDoc 4.0.3 on Mon Sep 23 2024 13:14:46 GMT-0500 (Central Daylight Time) using the Minami theme. + Generated by JSDoc 4.0.3 on Wed Sep 25 2024 15:51:20 GMT-0500 (Central Daylight Time) using the Minami theme.
diff --git a/docs/icon.mjs.html b/docs/icon.mjs.html index 03d02fd..c139ff2 100644 --- a/docs/icon.mjs.html +++ b/docs/icon.mjs.html @@ -24,7 +24,7 @@
@@ -47,17 +47,17 @@

icon.mjs

*/ export class Icon { /** - * An array of Icon's that are state of this icon. + * A map of icons that are state of this icon. * @private - * @type {Array} + * @type {Map} */ - states = []; + states = new Map(); /** - * An arary of Frame's that are the frames of this icon. + * A map of frames that are the frames of this icon. * @private - * @type {Array} + * @type {Map} */ - frames = []; + frames = new Map(); /** * The width of this icon. All states and frames of this icon must match this size. * @private @@ -102,62 +102,82 @@

icon.mjs

*/ vyi; /** - * A random unique ID attached to each icon to distinguish them from others in the event another icon shares the same name. + * A random unique Id attached to each icon to distinguish them from others in the event another icon shares the same name. * * @private * @type {string} */ id; + /** + * An set of used Ids to prevent collusion between duplicate named icons. + * + * @private + * @type {Set} + */ + static reservedIds = new Set(); /** * Generates a UUID (Universally Unique Identifier) version 4. * * @private - * @param {VYI} pVYI - The vyi that will reserve this ID. * @returns {string} The generated UUID. */ - static generateID(pVYI) { - const genID = () => { + static generateId() { + const genId = () => { return Math.floor(Math.random() * 0xFFFFFFFF).toString(16).padStart(8, '0'); } - // Generate a random number in the range of 0 to 0xFFFFFFFF (8 hex digits) and convert to hex - let id = genID(); - while (pVYI.reservedIDs.includes(id)) { - id = genID(); + + let id = genId(); + while (this.reservedIds.has(id)) { + id = genId(); } - pVYI.reservedIDs.push(id); + this.reservedIds.add(id); return id; } /** * Creates this icon instance. - * @param {Object} pIconData - The icon data that is used to build this icon. - * @param {VYI} pVYI - The vyi this icon | state belongs to. + * @param {Array} pIconData - The icon data that is used to build this icon. * @private */ - constructor(pIconData, pVYI) { - this.vyi = pVYI; - this.assignID(pVYI); + constructor(pIconData) { this.parse(pIconData); + this.assignId(); } /** - * Assigns an ID to this icon. + * Sets the vyi of this icon. * - * @param {VYI} pVYI - The vyi that holds this ID. + * @private + * @param {VYI} pVyi - The vyi that owns this icon. + */ + setVyi(pVyi) { + if (!pVyi) return; + + if (pVyi instanceof VYI) { + this.vyi = pVyi; + } + } + /** + * Removes the vyi from this icon. + * @private + */ + removeVyi() { + this.vyi = null; + } + /** + * Assigns an Id to this icon. * @private */ - assignID(pVYI) { - this.id = Icon.generateID(pVYI); + assignId() { + this.id = Icon.generateId(); } /** * Gets the id of this icon. - * * @returns {string} The id of this icon. */ - getID() { + getId() { return this.id; } /** * Gets the vyi this icon belongs to. - * * @returns {VYI} The vyi this icon belongs to. */ getVyi() { @@ -165,19 +185,19 @@

icon.mjs

} /** * Gets the icon this state belongs to. If this icon is not a state, it will return undefined. - * * @returns {Icon|undefined} The icon this state belongs to. */ getParent() { return this.parent; } /** - * parses through the icon data and adds data to this icon. - * @param {Object} pIconData - The icon data that is used to build this icon. - * @private + * Parses through the icon data and adds data to this icon. + * @param {Array} pIconData - The icon data that is used to build this icon. */ parse(pIconData) { - // Loop through pIconData and create this icon + if (!pIconData) return; + + // Loop through the icon data and create this icon const iconName = pIconData[0]; const iconWidth = pIconData[1]; const iconHeight = pIconData[2]; @@ -236,13 +256,27 @@

icon.mjs

* @returns {self} This icon instance. */ setSize(pWidth, pHeight) { - if (typeof(pWidth) === 'number') { + if (typeof pWidth === 'number') { this.width = pWidth; } - if (typeof(pHeight) === 'number') { + if (typeof pHeight === 'number') { this.height = pHeight; } } + /** + * Gets the width of the icon. + * @returns {number} The width of the icon. + */ + getWidth() { + return this.width; + } + /** + * Gets the height of the icon. + * @returns {number} The height of the icon. + */ + getHeight() { + return this.height; + } /** * Gets the width and height of this icon and returns it. * @returns {Object} An object with the width and height of this icon. @@ -256,12 +290,10 @@

icon.mjs

* @returns {self} This icon instance. */ setDataURL(pDataURL) { - if (pDataURL) { - if (typeof(pDataURL) === 'string') { - this.dataURL = pDataURL; - } else { - VYI.logger.prefix('VYI-module').error('Invalid data url type!'); - } + if (typeof pDataURL === 'string') { + this.dataURL = pDataURL; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid data url type!'); } return this; } @@ -278,12 +310,10 @@

icon.mjs

* @returns {self} This icon instance. */ setDelay(pDelay) { - if (pDelay) { - if (typeof(pDelay) === 'number') { - this.delay = pDelay; - } else { - VYI.logger.prefix('VYI-module').error('Invalid delay type!'); - } + if (typeof pDelay === 'number') { + this.delay = pDelay; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid delay type!'); } return this; } @@ -300,12 +330,10 @@

icon.mjs

* @returns {self} This icon instance. */ rename(pName) { - if (pName || pName === '') { - if (typeof(pName) === 'string') { - this.name = pName; - } else { - VYI.logger.prefix('VYI-Module').error('Invalid type for pName!'); - } + if (typeof pName === 'string') { + this.name = pName; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid type for pName!'); } return this; } @@ -322,111 +350,70 @@

icon.mjs

* @returns {self} This icon instance. */ setAllFrameDelays(pDelay) { - if (pDelay) { - if (typeof(pDelay) === 'number') { - this.setDelay(pDelay); - this.frames.forEach((pFrame) => { - pFrame.setDelay(pDelay); - }); - } else { - VYI.logger.prefix('VYI-Module').error('Invalid type for pDelay!'); - } + if (typeof pDelay === 'number') { + this.setDelay(pDelay); + this.getFrames().forEach((pFrame) => pFrame.setDelay(pDelay)); + } else { + VYI.logger.prefix('Vyi-module').error('Invalid type for pDelay!'); } return this; } /** - * Adds this icon data as a state. A state is also an icon. - * @param {Object} pIconData - The data used to create this state icon. - * @returns {Icon|undefined} The state that was added or undefined. + * Adds a new frame to this icon. + * @param {Frame|Array} pFrameData - The frame data to give this frame. + * @returns {Frame|undefined} The frame that was added or undefined. */ - addState(pIconData) { - if (pIconData instanceof Object) { - const state = new Icon(pIconData, this.vyi); - state.parent = this; - this.states.push(state); - return state; + addFrame(pFrameData) { + if (!pFrameData) { + VYI.logger.prefix('Vyi-module').error('No frame data passed!'); + return; } - } - /** - * Removes the state passed or the state with the name pName. - * @param {Icon} pState - The state to remove from this icon. pName should be not be used in tandem with this method of removing. - * @param {string} pName - The name of the state to remove. pState must be undefined to use this method for removing. - * @returns {self} This icon instance. - */ - removeState(pState, pName) { - // The index used to remove this frame. - let index; - // Remove via reference to state. - if (this.states.includes(pState)) { - index = this.states.indexOf(pState); - // Remove via reference to name - } else if (typeof(pName) === 'string') { - const state = this.getState(pName); - if (state) { - index = this.states.indexOf(state); - } - } else { - VYI.logger.prefix('VYI-Module').error('Failed to remove state!'); - return this; + + if (!(pFrameData instanceof Frame) && !Array.isArray(pFrameData)) { + VYI.logger.prefix('Vyi-module').error('Invalid frame data type passed!'); + return; } - if (typeof(index) === 'number') { - // Remove the state - this.states.splice(index, 1); + + // Create the icon instance + const frame = pFrameData instanceof Frame + ? pFrameData + : new Frame(pFrameData); + + if (frame.getWidth() !== frame.getWidth() || frame.getHeight() !== frame.getHeight()) { + VYI.logger.prefix('Vyi-module').error('Frame dimensions do not match parent!'); + return; } - return this; + + frame.setParent(this); + // We store this frame under its index in the Map 0-1 + this.frames.set(this.frames.size, frame); + this.indexFrames(); + + return frame; } /** - * Adds a new frame to this icon. - * @param {Array} pFrameData - The frame data to give this frame. - * @returns {Frame|undefined} The frame that was added or undefined. + * Removes the frame passed. + * @param {Frame} pFrame - The frame to remove from this icon. + * @returns {self} This icon instance. */ - addFrame(pFrameData) { - if (pFrameData) { - if (Array.isArray(pFrameData)) { - const frame = new Frame(pFrameData, this); - // Add the frame to the frames array. - this.frames.push(frame); - // Re-index frames after a change + removeFrame(pFrame) { + if (!pFrame) return; + if (pFrame instanceof Frame) { + if (this.frames.delete(pFrame.index)) { + pFrame.removeParent(); this.indexFrames(); - return frame; - } else { - VYI.logger.prefix('VYI-Module').error('Invalid frame data passed!'); } - } else { - VYI.logger.prefix('VYI-Module').error('No frame data passed!'); } + return this; } /** - * Removes the frame passed or the frame that exists at pIndex. - * @param {Frame} pFrame - The frame to remove from this icon. pIndex should be not be used in tandem with this method of removing. - * @param {number} pIndex - The index of the frame to remove. pFrame must be undefined to use this method for removing. + * Removes the frame via it's index. + * @param {number} pIndex - The index of the frame to remove. * @returns {self} This icon instance. */ - removeFrame(pFrame, pIndex) { - // The index used to remove this frame. - let index; - // Remove via reference to frame. - if (this.frames.includes(pFrame)) { - index = this.frames.indexOf(pFrame); - // Remove via index passed. - } else if (pIndex || pIndex === 0) { - if (typeof(pIndex) === 'number') { - const frame = this.getFrame(pIndex); - if (frame) { - index = pIndex; - } - } else { - VYI.logger.prefix('VYI-Module').error('Invalid pIndex type!'); - } - } else { - VYI.logger.prefix('VYI-Module').error('Failed to remove frame!'); - } - if (typeof(index) === 'number') { - // Remove the frame - this.frames.splice(index, 1); - // Re-index frames after a change - this.indexFrames(); - } + removeFrameByIndex(pIndex) { + const frame = this.getFrame(pIndex); + this.removeFrame(frame); return this; } /** @@ -434,8 +421,7 @@

icon.mjs

* @private */ indexFrames() { - // Reorder the frames after removing. - this.frames.forEach((pFrame, pIndex) => { + this.getFrames().forEach((pFrame, pIndex) => { pFrame.index = pIndex; }); } @@ -443,27 +429,17 @@

icon.mjs

* Reorders the frame in the animation. The index of the passed frame will be swapped with the frame at pIndex. * The "first" frame of the animation is technically this icon's dataURL. So if you are aiming to change the order of this icon and convert it into a frame. * pCurrentIndex must be set to -1 to match this icon. + * * @param {number} pCurrentIndex - The current index of the frame. * @param {number} pIndex - The index the frame will be moving to. * @returns {self} This icon instance. */ reorderFrame(pCurrentIndex, pIndex) { - if (typeof(pCurrentIndex) === 'number' && typeof(pIndex) === 'number') { - let frameAtIndex; - let currentFrame; - // We check if the current index is -1, if it is then it means we want to treat this icon as a frame. As the icon data and delay of this icon serves - // as the frame 0. - if (pCurrentIndex === -1) { - currentFrame = this; - // Otherwise if the index passed can be found in the frames array, then we use that frame. - } else if (this.frames[pCurrentIndex]) { - currentFrame = this.frames[pCurrentIndex]; - } - - // We get the frame at the specified index. - if (this.frames[pIndex]) { - frameAtIndex = this.frames[pIndex]; - } + if (typeof pCurrentIndex === 'number' && typeof pIndex === 'number') { + let frameAtIndex = this.getFrame(pIndex); + let currentFrame = pCurrentIndex === -1 + ? this + : this.getFrame(pCurrentIndex) // If both frames can be found, we can swap their data. if (currentFrame && frameAtIndex) { @@ -477,14 +453,15 @@

icon.mjs

// Swap data from frame currentFrame.setDataURL(frameAtIndexDataURL); currentFrame.setDelay(frameAtIndexDelay); + // Swap data to frame frameAtIndex.setDataURL(currentFrameDataURL); frameAtIndex.setDelay(currentFrameDelay); } else { - VYI.logger.prefix('VYI-Module').error('There was no frame found at pCurrentIndex, or there was no frame found at pIndex!'); + VYI.logger.prefix('Vyi-module').error('There was no frame found at pCurrentIndex, or there was no frame found at pIndex!'); } } else { - VYI.logger.prefix('VYI-Module').error('Invalid type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid type used!'); } return this; } @@ -496,18 +473,14 @@

icon.mjs

* @returns {Frame|undefined} The frame found at pIndex. */ getFrame(pIndex) { - if (typeof(pIndex) === 'number') { - return this.frames[pIndex]; - } else { - VYI.logger.prefix('VYI-Module').error('Invalid type used!'); - } + return this.frames.get(pIndex); } /** * Returns an array of all the frames this icons has. * @returns {Array} An array of frames this icon has. */ getFrames() { - return [ ...this.frames ]; + return Array.from(this.frames.values()); } /** * Gets all the frames belonging to this icon. @@ -515,36 +488,130 @@

icon.mjs

* @returns {Array} An array containing the frame data of all frames. */ getFramesData() { - const frameDataArray = []; - this.frames.forEach((pFrame) => { - frameDataArray.push(pFrame.export()); - }); + const frameDataArray = this.getFrames().map((pFrame) => pFrame.export()); return frameDataArray; } /** - * Gets the state that has the name pName. + * Adds this icon data as a state. A state is also an icon. + * @param {Array} pIconData - The data used to create this state icon. + * @returns {Icon|undefined} The state that was added or undefined. + */ + addState(pIconData) { + if (!pIconData) { + VYI.logger.prefix('Vyi-module').error('No icon data passed!'); + return; + } + + if (!(pIconData instanceof Icon) && !Array.isArray(pIconData)) { + VYI.logger.prefix('Vyi-module').error('Invalid icon data type passed!'); + return; + } + + // Create the icon instance + const state = pIconData instanceof Icon + ? pIconData + : new Icon(pIconData); + + if (state.getWidth() !== this.getWidth() || state.getHeight() !== this.getHeight()) { + VYI.logger.prefix('Vyi-module').error('State dimensions do not match parent!'); + return; + } + + state.setParent(this); + state.setVyi(this.vyi); + this.states.set(state.id, state); + + return state; + } + /** + * Sets the parent for this state. + * @private + * @param {Icon} pParent - The parent icon of this state. + */ + setParent(pParent) { + if (!pParent || this.parent) return; + if (pParent instanceof Icon) { + this.parent = pParent; + } + } + /** + * Removes the parent and vyi from this state. + * @private + */ + removeParent() { + if (this.parent) { + this.parent = null; + this.vyi = null; + } + } + /** + * Removes the state passed. + * @param {Icon} pState - The state to remove from this icon. + * @returns {self} This icon instance. + */ + removeState(pState) { + if (pState instanceof Icon) { + if (this.icons.delete(pState.id)) {; + pState.removeParent(); + } + } + return this; + } + /** + * Removes the state via it's name. The LAST defined icon that has the passed name will be removed. As names are not unique. + * @param {string} pName - The name to use to find the state. + * @returns {self} This icon instance. + */ + removeStateByName(pName) { + const state = this.getState(pName); + this.removeState(state); + return this; + } + /** + * Removes the state via it's id. + * @param {string} pName - The id to use to find the state. + * @returns {self} This icon instance. + */ + removeStateById(pId) { + const state = this.getStateById(pId); + this.removeState(state); + return this; + } + /** + * Gets the state that has the name pName. The LAST defined state that has the passed name will be returned. * @param {string} pName - The name of the state to get. * @returns {Icon} The state that has the name of pName. */ getState(pName) { - if (typeof(pName) === 'string') { - for (let i = this.states.length - 1; i >= 0; i--) { - const icon = this.states[i]; + if (typeof pName === 'string') { + const states = this.getStates(); + for (let i = states.length - 1; i >= 0; i--) { + const state = states[i]; // If the icon has the same name, return that icon - if (icon.getName() === pName) { - return icon; + if (state.getName() === pName) { + return state; } } } else { - VYI.logger.prefix('VYI-module').error('Invalid name type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid name type used!'); } } + /** + * Gets the state by the id provided. + * @private + * @param {string} pId - The id of the state. + * @returns {Icon} The state that has the id that was passed. + */ + getStateById(pId) { + if (!pId) return; + return this.states.get(pId); + } /** * Returns an array of all the states this icons has. * @returns {Array} An array of states this icon has. */ getStates() { - return [ ...this.states ]; + return Array.from(this.states.values()); } /** * Gets all the states belonging to this icon. @@ -552,11 +619,7 @@

icon.mjs

* @returns {Array} An array containing the state data of all frames. */ getStatesData() { - const stateDataArray = []; - // Loop state array to export relevant information. - this.states.forEach((pState) => { - stateDataArray.push(pState.exportAsState()); - }); + const stateDataArray = this.getStates().map((pState) => pState.exportAsState()); return stateDataArray; } /** @@ -573,12 +636,7 @@

icon.mjs

// state frame delay stateData[2] = this.getDelay(); // state frame array - stateData[3] = []; - - // Loop frame array to export relevant information. - this.frames.forEach((pFrame) => { - stateData[3].push(pFrame.export()); - }); + stateData[3] = this.getFrames().map((pFrame) => pFrame.export()); return stateData; } /** @@ -590,12 +648,10 @@

icon.mjs

const iconData = []; // icon name iconData[0] = this.getName(); - // Get the size of this icon. - const size = this.getSize(); // icon width - iconData[1] = size.width; + iconData[1] = this.getWidth(); // icon height - iconData[2] = size.height; + iconData[2] = this.getHeight(); // frame delay iconData[3] = this.getDelay(); // icon DataURL @@ -603,10 +659,8 @@

icon.mjs

// frame array iconData[5] = this.getFramesData(); - // this is actually an optional data entry into the vyi, only used if states actually exist on this icon. - // this will save data - if (this.states.length) { - // states array + // This is actually an optional data entry into the vyi, only used if states actually exist on this icon. + if (this.states.size > 0) { iconData[6] = this.getStatesData(); } return iconData; @@ -623,7 +677,7 @@

icon.mjs


- Generated by JSDoc 4.0.3 on Mon Sep 23 2024 13:14:46 GMT-0500 (Central Daylight Time) using the Minami theme. + Generated by JSDoc 4.0.3 on Wed Sep 25 2024 15:51:20 GMT-0500 (Central Daylight Time) using the Minami theme.
diff --git a/docs/index.html b/docs/index.html index 612af13..d43b96a 100644 --- a/docs/index.html +++ b/docs/index.html @@ -24,7 +24,7 @@
@@ -76,7 +76,7 @@

Global Dependency


- Generated by JSDoc 4.0.3 on Mon Sep 23 2024 13:14:46 GMT-0500 (Central Daylight Time) using the Minami theme. + Generated by JSDoc 4.0.3 on Wed Sep 25 2024 15:51:20 GMT-0500 (Central Daylight Time) using the Minami theme.
diff --git a/docs/vyi.mjs.html b/docs/vyi.mjs.html index e0e9833..d66ea1e 100644 --- a/docs/vyi.mjs.html +++ b/docs/vyi.mjs.html @@ -24,7 +24,7 @@
@@ -41,12 +41,13 @@

vyi.mjs

import { Logger } from './vendor/logger.mjs';
 import { Icon } from './icon.mjs';
+import { Frame } from './frame.mjs';
 import pako from './vendor/pako.esm.mjs';
 
 /**
  * @public
  */
-export class VYI {
+class VYI {
 	/**
 	 * The version of the module.
 	 */
@@ -57,11 +58,11 @@ 

vyi.mjs

*/ static logger = new Logger(); /** - * An array of icons that belong to this VYI + * A map of icons that belong to this VYI * @private - * @type {Array} + * @type {Map} */ - icons = []; + icons = new Map(); /** * The name of this vyi. * @private @@ -73,20 +74,13 @@

vyi.mjs

* @private * @type {number} */ - formatVersion; - /** - * An array of used IDs to prevent collusion between duplicate named icons. - * - * @private - * @type {Array} - */ - reservedIDs = []; + formatVersion = 1; /** * Initializes this module with the information from the VYI passed. * @param {Object} pVyiData - A JSON / Javascript object containing the vyi information.this.ogger */ constructor(pVyiData) { - VYI.logger.registerType('VYI-Module', '#ff6600'); + VYI.logger.registerType('Vyi-module', '#ff6600'); this.parse(pVyiData); } /** @@ -104,31 +98,28 @@

vyi.mjs

try { let vyi; - if (typeof(pVyiData) === 'string') { - const isNodeEnv = typeof(window) === 'undefined'; + if (typeof pVyiData === 'string') { + const isNodeEnv = typeof window === 'undefined'; vyi = isNodeEnv ? await this.readFileAndGetVYI(pVyiData) : await this.fetchAndParseJSON(pVyiData); - } else if (typeof(pVyiData) === 'object' && !Array.isArray(pVyiData) && !(pVyiData instanceof ArrayBuffer || pVyiData instanceof Uint8Array)) { + } else if (pVyiData instanceof VYI) { + vyi = pVyiData.export(); + } else if (pVyiData instanceof Object && !Array.isArray(pVyiData) && !(pVyiData instanceof ArrayBuffer || pVyiData instanceof Uint8Array)) { vyi = pVyiData; } else if (pVyiData instanceof ArrayBuffer || pVyiData instanceof Uint8Array) { vyi = await this.handleBinaryData(pVyiData); } else { - throw new Error('Invalid input type provided.'); + throw new Error('Error processing: Invalid input type provided.'); } - // If there is valid vyi data, process it - if (vyi) { - this.processVyiData(vyi); - } + this.processVyiData(vyi); } catch (pError) { - VYI.logger.prefix('VYI-module').error(`Error processing VYI data: ${pError.message}`); - throw pError; // Rethrow the error for further handling + VYI.logger.prefix('Vyi-module').error(`${pError.message}`); } } /** * Reads a file and returns the vyi from it. - * * @private * @param {string} - The URL to read the data from. * @returns {Promise<Object>} - The vyi from the file. @@ -140,7 +131,6 @@

vyi.mjs

} /** * Fetches data from a URL and parses it as JSON. - * * @private * @param {string} pURL - The URL to fetch the data from. * @returns {Promise<Object>} - A promise that resolves to the parsed JSON data. @@ -156,7 +146,6 @@

vyi.mjs

} /** * Handles binary data (ArrayBuffer or Uint8Array). Attempts to inflate or decode it. - * * @private * @param {ArrayBuffer|Uint8Array} pBinaryData - The binary data to process. * @returns {Object|string|null} - The parsed JSON object or decoded string, or null if it fails. @@ -176,7 +165,6 @@

vyi.mjs

} /** * Processes the parsed VYI data and adds icons to the VYI module instance. - * * @private * @param {Object} pVyi - The parsed VYI data. */ @@ -189,104 +177,114 @@

vyi.mjs

this.addIcon(pIconData, this); }); } else { - VYI.logger.prefix('VYI-module').error('Invalid .vyi file! Cannot parse icons.'); + VYI.logger.prefix('Vyi-module').error('Invalid .vyi file! Cannot parse icons.'); } } /** * Adds an icon to this VYI. - * @param {Object} pIconData - The icon data to use. + * @param {Icon|Array} pIconData - The icon data to use. * @returns {Icon|undefined} - The Icon added or undefined. */ addIcon(pIconData) { - if (pIconData) { - if (pIconData instanceof Object) { - const icon = new Icon(pIconData, this); - // Add the icon to the icons array. - this.icons.push(icon); - return icon; - } else { - VYI.logger.prefix('VYI-module').error('Invalid icon data type passed!'); - } - } else { - VYI.logger.prefix('VYI-module').error('No icon data passed!'); + if (!pIconData) { + VYI.logger.prefix('Vyi-module').error('No icon data passed!'); + return; } + + if (!(pIconData instanceof Icon) && !Array.isArray(pIconData)) { + VYI.logger.prefix('Vyi-module').error('Invalid icon data type passed!'); + return; + } + + // Create the icon instance + const icon = pIconData instanceof Icon + ? pIconData + : new Icon(pIconData); + + icon.setVyi(this); + this.icons.set(icon.id, icon); + return icon; } /** - * Removes the icon passed or the icon with the name pName. - * @param {Icon} pIcon - The state to remove from this icon. pName should be not be used in tandem with this method of removing. - * @param {string} pName - The name of the icon to remove. pIcon must be undefined to use this method for removing. + * Removes the icon passed. + * @param {Icon} pIcon - The icon to remove from this vyi. */ - removeIcon(pIcon, pName) { - const icon = pIcon || this.getIcon(pName); - if (icon) { - if (this.icons.includes(icon)) { - this.icons.splice(this.icons.indexOf(icon), 1); + removeIcon(pIcon) { + if (!pIcon) return; + if (pIcon instanceof Icon) { + if (this.icons.delete(pIcon.id)) {; + pIcon.removeVyi(); } } } + /** + * Removes the icon via it's name. The LAST defined icon that has the passed name will be removed. As names are not unique. + * @param {string} pName - The name to use to find the icon. + */ + removeIconByName(pName) { + const icon = this.getIcon(pName); + this.removeIcon(icon); + } + /** + * Removes the icon via it's id. + * @param {string} pName - The id to use to find the icon. + */ + removeIconById(pId) { + const icon = this.getIconById(pId); + this.removeIcon(icon); + } /** * Returns all the icon names in this vyi. * @returns {Array} An array of icon names in this vyi. */ getIconNames() { - // Array to store the icon names. - const iconNames = []; - this.icons.forEach((pIcon) => { - iconNames.push(pIcon.name); - }); + const iconNames = this.getIcons().map((pIcon) => pIcon.name); return iconNames; } /** - * Gets the icon that has the name pName. + * Gets the icon that has the name pName. The LAST defined icon that has the passed name will be returned. * @param {string} pName - The name of the icon to get. * @returns {Icon|undefined} The icon that has the name pName or undefined. */ getIcon(pName) { - if (typeof(pName) === 'string') { - for (let i = this.icons.length - 1; i >= 0; i--) { - const icon = this.icons[i]; + if (typeof pName === 'string') { + const icons = this.getIcons(); + for (let i = icons.length - 1; i >= 0; i--) { + const icon = icons[i]; // If the icon has the same name, return that icon if (icon.getName() === pName) { return icon; } } } else { - VYI.logger.prefix('VYI-module').error('Invalid name type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid name type used!'); } } /** * Gets an icon by the id provided. - * - * @private - * @param {string} pID - The id of the icon. + * @param {string} pId - The id of the icon. * @returns {Icon} The icon that has the id that was passed. */ - getIconByID(pID) { - if (!pID) return; - for (const icon of this.icons) { - for (const state of icon.states) { - if (state.id === pID) return state; - } - if (icon.id === pID) return icon; - } + getIconById(pId) { + if (!pId) return; + return this.icons.get(pId); } /** * Gets all the icons in this vyi. * @returns {Array<Icon>} */ getIcons() { - return [...this.icons]; + return Array.from(this.icons.values()); } /** * Renames the vyi. - * * @param {string} pName - The name to give this vyi. */ rename(pName) { - if (typeof(pName) === 'string') { + if (typeof pName === 'string') { this.name = pName; } else { - VYI.logger.prefix('VYI-module').error('Invalid name type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid name type used!'); } } /** @@ -302,17 +300,13 @@

vyi.mjs

*/ export() { const vyi = {}; - // Set version vyi.v = this.formatVersion; - // Set the icons array - vyi.i = []; - this.icons.forEach((pIcon) => { - // Push the icon data to the vyi export object. - vyi.i.push(pIcon.export()); - }); + vyi.i = this.getIcons().map((pIcon) => pIcon.export()); return vyi; } -}
+} + +export { VYI, Icon, Frame };
@@ -324,7 +318,7 @@

vyi.mjs


- Generated by JSDoc 4.0.3 on Mon Sep 23 2024 13:14:46 GMT-0500 (Central Daylight Time) using the Minami theme. + Generated by JSDoc 4.0.3 on Wed Sep 25 2024 15:51:20 GMT-0500 (Central Daylight Time) using the Minami theme.
diff --git a/package.json b/package.json index f5bf818..2540ce9 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "vyi", - "version": "1.4.0", + "version": "1.5.0", "description": "A lightweight module to read / manage .vyi files created in the Vylocity Game Engine.", "main": "src/vyi.mjs", "scripts": { diff --git a/src/frame.mjs b/src/frame.mjs index 977fe83..bbd5a3f 100644 --- a/src/frame.mjs +++ b/src/frame.mjs @@ -1,4 +1,4 @@ -import { VYI } from './vyi.mjs'; +import { VYI, Icon } from './vyi.mjs'; /** * @public @@ -9,7 +9,7 @@ export class Frame { * @private * @type {number} */ - delay = 100; + delay; /** * The data URL of the sprite in this frame. * @private @@ -30,7 +30,6 @@ export class Frame { parent; /** * The vyi this frame belongs to. - * * @private * @type {VYI} */ @@ -47,24 +46,53 @@ export class Frame { * @param {Icon} pParentIcon - The icon that created this frame. * @private */ - constructor(pFrameData, pParentIcon) { - this.vyi = pParentIcon.vyi; - this.parent = pParentIcon; + constructor(pFrameData) { this.parse(pFrameData); } /** - * parses through the icon data and adds data to this frame. + * Parses through the icon data and adds data to this frame. * @param {Array} pFrameData - The frame data that is used to build this frame. * @private */ parse(pFrameData) { + if (!pFrameData) return; // Loop through frame data and build frame. const dataURL = pFrameData[0]; - const frameDelay = pFrameData[1] ? pFrameData[1] : this.parent.getDelay(); - // Set the data url + const frameDelay = pFrameData[1] + ? pFrameData[1] + : this.parent + ? this.parent.getDelay() + : null; + this.setDataURL(dataURL); - // Set the frame delay - this.setDelay(frameDelay); + // A frame delay may not be passed. So we await for a parent to default this frame's delay to. + if (frameDelay) { + this.setDelay(frameDelay); + } + } + /** + * Sets the parent for this frame. + * @private + * @param {Icon} pParent - The parent icon of this frame. + */ + setParent(pParent) { + if (!pParent || this.parent) return; + if (pParent instanceof Icon) { + this.parent = pParent; + this.vyi = pParent.vyi; + // If no delay is found, get it from the parent. + if (!this.getDelay()) { + this.setDelay(this.parent.getDelay()); + } + } + } + /** + * Removes the parent and vyi from this frame. + * @private + */ + removeParent() { + this.parent = null; + this.vyi = null; } /** * Sets the delay of this frame in ms. @@ -72,12 +100,10 @@ export class Frame { * @returns {self} This frame instance. */ setDelay(pDelay) { - if (pDelay) { - if (typeof(pDelay) === 'number') { - this.delay = pDelay; - } else { - VYI.logger.prefix('VYI-module').error('Invalid delay type!'); - } + if (typeof pDelay === 'number') { + this.delay = pDelay; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid delay type!'); } return this; } @@ -94,12 +120,10 @@ export class Frame { * @returns {self} This frame instance. */ setDataURL(pDataURL) { - if (pDataURL) { - if (typeof(pDataURL) === 'string') { - this.dataURL = pDataURL; - } else { - VYI.logger.prefix('VYI-module').error('Invalid data url type!'); - } + if (typeof pDataURL === 'string') { + this.dataURL = pDataURL; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid data url type!'); } return this; } @@ -110,9 +134,32 @@ export class Frame { getDataURL() { return this.dataURL; } + /** + * Gets the width of the frame. + * @returns {number} The width of the frame. + */ + getWidth() { + if (!this.parent) return; + return this.parent.width; + } + /** + * Gets the height of the frame. + * @returns {number} The height of the frame. + */ + getHeight() { + if (!this.parent) return; + return this.parent.height; + } + /** + * Gets the width and height of this frame and returns it. + * @returns {Object} An object with the width and height of this frame. + */ + getSize() { + if (!this.parent) return; + return { width: this.parent.width, height: this.parent.height }; + } /** * Gets the vyi this frame belongs to. - * * @returns {VYI} The vyi this frame belongs to. */ getVyi() { @@ -120,7 +167,6 @@ export class Frame { } /** * Gets the icon this frame belongs to. - * * @returns {Icon} The icon this frame belongs to. */ getParent() { @@ -132,14 +178,10 @@ export class Frame { * @returns {Array} An array of data related to this frame in the proper vyi format. */ export() { - const frameData = []; - // frame dataURL - frameData[0] = this.getDataURL(); - // We do not have to store the delay if it is the default value of 100. This will save data. + const frameData = [this.getDataURL()]; const delayIsDefault = this.getDelay() === Frame.defaultDelay; if (!delayIsDefault) { - // frame delay - frameData[1] = this.getDelay(); + frameData[1] = this.getDelay() || Frame.defaultDelay; } return frameData; } diff --git a/src/icon.mjs b/src/icon.mjs index 4c3d603..4c9e8c7 100644 --- a/src/icon.mjs +++ b/src/icon.mjs @@ -6,17 +6,17 @@ import { Frame } from './frame.mjs'; */ export class Icon { /** - * An array of Icon's that are state of this icon. + * A map of icons that are state of this icon. * @private - * @type {Array} + * @type {Map} */ - states = []; + states = new Map(); /** - * An arary of Frame's that are the frames of this icon. + * A map of frames that are the frames of this icon. * @private - * @type {Array} + * @type {Map} */ - frames = []; + frames = new Map(); /** * The width of this icon. All states and frames of this icon must match this size. * @private @@ -61,62 +61,82 @@ export class Icon { */ vyi; /** - * A random unique ID attached to each icon to distinguish them from others in the event another icon shares the same name. + * A random unique Id attached to each icon to distinguish them from others in the event another icon shares the same name. * * @private * @type {string} */ id; + /** + * An set of used Ids to prevent collusion between duplicate named icons. + * + * @private + * @type {Set} + */ + static reservedIds = new Set(); /** * Generates a UUID (Universally Unique Identifier) version 4. * * @private - * @param {VYI} pVYI - The vyi that will reserve this ID. * @returns {string} The generated UUID. */ - static generateID(pVYI) { - const genID = () => { + static generateId() { + const genId = () => { return Math.floor(Math.random() * 0xFFFFFFFF).toString(16).padStart(8, '0'); } - // Generate a random number in the range of 0 to 0xFFFFFFFF (8 hex digits) and convert to hex - let id = genID(); - while (pVYI.reservedIDs.includes(id)) { - id = genID(); + + let id = genId(); + while (this.reservedIds.has(id)) { + id = genId(); } - pVYI.reservedIDs.push(id); + this.reservedIds.add(id); return id; } /** * Creates this icon instance. - * @param {Object} pIconData - The icon data that is used to build this icon. - * @param {VYI} pVYI - The vyi this icon | state belongs to. + * @param {Array} pIconData - The icon data that is used to build this icon. * @private */ - constructor(pIconData, pVYI) { - this.vyi = pVYI; - this.assignID(pVYI); + constructor(pIconData) { this.parse(pIconData); + this.assignId(); } /** - * Assigns an ID to this icon. + * Sets the vyi of this icon. * - * @param {VYI} pVYI - The vyi that holds this ID. + * @private + * @param {VYI} pVyi - The vyi that owns this icon. + */ + setVyi(pVyi) { + if (!pVyi) return; + + if (pVyi instanceof VYI) { + this.vyi = pVyi; + } + } + /** + * Removes the vyi from this icon. + * @private + */ + removeVyi() { + this.vyi = null; + } + /** + * Assigns an Id to this icon. * @private */ - assignID(pVYI) { - this.id = Icon.generateID(pVYI); + assignId() { + this.id = Icon.generateId(); } /** * Gets the id of this icon. - * * @returns {string} The id of this icon. */ - getID() { + getId() { return this.id; } /** * Gets the vyi this icon belongs to. - * * @returns {VYI} The vyi this icon belongs to. */ getVyi() { @@ -124,19 +144,19 @@ export class Icon { } /** * Gets the icon this state belongs to. If this icon is not a state, it will return undefined. - * * @returns {Icon|undefined} The icon this state belongs to. */ getParent() { return this.parent; } /** - * parses through the icon data and adds data to this icon. - * @param {Object} pIconData - The icon data that is used to build this icon. - * @private + * Parses through the icon data and adds data to this icon. + * @param {Array} pIconData - The icon data that is used to build this icon. */ parse(pIconData) { - // Loop through pIconData and create this icon + if (!pIconData) return; + + // Loop through the icon data and create this icon const iconName = pIconData[0]; const iconWidth = pIconData[1]; const iconHeight = pIconData[2]; @@ -195,13 +215,27 @@ export class Icon { * @returns {self} This icon instance. */ setSize(pWidth, pHeight) { - if (typeof(pWidth) === 'number') { + if (typeof pWidth === 'number') { this.width = pWidth; } - if (typeof(pHeight) === 'number') { + if (typeof pHeight === 'number') { this.height = pHeight; } } + /** + * Gets the width of the icon. + * @returns {number} The width of the icon. + */ + getWidth() { + return this.width; + } + /** + * Gets the height of the icon. + * @returns {number} The height of the icon. + */ + getHeight() { + return this.height; + } /** * Gets the width and height of this icon and returns it. * @returns {Object} An object with the width and height of this icon. @@ -215,12 +249,10 @@ export class Icon { * @returns {self} This icon instance. */ setDataURL(pDataURL) { - if (pDataURL) { - if (typeof(pDataURL) === 'string') { - this.dataURL = pDataURL; - } else { - VYI.logger.prefix('VYI-module').error('Invalid data url type!'); - } + if (typeof pDataURL === 'string') { + this.dataURL = pDataURL; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid data url type!'); } return this; } @@ -237,12 +269,10 @@ export class Icon { * @returns {self} This icon instance. */ setDelay(pDelay) { - if (pDelay) { - if (typeof(pDelay) === 'number') { - this.delay = pDelay; - } else { - VYI.logger.prefix('VYI-module').error('Invalid delay type!'); - } + if (typeof pDelay === 'number') { + this.delay = pDelay; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid delay type!'); } return this; } @@ -259,12 +289,10 @@ export class Icon { * @returns {self} This icon instance. */ rename(pName) { - if (pName || pName === '') { - if (typeof(pName) === 'string') { - this.name = pName; - } else { - VYI.logger.prefix('VYI-Module').error('Invalid type for pName!'); - } + if (typeof pName === 'string') { + this.name = pName; + } else { + VYI.logger.prefix('Vyi-module').error('Invalid type for pName!'); } return this; } @@ -281,111 +309,70 @@ export class Icon { * @returns {self} This icon instance. */ setAllFrameDelays(pDelay) { - if (pDelay) { - if (typeof(pDelay) === 'number') { - this.setDelay(pDelay); - this.frames.forEach((pFrame) => { - pFrame.setDelay(pDelay); - }); - } else { - VYI.logger.prefix('VYI-Module').error('Invalid type for pDelay!'); - } + if (typeof pDelay === 'number') { + this.setDelay(pDelay); + this.getFrames().forEach((pFrame) => pFrame.setDelay(pDelay)); + } else { + VYI.logger.prefix('Vyi-module').error('Invalid type for pDelay!'); } return this; } /** - * Adds this icon data as a state. A state is also an icon. - * @param {Object} pIconData - The data used to create this state icon. - * @returns {Icon|undefined} The state that was added or undefined. + * Adds a new frame to this icon. + * @param {Frame|Array} pFrameData - The frame data to give this frame. + * @returns {Frame|undefined} The frame that was added or undefined. */ - addState(pIconData) { - if (pIconData instanceof Object) { - const state = new Icon(pIconData, this.vyi); - state.parent = this; - this.states.push(state); - return state; + addFrame(pFrameData) { + if (!pFrameData) { + VYI.logger.prefix('Vyi-module').error('No frame data passed!'); + return; } - } - /** - * Removes the state passed or the state with the name pName. - * @param {Icon} pState - The state to remove from this icon. pName should be not be used in tandem with this method of removing. - * @param {string} pName - The name of the state to remove. pState must be undefined to use this method for removing. - * @returns {self} This icon instance. - */ - removeState(pState, pName) { - // The index used to remove this frame. - let index; - // Remove via reference to state. - if (this.states.includes(pState)) { - index = this.states.indexOf(pState); - // Remove via reference to name - } else if (typeof(pName) === 'string') { - const state = this.getState(pName); - if (state) { - index = this.states.indexOf(state); - } - } else { - VYI.logger.prefix('VYI-Module').error('Failed to remove state!'); - return this; + + if (!(pFrameData instanceof Frame) && !Array.isArray(pFrameData)) { + VYI.logger.prefix('Vyi-module').error('Invalid frame data type passed!'); + return; } - if (typeof(index) === 'number') { - // Remove the state - this.states.splice(index, 1); + + // Create the icon instance + const frame = pFrameData instanceof Frame + ? pFrameData + : new Frame(pFrameData); + + if (frame.getWidth() !== frame.getWidth() || frame.getHeight() !== frame.getHeight()) { + VYI.logger.prefix('Vyi-module').error('Frame dimensions do not match parent!'); + return; } - return this; + + frame.setParent(this); + // We store this frame under its index in the Map 0-1 + this.frames.set(this.frames.size, frame); + this.indexFrames(); + + return frame; } /** - * Adds a new frame to this icon. - * @param {Array} pFrameData - The frame data to give this frame. - * @returns {Frame|undefined} The frame that was added or undefined. + * Removes the frame passed. + * @param {Frame} pFrame - The frame to remove from this icon. + * @returns {self} This icon instance. */ - addFrame(pFrameData) { - if (pFrameData) { - if (Array.isArray(pFrameData)) { - const frame = new Frame(pFrameData, this); - // Add the frame to the frames array. - this.frames.push(frame); - // Re-index frames after a change + removeFrame(pFrame) { + if (!pFrame) return; + if (pFrame instanceof Frame) { + if (this.frames.delete(pFrame.index)) { + pFrame.removeParent(); this.indexFrames(); - return frame; - } else { - VYI.logger.prefix('VYI-Module').error('Invalid frame data passed!'); } - } else { - VYI.logger.prefix('VYI-Module').error('No frame data passed!'); } + return this; } /** - * Removes the frame passed or the frame that exists at pIndex. - * @param {Frame} pFrame - The frame to remove from this icon. pIndex should be not be used in tandem with this method of removing. - * @param {number} pIndex - The index of the frame to remove. pFrame must be undefined to use this method for removing. + * Removes the frame via it's index. + * @param {number} pIndex - The index of the frame to remove. * @returns {self} This icon instance. */ - removeFrame(pFrame, pIndex) { - // The index used to remove this frame. - let index; - // Remove via reference to frame. - if (this.frames.includes(pFrame)) { - index = this.frames.indexOf(pFrame); - // Remove via index passed. - } else if (pIndex || pIndex === 0) { - if (typeof(pIndex) === 'number') { - const frame = this.getFrame(pIndex); - if (frame) { - index = pIndex; - } - } else { - VYI.logger.prefix('VYI-Module').error('Invalid pIndex type!'); - } - } else { - VYI.logger.prefix('VYI-Module').error('Failed to remove frame!'); - } - if (typeof(index) === 'number') { - // Remove the frame - this.frames.splice(index, 1); - // Re-index frames after a change - this.indexFrames(); - } + removeFrameByIndex(pIndex) { + const frame = this.getFrame(pIndex); + this.removeFrame(frame); return this; } /** @@ -393,8 +380,7 @@ export class Icon { * @private */ indexFrames() { - // Reorder the frames after removing. - this.frames.forEach((pFrame, pIndex) => { + this.getFrames().forEach((pFrame, pIndex) => { pFrame.index = pIndex; }); } @@ -402,27 +388,17 @@ export class Icon { * Reorders the frame in the animation. The index of the passed frame will be swapped with the frame at pIndex. * The "first" frame of the animation is technically this icon's dataURL. So if you are aiming to change the order of this icon and convert it into a frame. * pCurrentIndex must be set to -1 to match this icon. + * * @param {number} pCurrentIndex - The current index of the frame. * @param {number} pIndex - The index the frame will be moving to. * @returns {self} This icon instance. */ reorderFrame(pCurrentIndex, pIndex) { - if (typeof(pCurrentIndex) === 'number' && typeof(pIndex) === 'number') { - let frameAtIndex; - let currentFrame; - // We check if the current index is -1, if it is then it means we want to treat this icon as a frame. As the icon data and delay of this icon serves - // as the frame 0. - if (pCurrentIndex === -1) { - currentFrame = this; - // Otherwise if the index passed can be found in the frames array, then we use that frame. - } else if (this.frames[pCurrentIndex]) { - currentFrame = this.frames[pCurrentIndex]; - } - - // We get the frame at the specified index. - if (this.frames[pIndex]) { - frameAtIndex = this.frames[pIndex]; - } + if (typeof pCurrentIndex === 'number' && typeof pIndex === 'number') { + let frameAtIndex = this.getFrame(pIndex); + let currentFrame = pCurrentIndex === -1 + ? this + : this.getFrame(pCurrentIndex) // If both frames can be found, we can swap their data. if (currentFrame && frameAtIndex) { @@ -436,14 +412,15 @@ export class Icon { // Swap data from frame currentFrame.setDataURL(frameAtIndexDataURL); currentFrame.setDelay(frameAtIndexDelay); + // Swap data to frame frameAtIndex.setDataURL(currentFrameDataURL); frameAtIndex.setDelay(currentFrameDelay); } else { - VYI.logger.prefix('VYI-Module').error('There was no frame found at pCurrentIndex, or there was no frame found at pIndex!'); + VYI.logger.prefix('Vyi-module').error('There was no frame found at pCurrentIndex, or there was no frame found at pIndex!'); } } else { - VYI.logger.prefix('VYI-Module').error('Invalid type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid type used!'); } return this; } @@ -455,18 +432,14 @@ export class Icon { * @returns {Frame|undefined} The frame found at pIndex. */ getFrame(pIndex) { - if (typeof(pIndex) === 'number') { - return this.frames[pIndex]; - } else { - VYI.logger.prefix('VYI-Module').error('Invalid type used!'); - } + return this.frames.get(pIndex); } /** * Returns an array of all the frames this icons has. * @returns {Array} An array of frames this icon has. */ getFrames() { - return [ ...this.frames ]; + return Array.from(this.frames.values()); } /** * Gets all the frames belonging to this icon. @@ -474,36 +447,130 @@ export class Icon { * @returns {Array} An array containing the frame data of all frames. */ getFramesData() { - const frameDataArray = []; - this.frames.forEach((pFrame) => { - frameDataArray.push(pFrame.export()); - }); + const frameDataArray = this.getFrames().map((pFrame) => pFrame.export()); return frameDataArray; } /** - * Gets the state that has the name pName. + * Adds this icon data as a state. A state is also an icon. + * @param {Array} pIconData - The data used to create this state icon. + * @returns {Icon|undefined} The state that was added or undefined. + */ + addState(pIconData) { + if (!pIconData) { + VYI.logger.prefix('Vyi-module').error('No icon data passed!'); + return; + } + + if (!(pIconData instanceof Icon) && !Array.isArray(pIconData)) { + VYI.logger.prefix('Vyi-module').error('Invalid icon data type passed!'); + return; + } + + // Create the icon instance + const state = pIconData instanceof Icon + ? pIconData + : new Icon(pIconData); + + if (state.getWidth() !== this.getWidth() || state.getHeight() !== this.getHeight()) { + VYI.logger.prefix('Vyi-module').error('State dimensions do not match parent!'); + return; + } + + state.setParent(this); + state.setVyi(this.vyi); + this.states.set(state.id, state); + + return state; + } + /** + * Sets the parent for this state. + * @private + * @param {Icon} pParent - The parent icon of this state. + */ + setParent(pParent) { + if (!pParent || this.parent) return; + if (pParent instanceof Icon) { + this.parent = pParent; + } + } + /** + * Removes the parent and vyi from this state. + * @private + */ + removeParent() { + if (this.parent) { + this.parent = null; + this.vyi = null; + } + } + /** + * Removes the state passed. + * @param {Icon} pState - The state to remove from this icon. + * @returns {self} This icon instance. + */ + removeState(pState) { + if (pState instanceof Icon) { + if (this.icons.delete(pState.id)) {; + pState.removeParent(); + } + } + return this; + } + /** + * Removes the state via it's name. The LAST defined icon that has the passed name will be removed. As names are not unique. + * @param {string} pName - The name to use to find the state. + * @returns {self} This icon instance. + */ + removeStateByName(pName) { + const state = this.getState(pName); + this.removeState(state); + return this; + } + /** + * Removes the state via it's id. + * @param {string} pName - The id to use to find the state. + * @returns {self} This icon instance. + */ + removeStateById(pId) { + const state = this.getStateById(pId); + this.removeState(state); + return this; + } + /** + * Gets the state that has the name pName. The LAST defined state that has the passed name will be returned. * @param {string} pName - The name of the state to get. * @returns {Icon} The state that has the name of pName. */ getState(pName) { - if (typeof(pName) === 'string') { - for (let i = this.states.length - 1; i >= 0; i--) { - const icon = this.states[i]; + if (typeof pName === 'string') { + const states = this.getStates(); + for (let i = states.length - 1; i >= 0; i--) { + const state = states[i]; // If the icon has the same name, return that icon - if (icon.getName() === pName) { - return icon; + if (state.getName() === pName) { + return state; } } } else { - VYI.logger.prefix('VYI-module').error('Invalid name type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid name type used!'); } } + /** + * Gets the state by the id provided. + * @private + * @param {string} pId - The id of the state. + * @returns {Icon} The state that has the id that was passed. + */ + getStateById(pId) { + if (!pId) return; + return this.states.get(pId); + } /** * Returns an array of all the states this icons has. * @returns {Array} An array of states this icon has. */ getStates() { - return [ ...this.states ]; + return Array.from(this.states.values()); } /** * Gets all the states belonging to this icon. @@ -511,11 +578,7 @@ export class Icon { * @returns {Array} An array containing the state data of all frames. */ getStatesData() { - const stateDataArray = []; - // Loop state array to export relevant information. - this.states.forEach((pState) => { - stateDataArray.push(pState.exportAsState()); - }); + const stateDataArray = this.getStates().map((pState) => pState.exportAsState()); return stateDataArray; } /** @@ -532,12 +595,7 @@ export class Icon { // state frame delay stateData[2] = this.getDelay(); // state frame array - stateData[3] = []; - - // Loop frame array to export relevant information. - this.frames.forEach((pFrame) => { - stateData[3].push(pFrame.export()); - }); + stateData[3] = this.getFrames().map((pFrame) => pFrame.export()); return stateData; } /** @@ -549,12 +607,10 @@ export class Icon { const iconData = []; // icon name iconData[0] = this.getName(); - // Get the size of this icon. - const size = this.getSize(); // icon width - iconData[1] = size.width; + iconData[1] = this.getWidth(); // icon height - iconData[2] = size.height; + iconData[2] = this.getHeight(); // frame delay iconData[3] = this.getDelay(); // icon DataURL @@ -562,10 +618,8 @@ export class Icon { // frame array iconData[5] = this.getFramesData(); - // this is actually an optional data entry into the vyi, only used if states actually exist on this icon. - // this will save data - if (this.states.length) { - // states array + // This is actually an optional data entry into the vyi, only used if states actually exist on this icon. + if (this.states.size > 0) { iconData[6] = this.getStatesData(); } return iconData; diff --git a/src/vyi.mjs b/src/vyi.mjs index 4d71d51..22b5b37 100644 --- a/src/vyi.mjs +++ b/src/vyi.mjs @@ -1,11 +1,12 @@ import { Logger } from './vendor/logger.mjs'; import { Icon } from './icon.mjs'; +import { Frame } from './frame.mjs'; import pako from './vendor/pako.esm.mjs'; /** * @public */ -export class VYI { +class VYI { /** * The version of the module. */ @@ -16,11 +17,11 @@ export class VYI { */ static logger = new Logger(); /** - * An array of icons that belong to this VYI + * A map of icons that belong to this VYI * @private - * @type {Array} + * @type {Map} */ - icons = []; + icons = new Map(); /** * The name of this vyi. * @private @@ -32,20 +33,13 @@ export class VYI { * @private * @type {number} */ - formatVersion; - /** - * An array of used IDs to prevent collusion between duplicate named icons. - * - * @private - * @type {Array} - */ - reservedIDs = []; + formatVersion = 1; /** * Initializes this module with the information from the VYI passed. * @param {Object} pVyiData - A JSON / Javascript object containing the vyi information.this.ogger */ constructor(pVyiData) { - VYI.logger.registerType('VYI-Module', '#ff6600'); + VYI.logger.registerType('Vyi-module', '#ff6600'); this.parse(pVyiData); } /** @@ -63,31 +57,28 @@ export class VYI { try { let vyi; - if (typeof(pVyiData) === 'string') { - const isNodeEnv = typeof(window) === 'undefined'; + if (typeof pVyiData === 'string') { + const isNodeEnv = typeof window === 'undefined'; vyi = isNodeEnv ? await this.readFileAndGetVYI(pVyiData) : await this.fetchAndParseJSON(pVyiData); - } else if (typeof(pVyiData) === 'object' && !Array.isArray(pVyiData) && !(pVyiData instanceof ArrayBuffer || pVyiData instanceof Uint8Array)) { + } else if (pVyiData instanceof VYI) { + vyi = pVyiData.export(); + } else if (pVyiData instanceof Object && !Array.isArray(pVyiData) && !(pVyiData instanceof ArrayBuffer || pVyiData instanceof Uint8Array)) { vyi = pVyiData; } else if (pVyiData instanceof ArrayBuffer || pVyiData instanceof Uint8Array) { vyi = await this.handleBinaryData(pVyiData); } else { - throw new Error('Invalid input type provided.'); + throw new Error('Error processing: Invalid input type provided.'); } - // If there is valid vyi data, process it - if (vyi) { - this.processVyiData(vyi); - } + this.processVyiData(vyi); } catch (pError) { - VYI.logger.prefix('VYI-module').error(`Error processing VYI data: ${pError.message}`); - throw pError; // Rethrow the error for further handling + VYI.logger.prefix('Vyi-module').error(`${pError.message}`); } } /** * Reads a file and returns the vyi from it. - * * @private * @param {string} - The URL to read the data from. * @returns {Promise} - The vyi from the file. @@ -99,7 +90,6 @@ export class VYI { } /** * Fetches data from a URL and parses it as JSON. - * * @private * @param {string} pURL - The URL to fetch the data from. * @returns {Promise} - A promise that resolves to the parsed JSON data. @@ -115,7 +105,6 @@ export class VYI { } /** * Handles binary data (ArrayBuffer or Uint8Array). Attempts to inflate or decode it. - * * @private * @param {ArrayBuffer|Uint8Array} pBinaryData - The binary data to process. * @returns {Object|string|null} - The parsed JSON object or decoded string, or null if it fails. @@ -135,7 +124,6 @@ export class VYI { } /** * Processes the parsed VYI data and adds icons to the VYI module instance. - * * @private * @param {Object} pVyi - The parsed VYI data. */ @@ -148,104 +136,114 @@ export class VYI { this.addIcon(pIconData, this); }); } else { - VYI.logger.prefix('VYI-module').error('Invalid .vyi file! Cannot parse icons.'); + VYI.logger.prefix('Vyi-module').error('Invalid .vyi file! Cannot parse icons.'); } } /** * Adds an icon to this VYI. - * @param {Object} pIconData - The icon data to use. + * @param {Icon|Array} pIconData - The icon data to use. * @returns {Icon|undefined} - The Icon added or undefined. */ addIcon(pIconData) { - if (pIconData) { - if (pIconData instanceof Object) { - const icon = new Icon(pIconData, this); - // Add the icon to the icons array. - this.icons.push(icon); - return icon; - } else { - VYI.logger.prefix('VYI-module').error('Invalid icon data type passed!'); - } - } else { - VYI.logger.prefix('VYI-module').error('No icon data passed!'); + if (!pIconData) { + VYI.logger.prefix('Vyi-module').error('No icon data passed!'); + return; } + + if (!(pIconData instanceof Icon) && !Array.isArray(pIconData)) { + VYI.logger.prefix('Vyi-module').error('Invalid icon data type passed!'); + return; + } + + // Create the icon instance + const icon = pIconData instanceof Icon + ? pIconData + : new Icon(pIconData); + + icon.setVyi(this); + this.icons.set(icon.id, icon); + return icon; } /** - * Removes the icon passed or the icon with the name pName. - * @param {Icon} pIcon - The state to remove from this icon. pName should be not be used in tandem with this method of removing. - * @param {string} pName - The name of the icon to remove. pIcon must be undefined to use this method for removing. + * Removes the icon passed. + * @param {Icon} pIcon - The icon to remove from this vyi. */ - removeIcon(pIcon, pName) { - const icon = pIcon || this.getIcon(pName); - if (icon) { - if (this.icons.includes(icon)) { - this.icons.splice(this.icons.indexOf(icon), 1); + removeIcon(pIcon) { + if (!pIcon) return; + if (pIcon instanceof Icon) { + if (this.icons.delete(pIcon.id)) {; + pIcon.removeVyi(); } } } + /** + * Removes the icon via it's name. The LAST defined icon that has the passed name will be removed. As names are not unique. + * @param {string} pName - The name to use to find the icon. + */ + removeIconByName(pName) { + const icon = this.getIcon(pName); + this.removeIcon(icon); + } + /** + * Removes the icon via it's id. + * @param {string} pName - The id to use to find the icon. + */ + removeIconById(pId) { + const icon = this.getIconById(pId); + this.removeIcon(icon); + } /** * Returns all the icon names in this vyi. * @returns {Array} An array of icon names in this vyi. */ getIconNames() { - // Array to store the icon names. - const iconNames = []; - this.icons.forEach((pIcon) => { - iconNames.push(pIcon.name); - }); + const iconNames = this.getIcons().map((pIcon) => pIcon.name); return iconNames; } /** - * Gets the icon that has the name pName. + * Gets the icon that has the name pName. The LAST defined icon that has the passed name will be returned. * @param {string} pName - The name of the icon to get. * @returns {Icon|undefined} The icon that has the name pName or undefined. */ getIcon(pName) { - if (typeof(pName) === 'string') { - for (let i = this.icons.length - 1; i >= 0; i--) { - const icon = this.icons[i]; + if (typeof pName === 'string') { + const icons = this.getIcons(); + for (let i = icons.length - 1; i >= 0; i--) { + const icon = icons[i]; // If the icon has the same name, return that icon if (icon.getName() === pName) { return icon; } } } else { - VYI.logger.prefix('VYI-module').error('Invalid name type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid name type used!'); } } /** * Gets an icon by the id provided. - * - * @private - * @param {string} pID - The id of the icon. + * @param {string} pId - The id of the icon. * @returns {Icon} The icon that has the id that was passed. */ - getIconByID(pID) { - if (!pID) return; - for (const icon of this.icons) { - for (const state of icon.states) { - if (state.id === pID) return state; - } - if (icon.id === pID) return icon; - } + getIconById(pId) { + if (!pId) return; + return this.icons.get(pId); } /** * Gets all the icons in this vyi. * @returns {Array} */ getIcons() { - return [...this.icons]; + return Array.from(this.icons.values()); } /** * Renames the vyi. - * * @param {string} pName - The name to give this vyi. */ rename(pName) { - if (typeof(pName) === 'string') { + if (typeof pName === 'string') { this.name = pName; } else { - VYI.logger.prefix('VYI-module').error('Invalid name type used!'); + VYI.logger.prefix('Vyi-module').error('Invalid name type used!'); } } /** @@ -261,14 +259,10 @@ export class VYI { */ export() { const vyi = {}; - // Set version vyi.v = this.formatVersion; - // Set the icons array - vyi.i = []; - this.icons.forEach((pIcon) => { - // Push the icon data to the vyi export object. - vyi.i.push(pIcon.export()); - }); + vyi.i = this.getIcons().map((pIcon) => pIcon.export()); return vyi; } -} \ No newline at end of file +} + +export { VYI, Icon, Frame }; \ No newline at end of file

NameTypeDescription
- The name of the icon to remove. pIcon must be undefined to use this method for removing. + The name to use to find the icon.