1
0
forked from mirrors/0ad

Map flares

Add flaring on the map and resize the minimap buttons.
Target marker and button by Stan.
Reviewed/Commented by wraitii, elexis, vladislavbelov
Refs: #3491
Refs: #57

Differential Revision: https://code.wildfiregames.com/D1751
This was SVN commit r25691.
This commit is contained in:
Imarok
2021-06-05 17:37:18 +00:00
parent 3bb5f364c2
commit 8e63a0322c
43 changed files with 494 additions and 13 deletions
+2
View File
@@ -341,6 +341,8 @@ rotate.cw = RightBracket ; Rotate building placement preview clockwise
rotate.ccw = LeftBracket ; Rotate building placement preview anticlockwise
snaptoedges = Ctrl ; Modifier to align new structures with nearby existing structure
toggledefaultformation = "" ; Switch between null default formation and the last default formation used (defaults to "box")
flare = K ; Modifier to send a flare to your allies
flareactivate = "" ; Modifier to activate the mode to send a flare to your allies
; Overlays
showstatusbars = Tab ; Toggle display of status bars
devcommands.toggle = "Alt+D" ; Toggle developer commands panel
+25
View File
@@ -230,6 +230,31 @@
<ref name="bool"/>
</attribute>
</optional>
<optional>
<attribute name="flare_texture_count">
<data type="nonNegativeInteger"/>
</attribute>
</optional>
<optional>
<attribute name="flare_render_size">
<data type="nonNegativeInteger"/>
</attribute>
</optional>
<optional>
<attribute name="flare_animation_speed">
<data type="nonNegativeInteger"/>
</attribute>
</optional>
<optional>
<attribute name="flare_interleave">
<ref name="bool"/>
</attribute>
</optional>
<optional>
<attribute name="flare_lifetime_seconds">
<data type="nonNegativeInteger"/>
</attribute>
</optional>
<optional>
<attribute name="font"/>
</optional>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<actor version="1">
<castshadow/>
<float/>
<group>
<variant frequency="100" name="Flare Target Marker">
<animations>
<animation file="other/flare_target_marker_idle.dae" name="Idle" speed="100"/>
</animations>
<mesh>skeletal/flare_target_marker.dae</mesh>
<textures>
<texture file="skeletal/flare_target_marker_diffuse.png" name="baseTex"/>
<texture file="skeletal/flare_target_marker_spec.png" name="specTex"/>
</textures>
</variant>
</group>
<material>player_trans_spec.xml</material>
</actor>
@@ -0,0 +1,27 @@
<?xml version='1.0' encoding='utf-8'?>
<skeletons>
<standard_skeleton title="flare-marker-armature" id="flare-marker-armature">
<bone name="base">
<bone name="ping-marker-ball" />
<bone name="ping-marker-body" />
</bone>
<bone name="target marker" />
</standard_skeleton>
<skeleton title="flare-marker-armature" target="flare-marker-armature">
<identifier>
<root>base</root>
</identifier>
<bone name="base">
<target>base</target>
<bone name="ping-marker-ball">
<target>ping-marker-ball</target>
</bone>
<bone name="ping-marker-body">
<target>ping-marker-body</target>
</bone>
</bone>
<bone name="target marker">
<target>target marker</target>
</bone>
</skeleton>
</skeletons>
@@ -0,0 +1 @@
1 1
@@ -115,6 +115,7 @@ You may change hotkeys in [font="sans-bold-14"]Options > Hotkeys[font="sans-14"]
hotkey.session.attackmove + Right Click with unit(s) selected Attack move (by default all enemy units and structures along the way are targeted)
hotkey.session.attackmoveUnit + Right Click with unit(s) selected Attack move, only units along the way are targeted
hotkey.session.snaptoedges + Mouse Move near structures Align the new structure with an existing nearby structure
hotkey.session.flare + Right Click Send a flare to your allies
[font="sans-bold-14"]Overlays[font="sans-14"]
hotkey.session.gui.toggle Toggle the GUI
+52 -1
View File
@@ -32,6 +32,7 @@ const INPUT_BUILDING_WALL_CLICK = 8;
const INPUT_BUILDING_WALL_PATHING = 9;
const INPUT_UNIT_POSITION_START = 10;
const INPUT_UNIT_POSITION = 11;
const INPUT_FLARE = 12;
var inputState = INPUT_NORMAL;
@@ -79,6 +80,16 @@ var g_DragStart;
*/
var clickedEntity = INVALID_ENTITY;
/**
* Store the last time the flare functionality was used to prevent overusage.
*/
var g_LastFlareTime;
/**
* The duration in ms for which we disable flaring after each flare to prevent overusage.
*/
const g_FlareCooldown = 5000;
// Same double-click behaviour for hotkey presses.
const doublePressTime = 500;
var doublePressTimer = 0;
@@ -89,7 +100,12 @@ function updateCursorAndTooltip()
let cursorSet = false;
let tooltipSet = false;
let informationTooltip = Engine.GetGUIObjectByName("informationTooltip");
if (!mouseIsOverObject && (inputState == INPUT_NORMAL || inputState == INPUT_PRESELECTEDACTION) || g_MiniMapPanel.isMouseOverMiniMap())
if (inputState == INPUT_FLARE || inputState == INPUT_NORMAL && Engine.HotkeyIsPressed("session.flare") && !g_IsObserver)
{
Engine.SetCursor("action-flare");
cursorSet = true;
}
else if (!mouseIsOverObject && (inputState == INPUT_NORMAL || inputState == INPUT_PRESELECTEDACTION) || g_MiniMapPanel.isMouseOverMiniMap())
{
let action = determineAction(mouseX, mouseY, g_MiniMapPanel.isMouseOverMiniMap());
if (action)
@@ -810,6 +826,11 @@ function handleInputAfterGui(ev)
return false;
case "mousebuttondown":
if (Engine.HotkeyIsPressed("session.flare") && controlsPlayer(g_ViewedPlayer))
{
triggerFlareAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y));
return true;
}
if (ev.button == SDL_BUTTON_LEFT)
{
g_DragStart = new Vector2D(ev.x, ev.y);
@@ -1111,6 +1132,21 @@ function handleInputAfterGui(ev)
}
break;
case INPUT_FLARE:
if (ev.type == "mousebuttondown")
{
if (ev.button == SDL_BUTTON_LEFT && controlsPlayer(g_ViewedPlayer))
{
triggerFlareAction(Engine.GetTerrainAtScreenPoint(ev.x, ev.y));
inputState = INPUT_NORMAL;
return true;
}
else if (ev.button == SDL_BUTTON_RIGHT)
{
inputState = INPUT_NORMAL;
return true;
}
}
}
return false;
}
@@ -1224,6 +1260,21 @@ function positionUnitsFreehandSelectionMouseUp(ev)
return true;
}
function triggerFlareAction(target)
{
let now = Date.now();
if (g_LastFlareTime && now < g_LastFlareTime + g_FlareCooldown)
return;
g_LastFlareTime = now;
displayFlare(target, Engine.GetPlayerID());
Engine.PlayUISound(g_FlareSound, false);
Engine.PostNetworkCommand({
"type": "map-flare",
"target": target
});
}
function handleUnitAction(target, action)
{
if (!g_UnitActions[action.type] || !g_UnitActions[action.type].execute)
@@ -8,6 +8,22 @@ var g_TutorialMessages = [];
*/
var g_TutorialNewMessageTags = { "color": "255 226 149" };
/**
* The number of seconds we observe for rate limiting flares.
*/
var g_FlareRateLimitScope = 10;
/**
* The maximum allowed number of flares within g_FlareRateLimitScope seconds.
* This should be a bit larger than the number of flares that can be sent in theory by using the GUI.
*/
var g_FlareRateLimitMaximumFlares = 16;
/**
* Contains the arrival timestamps the flares of the last g_FlareRateLimitScope seconds.
*/
var g_FlareRateLimitLastTimes = [];
/**
* These handlers are called everytime a client joins or disconnects.
*/
@@ -267,6 +283,27 @@ var g_NotificationsTypes =
}
global.music.setLocked(notification.lock);
},
"map-flare": function(notification, player)
{
// Don't display for the player that did the flare because they will see it immediately
if (player != Engine.GetPlayerID() && g_Players[player].isMutualAlly[Engine.GetPlayerID()])
{
let now = Date.now();
if (g_FlareRateLimitLastTimes.length)
{
g_FlareRateLimitLastTimes = g_FlareRateLimitLastTimes.filter(t => now - t < g_FlareRateLimitScope * 1000);
if (g_FlareRateLimitLastTimes.length >= g_FlareRateLimitMaximumFlares)
{
warn("Received too many flares. Dropping a flare request by '" + g_Players[player].name + "'.");
return;
}
}
g_FlareRateLimitLastTimes.push(now);
displayFlare(notification.target, player);
Engine.PlayUISound(g_FlareSound, false);
}
}
};
@@ -6,9 +6,10 @@ class MiniMap
{
constructor()
{
Engine.GetGUIObjectByName("minimap").onWorldClick = this.onWorldClick.bind(this);
Engine.GetGUIObjectByName("minimap").onMouseEnter = this.onMouseEnter.bind(this);
Engine.GetGUIObjectByName("minimap").onMouseLeave = this.onMouseLeave.bind(this);
this.miniMap = Engine.GetGUIObjectByName("minimap");
this.miniMap.onWorldClick = this.onWorldClick.bind(this);
this.miniMap.onMouseEnter = this.onMouseEnter.bind(this);
this.miniMap.onMouseLeave = this.onMouseLeave.bind(this);
this.mouseIsOverMiniMap = false;
}
@@ -16,9 +17,15 @@ class MiniMap
{
// Partly duplicated from handleInputAfterGui(), but with the input being
// world coordinates instead of screen coordinates.
if (inputState == INPUT_NORMAL && controlsPlayer(g_ViewedPlayer) && Engine.HotkeyIsPressed("session.flare"))
{
triggerFlareAction(target);
return true;
}
if (button == SDL_BUTTON_LEFT)
{
if (inputState != INPUT_PRESELECTEDACTION || preSelectedAction == ACTION_NONE)
if (inputState != INPUT_FLARE && (inputState != INPUT_PRESELECTEDACTION || preSelectedAction == ACTION_NONE))
return false;
}
else if (button == SDL_BUTTON_RIGHT)
@@ -29,6 +36,11 @@ class MiniMap
inputState = INPUT_NORMAL;
return true;
}
else if (inputState == INPUT_FLARE)
{
inputState = INPUT_NORMAL;
return true;
}
else if (inputState != INPUT_NORMAL)
return false;
}
@@ -39,6 +51,13 @@ class MiniMap
if (!controlsPlayer(g_ViewedPlayer))
return false;
if (inputState == INPUT_FLARE && button == SDL_BUTTON_LEFT)
{
triggerFlareAction(target);
inputState = INPUT_NORMAL;
return true;
}
let action = determineAction(undefined, undefined, true);
if (!action)
return false;
@@ -64,4 +83,9 @@ class MiniMap
{
return this.mouseIsOverMiniMap;
}
flare(target, playerID)
{
return this.miniMap.flare({ "x": target.x, "y": target.z }, g_DiplomacyColors.getPlayerColor(playerID));
}
}
@@ -16,7 +16,7 @@
<!-- Idle Worker Button -->
<object name="idleWorkerButton"
type="button"
size="50%-5 50%-5 100%-5 100%-5"
size="100%-119 100%-120 100%-4 100%-5"
tooltip_style="sessionToolTip"
hotkey="selection.idleworker"
sprite="stretched:session/minimap-idle.png"
@@ -28,11 +28,33 @@
<!-- Diplomacy Colors Button -->
<object name="diplomacyColorsButton"
type="button"
size="5 50%-5 50%+5 100%-5"
size="4 100%-120 119 100%-5"
tooltip_style="sessionToolTip"
hotkey="session.diplomacycolors"
/>
<!-- Flare Button -->
<object
name="flareButton"
type="button"
size="3 3 118 118"
tooltip_style="sessionToolTip"
hotkey="session.flareactivate"
sprite="stretched:session/minimap-flare.png"
sprite_over="stretched:session/minimap-flare-highlight.png"
mouse_event_mask="texture:session/minimap-flare.png"
/>
<!-- MiniMap -->
<object name="minimap" size="8 8 100%-8 100%-8" type="minimap" mask="true"/>
<object
name="minimap"
size="8 8 100%-8 100%-8"
type="minimap"
mask="true"
flare_texture_count="16"
flare_render_size="32"
flare_animation_speed="7"
flare_interleave="true"
flare_lifetime_seconds="6"
/>
</object>
@@ -0,0 +1,29 @@
/**
* If the button that this class manages is pressed, an idle unit having one of the given classes is selected.
*/
class MiniMapFlareButton
{
constructor()
{
this.flareButton = Engine.GetGUIObjectByName("flareButton");
this.flareButton.onPress = this.onPress.bind(this);
registerHotkeyChangeHandler(this.onHotkeyChange.bind(this));
}
onHotkeyChange()
{
this.flareButton.tooltip =
colorizeHotkey("%(hotkey)s" + " ", "session.flare") +
translate(this.Tooltip);
}
onPress()
{
if (g_IsObserver)
return;
if (inputState == INPUT_NORMAL)
inputState = INPUT_FLARE;
}
}
MiniMapFlareButton.prototype.Tooltip = markForTranslation("Send a flare to your allies");
@@ -7,9 +7,15 @@ class MiniMapPanel
{
this.diplomacyColorsButton = new MiniMapDiplomacyColorsButton(diplomacyColors);
this.idleWorkerButton = new MiniMapIdleWorkerButton(playerViewControl, idleWorkerClasses);
this.flareButton = new MiniMapFlareButton();
this.miniMap = new MiniMap();
}
flare(target, playerID)
{
return this.miniMap.flare(target, playerID);
}
isMouseOverMiniMap()
{
return this.miniMap.isMouseOverMiniMap();
@@ -3,9 +3,15 @@
* given a command type.
*/
var g_TargetMarker = {
"move": "special/target_marker"
"move": "special/target_marker",
"map_flare": "special/flare_target_marker"
};
/**
* Sound we play when displaying a flare.
*/
var g_FlareSound = "audio/interface/alarm/alarmally_1.ogg";
/**
* Which enemy entity types will be attacked on sight when patroling.
*/
@@ -1828,6 +1834,17 @@ function DrawTargetMarker(target)
});
}
function displayFlare(target, playerID)
{
Engine.GuiInterfaceCall("AddTargetMarker", {
"template": g_TargetMarker.map_flare,
"x": target.x,
"z": target.z,
"owner": playerID
});
g_MiniMapPanel.flare(target, playerID);
}
function getCommandInfo(command, entStates)
{
return entStates && g_EntityCommands[command] &&
@@ -1116,7 +1116,9 @@ GuiInterface.prototype.AddTargetMarker = function(player, cmd)
let ent = Engine.AddLocalEntity(cmd.template);
if (!ent)
return;
let cmpOwnership = Engine.QueryInterface(ent, IID_Ownership);
if (cmpOwnership)
cmpOwnership.SetOwner(cmd.owner);
let cmpPosition = Engine.QueryInterface(ent, IID_Position);
cmpPosition.JumpTo(cmd.x, cmd.z);
};
@@ -878,6 +878,16 @@ var g_Commands = {
}
},
"map-flare": function(player, cmd, data)
{
let cmpGuiInterface = Engine.QueryInterface(SYSTEM_ENTITY, IID_GuiInterface);
cmpGuiInterface.PushNotification({
"type": "map-flare",
"players": [player],
"target": cmd.target
});
},
"autoqueue-on": function(player, cmd, data)
{
for (let ent of data.entities)
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<Entity parent="special/actor">
<Decay>
<Active>true</Active>
<SinkingAnim>false</SinkingAnim>
<DelayTime>6</DelayTime>
<SinkRate>10000</SinkRate>
<SinkAccel>0</SinkAccel>
</Decay>
<Ownership/>
<Position>
<Floating>true</Floating>
</Position>
<VisualActor>
<Actor>special/flare_target_marker.xml</Actor>
</VisualActor>
</Entity>
+1
View File
@@ -40,6 +40,7 @@ void CGUI::AddObjectTypes()
m_ProxyData.insert(JSI_GUIProxy<IGUIObject>::CreateData(*m_ScriptInterface));
m_ProxyData.insert(JSI_GUIProxy<CText>::CreateData(*m_ScriptInterface));
m_ProxyData.insert(JSI_GUIProxy<CList>::CreateData(*m_ScriptInterface));
m_ProxyData.insert(JSI_GUIProxy<CMiniMap>::CreateData(*m_ScriptInterface));
m_ProxyData.insert(JSI_GUIProxy<CButton>::CreateData(*m_ScriptInterface));
AddObjectType("button", &CButton::ConstructObject);
+85 -3
View File
@@ -37,6 +37,7 @@
#include "lib/external_libraries/libsdl.h"
#include "lib/ogl.h"
#include "lib/timer.h"
#include "ps/CLogger.h"
#include "ps/ConfigDB.h"
#include "ps/CStrInternStatic.h"
#include "ps/Filesystem.h"
@@ -141,7 +142,10 @@ CMiniMap::CMiniMap(CGUI& pGUI) :
IGUIObject(pGUI),
m_MapSize(0), m_MapScale(1.f),
m_EntitiesDrawn(0), m_IndexArray(GL_STATIC_DRAW), m_VertexArray(GL_DYNAMIC_DRAW), m_Mask(this, "mask", false),
m_NextBlinkTime(0.0), m_PingDuration(25.0), m_BlinkState(false)
m_NextBlinkTime(0.0), m_PingDuration(25.0), m_BlinkState(false),
m_FlareTextureCount(this, "flare_texture_count", 0), m_FlareRenderSize(this, "flare_render_size", 0),
m_FlareAnimationSpeed(this, "flare_animation_speed", 0), m_FlareInterleave(this, "flare_interleave", false),
m_FlareLifetimeSeconds(this, "flare_lifetime_seconds", 0)
{
m_Clicking = false;
m_MouseHovering = false;
@@ -201,6 +205,13 @@ void CMiniMap::HandleMessage(SGUIMessage& Message)
IGUIObject::HandleMessage(Message);
switch (Message.type)
{
case GUIM_LOAD:
RecreateFlareTextures();
break;
case GUIM_SETTINGS_UPDATED:
if (Message.value == "flare_texture_count")
RecreateFlareTextures();
break;
case GUIM_MOUSE_PRESS_LEFT:
if (m_MouseHovering)
{
@@ -248,6 +259,24 @@ void CMiniMap::HandleMessage(SGUIMessage& Message)
}
}
void CMiniMap::RecreateFlareTextures()
{
// Catch invalid values.
if (m_FlareTextureCount > 99)
{
LOGERROR("Invalid value for flare texture count. Valid range is 0-99.");
return;
}
const CStr numberingFormat = "%02u";
m_FlareTextures.clear();
m_FlareTextures.reserve(m_FlareTextureCount);
for (u32 i = 0; i < m_FlareTextureCount; ++i)
{
CTextureProperties textureProps(L"art/textures/animated/minimap-flare/frame" + CStr(fmt::sprintf(numberingFormat, i)).FromUTF8() + L".png");
m_FlareTextures.emplace_back(g_Renderer.GetTextureManager().CreateTexture(textureProps));
}
}
bool CMiniMap::IsMouseOver() const
{
// Get the mouse position.
@@ -369,6 +398,41 @@ void CMiniMap::DrawViewRect(const CMatrix3D& transform) const
glLineWidth(1.0f);
}
void CMiniMap::DrawFlare(CCanvas2D& canvas, const MapFlare& flare, double currentTime) const
{
if (!m_FlareTextures.size())
return;
// Coordinates with 0,0 in the middle of the minimap and +-0.5 as max.
const float invTileMapSize = 1.0f / static_cast<float>(TERRAIN_TILE_SIZE * m_MapSize);
const float relativeX = (flare.pos.X * invTileMapSize - 0.5) / m_MapScale;
const float relativeY = (flare.pos.Y * invTileMapSize - 0.5) / m_MapScale;
// Rotate coordinates.
const float angle = GetAngle();
const float rotatedX = cos(angle) * relativeX + sin(angle) * relativeY;
const float rotatedY = -sin(angle) * relativeX + cos(angle) * relativeY;
// Calculate coordinates in gui space.
const float cx = m_CachedActualSize.left + (0.5f + rotatedX) * m_CachedActualSize.GetWidth();
const float cy = m_CachedActualSize.bottom - (0.5f + rotatedY) * m_CachedActualSize.GetHeight();
const CRect destination(cx-m_FlareRenderSize, cy-m_FlareRenderSize, cx+m_FlareRenderSize, cy+m_FlareRenderSize);
const u32 flooredStep = floor((currentTime - flare.time) * m_FlareAnimationSpeed);
CTexturePtr texture = m_FlareTextures[flooredStep % m_FlareTextures.size()];
// TODO: Only draw inside the minimap circle.
canvas.DrawTexture(texture, destination, CRect(0, 0, texture->GetWidth(), texture->GetHeight()), flare.color, CColor(0.0f, 0.0f, 0.0f, 0.0f), 0.0f);
// Draw a second circle if the first has reached half of the animation
if (m_FlareInterleave && flooredStep >= m_FlareTextures.size() / 2)
{
texture = m_FlareTextures[(flooredStep - m_FlareTextures.size() / 2) % m_FlareTextures.size()];
// TODO: Only draw inside the minimap circle.
canvas.DrawTexture(texture, destination, CRect(0, 0, texture->GetWidth(), texture->GetHeight()), flare.color, CColor(0.0f, 0.0f, 0.0f, 0.0f), 0.0f);
}
}
struct MinimapUnitVertex
{
// This struct is copyable for convenience and because to move is to copy for primitives.
@@ -521,7 +585,7 @@ void CMiniMap::Draw(CCanvas2D& canvas)
glDisable(GL_BLEND);
PROFILE_START("minimap units");
PROFILE_START("minimap units and flares");
CShaderDefines pointDefines;
pointDefines.Add(str_MINIMAP_POINT, str_1);
@@ -641,5 +705,23 @@ void CMiniMap::Draw(CCanvas2D& canvas)
DrawViewRect(unitMatrix);
PROFILE_END("minimap units");
while (!m_MapFlares.empty() && m_FlareLifetimeSeconds + m_MapFlares.front().time < cur_time)
m_MapFlares.pop_front();
for (const MapFlare& flare : m_MapFlares)
DrawFlare(canvas, flare, cur_time);
PROFILE_END("minimap units and flares");
}
bool CMiniMap::Flare(const CVector2D& pos, const CStr& colorStr)
{
CColor color;
if (!color.ParseString(colorStr))
{
LOGERROR("CMiniMap::Flare: Couldn't parse color string");
return false;
}
m_MapFlares.push_back({ pos, color, timer_Time() });
return true;
}
+32
View File
@@ -18,9 +18,15 @@
#ifndef INCLUDED_MINIMAP
#define INCLUDED_MINIMAP
#include "graphics/Color.h"
#include "graphics/Texture.h"
#include "gui/ObjectBases/IGUIObject.h"
#include "maths/Vector2D.h"
#include "renderer/VertexArray.h"
#include <deque>
#include <vector>
class CCamera;
class CMatrix3D;
class CTerrain;
@@ -28,13 +34,25 @@ class CTerrain;
class CMiniMap : public IGUIObject
{
GUI_OBJECT(CMiniMap)
public:
CMiniMap(CGUI& pGUI);
virtual ~CMiniMap();
bool Flare(const CVector2D& pos, const CStr& colorStr);
protected:
struct MapFlare
{
CVector2D pos;
CColor color;
double time;
};
virtual void Draw(CCanvas2D& canvas);
virtual void CreateJSObject();
/**
* @see IGUIObject#HandleMessage()
*/
@@ -57,6 +75,16 @@ private:
// Whether or not the mouse is currently down
bool m_Clicking;
std::deque<MapFlare> m_MapFlares;
std::vector<CTexturePtr> m_FlareTextures;
CGUISimpleSetting<u32> m_FlareTextureCount;
CGUISimpleSetting<u32> m_FlareRenderSize;
CGUISimpleSetting<u32> m_FlareAnimationSpeed;
CGUISimpleSetting<bool> m_FlareInterleave;
CGUISimpleSetting<u32> m_FlareLifetimeSeconds;
// Whether to draw a black square around and under the minimap.
CGUISimpleSetting<bool> m_Mask;
@@ -66,8 +94,12 @@ private:
// 1.f if map is circular or 1.414f if square (to shrink it inside the circle)
float m_MapScale;
void RecreateFlareTextures();
void DrawViewRect(const CMatrix3D& transform) const;
void DrawFlare(CCanvas2D& canvas, const MapFlare& flare, double curentTime) const;
void GetMouseWorldCoordinates(float& x, float& z) const;
float GetAngle() const;
@@ -22,6 +22,7 @@
#include "gui/ObjectBases/IGUIObject.h"
#include "gui/ObjectTypes/CButton.h"
#include "gui/ObjectTypes/CList.h"
#include "gui/ObjectTypes/CMiniMap.h"
#include "gui/ObjectTypes/CText.h"
// Called for every specialization - adds the common interface.
@@ -58,3 +59,10 @@ template<> void JSI_GUIProxy<CList>::CreateFunctions(const ScriptRequest& rq, GU
CreateFunction<static_cast<void(CList::*)(const CGUIString&)>(&CList::AddItem)>(rq, cache, "addItem");
}
DECLARE_GUIPROXY(CList);
// CMiniMap
template<> void JSI_GUIProxy<CMiniMap>::CreateFunctions(const ScriptRequest& rq, GUIProxyProps* cache)
{
CreateFunction<&CMiniMap::Flare>(rq, cache, "flare");
}
DECLARE_GUIPROXY(CMiniMap);