From 5ae9f678b0798b1d2fb4c3e40328895c578ef239 Mon Sep 17 00:00:00 2001 From: sanderd17 Date: Mon, 26 May 2014 16:23:46 +0000 Subject: [PATCH] Clean up position height methods + add new. Now we have the ability to losslessly read and write positions to entities from the scripts. This was SVN commit r15230. --- .../simulation2/components/CCmpPosition.cpp | 160 ++++++++++-------- .../simulation2/components/ICmpPosition.cpp | 4 + source/simulation2/components/ICmpPosition.h | 24 ++- .../components/tests/test_RangeManager.h | 4 + 4 files changed, 116 insertions(+), 76 deletions(-) diff --git a/source/simulation2/components/CCmpPosition.cpp b/source/simulation2/components/CCmpPosition.cpp index b32cae6fbd..83379ff1a2 100644 --- a/source/simulation2/components/CCmpPosition.cpp +++ b/source/simulation2/components/CCmpPosition.cpp @@ -72,8 +72,9 @@ public: // m_LastX/Z contain the position from the start of the most recent turn // m_PrevX/Z conatain the position from the turn before that entity_pos_t m_X, m_Z, m_LastX, m_LastZ, m_PrevX, m_PrevZ; // these values contain undefined junk if !InWorld - entity_pos_t m_YOffset, m_LastYOffset; - bool m_RelativeToGround; // whether m_YOffset is relative to terrain/water plane, or an absolute height + + entity_pos_t m_Y, m_LastYDifference; // either the relative or the absolute Y coordinate + bool m_RelativeToGround; // whether m_Y is relative to terrain/water plane, or an absolute height entity_angle_t m_RotX, m_RotY, m_RotZ; @@ -128,7 +129,8 @@ public: m_InWorld = false; - m_LastYOffset = m_YOffset = paramNode.GetChild("Altitude").ToFixed(); + m_LastYDifference = entity_pos_t::Zero(); + m_Y = paramNode.GetChild("Altitude").ToFixed(); m_RelativeToGround = true; m_Floating = paramNode.GetChild("Floating").ToBool(); @@ -152,16 +154,19 @@ public: if (m_InWorld) { serialize.NumberFixed_Unbounded("x", m_X); + serialize.NumberFixed_Unbounded("y", m_Y); serialize.NumberFixed_Unbounded("z", m_Z); serialize.NumberFixed_Unbounded("last x", m_LastX); + serialize.NumberFixed_Unbounded("last y diff", m_LastYDifference); serialize.NumberFixed_Unbounded("last z", m_LastZ); } serialize.NumberI32_Unbounded("territory", m_Territory); serialize.NumberFixed_Unbounded("rot x", m_RotX); serialize.NumberFixed_Unbounded("rot y", m_RotY); serialize.NumberFixed_Unbounded("rot z", m_RotZ); - serialize.NumberFixed_Unbounded("altitude", m_YOffset); + serialize.NumberFixed_Unbounded("altitude", m_Y); serialize.Bool("relative", m_RelativeToGround); + serialize.Bool("floating", m_Floating); if (serialize.IsDebug()) { @@ -186,7 +191,6 @@ public: break; } serialize.StringASCII("anchor", anchor, 0, 16); - serialize.Bool("floating", m_Floating); } } @@ -198,20 +202,22 @@ public: if (m_InWorld) { deserialize.NumberFixed_Unbounded("x", m_X); + deserialize.NumberFixed_Unbounded("y", m_Y); deserialize.NumberFixed_Unbounded("z", m_Z); deserialize.NumberFixed_Unbounded("last x", m_LastX); + deserialize.NumberFixed_Unbounded("last y diff", m_LastYDifference); deserialize.NumberFixed_Unbounded("last z", m_LastZ); } deserialize.NumberI32_Unbounded("territory", m_Territory); deserialize.NumberFixed_Unbounded("rot x", m_RotX); deserialize.NumberFixed_Unbounded("rot y", m_RotY); deserialize.NumberFixed_Unbounded("rot z", m_RotZ); - deserialize.NumberFixed_Unbounded("altitude", m_YOffset); + deserialize.NumberFixed_Unbounded("altitude", m_Y); deserialize.Bool("relative", m_RelativeToGround); + deserialize.Bool("floating", m_Floating); // TODO: should there be range checks on all these values? m_InterpolatedRotY = m_RotY.ToFloat(); - m_LastYOffset = m_YOffset; if (m_InWorld) UpdateXZRotation(); @@ -239,7 +245,7 @@ public: m_InWorld = true; m_LastX = m_PrevX = m_X; m_LastZ = m_PrevZ = m_Z; - m_LastYOffset = m_YOffset; + m_LastYDifference = entity_pos_t::Zero(); } AdvertisePositionChanges(); @@ -256,7 +262,7 @@ public: m_InWorld = true; m_LastX = m_PrevX = m_X; m_LastZ = m_PrevZ = m_Z; - m_LastYOffset = m_YOffset; + m_LastYDifference = entity_pos_t::Zero(); } AdvertisePositionChanges(); @@ -278,37 +284,69 @@ public: virtual void SetHeightOffset(entity_pos_t dy) { - if (m_RelativeToGround) - { - m_LastYOffset = m_YOffset; - m_YOffset = dy; - } - else - { - m_LastYOffset = m_YOffset = dy; - m_RelativeToGround = true; - } - + // subtract the offset and replace with a new offset + m_LastYDifference = dy - GetHeightOffset(); + m_Y += m_LastYDifference; AdvertisePositionChanges(); } virtual entity_pos_t GetHeightOffset() { - return m_YOffset; + if (m_RelativeToGround) + return m_Y; + // not relative to the ground, so the height offset is m_Y - ground height + entity_pos_t baseY; + CmpPtr cmpTerrain(GetSystemEntity()); + if (cmpTerrain) + baseY = cmpTerrain->GetGroundLevel(m_X, m_Z); + + if (m_Floating) + { + CmpPtr cmpWaterManager(GetSystemEntity()); + if (cmpWaterManager) + baseY = std::max(baseY, cmpWaterManager->GetWaterLevel(m_X, m_Z)); + } + return m_Y - baseY; } virtual void SetHeightFixed(entity_pos_t y) { - if (m_RelativeToGround) + // subtract the absolute height and replace it with a new absolute height + m_LastYDifference = y - GetHeightFixed(); + m_Y += m_LastYDifference; + AdvertisePositionChanges(); + } + + virtual entity_pos_t GetHeightFixed() + { + if (!m_RelativeToGround) + return m_Y; + // relative to the ground, so the fixed height = ground height + m_Y + entity_pos_t baseY; + CmpPtr cmpTerrain(GetSystemEntity()); + if (cmpTerrain) + baseY = cmpTerrain->GetGroundLevel(m_X, m_Z); + + if (m_Floating) { - m_LastYOffset = m_YOffset = y; - m_RelativeToGround = false; - } - else - { - m_LastYOffset = m_YOffset; - m_YOffset = y; + CmpPtr cmpWaterManager(GetSystemEntity()); + if (cmpWaterManager) + baseY = std::max(baseY, cmpWaterManager->GetWaterLevel(m_X, m_Z)); } + return m_Y + baseY; + } + + virtual bool IsHeightRelative() + { + return m_RelativeToGround; + } + + virtual void SetHeightRelative(bool relative) + { + // move y to use the right offset (from terrain or from map origin) + m_Y = relative ? GetHeightOffset() : GetHeightFixed(); + m_RelativeToGround = relative; + m_LastYDifference = entity_pos_t::Zero(); } virtual bool IsFloating() @@ -316,6 +354,11 @@ public: return m_Floating; } + virtual void SetFloating(bool flag) + { + m_Floating = flag; + } + virtual CFixedVector3D GetPosition() { if (!m_InWorld) @@ -324,22 +367,7 @@ public: return CFixedVector3D(); } - entity_pos_t baseY; - if (m_RelativeToGround) - { - CmpPtr cmpTerrain(GetSystemEntity()); - if (cmpTerrain) - baseY = cmpTerrain->GetGroundLevel(m_X, m_Z); - - if (m_Floating) - { - CmpPtr cmpWaterManager(GetSystemEntity()); - if (cmpWaterManager) - baseY = std::max(baseY, cmpWaterManager->GetWaterLevel(m_X, m_Z)); - } - } - - return CFixedVector3D(m_X, baseY + m_YOffset, m_Z); + return CFixedVector3D(m_X, GetHeightFixed(), m_Z); } virtual CFixedVector2D GetPosition2D() @@ -361,22 +389,7 @@ public: return CFixedVector3D(); } - entity_pos_t baseY; - if (m_RelativeToGround) - { - CmpPtr cmpTerrain(GetSystemEntity()); - if (cmpTerrain) - baseY = cmpTerrain->GetGroundLevel(m_PrevX, m_PrevZ); - - if (m_Floating) - { - CmpPtr cmpWaterMan(GetSystemEntity()); - if (cmpWaterMan) - baseY = std::max(baseY, cmpWaterMan->GetWaterLevel(m_PrevX, m_PrevZ)); - } - } - - return CFixedVector3D(m_PrevX, baseY + m_YOffset, m_PrevZ); + return CFixedVector3D(m_PrevX, GetHeightFixed(), m_PrevZ); } virtual CFixedVector2D GetPreviousPosition2D() @@ -472,23 +485,22 @@ public: float x, z, rotY; GetInterpolatedPosition2D(frameOffset, x, z, rotY); - float baseY = 0; - if (m_RelativeToGround) - { - CmpPtr cmpTerrain(GetSystemEntity()); - if (cmpTerrain) - baseY = cmpTerrain->GetExactGroundLevel(x, z); + float y = GetHeightFixed().ToFloat() + Interpolate(0.f, m_LastYDifference.ToFloat(), frameOffset); - if (m_Floating || forceFloating) + if (forceFloating) + { + // if the actor has a flag, it shouldn't be serialized, + // so it's handled here separately + CmpPtr cmpTerrain(GetSystemEntity()); + CmpPtr cmpWaterManager(GetSystemEntity()); + if (cmpTerrain && cmpWaterManager) { - CmpPtr cmpWaterManager(GetSystemEntity()); - if (cmpWaterManager) - baseY = std::max(baseY, cmpWaterManager->GetExactWaterLevel(x, z)); + float diff = (cmpWaterManager->GetWaterLevel(m_X, m_Z) - cmpTerrain->GetGroundLevel(m_X, m_Z)).ToFloat(); + if (diff > 0.f) + y += diff; } } - float y = baseY + Interpolate(m_LastYOffset.ToFloat(), m_YOffset.ToFloat(), frameOffset); - CMatrix3D m; // linear interpolation is good enough (for RotX/Z). @@ -560,7 +572,7 @@ public: m_LastX = m_X; m_LastZ = m_Z; - m_LastYOffset = m_YOffset; + m_LastYDifference = entity_pos_t::Zero(); // warn when a position change also causes a territory change under the entity diff --git a/source/simulation2/components/ICmpPosition.cpp b/source/simulation2/components/ICmpPosition.cpp index c310d845e4..ab61fb944d 100644 --- a/source/simulation2/components/ICmpPosition.cpp +++ b/source/simulation2/components/ICmpPosition.cpp @@ -30,7 +30,11 @@ DEFINE_INTERFACE_METHOD_2("JumpTo", void, ICmpPosition, JumpTo, entity_pos_t, en DEFINE_INTERFACE_METHOD_1("SetHeightOffset", void, ICmpPosition, SetHeightOffset, entity_pos_t) DEFINE_INTERFACE_METHOD_0("GetHeightOffset", entity_pos_t, ICmpPosition, GetHeightOffset) DEFINE_INTERFACE_METHOD_1("SetHeightFixed", void, ICmpPosition, SetHeightFixed, entity_pos_t) +DEFINE_INTERFACE_METHOD_0("GetHeightFixed", entity_pos_t, ICmpPosition, GetHeightFixed) +DEFINE_INTERFACE_METHOD_0("IsHeightRelative", bool, ICmpPosition, IsHeightRelative) +DEFINE_INTERFACE_METHOD_1("SetHeightRelative", void, ICmpPosition, SetHeightRelative, bool) DEFINE_INTERFACE_METHOD_0("IsFloating", bool, ICmpPosition, IsFloating) +DEFINE_INTERFACE_METHOD_1("SetFloating", void, ICmpPosition, SetFloating, bool) DEFINE_INTERFACE_METHOD_0("GetPosition", CFixedVector3D, ICmpPosition, GetPosition) DEFINE_INTERFACE_METHOD_0("GetPosition2D", CFixedVector2D, ICmpPosition, GetPosition2D) DEFINE_INTERFACE_METHOD_0("GetPreviousPosition", CFixedVector3D, ICmpPosition, GetPreviousPosition) diff --git a/source/simulation2/components/ICmpPosition.h b/source/simulation2/components/ICmpPosition.h index ba95ff8505..11eb608622 100644 --- a/source/simulation2/components/ICmpPosition.h +++ b/source/simulation2/components/ICmpPosition.h @@ -94,16 +94,36 @@ public: virtual entity_pos_t GetHeightOffset() = 0; /** - * Set the vertical position as a fixed, absolute value. - * Will stay at this height until the next call to SetHeightFixed or SetHeightOffset. + * Set the vertical position above the map zero point */ virtual void SetHeightFixed(entity_pos_t y) = 0; + /** + * Returns the vertical offset above the map zero point + */ + virtual entity_pos_t GetHeightFixed() = 0; + + /** + * Returns true iff the entity will follow the terrain height (possibly with an offset) + */ + virtual bool IsHeightRelative() = 0; + + /** + * When set to true, the entity will follow the terrain height (possibly with an offset) + * When set to false, it's height won't change automatically + */ + virtual void SetHeightRelative(bool flag) = 0; + /** * Returns whether the entity floats on water. */ virtual bool IsFloating() = 0; + /** + * Set the entity to float on water + */ + virtual void SetFloating(bool flag) = 0; + /** * Returns the current x,y,z position (no interpolation). * Depends on the current terrain heightmap. diff --git a/source/simulation2/components/tests/test_RangeManager.h b/source/simulation2/components/tests/test_RangeManager.h index 3c03dcffc4..1d83485a08 100644 --- a/source/simulation2/components/tests/test_RangeManager.h +++ b/source/simulation2/components/tests/test_RangeManager.h @@ -48,7 +48,11 @@ public: virtual void SetHeightOffset(entity_pos_t UNUSED(dy)) { } virtual entity_pos_t GetHeightOffset() { return entity_pos_t::Zero(); } virtual void SetHeightFixed(entity_pos_t UNUSED(y)) { } + virtual entity_pos_t GetHeightFixed() { return entity_pos_t::Zero(); } + virtual bool IsHeightRelative() { return true; } + virtual void SetHeightRelative(bool UNUSED(relative)) { } virtual bool IsFloating() { return false; } + virtual void SetFloating(bool UNUSED(flag)) { } virtual CFixedVector3D GetPosition() { return CFixedVector3D(); } virtual CFixedVector2D GetPosition2D() { return CFixedVector2D(); } virtual CFixedVector3D GetPreviousPosition() { return CFixedVector3D(); }