LCOV - code coverage report
Current view: top level - modules/script/tweener - tweener.js (source / functions) Coverage Total Hit
Test: gjs- Code Coverage Lines: 84.2 % 438 369
Test Date: 2024-04-16 04:37:39 Functions: 83.3 % 42 35
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 79.0 % 252 199

             Branch data     Line data    Source code
       1                 :           1 : /* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil; -*- */
       2                 :             : /* eslint-disable block-scoped-var, eqeqeq, no-shadow, prefer-rest-params */
       3                 :             : // SPDX-License-Identifier: MIT
       4                 :             : // SPDX-FileCopyrightText: 2006-2007 Zeh Fernando and Nate Chatellier
       5                 :             : // SPDX-FileCopyrightText: 2008 litl, LLC.
       6                 :             : 
       7                 :             : /**
       8                 :             :  * Tweener
       9                 :             :  * Transition controller for movieclips, sounds, textfields and other objects
      10                 :             :  *
      11                 :             :  * @author              Zeh Fernando, Nate Chatellier, Arthur Debert
      12                 :             :  * @version             1.31.71
      13                 :             :  */
      14                 :             : /* exported addCaller, addTween, FrameTicker, getTweenCount, getTimeScale,
      15                 :             : pauseAllTweens, pauseTweens, PropertyList, registerSpecialProperty,
      16                 :             : registerSpecialPropertyModifier, registerSpecialPropertySplitter,
      17                 :             : removeAllTweens, removeTweens, restrictedWords, resumeAllTweens, resumeTweens,
      18                 :             : setFrameTicker, setTimeScale */
      19                 :             : 
      20                 :             : /*
      21                 :             :  http://code.google.com/p/tweener/
      22                 :             :  http://code.google.com/p/tweener/wiki/License
      23                 :             :  */
      24                 :             : 
      25                 :           1 : const GLib = imports.gi.GLib;
      26                 :             : 
      27                 :           1 : const TweenList = imports.tweener.tweenList;
      28                 :           1 : const Signals = imports.signals;
      29                 :             : 
      30                 :           1 : var _inited = false;
      31                 :           1 : var _engineExists = false;
      32                 :           1 : var _tweenList = null;
      33                 :             : 
      34                 :           1 : var _timeScale = 1;
      35                 :             : 
      36                 :           1 : var _specialPropertyList = [];
      37                 :           1 : var _specialPropertyModifierList = [];
      38                 :           1 : var _specialPropertySplitterList = [];
      39                 :             : 
      40                 :             : /*
      41                 :             :  * Ticker should implement:
      42                 :             :  *
      43                 :             :  * property FRAME_RATE
      44                 :             :  * start()
      45                 :             :  * stop()
      46                 :             :  * getTime() gets time in milliseconds from start()
      47                 :             :  * signal prepare-frame
      48                 :             :  *
      49                 :             :  */
      50                 :           1 : var _ticker = null;
      51                 :             : 
      52                 :           1 : var _prepareFrameId = 0;
      53                 :             : 
      54                 :             : /* default frame ticker */
      55                 :           1 : function FrameTicker() {
      56                 :           1 :     this._init();
      57                 :             : }
      58                 :             : 
      59                 :           1 : FrameTicker.prototype = {
      60                 :           1 :     FRAME_RATE: 65,
      61                 :             : 
      62                 :           1 :     _init() {
      63                 :             :     },
      64                 :             : 
      65                 :           1 :     start() {
      66                 :           0 :         this._currentTime = 0;
      67                 :             : 
      68                 :           0 :         let me = this;
      69                 :             : 
      70                 :           0 :         this._timeoutID = GLib.timeout_add(
      71                 :           0 :             GLib.PRIORITY_DEFAULT,
      72                 :           0 :             Math.floor(1000 / me.FRAME_RATE),
      73                 :           0 :             function () {
      74                 :           0 :                 me._currentTime += 1000 / me.FRAME_RATE;
      75                 :           0 :                 me.emit('prepare-frame');
      76                 :           0 :                 return true;
      77                 :             :             });
      78                 :             :     },
      79                 :             : 
      80                 :           1 :     stop() {
      81         [ #  # ]:           0 :         if ('_timeoutID' in this) {
      82                 :           0 :             GLib.source_remove(this._timeoutID);
      83                 :           0 :             delete this._timeoutID;
      84                 :             :         }
      85                 :             : 
      86                 :           0 :         this._currentTime = 0;
      87                 :             :     },
      88                 :             : 
      89                 :           1 :     getTime() {
      90                 :           0 :         return this._currentTime;
      91                 :             :     },
      92                 :             : };
      93                 :           1 : Signals.addSignalMethods(FrameTicker.prototype);
      94                 :             : 
      95                 :           1 : _ticker = new FrameTicker();
      96                 :             : 
      97                 :             : /* TODOs:
      98                 :             :  *
      99                 :             :  * Special properties:
     100                 :             :  *
     101                 :             :  * Special properties are 'proxy' properties used in Tweener to tween
     102                 :             :  * (animate) things that are not proper properties per se. One example
     103                 :             :  * given is the 'frame' of an object in ActionScript, which is not an
     104                 :             :  * object property. Using the special property '_frame' you could animate
     105                 :             :  * it like this:
     106                 :             :  *
     107                 :             :  * Tweener.addTween(myMovieClip, {_frame:20, time:1});
     108                 :             :  *
     109                 :             :  * which would be equivalent to applying a fast-forward to it.
     110                 :             :  *
     111                 :             :  * This properties need a special support in the code, and I've removed it
     112                 :             :  * for now until we see the need for it in our clutter based stuff.
     113                 :             :  */
     114                 :             : 
     115                 :             : /* This is a bit pointless now, but let's keep it anyway... */
     116                 :          52 : function _init() {
     117         [ +  - ]:           1 :     if (_inited)
     118                 :           0 :         return;
     119                 :             : 
     120                 :           1 :     _inited = true;
     121                 :             : }
     122                 :             : 
     123                 :           1 : function setFrameTicker(ticker) {
     124                 :           1 :     _ticker = ticker;
     125                 :             : }
     126                 :             : 
     127                 :           2 : function _startEngine() {
     128         [ +  - ]:           2 :     if (_engineExists)
     129                 :           0 :         return;
     130                 :             : 
     131                 :           2 :     _engineExists = true;
     132                 :           2 :     _tweenList = [];
     133                 :             : 
     134         [ +  - ]:           2 :     if (!_ticker)
     135                 :           0 :         throw new Error('Must call setFrameTicker()');
     136                 :             : 
     137                 :           4 :     _prepareFrameId = _ticker.connect('prepare-frame',
     138                 :           2 :         _onEnterFrame);
     139                 :           2 :     _ticker.start();
     140                 :             : }
     141                 :             : 
     142                 :           1 : function _stopEngine() {
     143         [ +  - ]:           1 :     if (!_engineExists)
     144                 :           0 :         return;
     145                 :             : 
     146                 :           1 :     _engineExists = false;
     147                 :           1 :     _tweenList = false;
     148                 :             : 
     149                 :           1 :     _ticker.disconnect(_prepareFrameId);
     150                 :           1 :     _prepareFrameId = 0;
     151                 :           1 :     _ticker.stop();
     152                 :             : }
     153                 :             : 
     154                 :         471 : function _getCurrentTweeningTime() {
     155                 :         471 :     return _ticker.getTime();
     156                 :             : }
     157                 :             : 
     158                 :          73 : function _removeTweenByIndex(i) {
     159                 :          73 :     _tweenList[i] = null;
     160                 :             : 
     161                 :          73 :     var finalRemoval = arguments[1];
     162                 :             : 
     163 [ +  + ][ +  + ]:          73 :     if (finalRemoval != undefined && finalRemoval)
     164                 :          32 :         _tweenList.splice(i, 1);
     165                 :             : 
     166                 :          73 :     return true;
     167                 :             : }
     168                 :             : 
     169                 :           4 : function _resumeTweenByIndex(i) {
     170                 :           4 :     var tweening = _tweenList[i];
     171                 :             : 
     172 [ -  + ][ +  - ]:           4 :     if (tweening == null || !tweening.isPaused)
     173                 :           0 :         return false;
     174                 :             : 
     175                 :           4 :     var currentTime = _getCurrentTweeningTime(tweening);
     176                 :             : 
     177                 :           4 :     tweening.timeStart += currentTime - tweening.timePaused;
     178                 :           4 :     tweening.timeComplete += currentTime - tweening.timePaused;
     179                 :           4 :     tweening.timePaused = undefined;
     180                 :           4 :     tweening.isPaused = false;
     181                 :             : 
     182                 :           4 :     return true;
     183                 :             : }
     184                 :             : 
     185                 :             : /* FIXME: any way to get the function name from the fn itself? */
     186                 :         466 : function _callOnFunction(fn, fnname, scope, fallbackScope, params) {
     187         [ +  + ]:         466 :     if (fn) {
     188         [ +  - ]:          75 :         var eventScope = scope ? scope : fallbackScope;
     189                 :          75 :         try {
     190                 :          75 :             fn.apply(eventScope, params);
     191                 :           0 :         } catch (e) {
     192                 :           0 :             logError(e, `Error calling ${fnname}`);
     193                 :             :         }
     194                 :             :     }
     195                 :             : }
     196                 :             : 
     197                 :         472 : function _updateTweenByIndex(i) {
     198                 :         472 :     var tweening = _tweenList[i];
     199                 :             : 
     200 [ +  + ][ +  + ]:         472 :     if (tweening == null || !tweening.scope)
     201                 :           9 :         return false;
     202                 :             : 
     203                 :         463 :     var currentTime = _getCurrentTweeningTime(tweening);
     204                 :             : 
     205         [ +  + ]:         463 :     if (currentTime < tweening.timeStart)
     206                 :          52 :         return true; // Hasn't started, so return true
     207                 :             : 
     208                 :         411 :     var scope = tweening.scope;
     209                 :             :     var t, b, c, d, nv;
     210                 :             : 
     211                 :         411 :     var isOver = false;
     212                 :             : 
     213         [ +  + ]:         411 :     if (tweening.isCaller) {
     214                 :           5 :         do {
     215                 :          14 :             t = (tweening.timeComplete - tweening.timeStart) / tweening.count *
     216                 :          14 :                 (tweening.timesCalled + 1);
     217                 :          14 :             b = tweening.timeStart;
     218                 :          14 :             c = tweening.timeComplete - tweening.timeStart;
     219                 :          14 :             d = tweening.timeComplete - tweening.timeStart;
     220                 :          14 :             nv = tweening.transition(t, b, c, d);
     221                 :             : 
     222         [ +  + ]:          14 :             if (currentTime >= nv) {
     223                 :          20 :                 _callOnFunction(tweening.onUpdate, 'onUpdate', tweening.onUpdateScope,
     224                 :          10 :                     scope, tweening.onUpdateParams);
     225                 :             : 
     226                 :          10 :                 tweening.timesCalled++;
     227         [ +  + ]:          10 :                 if (tweening.timesCalled >= tweening.count) {
     228                 :           1 :                     isOver = true;
     229                 :             :                     break;
     230                 :             :                 }
     231                 :             : 
     232         [ +  - ]:           9 :                 if (tweening.waitFrames)
     233                 :             :                     break;
     234                 :             :             }
     235         [ +  + ]:          13 :         } while (currentTime >= nv);
     236                 :             :     } else {
     237                 :             :         var mustUpdate, name;
     238                 :             : 
     239         [ +  + ]:         406 :         if (currentTime >= tweening.timeComplete) {
     240                 :          22 :             isOver = true;
     241                 :          22 :             mustUpdate = true;
     242                 :             :         } else {
     243         [ -  + ]:         384 :             mustUpdate = tweening.skipUpdates < 1 ||
     244         [ +  - ]:         384 :                 !tweening.skipUpdates ||
     245                 :           0 :                 tweening.updatesSkipped >= tweening.skipUpdates;
     246                 :             :         }
     247                 :             : 
     248         [ +  + ]:         406 :         if (!tweening.hasStarted) {
     249                 :          48 :             _callOnFunction(tweening.onStart, 'onStart', tweening.onStartScope,
     250                 :          24 :                 scope, tweening.onStartParams);
     251                 :             : 
     252         [ +  + ]:          59 :             for (name in tweening.properties) {
     253                 :             :                 var pv;
     254                 :             : 
     255         [ +  + ]:          35 :                 if (tweening.properties[name].isSpecialProperty) {
     256                 :             :                     // It's a special property, tunnel via the special property function
     257         [ +  - ]:           1 :                     if (_specialPropertyList[name].preProcess != undefined)
     258                 :           0 :                         tweening.properties[name].valueComplete = _specialPropertyList[name].preProcess(scope, _specialPropertyList[name].parameters, tweening.properties[name].originalValueComplete, tweening.properties[name].extra);
     259                 :           1 :                     pv = _specialPropertyList[name].getValue(scope, _specialPropertyList[name].parameters, tweening.properties[name].extra);
     260                 :             :                 } else {
     261                 :             :                     // Directly read property
     262                 :          34 :                     pv = scope[name];
     263                 :             :                 }
     264         [ +  - ]:          35 :                 tweening.properties[name].valueStart = isNaN(pv) ? tweening.properties[name].valueComplete : pv;
     265                 :             :             }
     266                 :             : 
     267                 :          24 :             mustUpdate = true;
     268                 :          24 :             tweening.hasStarted = true;
     269                 :             :         }
     270                 :             : 
     271         [ -  + ]:         406 :         if (mustUpdate) {
     272         [ +  + ]:        1166 :             for (name in tweening.properties) {
     273                 :         760 :                 var property = tweening.properties[name];
     274                 :             : 
     275         [ +  + ]:         760 :                 if (isOver) {
     276                 :             :                     // Tweening time has finished, just set it to the final value
     277                 :          33 :                     nv = property.valueComplete;
     278         [ +  + ]:         727 :                 } else if (property.hasModifier) {
     279                 :             :                     // Modified
     280                 :          49 :                     t = currentTime - tweening.timeStart;
     281                 :          49 :                     d = tweening.timeComplete - tweening.timeStart;
     282                 :          49 :                     nv = tweening.transition(t, 0, 1, d, tweening.transitionParams);
     283                 :          49 :                     nv = property.modifierFunction(property.valueStart, property.valueComplete, nv, property.modifierParameters);
     284                 :             :                 } else {
     285                 :             :                     // Normal update
     286                 :         678 :                     t = currentTime - tweening.timeStart;
     287                 :         678 :                     b = property.valueStart;
     288                 :         678 :                     c = property.valueComplete - property.valueStart;
     289                 :         678 :                     d = tweening.timeComplete - tweening.timeStart;
     290                 :         678 :                     nv = tweening.transition(t, b, c, d, tweening.transitionParams);
     291                 :             :                 }
     292                 :             : 
     293         [ +  - ]:         760 :                 if (tweening.rounded)
     294                 :           0 :                     nv = Math.round(nv);
     295                 :             : 
     296 [ +  + ][ +  + ]:         760 :                 if (tweening.min !== undefined && nv < tweening.min)
     297                 :          50 :                     nv = tweening.min;
     298 [ +  + ][ +  + ]:         760 :                 if (tweening.max !== undefined && nv > tweening.max)
     299                 :          16 :                     nv = tweening.max;
     300                 :             : 
     301         [ +  + ]:         760 :                 if (property.isSpecialProperty) {
     302                 :             :                     // It's a special property, tunnel via the special property method
     303                 :          50 :                     _specialPropertyList[name].setValue(scope, nv, _specialPropertyList[name].parameters, tweening.properties[name].extra);
     304                 :             :                 } else {
     305                 :             :                     // Directly set property
     306                 :         710 :                     scope[name] = nv;
     307                 :             :                 }
     308                 :             :             }
     309                 :             : 
     310                 :         406 :             tweening.updatesSkipped = 0;
     311                 :             : 
     312                 :         812 :             _callOnFunction(tweening.onUpdate, 'onUpdate', tweening.onUpdateScope,
     313                 :         406 :                 scope, tweening.onUpdateParams);
     314                 :             :         } else {
     315                 :           0 :             tweening.updatesSkipped++;
     316                 :             :         }
     317                 :             :     }
     318                 :             : 
     319         [ +  + ]:         411 :     if (isOver) {
     320                 :          46 :         _callOnFunction(tweening.onComplete, 'onComplete', tweening.onCompleteScope,
     321                 :          23 :             scope, tweening.onCompleteParams);
     322                 :             :     }
     323                 :             : 
     324                 :         411 :     return !isOver;
     325                 :             : }
     326                 :             : 
     327                 :         308 : function _updateTweens() {
     328         [ +  + ]:         308 :     if (_tweenList.length == 0)
     329                 :           1 :         return false;
     330                 :             : 
     331         [ +  + ]:         803 :     for (let i = 0; i < _tweenList.length; i++) {
     332 [ +  + ][ +  + ]:         496 :         if (_tweenList[i] == undefined || !_tweenList[i].isPaused) {
     333         [ +  + ]:         471 :             if (!_updateTweenByIndex(i))
     334                 :          31 :                 _removeTweenByIndex(i);
     335                 :             : 
     336         [ +  + ]:         471 :             if (_tweenList[i] == null) {
     337                 :          32 :                 _removeTweenByIndex(i, true);
     338                 :          32 :                 i--;
     339                 :             :             }
     340                 :             :         }
     341                 :             :     }
     342                 :             : 
     343                 :         307 :     return true;
     344                 :             : }
     345                 :             : 
     346                 :             : /* Ran once every 'frame'. It's the main engine, updates all existing tweenings */
     347                 :         308 : function _onEnterFrame() {
     348         [ +  + ]:         308 :     if (!_updateTweens())
     349                 :           1 :         _stopEngine();
     350                 :             : 
     351                 :         308 :     return true;
     352                 :             : }
     353                 :             : 
     354                 :           1 : var restrictedWords = {
     355                 :           1 :     time: true,
     356                 :           1 :     delay: true,
     357                 :           1 :     userFrames: true,
     358                 :           1 :     skipUpdates: true,
     359                 :           1 :     transition: true,
     360                 :           1 :     transitionParams: true,
     361                 :           1 :     onStart: true,
     362                 :           1 :     onUpdate: true,
     363                 :           1 :     onComplete: true,
     364                 :           1 :     onOverwrite: true,
     365                 :           1 :     onError: true,
     366                 :           1 :     rounded: true,
     367                 :           1 :     min: true,
     368                 :           1 :     max: true,
     369                 :           1 :     onStartParams: true,
     370                 :           1 :     onUpdateParams: true,
     371                 :           1 :     onCompleteParams: true,
     372                 :           1 :     onOverwriteParams: true,
     373                 :           1 :     onStartScope: true,
     374                 :           1 :     onUpdateScope: true,
     375                 :           1 :     onCompleteScope: true,
     376                 :           1 :     onOverwriteScope: true,
     377                 :           1 :     onErrorScope: true,
     378                 :             : };
     379                 :             : 
     380                 :          32 : function _constructPropertyList(obj) {
     381                 :          32 :     var properties = {};
     382                 :          32 :     var modifiedProperties = {};
     383                 :             : 
     384         [ +  + ]:         144 :     for (let istr in obj) {
     385         [ +  + ]:         112 :         if (restrictedWords[istr])
     386                 :             :             continue;
     387                 :             : 
     388         [ +  + ]:          50 :         if (_specialPropertySplitterList[istr] != undefined) {
     389                 :             :             // Special property splitter
     390                 :           1 :             var splitProperties = _specialPropertySplitterList[istr].splitValues(obj[istr], _specialPropertySplitterList[istr].parameters);
     391         [ +  + ]:           3 :             for (let i = 0; i < splitProperties.length; i++) {
     392         [ +  - ]:           2 :                 if (_specialPropertySplitterList[splitProperties[i].name] != undefined) {
     393                 :           0 :                     var splitProperties2 = _specialPropertySplitterList[splitProperties[i].name].splitValues(splitProperties[i].value, _specialPropertySplitterList[splitProperties[i].name].parameters);
     394         [ #  # ]:           0 :                     for (let j = 0; j < splitProperties2.length; j++) {
     395                 :           0 :                         properties[splitProperties2[j].name] = {
     396                 :           0 :                             valueStart: undefined,
     397                 :           0 :                             valueComplete: splitProperties2[j].value,
     398                 :           0 :                             arrayIndex: splitProperties2[j].arrayIndex,
     399                 :           0 :                             isSpecialProperty: false,
     400                 :             :                         };
     401                 :             :                     }
     402                 :             :                 } else {
     403                 :           2 :                     properties[splitProperties[i].name] = {
     404                 :           2 :                         valueStart: undefined,
     405                 :           2 :                         valueComplete: splitProperties[i].value,
     406                 :           2 :                         arrayIndex: splitProperties[i].arrayIndex,
     407                 :           2 :                         isSpecialProperty: false,
     408                 :             :                     };
     409                 :             :                 }
     410                 :             :             }
     411         [ +  + ]:          49 :         } else if (_specialPropertyModifierList[istr] != undefined) {
     412                 :             :             // Special property modifier
     413                 :           1 :             let tempModifiedProperties = _specialPropertyModifierList[istr].modifyValues(obj[istr]);
     414         [ +  + ]:           2 :             for (let i = 0; i < tempModifiedProperties.length; i++) {
     415                 :           1 :                 modifiedProperties[tempModifiedProperties[i].name] = {
     416                 :           1 :                     modifierParameters: tempModifiedProperties[i].parameters,
     417                 :           1 :                     modifierFunction: _specialPropertyModifierList[istr].getValue,
     418                 :             :                 };
     419                 :             :             }
     420                 :             :         } else {
     421                 :          48 :             properties[istr] = {
     422                 :          48 :                 valueStart: undefined,
     423                 :          48 :                 valueComplete: obj[istr],
     424                 :             :             };
     425                 :             :         }
     426                 :             :     }
     427                 :             : 
     428                 :             :     // Adds the modifiers to the list of properties
     429         [ +  + ]:          33 :     for (let istr in modifiedProperties) {
     430         [ -  + ]:           1 :         if (properties[istr]) {
     431                 :           1 :             properties[istr].modifierParameters = modifiedProperties[istr].modifierParameters;
     432                 :           1 :             properties[istr].modifierFunction = modifiedProperties[istr].modifierFunction;
     433                 :             :         }
     434                 :             :     }
     435                 :             : 
     436                 :          32 :     return properties;
     437                 :             : }
     438                 :             : 
     439                 :          50 : function PropertyInfo(valueStart, valueComplete, originalValueComplete,
     440                 :             :     arrayIndex, extra, isSpecialProperty,
     441                 :             :     modifierFunction, modifierParameters) {
     442                 :         100 :     this._init(valueStart, valueComplete, originalValueComplete,
     443                 :          50 :         arrayIndex, extra, isSpecialProperty,
     444                 :          50 :         modifierFunction, modifierParameters);
     445                 :             : }
     446                 :             : 
     447                 :           1 : PropertyInfo.prototype = {
     448                 :           1 :     _init(valueStart, valueComplete, originalValueComplete,
     449                 :             :         arrayIndex, extra, isSpecialProperty,
     450                 :             :         modifierFunction, modifierParameters) {
     451                 :          50 :         this.valueStart             =       valueStart;
     452                 :          50 :         this.valueComplete          =       valueComplete;
     453                 :          50 :         this.originalValueComplete  =       originalValueComplete;
     454                 :          50 :         this.arrayIndex             =       arrayIndex;
     455                 :          50 :         this.extra                  =       extra;
     456                 :          50 :         this.isSpecialProperty      =       isSpecialProperty;
     457                 :          50 :         this.hasModifier            =       Boolean(modifierFunction);
     458                 :          50 :         this.modifierFunction       =       modifierFunction;
     459                 :          50 :         this.modifierParameters     =       modifierParameters;
     460                 :             :     },
     461                 :             : };
     462                 :             : 
     463                 :          33 : function _addTweenOrCaller(target, tweeningParameters, isCaller) {
     464         [ +  - ]:          33 :     if (!target)
     465                 :           0 :         return false;
     466                 :             : 
     467                 :             :     var scopes; // List of objects to tween
     468         [ +  - ]:          33 :     if (Array.isArray(target)) {
     469                 :             :         // The first argument is an array
     470                 :           0 :         scopes = target.concat(); // XXX: To copy the array I guess
     471                 :             :     } else {
     472                 :             :         // The first argument(s) is(are) object(s)
     473                 :          33 :         scopes = new Array(target);
     474                 :             :     }
     475                 :             : 
     476                 :             :     var obj, istr;
     477                 :             : 
     478         [ +  + ]:          33 :     if (isCaller) {
     479                 :           1 :         obj = tweeningParameters;
     480                 :             :     } else {
     481                 :          32 :         obj = TweenList.makePropertiesChain(tweeningParameters);
     482                 :             : 
     483                 :          32 :         var properties = _constructPropertyList(obj);
     484                 :             : 
     485                 :             :         // Verifies whether the properties exist or not, for warning messages
     486         [ +  + ]:          82 :         for (istr in properties) {
     487         [ +  + ]:          50 :             if (_specialPropertyList[istr] != undefined) {
     488                 :           1 :                 properties[istr].isSpecialProperty = true;
     489                 :             :             } else {
     490         [ +  + ]:          98 :                 for (var i = 0; i < scopes.length; i++) {
     491         [ +  - ]:          49 :                     if (scopes[i][istr] == undefined) {
     492                 :           0 :                         log(`The property ${istr} doesn't seem to be a ` +
     493                 :           0 :                             `normal object property of ${scopes[i]} or a ` +
     494                 :           0 :                             'registered special property');
     495                 :             :                     }
     496                 :             :                 }
     497                 :             :             }
     498                 :             :         }
     499                 :             :     }
     500                 :             : 
     501                 :             :     // Creates the main engine if it isn't active
     502         [ +  + ]:          33 :     if (!_inited)
     503                 :           1 :         _init();
     504         [ +  + ]:          33 :     if (!_engineExists)
     505                 :           2 :         _startEngine();
     506                 :             : 
     507                 :             :     // Creates a "safer", more strict tweening object
     508         [ +  + ]:          33 :     var time = obj.time || 0;
     509         [ +  + ]:          33 :     var delay = obj.delay || 0;
     510                 :             : 
     511                 :             :     var transition;
     512                 :             : 
     513                 :             :     // FIXME: Tweener allows you to use functions with an all lower-case name
     514         [ +  + ]:          33 :     if (typeof obj.transition == 'string')
     515                 :           7 :         transition = imports.tweener.equations[obj.transition];
     516                 :             :     else
     517                 :          26 :         transition = obj.transition;
     518                 :             : 
     519         [ +  + ]:          33 :     if (!transition)
     520                 :          26 :         transition = imports.tweener.equations['easeOutExpo'];
     521                 :             : 
     522                 :             :     var tween;
     523                 :             : 
     524         [ +  + ]:          66 :     for (let i = 0; i < scopes.length; i++) {
     525         [ +  + ]:          33 :         if (!isCaller) {
     526                 :             :             // Make a copy of the properties
     527                 :          32 :             var copyProperties = {};
     528         [ +  + ]:          82 :             for (istr in properties) {
     529                 :         100 :                 copyProperties[istr] = new PropertyInfo(properties[istr].valueStart,
     530                 :          50 :                     properties[istr].valueComplete,
     531                 :          50 :                     properties[istr].valueComplete,
     532         [ -  + ]:          50 :                     properties[istr].arrayIndex || 0,
     533                 :          50 :                     {},
     534         [ +  + ]:          50 :                     properties[istr].isSpecialProperty || false,
     535         [ +  + ]:          50 :                     properties[istr].modifierFunction || null,
     536         [ -  + ]:          50 :                     properties[istr].modifierParameters || null);
     537                 :             :             }
     538                 :             :         }
     539                 :             : 
     540                 :          66 :         tween = new TweenList.TweenList(scopes[i],
     541                 :          33 :             _ticker.getTime() + delay * 1000 / _timeScale,
     542                 :          33 :             _ticker.getTime() + (delay * 1000 + time * 1000) / _timeScale,
     543                 :          33 :             false,
     544                 :          33 :             transition,
     545         [ -  + ]:          33 :             obj.transitionParams || null);
     546                 :             : 
     547         [ +  + ]:          33 :         tween.properties               =       isCaller ? null : copyProperties;
     548                 :          33 :         tween.onStart                  =       obj.onStart;
     549                 :          33 :         tween.onUpdate                 =       obj.onUpdate;
     550                 :          33 :         tween.onComplete               =       obj.onComplete;
     551                 :          33 :         tween.onOverwrite              =       obj.onOverwrite;
     552                 :          33 :         tween.onError                  =       obj.onError;
     553                 :          33 :         tween.onStartParams            =       obj.onStartParams;
     554                 :          33 :         tween.onUpdateParams           =       obj.onUpdateParams;
     555                 :          33 :         tween.onCompleteParams         =       obj.onCompleteParams;
     556                 :          33 :         tween.onOverwriteParams        =       obj.onOverwriteParams;
     557                 :          33 :         tween.onStartScope             =       obj.onStartScope;
     558                 :          33 :         tween.onUpdateScope            =       obj.onUpdateScope;
     559                 :          33 :         tween.onCompleteScope          =       obj.onCompleteScope;
     560                 :          33 :         tween.onOverwriteScope         =       obj.onOverwriteScope;
     561                 :          33 :         tween.onErrorScope             =       obj.onErrorScope;
     562                 :          33 :         tween.rounded                  =       obj.rounded;
     563                 :          33 :         tween.min                      =       obj.min;
     564                 :          33 :         tween.max                      =       obj.max;
     565                 :          33 :         tween.skipUpdates              =       obj.skipUpdates;
     566                 :          33 :         tween.isCaller                 =       isCaller;
     567                 :             : 
     568         [ +  + ]:          33 :         if (isCaller) {
     569                 :           1 :             tween.count = obj.count;
     570                 :           1 :             tween.waitFrames = obj.waitFrames;
     571                 :             :         }
     572                 :             : 
     573         [ +  + ]:          33 :         if (!isCaller) {
     574                 :             :             // Remove other tweenings that occur at the same time
     575                 :          32 :             removeTweensByTime(tween.scope, tween.properties, tween.timeStart, tween.timeComplete);
     576                 :             :         }
     577                 :             : 
     578                 :             :         // And finally adds it to the list
     579                 :          33 :         _tweenList.push(tween);
     580                 :             : 
     581                 :             :         // Immediate update and removal if it's an immediate tween
     582                 :             :         // If not deleted, it executes at the end of this frame execution
     583 [ +  + ][ +  + ]:          33 :         if (time == 0 && delay == 0) {
     584                 :           1 :             var myT = _tweenList.length - 1;
     585                 :           1 :             _updateTweenByIndex(myT);
     586                 :           1 :             _removeTweenByIndex(myT);
     587                 :             :         }
     588                 :             :     }
     589                 :             : 
     590                 :          33 :     return true;
     591                 :             : }
     592                 :             : 
     593                 :          32 : function addTween(target, tweeningParameters) {
     594                 :          32 :     return _addTweenOrCaller(target, tweeningParameters, false);
     595                 :             : }
     596                 :             : 
     597                 :           1 : function addCaller(target, tweeningParameters) {
     598                 :           1 :     return _addTweenOrCaller(target, tweeningParameters, true);
     599                 :             : }
     600                 :             : 
     601                 :          21 : function _getNumberOfProperties(object) {
     602                 :          21 :     var totalProperties = 0;
     603                 :             : 
     604                 :             :     // the following line is disabled because eslint was picking up the following error: the variable name is defined but never used, however since it is required to search the object it is used and we'll allow the line to be ignored to get rid of the error message
     605                 :             :     /* eslint-disable-next-line */
     606         [ +  + ]:          39 :     for (let name in object) {
     607                 :          18 :         totalProperties++;
     608                 :             :     }
     609                 :             : 
     610                 :             : 
     611                 :          21 :     return totalProperties;
     612                 :             : }
     613                 :             : 
     614                 :          32 : function removeTweensByTime(scope, properties, timeStart, timeComplete) {
     615                 :          32 :     var removed = false;
     616                 :             :     var removedLocally;
     617                 :             :     var name;
     618                 :             : 
     619         [ +  + ]:          77 :     for (let i = 0; i < _tweenList.length; i++) {
     620                 :          45 :         removedLocally = false;
     621                 :             : 
     622         [ +  + ]:          45 :         if (_tweenList[i] &&
     623         [ +  + ]:          42 :             scope == _tweenList[i].scope &&
     624         [ -  + ]:          13 :             timeComplete > _tweenList[i].timeStart &&
     625         [ +  + ]:          13 :             timeStart < _tweenList[i].timeComplete) {
     626         [ +  + ]:          30 :             for (name in _tweenList[i].properties) {
     627         [ +  + ]:          18 :                 if (properties[name]) {
     628         [ +  + ]:           9 :                     if (!removedLocally) {
     629                 :           6 :                         _callOnFunction(_tweenList[i].onOverwrite, 'onOverwrite', _tweenList[i].onOverwriteScope,
     630                 :           3 :                             _tweenList[i].scope, _tweenList[i].onOverwriteParams);
     631                 :             :                     }
     632                 :             : 
     633                 :           9 :                     _tweenList[i].properties[name] = undefined;
     634                 :           9 :                     delete _tweenList[i].properties[name];
     635                 :           9 :                     removedLocally = true;
     636                 :           9 :                     removed = true;
     637                 :             :                 }
     638                 :             :             }
     639                 :             : 
     640         [ +  + ]:          12 :             if (removedLocally &&
     641         [ +  + ]:           3 :                 _getNumberOfProperties(_tweenList[i].properties) == 0)
     642                 :           3 :                 _removeTweenByIndex(i);
     643                 :             :         }
     644                 :             :     }
     645                 :             : 
     646                 :          32 :     return removed;
     647                 :             : }
     648                 :             : 
     649                 :           5 : function _pauseTweenByIndex(i) {
     650                 :           5 :     var tweening = _tweenList[i];
     651                 :             : 
     652 [ -  + ][ +  + ]:           5 :     if (tweening == null || tweening.isPaused)
     653                 :           1 :         return false;
     654                 :             : 
     655                 :           4 :     tweening.timePaused = _getCurrentTweeningTime(tweening);
     656                 :           4 :     tweening.isPaused = true;
     657                 :             : 
     658                 :           4 :     return true;
     659                 :             : }
     660                 :             : 
     661                 :           0 : function _splitTweens(tween, properties) {
     662                 :           0 :     var originalTween = _tweenList[tween];
     663                 :           0 :     var newTween = originalTween.clone();
     664                 :             :     var name;
     665                 :             : 
     666         [ #  # ]:           0 :     for (let i = 0; i < properties.length; i++) {
     667                 :           0 :         name = properties[i];
     668         [ #  # ]:           0 :         if (originalTween.properties[name]) {
     669                 :           0 :             originalTween.properties[name] = undefined;
     670                 :           0 :             delete originalTween.properties[name];
     671                 :             :         }
     672                 :             :     }
     673                 :             : 
     674                 :           0 :     var found = false;
     675         [ #  # ]:           0 :     for (name in newTween.properties) {
     676                 :           0 :         found = false;
     677         [ #  # ]:           0 :         for (let i = 0; i < properties.length; i++) {
     678         [ #  # ]:           0 :             if (properties[i] == name) {
     679                 :           0 :                 found = true;
     680                 :             :                 break;
     681                 :             :             }
     682                 :             :         }
     683                 :             : 
     684         [ #  # ]:           0 :         if (!found) {
     685                 :           0 :             newTween.properties[name] = undefined;
     686                 :           0 :             delete newTween.properties[name];
     687                 :             :         }
     688                 :             :     }
     689                 :             : 
     690                 :           0 :     _tweenList.push(newTween);
     691                 :           0 :     return _tweenList.length - 1;
     692                 :             : }
     693                 :             : 
     694                 :           6 : function _affectTweens(affectFunction, scope, properties) {
     695                 :           6 :     var affected = false;
     696                 :             : 
     697         [ +  - ]:           6 :     if (!_tweenList)
     698                 :           0 :         return false;
     699                 :             : 
     700         [ +  + ]:          31 :     for (let i = 0; i < _tweenList.length; i++) {
     701 [ -  + ][ +  + ]:          25 :         if (!_tweenList[i] || _tweenList[i].scope != scope)
     702                 :             :             continue;
     703                 :             : 
     704         [ +  + ]:          11 :         if (properties.length == 0) {
     705                 :             :             // Can check everything
     706                 :           1 :             affectFunction(i);
     707                 :           1 :             affected = true;
     708                 :             :         } else {
     709                 :             :             // Must check whether this tween must have specific properties affected
     710                 :          10 :             var affectedProperties = [];
     711         [ +  + ]:          27 :             for (let j = 0; j < properties.length; j++) {
     712         [ +  + ]:          17 :                 if (_tweenList[i].properties[properties[j]])
     713                 :           6 :                     affectedProperties.push(properties[j]);
     714                 :             :             }
     715                 :             : 
     716         [ +  + ]:          10 :             if (affectedProperties.length > 0) {
     717                 :           6 :                 var objectProperties = _getNumberOfProperties(_tweenList[i].properties);
     718         [ -  + ]:           6 :                 if (objectProperties == affectedProperties.length) {
     719                 :             :                     // The list of properties is the same as all properties, so affect it all
     720                 :           6 :                     affectFunction(i);
     721                 :           6 :                     affected = true;
     722                 :             :                 } else {
     723                 :             :                     // The properties are mixed, so split the tween and affect only certain specific
     724                 :             :                     // properties
     725                 :           0 :                     var splicedTweenIndex = _splitTweens(i, affectedProperties);
     726                 :           0 :                     affectFunction(splicedTweenIndex);
     727                 :           0 :                     affected = true;
     728                 :             :                 }
     729                 :             :             }
     730                 :             :         }
     731                 :             :     }
     732                 :             : 
     733                 :           6 :     return affected;
     734                 :             : }
     735                 :             : 
     736                 :           7 : function _isInArray(string, array) {
     737                 :           7 :     var l = array.length;
     738                 :             : 
     739         [ +  + ]:           9 :     for (let i = 0; i < l; i++) {
     740         [ +  - ]:           2 :         if (array[i] == string)
     741                 :           0 :             return true;
     742                 :             :     }
     743                 :             : 
     744                 :           7 :     return false;
     745                 :           0 : }
     746                 :             : 
     747                 :           6 : function _affectTweensWithFunction(func, args) {
     748                 :           6 :     var properties = [];
     749                 :           6 :     var scope = args[0];
     750                 :           6 :     var affected = false;
     751                 :             :     var scopes;
     752                 :             : 
     753         [ +  - ]:           6 :     if (Array.isArray(scope))
     754                 :           0 :         scopes = scope.concat();
     755                 :             :     else
     756                 :           6 :         scopes = new Array(scope);
     757                 :             : 
     758         [ +  + ]:          13 :     for (let i = 1; args[i] != undefined; i++) {
     759 [ -  + ][ -  + ]:           7 :         if (typeof args[i] == 'string' && !_isInArray(args[i], properties)) {
     760         [ +  - ]:           7 :             if (_specialPropertySplitterList[args[i]]) {
     761                 :             :                 // special property, get splitter array first
     762                 :           0 :                 var sps = _specialPropertySplitterList[arguments[i]];
     763                 :           0 :                 var specialProps = sps.splitValues(scope, null);
     764         [ #  # ]:           0 :                 for (let j = 0; j < specialProps.length; j++)
     765                 :           0 :                     properties.push(specialProps[j].name);
     766                 :             :             } else {
     767                 :           7 :                 properties.push(args[i]);
     768                 :             :             }
     769                 :             :         }
     770                 :             :     }
     771                 :             : 
     772                 :             :     // the return now value means: "affect at least one tween"
     773         [ +  + ]:          12 :     for (let i = 0; i < scopes.length; i++)
     774         [ -  + ]:           6 :         affected = affected || _affectTweens(func, scopes[i], properties);
     775                 :             : 
     776                 :           6 :     return affected;
     777                 :             : }
     778                 :             : 
     779                 :           1 : function resumeTweens() {
     780                 :           1 :     return _affectTweensWithFunction(_resumeTweenByIndex, arguments);
     781                 :             : }
     782                 :             : 
     783                 :           3 : function pauseTweens() {
     784                 :           3 :     return _affectTweensWithFunction(_pauseTweenByIndex, arguments);
     785                 :             : }
     786                 :             : 
     787                 :           2 : function removeTweens() {
     788                 :           2 :     return _affectTweensWithFunction(_removeTweenByIndex, arguments);
     789                 :             : }
     790                 :             : 
     791                 :           3 : function _mapOverTweens(func) {
     792                 :           3 :     var rv = false;
     793                 :             : 
     794         [ +  - ]:           3 :     if (_tweenList == null)
     795                 :           0 :         return false;
     796                 :             : 
     797         [ +  + ]:          11 :     for (let i = 0; i < _tweenList.length; i++) {
     798         [ +  + ]:           8 :         if (func(i))
     799                 :           7 :             rv = true;
     800                 :             :     }
     801                 :             : 
     802                 :           3 :     return rv;
     803                 :             : }
     804                 :             : 
     805                 :           1 : function pauseAllTweens() {
     806                 :           1 :     return _mapOverTweens(_pauseTweenByIndex);
     807                 :             : }
     808                 :             : 
     809                 :           1 : function resumeAllTweens() {
     810                 :           1 :     return _mapOverTweens(_resumeTweenByIndex);
     811                 :             : }
     812                 :             : 
     813                 :           1 : function removeAllTweens() {
     814                 :           1 :     return _mapOverTweens(_removeTweenByIndex);
     815                 :             : }
     816                 :             : 
     817                 :           6 : function getTweenCount(scope) {
     818         [ +  - ]:           6 :     if (!_tweenList)
     819                 :           0 :         return 0;
     820                 :             : 
     821                 :           6 :     var c = 0;
     822                 :             : 
     823         [ +  + ]:          20 :     for (let i = 0; i < _tweenList.length; i++) {
     824 [ +  + ][ +  + ]:          14 :         if (_tweenList[i] && _tweenList[i].scope == scope)
     825                 :          12 :             c += _getNumberOfProperties(_tweenList[i].properties);
     826                 :             :     }
     827                 :             : 
     828                 :           6 :     return c;
     829                 :             : }
     830                 :             : 
     831                 :           1 : function registerSpecialProperty(name, getFunction, setFunction,
     832                 :             :     parameters, preProcessFunction) {
     833                 :           1 :     _specialPropertyList[name] = {
     834                 :           1 :         getValue: getFunction,
     835                 :           1 :         setValue: setFunction,
     836                 :           1 :         parameters,
     837                 :           1 :         preProcess: preProcessFunction,
     838                 :             :     };
     839                 :             : }
     840                 :             : 
     841                 :           1 : function registerSpecialPropertyModifier(name, modifyFunction, getFunction) {
     842                 :           1 :     _specialPropertyModifierList[name] = {
     843                 :           1 :         modifyValues: modifyFunction,
     844                 :           1 :         getValue: getFunction,
     845                 :             :     };
     846                 :             : }
     847                 :             : 
     848                 :           1 : function registerSpecialPropertySplitter(name, splitFunction, parameters) {
     849                 :           1 :     _specialPropertySplitterList[name] = {
     850                 :           1 :         splitValues: splitFunction,
     851                 :           1 :         parameters,
     852                 :             :     };
     853                 :             : }
     854                 :             : 
     855                 :           0 : function setTimeScale(scale) {
     856                 :           0 :     _timeScale = scale;
     857                 :             : }
     858                 :             : 
     859                 :           0 : function getTimeScale() {
     860                 :           0 :     return _timeScale;
     861                 :             : }
        

Generated by: LCOV version 2.0-1