diff --git a/binaries/data/mods/public/gui/session_new/input.js b/binaries/data/mods/public/gui/session_new/input.js index 393d9c26c9..34123f2225 100644 --- a/binaries/data/mods/public/gui/session_new/input.js +++ b/binaries/data/mods/public/gui/session_new/input.js @@ -65,7 +65,7 @@ function findGatherType(gatherer, supply) /** * Determine the context-sensitive action that should be performed when the mouse is at (x,y) */ -function determineAction(x, y) +function determineAction(x, y, fromMinimap) { var selection = g_Selection.toList(); @@ -89,7 +89,9 @@ function determineAction(x, y) return entState && entState.rallyPoint; }); - var targets = Engine.PickEntitiesAtPoint(x, y); + var targets = []; + if (!fromMinimap) + targets = Engine.PickEntitiesAtPoint(x, y); // If there's a target unit if (targets.length) @@ -119,13 +121,13 @@ function determineAction(x, y) // If the target is a resource and we have the right kind of resource gatherers selected, then gather // If the target is a foundation and we have builders selected, then build (or repair) // If the target is an enemy, then attack - if (targetState.resourceSupply && (playerOwned || gaiaOwned)) - { + if (targetState.resourceSupply && (playerOwned || gaiaOwned)) + { var resource = findGatherType(entState.resourceGatherRates, targetState.resourceSupply); if (resource) return {"type": "gather", "cursor": "action-gather-"+resource, "target": targets[0]}; } - else if (targetState.foundation && entState.buildEntities && playerOwned) + else if (targetState.foundation && entState.buildEntities && playerOwned) { return {"type": "build", "cursor": "action-build", "target": targets[0]}; } @@ -528,7 +530,7 @@ function handleInputAfterGui(ev) return true; default: - throw new Error("Invalid action.type "+action.type); + error("Invalid action.type "+action.type); } } break; @@ -608,6 +610,45 @@ function handleInputAfterGui(ev) return false; } +function handleMinimapEvent(target) +{ + // Partly duplicated from handleInputAfterGui(), but with the input being + // world coordinates instead of screen coordinates. + + if (inputState == INPUT_NORMAL) + { + var fromMinimap = true; + var action = determineAction(undefined, undefined, fromMinimap); + if (!action) + return false; + + var selection = g_Selection.toList(); + + var queued = (specialKeyStates[SDLK_RSHIFT] || specialKeyStates[SDLK_LSHIFT]); + + switch (action.type) + { + case "move": + Engine.PostNetworkCommand({"type": "walk", "entities": selection, "x": target.x, "z": target.z, "queued": queued}); + return true; + + case "set-rallypoint": + Engine.PostNetworkCommand({"type": "set-rallypoint", "entities": selection, "x": target.x, "z": target.z}); + // Display rally point at the new coordinates, to avoid display lag + Engine.GuiInterfaceCall("DisplayRallyPoint", { + "entities": selection, + "x": target.x, + "z": target.z + }); + return true; + + default: + error("Invalid action.type "+action.type); + } + } + return false; +} + // Called by GUI when user clicks construction button function startBuildingPlacement(buildEntType) { diff --git a/binaries/data/mods/public/gui/session_new/session.xml b/binaries/data/mods/public/gui/session_new/session.xml index c76b0c6751..2c723b9c2d 100644 --- a/binaries/data/mods/public/gui/session_new/session.xml +++ b/binaries/data/mods/public/gui/session_new/session.xml @@ -310,7 +310,9 @@ + > + handleMinimapEvent(arguments[0]); + diff --git a/source/gui/IGUIObject.cpp b/source/gui/IGUIObject.cpp index 248c683285..8ba2809f24 100644 --- a/source/gui/IGUIObject.cpp +++ b/source/gui/IGUIObject.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -26,6 +26,7 @@ IGUIObject #include "gui/scripting/JSInterface_IGUIObject.h" #include "gui/scripting/JSInterface_GUITypes.h" +#include "scriptinterface/ScriptVal.h" #include "ps/CLogger.h" #define LOG_CATEGORY L"gui" @@ -509,6 +510,8 @@ void IGUIObject::ScriptEvent(const CStr& Action) JSObject* jsGuiObject = JS_ConstructObjectWithArguments(g_ScriptingHost.getContext(), &JSI_IGUIObject::JSI_class, m_pGUI->m_ScriptObject, NULL, 1, &guiObject); debug_assert(jsGuiObject); // TODO: Handle errors + // TODO: why don't we use GetJSObject here? + // Prevent it from being garbage-collected before it's passed into the function JS_AddRoot(g_ScriptingHost.getContext(), &jsGuiObject); @@ -537,6 +540,24 @@ void IGUIObject::ScriptEvent(const CStr& Action) JS_RemoveRoot(g_ScriptingHost.getContext(), &jsGuiObject); } +void IGUIObject::ScriptEvent(const CStr& Action, const CScriptValRooted& Argument) +{ + std::map::iterator it = m_ScriptHandlers.find(Action); + if (it == m_ScriptHandlers.end()) + return; + + JSObject* object = GetJSObject(); + + jsval arg = Argument.get(); + + jsval result; + JSBool ok = JS_CallFunctionValue(g_ScriptingHost.getContext(), object, OBJECT_TO_JSVAL(*it->second), 1, &arg, &result); + if (!ok) + { + JS_ReportError(g_ScriptingHost.getContext(), "Errors executing script action \"%s\"", Action.c_str()); + } +} + JSObject* IGUIObject::GetJSObject() { // Cache the object when somebody first asks for it, because otherwise diff --git a/source/gui/IGUIObject.h b/source/gui/IGUIObject.h index a656145234..1ffdf2249a 100644 --- a/source/gui/IGUIObject.h +++ b/source/gui/IGUIObject.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2009 Wildfire Games. +/* Copyright (C) 2010 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -59,6 +59,7 @@ The base class of an object struct SGUISetting; struct SGUIStyle; class CGUI; +class CScriptValRooted; //-------------------------------------------------------- // Macros @@ -437,11 +438,21 @@ protected: /** * Execute the script for a particular action. * Does nothing if no script has been registered for that action. + * The mouse coordinates will be passed as the first argument. * * @param Action Name of action */ void ScriptEvent(const CStr& Action); + /** + * Execute the script for a particular action. + * Does nothing if no script has been registered for that action. + * + * @param Action Name of action + * @param Argument Argument to pass to action + */ + void ScriptEvent(const CStr& Action, const CScriptValRooted& Argument); + void SetScriptHandler(const CStr& Action, JSObject* Function); //@} diff --git a/source/gui/MiniMap.cpp b/source/gui/MiniMap.cpp index a866a67bec..266a4d8080 100644 --- a/source/gui/MiniMap.cpp +++ b/source/gui/MiniMap.cpp @@ -36,6 +36,7 @@ #include "ps/World.h" #include "renderer/Renderer.h" #include "renderer/WaterManager.h" +#include "scriptinterface/ScriptInterface.h" #include "simulation2/Simulation2.h" #include "simulation2/components/ICmpMinimap.h" @@ -135,19 +136,18 @@ void CMiniMap::SetCameraPos() void CMiniMap::FireWorldClickEvent(int button, int clicks) { - // TODO: we ought to pass this through to the GUI system - - //debug_printf(L"FireWorldClickEvent: button %d, clicks %d\n", button, clicks); - -/* + // Determine X and Z according to proportion of mouse position and minimap CPos MousePos = GetMousePos(); - CVector2D Destination; - //X and Z according to proportion of mouse position and minimap - Destination.x = CELL_SIZE * m_MapSize * - ( (MousePos.x - m_CachedActualSize.left) / m_CachedActualSize.GetWidth() ); - Destination.y = CELL_SIZE * m_MapSize * ( (m_CachedActualSize.bottom - MousePos.y) / - m_CachedActualSize.GetHeight() ); -*/ + float x = CELL_SIZE * m_MapSize * + ((MousePos.x - m_CachedActualSize.left) / m_CachedActualSize.GetWidth()); + float z = CELL_SIZE * m_MapSize * + ((m_CachedActualSize.bottom - MousePos.y) / m_CachedActualSize.GetHeight()); + + CScriptValRooted coords; + g_ScriptingHost.GetScriptInterface().Eval("({})", coords); + g_ScriptingHost.GetScriptInterface().SetProperty(coords.get(), "x", x, false); + g_ScriptingHost.GetScriptInterface().SetProperty(coords.get(), "z", z, false); + ScriptEvent("worldclick", coords); UNUSED2(button); UNUSED2(clicks);