Fix #549 (Allow units to be moved by right-clicking on the mini-map), based on patch from Badmadblacksad

This was SVN commit r8107.
This commit is contained in:
Ykkrosh
2010-09-11 19:49:21 +00:00
parent 19ba2927d8
commit 1cc4d358d7
5 changed files with 96 additions and 21 deletions
@@ -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)
{
@@ -310,7 +310,9 @@
<object name="minimapDisplay"
type="minimap"
size="6 100%-182 182 100%-6"
/>
>
<action on="WorldClick">handleMinimapEvent(arguments[0]);</action>
</object>
</object>
<!-- Player resource bar -->
+22 -1
View File
@@ -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<CStr, JSObject**>::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
+12 -1
View File
@@ -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);
//@}
+12 -12
View File
@@ -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);