diff --git a/binaries/data/mods/public/gui/session/selection.js b/binaries/data/mods/public/gui/session/selection.js
index d9edcbc..58c815b 100644
a
|
b
|
|
1 | 1 | const MAX_SELECTION_SIZE = 200; // Limits selection size |
2 | 2 | |
3 | | function _setHighlight(ents, alpha) |
| 3 | function _setHighlight(ents, alpha, selected) |
4 | 4 | { |
5 | 5 | if (ents.length) |
6 | | Engine.GuiInterfaceCall("SetSelectionHighlight", { "entities":ents, "alpha":alpha }); |
| 6 | Engine.GuiInterfaceCall("SetSelectionHighlight", { "entities":ents, "alpha":alpha, "selected":selected }); |
7 | 7 | } |
8 | 8 | |
9 | 9 | function _setStatusBars(ents, enabled) |
… |
… |
EntitySelection.prototype.update = function()
|
209 | 209 | if (entState.visibility == "hidden") |
210 | 210 | { |
211 | 211 | // Disable any highlighting of the disappeared unit |
212 | | _setHighlight([ent], 0); |
| 212 | _setHighlight([ent], 0, false); |
213 | 213 | _setStatusBars([ent], false); |
214 | 214 | _setMotionOverlay([ent], false); |
215 | 215 | |
… |
… |
EntitySelection.prototype.addList = function(ents)
|
275 | 275 | } |
276 | 276 | } |
277 | 277 | |
278 | | _setHighlight(added, 1); |
| 278 | _setHighlight(added, 1, true); |
279 | 279 | _setStatusBars(added, true); |
280 | 280 | _setMotionOverlay(added, this.motionDebugOverlay); |
281 | 281 | if (added.length) |
… |
… |
EntitySelection.prototype.removeList = function(ents)
|
299 | 299 | } |
300 | 300 | } |
301 | 301 | |
302 | | _setHighlight(removed, 0); |
| 302 | _setHighlight(removed, 0, false); |
303 | 303 | _setStatusBars(removed, false); |
304 | 304 | _setMotionOverlay(removed, false); |
305 | 305 | |
… |
… |
EntitySelection.prototype.removeList = function(ents)
|
308 | 308 | |
309 | 309 | EntitySelection.prototype.reset = function() |
310 | 310 | { |
311 | | _setHighlight(this.toList(), 0); |
| 311 | _setHighlight(this.toList(), 0, false); |
312 | 312 | _setStatusBars(this.toList(), false); |
313 | 313 | _setMotionOverlay(this.toList(), false); |
314 | 314 | this.selected = {}; |
… |
… |
EntitySelection.prototype.setHighlightList = function(ents)
|
344 | 344 | if (!this.highlighted[ent] && !this.selected[ent]) |
345 | 345 | added.push(+ent); |
346 | 346 | |
347 | | _setHighlight(removed, 0); |
| 347 | _setHighlight(removed, 0, false); |
348 | 348 | _setStatusBars(removed, false); |
349 | 349 | |
350 | | _setHighlight(added, 0.5); |
| 350 | _setHighlight(added, 0.5, true); |
351 | 351 | _setStatusBars(added, true); |
352 | 352 | |
353 | 353 | // Store the new highlight list |
diff --git a/binaries/data/mods/public/simulation/components/GuiInterface.js b/binaries/data/mods/public/simulation/components/GuiInterface.js
index 4ce8c71..d65af86 100644
a
|
b
|
GuiInterface.prototype.IsStanceSelected = function(player, data)
|
587 | 587 | return false; |
588 | 588 | }; |
589 | 589 | |
590 | | GuiInterface.prototype.SetSelectionHighlight = function(player, cmd) |
| 590 | GuiInterface.prototype.SetSelectionHighlight = function(player, cmd, selected) |
591 | 591 | { |
592 | 592 | var cmpPlayerMan = Engine.QueryInterface(SYSTEM_ENTITY, IID_PlayerManager); |
593 | 593 | var playerColours = {}; // cache of owner -> colour map |
… |
… |
GuiInterface.prototype.SetSelectionHighlight = function(player, cmd)
|
614 | 614 | playerColours[owner] = colour; |
615 | 615 | } |
616 | 616 | |
617 | | cmpSelectable.SetSelectionHighlight({"r":colour.r, "g":colour.g, "b":colour.b, "a":cmd.alpha}); |
| 617 | cmpSelectable.SetSelectionHighlight({"r":colour.r, "g":colour.g, "b":colour.b, "a":cmd.alpha}, cmd.selected); |
618 | 618 | } |
619 | 619 | }; |
620 | 620 | |
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero.xml
index f7e47eb..4b7b071 100644
a
|
b
|
|
49 | 49 | </Minimap> |
50 | 50 | <Selectable> |
51 | 51 | <Overlay> |
| 52 | <AlwaysVisible/> |
52 | 53 | <Texture> |
53 | 54 | <MainTexture>star/256x256.png</MainTexture> |
54 | 55 | <MainTextureMask>star/256x256_mask.png</MainTextureMask> |
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry.xml
index 3db18aa..b5c1f15 100644
a
|
b
|
|
53 | 53 | </Minimap> |
54 | 54 | <Selectable> |
55 | 55 | <Overlay> |
| 56 | <AlwaysVisible/> |
56 | 57 | <Texture> |
57 | 58 | <MainTexture>star/256x256.png</MainTexture> |
58 | 59 | <MainTextureMask>star/256x256_mask.png</MainTextureMask> |
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_archer.xml
index 05a0a20..8032a51 100644
a
|
b
|
Ranged attack 2x vs. spearmen. Ranged attack 1.5x vs. Swordsmen.</Tooltip>
|
62 | 62 | </Minimap> |
63 | 63 | <Selectable> |
64 | 64 | <Overlay> |
| 65 | <AlwaysVisible/> |
65 | 66 | <Texture> |
66 | 67 | <MainTexture>star/256x256.png</MainTexture> |
67 | 68 | <MainTextureMask>star/256x256_mask.png</MainTextureMask> |
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelinist.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_cavalry_javelinist.xml
index fa52c94..d39f071 100644
a
|
b
|
|
52 | 52 | </Minimap> |
53 | 53 | <Selectable> |
54 | 54 | <Overlay> |
| 55 | <AlwaysVisible/> |
55 | 56 | <Texture> |
56 | 57 | <MainTexture>star/256x256.png</MainTexture> |
57 | 58 | <MainTextureMask>star/256x256_mask.png</MainTextureMask> |
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry.xml
index 2bdeecb..56469ff 100644
a
|
b
|
|
51 | 51 | </Minimap> |
52 | 52 | <Selectable> |
53 | 53 | <Overlay> |
| 54 | <AlwaysVisible/> |
54 | 55 | <Texture> |
55 | 56 | <MainTexture>star/256x256.png</MainTexture> |
56 | 57 | <MainTextureMask>star/256x256_mask.png</MainTextureMask> |
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_archer.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_archer.xml
index 32ab5a9..6dbe0e2 100644
a
|
b
|
Counters Swordsmen and Cavalry Spearmen. Countered by Skirmishers and other Cava
|
54 | 54 | </Minimap> |
55 | 55 | <Selectable> |
56 | 56 | <Overlay> |
| 57 | <AlwaysVisible/> |
57 | 58 | <Texture> |
58 | 59 | <MainTexture>star/256x256.png</MainTexture> |
59 | 60 | <MainTextureMask>star/256x256_mask.png</MainTextureMask> |
diff --git a/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_javelinist.xml b/binaries/data/mods/public/simulation/templates/template_unit_hero_infantry_javelinist.xml
index 6d7ba9b..3b0eb82 100644
a
|
b
|
|
58 | 58 | </Minimap> |
59 | 59 | <Selectable> |
60 | 60 | <Overlay> |
| 61 | <AlwaysVisible/> |
61 | 62 | <Texture> |
62 | 63 | <MainTexture>star/256x256.png</MainTexture> |
63 | 64 | <MainTextureMask>star/256x256_mask.png</MainTextureMask> |
diff --git a/source/simulation2/components/CCmpSelectable.cpp b/source/simulation2/components/CCmpSelectable.cpp
index 6650e35..72d5be0 100644
a
|
b
|
public:
|
84 | 84 | "</element>" |
85 | 85 | "</optional>" |
86 | 86 | "<element name='Overlay' a:help='Specifies the type of overlay to be displayed when this entity is selected'>" |
| 87 | "<optional>" |
| 88 | "<element name='AlwaysVisible' a:help='If this element is present, the minimum alpha of the overlay will be 50%'>" |
| 89 | "<empty/>" |
| 90 | "</element>" |
| 91 | "</optional>" |
87 | 92 | "<choice>" |
88 | 93 | "<element name='Texture' a:help='Displays a texture underneath the entity.'>" |
89 | 94 | "<element name='MainTexture' a:help='Texture to display underneath the entity. Filepath relative to art/textures/selection/.'><text/></element>" |
… |
… |
public:
|
102 | 107 | { |
103 | 108 | m_EditorOnly = paramNode.GetChild("EditorOnly").IsOk(); |
104 | 109 | |
| 110 | // Certain special units always have their selection overlay shown. |
| 111 | m_AlphaMin = paramNode.GetChild("Overlay").GetChild("AlwaysVisible").IsOk() ? .5 : 0.; |
| 112 | |
105 | 113 | const CParamNode& textureNode = paramNode.GetChild("Overlay").GetChild("Texture"); |
106 | 114 | const CParamNode& outlineNode = paramNode.GetChild("Overlay").GetChild("Outline"); |
107 | 115 | |
… |
… |
public:
|
142 | 150 | |
143 | 151 | virtual void HandleMessage(const CMessage& msg, bool UNUSED(global)); |
144 | 152 | |
145 | | virtual void SetSelectionHighlight(CColor color) |
| 153 | virtual void SetSelectionHighlight(CColor color, bool selected) |
146 | 154 | { |
147 | 155 | m_Color.r = color.r; |
148 | 156 | m_Color.g = color.g; |
149 | 157 | m_Color.b = color.b; |
| 158 | |
| 159 | // Always-visible overlays will be desaturated if their parent unit is deselected. |
| 160 | if (m_AlphaMin > 0. && !selected) |
| 161 | { |
| 162 | float max; |
| 163 | |
| 164 | // Reduce saturation by one-third, the quick-and-dirty way. |
| 165 | if (m_Color.r > m_Color.b) |
| 166 | max = (m_Color.r > m_Color.g) ? m_Color.r : m_Color.g; |
| 167 | else |
| 168 | max = (m_Color.b > m_Color.g) ? m_Color.b : m_Color.g; |
| 169 | |
| 170 | m_Color.r += (max - m_Color.r) / 3.; |
| 171 | m_Color.g += (max - m_Color.g) / 3.; |
| 172 | m_Color.b += (max - m_Color.b) / 3.; |
| 173 | } |
| 174 | |
150 | 175 | SetSelectionHighlightAlpha(color.a); |
151 | 176 | } |
152 | 177 | |
153 | 178 | virtual void SetSelectionHighlightAlpha(float alpha) |
154 | 179 | { |
| 180 | alpha = std::max(m_AlphaMin, alpha); |
| 181 | |
155 | 182 | // set up fading from the current value (as the baseline) to the target value |
156 | 183 | m_FadeBaselineAlpha = m_Color.a; |
157 | 184 | m_FadeDeltaAlpha = alpha - m_FadeBaselineAlpha; |
… |
… |
private:
|
193 | 220 | |
194 | 221 | /// Current selection overlay color. Alpha component is subject to fading. |
195 | 222 | CColor m_Color; |
| 223 | /// Minimum value for current selection overlay alpha. |
| 224 | float m_AlphaMin; |
196 | 225 | /// Baseline alpha value to start fading from. Constant during a single fade. |
197 | 226 | float m_FadeBaselineAlpha; |
198 | 227 | /// Delta between target and baseline alpha. Constant during a single fade. Can be positive or negative. |
… |
… |
void CCmpSelectable::HandleMessage(const CMessage& msg, bool UNUSED(global))
|
269 | 298 | // Update the highlight color, while keeping the current alpha target value intact |
270 | 299 | // (i.e. baseline + delta), so that any ongoing fades simply continue with the new color. |
271 | 300 | CColor color = cmpPlayer->GetColour(); |
272 | | SetSelectionHighlight(CColor(color.r, color.g, color.b, m_FadeBaselineAlpha + m_FadeDeltaAlpha)); |
| 301 | SetSelectionHighlight(CColor(color.r, color.g, color.b, m_FadeBaselineAlpha + m_FadeDeltaAlpha), true); |
273 | 302 | } |
274 | 303 | // fall-through |
275 | 304 | case MT_PositionChanged: |
diff --git a/source/simulation2/components/CCmpTemplateManager.cpp b/source/simulation2/components/CCmpTemplateManager.cpp
index d69cc36..72e6727 100644
a
|
b
|
void CCmpTemplateManager::ConstructTemplateActor(const std::string& actorName, C
|
382 | 382 | "<VisualActor><Actor>" + name + "</Actor></VisualActor>" |
383 | 383 | "<Selectable>" |
384 | 384 | "<EditorOnly/>" |
385 | | "<Overlay><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay>" |
| 385 | "<Overlay><AlwaysVisible/><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay>" |
386 | 386 | "</Selectable>" |
387 | 387 | "</Entity>"; |
388 | 388 | |
diff --git a/source/simulation2/components/ICmpSelectable.cpp b/source/simulation2/components/ICmpSelectable.cpp
index 07c4b51..acc3cc0 100644
a
|
b
|
|
24 | 24 | #include "ps/Overlay.h" |
25 | 25 | |
26 | 26 | BEGIN_INTERFACE_WRAPPER(Selectable) |
27 | | DEFINE_INTERFACE_METHOD_1("SetSelectionHighlight", void, ICmpSelectable, SetSelectionHighlight, CColor) |
| 27 | DEFINE_INTERFACE_METHOD_2("SetSelectionHighlight", void, ICmpSelectable, SetSelectionHighlight, CColor, bool) |
28 | 28 | END_INTERFACE_WRAPPER(Selectable) |
29 | 29 | |
30 | 30 | bool ICmpSelectable::ms_EnableDebugOverlays = false; |
diff --git a/source/simulation2/components/ICmpSelectable.h b/source/simulation2/components/ICmpSelectable.h
index 6ce4019..9382e00 100644
a
|
b
|
public:
|
56 | 56 | * Set the color of the selection highlight (typically a circle/square |
57 | 57 | * around the unit). Set a = 0 to disable the highlight. |
58 | 58 | */ |
59 | | virtual void SetSelectionHighlight(CColor color) = 0; |
| 59 | virtual void SetSelectionHighlight(CColor color, bool selected) = 0; |
60 | 60 | |
61 | 61 | /** |
62 | 62 | * Set the alpha of the selection highlight. Set to 0 to disable the highlight. |
diff --git a/source/simulation2/tests/test_CmpTemplateManager.h b/source/simulation2/tests/test_CmpTemplateManager.h
index 0c3a0e5..0af29ed 100644
a
|
b
|
public:
|
78 | 78 | const CParamNode* actor = tempMan->LoadTemplate(ent2, "actor|example1", -1); |
79 | 79 | TS_ASSERT(actor != NULL); |
80 | 80 | TS_ASSERT_WSTR_EQUALS(actor->ToXML(), |
81 | | L"<Selectable><EditorOnly></EditorOnly><Overlay><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay></Selectable>" |
| 81 | L"<Selectable><EditorOnly></EditorOnly><Overlay><AlwaysVisible></AlwaysVisible><Texture><MainTexture>actor.png</MainTexture><MainTextureMask>actor_mask.png</MainTextureMask></Texture></Overlay></Selectable>" |
82 | 82 | L"<VisualActor><Actor>example1</Actor><SilhouetteDisplay>false</SilhouetteDisplay><SilhouetteOccluder>false</SilhouetteOccluder></VisualActor>"); |
83 | 83 | |
84 | 84 | const CParamNode* preview = tempMan->LoadTemplate(ent2, "preview|unit", -1); |
diff --git a/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/ObjectHandlers.cpp
index 46cf352..03b1790 100644
a
|
b
|
MESSAGEHANDLER(SetSelectionPreview)
|
148 | 148 | } |
149 | 149 | } |
150 | 150 | |
151 | | cmpSelectable->SetSelectionHighlight(colour); |
| 151 | cmpSelectable->SetSelectionHighlight(colour, true); |
152 | 152 | } |
153 | 153 | } |
154 | 154 | |