This Trac instance is not used for development anymore!

We migrated our development workflow to git and Gitea.
To test the future redirection, replace trac by ariadne in the page URL.

source: ps/trunk/source/simulation2/components/tests/test_Position.h

Last change on this file was 27965, checked in by Vladislav Belov, 13 months ago

Revert non-ASCII characters from source and configuration files introduced in rP27786.

Fixes #6846

Differential Revision: https://code.wildfiregames.com/D5185

  • Property svn:eol-style set to native
File size: 8.9 KB
Line 
1/* Copyright (C) 2023 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include "simulation2/system/ComponentTest.h"
19
20#include "maths/Matrix3D.h"
21#include "simulation2/components/ICmpPosition.h"
22#include "simulation2/components/ICmpWaterManager.h"
23
24class MockWater : public ICmpWaterManager
25{
26public:
27 DEFAULT_MOCK_COMPONENT()
28
29 entity_pos_t GetWaterLevel(entity_pos_t UNUSED(x), entity_pos_t UNUSED(z)) const override
30 {
31 return entity_pos_t::FromInt(100);
32 }
33
34 float GetExactWaterLevel(float UNUSED(x), float UNUSED(z)) const override
35 {
36 return 100.f;
37 }
38
39 void RecomputeWaterData() override
40 {
41 }
42
43 void SetWaterLevel(entity_pos_t UNUSED(h)) override
44 {
45 }
46};
47
48class TestCmpPosition : public CxxTest::TestSuite
49{
50public:
51 void setUp()
52 {
53 CXeromyces::Startup();
54 }
55
56 void tearDown()
57 {
58 CXeromyces::Terminate();
59 }
60
61 static CFixedVector3D fixedvec(int x, int y, int z)
62 {
63 return CFixedVector3D(fixed::FromInt(x), fixed::FromInt(y), fixed::FromInt(z));
64 }
65
66 void test_basic()
67 {
68 ComponentTestHelper test(*g_ScriptContext);
69
70 MockTerrain terrain;
71 test.AddMock(SYSTEM_ENTITY, IID_Terrain, terrain);
72
73 ICmpPosition* cmp = test.Add<ICmpPosition>(CID_Position, "<Anchor>upright</Anchor><Altitude>23</Altitude><Floating>false</Floating>");
74
75 // Defaults
76 TS_ASSERT(!cmp->IsInWorld());
77 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(23));
78 TS_ASSERT_EQUALS(cmp->GetRotation(), fixedvec(0, 0, 0));
79
80 // Change height offset
81 cmp->SetHeightOffset(entity_pos_t::FromInt(10));
82 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(10));
83
84 // Move out of world, while currently out of world
85 cmp->MoveOutOfWorld();
86 TS_ASSERT(!cmp->IsInWorld());
87
88 // Jump into world
89 cmp->JumpTo(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0));
90 TS_ASSERT(cmp->IsInWorld());
91 // Move out of world, while currently in world
92 cmp->MoveOutOfWorld();
93 TS_ASSERT(!cmp->IsInWorld());
94
95 // Move into world
96 cmp->MoveTo(entity_pos_t::FromInt(100), entity_pos_t::FromInt(200));
97 TS_ASSERT(cmp->IsInWorld());
98 // Position computed from move plus terrain
99 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 60, 200));
100 // Interpolated position should be constant
101 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(100, 60, 200));
102 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(100, 60, 200));
103 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(100, 60, 200));
104
105 // No TurnStart message, so this move doesn't affect the interpolation
106 cmp->MoveTo(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0));
107 // Move smoothly to new position
108 cmp->MoveTo(entity_pos_t::FromInt(200), entity_pos_t::FromInt(0));
109 // Position computed from move plus terrain
110 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(200, 60, 0));
111 // Interpolated position should vary, from original move into world to new move
112 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(100, 60, 200));
113 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(150, 60, 100));
114 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(200, 60, 0));
115
116 // Latch new position for interpolation
117 CMessageTurnStart msg;
118 test.HandleMessage(cmp, msg, false);
119
120 // Move smoothly to new position
121 cmp->MoveTo(entity_pos_t::FromInt(400), entity_pos_t::FromInt(300));
122 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(200, 60, 0));
123 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(300, 60, 150));
124 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(400, 60, 300));
125
126 // Jump to new position
127 cmp->JumpTo(entity_pos_t::FromInt(300), entity_pos_t::FromInt(100));
128 // Position computed from jump plus terrain
129 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(300, 60, 100));
130 // Interpolated position should be constant after jump
131 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(300, 60, 100));
132 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(300, 60, 100));
133 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(300, 60, 100));
134
135 // TODO: Test the rotation methods
136 }
137
138 void test_water()
139 {
140 ComponentTestHelper test(*g_ScriptContext);
141
142 MockTerrain terrain;
143 test.AddMock(SYSTEM_ENTITY, IID_Terrain, terrain);
144
145 MockWater water;
146 test.AddMock(SYSTEM_ENTITY, IID_WaterManager, water);
147
148 ICmpPosition* cmp = test.Add<ICmpPosition>(CID_Position, "<Anchor>upright</Anchor><Altitude>23</Altitude><Floating>true</Floating><FloatDepth>1</FloatDepth>");
149
150 // Move into the world, the fixed height uses the water level minus the float depth as a base
151 cmp->JumpTo(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0));
152 TS_ASSERT(cmp->IsInWorld());
153 TS_ASSERT(cmp->CanFloat());
154 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(23));
155 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(122));
156
157 // Change height offset, the fixed height changes too
158 cmp->SetHeightOffset(entity_pos_t::FromInt(11));
159 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(11));
160 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(110));
161 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(0, 110, 0));
162
163 // Move
164 cmp->MoveTo(entity_pos_t::FromInt(100), entity_pos_t::FromInt(200));
165 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(0, 122, 0));
166 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(50, 116, 100));
167 TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(100, 110, 200));
168
169 // Change fixed height, the height offset changes too
170 cmp->SetHeightFixed(entity_pos_t::FromInt(122));
171 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(122));
172 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(23));
173 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 122, 200));
174
175 // The entity can't float anymore, the fixed height is computed from the terrain base
176 cmp->SetFloating(false);
177 TS_ASSERT(!cmp->CanFloat());
178 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(73));
179 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(23));
180 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 73, 200));
181
182 // The entity can float again
183 cmp->SetFloating(true);
184 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(122));
185 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(23));
186 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 122, 200));
187
188 // Use non relative height, entity will not follow terrain/water height.
189 TS_ASSERT(cmp->IsHeightRelative());
190 cmp->SetHeightRelative(false);
191 TS_ASSERT(!cmp->IsHeightRelative());
192
193 cmp->SetHeightOffset(entity_pos_t::FromInt(11));
194 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(11));
195 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(110));
196 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 110, 200));
197
198 cmp->SetHeightFixed(entity_pos_t::FromInt(122));
199 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(122));
200 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(23));
201 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 122, 200));
202
203 // The entity can't float anymore and height is not relative, fixed height doesn't change
204 cmp->SetFloating(false);
205 TS_ASSERT(!cmp->CanFloat());
206 TS_ASSERT_EQUALS(cmp->GetHeightFixed(), entity_pos_t::FromInt(122));
207 TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(72));
208 TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 122, 200));
209 }
210
211 void test_serialize()
212 {
213 ComponentTestHelper test(*g_ScriptContext);
214
215 MockTerrain terrain;
216 test.AddMock(SYSTEM_ENTITY, IID_Terrain, terrain);
217
218 ICmpPosition* cmp = test.Add<ICmpPosition>(CID_Position, "<Anchor>upright</Anchor><Altitude>5</Altitude><Floating>false</Floating>");
219
220 test.Roundtrip();
221
222 cmp->SetHeightOffset(entity_pos_t::FromInt(20));
223 cmp->SetXZRotation(entity_angle_t::FromInt(1), entity_angle_t::FromInt(2));
224 cmp->SetYRotation(entity_angle_t::FromInt(3));
225
226 test.Roundtrip();
227
228 cmp->JumpTo(entity_pos_t::FromInt(10), entity_pos_t::FromInt(20));
229 cmp->MoveTo(entity_pos_t::FromInt(123), entity_pos_t::FromInt(456));
230
231 test.Roundtrip();
232 }
233};
Note: See TracBrowser for help on using the repository browser.