Fix editor scene persistence and XC scene workflow
This commit is contained in:
@@ -6,6 +6,7 @@ set(COMPONENTS_TEST_SOURCES
|
||||
test_component.cpp
|
||||
test_transform_component.cpp
|
||||
test_game_object.cpp
|
||||
test_camera_light_component.cpp
|
||||
)
|
||||
|
||||
add_executable(components_tests ${COMPONENTS_TEST_SOURCES})
|
||||
@@ -27,4 +28,4 @@ target_include_directories(components_tests PRIVATE
|
||||
)
|
||||
|
||||
include(GoogleTest)
|
||||
gtest_discover_tests(components_tests)
|
||||
gtest_discover_tests(components_tests)
|
||||
|
||||
57
tests/Components/test_camera_light_component.cpp
Normal file
57
tests/Components/test_camera_light_component.cpp
Normal file
@@ -0,0 +1,57 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
#include <XCEngine/Components/LightComponent.h>
|
||||
|
||||
using namespace XCEngine::Components;
|
||||
|
||||
namespace {
|
||||
|
||||
TEST(CameraComponent_Test, DefaultValues) {
|
||||
CameraComponent camera;
|
||||
|
||||
EXPECT_EQ(camera.GetProjectionType(), CameraProjectionType::Perspective);
|
||||
EXPECT_FLOAT_EQ(camera.GetFieldOfView(), 60.0f);
|
||||
EXPECT_FLOAT_EQ(camera.GetOrthographicSize(), 5.0f);
|
||||
EXPECT_FLOAT_EQ(camera.GetNearClipPlane(), 0.1f);
|
||||
EXPECT_FLOAT_EQ(camera.GetFarClipPlane(), 1000.0f);
|
||||
EXPECT_TRUE(camera.IsPrimary());
|
||||
}
|
||||
|
||||
TEST(CameraComponent_Test, SetterClamping) {
|
||||
CameraComponent camera;
|
||||
|
||||
camera.SetFieldOfView(500.0f);
|
||||
camera.SetOrthographicSize(-1.0f);
|
||||
camera.SetNearClipPlane(-10.0f);
|
||||
camera.SetFarClipPlane(0.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(camera.GetFieldOfView(), 179.0f);
|
||||
EXPECT_FLOAT_EQ(camera.GetOrthographicSize(), 0.001f);
|
||||
EXPECT_FLOAT_EQ(camera.GetNearClipPlane(), 0.001f);
|
||||
EXPECT_GT(camera.GetFarClipPlane(), camera.GetNearClipPlane());
|
||||
}
|
||||
|
||||
TEST(LightComponent_Test, DefaultValues) {
|
||||
LightComponent light;
|
||||
|
||||
EXPECT_EQ(light.GetLightType(), LightType::Directional);
|
||||
EXPECT_FLOAT_EQ(light.GetIntensity(), 1.0f);
|
||||
EXPECT_FLOAT_EQ(light.GetRange(), 10.0f);
|
||||
EXPECT_FLOAT_EQ(light.GetSpotAngle(), 30.0f);
|
||||
EXPECT_FALSE(light.GetCastsShadows());
|
||||
}
|
||||
|
||||
TEST(LightComponent_Test, SetterClamping) {
|
||||
LightComponent light;
|
||||
|
||||
light.SetIntensity(-3.0f);
|
||||
light.SetRange(-1.0f);
|
||||
light.SetSpotAngle(500.0f);
|
||||
|
||||
EXPECT_FLOAT_EQ(light.GetIntensity(), 0.0f);
|
||||
EXPECT_FLOAT_EQ(light.GetRange(), 0.001f);
|
||||
EXPECT_FLOAT_EQ(light.GetSpotAngle(), 179.0f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -142,7 +142,7 @@ TEST(GameObject_Test, SetParent_WithoutWorldPosition) {
|
||||
child.SetParent(&parent, false);
|
||||
|
||||
Vector3 childWorldPos = child.GetTransform()->GetPosition();
|
||||
EXPECT_NEAR(childWorldPos.x, 2.0f, 0.001f);
|
||||
EXPECT_NEAR(childWorldPos.x, 3.0f, 0.001f);
|
||||
}
|
||||
|
||||
TEST(GameObject_Test, GetChild_ValidIndex) {
|
||||
@@ -275,4 +275,4 @@ TEST(GameObject_Test, GetChildCount) {
|
||||
EXPECT_EQ(parent.GetChildCount(), 2u);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <XCEngine/Scene/Scene.h>
|
||||
#include <XCEngine/Components/CameraComponent.h>
|
||||
#include <XCEngine/Components/GameObject.h>
|
||||
#include <XCEngine/Components/LightComponent.h>
|
||||
#include <XCEngine/Components/TransformComponent.h>
|
||||
#include <XCEngine/Core/Math/Vector3.h>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
|
||||
@@ -36,6 +39,10 @@ protected:
|
||||
testScene = std::make_unique<Scene>("TestScene");
|
||||
}
|
||||
|
||||
std::filesystem::path GetTempScenePath(const char* fileName) const {
|
||||
return std::filesystem::temp_directory_path() / fileName;
|
||||
}
|
||||
|
||||
std::unique_ptr<Scene> testScene;
|
||||
};
|
||||
|
||||
@@ -222,30 +229,128 @@ TEST_F(SceneTest, Save_And_Load) {
|
||||
GameObject* go = testScene->CreateGameObject("SavedObject");
|
||||
go->GetTransform()->SetLocalPosition(XCEngine::Math::Vector3(1.0f, 2.0f, 3.0f));
|
||||
go->SetActive(true);
|
||||
|
||||
testScene->Save("test_scene.scene");
|
||||
|
||||
|
||||
const std::filesystem::path scenePath = GetTempScenePath("test_scene.xc");
|
||||
testScene->Save(scenePath.string());
|
||||
|
||||
Scene loadedScene;
|
||||
loadedScene.Load("test_scene.scene");
|
||||
|
||||
loadedScene.Load(scenePath.string());
|
||||
|
||||
GameObject* loadedGo = loadedScene.Find("SavedObject");
|
||||
EXPECT_NE(loadedGo, nullptr);
|
||||
EXPECT_EQ(loadedGo->GetTransform()->GetLocalPosition(), XCEngine::Math::Vector3(1.0f, 2.0f, 3.0f));
|
||||
|
||||
std::filesystem::remove(scenePath);
|
||||
}
|
||||
|
||||
TEST_F(SceneTest, Save_ContainsGameObjectData) {
|
||||
testScene->CreateGameObject("Player");
|
||||
testScene->CreateGameObject("Enemy");
|
||||
|
||||
testScene->Save("test_scene_multi.scene");
|
||||
|
||||
std::ifstream file("test_scene_multi.scene");
|
||||
|
||||
const std::filesystem::path scenePath = GetTempScenePath("test_scene_multi.xc");
|
||||
testScene->Save(scenePath.string());
|
||||
|
||||
std::ifstream file(scenePath);
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
std::string content = buffer.str();
|
||||
|
||||
file.close();
|
||||
|
||||
EXPECT_TRUE(content.find("Player") != std::string::npos);
|
||||
EXPECT_TRUE(content.find("Enemy") != std::string::npos);
|
||||
|
||||
std::filesystem::remove(scenePath);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
TEST_F(SceneTest, Save_And_Load_PreservesHierarchyAndComponents) {
|
||||
testScene->SetName("Serialized Scene");
|
||||
testScene->SetActive(false);
|
||||
|
||||
GameObject* parent = testScene->CreateGameObject("Rig Root");
|
||||
parent->GetTransform()->SetLocalPosition(Vector3(5.0f, 0.0f, 0.0f));
|
||||
parent->SetActive(false);
|
||||
|
||||
auto* light = parent->AddComponent<LightComponent>();
|
||||
light->SetLightType(LightType::Spot);
|
||||
light->SetIntensity(3.5f);
|
||||
light->SetRange(12.0f);
|
||||
light->SetSpotAngle(45.0f);
|
||||
light->SetCastsShadows(true);
|
||||
|
||||
GameObject* child = testScene->CreateGameObject("Main Camera", parent);
|
||||
child->GetTransform()->SetLocalPosition(Vector3(1.0f, 2.0f, 3.0f));
|
||||
child->GetTransform()->SetLocalScale(Vector3(2.0f, 2.0f, 2.0f));
|
||||
|
||||
auto* camera = child->AddComponent<CameraComponent>();
|
||||
camera->SetProjectionType(CameraProjectionType::Orthographic);
|
||||
camera->SetOrthographicSize(7.5f);
|
||||
camera->SetNearClipPlane(0.5f);
|
||||
camera->SetFarClipPlane(250.0f);
|
||||
camera->SetDepth(2.0f);
|
||||
camera->SetPrimary(false);
|
||||
|
||||
const std::filesystem::path scenePath = GetTempScenePath("test_scene_hierarchy_components.xc");
|
||||
testScene->Save(scenePath.string());
|
||||
|
||||
Scene loadedScene;
|
||||
loadedScene.Load(scenePath.string());
|
||||
|
||||
EXPECT_EQ(loadedScene.GetName(), "Serialized Scene");
|
||||
EXPECT_FALSE(loadedScene.IsActive());
|
||||
|
||||
GameObject* loadedParent = loadedScene.Find("Rig Root");
|
||||
GameObject* loadedChild = loadedScene.Find("Main Camera");
|
||||
ASSERT_NE(loadedParent, nullptr);
|
||||
ASSERT_NE(loadedChild, nullptr);
|
||||
|
||||
EXPECT_EQ(loadedChild->GetParent(), loadedParent);
|
||||
EXPECT_EQ(loadedScene.GetRootGameObjects().size(), 1u);
|
||||
EXPECT_FALSE(loadedParent->IsActive());
|
||||
EXPECT_EQ(loadedParent->GetTransform()->GetLocalPosition(), Vector3(5.0f, 0.0f, 0.0f));
|
||||
EXPECT_EQ(loadedChild->GetTransform()->GetLocalPosition(), Vector3(1.0f, 2.0f, 3.0f));
|
||||
EXPECT_EQ(loadedChild->GetTransform()->GetPosition(), Vector3(6.0f, 2.0f, 3.0f));
|
||||
|
||||
auto* loadedLight = loadedParent->GetComponent<LightComponent>();
|
||||
ASSERT_NE(loadedLight, nullptr);
|
||||
EXPECT_EQ(loadedLight->GetLightType(), LightType::Spot);
|
||||
EXPECT_FLOAT_EQ(loadedLight->GetIntensity(), 3.5f);
|
||||
EXPECT_FLOAT_EQ(loadedLight->GetRange(), 12.0f);
|
||||
EXPECT_FLOAT_EQ(loadedLight->GetSpotAngle(), 45.0f);
|
||||
EXPECT_TRUE(loadedLight->GetCastsShadows());
|
||||
|
||||
auto* loadedCamera = loadedChild->GetComponent<CameraComponent>();
|
||||
ASSERT_NE(loadedCamera, nullptr);
|
||||
EXPECT_EQ(loadedCamera->GetProjectionType(), CameraProjectionType::Orthographic);
|
||||
EXPECT_FLOAT_EQ(loadedCamera->GetOrthographicSize(), 7.5f);
|
||||
EXPECT_FLOAT_EQ(loadedCamera->GetNearClipPlane(), 0.5f);
|
||||
EXPECT_FLOAT_EQ(loadedCamera->GetFarClipPlane(), 250.0f);
|
||||
EXPECT_FLOAT_EQ(loadedCamera->GetDepth(), 2.0f);
|
||||
EXPECT_FALSE(loadedCamera->IsPrimary());
|
||||
|
||||
std::filesystem::remove(scenePath);
|
||||
}
|
||||
|
||||
TEST_F(SceneTest, Save_ContainsHierarchyAndComponentEntries) {
|
||||
GameObject* parent = testScene->CreateGameObject("Parent");
|
||||
GameObject* child = testScene->CreateGameObject("Child", parent);
|
||||
child->AddComponent<CameraComponent>();
|
||||
parent->AddComponent<LightComponent>();
|
||||
|
||||
const std::filesystem::path scenePath = GetTempScenePath("test_scene_format.xc");
|
||||
testScene->Save(scenePath.string());
|
||||
|
||||
std::ifstream file(scenePath);
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
const std::string content = buffer.str();
|
||||
file.close();
|
||||
|
||||
EXPECT_TRUE(content.find("gameobject_begin") != std::string::npos);
|
||||
EXPECT_TRUE(content.find("parent=" + std::to_string(parent->GetID())) != std::string::npos);
|
||||
EXPECT_TRUE(content.find("component=Camera;") != std::string::npos);
|
||||
EXPECT_TRUE(content.find("component=Light;") != std::string::npos);
|
||||
|
||||
std::filesystem::remove(scenePath);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Reference in New Issue
Block a user