diff --git a/editor/include/editor.hpp b/editor/include/editor.hpp index 0820057..982ce97 100755 --- a/editor/include/editor.hpp +++ b/editor/include/editor.hpp @@ -1,7 +1,6 @@ #ifndef EDITOR_HPP #define EDITOR_HPP -#include #include #include "open_engine/renderer/renderer3d.hpp" @@ -92,9 +91,11 @@ namespace OpenEngine { editor_camera = EditorCamera(30.0f, 1920.0f/1080.0f, 0.1f, 1000.0f); + // TODO: Add license icons["play"] = Texture2D::Create("resources/textures/icons/play.png"); icons["stop"] = Texture2D::Create("resources/textures/icons/stop.png"); + // ============================================= Entity cube = scene->CreateEntity("cube"); @@ -104,6 +105,7 @@ namespace OpenEngine { cube.AddComponent(mesh); + // ============================================= Entity quad = scene->CreateEntity("quad"); quad.AddComponent(); quad.GetComponents().translation = {0, 0, 0}; @@ -112,6 +114,7 @@ namespace OpenEngine { quad.AddComponent(quad_mesh); + // ============================================= Entity cube2 = scene->CreateEntity("cube2"); cube2.AddComponent(); cube2.GetComponents().translation = {2, 0, 0}; @@ -129,7 +132,6 @@ namespace OpenEngine { } */ - // TODO: Add file texture. Get free icons and add license //icons["folder"] = Texture2D::Create("resources/textures/icons/folder.png"); /* for (float i = 0; i < 200; i++) { @@ -352,7 +354,7 @@ namespace OpenEngine { bool was_focused = viewport_focused; viewport_focused = ImGui::IsWindowFocused(ImGuiFocusedFlags_RootWindow); viewport_hovered = ImGui::IsWindowHovered(ImGuiHoveredFlags_RootWindow); - Application::Get().GetImGuiLayer()->SetBlockEvents((!viewport_focused && !viewport_hovered) || ImGui::IsAnyItemActive()); + Application::Get().GetImGuiLayer()->SetBlockEvents(ImGui::IsAnyItemActive()); if (viewport_focused && !was_focused) editor_camera.ResetMousePosition(); diff --git a/editor/include/editor_component.hpp b/editor/include/editor_component.hpp index bc5623e..c9fd455 100644 --- a/editor/include/editor_component.hpp +++ b/editor/include/editor_component.hpp @@ -17,6 +17,7 @@ namespace OpenEngine { void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity); void CameraOnImGuiRender(entt::registry& registry, entt::entity entity); void MeshOnImGuiRender(entt::registry®istry, entt::entity entity); + void MaterialOnImGuiRender(entt::registry& registry, entt::entity entity); } #endif // EDITOR_COMPONENT_HPP diff --git a/editor/include/panels/content_browser.hpp b/editor/include/panels/content_browser.hpp index f68ca4d..72a9fc6 100644 --- a/editor/include/panels/content_browser.hpp +++ b/editor/include/panels/content_browser.hpp @@ -18,6 +18,7 @@ namespace OpenEngine { private: std::filesystem::path current_directory; Ref folder_icon; + Ref file_icon; }; } diff --git a/editor/src/editor_component.cpp b/editor/src/editor_component.cpp index 051f377..68de901 100644 --- a/editor/src/editor_component.cpp +++ b/editor/src/editor_component.cpp @@ -1,5 +1,9 @@ #include "imgui.h" +#include "open_engine/renderer/renderer3d.hpp" +#include "open_engine/scene/components.hpp" #include +#include +#include #include namespace OpenEngine { @@ -101,6 +105,7 @@ namespace OpenEngine { DrawVec3Control("Rotation", rotation_comp); transform.rotation = glm::radians(rotation_comp); DrawVec3Control("Scale", transform.scale); + ImGui::Spacing(); }; void SpriteOnImGuiRender(entt::registry& registry, entt::entity entity) @@ -171,8 +176,66 @@ namespace OpenEngine { }; - void MeshOnImGuiRender(entt::registry®istry, entt::entity entity) + void MeshOnImGuiRender(entt::registry& registry, entt::entity entity) { + auto& mesh_component = registry.get(entity); + const char* items[] = { "Quad", "Cube" }; + static int item_selected_idx = 0; + + if (ImGui::BeginCombo("Mesh", items[item_selected_idx])) { + for (int n = 0; n < 2; n++) + { + const bool is_selected = (item_selected_idx == n); + if (ImGui::Selectable(items[n], is_selected)) + item_selected_idx = n; + + // Set the initial focus when opening the combo (scrolling + keyboard navigation focus) + if (is_selected) + ImGui::SetItemDefaultFocus(); + } + ImGui::EndCombo(); + + if ((int)mesh_component.primitive_type == (item_selected_idx + 1)) + return; + + mesh_component.primitive_type = (PrimitiveType)(item_selected_idx + 1); + switch (mesh_component.primitive_type) { + case OpenEngine::PrimitiveType::Quad: + { + mesh_component.mesh = CreateQuad((uint32_t)entity); + break; + } + case OpenEngine::PrimitiveType::Cube: + { + mesh_component.mesh = CreateCube((uint32_t)entity); + break; + } + default: + break; + } + } + } + + void MaterialOnImGuiRender(entt::registry& registry, entt::entity entity) + { + auto& material = registry.get(entity).material; + + auto& albedo = material.albedo; + auto& roughness = material.roughness; + auto& metallic = material.metallic; + auto& ambient = material.ambient_strength; + auto& specular = material.specular_strength; + + if (ImGui::SliderFloat4("Albedo", glm::value_ptr(albedo), 0, 1)) + material.albedo = albedo; + if (ImGui::SliderFloat("Roughness", &roughness, 0, 1)) + material.roughness = roughness; + if (ImGui::SliderFloat("Metallic", &metallic, 0, 1)) + material.metallic = metallic; + if (ImGui::SliderFloat("Ambient strength", &ambient, 0, 1)) + material.ambient_strength = ambient; + if (ImGui::SliderFloat("Specular strength", &specular, 0, 10)) + material.specular_strength = specular; } } diff --git a/editor/src/panels/content_browser.cpp b/editor/src/panels/content_browser.cpp old mode 100644 new mode 100755 index acb26cd..7d7c056 --- a/editor/src/panels/content_browser.cpp +++ b/editor/src/panels/content_browser.cpp @@ -15,8 +15,9 @@ namespace OpenEngine { ContentBrowserPanel::ContentBrowserPanel() : current_directory(assets_directory) { - // TODO: Add file texture. Get free icons and add license - folder_icon = Texture2D::Create("resources/textures/icons/folder.png"); + // TODO: Add license + folder_icon = Texture2D::Create("resources/textures/icons/folder2.png"); + file_icon = Texture2D::Create("resources/textures/icons/file.png"); } void ContentBrowserPanel::OnImGuiRender() @@ -30,6 +31,16 @@ namespace OpenEngine { current_directory = current_directory.parent_path(); auto directory_it = std::filesystem::directory_iterator(current_directory); + std::vector entries; + + for (auto entry : directory_it) + entries.emplace_back(entry); + + std::sort(entries.begin(), entries.end(), + [](const std::filesystem::directory_entry& a, + const std::filesystem::directory_entry& b) { + return (a.is_directory() && !b.is_directory()); + }); ImVec2 button_size = { 100, 100 }; auto panel_width = ImGui::GetContentRegionAvail().x; @@ -42,9 +53,12 @@ namespace OpenEngine { ImGui::PushStyleVar(ImGuiStyleVar_CellPadding, padding); + float margin = 20.0f; + ImGui::Indent(margin); + if (ImGui::BeginTable("table1", table_columns, ImGuiTableFlags_SizingFixedSame)) { - for (auto& entry : directory_it) { + for (auto& entry : entries) { auto file_name = entry.path().filename().string(); ImGui::PushID(file_name.c_str()); @@ -56,17 +70,14 @@ namespace OpenEngine { ImGui::PushStyleColor(ImGuiCol_ButtonActive, { 0.270f, 0.278f, 0.352f, 1.0f }); ImGui::BeginGroup(); - ImGui::ImageButton("##X", (ImTextureID)folder_icon->GetID(), button_size, { 0, 1 }, { 1, 0 }); + Ref icon = entry.is_directory() ? folder_icon : file_icon; + ImGui::ImageButton("##X", (ImTextureID)icon->GetID(), button_size, { 0, 1 }, { 1, 0 }); if (entry.is_regular_file() && ImGui::BeginDragDropSource()) { const char* source = entry.path().c_str(); ImGui::SetDragDropPayload("CONTENT_BROWSER_PAYLOAD", source, (strlen(source) + 1) * sizeof(char), ImGuiCond_Once); ImGui::EndDragDropSource(); } - - float columnWidth = ImGui::GetColumnWidth(); - float textWidth = ImGui::CalcTextSize(file_name.c_str()).x; - ImGui::SetCursorPosX(ImGui::GetCursorPosX() + (columnWidth - textWidth) * 0.5f); ImGui::TextWrapped("%s", file_name.c_str()); ImGui::EndGroup(); @@ -81,6 +92,7 @@ namespace OpenEngine { } ImGui::EndTable(); } + ImGui::Unindent(); ImGui::PopStyleVar(); ImGui::End(); diff --git a/editor/src/panels/scene_hierarchy.cpp b/editor/src/panels/scene_hierarchy.cpp index f00d60e..0c716ad 100644 --- a/editor/src/panels/scene_hierarchy.cpp +++ b/editor/src/panels/scene_hierarchy.cpp @@ -23,6 +23,7 @@ namespace OpenEngine { RegisterDrawer("Sprite Renderer", &SpriteOnImGuiRender); RegisterDrawer("Camera", &CameraOnImGuiRender); RegisterDrawer("Mesh", &MeshOnImGuiRender); + RegisterDrawer("Material", &MaterialOnImGuiRender); scene = context; selected_context = {}; @@ -51,6 +52,11 @@ namespace OpenEngine { selected_context.AddComponent(); ImGui::CloseCurrentPopup(); } + if (!selected_context.HasComponent()) + if (ImGui::MenuItem("Material")) { + selected_context.AddComponent(); + ImGui::CloseCurrentPopup(); + } } void EntityPopup(Ref& scene) diff --git a/open_engine/include/open_engine/renderer/renderer3d.hpp b/open_engine/include/open_engine/renderer/renderer3d.hpp index c79cd39..2ee90df 100644 --- a/open_engine/include/open_engine/renderer/renderer3d.hpp +++ b/open_engine/include/open_engine/renderer/renderer3d.hpp @@ -10,6 +10,14 @@ namespace OpenEngine { // SHOULD BE MOVED ================================== + + enum class PrimitiveType + { + None = 0, + Quad, + Cube + }; + struct MeshVertex { glm::vec3 position; @@ -19,6 +27,15 @@ namespace OpenEngine { uint32_t id = -1; }; + struct Material + { + glm::vec4 albedo = { 1.0f, 1.0f, 1.0f, 1.0f }; + float roughness = 1.0f; + float metallic = 1.0f; + float ambient_strength = 1.0f; + float specular_strength = 1.0f; + }; + struct Mesh { Ref vertex_array; @@ -46,7 +63,8 @@ namespace OpenEngine { static void BeginScene(const EditorCamera& camera); static void EndScene(); - static void DrawMesh(const Ref& mesh, const glm::mat4& transform); + static void DrawMesh(const Ref& mesh, Material& material, + const glm::mat4& transform); }; } diff --git a/open_engine/include/open_engine/scene/components.hpp b/open_engine/include/open_engine/scene/components.hpp index b1e55f1..aae8457 100644 --- a/open_engine/include/open_engine/scene/components.hpp +++ b/open_engine/include/open_engine/scene/components.hpp @@ -86,17 +86,28 @@ namespace OpenEngine { (delete nsc->instance); nsc->instance = nullptr; }; - } + }; }; struct MeshComponent { Ref mesh; + PrimitiveType primitive_type = PrimitiveType::None; MeshComponent() = default; MeshComponent(const MeshComponent&) = default; MeshComponent(const Ref& mesh) - : mesh(mesh) {} + : mesh(mesh) {}; + }; + + struct MaterialComponent + { + Material material; + + MaterialComponent() = default; + MaterialComponent(const MaterialComponent&) = default; + MaterialComponent(const Material& material) + : material(material) {}; }; } diff --git a/open_engine/include/open_engine/scene/scene.hpp b/open_engine/include/open_engine/scene/scene.hpp index cf299a8..a4cb2cc 100644 --- a/open_engine/include/open_engine/scene/scene.hpp +++ b/open_engine/include/open_engine/scene/scene.hpp @@ -40,7 +40,7 @@ namespace OpenEngine { uint32_t viewport_width = 0, viewport_height = 0; - std::vector entities_to_be_deleted; + std::vector pending_deletion; friend class SceneSerializer; friend class Entity; diff --git a/open_engine/src/open_engine/renderer/renderer3d.cpp b/open_engine/src/open_engine/renderer/renderer3d.cpp index cc14723..58120ba 100644 --- a/open_engine/src/open_engine/renderer/renderer3d.cpp +++ b/open_engine/src/open_engine/renderer/renderer3d.cpp @@ -176,6 +176,9 @@ namespace OpenEngine { }; TransformData transform_buffer; Ref transform_uniform_buffer; + + Material material_buffer; + Ref material_uniform_buffer; }; static Renderer3DData renderer_data; @@ -190,6 +193,7 @@ namespace OpenEngine { renderer_data.color_shader_3d = Shader::Create("assets/shaders/color3d.glsl"); renderer_data.camera_uniform_buffer = UniformBuffer::Create(sizeof(Renderer3DData::CameraData), 0); renderer_data.transform_uniform_buffer = UniformBuffer::Create(sizeof(Renderer3DData::TransformData), 1); + renderer_data.material_uniform_buffer = UniformBuffer::Create(sizeof(Material), 2); glEnable(GL_DEBUG_OUTPUT); glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); @@ -230,7 +234,8 @@ namespace OpenEngine { } - void Renderer3D::DrawMesh(const Ref& mesh, const glm::mat4& transform) + void Renderer3D::DrawMesh(const Ref& mesh, Material& material, + const glm::mat4& transform) { OE_PROFILE_FUNCTION(); @@ -239,6 +244,9 @@ namespace OpenEngine { renderer_data.transform_buffer.transform = transform; renderer_data.transform_uniform_buffer->SetData(&renderer_data.transform_buffer, sizeof(Renderer3DData::TransformData)); + renderer_data.material_buffer = material; + renderer_data.material_uniform_buffer->SetData(&renderer_data.material_buffer, sizeof(Material)); + mesh->vertex_array->Bind(); RenderCommand::DrawIndexed(mesh->vertex_array, mesh->indices.size()); diff --git a/open_engine/src/open_engine/scene/scene.cpp b/open_engine/src/open_engine/scene/scene.cpp index d6a114e..5fe217d 100644 --- a/open_engine/src/open_engine/scene/scene.cpp +++ b/open_engine/src/open_engine/scene/scene.cpp @@ -26,15 +26,15 @@ namespace OpenEngine { void Scene::MarkEntityForDeletion(Entity entity) { - entities_to_be_deleted.emplace_back(entity); + pending_deletion.emplace_back(entity); } void Scene::UpdateEntities() { - for (auto& entity : entities_to_be_deleted) + for (auto& entity : pending_deletion) DeleteEntity(entity); - entities_to_be_deleted.clear(); + pending_deletion.clear(); } void Scene::OnUpdateRuntime() @@ -75,8 +75,13 @@ namespace OpenEngine { for (const auto& entity : view) { auto [transform, mesh] = view.get(entity); + Material material; - Renderer3D::DrawMesh(mesh.mesh, GetTransformFromComp(transform)); + Entity _entity(entity, this); + if (_entity.HasComponent()) + material = _entity.GetComponents().material; + + Renderer3D::DrawMesh(mesh.mesh, material, GetTransformFromComp(transform)); /* if (sprite.texture) Renderer2D::DrawQuad(GetTransformFromComp(transform), @@ -101,7 +106,13 @@ namespace OpenEngine { for (const auto& entity : view) { auto [transform, mesh] = view.get(entity); - Renderer3D::DrawMesh(mesh.mesh, GetTransformFromComp(transform)); + Material material; + + Entity _entity(entity, this); + if (_entity.HasComponent()) + material = _entity.GetComponents().material; + + Renderer3D::DrawMesh(mesh.mesh, material, GetTransformFromComp(transform)); } Renderer3D::EndScene(); @@ -170,4 +181,9 @@ namespace OpenEngine { void Scene::OnComponentAdded(Entity entity, MeshComponent& component) { } + + template<> + void Scene::OnComponentAdded(Entity entity, MaterialComponent& component) + { + } } diff --git a/open_engine/src/open_engine/scene/scene_serializer.cpp b/open_engine/src/open_engine/scene/scene_serializer.cpp index 270273e..26600b5 100644 --- a/open_engine/src/open_engine/scene/scene_serializer.cpp +++ b/open_engine/src/open_engine/scene/scene_serializer.cpp @@ -1,7 +1,9 @@ +#include #include #include "core.hpp" #include +#include "renderer/renderer3d.hpp" #include "scene/components.hpp" #include "scene/entity.hpp" @@ -149,6 +151,32 @@ namespace OpenEngine { out << YAML::EndMap; // SpriteRendererComponent } + if (entity.HasComponent()) + { + out << YAML::Key << "MeshComponent"; + out << YAML::BeginMap; // MeshComponent + + auto& mesh_component = entity.GetComponents(); + out << YAML::Key << "MeshType" << YAML::Value << (int)mesh_component.primitive_type; + + out << YAML::EndMap; // MeshComponent + } + + if (entity.HasComponent()) + { + out << YAML::Key << "MaterialComponent"; + out << YAML::BeginMap; // MaterialComponent + + auto& material = entity.GetComponents().material; + out << YAML::Key << "Albedo" << YAML::Value << material.albedo; + out << YAML::Key << "Roughness" << YAML::Value << material.roughness; + out << YAML::Key << "Metalic" << YAML::Value << material.metallic; + out << YAML::Key << "AmbiantStrength" << YAML::Value << material.ambient_strength; + out << YAML::Key << "SpecularStrength" << YAML::Value << material.specular_strength; + + out << YAML::EndMap; // MaterialComponent + } + out << YAML::EndMap; } @@ -241,6 +269,40 @@ namespace OpenEngine { auto& src = deserializedEntity.AddComponent(); src.color = spriteRendererComponent["Color"].as(); } + + auto mesh_component = entity["MeshComponent"]; + if (mesh_component) + { + auto& mesh = deserializedEntity.AddComponent(); + switch (mesh.primitive_type) { + case OpenEngine::PrimitiveType::Quad: + { + mesh.mesh = CreateQuad((uint32_t)deserializedEntity); + break; + } + case OpenEngine::PrimitiveType::Cube: + { + mesh.mesh = CreateCube((uint32_t)deserializedEntity); + break; + } + default: + break; + } + } + + auto material_component = entity["MaterialComponent"]; + if (material_component) + { + auto& material = deserializedEntity.AddComponent(); + material.material.albedo = material_component["Albedo"].as(); + material.material.roughness = material_component["Roughness"].as(); + material.material.metallic = material_component["Metalic"].as(); + material.material.ambient_strength = material_component["AmbiantStrength"].as(); + material.material.specular_strength = material_component["SpecularStrength"].as(); + } + + auto mesh = CreateCube((uint32_t)deserializedEntity); + deserializedEntity.AddComponent(mesh); } } diff --git a/resources/textures/icons/file.png b/resources/textures/icons/file.png new file mode 100644 index 0000000..4c885f7 Binary files /dev/null and b/resources/textures/icons/file.png differ diff --git a/resources/textures/icons/folder2.png b/resources/textures/icons/folder2.png new file mode 100644 index 0000000..5bfd08a Binary files /dev/null and b/resources/textures/icons/folder2.png differ diff --git a/resources/textures/icons/play.png b/resources/textures/icons/play.png index 274b12a..f9058d9 100644 Binary files a/resources/textures/icons/play.png and b/resources/textures/icons/play.png differ diff --git a/resources/textures/icons/stop.png b/resources/textures/icons/stop.png index f8b14b5..ce54396 100644 Binary files a/resources/textures/icons/stop.png and b/resources/textures/icons/stop.png differ