Changeset View
Standalone View
binaries/data/mods/mod/gui/common/animateGUI.js
/** | |||||
* Simple GUI animator addon | |||||
* GUIObject can be a string or a GUI object | |||||
* Use: | |||||
* animate (GUIObject, settings) | |||||
* animate.complete (GUIObject, [completeQueue]) | |||||
* animate.end (GUIObject, [endQueue]) | |||||
* animate.chain (GUIObject, chainSettingsList, [defaultSettings]) | |||||
* | |||||
* Example of settings: | |||||
* | |||||
* let settings = { | |||||
* "color": "255 255 255 12", | |||||
* "color": { | |||||
* "r": 255, "g": 255, "b": 255, "a": 12 | |||||
* }, | |||||
* "textcolor": "140 140 140 28", | |||||
* "textcolor": { | |||||
* "r": 140, "g": 140, "b": 140, "a": 28 | |||||
* }, | |||||
* "size": "rleft%left rtop%top rright%right rbottom%bottom", | |||||
* "size": { | |||||
* "left": 0, "top": 10, "right": 250, "bottom": 300, | |||||
* "rleft": 50, "rtop": 50, "rright": 50, "rbottom": 100, | |||||
* }, | |||||
* "duration": 1000, | |||||
* "delay": 100, | |||||
* "curve": "linear", | |||||
* "onStart": function () { warn("animation has started") }, | |||||
* "onTick": function () { warn("animation has ticked") }, | |||||
* "onComplete": function () { warn("animation has completed") }, | |||||
* "onStartNoDelay": false, | |||||
* "onTickNoDelay": false, | |||||
* "queue": false, | |||||
* }; | |||||
* | |||||
* "textcolor" only works with objects of type="text" | |||||
bb: type="string" | |||||
* "color" only works with if the object sprite is defined as sprite="color: R G B A" | |||||
* "size" always works | |||||
* | |||||
* AnimateGUIObject.default for defaults that can be changed | |||||
* AnimateGUIObject.curves for types of curves that can be changed | |||||
* | |||||
* Each setting can be set independent from the other (including individual values of each setting) | |||||
* In case of two animations with the same setting the new animation setting will overrite the old one | |||||
*/ | |||||
Done Inline ActionsThe spaces do not really help the readability and they are wrong from a style convention perspective, please nuke. One could consider newlines to group related settings together bb: The spaces do not really help the readability and they are wrong from a style convention… | |||||
function AnimateGUIObject(GUIObject, settings) | |||||
{ | |||||
this.GUIObject = GUIObject; | |||||
this.settings = deepfreeze(settings); | |||||
this.queue = clone((settings.queue === undefined) ? AnimateGUIObject.default.queue : this.settings.queue); | |||||
Done Inline ActionsAre those clones really required? Also instead of a default object somewhere hidden, I rather have them inline here i.e bb: Are those clones really required? Also instead of a default object somewhere hidden, I rather… | |||||
Done Inline ActionsYeah, clones are required, imagine you share an object properties for an animation setting, some of that might get modified so better be sure from the start you have two independent values. I have moved the default to the top. IMHO having all defaults grouped allows to find/modify them faster. nani: Yeah, clones are required, imagine you share an object properties for an animation setting… | |||||
this.values = {}; | |||||
this.values.delay = clone((this.settings.delay === undefined) ? (AnimateGUIObject.default.delay) : Math.max(0, this.settings.delay)); | |||||
this.values.duration = clone((this.settings.duration === undefined) ? AnimateGUIObject.default.duration : Math.max(0, this.settings.duration)); | |||||
// Stores if something has already been marked as done | |||||
this.done = {}; | |||||
// Stores the settings parsed data, filled when an AnimateGUIObject.prototype.run is called | |||||
this.properties = {}; | |||||
// Stores the settings parsed actions, filled when AnimateGUIObject.prototype.onStart is called | |||||
this.attributes = {}; | |||||
this.parseSettingsProperty("size", "sizeStringToObject"); | |||||
this.parseSettingsProperty("color", "rgbaStringToObject"); | |||||
this.parseSettingsProperty("textcolor", "rgbaStringToObject"); | |||||
return this; | |||||
} | |||||
AnimateGUIObject.prototype.elements = { | |||||
"size": { | |||||
"types": deepfreeze(["left", "top", "right", "bottom", "rleft", "rtop", "rright", "rbottom"]) | |||||
}, | |||||
Not Done Inline ActionsIIRC we use uppercase for prototype function names, one could take a look at the simulation. elexis: IIRC we use uppercase for prototype function names, one could take a look at the simulation. | |||||
Done Inline Actionsuppercase or lower camel case ? Most of rmgen prototypes don't start with uppercase. nani: uppercase or lower camel case ? Most of rmgen prototypes don't start with uppercase. | |||||
"color": { | |||||
"types": deepfreeze(["r", "g", "b", "a"]) | |||||
}, | |||||
"textcolor": { | |||||
"types": deepfreeze(["r", "g", "b", "a"]) | |||||
} | |||||
Done Inline ActionsDislike the duplication in these switches, I guess one could define an object like { "size": { "setFunction": () => setFoo (), "getFunction": () => getFoo() } etc. } to nuke some of that bb: Dislike the duplication in these switches, I guess one could define an object like
```{
"size"… | |||||
} | |||||
Done Inline Actionss/switch/object (switch, at least in JS, is an anti-pattern as it fragments the scopes, I think I explained it in another diff a bit longer) elexis: s/switch/object (switch, at least in JS, is an anti-pattern as it fragments the scopes, I think… | |||||
AnimateGUIObject.prototype.setProperty = function (property, object) | |||||
{ | |||||
switch (property) | |||||
{ | |||||
case "size": this.GUIObject.size = object; break; | |||||
case "color": this.GUIObject.sprite = "color: " + this.rgbaObjectToString(object); break; | |||||
case "textcolor": this.GUIObject.textcolor = this.rgbaObjectToString(object); break; | |||||
} | |||||
} | |||||
AnimateGUIObject.prototype.getProperty = function (property) | |||||
{ | |||||
Done Inline ActionsWhy not on init? bb: Why not on init? | |||||
Done Inline ActionsThere is no init, if you mean the constructor then is because the animation instance is created but might be sent to queue (doesn't start so its starting defaults can't be set) nani: There is no init, if you mean the constructor then is because the animation instance is created… | |||||
switch (property) | |||||
{ | |||||
case "size": return this.getSize(); | |||||
case "color": return this.getColor(); | |||||
case "textcolor": return this.getTextcolor(); | |||||
} | |||||
} | |||||
// Filled when AnimateGUIObject.prototype.run is first called | |||||
AnimateGUIObject.prototype.parseSettingsDefaults = function () | |||||
{ | |||||
if (this.done.parseSettingsDefaults) | |||||
return; | |||||
Done Inline ActionsWe don't use these alignments, because adding one longer line would require changing the whitespace of all other lines elexis: We don't use these alignments, because adding one longer line would require changing the… | |||||
this.done.parseSettingsDefaults = true; | |||||
const time = Date.now(); | |||||
this.name = this.GUIObject.name; | |||||
this.values.onStart = (this.settings.onStart === undefined) ? () => { } : this.settings.onStart; | |||||
this.values.start = time + this.values.delay; | |||||
this.values.end = this.values.start + this.values.duration; | |||||
this.values.curve = clone((this.settings.curve === undefined || AnimateGUIObject.curves[this.settings.curve] === undefined) ? AnimateGUIObject.default.curve : this.settings.curve); | |||||
Not Done Inline ActionsIs there any example of a guipage where we only have the size/color etc. in a string? if so we better add a fromString function to JSInterface_GUITypes, than reinvent the wheel here. IMO just assume the this.settings[property] is an object (and thus remove the now irrelevant code) bb: Is there any example of a guipage where we only have the size/color etc. in a string? if so we… | |||||
Done Inline ActionsWell the idea behind these two options is to make the end user life easier so he can choose what he thinks is more practical for him at that given moment. Case 2: nani: Well the idea behind these two options is to make the end user life easier so he can choose… | |||||
this.values.curveFunction = AnimateGUIObject.curves[this.values.curve]; | |||||
this.running = time < this.values.end; | |||||
this.started = time > this.values.start; | |||||
}; | |||||
// Parse property and make sure that the final object is a copy not a reference | |||||
AnimateGUIObject.prototype.parseSettingsProperty = function (property, propertyStringParser) | |||||
{ | |||||
if (this.settings[property] !== undefined) | |||||
this.properties[property] = (typeof this.settings[property] === "string") ? this[propertyStringParser](this.settings[property]) : Object.assign({}, this.settings[property]); | |||||
}; | |||||
AnimateGUIObject.prototype.parseAction = function (property, parametersList) | |||||
{ | |||||
if (this.properties[property] === undefined) | |||||
return; | |||||
let original = this.getProperty(property); | |||||
let attribute = {}; | |||||
Done Inline Actionswhat is "x" here? Also what does this line do? (filter doesn't change the array, it creates a new one) bb: what is "x" here? Also what does this line do? (filter doesn't change the array, it creates a… | |||||
Done Inline ActionsFilter returns the properties that you, in the properties related to the XML object (from the animation settings), have defined you want to change. x is the normalized (unitary) time (with the AnimateGUIObject.curve function applied), x does a simple linear interpolation between the initial value and final value. nani: **Filter** returns the properties that you, in the properties related to the XML object (from… | |||||
attribute.parameters = {}; | |||||
parametersList.filter(type => this.properties[property][type] !== undefined) | |||||
.forEach(type => attribute.parameters[type] = x => original[type] + x * (this.properties[property][type] - original[type])); | |||||
attribute.calc = (x) => | |||||
{ | |||||
let object = this.getProperty(property); | |||||
Object.keys(attribute.parameters).forEach(type => object[type] = attribute.parameters[type](x)); | |||||
Done Inline Actions.size elexis: .size | |||||
this.setProperty(property, object); | |||||
}; | |||||
this.attributes[property] = attribute; | |||||
} | |||||
AnimateGUIObject.prototype.sizeStringToObject = function (text) | |||||
{ | |||||
const types = this.elements["size"].types.slice(0, 4); | |||||
const rtypes = this.elements["size"].types.slice(4, 8); | |||||
const slist = this.splitSpaces(text).map((t) => t.split("%")); | |||||
let size = {}; | |||||
types.forEach((type, index) => | |||||
{ | |||||
const para = slist[index]; | |||||
if (para.length === 2) | |||||
{ | |||||
size[rtypes[index]] = parseInt(para[0]); | |||||
if (para[1] !== "") | |||||
size[type] = this.evalMathExpression(para[1]); | |||||
} | |||||
else | |||||
size[type] = this.evalMathExpression(para[0]); | |||||
}); | |||||
return size; | |||||
}; | |||||
// Can be either input RGB or RGBA | |||||
AnimateGUIObject.prototype.rgbaStringToObject = function (text) | |||||
Done Inline ActionsOne could consider making the object a GUIColor and using the already existing toString on that bb: One could consider making the object a GUIColor and using the already existing `toString` on… | |||||
Done Inline ActionsTrue, will try. nani: True, will try. | |||||
{ | |||||
let color = this.splitSpaces(text); | |||||
return color.length === 4 ? | |||||
{ "r": parseInt(color[0]), "g": parseInt(color[1]), "b": parseInt(color[2]), "a": parseInt(color[3]) } : | |||||
{ "r": parseInt(color[0]), "g": parseInt(color[1]), "b": parseInt(color[2]) }; | |||||
} | |||||
// Can be either input {R,G,B} or {R,G,B,A} | |||||
AnimateGUIObject.prototype.rgbaObjectToString = function (color) | |||||
{ | |||||
return parseInt(color.r) + " " + parseInt(color.g) + " " + parseInt(color.b) + (color.a === undefined ? "" : " " + parseInt(color.a)); | |||||
} | |||||
// This makes a copy (keeps current state) | |||||
AnimateGUIObject.prototype.getSize = function () | |||||
{ | |||||
return this.GUIObject.size; | |||||
Done Inline Actionscolor.js has such transformations, all three functions if Im not mistaken elexis: `color.js` has such transformations, all three functions if Im not mistaken | |||||
} | |||||
/// string input format : "color: R G B A" or "color: R G B" | |||||
AnimateGUIObject.prototype.getColor = function () | |||||
Done Inline Actionsspace goes after comma not before bb: space goes after comma not before | |||||
{ | |||||
let color = this.rgbaStringToObject(this.GUIObject.sprite.split(":")[1]); | |||||
if (this.properties.color["a"] !== undefined && color["a"] === undefined) | |||||
color["a"] = 255; | |||||
return color; | |||||
} | |||||
// String input format as {r:value ,g:value ,b:value ,a:value} (values are ) | |||||
// This makes a copy (keeps current state) | |||||
AnimateGUIObject.prototype.getTextcolor = function () | |||||
{ | |||||
let color = this.GUIObject.textcolor; | |||||
this.elements["textcolor"].types.forEach(type => color[type] = parseInt(255 * color[type])); | |||||
if (this.properties.textcolor["a"] !== undefined && color["a"] === undefined) | |||||
color["a"] = 255; | |||||
return color; | |||||
Not Done Inline Actionsinstead of setting this parameter every tick, one could just set it onIntit, onStart and onComplete achieve the same result. (Together with the comments just below) bb: instead of setting this parameter every tick, one could just set it `onIntit`, `onStart` and… | |||||
Done Inline ActionsSeems worth the try. nani: Seems worth the try. | |||||
} | |||||
Not Done Inline ActionsI guess with the below, this parameter becomes useless bb: I guess with the below, this parameter becomes useless | |||||
Not Done Inline ActionsWhy not set a timer on init for this function? Same for onComplete? With this also the us of the this.done object should be reviewed bb: Why not set a timer on init for this function? Same for `onComplete`? With this also the us of… | |||||
// Run for each tick | |||||
AnimateGUIObject.prototype.run = function (time) | |||||
Not Done Inline ActionsThese two functions seem to have the same purpose: do something every tick (whether it is resizing an guiObject or calling a arbitrary function is indifferent for me), so merge the two bb: These two functions seem to have the same purpose: do something every tick (whether it is… | |||||
{ | |||||
this.parseSettingsDefaults(); | |||||
this.running = time < this.values.end; | |||||
this.started = time >= this.values.start; | |||||
this.onStart(); | |||||
this.update(time); | |||||
this.onTick(); | |||||
this.onComplete(); | |||||
return this.running; | |||||
}; | |||||
// Updates animation object attributes | |||||
Done Inline Actionsseemed to be a clean solution at first sight, however it is to limiting: consider the sliding background at the main menu, that is a perfect example of where such a gui component can be useful, however that needs an infinite liftime, so imo we have to allow that. bb: seemed to be a clean solution at first sight, however it is to limiting: consider the sliding… | |||||
Done Inline ActionsMore than infinite it could be said is a loop with no end, no? I was thinking the loop should be at the animation manager and not at the animation per se. The sliding background would be two animation chained that would loop from one to the other forever (would give more fine grained control too). Opinions? nani: More than infinite it could be said is a loop with no end, no? I was thinking the loop should… | |||||
AnimateGUIObject.prototype.update = function (time) | |||||
{ | |||||
if (!this.started) | |||||
return; | |||||
const uniformTime = this.running ? (time - this.values.start) / this.values.duration : 1; | |||||
Done Inline ActionsIf adding comments, use JSdoc format /** elexis: If adding comments, use JSdoc format /**
| |||||
const x = this.values.curveFunction(uniformTime); | |||||
for (let attribute of Object.keys(this.attributes)) | |||||
this.attributes[attribute].calc(x) | |||||
}; | |||||
// There can be onStart with/without delay and will always execute once per animation | |||||
AnimateGUIObject.prototype.onStart = function () | |||||
{ | |||||
if (!this.values.onStart || (!this.started && !this.settings.onStartNoDelay) || this.done.onStart) | |||||
return; | |||||
this.values.onStart(this.GUIObject); | |||||
this.done.onStart = true; | |||||
// Parse action is called here given that this.values.onStart() could | |||||
// want to modify the object's initial values before the animation starts | |||||
for (let property of Object.keys(this.properties)) | |||||
this.parseAction(property, this.elements[property].types); | |||||
}; | |||||
/** | |||||
* There can be onTick with/without delay or no onTick at all | |||||
* and will always execute once per animation at maximum. | |||||
Done Inline Actionsmissing space bb: missing space | |||||
*/ | |||||
AnimateGUIObject.prototype.onTick = function () | |||||
{ | |||||
if (!this.settings.onTick || (!this.started && !this.settings.onTickNoDelay)) | |||||
return; | |||||
Done Inline Actionsperiod bb: period | |||||
this.settings.onTick(this.GUIObject); | |||||
}; | |||||
/** | |||||
* There can be onComplete with/without delay or no onTick at all | |||||
* and will always execute once per animation at maximum | |||||
Done Inline Actionsmissing space bb: missing space | |||||
*/ | |||||
AnimateGUIObject.prototype.onComplete = function () | |||||
{ | |||||
if (!this.settings.onComplete || this.running || this.done.onComplete) | |||||
return; | |||||
this.settings.onComplete(this.GUIObject); | |||||
this.done.onComplete = true; | |||||
}; | |||||
// Checks if the animation has any attribute/property that still modifies the GUIObject | |||||
AnimateGUIObject.prototype.isAlive = function () | |||||
{ | |||||
return Object.keys(this.properties).length !== 0; | |||||
} | |||||
// Removes properties/attributes from the old animation that the new animation has | |||||
AnimateGUIObject.prototype.removeIntersections = function (newAnimateGUIObject) | |||||
{ | |||||
for (let property of Object.keys(this.properties)) | |||||
this.removePropertyIntersections(newAnimateGUIObject, property) | |||||
return this; | |||||
}; | |||||
AnimateGUIObject.prototype.removePropertyIntersections = function (newAnimateGUIObject, property) | |||||
{ | |||||
if (this.properties[property] === undefined || newAnimateGUIObject.properties[property] === undefined) | |||||
return; | |||||
for (let type of Object.keys(this.properties[property])) | |||||
{ | |||||
if (this.properties[property][type] === undefined || newAnimateGUIObject.properties[property][type] === undefined) | |||||
continue; | |||||
delete this.properties[property][type]; | |||||
if (this.attributes[property] !== undefined && this.attributes[property].parameters !== undefined) | |||||
delete this.attributes[property].parameters[type]; | |||||
} | |||||
if (Object.keys(this.properties[property]).length !== 0) | |||||
return; | |||||
delete this.properties[property]; | |||||
Not Done Inline Actionsticks can in principle have arbitrary length, so don't assume it will be quick enough: directly onComplete him bb: ticks can in principle have arbitrary length, so don't assume it will be quick enough: directly… | |||||
Done Inline ActionsIt will be processed at the next tick anyway no? nani: It will be processed at the next tick anyway no? | |||||
delete this.attributes[property]; | |||||
}; | |||||
// Jump to the end of the animation, onStart/onTick/onComplete behaviour doesn't change. | |||||
AnimateGUIObject.prototype.complete = function () | |||||
{ | |||||
this.value.end = Date.now(); | |||||
} | |||||
Done Inline ActionsI suspect this function or parts from it were taken from some website. If that's the case, you should mention which one you used. elexis: I suspect this function or parts from it were taken from some website. If that's the case, you… | |||||
Done Inline ActionsIt was some stackoverflow post, can't seem to find it. Anyway, nucked for the moment, nani: It was some stackoverflow post, can't seem to find it. Anyway, nucked for the moment, | |||||
// Evaluates +,- expressions | |||||
AnimateGUIObject.prototype.evalMathExpression = function (text) | |||||
Done Inline Actionshttp://trac.wildfiregames.com/wiki/Coding_Conventions states parseInt shall not be used elexis: http://trac.wildfiregames.com/wiki/Coding_Conventions states parseInt shall not be used | |||||
{ | |||||
let val = 0; | |||||
let vals = text.split(/((?:\+|\-)+)/); | |||||
if (vals[0] == "") vals.shift(); else vals.unshift("+"); | |||||
for (let i = 0; i * 2 < vals.length; ++i) | |||||
val += parseInt(vals[i] + vals[i + 1]); | |||||
Done Inline Actionsneed to distinguish space from other falsy values? === / !== only when == / != is insufficient (to have it consistent, mentinoed in other diffs) elexis: need to distinguish space from other falsy values? === / !== only when == / != is insufficient… | |||||
Done Inline ActionsOk mom. nani: Ok mom. | |||||
return val; | |||||
}; | |||||
// Splits text with spaces taking into account repeated spaces. | |||||
AnimateGUIObject.prototype.splitSpaces = function (text) | |||||
{ | |||||
return text.split(" ").filter(t => t !== ""); | |||||
Done Inline ActionsDon't predefine functions, let the calling page do that bb: Don't predefine functions, let the calling page do that | |||||
Done Inline ActionsThese are basic curve settings I don't think is bad to have them. nani: These are basic curve settings I don't think is bad to have them. | |||||
Done Inline ActionsMath.square, Math.pow(x, 3)? I heard that's supposedly slower though elexis: Math.square, Math.pow(x, 3)? I heard that's supposedly slower though | |||||
Done Inline ActionsQuite slow. nani: Quite slow. | |||||
}; | |||||
AnimateGUIObject.curves = { | |||||
"ease-in-out": x => x * x * x * (x * (x * 6 - 15) + 10), | |||||
"ease-in-out-2": x => 3 * x * x * (1 - x) + x * x * x, | |||||
"linear": x => x | |||||
}; | |||||
AnimateGUIObject.default = { | |||||
"duration": 150, | |||||
"curve": "ease-in-out", | |||||
"delay": 0, | |||||
"queue": false, | |||||
}; | |||||
// Manages all the animations | |||||
function AnimateGUI() | |||||
{ | |||||
this.GUIObjects = {}; | |||||
this.GUIObjectsQueue = {}; | |||||
}; | |||||
Done Inline ActionsThis pattern should be avoided. There should be as few ambiguity as possible about the types when passing arguments. local objects start with lowercase elexis: This pattern should be avoided. There should be as few ambiguity as possible about the types… | |||||
AnimateGUI.prototype.parseGUIObject = function (GUIObject) | |||||
{ | |||||
return typeof GUIObject === "string" ? Engine.GetGUIObjectByName(GUIObject) : GUIObject; | |||||
} | |||||
AnimateGUI.prototype.addAnimation = function (GUIObject, settings) | |||||
{ | |||||
const _GUIObject = this.parseGUIObject(GUIObject); | |||||
let newAnimation = new AnimateGUIObject(_GUIObject, settings); | |||||
if (this.GUIObjects[_GUIObject.name] === undefined) | |||||
{ | |||||
// If no animation running. | |||||
this.GUIObjects[_GUIObject.name] = [newAnimation]; | |||||
delete this.GUIObjectsQueue[_GUIObject.name]; | |||||
} | |||||
else if (!newAnimation.queue) | |||||
{ | |||||
// If animation(s) running and new animation doesn't queue. | |||||
// Delete parts of the other animations that conflic with the new one. | |||||
this.GUIObjects[_GUIObject.name] = this.GUIObjects[_GUIObject.name].filter((animation) => | |||||
{ | |||||
return animation.removeIntersections(newAnimation).isAlive(); | |||||
}); | |||||
this.GUIObjects[_GUIObject.name].push(newAnimation); | |||||
delete this.GUIObjectsQueue[_GUIObject.name]; | |||||
} | |||||
else | |||||
{ | |||||
Done Inline Actionsmissing space bb: missing space | |||||
// If animaton(s) running and new animation does queue. | |||||
if (this.GUIObjectsQueue[_GUIObject.name] === undefined) | |||||
this.GUIObjectsQueue[_GUIObject.name] = []; | |||||
this.GUIObjectsQueue[_GUIObject.name].push(newAnimation); | |||||
} | |||||
return this; | |||||
}; | |||||
AnimateGUI.prototype.animationsInQueue = function (objectName) | |||||
{ | |||||
// If there are animations running | |||||
if (this.GUIObjects[objectName].length !== 0) | |||||
return false; | |||||
// If there are no animations running and no animations pending | |||||
else if (this.GUIObjectsQueue[objectName] === undefined) | |||||
delete this.GUIObjects[objectName]; | |||||
// If there are no animations running and animations pending | |||||
Done Inline Actionsno else after return elexis: no else after return | |||||
else | |||||
{ | |||||
let nextAnimation = this.GUIObjectsQueue[objectName].shift(); | |||||
if (nextAnimation === undefined) | |||||
delete this.GUIObjectsQueue[objectName]; | |||||
else | |||||
Done Inline Actions!nextAnimation elexis: !nextAnimation | |||||
{ | |||||
this.GUIObjects[objectName] = [nextAnimation]; | |||||
return true; | |||||
} | |||||
} | |||||
return false; | |||||
} | |||||
AnimateGUI.prototype.onTick = function () | |||||
{ | |||||
const time = Date.now(); | |||||
for (let objectName of Object.keys(this.GUIObjects)) | |||||
{ | |||||
// Repeat loop in case there are multiple animation queued that have delay:0 and duration:0 (AnimateGUI.prototype.complete case) | |||||
do { this.GUIObjects[objectName] = this.GUIObjects[objectName].filter(animation => animation.run(time)) } | |||||
while (this.animationsInQueue(objectName)) | |||||
Not Done Inline Actionskey? elexis: key? | |||||
Done Inline Actionsyeah? nani: yeah? | |||||
} | |||||
}; | |||||
AnimateGUI.prototype.complete = function (GUIObject, completeQueue) | |||||
Done Inline Actionsdo elexis: do
{
...
| |||||
{ | |||||
const GUIObjectName = this.parseGUIObject(GUIObject).name; | |||||
if (this.GUIObjects[GUIObjectName] === undefined) | |||||
return; | |||||
for (let animation of Object.keys(this.GUIObjects[GUIObjectName])) | |||||
this.GUIObjects[GUIObjectName][animation].complete(); | |||||
if (completeQueue !== true || this.GUIObjectsQueue[GUIObjectName] === undefined) | |||||
return; | |||||
for (let animation of this.GUIObjectsQueue[GUIObjectName]) | |||||
{ | |||||
animation.value.delay = 0; | |||||
animation.value.duration = 0; | |||||
} | |||||
return this; | |||||
} | |||||
AnimateGUI.prototype.end = function (GUIObject, endQueue) | |||||
{ | |||||
const GUIObjectName = this.parseGUIObject(GUIObject).name; | |||||
delete this.GUIObjects[GUIObjectName]; | |||||
if (endQueue === true) | |||||
delete this.GUIObjectsQueue[GUIObjectName]; | |||||
return this; | |||||
} | |||||
const animate = function (GUIObject, settings) { animate.gui.addAnimation(GUIObject, settings); } | |||||
animate.onTick = function () { animate.gui.onTick(); } | |||||
animate.gui = new AnimateGUI(); | |||||
// Ends animation as if had reached end time. onStart/onTick/onComplete called as usual | |||||
// Optional argument to complete all remaining queues. | |||||
animate.complete = function (GUIObject, completeQueue) { animate.gui.complete(GUIObject, completeQueue); } | |||||
// Ends animation at given time of command. onStart/onTick/onComplete not called. | |||||
// Optional argument to end all remaining queues. | |||||
animate.end = function (GUIObject, endQueue) { animate.gui.end(GUIObject, endQueue); } | |||||
/** | |||||
* Makes a chained animation | |||||
* @param {Object} GUIObject | |||||
* @param {List} chainSettingsList | |||||
* @param {Object} defaultSettings | |||||
*/ | |||||
animate.chain = function (GUIObject, chainSettingsList, defaultSettings) | |||||
{ | |||||
Done Inline ActionsEvery statement on an own line. global objects start with g_ Naming needs to be more precise, "Animate" can be anything and nothing. elexis: Every statement on an own line.
global objects start with g_
no let in global context… | |||||
Done Inline ActionsIs more of a function than an object, variable... nani: Is more of a function than an object, variable... | |||||
const _defaultSettings = defaultSettings === undefined ? {} : defaultSettings; | |||||
for (let settings of chainSettingsList) | |||||
animate(GUIObject, Object.assign({}, _defaultSettings, settings)); | |||||
} | |||||
No newline at end of file | |||||
Not Done Inline Actionsunnecessary double negation, also use || can be used instead of ?. also defaultSettings = {} in the argument. also default arguments are not so nice. elexis: unnecessary double negation, also use || can be used instead of ?. also defaultSettings = {}… | |||||
Done Inline ActionsThere is no such thing as a list in JS. elexis: There is no such thing as a list in JS.
Don't add the JSdoc if it doesn't add information that… |
type="string"