/* Copyright (C) 2010 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 "simulation2/system/ComponentTest.h"
#include "simulation2/components/ICmpPosition.h"
class TestCmpPosition : public CxxTest::TestSuite
{
public:
void setUp()
{
CXeromyces::Startup();
}
void tearDown()
{
CXeromyces::Terminate();
}
static CFixedVector3D fixedvec(int x, int y, int z)
{
return CFixedVector3D(fixed::FromInt(x), fixed::FromInt(y), fixed::FromInt(z));
}
void test_basic()
{
ComponentTestHelper test(g_ScriptRuntime);
MockTerrain terrain;
test.AddMock(SYSTEM_ENTITY, IID_Terrain, terrain);
ICmpPosition* cmp = test.Add(CID_Position, "upright23false");
// Defaults
TS_ASSERT(!cmp->IsInWorld());
TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(23));
TS_ASSERT_EQUALS(cmp->GetRotation(), fixedvec(0, 0, 0));
// Change height offset
cmp->SetHeightOffset(entity_pos_t::FromInt(10));
TS_ASSERT_EQUALS(cmp->GetHeightOffset(), entity_pos_t::FromInt(10));
// Move out of world, while currently out of world
cmp->MoveOutOfWorld();
TS_ASSERT(!cmp->IsInWorld());
// Jump into world
cmp->JumpTo(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0));
TS_ASSERT(cmp->IsInWorld());
// Move out of world, while currently in world
cmp->MoveOutOfWorld();
TS_ASSERT(!cmp->IsInWorld());
// Move into world
cmp->MoveTo(entity_pos_t::FromInt(100), entity_pos_t::FromInt(200));
TS_ASSERT(cmp->IsInWorld());
// Position computed from move plus terrain
TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(100, 60, 200));
// Interpolated position should be constant
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(100, 60, 200));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(100, 60, 200));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(100, 60, 200));
// No TurnStart message, so this move doesn't affect the interpolation
cmp->MoveTo(entity_pos_t::FromInt(0), entity_pos_t::FromInt(0));
// Move smoothly to new position
cmp->MoveTo(entity_pos_t::FromInt(200), entity_pos_t::FromInt(0));
// Position computed from move plus terrain
TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(200, 60, 0));
// Interpolated position should vary, from original move into world to new move
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(100, 60, 200));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(150, 60, 100));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(200, 60, 0));
// Latch new position for interpolation
CMessageTurnStart msg;
test.HandleMessage(cmp, msg, false);
// Move smoothly to new position
cmp->MoveTo(entity_pos_t::FromInt(400), entity_pos_t::FromInt(300));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(200, 60, 0));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(300, 60, 150));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(400, 60, 300));
// Jump to new position
cmp->JumpTo(entity_pos_t::FromInt(300), entity_pos_t::FromInt(100));
// Position computed from jump plus terrain
TS_ASSERT_EQUALS(cmp->GetPosition(), fixedvec(300, 60, 100));
// Interpolated position should be constant after jump
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.0f).GetTranslation(), CVector3D(300, 60, 100));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(0.5f).GetTranslation(), CVector3D(300, 60, 100));
TS_ASSERT_EQUALS(cmp->GetInterpolatedTransform(1.0f).GetTranslation(), CVector3D(300, 60, 100));
// TODO: Test the rotation methods
}
void test_serialize()
{
ComponentTestHelper test(g_ScriptRuntime);
MockTerrain terrain;
test.AddMock(SYSTEM_ENTITY, IID_Terrain, terrain);
ICmpPosition* cmp = test.Add(CID_Position, "upright5false");
test.Roundtrip();
cmp->SetHeightOffset(entity_pos_t::FromInt(20));
cmp->SetXZRotation(entity_angle_t::FromInt(1), entity_angle_t::FromInt(2));
cmp->SetYRotation(entity_angle_t::FromInt(3));
test.Roundtrip();
cmp->JumpTo(entity_pos_t::FromInt(10), entity_pos_t::FromInt(20));
cmp->MoveTo(entity_pos_t::FromInt(123), entity_pos_t::FromInt(456));
test.Roundtrip();
}
};