feat: fix scene loading that it loads from disk if not already loaded

This commit is contained in:
2026-08-11 01:52:14 +02:00
parent f298c7ada5
commit 662940793e
20 changed files with 964 additions and 434 deletions
+91
View File
@@ -7,6 +7,7 @@
#include <string>
#include <destrum/Event.h>
#include <destrum/Assets/AssetReference.h>
#include <destrum/FS/AssetFS.h>
#include <destrum/ObjectModel/Component.h>
#include <destrum/ObjectModel/GameObject.h>
@@ -17,7 +18,9 @@
#include <destrum/Physics/JoltPhysicsWorld.h>
#include <destrum/Components/Physics/SphereCollider.h>
#include <destrum/Components/Physics/BoxCollider.h>
#include <destrum/Components/Animator.h>
#include <destrum/Components/Physics/Rigidbody.h>
#include <destrum/Graphics/Material.h>
namespace {
class TestComponent final : public Component {
@@ -343,6 +346,91 @@ namespace {
SceneManager::GetInstance().Destroy();
}
void testAnimatorAssetReferences()
{
GameObject object{"animated"};
auto* animator = object.AddComponent<Animator>();
Skeleton skeleton;
Joint joint;
joint.id = 0;
joint.localTranslation = glm::vec3{0.0f};
joint.localRotation = glm::identity<glm::quat>();
joint.localScale = glm::vec3{1.0f};
skeleton.joints.push_back(joint);
skeleton.inverseBindMatrices.push_back(glm::mat4{1.0f});
skeleton.jointNames.push_back("root");
skeleton.assetReference.path = "engine://character.fbx";
buildParentIndex(skeleton);
animator->setSkeleton(std::move(skeleton));
auto clip = std::make_shared<SkeletalAnimation>();
clip->name = "walk";
clip->assetReference.path = "engine://walk.fbx";
clip->assetReference.subresource = "animation:0";
clip->duration = 1.0f;
SkeletalAnimation::Keyframe keyframe;
keyframe.time = 0.0f;
keyframe.translation = glm::vec3{0.0f};
keyframe.rotation = glm::identity<glm::quat>();
keyframe.scale = glm::vec3{1.0f};
SkeletalAnimation::Track track;
track.jointIndex = 0;
track.keyframes.push_back(keyframe);
clip->tracks.push_back(std::move(track));
animator->addClip(std::move(clip));
animator->play("walk");
const auto data = animator->Serialize();
check(data.contains("assetReferences"),
"Animator scenes must store asset references");
check(data.at("assetReferences").at("skeleton").at("path") == "engine://character.fbx",
"Animator serialization must store the skeleton source");
check(data.at("assetReferences").at("animations").at(0).at("asset").at("subresource") ==
"animation:0",
"Animator serialization must store the animation subresource");
check(data.dump().find("keyframes") == std::string::npos,
"Animator scene data must not embed animation keyframes");
}
void testSimpleColorMaterial()
{
const auto material = Material::SimpleColor(
glm::vec3{0.2f, 0.4f, 0.8f},
"blue material");
check(material.baseColor == glm::vec3{0.2f, 0.4f, 0.8f},
"simple materials must preserve their color");
check(material.metallicFactor == 0.0f &&
material.roughnessFactor == 1.0f &&
material.emissiveFactor == 0.0f,
"simple materials must use non-metallic default factors");
check(material.diffuseTexture == NULL_IMAGE_ID,
"simple materials must not require a diffuse image");
check(material.name == "blue material",
"simple materials must preserve their optional name");
}
void testAssetReferenceCacheKeys()
{
const AssetReference reference{
.path = "game://CharacterMedium.fbx",
.subresource = "mesh:0",
};
const auto key = reference.cacheKey();
check(key == "game://CharacterMedium.fbx#mesh:0",
"asset references must produce stable cache keys");
const auto parsed = AssetReference::fromCacheKey(key);
check(parsed.has_value() &&
parsed->path == reference.path &&
parsed->subresource == reference.subresource,
"asset cache keys must recover their source reference");
check(!AssetReference::fromCacheKey("CharacterMedium.fbx").has_value(),
"plain cache names must not be treated as file-backed assets");
}
}
int main()
@@ -358,6 +446,9 @@ int main()
testPhysicsWorldUnits();
testJoltSphereCollisions();
testSceneJoltSphereCollisions();
testAnimatorAssetReferences();
testSimpleColorMaterial();
testAssetReferenceCacheKeys();
std::cout << "destrum tests passed\n";
return EXIT_SUCCESS;
}