Index: ps/trunk/source/simulation2/components/CCmpFootprint.cpp =================================================================== --- ps/trunk/source/simulation2/components/CCmpFootprint.cpp +++ ps/trunk/source/simulation2/components/CCmpFootprint.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2018 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 @@ -49,7 +49,7 @@ static std::string GetSchema() { return - "Approximation of the entity's shape, for collision detection and outline rendering. " + "Approximation of the entity's shape, for collision detection and may be used for outline rendering or to determine selectable bounding box. " "Shapes are flat horizontal squares or circles, extended vertically to a given height." "" "" Index: ps/trunk/source/simulation2/components/CCmpSelectable.cpp =================================================================== --- ps/trunk/source/simulation2/components/CCmpSelectable.cpp +++ ps/trunk/source/simulation2/components/CCmpSelectable.cpp @@ -1,4 +1,4 @@ -/* 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 @@ -52,6 +52,13 @@ class CCmpSelectable : public ICmpSelectable { public: + enum EShape + { + FOOTPRINT, + CIRCLE, + SQUARE + }; + static void ClassInit(CComponentManager& componentManager) { componentManager.SubscribeToMessageType(MT_OwnershipChanged); @@ -90,26 +97,57 @@ "" "" "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" - "" + "" + "" + "" + "" + "" + "" + "" + "" + "0.0" + "" + "" + "" + "" + "0.0" + "" + "" + "" + "" + "" + "" + "0.0" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" ""; } + EShape m_Shape; + entity_pos_t m_Width; // width/radius + entity_pos_t m_Height; // height/radius + virtual void Init(const CParamNode& paramNode) { m_EditorOnly = paramNode.GetChild("EditorOnly").IsOk(); @@ -145,6 +183,32 @@ m_OverlayDescriptor.m_LineThickness = outlineNode.GetChild("LineThickness").ToFloat(); } + const CParamNode& shapeNode = paramNode.GetChild("Overlay").GetChild("Shape"); + if (shapeNode.IsOk()) + { + if (shapeNode.GetChild("Square").IsOk()) + { + m_Shape = SQUARE; + m_Width = shapeNode.GetChild("Square").GetChild("@width").ToFixed(); + m_Height = shapeNode.GetChild("Square").GetChild("@depth").ToFixed(); + } + else if (shapeNode.GetChild("Circle").IsOk()) + { + m_Shape = CIRCLE; + m_Width = m_Height = shapeNode.GetChild("Circle").GetChild("@radius").ToFixed(); + } + else + { + // Should not happen + m_Shape = FOOTPRINT; + LOGWARNING("[Selectable] Selected overlay shape is not implemented."); + } + } + else + { + m_Shape = FOOTPRINT; + } + m_EnabledInterpolate = false; m_EnabledRenderSubmit = false; UpdateMessageSubscriptions(); @@ -218,7 +282,7 @@ void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling); /** - * Draw a textured line overlay. The selection overlays for structures are based solely on footprint shape. + * Draw a textured line overlay. */ void UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset); @@ -427,14 +491,18 @@ return; CmpPtr cmpPosition(GetEntityHandle()); - CmpPtr cmpFootprint(GetEntityHandle()); - if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) + if (!cmpPosition || !cmpPosition->IsInWorld()) return; - ICmpFootprint::EShape fpShape; - entity_pos_t fpSize0_fixed, fpSize1_fixed, fpHeight_fixed; - cmpFootprint->GetShape(fpShape, fpSize0_fixed, fpSize1_fixed, fpHeight_fixed); - + ICmpFootprint::EShape fpShape = ICmpFootprint::CIRCLE; + if (m_Shape == FOOTPRINT) + { + CmpPtr cmpFootprint(GetEntityHandle()); + if (!cmpFootprint) + return; + entity_pos_t h; + cmpFootprint->GetShape(fpShape, m_Width, m_Height, h); + } float rotY; CVector2D origin; cmpPosition->GetInterpolatedPosition2D(frameOffset, origin.X, origin.Y, rotY); @@ -443,10 +511,10 @@ overlay.m_Color = m_Color; overlay.CreateOverlayTexture(overlayDescriptor); - if (fpShape == ICmpFootprint::SQUARE) - SimRender::ConstructTexturedLineBox(overlay, origin, cmpPosition->GetRotation(), fpSize0_fixed.ToFloat(), fpSize1_fixed.ToFloat()); + if (m_Shape == SQUARE || (m_Shape == FOOTPRINT && fpShape == ICmpFootprint::SQUARE)) + SimRender::ConstructTexturedLineBox(overlay, origin, cmpPosition->GetRotation(), m_Width.ToFloat(), m_Height.ToFloat()); else - SimRender::ConstructTexturedLineCircle(overlay, origin, fpSize0_fixed.ToFloat()); + SimRender::ConstructTexturedLineCircle(overlay, origin, m_Width.ToFloat()); } void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) @@ -462,10 +530,19 @@ return; CmpPtr cmpPosition(GetEntityHandle()); - CmpPtr cmpFootprint(GetEntityHandle()); - if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) + if (!cmpPosition || !cmpPosition->IsInWorld()) return; + ICmpFootprint::EShape fpShape = ICmpFootprint::CIRCLE; + if (m_Shape == FOOTPRINT) + { + CmpPtr cmpFootprint(GetEntityHandle()); + if (!cmpFootprint) + return; + entity_pos_t h; + cmpFootprint->GetShape(fpShape, m_Width, m_Height, h); + } + float rotY; CVector2D position; cmpPosition->GetInterpolatedPosition2D(frameOffset, position.X, position.Y, rotY); @@ -477,10 +554,6 @@ CTerrain* terrain = cmpTerrain->GetCTerrain(); ENSURE(terrain); - ICmpFootprint::EShape fpShape; - entity_pos_t fpSize0_fixed, fpSize1_fixed, fpHeight_fixed; - cmpFootprint->GetShape(fpShape, fpSize0_fixed, fpSize1_fixed, fpHeight_fixed); - // --------------------------------------------------------------------------------- if (!m_UnitOverlay) @@ -510,9 +583,9 @@ CVector2D unitX(c, s); CVector2D unitZ(-s, c); - float halfSizeX = fpSize0_fixed.ToFloat(); - float halfSizeZ = fpSize1_fixed.ToFloat(); - if (fpShape == ICmpFootprint::SQUARE) + float halfSizeX = m_Width.ToFloat(); + float halfSizeZ = m_Height.ToFloat(); + if (m_Shape == SQUARE || (m_Shape == FOOTPRINT && fpShape == ICmpFootprint::SQUARE)) { halfSizeX /= 2.0f; halfSizeZ /= 2.0f;