diff --git a/binaries/data/mods/public/gui/session_new/session.js b/binaries/data/mods/public/gui/session_new/session.js index ebf293d302..7c588f425d 100644 --- a/binaries/data/mods/public/gui/session_new/session.js +++ b/binaries/data/mods/public/gui/session_new/session.js @@ -18,7 +18,10 @@ function updateDebug() text += "\n\n"; for (var ent in g_Selection) { - text += "Entity "+ent+":\n" + uneval(Engine.GuiInterfaceCall("GetEntityState", ent)) + "\n"; + var entState = Engine.GuiInterfaceCall("GetEntityState", ent); + text += "Entity "+ent+":\n" + uneval(entState); + text += "\n\n"; + text += "Template:\n" + uneval(Engine.GuiInterfaceCall("GetTemplateData", entState.template)); } debug.caption = text; } @@ -32,7 +35,15 @@ function updateBuildButton() if (entity.buildEntities && entity.buildEntities.length) { var ent = entity.buildEntities[0]; - getGUIObjectByName("testBuild").caption = "Construct "+ent; + var template = Engine.GuiInterfaceCall("GetTemplateData", ent); + + var name; + if (template.name.specific && template.name.generic) + name = template.name.specific + " (" + template.name.generic + ")"; + else + name = template.name.specific || template.name.generic; + + getGUIObjectByName("testBuild").caption = "Construct "+name; getGUIObjectByName("testBuild").onpress = function() { testBuild(ent) }; getGUIObjectByName("testBuild").hidden = false; return; diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js index 48e0940444..55afebba2c 100644 --- a/binaries/data/mods/public/simulation/components/GuiInterface.js +++ b/binaries/data/mods/public/simulation/components/GuiInterface.js @@ -9,7 +9,7 @@ GuiInterface.prototype.Init = function() GuiInterface.prototype.GetSimulationState = function(player) { var ret = { - players: [] + "players": [] }; var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); @@ -19,8 +19,8 @@ GuiInterface.prototype.GetSimulationState = function(player) var playerEnt = cmpPlayerMan.GetPlayerByID(i); var cmpPlayer = Engine.QueryInterface(playerEnt, IID_Player); var player = { - popCount: cmpPlayer.GetPopulationCount(), - popLimit: cmpPlayer.GetPopulationLimit() + "popCount": cmpPlayer.GetPopulationCount(), + "popLimit": cmpPlayer.GetPopulationLimit() }; ret.players.push(player); } @@ -30,10 +30,12 @@ GuiInterface.prototype.GetSimulationState = function(player) GuiInterface.prototype.GetEntityState = function(player, ent) { + var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); var cmpPosition = Engine.QueryInterface(ent, IID_Position); var ret = { - position: cmpPosition.GetPosition() + "template": cmpTempMan.GetCurrentTemplateName(ent), + "position": cmpPosition.GetPosition() }; var cmpBuilder = Engine.QueryInterface(ent, IID_Builder); @@ -45,6 +47,24 @@ GuiInterface.prototype.GetEntityState = function(player, ent) return ret; }; +GuiInterface.prototype.GetTemplateData = function(player, name) +{ + var cmpTempMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_TemplateManager); + var template = cmpTempMan.GetTemplate(name); + + var ret = {}; + + if (template.Identity) + { + ret.name = { + "specific": template.Identity.SpecificName, + "generic": template.Identity.GenericName + }; + } + + return ret; +}; + GuiInterface.prototype.SetSelectionHighlight = function(player, cmd) { var cmpSelectable = Engine.QueryInterface(cmd.entity, IID_Selectable); @@ -86,6 +106,7 @@ GuiInterface.prototype.SetBuildingPlacementPreview = function(player, cmd) var exposedFunctions = { "GetSimulationState": 1, "GetEntityState": 1, + "GetTemplateData": 1, "SetSelectionHighlight": 1, "SetBuildingPlacementPreview": 1 }; diff --git a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js index b204d03d39..7ead66c8ab 100644 --- a/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js +++ b/binaries/data/mods/public/simulation/components/tests/test_GuiInterface.js @@ -8,6 +8,12 @@ AddMock(SYSTEM_ENTITY, IID_PlayerManager, { GetPlayerByID: function(id) { TS_ASSERT(id === 0 || id === 1); return 100+id; } }); +AddMock(SYSTEM_ENTITY, IID_TemplateManager, { + GetCurrentTemplateName: function(ent) { return "example"; }, + GetTemplate: function(name) { return ""; }, +}); + + AddMock(100, IID_Player, { GetPopulationCount: function() { return 10; }, GetPopulationLimit: function() { return 20; } @@ -18,7 +24,9 @@ AddMock(101, IID_Player, { GetPopulationLimit: function() { return 30; } }); -TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), { players: [{popCount:10, popLimit:20}, {popCount:40, popLimit:30}] }); +TS_ASSERT_UNEVAL_EQUALS(cmp.GetSimulationState(), { + players: [{popCount:10, popLimit:20}, {popCount:40, popLimit:30}] +}); AddMock(10, IID_Position, { @@ -34,4 +42,8 @@ AddMock(10, IID_Builder, { }); var state = cmp.GetEntityState(-1, 10); -TS_ASSERT_UNEVAL_EQUALS(state, { position: {x:1, y:2, z:3}, buildEntities: ["test1", "test2"] }); +TS_ASSERT_UNEVAL_EQUALS(state, { + template: "example", + position: {x:1, y:2, z:3}, + buildEntities: ["test1", "test2"] +}); diff --git a/source/gui/scripting/ScriptFunctions.cpp b/source/gui/scripting/ScriptFunctions.cpp index efda193176..8e32462f5b 100644 --- a/source/gui/scripting/ScriptFunctions.cpp +++ b/source/gui/scripting/ScriptFunctions.cpp @@ -27,8 +27,9 @@ #include "ps/Overlay.h" #include "ps/Player.h" #include "simulation2/Simulation2.h" -#include "simulation2/components/ICmpGuiInterface.h" #include "simulation2/components/ICmpCommandQueue.h" +#include "simulation2/components/ICmpGuiInterface.h" +#include "simulation2/components/ICmpTemplateManager.h" #include "simulation2/helpers/Selection.h" /* @@ -108,7 +109,7 @@ static jsval CloneValueBetweenContexts(JSContext* cxFrom, JSContext* cxTo, jsval return JSVAL_VOID; } -CScriptVal GuiInterfaceCall(void* cbdata, std::string name, CScriptVal data) +CScriptVal GuiInterfaceCall(void* cbdata, std::wstring name, CScriptVal data) { CGUIManager* guiManager = static_cast (cbdata); @@ -116,6 +117,7 @@ CScriptVal GuiInterfaceCall(void* cbdata, std::string name, CScriptVal data) return JSVAL_VOID; CSimulation2* sim = g_Game->GetSimulation2(); debug_assert(sim); + CmpPtr gui(*sim, SYSTEM_ENTITY); if (gui.null()) return JSVAL_VOID; @@ -138,6 +140,7 @@ void PostNetworkCommand(void* cbdata, CScriptVal cmd) return; CSimulation2* sim = g_Game->GetSimulation2(); debug_assert(sim); + CmpPtr queue(*sim, SYSTEM_ENTITY); if (queue.null()) return; @@ -177,8 +180,7 @@ void GuiScriptingInit(ScriptInterface& scriptInterface) // Simulation<->GUI interface functions: scriptInterface.RegisterFunction("IsNewSimulation"); - scriptInterface.RegisterFunction("GuiInterfaceCall"); - + scriptInterface.RegisterFunction("GuiInterfaceCall"); scriptInterface.RegisterFunction("PostNetworkCommand"); // Entity picking diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp index ee85f7d8b5..c495949589 100644 --- a/source/simulation2/components/CCmpTemplateManager.cpp +++ b/source/simulation2/components/CCmpTemplateManager.cpp @@ -81,6 +81,8 @@ public: virtual const CParamNode* LoadTemplate(entity_id_t ent, const std::wstring& templateName, int playerID); + virtual const CParamNode* GetTemplate(std::wstring templateName); + virtual const CParamNode* LoadLatestTemplate(entity_id_t ent); virtual std::wstring GetCurrentTemplateName(entity_id_t ent); @@ -119,6 +121,17 @@ const CParamNode* CCmpTemplateManager::LoadTemplate(entity_id_t ent, const std:: { m_LatestTemplates[ent] = templateName; + const CParamNode* templateRoot = GetTemplate(templateName); + if (!templateRoot) + return NULL; + + // TODO: Eventually we need to support techs in here, and return a different template per playerID + + return templateRoot; +} + +const CParamNode* CCmpTemplateManager::GetTemplate(std::wstring templateName) +{ // Load the template if necessary if (!LoadTemplateFile(templateName, 0)) { @@ -126,8 +139,6 @@ const CParamNode* CCmpTemplateManager::LoadTemplate(entity_id_t ent, const std:: return NULL; } - // TODO: Eventually we need to support techs in here, and return a different template per playerID - const CParamNode* templateRoot = m_TemplateFileData[templateName].GetChild("Entity"); if (!templateRoot) { diff --git a/source/simulation2/components/ICmpGuiInterface.cpp b/source/simulation2/components/ICmpGuiInterface.cpp index d963fa3e13..8c79a30c3b 100644 --- a/source/simulation2/components/ICmpGuiInterface.cpp +++ b/source/simulation2/components/ICmpGuiInterface.cpp @@ -30,7 +30,7 @@ class CCmpGuiInterfaceScripted : public ICmpGuiInterface public: DEFAULT_SCRIPT_WRAPPER(GuiInterfaceScripted) - virtual CScriptVal ScriptCall(int player, std::string cmd, CScriptVal data) + virtual CScriptVal ScriptCall(int player, std::wstring cmd, CScriptVal data) { return m_Script.Call ("ScriptCall", player, cmd, data); } diff --git a/source/simulation2/components/ICmpGuiInterface.h b/source/simulation2/components/ICmpGuiInterface.h index 0025dfe8b4..edb245d922 100644 --- a/source/simulation2/components/ICmpGuiInterface.h +++ b/source/simulation2/components/ICmpGuiInterface.h @@ -28,7 +28,7 @@ public: /** * Generic call function, for use by GUI scripts to talk to the GuiInterface script. */ - virtual CScriptVal ScriptCall(int player, std::string cmd, CScriptVal data) = 0; + virtual CScriptVal ScriptCall(int player, std::wstring cmd, CScriptVal data) = 0; // TODO: some of the earlier functions should just use ScriptCall. DECLARE_INTERFACE_TYPE(GuiInterface) diff --git a/source/simulation2/components/ICmpTemplateManager.cpp b/source/simulation2/components/ICmpTemplateManager.cpp index d90753e8a9..9b276fc9b6 100644 --- a/source/simulation2/components/ICmpTemplateManager.cpp +++ b/source/simulation2/components/ICmpTemplateManager.cpp @@ -22,4 +22,6 @@ #include "simulation2/system/InterfaceScripted.h" BEGIN_INTERFACE_WRAPPER(TemplateManager) +DEFINE_INTERFACE_METHOD_1("GetTemplate", const CParamNode*, ICmpTemplateManager, GetTemplate, std::wstring) +DEFINE_INTERFACE_METHOD_1("GetCurrentTemplateName", std::wstring, ICmpTemplateManager, GetCurrentTemplateName, entity_id_t) END_INTERFACE_WRAPPER(TemplateManager) diff --git a/source/simulation2/components/ICmpTemplateManager.h b/source/simulation2/components/ICmpTemplateManager.h index e0d539933a..6eb7f3f227 100644 --- a/source/simulation2/components/ICmpTemplateManager.h +++ b/source/simulation2/components/ICmpTemplateManager.h @@ -47,6 +47,12 @@ public: */ virtual const CParamNode* LoadTemplate(entity_id_t ent, const std::wstring& templateName, int playerID) = 0; + /** + * Loads the template XML file identified by 'templateName' (including inheritance + * from parent XML files). The templateName syntax is the same as LoadTemplate. + */ + virtual const CParamNode* GetTemplate(std::wstring templateName) = 0; + /** * Returns the template most recently specified for the entity 'ent'. * Used during deserialization. diff --git a/source/simulation2/scripting/EngineScriptConversions.cpp b/source/simulation2/scripting/EngineScriptConversions.cpp index 8d3f4aac26..3d15efec95 100644 --- a/source/simulation2/scripting/EngineScriptConversions.cpp +++ b/source/simulation2/scripting/EngineScriptConversions.cpp @@ -115,6 +115,14 @@ template<> jsval ScriptInterface::ToJSVal(JSContext* cx, CParamNode return OBJECT_TO_JSVAL(obj); } +template<> jsval ScriptInterface::ToJSVal(JSContext* cx, const CParamNode* const& val) +{ + if (val) + return ToJSVal(cx, *val); + else + return JSVAL_VOID; +} + template<> bool ScriptInterface::FromJSVal(JSContext* cx, jsval v, CColor& out) { ScriptInterface::LocalRootScope scope(cx);