#include "copium/core/Scene.h" #include "copium/asset/AssetManager.h" #include "copium/asset/AssetMeta.h" #include "copium/asset/AssetRef.h" #include "copium/core/Vulkan.h" #include "copium/ecs/Entity.h" #include "copium/ecs/System.h" #include "copium/event/MouseMoveEvent.h" #include "copium/example/AnimationSystem.h" #include "copium/example/CameraFollowPlayerSystem.h" #include "copium/example/CameraUpdateSystem.h" #include "copium/example/ColliderSystem.h" #include "copium/example/Components.h" #include "copium/example/DebugSystem.h" #include "copium/example/FrameCountSystem.h" #include "copium/example/HealthChangeSystem.h" #include "copium/example/HealthComponentListener.h" #include "copium/example/HealthDisplaySystem.h" #include "copium/example/LevelGeneratorComponentListener.h" #include "copium/example/MouseFollowSystem.h" #include "copium/example/PhysicsSystem.h" #include "copium/example/PickupSystem.h" #include "copium/example/PlayerControllerSystem.h" #include "copium/example/RenderSystem.h" #include "copium/example/UiRenderSystem.h" #include #include #include namespace Copium { Scene::Scene(CommandBuffer& commandBuffer, DescriptorPool& descriptorPool) { renderer = std::make_unique(); uiRenderer = std::make_unique(); descriptorSetRenderer = renderer->GetGraphicsPipeline().CreateDescriptorSet(descriptorPool, 1); uiDescriptorSetRenderer = renderer->GetGraphicsPipeline().CreateDescriptorSet(descriptorPool, 1); ecs = std::make_unique(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(&viewMatrix, &projectionMatrix, &invPvMatrix, &uiProjectionMatrix); ecs->AddSystem(&invPvMatrix); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(); ecs->AddSystem(renderer.get(), descriptorSetRenderer.get(), &commandBuffer, &viewMatrix, &projectionMatrix); // better way to store the RenderSystem data? ecs->AddSystem(uiRenderer.get(), uiDescriptorSetRenderer.get(), &commandBuffer, &uiProjectionMatrix); ecs->SetComponentListener(); ecs->SetComponentListener(); Deserialize("res/scenes/scene.meta"); } void Scene::Update() { ecs->UpdateSystems(); } EventResult Scene::OnEvent(const Event& event) { ecs->UpdateSystems(EventSignal{event}); return EventResult::Continue; } void Scene::Deserialize(const std::string& file) { float aspect = Vulkan::GetSwapChain().GetExtent().width / (float)Vulkan::GetSwapChain().GetExtent().height; std::vector metaFiles = MetaFile::ReadList(file); for (auto& metaFile : metaFiles) { Entity entity = Entity::Create(ecs.get()); for (auto& [name, metaClass] : metaFile.GetMetaFileClasses()) { try { char* endPtr; if (name == "Transform") { TransformC transform; transform.position = ReadVec2Opt(metaClass, "position", glm::vec2{0.0f, 0.0f}); transform.size = ReadVec2Opt(metaClass, "size", glm::vec2{1.0f, 1.0f}); entity.AddComponent(transform); } else if (name == "Texture") { TextureC texture; texture.asset = AssetRef{AssetManager::LoadAsset(Uuid{metaClass.GetValue("texture-uuid")})}; texture.texCoord1 = ReadVec2Opt(metaClass, "tex-coord", glm::vec2{0.0f, 0.0f}); texture.texCoord2 = texture.texCoord1 + ReadVec2Opt(metaClass, "tex-size", glm::vec2{1.0f, 1.0f} - texture.texCoord1); entity.AddComponent(texture); } else if (name == "StaticCollider") { StaticColliderC staticCollider; staticCollider.resolveCollision = ReadBoolOpt(metaClass, "resolve-collision", true); entity.AddComponent(staticCollider); } else if (name == "DynamicCollider") { DynamicColliderC dynamicCollider; dynamicCollider.resolveCollision = ReadBoolOpt(metaClass, "resolve-collision", true); dynamicCollider.colliderOffset = ReadVec2Opt(metaClass, "collider-offset", glm::vec2{0.0f, 0.0f}); dynamicCollider.colliderSize = ReadVec2Opt(metaClass, "collider-size", glm::vec2{1.0f, 1.0f}); entity.AddComponent(dynamicCollider); } else if (name == "Text") { TextC text; text.font = AssetRef{AssetManager::LoadAsset(Uuid{metaClass.GetValue("font")})}; text.text = metaClass.GetValue("text"); text.fontSize = std::strtof(metaClass.GetValue("font-size").c_str(), &endPtr); entity.AddComponent(text); } else if (name == "Camera") { CameraC camera; camera.staticBoundingBox = ReadBoolOpt(metaClass, "static-bounding-box", false); camera.uiCamera = ReadBoolOpt(metaClass, "ui-camera", false); if (camera.uiCamera) camera.projection = BoundingBox(0, 0, Vulkan::GetSwapChain().GetExtent().width, Vulkan::GetSwapChain().GetExtent().height); else camera.projection = BoundingBox(-aspect, -1.0f, aspect, 1.0f); entity.AddComponent(camera); } else if (name == "Uuid") { UuidC uuid; uuid.uuid = Uuid{metaClass.GetValue("uuid")}; entity.AddComponent(uuid); } else if (name == "Player") { PlayerC player; player.camera = GetEntity(Uuid{metaClass.GetValue("camera-uuid")}); entity.AddComponent(player); } else if (name == "Health") { HealthC health; health.max = std::strtol(metaClass.GetValue("health").c_str(), &endPtr, 10); health.current = health.max; entity.AddComponent(health); } else if (name == "Physics") { PhysicsC physics; physics.mass = std::strtof(metaClass.GetValue("mass").c_str(), &endPtr); entity.AddComponent(physics); } else if (name == "Animation") { AnimationC animation; animation.sheetCoord = ReadVec2Opt(metaClass, "sheet-coord", glm::ivec2{0, 0}); animation.sheetSize = ReadVec2Opt(metaClass, "sheet-size", glm::ivec2{1, 1}); animation.images = std::strtol(metaClass.GetValue("images").c_str(), &endPtr, 10); animation.horizontal = ReadBoolOpt(metaClass, "horizontal", true); animation.time = std::strtof(metaClass.GetValue("time").c_str(), &endPtr); entity.AddComponent(animation); } else if (name == "Debug") { DebugC debug; debug.playerEntity = GetEntity(Uuid{metaClass.GetValue("player-uuid")}); entity.AddComponent(debug); } else if (name == "Renderable") entity.AddComponent(); else if (name == "Pickup") entity.AddComponent(); else if (name == "FrameCount") entity.AddComponent(); else if (name == "MouseFollow") entity.AddComponent(); else if (name == "UiRenderable") entity.AddComponent(); else if(name == "LevelGenerator") entity.AddComponent(); else CP_WARN("Unknown component: %s", name.c_str()); } catch (RuntimeException& exception) { CP_ERR("Invalid %s component: %s", name.c_str(), exception.GetErrorMessage().c_str()); } } } } Entity Scene::GetEntity(const Uuid& uuid) const { Entity entity{ecs.get(),ecs->Find([&](EntityId entity, const UuidC& uuidArg) { return uuid == uuidArg.uuid; })}; CP_ASSERT(entity, "Failed to find entity with Uuid=%s", uuid.ToString().c_str()); return entity; } glm::vec2 Scene::ReadVec2Opt(const MetaFileClass& metaClass, const std::string& key, glm::vec2 vec) { if (!metaClass.HasValue(key)) return vec; const std::string& value = metaClass.GetValue(key); char* endPos; vec.x = std::strtof(value.c_str(), &endPos); vec.y = std::strtof(endPos, &endPos); return vec; } glm::ivec2 Scene::ReadVec2Opt(const MetaFileClass& metaClass, const std::string& key, glm::ivec2 vec) { if (!metaClass.HasValue(key)) return vec; const std::string& value = metaClass.GetValue(key); char* endPos; vec.x = std::strtof(value.c_str(), &endPos); vec.y = std::strtof(endPos, &endPos); return vec; } bool Scene::ReadBoolOpt(const MetaFileClass& metaClass, const std::string& key, bool vec) { if (!metaClass.HasValue(key)) return vec; const std::string& value = metaClass.GetValue(key); if (value == "true") return true; return false; } }