Ticket #2357: idle_worker_blink.patch

File idle_worker_blink.patch, 16.9 KB (added by Michael, 10 years ago)

Effect is working but patch need some improvments...

  • binaries/data/mods/public/gui/common/colorFades.js

     
    11/*
    2     DESCRIPTION : Some functions to make colour fades on GUI elements (f.e. used for hero and group icons)
     2    DESCRIPTION : Some functions to make color fades on GUI elements (f.e. used for hero and group icons)
    33    NOTES       :
    44*/
    55
    6 // Used for storing object names of running color fades in order to stop them, if the fade is restarted before the old ended
    7 var g_colorFade = {};
    8 g_colorFade["id"] = {};
    9 g_colorFade["tick"] = {};
     6// Used for storing information about color fades
     7var g_colorFade = {};
    108
    119/**
    12  * starts fading a colour of a GUI object using the sprite argument
    13  * name: name of the object which colour should be faded
    14  * changeInterval: interval in ms when the next colour change should be made
    15  * duration: maximal duration of the complete fade
    16  * colour: RGB + opacity object with keys r,g,b and o
     10 * starts fading a color of a GUI object using the sprite argument
     11 * name: name of the object which color should be faded
     12 * tickInterval: interval in ms when the next color change should be made
     13 * duration: maximal duration of the complete fade (if 0 it runs until it is stopped)
    1714 * fun_colorTransform: function which transform the colors;
    18  *                    arguments: [colour object, tickCounter]
     15 *                    arguments: [color object, tickCounter]
     16 * restartAble [optional: if false, the fade can not be restarted; default: true
    1917 * fun_smoothRestart [optional]: a function, which returns a smooth tick counter, if the fade should be started;
    2018 *                              arguments: [tickCounter of current fade; not smaller than 1 or it restarts at 0] returns: smooth tick counter value
    21  * tickCounter [optional]: should not be set by hand! - how often the function was called recursively
    2219 */
    23 function fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)
     20function startColorFade(name, tickInterval, duration, fun_colorTransform, restartAble, fun_smoothRestart)
    2421{
    2522    // get the overlay
    2623    var overlay = Engine.GetGUIObjectByName(name);
     
    2825        return;
    2926
    3027    // check, if fade overlay was started just now
    31     if (!tickCounter)
     28    if (!isColorFadeRunning(name))
    3229    {
    33         tickCounter = 1;
    3430        overlay.hidden = false;
    35                    
    36         // check, if another animation is running and restart it, if it's the case
    37         if (isColourFadeRunning(name))
    38         {
    39             restartColourFade(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, g_colorFade.tick[name]);
    40             return;
    41         }
     31       
     32        // store the values into a var to make it more flexible (can be changed from every function)
     33        var data = {};
     34        data.timerId = -1;
     35        data.tickInterval = tickInterval;
     36        data.duration = duration;
     37        data.fun_colorTransform = fun_colorTransform;
     38        data.restartAble = restartAble !== false;
     39        data.fun_smoothRestart = fun_smoothRestart;
     40        data.tickCounter = 1;
     41        data.runsUntilStop = duration == 0;
     42        data.stopFade = false;
     43        var rgb = {"r": 255,"g": 255,"b": 255,"o": 100};
     44        data.rgb = rgb;
     45        // store it!
     46        g_colorFade[name] = data;
     47
     48        // start with fading
     49        fadeColorTick(name);
    4250    }
    43    
    44     // get colors
    45     fun_colorTransform(colour, tickCounter);
    46    
    47     // set new colour
    48     overlay.sprite="colour: "+colour.r+" "+colour.g+" "+colour.b+" "+colour.o;
     51    else if (restartAble)
     52    {
     53        restartColorFade(name, tickInterval, duration, fun_colorTransform, restartAble, fun_smoothRestart);
     54        return;
     55    }
     56}
    4957
     58/**
     59 * makes the color changes in a tick
     60 * name: name of the object which color should be faded
     61 */
     62function fadeColorTick(name)
     63{
     64    // make some checks
     65    if (!isColorFadeRunning(name))
     66        return;
     67       
     68    var overlay = Engine.GetGUIObjectByName(name);
     69    if (!overlay)
     70        return;
     71       
     72    var data = g_colorFade[name];
     73       
     74    // change the color
     75    data.fun_colorTransform(data);
     76
     77    // set new color
     78    var rgb = data.rgb;
     79    overlay.sprite="colour: "+rgb.r+" "+rgb.g+" "+rgb.b+" "+rgb.o;
     80
    5081    // recusive call, if duration is positive
    51     duration-= changeInterval;
    52     if (duration > 0 && colour.o > 0)
     82    if (!data.stopFade && (data.runsUntilStop || data.duration - (data.tickInterval * data.tickCounter) > 0))
    5383    {
    54         var id = setTimeout(function() { fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, ++tickCounter); }, changeInterval);
    55         g_colorFade.id[name] = id;
    56         g_colorFade.tick[name] = tickCounter;
     84        var id = setTimeout(function() { fadeColorTick(name); }, data.tickInterval);
     85        data.timerId = id;
     86        data.tickCounter++;
    5787    }
    5888    else
    5989    {
    6090        overlay.hidden = true;
    61         stopColourFade(name);
     91        stopColorFade(name);
    6292    }
    6393}
    6494
    65 
    6695/**
    67  * checks, if a colour fade on that object is running
    68  * name: name of the object which colour fade should be checked
     96 * checks, if a color fade on that object is running
     97 * name: name of the object which color fade should be checked
    6998 * return: true a running fade was found
    7099 */
    71 function isColourFadeRunning(name)
     100function isColorFadeRunning(name)
    72101{
    73     return name in g_colorFade.id;
     102    return name in g_colorFade;
    74103}
    75104
    76105/**
    77  * stops fading a colour
    78  * name: name of the object which colour fade should be stopped
    79  * hideOverlay: hides the overlay, if true
     106 * stops fading a color
     107 * name: name of the object which color fade should be stopped
     108 * hideOverlay [optional]: hides the overlay, if true [default: true]
    80109 * return: true a running fade was stopped
    81110 */
    82 function stopColourFade(name, hideOverlay)
     111function stopColorFade(name, hideOverlay)
    83112{
    84     // check, if a colour fade is running
    85     if (!isColourFadeRunning(name))
     113    // check, if a color fade is running
     114    if (!isColorFadeRunning(name))
    86115        return false;
    87116
    88117    // delete the timer
    89     clearTimeout(g_colorFade.id[name]);
    90     delete g_colorFade.id[name];
    91     delete g_colorFade.tick[name];
    92    
     118    clearTimeout(g_colorFade[name].timerId);
     119    delete g_colorFade[name];
     120
     121    hideOverlay = hideOverlay !== false;
    93122    // get the overlay and hide it
    94123    if (hideOverlay)
    95124    {
    96125        var overlay = Engine.GetGUIObjectByName(name);
    97         if(overlay)
     126        if (overlay)
    98127            overlay.hidden = true;
    99128    }
    100129    return true;
     
    101130}
    102131
    103132/**
    104  * restarts a colour fade
    105  * see paramter in fadeColour function
     133 * restarts a color fade
     134 * see paramter in startColorFade function
    106135 */
    107 function restartColourFade(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)
     136function restartColorFade(name)
    108137{
    109     // check, if a colour fade is running
    110     if (!isColourFadeRunning(name))
     138    // check, if a color fade is running
     139    if (!isColorFadeRunning(name))
    111140        return false;
    112141   
     142    var data = g_colorFade[name];
    113143    // check, if fade can be restarted smoothly
    114     if (fun_smoothRestart)
     144    if (data.fun_smoothRestart)
    115145    {
    116         tickCounter = fun_smoothRestart(colour, tickCounter);
    117         // set new function to existing timer
    118         var fun = function() { fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter); };
    119         setNewTimerFunction(g_colorFade.id[name], fun);
     146        data.fun_smoothRestart(data);
    120147    }
    121148    // stop it and restart it
    122149    else
    123150    {
    124         stopColourFade(name, true);
    125         fadeColour(name, changeInterval, duration, colour, fun_colorTransform);
     151        stopColorFade(name, false);
     152        startColorFade(name, data.changeInterval, data.duration, data.fun_colorTransform, data.restartAble, data.fun_smoothRestart);
    126153    }
    127154    return true;
    128155}
     
    133160
    134161var g_fadeAttackUnit = {};
    135162g_fadeAttackUnit.blinkingTicks = 50; // how many ticks should first blinking phase be
    136 g_fadeAttackUnit.blinkingChangeInterval = 5; // how often should the colour be changed during the blinking phase
    137 g_fadeAttackUnit.gbColourChangeRate = 3; // how fast should blue and green part of the colour change
     163g_fadeAttackUnit.blinkingChangeInterval = 5; // how often should the color be changed during the blinking phase
     164g_fadeAttackUnit.gbcolorChangeRate = 3; // how fast should blue and green part of the color change
    138165g_fadeAttackUnit.fadeOutStart = 100; // when should the fade out start using the opacity
    139166g_fadeAttackUnit.opacityChangeRate = 3; // how fast should opacity change
    140167
    141 /**
    142  * rgb: colour object with keys r,g,b and o
    143  * tickCounter: how often the fade was executed
    144  */
    145 function colourFade_attackUnit(rgb, tickCounter)
     168function colorFade_attackUnit(data)
    146169{
     170    var rgb = data.rgb;
     171    // init color
     172    if (data.tickCounter == 1)
     173        rgb.r = 175;
    147174    // blinking
    148     if (tickCounter < g_fadeAttackUnit.blinkingTicks)
     175    if (data.tickCounter < g_fadeAttackUnit.blinkingTicks)
    149176    {
    150177        // slow that process down
    151         if (tickCounter % g_fadeAttackUnit.blinkingChangeInterval != 0)
     178        if (data.tickCounter % g_fadeAttackUnit.blinkingChangeInterval != 0)
    152179            return;
    153180           
    154         rgb.g = rgb.g == 0 ? 255 : rgb.g = 0;
    155         rgb.b = rgb.b == 0 ? 255 : rgb.b = 0;
     181        rgb.g = rgb.g == 0 ? 255 : 0;
    156182    }
    157     // wait a short time and then colour fade from red to grey to nothing
    158     else if ( tickCounter >= g_fadeAttackUnit.blinkingTicks + g_fadeAttackUnit.blinkingChangeInterval)
     183    // wait a short time and then color fade from red to grey to nothing
     184    else if ( data.tickCounter >= g_fadeAttackUnit.blinkingTicks + g_fadeAttackUnit.blinkingChangeInterval)
    159185    {
    160         rgb.g = rgb.g < 255 ? rgb.g += g_fadeAttackUnit.gbColourChangeRate * Math.sqrt(tickCounter - g_fadeAttackUnit.blinkingTicks) : 255;
    161         rgb.b = rgb.g;
     186        rgb.g = rgb.g < 255 ? rgb.g += g_fadeAttackUnit.gbcolorChangeRate * Math.sqrt(data.tickCounter - g_fadeAttackUnit.blinkingTicks) : 255;
    162187       
    163188        // start with fading it out
    164189        if (rgb.g > g_fadeAttackUnit.fadeOutStart)
    165190            rgb.o = rgb.o > g_fadeAttackUnit.opacityChangeRate ? rgb.o -= g_fadeAttackUnit.opacityChangeRate : 0;
     191        // check for end
     192        if (rgb.o == 0)
     193            data.stopFade = true;
    166194    }
     195    rgb.b = rgb.g;
    167196}
    168197
    169 /**
    170  * makes a smooth fade, if the attack on the unit has not stopped yet
    171  * rgb: colour object with keys r,g,b and o
    172  * tickCounter: how often the fade was executed
    173  */
    174 function smoothColourFadeRestart_attackUnit(rgb, tickCounter)
     198function smoothColorFadeRestart_attackUnit(data)
    175199{
    176200    // check, if in blinking phase
    177     if (tickCounter < g_fadeAttackUnit.blinkingTicks)
     201    if (data.tickCounter < g_fadeAttackUnit.blinkingTicks)
    178202    {
    179         // get rgb to current state
    180         for (var i = 1; i <= tickCounter; i++)
    181             colourFade_attackUnit(rgb, i);
    182         // set the tick counter back to start
    183         return (tickCounter % (g_fadeAttackUnit.blinkingChangeInterval * 2)) + 1;
     203        // set the tick counter back to a smooth position
     204        data.tickCounter = (data.tickCounter % (g_fadeAttackUnit.blinkingChangeInterval * 2)) + 1;
    184205    }
    185     return 1;
     206    data.tickCounter = 1;
    186207}
    187208
    188 //[END] of hero fade functions
    189  No newline at end of file
     209//[END] of hero fade functions
     210//[START] idle workers icon
     211
     212//var g_fadeIdleWorker = {};
     213
     214function colorFade_IdleWorker(data)
     215{
     216    var rgb = data.rgb;
     217    rgb.g = rgb.g == 0 ? 255 : 0;
     218    rgb.b = rgb.g;
     219    if (rgb.g == 0)
     220        rgb.o = 0;
     221    else
     222        rgb.o = 100;
     223}
     224
     225//[END] of idle workers icon functions
     226 No newline at end of file
  • binaries/data/mods/public/gui/session/session.js

     
    478478
    479479    updateHero();
    480480    updateGroups();
     481    updateIdleWorkerButton();
    481482    updateDebug();
    482483    updatePlayerDisplay();
    483484    updateSelectionDetails();
     
    491492    if (battleState)
    492493        global.music.setState(global.music.states[battleState]);
    493494   
     495};
     496
     497function updateIdleWorkerButton()
     498{
     499    var idleUnitsCounter = Engine.GuiInterfaceCall("getNumberOfIdleUnits");
     500
     501    if (idleUnitsCounter != 0)
     502        startColorFade("idleWorkerOverlay", 500, 0, colorFade_IdleWorker, false);
     503    else
     504        stopColorFade("idleWorkerOverlay");
     505   
    494506}
    495507
     508
    496509/**
    497510* updates a status bar on the GUI
    498511* nameOfBar: name of the bar
     
    587600    {   
    588601        g_previousHeroHitPoints = heroState.hitpoints;
    589602        // trigger the animation
    590         fadeColour("heroHitOverlay", 100, 10000, {"r": 175,"g": 0,"b": 0,"o": 100}, colourFade_attackUnit, smoothColourFadeRestart_attackUnit);
     603        startColorFade("heroHitOverlay", 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
    591604        return;
    592605    }
    593606}
  • binaries/data/mods/public/gui/session/session.xml

     
    951951            >
    952952            <!-- TODO: should highlight the button if there's non-zero idle workers -->
    953953            <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" />
     954            <object name="idleWorkerOverlay" hidden="true" type="image" ghost="true" size="2 2 100%-2 100%-2"/>
    954955            <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action>
    955956            </object>
    956957        </object>
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    17091709    PlaySound(data.name, data.entity);
    17101710};
    17111711
     1712GuiInterface.prototype.getNumberOfIdleUnits = function(player)
     1713{
     1714    var entities = this.GetPlayerEntities(player);
     1715    var cmpUnitAI = Engine.QueryInterface(entities[0], IID_UnitAI);
     1716    if (!cmpUnitAI)
     1717        return 0;
     1718    return cmpUnitAI.getNumberOfIdleUnits();
     1719}
     1720
    17121721function isIdleUnit(ent, idleClass)
    17131722{
    17141723    var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     
    19461955    "SetWallPlacementPreview": 1,
    19471956    "GetFoundationSnapData": 1,
    19481957    "PlaySound": 1,
     1958    "getNumberOfIdleUnits": 1,
    19491959    "FindIdleUnits": 1,
    19501960    "GetTradingRouteGain": 1,
    19511961    "GetTradingDetails": 1,
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    169169    "GuardedAttacked": function(msg) {
    170170        // ignore
    171171    },
     172   
     173    "UnitIdleChanged": function(msg) {
     174        // check if this are units which can be selected by the workes idle button
     175        if(this.IsUsedForIdleWorkerButton())
     176        {
     177            if(msg.idle)
     178                increaseIdleCount(msg.player);
     179            else
     180                decreaseIdleCount(msg.player);
     181        }
     182    },
    172183
    173184    // Formation handlers:
    174185
     
    30363047    return Engine.QueryInterface(this.entity, IID_Heal);
    30373048};
    30383049
     3050UnitAI.prototype.IsUsedForIdleWorkerButton = function()
     3051{
     3052    var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
     3053    if (!cmpIdentity)
     3054        return false;
     3055    // check idle class names   
     3056    for each(var className in g_idleClassNames)
     3057        if (cmpIdentity.HasClass(className)) {
     3058            return true;
     3059        }
     3060    // return false because all checks where negative
     3061    return false;
     3062};
     3063
    30393064UnitAI.prototype.IsIdle = function()
    30403065{
    30413066    return this.isIdle;
     
    31003125        if(!this.isGarrisoned)
    31013126            this.Stop(false);
    31023127    }
     3128    // check for idleWorks
     3129    else if (this.isIdle)
     3130    {
     3131        // idle worker gone
     3132        if (msg.to == -1)
     3133        {
     3134            decreaseIdleCount(msg.from);
     3135            increaseIdleCount(msg.to);
     3136        }
     3137        // new idle worker
     3138        else
     3139        {
     3140            decreaseIdleCount(msg.to);
     3141            increaseIdleCount(msg.from);
     3142        }
     3143    }
    31033144};
    31043145
    31053146UnitAI.prototype.OnDestroy = function()
     
    36823723    UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
    36833724};
    36843725
     3726UnitAI.prototype.OnUnitIdleChanged = function(msg)
     3727{
     3728    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     3729    if (!cmpOwnership)
     3730        return;
     3731    UnitFsm.ProcessMessage(this, {"type": "UnitIdleChanged", "idle": msg.idle, "player": cmpOwnership.GetOwner()});
     3732}
     3733
    36853734//// Helper functions to be called by the FSM ////
    36863735
    36873736UnitAI.prototype.GetWalkSpeed = function()
     
    54815530    );
    54825531};
    54835532
     5533UnitAI.prototype.getNumberOfIdleUnits = function()
     5534{
     5535    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     5536    if (!cmpOwnership)
     5537        return 0;
     5538    if (!isIdleCountDefined(cmpOwnership.GetOwner()))
     5539        return 0;
     5540    return getIdleCount(cmpOwnership.GetOwner());
     5541}
     5542
     5543var g_idleClassNames = ["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"];
     5544var g_idleUnitsCounter = {};
     5545
     5546function increaseIdleCount(player)
     5547{
     5548    if (player == -1)
     5549        return;
     5550    if (!isIdleCountDefined(player))
     5551        g_idleUnitsCounter[player] = 1;
     5552    else
     5553        g_idleUnitsCounter[player]++;
     5554}
     5555
     5556function decreaseIdleCount(player)
     5557{
     5558    if (player == -1)
     5559        return;
     5560    // should not happen
     5561    if (!isIdleCountDefined(player))
     5562        error("Negative idle worker count for player '" + player + "'");
     5563    else
     5564        g_idleUnitsCounter[player]--;
     5565}
     5566
     5567function isIdleCountDefined(player)
     5568{
     5569    return (player in g_idleUnitsCounter);
     5570}
     5571
     5572function getIdleCount(player)
     5573{
     5574    if (!isIdleCountDefined(player))
     5575        return 0;
     5576    else
     5577        return g_idleUnitsCounter[player];
     5578}
     5579
    54845580Engine.RegisterComponentType(IID_UnitAI, "UnitAI", UnitAI);