Ticket #3731: t3731_observer_selection_panels_v1.patch

File t3731_observer_selection_panels_v1.patch, 17.5 KB (added by elexis, 8 years ago)
  • binaries/data/mods/public/gui/session/input.js

    function handleInputBeforeGui(ev, hovere  
    683683                var result = updateBuildingPlacementPreview(); // includes an update of the snap entity candidates
    684684
    685685                if (result && result.cost)
    686686                {
    687687                    placementSupport.tooltipMessage = getEntityCostTooltip(result);
    688                     var neededResources = Engine.GuiInterfaceCall("GetNeededResources", result.cost);
     688                    var neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost": result.cost });
    689689                    if (neededResources)
    690690                        placementSupport.tooltipMessage += getNeededResourcesTooltip(neededResources);
    691691                }
    692692
    693693                break;
    function handleInputAfterGui(ev)  
    10791079                placementSupport.wallSnapEntitiesIncludeOffscreen = false;
    10801080            }
    10811081            else
    10821082            {
    10831083                // cancel if not enough resources
    1084                 if (placementSupport.template && Engine.GuiInterfaceCall("GetNeededResources", GetTemplateData(placementSupport.template).cost))
     1084                if (placementSupport.template && Engine.GuiInterfaceCall("GetNeededResources", { "cost": GetTemplateData(placementSupport.template).cost }))
    10851085                {
    10861086                    placementSupport.Reset();
    10871087                    inputState = INPUT_NORMAL;
    10881088                    return true;
    10891089                }
    function addTrainingToQueue(selection, t  
    14121412                        inputState = INPUT_NORMAL;
    14131413                }
    14141414                else if (limits.canBeAddedCount == undefined ||
    14151415                    limits.canBeAddedCount > batchTrainingCount * appropriateBuildings.length)
    14161416                {
    1417                     if (Engine.GuiInterfaceCall("GetNeededResources", multiplyEntityCosts(
    1418                         template, batchTrainingCount + batchIncrementSize)))
     1417                    if (Engine.GuiInterfaceCall("GetNeededResources", { "cost":
     1418                        multiplyEntityCosts(template, batchTrainingCount + batchIncrementSize) }))
    14191419                        return;
    14201420
    14211421                    batchTrainingCount += batchIncrementSize;
    14221422                }
    14231423                batchTrainingEntityAllowedCount = limits.canBeAddedCount;
    function addTrainingToQueue(selection, t  
    14301430                // fall through to create the new batch
    14311431            }
    14321432        }
    14331433
    14341434        // Don't start a new batch if decrementing or unable to afford it.
    1435         if (decrement || Engine.GuiInterfaceCall("GetNeededResources",
    1436             multiplyEntityCosts(template, batchIncrementSize)))
     1435        if (decrement || Engine.GuiInterfaceCall("GetNeededResources", { "cost":
     1436            multiplyEntityCosts(template, batchIncrementSize) }))
    14371437            return;
    14381438
    14391439        inputState = INPUT_BATCHTRAINING;
    14401440        batchTrainingEntities = selection;
    14411441        batchTrainingType = trainEntType;
  • binaries/data/mods/public/gui/session/selection_details.js

    function updateSelectionDetails()  
    412412        displayMultiple(selection);
    413413
    414414    // Show basic details.
    415415    detailsPanel.hidden = false;
    416416
    417     if (g_IsObserver)
    418     {
    419         // Observers don't need these displayed.
    420         supplementalDetailsPanel.hidden = true;
    421         commandsPanel.hidden = true;
    422     }
    423     else
    424     {
    425         // Fill out commands panel for specific unit selected (or first unit of primary group)
    426         updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection);
    427     }
     417    // Fill out commands panel for specific unit selected (or first unit of primary group)
     418    updateUnitCommands(entState, supplementalDetailsPanel, commandsPanel, selection);
    428419}
  • binaries/data/mods/public/gui/session/selection_panels.js

    g_SelectionPanels.Alert = {  
    8888        else if (data.item == "end")
    8989        {
    9090            data.button.hidden = !data.unitEntState.alertRaiser.hasRaisedAlert;
    9191            data.icon.sprite = "stretched:session/icons/bell_level0.png";
    9292        }
    93         data.button.enabled = !data.button.hidden;
     93        data.button.enabled = !data.button.hidden && IsPlaying();
    9494    },
    9595};
    9696
    9797// BARTER
    9898g_SelectionPanels.Barter = {
    g_SelectionPanels.Barter = {  
    156156        var grayscale = data.isSelected ? "color: 0 0 0 100:grayscale:" : "";
    157157
    158158        // do we have enough of this resource to sell?
    159159        var neededRes = {};
    160160        neededRes[data.item] = data.amountToSell;
    161         var canSellCurrent = Engine.GuiInterfaceCall("GetNeededResources", neededRes) != undefined ? "color:255 0 0 80:" : "";
     161        var canSellCurrent = Engine.GuiInterfaceCall("GetNeededResources", {
     162            "cost": neededRes,
     163            "player": data.unitEntState.player
     164        }) ? "color:255 0 0 80:" : "";
     165
    162166        // Let's see if we have enough resources to barter.
    163167        neededRes = {};
    164168        neededRes[g_barterSell] = data.amountToSell;
    165         var canBuyAny = Engine.GuiInterfaceCall("GetNeededResources", neededRes) != undefined ? "color:255 0 0 80:" : "";
     169        var canBuyAny = Engine.GuiInterfaceCall("GetNeededResources", {
     170            "cost": neededRes,
     171            "player": data.unitEntState.player
     172        }) ? "color:255 0 0 80:" : "";
    166173
    167174        data.icon.Sell.sprite = canSellCurrent + "stretched:"+grayscale+"session/icons/resources/" + data.item + ".png";
    168175        data.icon.Buy.sprite = canBuyAny + "stretched:"+grayscale+"session/icons/resources/" + data.item + ".png";
    169176
    170177        data.button.Buy.hidden = data.isSelected;
     178        data.button.Buy.enabled = IsPlaying();
    171179        data.button.Sell.hidden = false;
    172180        data.selectionIcon.hidden = !data.isSelected;
    173181    },
    174182    "setPosition": function(data)
    175183    {
    g_SelectionPanels.Command = {  
    210218        data.countDisplay.caption = data.item.count || "";
    211219    },
    212220    "setGraphics": function(data)
    213221    {
    214222        data.icon.sprite = "stretched:session/icons/" + data.item.icon;
     223        data.button.enabled = IsPlaying();
    215224    },
    216225    "setPosition": function(data)
    217226    {
    218227        var size = data.button.size;
    219228        // count on square buttons, so size.bottom is the width too
    g_SelectionPanels.AllyCommand = {  
    260269        data.countDisplay.caption = data.item.count || "";
    261270    },
    262271    "setGraphics": function(data)
    263272    {
    264273        data.icon.sprite = "stretched:session/icons/" + data.item.icon;
     274        data.button.enabled = IsPlaying();
    265275    },
    266276    "setPosition": function(data)
    267277    {
    268278        var size = data.button.size;
    269279        // count on square buttons, so size.bottom is the width too
    g_SelectionPanels.Construction = {  
    291301    {
    292302        data.entType = data.item;
    293303        data.template = GetTemplateData(data.entType);
    294304        if (!data.template) // abort if no template
    295305            return false;
    296         data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", data.template.requiredTechnology);
     306
     307        data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
     308            "tech": data.template.requiredTechnology,
     309            "player": data.unitEntState.player
     310        });
     311
    297312        if (data.template.cost)
    298         {
    299             var totalCost = multiplyEntityCosts(data.template, 1);
    300             data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", totalCost);
    301         }
     313            data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", {
     314                "cost": multiplyEntityCosts(data.template, 1),
     315                "player": data.unitEntState.player
     316            });
     317
    302318        data.limits = getEntityLimitAndCount(data.playerState, data.entType);
    303319        return true;
    304320    },
    305321    "setAction": function(data)
    306322    {
    g_SelectionPanels.Construction = {  
    340356        else if (data.neededResources)
    341357        {
    342358            data.button.enabled = false;
    343359            modifier += resourcesToAlphaMask(data.neededResources) +":";
    344360        }
     361        else
     362            data.button.enabled = IsPlaying();
    345363
    346364        if (data.template.icon)
    347365            data.icon.sprite = modifier + "stretched:session/portraits/" + data.template.icon;
    348366    },
    349367    "setPosition": function(data)
    g_SelectionPanels.Formation = {  
    392410            tooltip += "\n" + "[color=\"red\"]" + translate(data.formationInfo.tooltip) + "[/color]";
    393411        data.button.tooltip = tooltip;
    394412    },
    395413    "setGraphics": function(data)
    396414    {
    397         data.button.enabled = data.formationOk;
     415        data.button.enabled = data.formationOk && IsPlaying();
    398416        var grayscale = data.formationOk ? "" : "grayscale:";
    399417        data.guiSelection.hidden = !data.formationSelected;
    400418        data.icon.sprite = "stretched:"+grayscale+"session/icons/"+data.formationInfo.icon;
    401419    },
    402420};
    g_SelectionPanels.Gate = {  
    543561                    return count;
    544562                }, 0);
    545563
    546564            tooltip += "\n" + getEntityCostTooltip(data.template, data.wallCount);
    547565
     566            data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", { "cost":
     567                multiplyEntityCosts(data.template, data.wallCount) });
    548568
    549             data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", multiplyEntityCosts(data.template, data.wallCount));
    550569            if (data.neededResources)
    551570                tooltip += getNeededResourcesTooltip(data.neededResources);
    552571        }
    553572        data.button.tooltip = tooltip;
    554573    },
    555574    "setGraphics": function(data)
    556575    {
     576        data.button.enabled = IsPlaying();
    557577        var gateIcon;
    558578        if (data.item.gate)
    559579        {
    560580            // If already a gate, show locking actions
    561581            gateIcon = "icons/lock_" + GATE_ACTIONS[data.item.locked ? 0 : 1] + "ed.png";
    g_SelectionPanels.Pack = {  
    638658            data.icon.sprite = "stretched:session/icons/cancel.png";
    639659        else if (data.item.packed)
    640660            data.icon.sprite = "stretched:session/icons/unpack.png";
    641661        else
    642662            data.icon.sprite = "stretched:session/icons/pack.png";
     663
     664        data.button.enabled = IsPlaying();
    643665    },
    644666    "setPosition": function(data)
    645667    {
    646668        var index = data.i + getNumberOfRightPanelButtons();
    647669        setPanelObjectPosition(data.button, index, data.rowLength);
    g_SelectionPanels.Queue = {  
    718740    },
    719741    "setGraphics": function(data)
    720742    {
    721743        if (data.template.icon)
    722744            data.icon.sprite = "stretched:session/portraits/" + data.template.icon;
     745
     746        data.button.enabled = IsPlaying();
    723747    },
    724748};
    725749
    726750// RESEARCH
    727751g_SelectionPanels.Research = {
    g_SelectionPanels.Research = {  
    777801        data.unchosenIcon = data.positions.map(function(p) {
    778802            return Engine.GetGUIObjectByName("unitResearchUnchosenIcon["+p+"]");
    779803        });
    780804
    781805        data.neededResources = data.template.map(function(t) {
    782             return Engine.GuiInterfaceCall("GetNeededResources", t.cost);
     806            return Engine.GuiInterfaceCall("GetNeededResources", {
     807                "cost": t.cost,
     808                "player": data.unitEntState.player
     809            });
    783810        });
    784811
    785812        data.requirementsPassed = data.entType.map(function(e) {
    786             return Engine.GuiInterfaceCall("CheckTechnologyRequirements",e);
     813            return Engine.GuiInterfaceCall("CheckTechnologyRequirements", {
     814                "tech": e,
     815                "player": data.unitEntState.player
     816            });
    787817        });
    788818
    789819        data.pair = Engine.GetGUIObjectByName("unitResearchPair["+data.i+"]");
    790820
    791821        return true;
    g_SelectionPanels.Research = {  
    804834            if (!data.requirementsPassed[i])
    805835            {
    806836                tooltip += "\n" + template.requirementsTooltip;
    807837                if (template.classRequirements)
    808838                {
    809                     var player = Engine.GetPlayerID();
     839                    var player = data.unitEntState.player;
    810840                    var current = GetSimState().players[player].classCounts[template.classRequirements.class] || 0;
    811841                    var remaining = template.classRequirements.number - current;
    812842                    tooltip += " " + sprintf(translatePlural("Remaining: %(number)s to build.", "Remaining: %(number)s to build.", remaining), { number: remaining});
    813843                }
    814844            }
    g_SelectionPanels.Research = {  
    860890            {
    861891                button.enabled = false;
    862892                modifier += resourcesToAlphaMask(data.neededResources[i]) + ":";
    863893            }
    864894            else
    865                 button.enabled = true;
     895                button.enabled = IsPlaying();
    866896
    867897            if (data.template[i].icon)
    868898                data.icon[i].sprite = modifier + "stretched:session/portraits/" + data.template[i].icon;
    869899        }
    870900        for (var button of data.buttonsToHide)
    g_SelectionPanels.Selection = {  
    968998    },
    969999    "setGraphics": function(data)
    9701000    {
    9711001        if (data.template.icon)
    9721002            data.icon.sprite = "stretched:session/portraits/" + data.template.icon;
     1003
     1004        data.button.enabled = IsPlaying();
    9731005    },
    9741006};
    9751007
    9761008// STANCE
    9771009g_SelectionPanels.Stance = {
    g_SelectionPanels.Stance = {  
    10031035    },
    10041036    "setGraphics": function(data)
    10051037    {
    10061038        data.guiSelection.hidden = !data.stanceSelected;
    10071039        data.icon.sprite = "stretched:session/icons/stances/"+data.item+".png";
     1040        data.button.enabled = IsPlaying();
    10081041    },
    10091042};
    10101043
    10111044// TRAINING
    10121045g_SelectionPanels.Training = {
    g_SelectionPanels.Training = {  
    10221055    {
    10231056        data.entType = data.item;
    10241057        data.template = GetTemplateData(data.entType);
    10251058        if (!data.template)
    10261059            return false;
    1027         data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", data.template.requiredTechnology);
     1060
     1061        data.technologyEnabled = Engine.GuiInterfaceCall("IsTechnologyResearched", {
     1062            "tech": data.template.requiredTechnology,
     1063            "player": data.unitEntState.player
     1064        });
    10281065
    10291066        var [buildingsCountToTrainFullBatch, fullBatchSize, remainderBatch] =
    10301067            getTrainingBatchStatus(data.playerState, data.unitEntState.id, data.entType, data.selection);
    10311068        data.buildingsCountToTrainFullBatch = buildingsCountToTrainFullBatch;
    10321069        data.fullBatchSize = fullBatchSize;
    g_SelectionPanels.Training = {  
    10361073            data.trainNum = buildingsCountToTrainFullBatch * fullBatchSize + remainderBatch;
    10371074
    10381075        if (data.template.cost)
    10391076        {
    10401077            var totalCosts = multiplyEntityCosts(data.template, data.trainNum);
    1041             data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", totalCosts);
     1078            data.neededResources = Engine.GuiInterfaceCall("GetNeededResources", {
     1079                "cost": totalCosts,
     1080                "player": data.unitEntState.player
     1081            });
    10421082        }
    10431083
    10441084        return true;
    10451085    },
    10461086    "setAction": function(data)
    var g_PanelsOrder = [  
    11381178    "Command",
    11391179    "AllyCommand",
    11401180    "Queue",
    11411181    "Selection",
    11421182];
     1183
     1184/**
     1185 * Returns true if the user is an assigned player or if an observer uses the change-perspective tool.
     1186 */
     1187function IsPlaying()
     1188{
     1189    return Engine.GetPlayerID() != -1;
     1190}
  • binaries/data/mods/public/gui/session/unit_commands.js

    function updateUnitCommands(entState, su  
    166166    // Get player state to check some constraints
    167167    // e.g. presence of a hero or build limits
    168168    var simState = GetSimState();
    169169    var playerState = simState.players[player];
    170170
    171     if (entState.player == player || g_DevSettings.controlAll)
     171    if (entState.player == player || g_DevSettings.controlAll || g_IsObserver)
    172172    {
    173173        for (var guiName of g_PanelsOrder)
    174174        {
    175175            if (
    176176                g_SelectionPanels[guiName].conflictsWith &&
    177177                g_SelectionPanels[guiName].conflictsWith.some(function (p) { return g_SelectionPanels[p].used; })
    178178            )
    179179                continue;
    180180
    181             setupUnitPanel(guiName, entState, playerState);
     181            setupUnitPanel(guiName, entState, simState.players[entState.player]);
    182182        }
    183183
    184184        supplementalDetailsPanel.hidden = false;
    185185        commandsPanel.hidden = false;
    186186    }
  • binaries/data/mods/public/simulation/components/GuiInterface.js

    GuiInterface.prototype.GetTechnologyData  
    582582
    583583    let cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
    584584    return GetTechnologyDataHelper(template, cmpPlayer.GetCiv());
    585585};
    586586
    587 GuiInterface.prototype.IsTechnologyResearched = function(player, tech)
     587GuiInterface.prototype.IsTechnologyResearched = function(player, data)
    588588{
    589     if (!tech)
     589    if (!data.tech)
    590590        return true;
    591591
    592     let cmpTechnologyManager = QueryPlayerIDInterface(player, IID_TechnologyManager);
     592    let cmpTechnologyManager = QueryPlayerIDInterface(data.player || player, IID_TechnologyManager);
    593593
    594594    if (!cmpTechnologyManager)
    595595        return false;
    596596
    597     return cmpTechnologyManager.IsTechnologyResearched(tech);
     597    return cmpTechnologyManager.IsTechnologyResearched(data.tech);
    598598};
    599599
    600600// Checks whether the requirements for this technology have been met
    601 GuiInterface.prototype.CheckTechnologyRequirements = function(player, tech)
     601GuiInterface.prototype.CheckTechnologyRequirements = function(player, data)
    602602{
    603     let cmpTechnologyManager = QueryPlayerIDInterface(player, IID_TechnologyManager);
     603    let cmpTechnologyManager = QueryPlayerIDInterface(data.player || player, IID_TechnologyManager);
    604604
    605605    if (!cmpTechnologyManager)
    606606        return false;
    607607
    608     return cmpTechnologyManager.CanResearch(tech);
     608    return cmpTechnologyManager.CanResearch(data.tech);
    609609};
    610610
    611611// Returns technologies that are being actively researched, along with
    612612// which entity is researching them and how far along the research is.
    613613GuiInterface.prototype.GetStartedResearch = function(player)
    GuiInterface.prototype.GetIncomingAttack  
    645645{
    646646    return QueryPlayerIDInterface(player, IID_AttackDetection).GetIncomingAttacks();
    647647};
    648648
    649649// Used to show a red square over GUI elements you can't yet afford.
    650 GuiInterface.prototype.GetNeededResources = function(player, amounts)
     650GuiInterface.prototype.GetNeededResources = function(player, data)
    651651{
    652     return QueryPlayerIDInterface(player).GetNeededResources(amounts);
     652    return QueryPlayerIDInterface(data.player || player).GetNeededResources(data.cost);
    653653};
    654654
    655655/**
    656656 * Add a timed notification.
    657657 * Warning: timed notifacations are serialised
    GuiInterface.prototype.SetWallPlacementP  
    14861486            result.cost.time += tplData.cost.time;
    14871487        }
    14881488
    14891489        let canAfford = true;
    14901490        let cmpPlayer = QueryPlayerIDInterface(player, IID_Player);
    1491         if (cmpPlayer && cmpPlayer.GetNeededResources(result.cost))
     1491        if (cmpPlayer && cmpPlayer.GetNeededResources({ "cost": result.cost }))
    14921492            canAfford = false;
    14931493
    14941494        let cmpVisual = Engine.QueryInterface(ent, IID_Visual);
    14951495        if (cmpVisual)
    14961496        {