Index: ps/trunk/source/simulation2/components/CCmpRangeOverlayRenderer.cpp =================================================================== --- ps/trunk/source/simulation2/components/CCmpRangeOverlayRenderer.cpp (revision 24071) +++ ps/trunk/source/simulation2/components/CCmpRangeOverlayRenderer.cpp (revision 24072) @@ -1,233 +1,215 @@ -/* Copyright (C) 2019 Wildfire Games. +/* Copyright (C) 2020 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/ICmpOwnership.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" #include class CCmpRangeOverlayRenderer : public ICmpRangeOverlayRenderer { public: static void ClassInit(CComponentManager& componentManager) { componentManager.SubscribeToMessageType(MT_Deserialized); componentManager.SubscribeToMessageType(MT_OwnershipChanged); componentManager.SubscribeToMessageType(MT_PlayerColorChanged); } DEFAULT_COMPONENT_ALLOCATOR(RangeOverlayRenderer) CCmpRangeOverlayRenderer() : m_RangeOverlayData() { m_Color = CColor(0.f, 0.f, 0.f, 1.f); } ~CCmpRangeOverlayRenderer() = default; static std::string GetSchema() { return ""; } virtual void Init(const CParamNode& UNUSED(paramNode)) { - m_EnabledInterpolate = false; - m_EnabledRenderSubmit = false; - m_Enabled = false; + m_Enabled = m_LastEnabledState = false; UpdateMessageSubscriptions(); } virtual void Deinit() { } virtual void Serialize(ISerializer& UNUSED(serialize)) { } virtual void Deserialize(const CParamNode& paramNode, IDeserializer& UNUSED(deserialize)) { Init(paramNode); } void ResetRangeOverlays() { 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; rangeOverlayDescriptor.m_Radius = radius; rangeOverlayDescriptor.m_LineTexture = CStrIntern(TEXTURE_BASE_PATH + texture); rangeOverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTURE_BASE_PATH + textureMask); rangeOverlayDescriptor.m_LineThickness = thickness; m_RangeOverlayData.push_back({ rangeOverlayDescriptor, std::unique_ptr() }); 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) UpdateRangeOverlay(rangeOverlay, msgData.offset); UpdateMessageSubscriptions(); break; } case MT_Deserialized: case MT_OwnershipChanged: case MT_PlayerColorChanged: { UpdateColor(); break; } case MT_RenderSubmit: { const CMessageRenderSubmit& msgData = static_cast (msg); RenderSubmit(msgData.collector, msgData.frustum, msgData.culling); break; } } } private: struct RangeOverlayData { SOverlayDescriptor descriptor; std::unique_ptr line; }; virtual void UpdateColor() { CmpPtr cmpOwnership(GetEntityHandle()); if (!cmpOwnership) return; player_id_t owner = cmpOwnership->GetOwner(); if (owner == INVALID_PLAYER) return; CmpPtr cmpPlayerManager(GetSystemEntity()); if (!cmpPlayerManager) return; CmpPtr cmpPlayer(GetSimContext(), cmpPlayerManager->GetPlayerByID(owner)); if (!cmpPlayer) return; CColor color = cmpPlayer->GetDisplayedColor(); m_Color = color; } 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 (m_Enabled == m_LastEnabledState) + return; - if (needRenderSubmit != m_EnabledRenderSubmit) - { - GetSimContext().GetComponentManager().DynamicSubscriptionNonsync(MT_RenderSubmit, this, needRenderSubmit); - m_EnabledRenderSubmit = needRenderSubmit; - m_Enabled = needRenderSubmit; - } + CComponentManager& cmpManager = GetSimContext().GetComponentManager(); + cmpManager.DynamicSubscriptionNonsync(MT_Interpolate, this, m_Enabled); + cmpManager.DynamicSubscriptionNonsync(MT_RenderSubmit, this, m_Enabled); + m_LastEnabledState = m_Enabled; } void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling) { if (!m_RangeOverlayData.size()) return; for (const RangeOverlayData& rangeOverlay : m_RangeOverlayData) { if (!rangeOverlay.line) continue; if (culling && !rangeOverlay.line->IsVisibleInFrustum(frustum)) continue; collector.Submit(rangeOverlay.line.get()); } } void UpdateRangeOverlay(RangeOverlayData& rangeOverlay, const 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); rangeOverlay.line = std::unique_ptr(new SOverlayTexturedLine); rangeOverlay.line->m_SimContext = &GetSimContext(); rangeOverlay.line->m_Color = m_Color; rangeOverlay.line->CreateOverlayTexture(&rangeOverlay.descriptor); SimRender::ConstructTexturedLineCircle(*rangeOverlay.line.get(), origin, rangeOverlay.descriptor.m_Radius); } - bool m_EnabledInterpolate; - bool m_EnabledRenderSubmit; + bool m_LastEnabledState; bool m_Enabled; const char* TEXTURE_BASE_PATH = "art/textures/selection/"; std::vector m_RangeOverlayData; CColor m_Color; }; REGISTER_COMPONENT_TYPE(RangeOverlayRenderer)