Index: ps/trunk/binaries/data/mods/public/simulation/components/RangeVisualization.js =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/components/RangeVisualization.js +++ ps/trunk/binaries/data/mods/public/simulation/components/RangeVisualization.js @@ -70,11 +70,11 @@ RangeVisualization.prototype.RegenerateRangeVisualizations = function(forceUpdate) { - let cmpSelectable = Engine.QueryInterface(this.entity, IID_Selectable); - if (!cmpSelectable) + let cmpRangeOverlayRenderer = Engine.QueryInterface(this.entity, IID_RangeOverlayRenderer); + if (!cmpRangeOverlayRenderer) return; - cmpSelectable.ResetRangeOverlays(); + cmpRangeOverlayRenderer.ResetRangeOverlays(); if (!this.enabled && !forceUpdate) return; @@ -83,7 +83,7 @@ for (let rangeOverlayType of this.rangeVisualizations.keys()) if (this.enabledRangeTypes[rangeOverlayType]) for (let rangeOverlay of this.rangeVisualizations.get(rangeOverlayType)) - cmpSelectable.AddRangeOverlay( + cmpRangeOverlayRenderer.AddRangeOverlay( rangeOverlay.radius, rangeOverlay.texture, rangeOverlay.textureMask, Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml +++ ps/trunk/binaries/data/mods/public/simulation/templates/template_structure.xml @@ -100,6 +100,7 @@ round default + 2.0 Index: ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml =================================================================== --- ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml +++ ps/trunk/binaries/data/mods/public/simulation/templates/template_unit.xml @@ -66,6 +66,7 @@ false + 2.0 Index: ps/trunk/source/simulation2/TypeList.h =================================================================== --- ps/trunk/source/simulation2/TypeList.h +++ ps/trunk/source/simulation2/TypeList.h @@ -150,6 +150,9 @@ INTERFACE(RangeManager) COMPONENT(RangeManager) +INTERFACE(RangeOverlayRenderer) +COMPONENT(RangeOverlayRenderer) + INTERFACE(Selectable) COMPONENT(Selectable) Index: ps/trunk/source/simulation2/components/CCmpRangeOverlayRenderer.cpp =================================================================== --- ps/trunk/source/simulation2/components/CCmpRangeOverlayRenderer.cpp +++ ps/trunk/source/simulation2/components/CCmpRangeOverlayRenderer.cpp @@ -0,0 +1,216 @@ +/* Copyright (C) 2017 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "ICmpRangeOverlayRenderer.h" + +#include "graphics/Overlay.h" +#include "graphics/TextureManager.h" +#include "renderer/Renderer.h" +#include "simulation2/MessageTypes.h" +#include "simulation2/components/ICmpPlayer.h" +#include "simulation2/components/ICmpPlayerManager.h" +#include "simulation2/components/ICmpPosition.h" +#include "simulation2/helpers/Render.h" +#include "simulation2/system/Component.h" + +class CCmpRangeOverlayRenderer : public ICmpRangeOverlayRenderer +{ +public: + static void ClassInit(CComponentManager& componentManager) + { + componentManager.SubscribeToMessageType(MT_OwnershipChanged); + } + + DEFAULT_COMPONENT_ALLOCATOR(RangeOverlayRenderer) + + CCmpRangeOverlayRenderer() : m_RangeOverlayData() + { + m_Color = CColor(0, 0, 0, 0); + } + + ~CCmpRangeOverlayRenderer() + { + for (const RangeOverlayData& rangeOverlay : m_RangeOverlayData) + delete rangeOverlay.second; + } + + static std::string GetSchema() + { + return ""; + } + + virtual void Init(const CParamNode& UNUSED(paramNode)) + { + m_EnabledInterpolate = false; + m_EnabledRenderSubmit = false; + m_Enabled = false; + UpdateMessageSubscriptions(); + } + + virtual void Deinit() { } + + virtual void Serialize(ISerializer& UNUSED(serialize)) + { + } + + virtual void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) + { + Init(paramNode); + } + + void ResetRangeOverlays() + { + for (const RangeOverlayData& rangeOverlay : m_RangeOverlayData) + delete rangeOverlay.second; + m_RangeOverlayData.clear(); + UpdateMessageSubscriptions(); + m_Enabled = false; + } + + virtual void AddRangeOverlay(float radius, const std::string& texture, const std::string& textureMask, float thickness) + { + if (!CRenderer::IsInitialised()) + return; + + SOverlayDescriptor rangeOverlayDescriptor; + SOverlayTexturedLine* rangeOverlay = nullptr; + rangeOverlayDescriptor.m_Radius = radius; + rangeOverlayDescriptor.m_LineTexture = CStrIntern(TEXTUREBASEPATH + texture); + rangeOverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTUREBASEPATH + textureMask); + rangeOverlayDescriptor.m_LineThickness = thickness; + + m_RangeOverlayData.push_back({ rangeOverlayDescriptor, rangeOverlay }); + m_Enabled = true; + UpdateMessageSubscriptions(); + } + + void HandleMessage(const CMessage& msg, bool UNUSED(global)) + { + switch (msg.GetType()) + { + case MT_Interpolate: + { + const CMessageInterpolate& msgData = static_cast (msg); + + for (RangeOverlayData& rangeOverlay : m_RangeOverlayData) + { + delete rangeOverlay.second; + rangeOverlay.second = new SOverlayTexturedLine; + UpdateRangeOverlay(&rangeOverlay.first, *rangeOverlay.second, msgData.offset); + } + + UpdateMessageSubscriptions(); + + break; + } + case MT_OwnershipChanged: + { + const CMessageOwnershipChanged& msgData = static_cast (msg); + if (msgData.to == INVALID_PLAYER) + break; + + CmpPtr cmpPlayerManager(GetSystemEntity()); + if (!cmpPlayerManager) + break; + + CmpPtr cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(msgData.to)); + if (!cmpPlayer) + break; + + CColor color = cmpPlayer->GetColor(); + m_Color = color; + break; + } + case MT_RenderSubmit: + { + const CMessageRenderSubmit& msgData = static_cast (msg); + RenderSubmit(msgData.collector); + break; + } + } + } + + void UpdateMessageSubscriptions() + { + bool needInterpolate = false; + bool needRenderSubmit = false; + + if (m_Enabled) + { + needInterpolate = true; + needRenderSubmit = true; + } + + if (needInterpolate != m_EnabledInterpolate) + { + GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_Interpolate, this, needInterpolate); + m_EnabledInterpolate = needInterpolate; + m_Enabled = needInterpolate; + } + + if (needRenderSubmit != m_EnabledRenderSubmit) + { + GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_RenderSubmit, this, needRenderSubmit); + m_EnabledRenderSubmit = needRenderSubmit; + m_Enabled = needRenderSubmit; + } + } + + void RenderSubmit(SceneCollector& collector) + { + if (!m_RangeOverlayData.size()) + return; + + for (const RangeOverlayData& rangeOverlay : m_RangeOverlayData) + if (rangeOverlay.second) + collector.Submit(rangeOverlay.second); + } + +private: + void UpdateRangeOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset) + { + if (!CRenderer::IsInitialised()) + return; + + CmpPtr cmpPosition(GetEntityHandle()); + if (!cmpPosition || !cmpPosition->IsInWorld()) + return; + + float rotY; + CVector2D origin; + cmpPosition->GetInterpolatedPosition2D(frameOffset, origin.X, origin.Y, rotY); + + overlay.m_SimContext = &GetSimContext(); + overlay.m_Color = m_Color; + overlay.CreateOverlayTexture(overlayDescriptor); + + SimRender::ConstructTexturedLineCircle(overlay, origin, overlayDescriptor->m_Radius); + } + + bool m_EnabledInterpolate; + bool m_EnabledRenderSubmit; + bool m_Enabled; + + const char* TEXTUREBASEPATH = "art/textures/selection/"; + typedef std::pair RangeOverlayData; + std::vector m_RangeOverlayData; + CColor m_Color; +}; + +REGISTER_COMPONENT_TYPE(RangeOverlayRenderer) Index: ps/trunk/source/simulation2/components/CCmpSelectable.cpp =================================================================== --- ps/trunk/source/simulation2/components/CCmpSelectable.cpp +++ ps/trunk/source/simulation2/components/CCmpSelectable.cpp @@ -65,7 +65,7 @@ CCmpSelectable() : m_DebugBoundingBoxOverlay(NULL), m_DebugSelectionBoxOverlay(NULL), - m_BuildingOverlay(NULL), m_UnitOverlay(NULL), m_RangeOverlayData(), + m_BuildingOverlay(NULL), m_UnitOverlay(NULL), m_FadeBaselineAlpha(0.f), m_FadeDeltaAlpha(0.f), m_FadeProgress(0.f), m_Selected(false), m_Cached(false), m_Visible(false) { @@ -78,8 +78,6 @@ delete m_DebugSelectionBoxOverlay; delete m_BuildingOverlay; delete m_UnitOverlay; - for (RangeOverlayData& rangeOverlay : m_RangeOverlayData) - delete rangeOverlay.second; } static std::string GetSchema() @@ -194,22 +192,6 @@ SetSelectionHighlightAlpha(color.a); } - virtual void AddRangeOverlay(float radius, const std::string& texture, const std::string& textureMask, float thickness) - { - if (!CRenderer::IsInitialised()) - return; - - SOverlayDescriptor rangeOverlayDescriptor; - SOverlayTexturedLine* rangeOverlay = nullptr; - - rangeOverlayDescriptor.m_Radius = radius; - rangeOverlayDescriptor.m_LineTexture = CStrIntern(TEXTUREBASEPATH + texture); - rangeOverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTUREBASEPATH + textureMask); - rangeOverlayDescriptor.m_LineThickness = thickness; - - m_RangeOverlayData.push_back({rangeOverlayDescriptor, rangeOverlay}); - } - virtual void SetSelectionHighlightAlpha(float alpha) { alpha = std::max(m_AlphaMin, alpha); @@ -238,7 +220,7 @@ /** * Draw a textured line overlay. The selection overlays for structures are based solely on footprint shape. */ - void UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset, bool buildingOverlay); + void UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset); /** * Called from the interpolation handler; responsible for ensuring the dynamic overlay (provided we're @@ -260,11 +242,6 @@ void UpdateMessageSubscriptions(); /** - * Delete all range overlays. - */ - void ResetRangeOverlays(); - - /** * Set the color of the current owner. */ void UpdatePlayerColor(); @@ -274,10 +251,6 @@ SOverlayTexturedLine* m_BuildingOverlay; SOverlayQuad* m_UnitOverlay; - // Holds the data for all range overlays - typedef std::pair RangeOverlayData; - std::vector m_RangeOverlayData; - SOverlayLine* m_DebugBoundingBoxOverlay; SOverlayLine* m_DebugSelectionBoxOverlay; @@ -345,17 +318,8 @@ // update dynamic overlay only when visible if (m_Color.a > 0) - { UpdateDynamicOverlay(msgData.offset); - for (RangeOverlayData& rangeOverlay : m_RangeOverlayData) - { - delete rangeOverlay.second; - rangeOverlay.second = new SOverlayTexturedLine; - UpdateTexturedLineOverlay(&rangeOverlay.first, *rangeOverlay.second, msgData.offset, false); - } - } - UpdateMessageSubscriptions(); break; @@ -439,15 +403,6 @@ SetSelectionHighlight(color, m_Selected); } -void CCmpSelectable::ResetRangeOverlays() -{ - for (RangeOverlayData& rangeOverlay : m_RangeOverlayData) - delete rangeOverlay.second; - m_RangeOverlayData.clear(); - - UpdateMessageSubscriptions(); -} - void CCmpSelectable::UpdateMessageSubscriptions() { bool needInterpolate = false; @@ -477,7 +432,7 @@ SAFE_DELETE(m_BuildingOverlay); } -void CCmpSelectable::UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset, bool buildingOverlay) +void CCmpSelectable::UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset) { if (!CRenderer::IsInitialised()) return; @@ -499,10 +454,10 @@ overlay.m_Color = m_Color; overlay.CreateOverlayTexture(overlayDescriptor); - if (buildingOverlay && fpShape == ICmpFootprint::SQUARE) + if (fpShape == ICmpFootprint::SQUARE) SimRender::ConstructTexturedLineBox(overlay, origin, cmpPosition->GetRotation(), fpSize0_fixed.ToFloat(), fpSize1_fixed.ToFloat()); else - SimRender::ConstructTexturedLineCircle(overlay, origin, buildingOverlay ? fpSize0_fixed.ToFloat() : overlayDescriptor->m_Radius); + SimRender::ConstructTexturedLineCircle(overlay, origin, fpSize0_fixed.ToFloat()); } void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) @@ -615,7 +570,7 @@ // (see InvalidateStaticOverlay). Since they are expected to change rarely (if ever) during // normal gameplay, this saves us doing all the work below on each frame. m_BuildingOverlay = new SOverlayTexturedLine; - UpdateTexturedLineOverlay(&m_OverlayDescriptor, *m_BuildingOverlay, 0, true); + UpdateTexturedLineOverlay(&m_OverlayDescriptor, *m_BuildingOverlay, 0); } m_BuildingOverlay->m_Color = m_Color; // done separately so alpha changes don't require a full update call collector.Submit(m_BuildingOverlay); @@ -630,10 +585,6 @@ default: break; } - - for (const RangeOverlayData& rangeOverlay : m_RangeOverlayData) - if (rangeOverlay.second) - collector.Submit(rangeOverlay.second); } // Render bounding box debug overlays if we have a positive target alpha value. This ensures Index: ps/trunk/source/simulation2/components/ICmpRangeOverlayRenderer.h =================================================================== --- ps/trunk/source/simulation2/components/ICmpRangeOverlayRenderer.h +++ ps/trunk/source/simulation2/components/ICmpRangeOverlayRenderer.h @@ -0,0 +1,40 @@ +/* Copyright (C) 2017 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_ICMPRANGEOVERLAYRENDERER +#define INCLUDED_ICMPRANGEOVERLAYRENDERER + +#include "ps/CStrIntern.h" +#include "simulation2/system/Interface.h" + +class ICmpRangeOverlayRenderer : public IComponent +{ +public: + /** + * Add a range overlay to this entity, for example for an aura or attack. + */ + virtual void AddRangeOverlay(float radius, const std::string& texture, const std::string& textureMask, float thickness) = 0; + + /** + * Delete all range overlays. + */ + virtual void ResetRangeOverlays() = 0; + + DECLARE_INTERFACE_TYPE(RangeOverlayRenderer) +}; + +#endif // INCLUDED_ICMPRANGEOVERLAYRENDERER Index: ps/trunk/source/simulation2/components/ICmpRangeOverlayRenderer.cpp =================================================================== --- ps/trunk/source/simulation2/components/ICmpRangeOverlayRenderer.cpp +++ ps/trunk/source/simulation2/components/ICmpRangeOverlayRenderer.cpp @@ -0,0 +1,26 @@ +/* Copyright (C) 2017 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "ICmpRangeOverlayRenderer.h" +#include "simulation2/system/InterfaceScripted.h" + +BEGIN_INTERFACE_WRAPPER(RangeOverlayRenderer) +DEFINE_INTERFACE_METHOD_4("AddRangeOverlay", void, ICmpRangeOverlayRenderer, AddRangeOverlay, float, std::string, std::string, float) +DEFINE_INTERFACE_METHOD_0("ResetRangeOverlays", void, ICmpRangeOverlayRenderer, ResetRangeOverlays) +END_INTERFACE_WRAPPER(RangeOverlayRenderer) Index: ps/trunk/source/simulation2/components/ICmpSelectable.h =================================================================== --- ps/trunk/source/simulation2/components/ICmpSelectable.h +++ ps/trunk/source/simulation2/components/ICmpSelectable.h @@ -39,16 +39,6 @@ virtual void SetSelectionHighlight(const CColor& color, bool selected) = 0; /** - * Add a range overlay to this entity, for example for an aura or attack. - */ - virtual void AddRangeOverlay(float radius, const std::string& texture, const std::string& textureMask, float thickness) = 0; - - /** - * Delete all range overlays. - */ - virtual void ResetRangeOverlays() = 0; - - /** * Enables or disables rendering of an entity's selectable. * @param visible Whether the selectable should be visible. */ Index: ps/trunk/source/simulation2/components/ICmpSelectable.cpp =================================================================== --- ps/trunk/source/simulation2/components/ICmpSelectable.cpp +++ ps/trunk/source/simulation2/components/ICmpSelectable.cpp @@ -25,8 +25,6 @@ BEGIN_INTERFACE_WRAPPER(Selectable) DEFINE_INTERFACE_METHOD_2("SetSelectionHighlight", void, ICmpSelectable, SetSelectionHighlight, CColor, bool) -DEFINE_INTERFACE_METHOD_4("AddRangeOverlay", void, ICmpSelectable, AddRangeOverlay, float, std::string, std::string, float) -DEFINE_INTERFACE_METHOD_0("ResetRangeOverlays", void, ICmpSelectable, ResetRangeOverlays) END_INTERFACE_WRAPPER(Selectable) bool ICmpSelectable::ms_EnableDebugOverlays = false;