Changeset View
Changeset View
Standalone View
Standalone View
source/simulation2/components/CCmpSelectable.cpp
/* Copyright (C) 2019 Wildfire Games. | /* Copyright (C) 2020 Wildfire Games. | ||||
* This file is part of 0 A.D. | * This file is part of 0 A.D. | ||||
* | * | ||||
* 0 A.D. is free software: you can redistribute it and/or modify | * 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 | * it under the terms of the GNU General Public License as published by | ||||
* the Free Software Foundation, either version 2 of the License, or | * the Free Software Foundation, either version 2 of the License, or | ||||
* (at your option) any later version. | * (at your option) any later version. | ||||
* | * | ||||
* 0 A.D. is distributed in the hope that it will be useful, | * 0 A.D. is distributed in the hope that it will be useful, | ||||
▲ Show 20 Lines • Show All 92 Lines • ▼ Show 20 Lines | return | ||||
"<element name='MainTextureMask' a:help='Mask texture that controls where to apply player color. Filepath relative to art/textures/selection/.'><text/></element>" | "<element name='MainTextureMask' a:help='Mask texture that controls where to apply player color. Filepath relative to art/textures/selection/.'><text/></element>" | ||||
"</element>" | "</element>" | ||||
"<element name='Outline' a:help='Traces the outline of the entity with a line texture.'>" | "<element name='Outline' a:help='Traces the outline of the entity with a line texture.'>" | ||||
"<element name='LineTexture' a:help='Texture to apply to the line. Filepath relative to art/textures/selection/.'><text/></element>" | "<element name='LineTexture' a:help='Texture to apply to the line. Filepath relative to art/textures/selection/.'><text/></element>" | ||||
"<element name='LineTextureMask' a:help='Texture that controls where to apply player color. Filepath relative to art/textures/selection/.'><text/></element>" | "<element name='LineTextureMask' a:help='Texture that controls where to apply player color. Filepath relative to art/textures/selection/.'><text/></element>" | ||||
"<element name='LineThickness' a:help='Thickness of the line, in world units.'><ref name='positiveDecimal'/></element>" | "<element name='LineThickness' a:help='Thickness of the line, in world units.'><ref name='positiveDecimal'/></element>" | ||||
"</element>" | "</element>" | ||||
"</choice>" | "</choice>" | ||||
"</element>"; | "</element>" | ||||
"<optional>" | |||||
"<choice>" | |||||
"<element name='Square' a:help='Set the selection to a square of the given size'>" | |||||
"<attribute name='width' a:help='Size of the selection along the left/right direction (in metres)'>" | |||||
Stan: Is it really meters? | |||||
Done Inline ActionsI think it refers to in game length (with scaling), like attack range is somewhere said it is in meters or something like that. Silier: I think it refers to in game length (with scaling), like attack range is somewhere said it is… | |||||
"<data type='decimal'>" | |||||
"<param name='minExclusive'>0.0</param>" | |||||
"</data>" | |||||
"</attribute>" | |||||
"<attribute name='depth' a:help='Size of the selection along the front/back direction (in metres)'>" | |||||
"<data type='decimal'>" | |||||
"<param name='minExclusive'>0.0</param>" | |||||
"</data>" | |||||
"</attribute>" | |||||
"</element>" | |||||
"<element name='Circle' a:help='Set the selection to a circle of the given size'>" | |||||
"<attribute name='radius' a:help='Radius of the selection (in metres)'>" | |||||
"<data type='decimal'>" | |||||
"<param name='minExclusive'>0.0</param>" | |||||
"</data>" | |||||
"</attribute>" | |||||
"</element>" | |||||
"</choice>" | |||||
"</optional>"; | |||||
} | } | ||||
EShape m_Shape; | |||||
entity_pos_t m_Size0; // width/radius | |||||
entity_pos_t m_Size1; // height/radius | |||||
virtual void Init(const CParamNode& paramNode) | virtual void Init(const CParamNode& paramNode) | ||||
{ | { | ||||
m_EditorOnly = paramNode.GetChild("EditorOnly").IsOk(); | m_EditorOnly = paramNode.GetChild("EditorOnly").IsOk(); | ||||
// Certain special units always have their selection overlay shown | // Certain special units always have their selection overlay shown | ||||
m_AlwaysVisible = paramNode.GetChild("Overlay").GetChild("AlwaysVisible").IsOk(); | m_AlwaysVisible = paramNode.GetChild("Overlay").GetChild("AlwaysVisible").IsOk(); | ||||
if (m_AlwaysVisible) | if (m_AlwaysVisible) | ||||
{ | { | ||||
Show All 19 Lines | virtual void Init(const CParamNode& paramNode) | ||||
{ | { | ||||
// textured outline mode (static, for buildings) | // textured outline mode (static, for buildings) | ||||
m_OverlayDescriptor.m_Type = STATIC_OUTLINE; | m_OverlayDescriptor.m_Type = STATIC_OUTLINE; | ||||
m_OverlayDescriptor.m_LineTexture = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTexture").ToUTF8()); | m_OverlayDescriptor.m_LineTexture = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTexture").ToUTF8()); | ||||
m_OverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTextureMask").ToUTF8()); | m_OverlayDescriptor.m_LineTextureMask = CStrIntern(TEXTUREBASEPATH + outlineNode.GetChild("LineTextureMask").ToUTF8()); | ||||
m_OverlayDescriptor.m_LineThickness = outlineNode.GetChild("LineThickness").ToFloat(); | m_OverlayDescriptor.m_LineThickness = outlineNode.GetChild("LineThickness").ToFloat(); | ||||
} | } | ||||
if (paramNode.GetChild("Square").IsOk()) | |||||
Not Done Inline ActionsYou're missing a GetChild("Overlay") here. wraitii: You're missing a GetChild("Overlay") here. | |||||
Done Inline Actionsoh, thnx Silier: oh, thnx | |||||
{ | |||||
m_Shape = SQUARE; | |||||
m_Size0 = paramNode.GetChild("Square").GetChild("@width").ToFixed(); | |||||
m_Size1 = paramNode.GetChild("Square").GetChild("@depth").ToFixed(); | |||||
} | |||||
else if (paramNode.GetChild("Circle").IsOk()) | |||||
{ | |||||
m_Shape = CIRCLE; | |||||
m_Size0 = m_Size1 = paramNode.GetChild("Circle").GetChild("@radius").ToFixed(); | |||||
} | |||||
else | |||||
{ | |||||
m_Shape = NONE; | |||||
} | |||||
m_EnabledInterpolate = false; | m_EnabledInterpolate = false; | ||||
Not Done Inline ActionsProbably worth at least a LOGWARNING, possibly an ENSURE. wraitii: Probably worth at least a LOGWARNING, possibly an ENSURE. | |||||
m_EnabledRenderSubmit = false; | m_EnabledRenderSubmit = false; | ||||
UpdateMessageSubscriptions(); | UpdateMessageSubscriptions(); | ||||
} | } | ||||
virtual void Deinit() { } | virtual void Deinit() { } | ||||
virtual void Serialize(ISerializer& UNUSED(serialize)) | virtual void Serialize(ISerializer& UNUSED(serialize)) | ||||
{ | { | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | public: | ||||
virtual bool IsEditorOnly() const | virtual bool IsEditorOnly() const | ||||
{ | { | ||||
return m_EditorOnly; | return m_EditorOnly; | ||||
} | } | ||||
void RenderSubmit(SceneCollector& collector, const CFrustum& frustum, bool culling); | 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); | void UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset); | ||||
/** | /** | ||||
* Called from the interpolation handler; responsible for ensuring the dynamic overlay (provided we're | * Called from the interpolation handler; responsible for ensuring the dynamic overlay (provided we're | ||||
* using one) is up-to-date and ready to be submitted to the next rendering run. | * using one) is up-to-date and ready to be submitted to the next rendering run. | ||||
*/ | */ | ||||
void UpdateDynamicOverlay(float frameOffset); | void UpdateDynamicOverlay(float frameOffset); | ||||
▲ Show 20 Lines • Show All 192 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
void CCmpSelectable::UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset) | void CCmpSelectable::UpdateTexturedLineOverlay(const SOverlayDescriptor* overlayDescriptor, SOverlayTexturedLine& overlay, float frameOffset) | ||||
{ | { | ||||
if (!CRenderer::IsInitialised()) | if (!CRenderer::IsInitialised()) | ||||
return; | return; | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
CmpPtr<ICmpFootprint> cmpFootprint(GetEntityHandle()); | if (!cmpPosition || !cmpPosition->IsInWorld()) | ||||
if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) | |||||
return; | return; | ||||
ICmpFootprint::EShape fpShape; | ICmpFootprint::EShape shape; | ||||
entity_pos_t fpSize0_fixed, fpSize1_fixed, fpHeight_fixed; | if (m_Shape == ICmpSelectable::NONE) { | ||||
cmpFootprint->GetShape(fpShape, fpSize0_fixed, fpSize1_fixed, fpHeight_fixed); | CmpPtr<ICmpFootprint> cmpFootprint(GetEntityHandle()); | ||||
if (!cmpFootprint) | |||||
return; | |||||
entity_pos_t h; | |||||
cmpFootprint->GetShape(shape, m_Size0, m_Size1, h); | |||||
} | |||||
float rotY; | float rotY; | ||||
CVector2D origin; | CVector2D origin; | ||||
cmpPosition->GetInterpolatedPosition2D(frameOffset, origin.X, origin.Y, rotY); | cmpPosition->GetInterpolatedPosition2D(frameOffset, origin.X, origin.Y, rotY); | ||||
overlay.m_SimContext = &GetSimContext(); | overlay.m_SimContext = &GetSimContext(); | ||||
overlay.m_Color = m_Color; | overlay.m_Color = m_Color; | ||||
overlay.CreateOverlayTexture(overlayDescriptor); | overlay.CreateOverlayTexture(overlayDescriptor); | ||||
if (fpShape == ICmpFootprint::SQUARE) | if (m_Shape == ICmpSelectable::SQUARE || shape == ICmpFootprint::SQUARE) | ||||
SimRender::ConstructTexturedLineBox(overlay, origin, cmpPosition->GetRotation(), fpSize0_fixed.ToFloat(), fpSize1_fixed.ToFloat()); | SimRender::ConstructTexturedLineBox(overlay, origin, cmpPosition->GetRotation(), m_Size0.ToFloat(), m_Size1.ToFloat()); | ||||
Done Inline Actionsand this Silier: and this | |||||
else | else | ||||
SimRender::ConstructTexturedLineCircle(overlay, origin, fpSize0_fixed.ToFloat()); | SimRender::ConstructTexturedLineCircle(overlay, origin, m_Size0.ToFloat()); | ||||
} | } | ||||
void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) | void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) | ||||
{ | { | ||||
// Dynamic overlay lines are allocated once and never deleted. Since they are expected to change frequently, | // Dynamic overlay lines are allocated once and never deleted. Since they are expected to change frequently, | ||||
// they are assumed dirty on every call to this function, and we should therefore use this function more | // they are assumed dirty on every call to this function, and we should therefore use this function more | ||||
// thoughtfully than calling it right before every frame render. | // thoughtfully than calling it right before every frame render. | ||||
if (m_OverlayDescriptor.m_Type != DYNAMIC_QUAD) | if (m_OverlayDescriptor.m_Type != DYNAMIC_QUAD) | ||||
return; | return; | ||||
if (!CRenderer::IsInitialised()) | if (!CRenderer::IsInitialised()) | ||||
return; | return; | ||||
CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | CmpPtr<ICmpPosition> cmpPosition(GetEntityHandle()); | ||||
if (!cmpPosition || !cmpPosition->IsInWorld()) | |||||
return; | |||||
ICmpFootprint::EShape shape; | |||||
if (m_Shape == ICmpSelectable::NONE) { | |||||
CmpPtr<ICmpFootprint> cmpFootprint(GetEntityHandle()); | CmpPtr<ICmpFootprint> cmpFootprint(GetEntityHandle()); | ||||
if (!cmpFootprint || !cmpPosition || !cmpPosition->IsInWorld()) | if (!cmpFootprint) | ||||
return; | return; | ||||
entity_pos_t h; | |||||
cmpFootprint->GetShape(shape, m_Size0, m_Size1, h); | |||||
} | |||||
float rotY; | float rotY; | ||||
Not Done Inline ActionsYou need to initialise this value: ICmpFootprint::EShape fpShape = ICmpFootprint::CIRCLE; I've tested with a circle outline and it drew a box in your code. I suspect it compiles to a check like "fpShape != 0", and since this will be a random value, it's rather unlikely to be 0. wraitii: You need to initialise this value:
```ICmpFootprint::EShape fpShape = ICmpFootprint::CIRCLE;```… | |||||
CVector2D position; | CVector2D position; | ||||
cmpPosition->GetInterpolatedPosition2D(frameOffset, position.X, position.Y, rotY); | cmpPosition->GetInterpolatedPosition2D(frameOffset, position.X, position.Y, rotY); | ||||
CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity()); | CmpPtr<ICmpWaterManager> cmpWaterManager(GetSystemEntity()); | ||||
CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity()); | CmpPtr<ICmpTerrain> cmpTerrain(GetSystemEntity()); | ||||
ENSURE(cmpWaterManager && cmpTerrain); | ENSURE(cmpWaterManager && cmpTerrain); | ||||
CTerrain* terrain = cmpTerrain->GetCTerrain(); | CTerrain* terrain = cmpTerrain->GetCTerrain(); | ||||
ENSURE(terrain); | 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) | if (!m_UnitOverlay) | ||||
{ | { | ||||
m_UnitOverlay = new SOverlayQuad; | m_UnitOverlay = new SOverlayQuad; | ||||
// Assuming we don't need the capability of swapping textures on-demand. | // Assuming we don't need the capability of swapping textures on-demand. | ||||
CTextureProperties texturePropsBase(m_OverlayDescriptor.m_QuadTexture.c_str()); | CTextureProperties texturePropsBase(m_OverlayDescriptor.m_QuadTexture.c_str()); | ||||
Show All 13 Lines | void CCmpSelectable::UpdateDynamicOverlay(float frameOffset) | ||||
// TODO: some code duplication here :< would be nice to factor out getting the corner points of an | // TODO: some code duplication here :< would be nice to factor out getting the corner points of an | ||||
// entity based on its footprint sizes (and regardless of whether it's a circle or a square) | // entity based on its footprint sizes (and regardless of whether it's a circle or a square) | ||||
float s = sinf(-rotY); | float s = sinf(-rotY); | ||||
float c = cosf(-rotY); | float c = cosf(-rotY); | ||||
CVector2D unitX(c, s); | CVector2D unitX(c, s); | ||||
CVector2D unitZ(-s, c); | CVector2D unitZ(-s, c); | ||||
float halfSizeX = fpSize0_fixed.ToFloat(); | float halfSizeX = m_Size0.ToFloat(); | ||||
float halfSizeZ = fpSize1_fixed.ToFloat(); | float halfSizeZ = m_Size1.ToFloat(); | ||||
if (fpShape == ICmpFootprint::SQUARE) | if (m_Shape == ICmpSelectable::SQUARE || shape == ICmpFootprint::SQUARE) | ||||
Done Inline ActionsMight be worth considering whether they affect simulation and if they don't use float instead of fixed. Stan: Might be worth considering whether they affect simulation and if they don't use float instead… | |||||
Done Inline Actionsactually I should rather fix this if Silier: actually I should rather fix this if | |||||
{ | { | ||||
halfSizeX /= 2.0f; | halfSizeX /= 2.0f; | ||||
halfSizeZ /= 2.0f; | halfSizeZ /= 2.0f; | ||||
} | } | ||||
std::vector<CVector2D> points; | std::vector<CVector2D> points; | ||||
points.push_back(CVector2D(position + unitX *(-halfSizeX) + unitZ * halfSizeZ)); // top left | points.push_back(CVector2D(position + unitX *(-halfSizeX) + unitZ * halfSizeZ)); // top left | ||||
points.push_back(CVector2D(position + unitX *(-halfSizeX) + unitZ *(-halfSizeZ))); // bottom left | points.push_back(CVector2D(position + unitX *(-halfSizeX) + unitZ *(-halfSizeZ))); // bottom left | ||||
▲ Show 20 Lines • Show All 96 Lines • Show Last 20 Lines |
Wildfire Games · Phabricator
Is it really meters?