Ticket #2357: idle_worker_blink_v3.patch

File idle_worker_blink_v3.patch, 18.8 KB (added by Michael, 10 years ago)

Moved ownershipChanged to player; added label.

  • 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: [var data]
     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;
    20  *                              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
     18 *                               arguments: [var data]
    2219 */
    23 function fadeColour(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)
     20function startColorFade(name, tickInterval, duration, fun_colorTransform, restartAble, fun_smoothRestart) // TODO: replace restartAble = true, fun_smoothRestart = null when it is supported (spiderMonkey upgrade #1886)
    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;  // TODO: ' !== false' and add default parameter
     39        data.fun_smoothRestart = fun_smoothRestart;
     40        data.tickCounter = 0;
     41        data.runsUntilStop = duration == 0;
     42        data.stopFade = false;
     43        var rgb = {"r": 0,"g": 0,"b": 0,"o": 100};
     44        data.rgb = rgb;
     45        // store it!
     46        g_colorFade[name] = data;
     47
     48        // start with fading
     49        fadeColorTick(name);
    4250    }
     51    else if (restartAble)
     52    {
     53        restartColorFade(name, tickInterval, duration, fun_colorTransform, restartAble, fun_smoothRestart);
     54        return;
     55    }
     56}
     57
     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    var data = g_colorFade[name];
     72       
     73    // change the color
     74    data.fun_colorTransform(data);
    4375   
    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;
     76    // set new color
     77    var rgb = data.rgb;
     78    overlay.sprite="colour: "+rgb.r+" "+rgb.g+" "+rgb.b+" "+rgb.o;
    4979
    5080    // recusive call, if duration is positive
    51     duration-= changeInterval;
    52     if (duration > 0 && colour.o > 0)
     81    if (!data.stopFade && (data.runsUntilStop || data.duration - (data.tickInterval * data.tickCounter) > 0))
    5382    {
    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;
     83        var id = setTimeout(function() { fadeColorTick(name); }, data.tickInterval);
     84        data.timerId = id;
     85        data.tickCounter++;
    5786    }
    5887    else
    5988    {
    6089        overlay.hidden = true;
    61         stopColourFade(name);
     90        stopColorFade(name);
    6291    }
    6392}
    6493
    65 
    6694/**
    67  * checks, if a colour fade on that object is running
    68  * name: name of the object which colour fade should be checked
     95 * checks, if a color fade on that object is running
     96 * name: name of the object which color fade should be checked
    6997 * return: true a running fade was found
    7098 */
    71 function isColourFadeRunning(name)
     99function isColorFadeRunning(name)
    72100{
    73     return name in g_colorFade.id;
     101    return name in g_colorFade;
    74102}
    75103
    76104/**
    77  * stops fading a colour
    78  * name: name of the object which colour fade should be stopped
    79  * hideOverlay: hides the overlay, if true
     105 * stops fading a color
     106 * name: name of the object which color fade should be stopped
     107 * hideOverlay [optional]: hides the overlay, if true [default: true]
    80108 * return: true a running fade was stopped
    81109 */
    82 function stopColourFade(name, hideOverlay)
     110function stopColorFade(name, hideOverlay) //TODO: add 'hideOverlay = true' when its supported (spiderMonkey upgrade #1886)
    83111{
    84     // check, if a colour fade is running
    85     if (!isColourFadeRunning(name))
     112    // check, if a color fade is running
     113    if (!isColorFadeRunning(name))
    86114        return false;
    87115
    88116    // delete the timer
    89     clearTimeout(g_colorFade.id[name]);
    90     delete g_colorFade.id[name];
    91     delete g_colorFade.tick[name];
    92    
     117    clearTimeout(g_colorFade[name].timerId);
     118    delete g_colorFade[name];
     119
     120    hideOverlay = hideOverlay !== false; // TODO: remove this line and add default value for hideOverlay
    93121    // get the overlay and hide it
    94122    if (hideOverlay)
    95123    {
    96124        var overlay = Engine.GetGUIObjectByName(name);
    97         if(overlay)
     125        if (overlay)
    98126            overlay.hidden = true;
    99127    }
    100128    return true;
     
    101129}
    102130
    103131/**
    104  * restarts a colour fade
    105  * see paramter in fadeColour function
     132 * restarts a color fade
     133 * see paramter in startColorFade function
    106134 */
    107 function restartColourFade(name, changeInterval, duration, colour, fun_colorTransform, fun_smoothRestart, tickCounter)
     135function restartColorFade(name)
    108136{
    109     // check, if a colour fade is running
    110     if (!isColourFadeRunning(name))
     137    // check, if a color fade is running
     138    if (!isColorFadeRunning(name))
    111139        return false;
    112140   
     141    var data = g_colorFade[name];
    113142    // check, if fade can be restarted smoothly
    114     if (fun_smoothRestart)
     143    if (data.fun_smoothRestart)
    115144    {
    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);
     145        data.fun_smoothRestart(data);
    120146    }
    121147    // stop it and restart it
    122148    else
    123149    {
    124         stopColourFade(name, true);
    125         fadeColour(name, changeInterval, duration, colour, fun_colorTransform);
     150        stopColorFade(name, false);
     151        startColorFade(name, data.changeInterval, data.duration, data.fun_colorTransform, data.restartAble, data.fun_smoothRestart);
    126152    }
    127153    return true;
    128154}
     
    133159
    134160var g_fadeAttackUnit = {};
    135161g_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
     162g_fadeAttackUnit.blinkingChangeInterval = 5; // how often should the color be changed during the blinking phase
     163g_fadeAttackUnit.gbcolorChangeRate = 3; // how fast should blue and green part of the color change
    138164g_fadeAttackUnit.fadeOutStart = 100; // when should the fade out start using the opacity
    139165g_fadeAttackUnit.opacityChangeRate = 3; // how fast should opacity change
    140166
    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)
     167function colorFade_attackUnit(data)
    146168{
     169    var rgb = data.rgb;
     170    // init color
     171    if (data.tickCounter == 0)
     172        rgb.r = 175;
    147173    // blinking
    148     if (tickCounter < g_fadeAttackUnit.blinkingTicks)
     174    if (data.tickCounter < g_fadeAttackUnit.blinkingTicks)
    149175    {
    150176        // slow that process down
    151         if (tickCounter % g_fadeAttackUnit.blinkingChangeInterval != 0)
     177        if (data.tickCounter % g_fadeAttackUnit.blinkingChangeInterval != 0)
    152178            return;
    153179           
    154         rgb.g = rgb.g == 0 ? 255 : rgb.g = 0;
    155         rgb.b = rgb.b == 0 ? 255 : rgb.b = 0;
     180        rgb.g = rgb.g == 0 ? 255 : 0;
    156181    }
    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)
     182    // wait a short time and then color fade from red to grey to nothing
     183    else if ( data.tickCounter >= g_fadeAttackUnit.blinkingTicks + g_fadeAttackUnit.blinkingChangeInterval)
    159184    {
    160         rgb.g = rgb.g < 255 ? rgb.g += g_fadeAttackUnit.gbColourChangeRate * Math.sqrt(tickCounter - g_fadeAttackUnit.blinkingTicks) : 255;
    161         rgb.b = rgb.g;
     185        rgb.g = rgb.g < 255 ? rgb.g += g_fadeAttackUnit.gbcolorChangeRate * Math.sqrt(data.tickCounter - g_fadeAttackUnit.blinkingTicks) : 255;
    162186       
    163187        // start with fading it out
    164188        if (rgb.g > g_fadeAttackUnit.fadeOutStart)
    165189            rgb.o = rgb.o > g_fadeAttackUnit.opacityChangeRate ? rgb.o -= g_fadeAttackUnit.opacityChangeRate : 0;
     190        // check for end
     191        if (rgb.o == 0)
     192            data.stopFade = true;
    166193    }
     194    rgb.b = rgb.g;
    167195}
    168196
    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)
     197function smoothColorFadeRestart_attackUnit(data)
    175198{
    176199    // check, if in blinking phase
    177     if (tickCounter < g_fadeAttackUnit.blinkingTicks)
     200    if (data.tickCounter < g_fadeAttackUnit.blinkingTicks)
    178201    {
    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;
     202        data.tickCounter = data.tickCounter % (g_fadeAttackUnit.blinkingChangeInterval * 2);
    184203    }
    185     return 1;
     204    else
     205        data.tickCounter = 1;
    186206}
    187207
    188 //[END] of hero fade functions
    189  No newline at end of file
     208//[END] of hero fade functions
     209//[START] idle workers icon
     210
     211//var g_fadeIdleWorker = {};
     212
     213function colorFade_IdleWorker(data)
     214{
     215    var rgb = data.rgb;
     216    // init color
     217    if (data.tickCounter == 0)
     218    {
     219        rgb.r = 255;
     220        rgb.g = 255;
     221        rgb.b = 255;
     222    }
     223    // hide it every tick
     224    if (data.tickCounter % 2 == 0)
     225        rgb.o = 0;
     226    else
     227        rgb.o = 100;
     228}
     229
     230//[END] of idle workers icon functions
     231 No newline at end of file
  • binaries/data/mods/public/gui/session/session.js

     
    486486
    487487    updateHero();
    488488    updateGroups();
     489    updateIdleWorkerButton();
    489490    updateDebug();
    490491    updatePlayerDisplay();
    491492    updateSelectionDetails();
     
    499500    if (battleState)
    500501        global.music.setState(global.music.states[battleState]);
    501502   
     503};
     504
     505/**
     506 * updates the idle worker button
     507 */
     508function updateIdleWorkerButton()
     509{
     510    var idleUnitsCounter = Engine.GuiInterfaceCall("GetIdleWorkerButtonCount");
     511    // set color fade and label
     512    if (idleUnitsCounter > 0)
     513    {
     514        startColorFade("idleWorkerOverlay", 750, 0, colorFade_IdleWorker, false);
     515        var label = Engine.GetGUIObjectByName("idleWorkerLabel")
     516        label.caption = idleUnitsCounter;
     517        label.hidden = false;
     518    }
     519    else
     520    {
     521        stopColorFade("idleWorkerOverlay");
     522        var label = Engine.GetGUIObjectByName("idleWorkerLabel");
     523        label.hidden = true;
     524    }
    502525}
    503526
     527
    504528/**
    505529* updates a status bar on the GUI
    506530* nameOfBar: name of the bar
     
    595619    {   
    596620        g_previousHeroHitPoints = heroState.hitpoints;
    597621        // trigger the animation
    598         fadeColour("heroHitOverlay", 100, 10000, {"r": 175,"g": 0,"b": 0,"o": 100}, colourFade_attackUnit, smoothColourFadeRestart_attackUnit);
     622        startColorFade("heroHitOverlay", 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
    599623        return;
    600624    }
    601625}
  • binaries/data/mods/public/gui/session/session.xml

     
    956956                tooltip="Find idle worker"
    957957                hotkey="selection.idleworker"
    958958            >
    959             <!-- TODO: should highlight the button if there's non-zero idle workers -->
    960959            <object size="0 0 100% 100%" type="image" sprite="idleWorker" ghost="true" />
    961             <action on="Press">findIdleUnit(["Female", "Trade", "FishingBoat", "CitizenSoldier", "Healer"]);</action>
     960            <object name="idleWorkerOverlay" hidden="true" type="image" ghost="true" size="2 2 100%-2 100%-2"/>
     961            <object name="idleWorkerLabel" type="text" style="groupIconsText" size="0 0 100% 100%" ghost="true"/>
     962            <action on="Press">findIdleUnit(["Worker", "Trade", "FishingBoat", "Healer"]);</action>
    962963            </object>
    963964        </object>
    964965        </object>
  • binaries/data/mods/public/simulation/components/GuiInterface.js

     
    17181718    PlaySound(data.name, data.entity);
    17191719};
    17201720
     1721GuiInterface.prototype.GetIdleWorkerButtonCount = function(player)
     1722{
     1723    var cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
     1724    if (!cmpPlayer)
     1725        return -1;
     1726    return cmpPlayer.GetIdleWorkerButtonCount();
     1727}
     1728
    17211729function isIdleUnit(ent, idleClass)
    17221730{
    17231731    var cmpUnitAI = Engine.QueryInterface(ent, IID_UnitAI);
     
    19561964    "SetWallPlacementPreview": 1,
    19571965    "GetFoundationSnapData": 1,
    19581966    "PlaySound": 1,
     1967    "GetIdleWorkerButtonCount": 1,
    19591968    "FindIdleUnits": 1,
    19601969    "GetTradingRouteGain": 1,
    19611970    "GetTradingDetails": 1,
  • binaries/data/mods/public/simulation/components/Player.js

     
    3636    this.gatherRateMultiplier = 1;
    3737    this.cheatsEnabled = false;
    3838    this.cheatTimeMultiplier = 1;
     39    this.idleWorkerButtonCount = 0;
    3940    this.heroes = [];
    4041    Engine.QueryInterface(SYSTEM_ENTITY, IID_EndGameManager).CheckConquestCriticalEntities();
    4142};
     
    558559            if (index >= 0)
    559560                this.heroes.splice(index, 1);
    560561        }
     562       
     563        // check, if new idle worker is gone
     564        var cmpUnitAI = Engine.QueryInterface(msg.entity, IID_UnitAI);
     565        if (cmpUnitAI)
     566            if (cmpUnitAI.IsIdle() && cmpUnitAI.IsUsedForIdleWorkerButton())
     567                this.DecreaseWorkerButtonCount();
    561568    }
    562569    if (msg.to == this.playerID)
    563570    {
     
    572579
    573580        if (cmpIdentity && cmpIdentity.HasClass("Hero"))
    574581            this.heroes.push(msg.entity);
     582           
     583        // check, if new idle worker is there
     584        var cmpUnitAI = Engine.QueryInterface(msg.entity, IID_UnitAI);
     585        if (cmpUnitAI)
     586            if (cmpUnitAI.IsIdle() && cmpUnitAI.IsUsedForIdleWorkerButton())
     587                this.IncreaseWorkerButtonCount();
    575588    }
    576589};
    577590
     
    665678        cmpGUIInterface.PushNotification(notification);
    666679};
    667680
     681Player.prototype.GetIdleWorkerButtonCount = function()
     682{
     683    return this.idleWorkerButtonCount;
     684};
     685
     686Player.prototype.IncreaseWorkerButtonCount = function()
     687{
     688    this.idleWorkerButtonCount++;
     689};
     690
     691Player.prototype.DecreaseWorkerButtonCount = function()
     692{
     693    this.idleWorkerButtonCount--;
     694    if (this.idleWorkerButtonCount < 0)
     695        error("Negative worker idle count for player '" + this.playerID + "'");
     696};
     697
    668698Engine.RegisterComponentType(IID_Player, "Player", Player);
  • binaries/data/mods/public/simulation/components/UnitAI.js

     
    123123    },
    124124};
    125125
     126// classes used for the work idle button
     127var g_idleClassNames = ["Worker", "Trade", "FishingBoat", "Healer"];
     128
    126129// See ../helpers/FSM.js for some documentation of this FSM specification syntax
    127130var UnitFsmSpec = {
    128131
     
    169172    "GuardedAttacked": function(msg) {
    170173        // ignore
    171174    },
     175   
     176    "UnitIdleChanged": function(msg) {
     177        // check if this are units which can be selected by the workes idle button
     178        if(this.IsUsedForIdleWorkerButton())
     179        {
     180            if(msg.idle)
     181                this.IncreaseIdleWorkerButtonCount();
     182            else
     183                this.DecreaseIdleWorkerButtonCount();
     184        }
     185    },
    172186
    173187    // Formation handlers:
    174188
     
    31453159    return Engine.QueryInterface(this.entity, IID_Heal);
    31463160};
    31473161
     3162UnitAI.prototype.IsUsedForIdleWorkerButton = function()
     3163{
     3164    var cmpIdentity = Engine.QueryInterface(this.entity, IID_Identity);
     3165    if (!cmpIdentity)
     3166        return false;
     3167    // check idle class names   
     3168    for each(var className in g_idleClassNames)
     3169        if (cmpIdentity.HasClass(className)) {
     3170            return true;
     3171        }
     3172    // return false because all checks where negative
     3173    return false;
     3174};
     3175
    31483176UnitAI.prototype.IsIdle = function()
    31493177{
    31503178    return this.isIdle;
     
    37913819    UnitFsm.ProcessMessage(this, {"type": "PackFinished", "packed": msg.packed});
    37923820};
    37933821
     3822UnitAI.prototype.OnUnitIdleChanged = function(msg)
     3823{
     3824    var cmpOwnership = Engine.QueryInterface(this.entity, IID_Ownership);
     3825    if (!cmpOwnership)
     3826        return;
     3827    UnitFsm.ProcessMessage(this, {"type": "UnitIdleChanged", "idle": msg.idle, "player": cmpOwnership.GetOwner()});
     3828}
     3829
    37943830//// Helper functions to be called by the FSM ////
    37953831
    37963832UnitAI.prototype.GetWalkSpeed = function()
     
    55905626    );
    55915627};
    55925628
     5629UnitAI.prototype.IncreaseIdleWorkerButtonCount = function()
     5630{
     5631    var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
     5632    if (cmpPlayer)
     5633        cmpPlayer.IncreaseWorkerButtonCount();
     5634}
     5635
     5636UnitAI.prototype.DecreaseIdleWorkerButtonCount = function()
     5637{
     5638    var cmpPlayer = QueryOwnerInterface(this.entity, IID_Player);
     5639    if (cmpPlayer)
     5640        cmpPlayer.DecreaseWorkerButtonCount();
     5641}
     5642
    55935643Engine.RegisterComponentType(IID_UnitAI, "UnitAI", UnitAI);