Files
simian/tests/scenegraph_tests.cpp
T
nick 5367b31f4e
CI / build-and-test (push) Failing after 2m9s
Sync Docs to Gitea Wiki / Sync docs to Gitea wiki (push) Failing after 23s
chore: fixing CI
2026-03-08 16:04:38 +13:00

171 lines
5.0 KiB
C++

#define TEST_NO_MAIN
#include "acutest.h"
#include <filesystem>
#include <fstream>
#include <cstdlib>
#include "../include/ECSComponents.h"
#include "../include/SceneGraph.h"
#include "../include/SceneLoader.h"
#include "../include/ModelManager.h"
#include "../include/ShaderManager.h"
#include "raylib.h"
#include "entt.hpp"
static bool HasDisplay() {
#if defined(_WIN32)
return true;
#elif defined(__APPLE__)
return true;
#else
const char* display = std::getenv("DISPLAY");
const char* wayland = std::getenv("WAYLAND_DISPLAY");
return (display && *display) || (wayland && *wayland);
#endif
}
static bool InitRaylibHidden() {
const char* forceHeadless = std::getenv("SIMIAN_HEADLESS");
if (forceHeadless && forceHeadless[0] == '1') {
return false;
}
if (!HasDisplay()) {
return false;
}
if (!IsWindowReady()) {
SetConfigFlags(FLAG_WINDOW_HIDDEN);
InitWindow(1, 1, "simian_test_scene");
SetTargetFPS(60);
}
return IsWindowReady();
}
static void ShutdownRaylibHidden() {
if (IsWindowReady()) {
CloseWindow();
}
}
void test_scenegraph_world_transform(void) {
entt::registry registry;
entt::entity parent = registry.create();
entt::entity child = registry.create();
registry.emplace<ECSTransform>(parent, Vector3{1.0f, 0.0f, 0.0f}, Vector3{2.0f, 2.0f, 2.0f}, 0.0f);
registry.emplace<ECSTransform>(child, Vector3{1.0f, 0.0f, 0.0f}, Vector3{1.0f, 1.0f, 1.0f}, 0.0f);
AttachChild(registry, child, parent);
UpdateWorldTransforms(registry);
auto* childWorld = registry.try_get<WorldTransform>(child);
TEST_CHECK(childWorld != nullptr);
if (childWorld) {
TEST_CHECK(childWorld->position.x == 3.0f);
TEST_CHECK(childWorld->position.y == 0.0f);
TEST_CHECK(childWorld->position.z == 0.0f);
}
}
void test_scenegraph_detach(void) {
entt::registry registry;
entt::entity parent = registry.create();
entt::entity child = registry.create();
AttachChild(registry, child, parent);
DetachFromParent(registry, child);
auto* childHierarchy = registry.try_get<Hierarchy>(child);
TEST_CHECK(childHierarchy != nullptr);
if (childHierarchy) {
TEST_CHECK(childHierarchy->parent == entt::null);
TEST_CHECK(childHierarchy->prev == entt::null);
TEST_CHECK(childHierarchy->next == entt::null);
}
auto* parentHierarchy = registry.try_get<Hierarchy>(parent);
TEST_CHECK(parentHierarchy != nullptr);
if (parentHierarchy) {
TEST_CHECK(parentHierarchy->first == entt::null);
}
}
void test_scene_loader_basic(void) {
if (!InitRaylibHidden()) {
TEST_SKIP("No display available for raylib");
return;
}
entt::registry registry;
ModelManager modelManager;
ShaderManager shaderManager;
SetSceneContext(&registry, &modelManager, &shaderManager);
std::filesystem::path tmpDir = std::filesystem::current_path() / "tmp_scene";
std::filesystem::create_directories(tmpDir);
std::filesystem::path scenePath = tmpDir / "scene.toml";
{
std::ofstream scene(scenePath);
scene << "[[entity]]\n";
scene << "id = \"root\"\n";
scene << "tag = \"Root\"\n";
scene << "position = [0.0, 0.0, 0.0]\n";
scene << "\n";
scene << "[[entity]]\n";
scene << "id = \"parent\"\n";
scene << "parent = \"root\"\n";
scene << "tag = \"Parent\"\n";
scene << "position = [1.0, 0.0, 0.0]\n";
scene << "model = \"cube\"\n";
scene << "model_size = [1.0, 1.0, 1.0]\n";
scene << "color = 0x00FF00FF\n";
scene << "\n";
scene << "[[entity]]\n";
scene << "id = \"child\"\n";
scene << "parent = \"parent\"\n";
scene << "tag = \"Child\"\n";
scene << "position = [0.0, 1.0, 0.0]\n";
scene << "model = \"sphere\"\n";
scene << "radius = 0.5\n";
scene << "color = 0xFF0000FF\n";
}
entt::entity root = LoadSceneFromFile(scenePath.string(), true);
TEST_CHECK(root != entt::null);
entt::entity parentEntity = entt::null;
entt::entity childEntity = entt::null;
auto tagView = registry.view<Tag>();
for (auto entity : tagView) {
const auto& tag = tagView.get<Tag>(entity);
if (tag.name == "Parent") {
parentEntity = entity;
} else if (tag.name == "Child") {
childEntity = entity;
}
}
TEST_CHECK(parentEntity != entt::null);
TEST_CHECK(childEntity != entt::null);
if (parentEntity != entt::null && childEntity != entt::null) {
auto* childHierarchy = registry.try_get<Hierarchy>(childEntity);
TEST_CHECK(childHierarchy != nullptr);
if (childHierarchy) {
TEST_CHECK(childHierarchy->parent == parentEntity);
}
TEST_CHECK(registry.all_of<Sprite>(parentEntity));
TEST_CHECK(registry.all_of<Sprite>(childEntity));
}
std::filesystem::remove(scenePath);
std::filesystem::remove(tmpDir);
ShutdownRaylibHidden();
}