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

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

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>

View File

@ -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>

Binary file not shown.

Binary file not shown.

View File

@ -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>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1 @@
1 1

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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

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)

View File

@ -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);
}
}
};

View File

@ -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));
}
}

View File

@ -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>

View File

@ -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");

View File

@ -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();

View File

@ -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] &&

View File

@ -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);
};

View File

@ -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)

View File

@ -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>

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);

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;
}

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;

View File

@ -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);