Ticket #3000: heropanel_split.patch

File heropanel_split.patch, 9.6 KB (added by Stephen Imhoff, 8 years ago)

split update/display cycle.

  • binaries/data/mods/public/gui/session/session.js

    From d2a17557b42fda18c666bf1cf498654c9a07f13e Mon Sep 17 00:00:00 2001
    From: "Stephen A. Imhoff" <clockwork-muse@outlook.com>
    Date: Sat, 14 May 2016 11:03:03 +0900
    Subject: [PATCH] heros
    
    ---
     binaries/data/mods/public/gui/session/session.js   | 149 +++++++++++++++------
     .../gui/session/session_objects/hero_icon.xml      |  29 ++--
     2 files changed, 120 insertions(+), 58 deletions(-)
    
    diff --git a/binaries/data/mods/public/gui/session/session.js b/binaries/data/mods/public/gui/session/session.js
    index c1a0d9d..bee337e 100644
    a b var g_ShowGuarded = false;  
    143143var g_AdditionalHighlight = [];
    144144
    145145/**
    146  * Blink the hero selection if that entity has lost health since the last turn.
     146 * List of heroes to display.
    147147 */
    148 var g_PreviousHeroHitPoints;
     148var g_Heroes = [];
    149149
    150150/**
    151151 * Unit classes to be checked for the idle-worker-hotkey.
    function init(initData, hotloadData)  
    269269    gameSpeed.onSelectionChange = function() { changeGameSpeed(+this.list_data[this.selected]); };
    270270    initMenuPosition();
    271271
     272    for (let slot = 0, length = Engine.GetGUIObjectByName("unitHeroPanel").children.length; slot < length; ++slot)
     273        initGUIHeroes(slot);
     274
    272275    // Populate player selection dropdown
    273276    let playerNames = [translate("Observer")];
    274277    let playerIDs = [-1];
    function initHotkeyTooltips()  
    320323            "session.fulltradeswap");
    321324}
    322325
     326function initGUIHeroes(slot)
     327{
     328    let button = Engine.GetGUIObjectByName("unitHeroButton[" + slot + "]");
     329    button.onPress = function()
     330    {
     331        let hero = g_Heroes.find(hero => hero.slot !== undefined && hero.slot == slot);
     332        if (!hero)
     333            return;
     334        if (!Engine.HotkeyIsPressed("selection.add"))
     335            g_Selection.reset();
     336        g_Selection.addList([hero.ent]);
     337    };
     338
     339    button.onDoublePress = function() {
     340        let hero = g_Heroes.find(hero => hero.slot !== undefined && hero.slot == slot);
     341        if (hero)
     342            selectAndMoveTo(getEntityOrHolder(hero.ent));
     343    };
     344}
     345
    323346function initializeMusic()
    324347{
    325348    initMusic();
    function updateGUIObjects()  
    726749    if (g_ShowGuarding || g_ShowGuarded)
    727750        updateAdditionalHighlight();
    728751
    729     updateHero();
     752    updateHeroes();
     753    displayHeroes();
    730754    updateGroups();
    731755    updateDebug();
    732756    updatePlayerDisplay();
    function updateGUIStatusBar(nameOfBar, points, maxPoints, direction)  
    802826}
    803827
    804828
    805 function updateHero()
     829function updateHeroes()
    806830{
    807     let unitHeroPanel = Engine.GetGUIObjectByName("unitHeroPanel");
    808     let heroButton = Engine.GetGUIObjectByName("unitHeroButton");
    809 
    810831    let playerState = GetSimState().players[g_ViewedPlayer];
    811     if (!playerState || playerState.heroes.length <= 0)
    812     {
    813         g_PreviousHeroHitPoints = undefined;
    814         unitHeroPanel.hidden = true;
    815         return;
    816     }
     832    let heroes = playerState ? playerState.heroes : [];
    817833
    818     let heroImage = Engine.GetGUIObjectByName("unitHeroImage");
    819     let heroState = GetExtendedEntityState(playerState.heroes[0]);
    820     let template = GetTemplateData(heroState.template);
    821     heroImage.sprite = "stretched:session/portraits/" + template.icon;
    822     let hero = playerState.heroes[0];
     834     g_Heroes =  g_Heroes.filter(hero => heroes.find(ent => ent == hero.ent));
    823835
    824     heroButton.onpress = function()
     836    for (let ent of heroes)
    825837    {
    826         if (!Engine.HotkeyIsPressed("selection.add"))
    827             g_Selection.reset();
    828         g_Selection.addList([hero]);
    829     };
    830     heroButton.ondoublepress = function() { selectAndMoveTo(getEntityOrHolder(hero)); };
    831     unitHeroPanel.hidden = false;
     838        let heroState = GetExtendedEntityState(ent);
     839        let template = GetTemplateData(heroState.template);
     840
     841        let hero = g_Heroes.find(hero => ent == hero.ent);
     842
     843        if (!hero)
     844        {
     845            hero = {
     846                "ent": ent,
     847                "tooltip": undefined,
     848                "sprite": "stretched:session/portraits/" + template.icon,
     849                "maxHitpoints": undefined,
     850                "currentHitpoints": heroState.hitpoints,
     851                "previousHitpoints": undefined
     852            };
     853            g_Heroes.push(hero);
     854        }
     855
     856        hero.tooltip = createHeroTooltip(heroState, template);
     857        hero.previousHitpoints = hero.currentHitpoints;
     858        hero.currentHitpoints = heroState.hitpoints;
     859        hero.maxHitpoints = heroState.maxHitpoints;
     860    }
     861}
    832862
     863function createHeroTooltip(heroState, template)
     864{
    833865    // Setup tooltip
    834     let tooltip = "[font=\"sans-bold-16\"]" + template.name.specific + "[/font]";
    835     let healthLabel = "[font=\"sans-bold-13\"]" + translate("Health:") + "[/font]";
    836     tooltip += "\n" + sprintf(translate("%(label)s %(current)s / %(max)s"), {
    837         "label": healthLabel,
    838         "current": Math.ceil(heroState.hitpoints),
    839         "max": Math.ceil(heroState.maxHitpoints)
     866    let tooltip = "[font=\"sans-bold-16\"]" + template.name.specific + "[/font]" + "\n"
     867        + sprintf(translate("%(label)s %(current)s / %(max)s"), {
     868            "label": "[font=\"sans-bold-13\"]" + translate("Health:") + "[/font]",
     869            "current": Math.ceil(heroState.hitpoints),
     870            "max": Math.ceil(heroState.maxHitpoints)
    840871    });
    841872    if (heroState.attack)
    842873        tooltip += "\n" + getAttackTooltip(heroState);
    function updateHero()  
    844875    tooltip += "\n" + getArmorTooltip(heroState.armour);
    845876    if (template.tooltip)
    846877        tooltip += "\n" + template.tooltip;
     878    return tooltip;
     879}
    847880
    848     heroButton.tooltip = tooltip;
     881function displayHeroes()
     882{
     883    let buttons = Engine.GetGUIObjectByName("unitHeroPanel").children;
    849884
    850     // update heros health bar
    851     updateGUIStatusBar("heroHealthBar", heroState.hitpoints, heroState.maxHitpoints);
     885    buttons.forEach((button, slot) =>
     886        {
     887            if (button.hidden || g_Heroes.find(hero => hero.slot !== undefined && hero.slot == slot))
     888                return;
    852889
    853     let heroHP = {
    854         "hitpoints": heroState.hitpoints,
    855         "player": g_ViewedPlayer
    856     };
     890            Engine.GetGUIObjectByName("unitHeroButton[" + slot + "]").hidden = true;
     891            stopColorFade("heroHitOverlay[" + slot + "]");
    857892
    858     if (!g_PreviousHeroHitPoints)
    859         g_PreviousHeroHitPoints = heroHP;
     893        });
    860894
    861     // if the health of the hero changed since the last update, trigger the animation
    862     if (g_PreviousHeroHitPoints.player == heroHP.player && g_PreviousHeroHitPoints.hitpoints > heroHP.hitpoints)
    863         startColorFade("heroHitOverlay", 100, 0, colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
     895    for (let displayIndex = 0; displayIndex < Math.min(g_Heroes.length, buttons.length); ++displayIndex)
     896    {
     897        let hero = g_Heroes[displayIndex];
     898        // Find the first unused slot if new, otherwise reuse previous.
     899        let slot = hero.slot === undefined ?
     900            buttons.findIndex(button => button.hidden) :
     901            hero.slot;
     902
     903        let heroButton = Engine.GetGUIObjectByName("unitHeroButton[" + slot + "]");
     904        heroButton.tooltip = hero.tooltip;
     905        updateGUIStatusBar("heroHealthBar[" + slot + "]", hero.currentHitpoints, hero.maxHitpoints);
    864906
    865     g_PreviousHeroHitPoints = heroHP;
     907        if (hero.slot === undefined)
     908        {
     909            let heroImage = Engine.GetGUIObjectByName("unitHeroImage[" + slot + "]");
     910            heroImage.sprite = hero.sprite;
     911            heroButton.hidden = false;
     912
     913            hero.slot = slot;
     914        }
     915
     916        // If the health of the hero changed since the last update, trigger the animation.
     917        if (hero.previousHitpoints > hero.currentHitpoints)
     918            startColorFade("heroHitOverlay[" + slot + "]", 100, 0,
     919                    colorFade_attackUnit, true, smoothColorFadeRestart_attackUnit);
     920
     921        // The "slot" is which button, but it's the identity (name) of the button, not its position.
     922        // Heroes stay in the same slot, but the position of the button may change.
     923        // TODO: Instead of instant position changes, animate button movement.
     924        setPanelObjectPosition(heroButton, displayIndex, buttons.length);
     925
     926    }
    866927}
    867928
    868929function updateGroups()
  • binaries/data/mods/public/gui/session/session_objects/hero_icon.xml

    diff --git a/binaries/data/mods/public/gui/session/session_objects/hero_icon.xml b/binaries/data/mods/public/gui/session/session_objects/hero_icon.xml
    index 35d7053..6219006 100644
    a b  
    22<object
    33    name="unitHeroPanel"
    44    size="0 36 50 93"
    5     hidden="true"
     5    hidden="false"
    66>
    7     <object name="unitHeroButton" size="0 0 50 50" type="button" style="iconButton"
    8         tooltip_style="sessionToolTip">
    9         <object name="unitHeroImage" size="5 5 100%-5 100%-5" type="image" ghost="true"/>
    10         <object name="heroHitOverlay" hidden="true" type="image" ghost="true" size="5 5 100%-5 100%-5"/>
    11     </object>
    12     <!-- Hero Health bar -->
    13     <object size="3 100%-7 100%-3 100%-2" name="heroHealthSection" ghost="true">
    14         <object size="0 0 100% 5" name="heroHealth" type="image" ghost="true">
    15             <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
    16             <object type="image" sprite="healthBackground" ghost="true"/>
    17             <object type="image" sprite="healthForeground" ghost="true" name="heroHealthBar"/>
    18             <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/>
     7    <repeat count="10" var="n">
     8        <object name="unitHeroButton[n]" size="0 0 50 50" type="button" hidden="true" style="iconButton" tooltip_style="sessionToolTip">
     9            <object name="unitHeroImage[n]" size="5 5 100%-5 100%-5" type="image" ghost="true"/>
     10            <object name="heroHitOverlay[n]" hidden="true" type="image" ghost="true" size="5 5 100%-5 100%-5"/>
     11            <!-- Hero Health bar -->
     12            <object size="3 100%-7 100%-3 100%-2" name="heroHealthSection[n]" ghost="true">
     13                <object size="0 0 100% 5" name="heroHealth[n]" type="image" ghost="true">
     14                    <object type="image" sprite="barBorder" ghost="true" size="-1 -1 100%+1 100%+1"/>
     15                    <object type="image" sprite="healthBackground" ghost="true"/>
     16                    <object type="image" sprite="healthForeground" ghost="true" name="heroHealthBar[n]"/>
     17                    <object type="image" sprite="statsBarShaderHorizontal" ghost="true"/>
     18                </object>
     19            </object>
    1920        </object>
    20     </object>
     21    </repeat>
    2122</object>