diff --git a/CopiumEngine/assets/fileicon.meta b/CopiumEngine/assets/fileicon.meta new file mode 100644 index 0000000..0d3de0c --- /dev/null +++ b/CopiumEngine/assets/fileicon.meta @@ -0,0 +1,4 @@ +[Texture2D] +filepath=res/textures/FileIcon.png +mag-filter=linear +uuid=e2c32c71-e694-91a9-87dc-8162eda5b7c7 diff --git a/CopiumEngine/res/scenes/scene.meta b/CopiumEngine/res/scenes/scene.meta index 9b2cb5f..ee75eab 100644 --- a/CopiumEngine/res/scenes/scene.meta +++ b/CopiumEngine/res/scenes/scene.meta @@ -1,6 +1,30 @@ +[Name] +name=Level Generator + [LevelGenerator] --- +[Name] +name=Block + +[Transform] +position=2 -8.5 +size=1 1 + +[Texture] +texture-uuid=0c83bab1-9406-94fe-2068-6ea324dacb27 +tex-coord=0.75 0 +tex-size=0.25 1 + +[StaticCollider] +resolve-collision=true + +[Renderable] + +--- +[Name] +name=Pickup + [Transform] position=0.1 -0.4 size=0.8 0.8 @@ -15,6 +39,9 @@ resolve-collision=false [Renderable] --- +[Name] +name=Mouse Follower + [Transform] position=0.1 0.1 size=0.2 0.2 @@ -26,6 +53,9 @@ texture-uuid=f49a5284-d666-0982-95ca-cf68cc3d4f45 [Renderable] --- +[Name] +name=Fps counter + [Transform] position=10 10 size=0 @@ -39,15 +69,9 @@ font-size=20 [UiRenderable] --- -[Camera] -static-bounding-box=false -ui-camera=false +[Name] +name=Camera -[Transform] -position=0 0 -size=2 2 - ---- [Camera] static-bounding-box=false ui-camera=false @@ -60,6 +84,9 @@ size=2 2 uuid=a14e2328-ebce-5026-e5ab-495daf8c3660 --- +[Name] +name=Ui Camera + [Camera] static-bounding-box=false ui-camera=true @@ -69,6 +96,8 @@ position=0 0 size=1 1 --- +[Name] +name=Player [Player] camera-uuid=a14e2328-ebce-5026-e5ab-495daf8c3660 @@ -106,6 +135,9 @@ uuid=09617c73-2b1e-0a83-db81-3ae3b5971c11 [Renderable] --- +[Name] +name=Debug Info + [Transform] position=10 800 size=1 1 diff --git a/CopiumEngine/res/textures/FileIcon.png b/CopiumEngine/res/textures/FileIcon.png new file mode 100644 index 0000000..fa3ae22 Binary files /dev/null and b/CopiumEngine/res/textures/FileIcon.png differ diff --git a/CopiumEngine/src/copium/asset/AssetManager.cpp b/CopiumEngine/src/copium/asset/AssetManager.cpp index a25cb2c..4eb17ed 100644 --- a/CopiumEngine/src/copium/asset/AssetManager.cpp +++ b/CopiumEngine/src/copium/asset/AssetManager.cpp @@ -100,6 +100,16 @@ namespace Copium // TODO: Reload the assetCache to see if a new file has appeared with that uuid } + AssetHandle AssetManager::DuplicateAsset(AssetHandle handle) + { + auto it = assets.find(handle); + CP_ASSERT(it != assets.end(), "Failed to find asset with handle=%d", handle); + + CP_DEBUG("Duplicating asset: %s", it->second->GetName().c_str()); + it->second->metaData.loadCount++; + return handle; + } + void AssetManager::UnloadAsset(AssetHandle handle) { auto it = assets.find(handle); @@ -108,7 +118,7 @@ namespace Copium CP_WARN("Asset not loaded"); return; } - CP_DEBUG("Unloading Asset: %s", it->second->GetName().c_str()); + CP_DEBUG("Unloading Asset: %s (%d instances left)", it->second->GetName().c_str(), it->second->metaData.loadCount - 1); it->second->metaData.loadCount--; if (it->second->metaData.loadCount > 0) @@ -121,6 +131,11 @@ namespace Copium assets.erase(it); } + const std::vector& AssetManager::GetAssetFiles() + { + return cachedAssetFiles; + } + void AssetManager::Cleanup() { if (assets.empty()) @@ -141,7 +156,7 @@ namespace Copium auto it = nameToAssetCache.find(name); CP_ASSERT(it == nameToAssetCache.end(), "Asset already exists: %s", name); - AssetHandle handle = runtimeAssetHandle++; + AssetHandle handle = runtimeAssetHandle++; Asset* asset2 = assets.emplace(handle, std::move(asset)).first->second.get(); asset2->metaData.handle = handle; asset2->metaData.name = name; diff --git a/CopiumEngine/src/copium/asset/AssetManager.h b/CopiumEngine/src/copium/asset/AssetManager.h index 9396dc5..8eca434 100644 --- a/CopiumEngine/src/copium/asset/AssetManager.h +++ b/CopiumEngine/src/copium/asset/AssetManager.h @@ -31,8 +31,10 @@ namespace Copium static Asset& GetAsset(AssetHandle handle); static Asset& LoadAsset(const std::string& assetPath); static Asset& LoadAsset(const Uuid& uuid); + static AssetHandle DuplicateAsset(AssetHandle handle); static void UnloadAsset(AssetHandle handle); static Asset& RegisterRuntimeAsset(const std::string& name, std::unique_ptr&& asset); + static const std::vector& GetAssetFiles(); static void Cleanup(); template diff --git a/CopiumEngine/src/copium/core/Application.cpp b/CopiumEngine/src/copium/core/Application.cpp index 3799dd4..68d7cd4 100644 --- a/CopiumEngine/src/copium/core/Application.cpp +++ b/CopiumEngine/src/copium/core/Application.cpp @@ -79,7 +79,11 @@ namespace Copium case EventType::ViewportResize: { const ViewportResize& viewportResizeEvent = static_cast(event); - AssetManager::GetAsset(framebuffer).Resize(viewportResizeEvent.GetViewport().GetSize().x, viewportResizeEvent.GetViewport().GetSize().y); + glm::vec2 size = viewportResizeEvent.GetViewport().GetSize(); + if (size.x == 0 || size.y == 0) + return EventResult::Continue; + + AssetManager::GetAsset(framebuffer).Resize(size.x, size.y); descriptorSetImGui->SetSampler(AssetManager::GetAsset(framebuffer).GetColorAttachment(), 0); return EventResult::Continue; @@ -157,6 +161,7 @@ namespace Copium // TODO: Move this logic elsewhere Vulkan::GetImGuiInstance().Begin(); + ImGui::ShowDemoWindow(); ImGui::SetNextWindowPos(ImVec2{0, 0}); ImGui::SetNextWindowSize(ImVec2{(float)Vulkan::GetWindow().GetWidth(), (float)Vulkan::GetWindow().GetHeight()}); diff --git a/CopiumEngine/src/copium/core/Scene.cpp b/CopiumEngine/src/copium/core/Scene.cpp index 7542fb0..95776b6 100644 --- a/CopiumEngine/src/copium/core/Scene.cpp +++ b/CopiumEngine/src/copium/core/Scene.cpp @@ -28,12 +28,17 @@ #include #include +#include +#include #include namespace Copium { Scene::Scene(CommandBuffer& commandBuffer, DescriptorPool& descriptorPool) { + fileIcon = AssetManager::LoadAsset("fileicon.meta"); + descriptorSetFileIcon = Vulkan::GetImGuiInstance().CreateDescriptorSet(); + descriptorSetFileIcon->SetSampler(AssetManager::GetAsset(fileIcon), 0, 0); renderer = std::make_unique(); uiRenderer = std::make_unique(); descriptorSetRenderer = renderer->GetGraphicsPipeline().CreateDescriptorSet(descriptorPool, 1); @@ -60,8 +65,16 @@ namespace Copium Deserialize("res/scenes/scene.meta"); } + Scene::~Scene() + { + AssetManager::UnloadAsset(fileIcon); + } + void Scene::Update() { + EntityViewGui(); + ComponentViewGui(); + AssetViewGui(); ecs->UpdateSystems(); } @@ -89,6 +102,7 @@ namespace Copium for (auto& metaFile : metaFiles) { Entity entity = Entity::Create(ecs.get()); + entity.AddComponent(); for (auto& [name, metaClass] : metaFile.GetMetaFileClasses()) { try @@ -183,6 +197,12 @@ namespace Copium debug.playerEntity = GetEntity(Uuid{metaClass.GetValue("player-uuid")}); entity.AddComponent(debug); } + else if (name == "Name") + { + NameC name; + name.name = metaClass.GetValue("name"); + entity.AddComponent(name); + } else if (name == "Renderable") entity.AddComponent(); else if (name == "Pickup") @@ -193,16 +213,111 @@ namespace Copium entity.AddComponent(); else if (name == "UiRenderable") entity.AddComponent(); - else if(name == "LevelGenerator") + 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()); } } + if (!entity.HasComponent()) + entity.AddComponent(); + if (!entity.HasComponent()) + entity.AddComponent(String::Format("Entity %d", entity.GetId())); } } + void Scene::EntityViewGui() + { + ImGui::Begin("Entity Tree View"); + ecs->Each([&](EntityId entityId, SerializableC& serializable) { + Entity entity{ecs.get(), entityId}; + std::string name; + if (entity.HasComponent()) + name = entity.GetComponent().name; + if (name.empty()) + name = String::Format("Entity %u", entity.GetId()); + ImGuiTreeNodeFlags flags = ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; + if (selectedEntity == entity) + flags |= ImGuiTreeNodeFlags_Selected; + ImGui::TreeNodeEx(name.c_str(), flags); + if (ImGui::IsItemClicked() && !ImGui::IsItemToggledOpen()) + selectedEntity = entity; + }); + ImGui::End(); + } + + void Scene::ComponentViewGui() + { + ImGui::Begin("Entitiy View"); + if (selectedEntity) + { + ImGui::SeparatorText("Entity"); + ImGui::Text("Uuid: %s", selectedEntity.GetComponent().uuid.ToString().c_str()); + if (ImGui::Button("Delete Entity")) + { + selectedEntity.Destroy(); + selectedEntity.Invalidate(); + } + + ImGui::SeparatorText("Components"); + ComponentGui(selectedEntity, "Name", Scene::NameGui, Scene::NameCreate); + ComponentGui(selectedEntity, "Transform", Scene::TransformGui, Scene::TransformCreate); + ComponentGui(selectedEntity, "Texture", Scene::TextureGui, Scene::TextureCreate); + ComponentGui(selectedEntity, "Text", Scene::TextGui, Scene::TextCreate); + ComponentGui(selectedEntity, "Player", Scene::PlayerGui, Scene::PlayerCreate); + ComponentGui(selectedEntity, "Static Collider", Scene::StaticColliderGui, Scene::StaticColliderCreate); + ComponentGui(selectedEntity, "Dynamic Collider", Scene::DynamicColliderGui, Scene::DynamicColliderCreate); + ComponentGui(selectedEntity, "Camera", Scene::CameraGui, Scene::CameraCreate); + ComponentGui(selectedEntity, "Health", Scene::HealthGui, Scene::HealthCreate); + ComponentGui(selectedEntity, "Physics", Scene::PhysicsGui, Scene::PhysicsCreate); + ComponentGui(selectedEntity, "Animation", Scene::AnimationGui, Scene::AnimationCreate); + ComponentGui(selectedEntity, "Debug Information", Scene::DebugGui, Scene::DebugCreate); + + ComponentGui(selectedEntity, "Mouse Follow"); + ComponentGui(selectedEntity, "Renderable"); + ComponentGui(selectedEntity, "Ui Renderable"); + ComponentGui(selectedEntity, "Pickup"); + ComponentGui(selectedEntity, "Level Generator"); + ComponentGui(selectedEntity, "Frame Count"); + } + ImGui::End(); + } + + void Scene::AssetViewGui() + { + ImGui::Begin("Asset View"); + std::vector assetFiles = AssetManager::GetAssetFiles(); + float width = 0; + float maxWidth = ImGui::GetWindowContentRegionMax().x; + ImGuiStyle& style = ImGui::GetStyle(); + float defaultSpacing = style.ItemSpacing.x; + style.ItemSpacing.x = 30; + float buttonWidth = 50; + float itemWidth = buttonWidth + style.ItemSpacing.x; + for (int i = 0; i < assetFiles.size(); i++) + { + std::string name = assetFiles[i].GetPath(); + size_t slash = name.find('/'); + if (slash != std::string::npos) + name = name.substr(slash + 1); + ImGui::BeginGroup(); + ImGui::Image(*descriptorSetFileIcon, ImVec2{buttonWidth, buttonWidth}, ImVec2{0, 1}, ImVec2{1, 0}); + + ImGui::PushTextWrapPos(ImGui::GetCursorPos().x + buttonWidth); + ImGui::TextWrapped(name.c_str()); + ImGui::PopTextWrapPos(); + ImGui::EndGroup(); + width += itemWidth; + if (i < assetFiles.size() - 1 && width + itemWidth >= maxWidth) + width = 0; + else + ImGui::SameLine(); + } + style.ItemSpacing.x = defaultSpacing; + ImGui::End(); + } + Entity Scene::GetEntity(const Uuid& uuid) const { Entity entity{ecs.get(),ecs->Find([&](EntityId entity, const UuidC& uuidArg) { return uuid == uuidArg.uuid; })}; @@ -246,4 +361,183 @@ namespace Copium return true; return false; } + + template + void Scene::ComponentGui(Entity entity, const std::string& componentName, FuncGui funcGui, FuncCreate funcCreate) + { + if (entity.HasComponent()) + { + Component& component = entity.GetComponent(); + if (ImGui::CollapsingHeader(componentName.c_str(), ImGuiTreeNodeFlags_DefaultOpen)) + { + funcGui(component); + if (ImGui::Button(std::string("Delete " + componentName).c_str())) + entity.RemoveComponent(); + } + } + else + { + // TODO: These buttons should probably be in a context menu when you right-click the entity instead + if (ImGui::Button(std::string("Add " + componentName).c_str())) + funcCreate(entity); + } + } + + template + void Scene::ComponentGui(Entity entity, const std::string& componentName) + { + if (entity.HasComponent()) + { + Component& component = entity.GetComponent(); + if (ImGui::Button(std::string("Delete " + componentName).c_str())) + entity.RemoveComponent(); + } + else + { + // TODO: These buttons should probably be in a context menu when you right-click the entity instead + if (ImGui::Button(std::string("Add " + componentName).c_str())) + entity.AddComponent(); + } + } + + void Scene::TransformGui(TransformC& transform) + { + ImGui::DragFloat2("Position", (float*)&transform.position); + ImGui::DragFloat2("Size", (float*)&transform.size); + } + + void Scene::TransformCreate(Entity entity) + { + entity.AddComponent(glm::vec2{0, 0}, glm::vec2{1, 1}); + } + + void Scene::TextureGui(TextureC& texture) + { + Asset& asset = AssetManager::GetAsset(texture.asset); + ImGui::Text("Asset: %s", asset.GetName().c_str()); + ImGui::DragFloat2("Tex Coord 1", (float*)&texture.texCoord1, 0.01, 0.0f, 1.0f); + ImGui::DragFloat2("Tex Coord 2", (float*)&texture.texCoord2, 0.01, 0.0f, 1.0f); + } + + void Scene::TextureCreate(Entity entity) + { + entity.AddComponent(AssetRef{AssetManager::DuplicateAsset(Vulkan::GetEmptyTexture2D())}, glm::vec2{0, 0}, glm::vec2{1, 1}); + } + + void Scene::TextGui(TextC& text) + { + Asset& asset = AssetManager::GetAsset(text.font); + ImGui::Text(asset.GetName().c_str()); + ImGui::InputTextMultiline("Text##Text", &text.text); + ImGui::DragFloat("Font Size", &text.fontSize); + } + + void Scene::TextCreate(Entity entity) + { + entity.AddComponent(AssetRef{AssetManager::LoadAsset("font.meta")}, "", 20.0f); + } + + void Scene::PlayerGui(PlayerC& player) + { + if (player.camera) + ImGui::Text("Camera: %s", player.camera.GetComponent().name.c_str()); + else + ImGui::Text("No camera attached"); + } + + void Scene::PlayerCreate(Entity entity) + { + entity.AddComponent(); + } + + void Scene::StaticColliderGui(StaticColliderC& staticCollider) + { + ImGui::Checkbox("StaticCollider##Resolve Collision", &staticCollider.resolveCollision); + } + + void Scene::StaticColliderCreate(Entity entity) + { + entity.AddComponent(false); + } + + void Scene::DynamicColliderGui(DynamicColliderC& dynamicCollider) + { + ImGui::Checkbox("DynamicCollider##Resolve Collision", &dynamicCollider.resolveCollision); + ImGui::DragFloat2("Collider Offset", (float*)&dynamicCollider.colliderOffset, 0.01); + ImGui::DragFloat2("Collider Size", (float*)&dynamicCollider.colliderSize, 0.01); + } + + void Scene::DynamicColliderCreate(Entity entity) + { + entity.AddComponent(true, glm::vec2{0, 0}, glm::vec2{1, 1}); + } + + void Scene::CameraGui(CameraC& camera) + { + ImGui::Checkbox("Static", &camera.staticBoundingBox); + ImGui::Checkbox("Ui camera", &camera.uiCamera); // TODO: If this changes, the bounding box should be modified if it is not static + } + + void Scene::CameraCreate(Entity entity) + { + // TODO: Make the BoundingBox based on the viewport somehow + entity.AddComponent(BoundingBox{-1.0f, -1.0f, 1.0f, 1.0f}, false, false); + } + + void Scene::HealthGui(HealthC& health) + { + ImGui::DragInt("Max Health", &health.max); + } + + void Scene::HealthCreate(Entity entity) + { + entity.AddComponent(10, 10); + } + + void Scene::PhysicsGui(PhysicsC& physics) + { + ImGui::DragFloat("Mass", &physics.mass); + } + + void Scene::PhysicsCreate(Entity entity) + { + entity.AddComponent(10.0f); + } + + void Scene::AnimationGui(AnimationC& animation) + { + ImGui::DragInt2("Sheet Size", (int*)&animation.sheetSize); + ImGui::DragInt2("Sheet Coord", (int*)&animation.sheetCoord, 1, 0, std::max(animation.sheetSize.x, animation.sheetSize.y)); + ImGui::DragInt("Images", &animation.images); + ImGui::DragFloat("Frame time", &animation.time); + ImGui::Checkbox("Horizontal", &animation.horizontal); + } + + void Scene::AnimationCreate(Entity entity) + { + entity.AddComponent(glm::ivec2{0, 0}, glm::ivec2{1, 1}, 1, true, 1.0f); + } + + void Scene::DebugGui(DebugC& debug) + { + if (debug.playerEntity) + ImGui::Text("Player: %s", debug.playerEntity.GetComponent().name.c_str()); + else + ImGui::Text("No player attached"); + } + + void Scene::DebugCreate(Entity entity) + { + entity.AddComponent(); + } + + void Scene::NameGui(NameC& name) + { + ImGui::InputText("Name##Name", &name.name); + } + + void Scene::NameCreate(Entity entity) + { + entity.AddComponent(String::Format("Entity %d", entity.GetId())); + } } \ No newline at end of file diff --git a/CopiumEngine/src/copium/core/Scene.h b/CopiumEngine/src/copium/core/Scene.h index a510a72..ede1d00 100644 --- a/CopiumEngine/src/copium/core/Scene.h +++ b/CopiumEngine/src/copium/core/Scene.h @@ -4,6 +4,7 @@ #include "copium/ecs/Entity.h" #include "copium/event/Event.h" #include "copium/event/EventResult.h" +#include "copium/example/Components.h" #include "copium/renderer/Renderer.h" #include "copium/util/Uuid.h" @@ -19,21 +20,61 @@ namespace Copium std::unique_ptr ecs; std::unique_ptr descriptorSetRenderer; std::unique_ptr uiDescriptorSetRenderer; + AssetHandle fileIcon; + std::unique_ptr descriptorSetFileIcon; glm::mat4 projectionMatrix; glm::mat4 viewMatrix; glm::mat4 invPvMatrix; glm::mat4 uiProjectionMatrix; BoundingBox viewport; + + Entity selectedEntity; public: Scene(CommandBuffer& commandBuffer, DescriptorPool& descriptorPool); + ~Scene(); void Update(); EventResult OnEvent(const Event& event); private: void Deserialize(const std::string& file); + void EntityViewGui(); + void ComponentViewGui(); + void AssetViewGui(); + Entity GetEntity(const Uuid& uuid) const; glm::vec2 ReadVec2Opt(const MetaFileClass& metaClass, const std::string& key, glm::vec2 vec); glm::ivec2 ReadVec2Opt(const MetaFileClass& metaClass, const std::string& key, glm::ivec2 vec); bool ReadBoolOpt(const MetaFileClass& metaClass, const std::string& key, bool vec); + + template + void ComponentGui(Entity entity, const std::string& componentName, FuncGui funcGui, FuncCreate funcCreate); + template + static void ComponentGui(Entity entity, const std::string& componentName); + + // TODO: Make these a class instead? + static void TransformGui(TransformC& transform); + static void TransformCreate(Entity entity); + static void TextureGui(TextureC& texture); + static void TextureCreate(Entity entity); + static void TextGui(TextC& text); + static void TextCreate(Entity entity); + static void PlayerGui(PlayerC& player); + static void PlayerCreate(Entity entity); + static void StaticColliderGui(StaticColliderC& staticCollider); + static void StaticColliderCreate(Entity entity); + static void DynamicColliderGui(DynamicColliderC& dynamicCollider); + static void DynamicColliderCreate(Entity entity); + static void CameraGui(CameraC& camera); + static void CameraCreate(Entity entity); + static void PhysicsGui(PhysicsC& physics); + static void PhysicsCreate(Entity entity); + static void HealthGui(HealthC& health); + static void HealthCreate(Entity entity); + static void AnimationGui(AnimationC& animation); + static void AnimationCreate(Entity entity); + static void DebugGui(DebugC& debug); + static void DebugCreate(Entity entity); + static void NameGui(NameC& name); + static void NameCreate(Entity entity); }; } \ No newline at end of file diff --git a/CopiumEngine/src/copium/core/Vulkan.cpp b/CopiumEngine/src/copium/core/Vulkan.cpp index 3650542..bf8229a 100644 --- a/CopiumEngine/src/copium/core/Vulkan.cpp +++ b/CopiumEngine/src/copium/core/Vulkan.cpp @@ -33,7 +33,7 @@ namespace Copium // TODO: Make the working directory always be relative to the assets folder // By looking at where the executable is, since that should always be in the bin folder (it currently isn't though) AssetManager::RegisterAssetDir("assets/"); - emptyTexture2D = AssetManager::RegisterRuntimeAsset("empty_texture2d", std::make_unique(std::vector{0, 0, 0, 255}, 1, 1, SamplerCreator{})); + emptyTexture2D = AssetManager::RegisterRuntimeAsset("empty_texture2d", std::make_unique(std::vector{255, 0, 255, 255}, 1, 1, SamplerCreator{})); } void Vulkan::Destroy() diff --git a/CopiumEngine/src/copium/ecs/System.h b/CopiumEngine/src/copium/ecs/System.h index ed80d0d..80483fb 100644 --- a/CopiumEngine/src/copium/ecs/System.h +++ b/CopiumEngine/src/copium/ecs/System.h @@ -22,5 +22,22 @@ namespace Copium virtual void RunEntity(Entity entity, Components&... components) {}; virtual void RunEntity(const Signal& signal, Entity entity, Components&... components) {}; + + + // TODO: Not sure if this is the way entities should be validated + std::set loggedEntities; + template + bool ValidateEntity(Entity entity) + { + if (entity && entity.HasComponents()) + { + loggedEntities.erase(entity); + return true; + } + if (loggedEntities.find(entity) == loggedEntities.end()) + CP_WARN("Invalid Entity"); + loggedEntities.emplace(entity); + return false; + } }; } diff --git a/CopiumEngine/src/copium/example/CameraFollowPlayerSystem.h b/CopiumEngine/src/copium/example/CameraFollowPlayerSystem.h index 5ce19dd..99d6fcf 100644 --- a/CopiumEngine/src/copium/example/CameraFollowPlayerSystem.h +++ b/CopiumEngine/src/copium/example/CameraFollowPlayerSystem.h @@ -10,6 +10,9 @@ namespace Copium public: void RunEntity(Entity entity, PlayerC& player, TransformC& transform) override { + if (!ValidateEntity(player.camera)) + return; + TransformC& cameraTransform = player.camera.GetComponent(); glm::vec2 wantedPos = transform.position + transform.size * 0.5f; cameraTransform.position -= (cameraTransform.position - wantedPos) * 0.10f; diff --git a/CopiumEngine/src/copium/example/Components.h b/CopiumEngine/src/copium/example/Components.h index c2819ab..2e41c85 100644 --- a/CopiumEngine/src/copium/example/Components.h +++ b/CopiumEngine/src/copium/example/Components.h @@ -3,6 +3,7 @@ #include "copium/asset/AssetRef.h" #include "copium/ecs/Entity.h" #include "copium/util/Uuid.h" +#include "copium/util/BoundingBox.h" #include @@ -16,9 +17,6 @@ namespace Copium glm::vec2 size; }; - struct RenderableC {}; - struct UiRenderableC {}; - struct ColorC { glm::vec3 color; @@ -38,12 +36,6 @@ namespace Copium float fontSize; }; - struct MouseFollowC - {}; - - struct FrameCountC - {}; - struct CameraC { BoundingBox projection; @@ -89,10 +81,6 @@ namespace Copium glm::vec2 oldPosition{}; }; - struct PickupC - { - - }; struct DebugC { @@ -120,4 +108,16 @@ namespace Copium { std::vector entities; }; + + struct NameC + { + std::string name; + }; + + struct RenderableC {}; + struct UiRenderableC {}; + struct SerializableC {}; + struct PickupC {}; + struct MouseFollowC {}; + struct FrameCountC {}; } \ No newline at end of file diff --git a/CopiumEngine/src/copium/example/DebugSystem.h b/CopiumEngine/src/copium/example/DebugSystem.h index 8281019..5e4381c 100644 --- a/CopiumEngine/src/copium/example/DebugSystem.h +++ b/CopiumEngine/src/copium/example/DebugSystem.h @@ -17,6 +17,9 @@ namespace Copium void RunEntity(Entity entity, DebugC& debug, TextC& text, TransformC& transform) override { + if (!ValidateEntity(debug.playerEntity)) + return; + const PlayerC& player = debug.playerEntity.GetComponent(); const TransformC& playerTransform = debug.playerEntity.GetComponent(); const PhysicsC& playerPhysics = debug.playerEntity.GetComponent(); @@ -25,7 +28,13 @@ namespace Copium text.text = ""; text.text += String::Format("Position: (%.3f, %.3f)\n", playerTransform.position.x, playerTransform.position.y); text.text += String::Format("Velocity: (%.3f, %.3f)\n", velocity.x, velocity.y) ; - text.text += String::Format("Grounded: %s", player.grounded ? "true" : "false"); + text.text += String::Format("Grounded: %s\n", player.grounded ? "true" : "false"); + + if (debug.playerEntity.HasComponent()) + { + const HealthC& playerHealth = debug.playerEntity.GetComponent(); + text.text += String::Format("Health: %d/%d", playerHealth.current, playerHealth.max); + } const Font& font = AssetManager::GetAsset(text.font); transform.position.y = viewport->GetSize().y - 10.0f - font.GetBaseHeight() * text.fontSize; diff --git a/CopiumEngine/src/copium/example/LevelGeneratorComponentListener.h b/CopiumEngine/src/copium/example/LevelGeneratorComponentListener.h index 001ba20..26363a5 100644 --- a/CopiumEngine/src/copium/example/LevelGeneratorComponentListener.h +++ b/CopiumEngine/src/copium/example/LevelGeneratorComponentListener.h @@ -23,6 +23,7 @@ namespace Copium entity.AddComponent(AssetRef{AssetManager::LoadAsset("stone.meta")}, glm::vec2{0.75f, 0.0f}, glm::vec2{1.0f, 1.0f}); entity.AddComponent(true); entity.AddComponent(); + levelGenerator.entities.emplace_back(entity); } { Entity entity = Entity::Create(manager); @@ -33,6 +34,7 @@ namespace Copium entity.AddComponent(AssetRef{AssetManager::LoadAsset("stone.meta")}, glm::vec2{0.75f, 0.0f}, glm::vec2{1.0f, 1.0f}); entity.AddComponent(true); entity.AddComponent(); + levelGenerator.entities.emplace_back(entity); } } for (int x = 1; x < 20; x++) @@ -43,6 +45,7 @@ namespace Copium entity.AddComponent(AssetRef{AssetManager::LoadAsset("stone.meta")}, glm::vec2{0.25f, 0.0f}, glm::vec2{0.5f, 1.0f}); entity.AddComponent(true); entity.AddComponent(); + levelGenerator.entities.emplace_back(entity); } { Entity entity = Entity::Create(manager); @@ -50,6 +53,7 @@ namespace Copium entity.AddComponent(AssetRef{AssetManager::LoadAsset("stone.meta")}, glm::vec2{0.25f, 0.0f}, glm::vec2{0.5f, 1.0f}); entity.AddComponent(true); entity.AddComponent(); + levelGenerator.entities.emplace_back(entity); } } for (int y = 0; y < 10; y++) @@ -62,6 +66,7 @@ namespace Copium entity.AddComponent(false); entity.AddComponent(); entity.AddComponent(); + levelGenerator.entities.emplace_back(entity); } } } diff --git a/CopiumEngine/src/copium/example/PickupSystem.h b/CopiumEngine/src/copium/example/PickupSystem.h index d50fab5..91ded0f 100644 --- a/CopiumEngine/src/copium/example/PickupSystem.h +++ b/CopiumEngine/src/copium/example/PickupSystem.h @@ -24,7 +24,7 @@ namespace Copium } else if (collideSignal.GetSecond().HasComponent()) { - if (collideSignal.GetFirst().HasComponent()) + if (collideSignal.GetFirst().HasComponent() && collideSignal.GetFirst().HasComponent()) { collideSignal.GetSecond().Destroy(); collideSignal.GetFirst().GetComponent().current++; diff --git a/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp b/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp index 1bac09f..2beae72 100644 --- a/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp +++ b/CopiumEngine/src/copium/pipeline/DescriptorSet.cpp @@ -83,6 +83,25 @@ namespace Copium } } + void DescriptorSet::SetSamplersDynamic(const std::vector& samplers, uint32_t binding) + { + std::vector descriptorWrites{samplers.size()}; + for (size_t i = 0; i < samplers.size(); i++) + { + VkDescriptorImageInfo imageInfo = samplers[i]->GetDescriptorImageInfo(Vulkan::GetSwapChain().GetFlightIndex()); + descriptorWrites[i].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + descriptorWrites[i].dstSet = descriptorSets[Vulkan::GetSwapChain().GetFlightIndex()]; + descriptorWrites[i].dstBinding = binding; + descriptorWrites[i].dstArrayElement = i; + descriptorWrites[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + descriptorWrites[i].descriptorCount = 1; + descriptorWrites[i].pBufferInfo = nullptr; + descriptorWrites[i].pImageInfo = &imageInfo; + descriptorWrites[i].pTexelBufferView = nullptr; + } + vkUpdateDescriptorSets(Vulkan::GetDevice(), descriptorWrites.size(), descriptorWrites.data(), 0, nullptr); + } + UniformBuffer& DescriptorSet::GetUniformBuffer(const std::string& uniformBuffer) { auto it = uniformBuffers.find(uniformBuffer); diff --git a/CopiumEngine/src/copium/pipeline/DescriptorSet.h b/CopiumEngine/src/copium/pipeline/DescriptorSet.h index d19d787..5b29cd1 100644 --- a/CopiumEngine/src/copium/pipeline/DescriptorSet.h +++ b/CopiumEngine/src/copium/pipeline/DescriptorSet.h @@ -34,6 +34,7 @@ namespace Copium void SetSampler(const Sampler& sampler, uint32_t binding, int arrayIndex = 0); void SetSamplerDynamic(const Sampler& sampler, uint32_t binding, int arrayIndex = 0); void SetSamplers(const std::vector& sampler, uint32_t binding); + void SetSamplersDynamic(const std::vector& samplers, uint32_t binding); UniformBuffer& GetUniformBuffer(const std::string& uniformBuffer); uint32_t GetSetIndex() const; diff --git a/CopiumEngine/src/copium/renderer/Batch.cpp b/CopiumEngine/src/copium/renderer/Batch.cpp index ced4a96..c11446d 100644 --- a/CopiumEngine/src/copium/renderer/Batch.cpp +++ b/CopiumEngine/src/copium/renderer/Batch.cpp @@ -8,9 +8,7 @@ namespace Copium Batch::Batch(AssetHandle pipeline, DescriptorPool& descriptorPool, int vertexCount, const std::vector samplers) : vertexBuffer{RendererVertex::GetDescriptor(), vertexCount}, descriptorSet{AssetManager::GetAsset(pipeline).CreateDescriptorSet(descriptorPool, 0)} - { - descriptorSet->SetSamplers(samplers, 0); - } + {} RendererVertexBuffer& Batch::GetVertexBuffer() { diff --git a/CopiumEngine/src/copium/renderer/Renderer.cpp b/CopiumEngine/src/copium/renderer/Renderer.cpp index f84ecc0..8c7832c 100644 --- a/CopiumEngine/src/copium/renderer/Renderer.cpp +++ b/CopiumEngine/src/copium/renderer/Renderer.cpp @@ -187,6 +187,7 @@ namespace Copium { batches.emplace_back(std::make_unique(pipeline, descriptorPool, MAX_NUM_VERTICES, samplers)); } + batches[batchIndex]->GetDescriptorSet().SetSamplersDynamic(samplers, 0); mappedVertexBuffer = (char*)batches[batchIndex]->GetVertexBuffer().Map() + batches[batchIndex]->GetVertexBuffer().GetPosition(Vulkan::GetSwapChain().GetFlightIndex()); quadCount = 0; textureCount = 0; diff --git a/CopiumEngine/src/copium/sampler/Texture2D.cpp b/CopiumEngine/src/copium/sampler/Texture2D.cpp index 57fb2b2..8604965 100644 --- a/CopiumEngine/src/copium/sampler/Texture2D.cpp +++ b/CopiumEngine/src/copium/sampler/Texture2D.cpp @@ -27,6 +27,10 @@ namespace Copium Texture2D::~Texture2D() { + // TODO: Do we want to queue the deletion and have it wait for idle once every frame instead? + // Something like: + // Vulkan::GetDevice().QueueIdleCommand([]() { Texture2D::Destroy(image, imageMemory, imageView); }); + vkDeviceWaitIdle(Vulkan::GetDevice()); vkDestroyImage(Vulkan::GetDevice(), image, nullptr); vkFreeMemory(Vulkan::GetDevice(), imageMemory, nullptr); vkDestroyImageView(Vulkan::GetDevice(), imageView, nullptr); diff --git a/ext/projects/imgui/imgui.vcxproj b/ext/projects/imgui/imgui.vcxproj index 03eb982..d30227a 100644 --- a/ext/projects/imgui/imgui.vcxproj +++ b/ext/projects/imgui/imgui.vcxproj @@ -26,6 +26,7 @@ + 16.0 diff --git a/ext/projects/imgui/imgui.vcxproj.filters b/ext/projects/imgui/imgui.vcxproj.filters index d7874be..7f88ac6 100644 --- a/ext/projects/imgui/imgui.vcxproj.filters +++ b/ext/projects/imgui/imgui.vcxproj.filters @@ -36,5 +36,8 @@ Source Files + + Source Files + \ No newline at end of file