diff --git a/Makefile b/Makefile index d9bbed8..c88b63f 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ # Compiler and Flags CXX := g++ -CXXFLAGS := -Wall -Wextra -std=c++17 -g +CXXFLAGS := -Wall -Wextra -std=c++17 -g -DDEBUG # Directories SRC_DIR := src @@ -11,7 +11,7 @@ BUILD_DIR := build # Include Directories GLFW_INCLUDE := C:/libraries/glfw/include -INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/stb/include +INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/stb/include C:\msys64\mingw64\include INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/gcml INCLUDES := $(addprefix -I, $(INCLUDE_DIRS)) @@ -43,7 +43,7 @@ OBJ_FILES := $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(ALL_SRC)) TARGET := TesseractEngine.exe # Libraries -LIBS := -LC:/libraries/glfw/lib -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid -lwinmm -lglew32 -lglu32 +LIBS := -LC:/libraries/glfw/lib -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid -lwinmm -lglew32 -lglu32 -lyaml-cpp # Phony Targets .PHONY: all clean copy_assets diff --git a/imgui.ini b/imgui.ini index 0aaccbf..b1f9709 100644 --- a/imgui.ini +++ b/imgui.ini @@ -10,7 +10,7 @@ Collapsed=0 [Window][Inspector] Pos=1588,27 -Size=324,772 +Size=324,587 Collapsed=0 DockId=0x00000005,0 @@ -21,8 +21,8 @@ Collapsed=0 DockId=0x00000003,0 [Window][Performance] -Pos=1588,801 -Size=324,368 +Pos=1588,616 +Size=324,553 Collapsed=0 DockId=0x00000006,0 @@ -54,6 +54,6 @@ DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,27 Size=1904,1142 Split= DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1578,770 CentralNode=1 HiddenTabBar=1 Selected=0xF7365A5A DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1578,370 HiddenTabBar=1 Selected=0x9DD4E196 DockNode ID=0x00000002 Parent=0x00000008 SizeRef=324,1142 Split=Y Selected=0x36DC96AB - DockNode ID=0x00000005 Parent=0x00000002 SizeRef=324,772 HiddenTabBar=1 Selected=0x36DC96AB - DockNode ID=0x00000006 Parent=0x00000002 SizeRef=324,368 HiddenTabBar=1 Selected=0x726D8899 + DockNode ID=0x00000005 Parent=0x00000002 SizeRef=324,587 HiddenTabBar=1 Selected=0x36DC96AB + DockNode ID=0x00000006 Parent=0x00000002 SizeRef=324,553 HiddenTabBar=1 Selected=0x726D8899 diff --git a/src/Componenets/Component.h b/src/Componenets/Component.h index 259c4dc..4c513bc 100644 --- a/src/Componenets/Component.h +++ b/src/Componenets/Component.h @@ -1,7 +1,7 @@ #pragma once #include -//#include +#include class Component { @@ -11,6 +11,6 @@ public: // Serialization methods - //virtual YAML::Node Serialize() = 0; - //virtual void Deserialize(const YAML::Node& node) = 0; + virtual YAML::Node Serialize() = 0; + virtual void Deserialize(const YAML::Node& node) = 0; }; \ No newline at end of file diff --git a/src/Componenets/GameObject.cpp b/src/Componenets/GameObject.cpp new file mode 100644 index 0000000..3dfd180 --- /dev/null +++ b/src/Componenets/GameObject.cpp @@ -0,0 +1,99 @@ + +#include "GameObject.h" +#include "Transform.h" +#include + +GameObject::GameObject(int id, const std::string &name) + : id(id), name(name) +{ +} + +int GameObject::GetComponentCount() const +{ + return static_cast(components.size()); +} + + +void GameObject::AddComponent(const std::shared_ptr &component) +{ + components[component->GetName()] = component; + //std::cout << "Added " << component->GetName() << std::endl; +} + +std::shared_ptr GameObject::GetComponentByName(const std::string &name) const +{ + auto it = components.find(name); + if (it != components.end()) + { + return it->second; + } + return nullptr; // Component not found +} + +YAML::Node GameObject::Serialize() +{ + YAML::Node node; + node["ID"] = id; + node["Name"] = name; + + YAML::Node componentsNode; + for (const auto &compPair : components) + { + const std::string &compName = compPair.first; + std::shared_ptr component = compPair.second; + componentsNode[compName] = component->Serialize(); + } + + node["Components"] = componentsNode; + return node; +} + +void GameObject::Deserialize(const YAML::Node &node) +{ + if (node["ID"]) + { + id = node["ID"].as(); + } + if (node["Name"]) + { + name = node["Name"].as(); + } + if (node["Components"]) + { + YAML::Node componentsNode = node["Components"]; + for (auto it = componentsNode.begin(); it != componentsNode.end(); ++it) + { + std::string compName = it->first.as(); + YAML::Node compNode = it->second; + + if (compName == TransformComponent::GetStaticName()) + { + auto transform = std::make_shared(); + transform->Deserialize(compNode); + AddComponent(transform); + } + else + { + std::cout << "[Poly] [De/Serialize] [ERROR] Invalid Component Type '" << compName << "' Skipping" << std::endl; + } + // Add deserialization for other components as needed + } + } +} + + + + + +//} +//else if (compName == MeshComponent::GetStaticName()) +//{ +// auto render = std::make_shared(); +// render->Deserialize(compNode); +// AddComponent(render); +//} +//else if (compName == MeshComponent::GetStaticName()) +//{ +// auto render = std::make_shared(); +// render->Deserialize(compNode); +// AddComponent(render); \ No newline at end of file diff --git a/src/Componenets/GameObject.h b/src/Componenets/GameObject.h index 63cadc5..558bcf8 100644 --- a/src/Componenets/GameObject.h +++ b/src/Componenets/GameObject.h @@ -2,14 +2,43 @@ #pragma once #include +#include +#include + +#include "Component.h" #include "Transform.h" #include "Mesh.h" +#include -struct GameObject +// GetComponent() + +class GameObject { - std::string name; // Unique name for the GameObject - Transform transform; // Position, Rotation, Scale - Mesh mesh; // Rendering Mesh - // Add other components as needed +public: + int id; + std::string name; + std::unordered_map> components; + + int GetComponentCount() const; + + GameObject(int id, const std::string &name); + + void AddComponent(const std::shared_ptr &component); + std::shared_ptr GetComponentByName(const std::string &name) const; + + template + std::shared_ptr GetComponent() + { + auto it = components.find(T::GetStaticName()); + if (it != components.end()) + { + return std::dynamic_pointer_cast(it->second); + } + return nullptr; + } + + // Serialization methods + YAML::Node Serialize(); + void Deserialize(const YAML::Node &node); }; diff --git a/src/Componenets/Mesh.cpp b/src/Componenets/Mesh.cpp new file mode 100644 index 0000000..914f0a5 --- /dev/null +++ b/src/Componenets/Mesh.cpp @@ -0,0 +1,48 @@ + +#include "Mesh.h" + +const std::string MeshComponent::name = "Mesh"; + +MeshComponent::MeshComponent() + : vao(0), indexCount(0), textureID(0) +{ +} + +const std::string& MeshComponent::GetName() const +{ + return name; +} + +const std::string& MeshComponent::GetStaticName() +{ + return name; +} + +YAML::Node MeshComponent::Serialize() +{ + YAML::Node node; + + node["vao"] = static_cast(vao); + node["indexCount"] = static_cast(indexCount); + node["textureID"] = static_cast(textureID); + + + + return node; +} + +void MeshComponent::Deserialize(const YAML::Node& node) +{ + if (node["vao"]) + { + vao = static_cast(node["vao"].as()); + } + if (node["indexCount"]) + { + indexCount = static_cast(node["indexCount"].as()); + } + if (node["textureID"]) + { + textureID = static_cast(node["textureID"].as()); + } +} diff --git a/src/Componenets/Mesh.h b/src/Componenets/Mesh.h index 9273ce7..8ededa3 100644 --- a/src/Componenets/Mesh.h +++ b/src/Componenets/Mesh.h @@ -1,12 +1,28 @@ // Mesh.h #pragma once -#include -// A simple mesh storing a VAO, index count, and texture ID -struct Mesh +#include "Component.h" + +#include +#include +#include + +class MeshComponent : public Component { +public: GLuint vao = 0; // Vertex Array Object GLuint indexCount = 0; // Number of indices to draw GLuint textureID = 0; // The texture handle -}; \ No newline at end of file + + MeshComponent(); + virtual const std::string& GetName() const override; + static const std::string& GetStaticName(); + + // Serialization methods + virtual YAML::Node Serialize() override; + virtual void Deserialize(const YAML::Node& node) override; + +private: + static const std::string name; +}; diff --git a/src/Componenets/Transform.cpp b/src/Componenets/Transform.cpp new file mode 100644 index 0000000..18d1467 --- /dev/null +++ b/src/Componenets/Transform.cpp @@ -0,0 +1,82 @@ +// TransformComponent.cpp +#include "Transform.h" + +const std::string TransformComponent::name = "Transform"; + +TransformComponent::TransformComponent() + : position(0.0f), rotation(0.0f), scale(1.0f) +{ + position = glm::vec3(0.0f, 0.0f, 0.0f); + rotation = glm::vec3(0.0f, 0.0f, 0.0f); + scale = glm::vec3(1.0f, 1.0f, 1.0f); + +} + +const std::string& TransformComponent::GetName() const +{ + return name; +} + +const std::string& TransformComponent::GetStaticName() +{ + return name; +} + +YAML::Node TransformComponent::Serialize() +{ + YAML::Node node; + + // Position + { + YAML::Node posNode; + posNode.SetStyle(YAML::EmitterStyle::Flow); + posNode.push_back(position.x); + posNode.push_back(position.y); + posNode.push_back(position.z); + node["Position"] = posNode; + } + + // Rotation + { + YAML::Node rotNode; + rotNode.SetStyle(YAML::EmitterStyle::Flow); + rotNode.push_back(rotation.x); + rotNode.push_back(rotation.y); + rotNode.push_back(rotation.z); + node["Rotation"] = rotNode; + } + + // Scale + { + YAML::Node scaleNode; + scaleNode.SetStyle(YAML::EmitterStyle::Flow); + scaleNode.push_back(scale.x); + scaleNode.push_back(scale.y); + scaleNode.push_back(scale.z); + node["Scale"] = scaleNode; + } + + return node; +} + +void TransformComponent::Deserialize(const YAML::Node& node) +{ + if (node["Position"]) + { + auto pos = node["Position"].as>(); + if (pos.size() == 3) + position = glm::vec3(pos[0], pos[1], pos[2]); + } + if (node["Rotation"]) + { + auto rot = node["Rotation"].as>(); + if (rot.size() == 3) + rotation = glm::vec3(rot[0], rot[1], rot[2]); + } + if (node["Scale"]) + { + auto scl = node["Scale"].as>(); + if (scl.size() == 3) + scale = glm::vec3(scl[0], scl[1], scl[2]); + } +} diff --git a/src/Componenets/Transform.h b/src/Componenets/Transform.h index 9cc362d..4e7cdeb 100644 --- a/src/Componenets/Transform.h +++ b/src/Componenets/Transform.h @@ -1,14 +1,25 @@ // Transform.h #pragma once + +#include "Component.h" #include +#include -// A simple transform with position, rotation, scale -struct Transform +class TransformComponent : public Component { - glm::vec3 position {0.f, 0.f, 0.f}; - glm::vec3 rotation {0.f, 0.f, 0.f}; // Euler angles, in degrees or radians - glm::vec3 scale {1.f, 1.f, 1.f}; +public: + glm::vec3 position; + glm::vec3 rotation; + glm::vec3 scale; + + TransformComponent(); + virtual const std::string& GetName() const override; + static const std::string& GetStaticName(); + + // Serialization methods + virtual YAML::Node Serialize() override; + virtual void Deserialize(const YAML::Node& node) override; + +private: + static const std::string name; }; - - - diff --git a/src/Engine.cpp b/src/Engine.cpp index ca4e0c0..2706510 100644 --- a/src/Engine.cpp +++ b/src/Engine.cpp @@ -1,7 +1,5 @@ // src/Engine.cpp - - // Settings #define VSync 1 @@ -11,6 +9,7 @@ #include #include #include +#include // Dear ImGui #include "imgui.h" @@ -23,36 +22,25 @@ #include "Windows/InspectorWindow.h" #include "Windows/SceneWindow.h" - #include "Engine/ThemeManager.h" - -#define YAML_CPP_STATIC_DEFINE +// #define YAML_CPP_STATIC_DEFINE #include - - #include "TestModel.h" - - - - - - - AssetManager g_AssetManager; LoggerWindow *g_LoggerWindow; -std::vector g_GameObjects; +std::vector> g_GameObjects; -GameObject* g_SelectedObject; // Pointer to the currently selected object +int g_GPU_Triangles_drawn_to_screen = 0; +GameObject *g_SelectedObject; // Pointer to the currently selected object - -bool MyEngine::Init(int width, int height, const std::string& title) +bool MyEngine::Init(int width, int height, const std::string &title) { DEBUG_PRINT("[START] Engine Init"); // ------------------------------------------ @@ -94,7 +82,7 @@ bool MyEngine::Init(int width, int height, const std::string& title) // ------------------------------------------ IMGUI_CHECKVERSION(); ImGui::CreateContext(); - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); (void)io; // Enable docking io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; @@ -104,18 +92,16 @@ bool MyEngine::Init(int width, int height, const std::string& title) // Style ImGui::StyleColorsDark(); - // Platform/Renderer bindings ImGui_ImplGlfw_InitForOpenGL(m_Window, true); ImGui_ImplOpenGL3_Init("#version 330"); // Initialize windows - m_RenderWindow = std::make_unique(); + m_RenderWindow = std::make_unique(); m_PerformanceWindow = std::make_unique(); - m_LoggerWindow = std::make_unique(); - m_InspectorWindow = std::make_unique(); - m_SceneWindow = std::make_unique(); - + m_LoggerWindow = std::make_unique(); + m_InspectorWindow = std::make_unique(); + m_SceneWindow = std::make_unique(); // Some initial logs m_LoggerWindow->AddLog("Engine initialized."); @@ -130,36 +116,70 @@ bool MyEngine::Init(int width, int height, const std::string& title) return true; } - void MyEngine::Run() { DEBUG_PRINT("[START] Engine Run "); + DEBUG_PRINT("Transition to Editor"); // Pseudocode: - GameObject cube; + int newId = g_GameObjects.size(); + auto newGameObject = std::make_shared(newId, ("Default")); - cube.name = std::string("Default"); - cube.transform.position = glm::vec3(0.f, 0.f, 0.f); - cube.transform.rotation = glm::vec3(0.f, 0.5f, 0.f); - cube.transform.scale = glm::vec3(1.f, 1.f, 1.f); + DEBUG_PRINT("Created Default GameObject"); - // Suppose we loaded a VAO, an EBO with 36 indices for the cube, + newGameObject->AddComponent(std::make_shared()); + newGameObject->AddComponent(std::make_shared()); + + DEBUG_PRINT("Added Componenets"); + + // Suppose we loaded a VAO, an EBO with 36 indices for the cube, // and a texture ID from the asset manager - cube.mesh.vao = CreateCubeVAO(); - cube.mesh.indexCount = 36; - cube.mesh.textureID = static_cast(reinterpret_cast(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"))); + auto mesh = newGameObject->GetComponent(); + auto transform = newGameObject->GetComponent(); - g_GameObjects.push_back(cube); + DEBUG_PRINT("Got pointers to Componenets"); - //printf("%p\n", &g_GameObjects); + if (mesh) + { + // printf("Got Valid Mesh Component\n"); + mesh->vao = CreateCubeVAO(); + mesh->indexCount = 36; + mesh->textureID = static_cast(reinterpret_cast(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"))); + } + else + { + + DEBUG_PRINT("Could not find Mesh Component\n"); + } + + if (transform) + { + // printf("Got Valid Transform Component\n"); + transform->position = glm::vec3(0.f, 0.f, 0.f); + transform->rotation = glm::vec3(0.f, 0.5f, 0.f); + transform->scale = glm::vec3(1.f, 1.f, 1.f); + } + else + { + + DEBUG_PRINT("Could not find Transform Component"); + } + + g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/bricks.png"); + g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/default.png"); + g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/lush_grass.png"); + + g_GameObjects.push_back(newGameObject); + DEBUG_PRINT("Put componenent into Global Componenets Subsystem"); + + // printf("%p\n", &g_GameObjects); // Possibly create more GameObjects with different positions or textures - ThemeManager_ChangeTheme(2); + DEBUG_PRINT("Changed Theme to default"); - while (!glfwWindowShouldClose(m_Window) && m_Running) { // Poll @@ -172,7 +192,7 @@ void MyEngine::Run() if (delta >= 0.1) { m_Fps = (float)(m_FrameCount / delta); - m_Ms = 100.0f / m_Fps; + m_Ms = 100.0f / m_Fps; m_FrameCount = 0; m_LastTime = current_time; } @@ -183,31 +203,31 @@ void MyEngine::Run() // Show main DockSpace ShowDockSpace(); - m_InspectorWindow->Show(); // Show our windows - m_RenderWindow->Show(); // The spinning triangle as ImGui::Image - m_PerformanceWindow->Show(m_Fps, m_Ms); // FPS & ms - m_LoggerWindow->Show(); // Logs + m_RenderWindow->Show(); // The spinning triangle as ImGui::Image + + m_PerformanceWindow->Show(m_Fps, m_Ms); // FPS & ms + + m_LoggerWindow->Show(); // Logs m_SceneWindow->Show(); // After rendering - m_PerformanceWindow->UpdatePerformanceStats(-1, -1); + m_PerformanceWindow->UpdatePerformanceStats(-1, g_GPU_Triangles_drawn_to_screen); // End frame EndFrame(); } DEBUG_PRINT("[OK] Engine Run "); - } void MyEngine::Cleanup() { DEBUG_PRINT("[START] Engine Cleanup "); - + // ImGui cleanup ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplGlfw_Shutdown(); @@ -223,7 +243,6 @@ void MyEngine::Cleanup() m_Running = false; DEBUG_PRINT("[OK] Engine Cleanup "); - } void MyEngine::BeginFrame() @@ -250,10 +269,10 @@ void MyEngine::EndFrame() ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); // (Optional) handle multi-viewport - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) { - GLFWwindow* backup_current_context = glfwGetCurrentContext(); + GLFWwindow *backup_current_context = glfwGetCurrentContext(); ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); glfwMakeContextCurrent(backup_current_context); @@ -267,31 +286,28 @@ void MyEngine::ShowDockSpace() { static bool dockspaceOpen = true; static bool opt_fullscreen = true; - static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None; + // Initialize dockspace_flags without ImGuiDockNodeFlags_DockSpace + static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_PassthruCentralNode; ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking; if (opt_fullscreen) { - ImGuiViewport* viewport = ImGui::GetMainViewport(); + ImGuiViewport *viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->WorkPos); ImGui::SetNextWindowSize(viewport->WorkSize); ImGui::SetNextWindowViewport(viewport->ID); - window_flags |= ImGuiWindowFlags_NoTitleBar - | ImGuiWindowFlags_NoCollapse - | ImGuiWindowFlags_NoResize - | ImGuiWindowFlags_NoMove; - window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus - | ImGuiWindowFlags_NoNavFocus; + window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove; + window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus; } - // Style + // Style adjustments ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::Begin("DockSpace", &dockspaceOpen, window_flags); ImGui::PopStyleVar(2); - // Menu bar example + // Menu bar if (ImGui::BeginMenuBar()) { if (ImGui::BeginMenu("File")) @@ -304,9 +320,12 @@ void MyEngine::ShowDockSpace() } // DockSpace - ImGuiIO& io = ImGui::GetIO(); + ImGuiIO &io = ImGui::GetIO(); if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) { + // Optional: Log the flags for debugging + // DEBUG_PRINT("DockSpace Flags: %d", dockspace_flags); + ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); } diff --git a/src/Engine.h b/src/Engine.h index 522b43f..02956b4 100644 --- a/src/Engine.h +++ b/src/Engine.h @@ -18,7 +18,7 @@ #include "TestModel.h" -//#define DEBUG + #include "gcml.h" // Forward declaration to avoid including GLFW in the header if you prefer diff --git a/src/Windows/InspectorWindow.cpp b/src/Windows/InspectorWindow.cpp index 81c72e5..35f0371 100644 --- a/src/Windows/InspectorWindow.cpp +++ b/src/Windows/InspectorWindow.cpp @@ -7,10 +7,7 @@ #include extern std::vector g_GameObjects; -extern GameObject* g_SelectedObject; // Pointer to the currently selected object - - - +extern GameObject *g_SelectedObject; // Pointer to the currently selected object void InspectorWindow::Show() { @@ -22,261 +19,310 @@ void InspectorWindow::Show() if (ImGui::Begin("Inspector")) { // Title label (white text) - ImGui::TextUnformatted("Selected Object Inspector"); - ImGui::Separator(); - ImGui::Spacing(); - - // =========================== - // 1) TRANSFORM - // =========================== - // Color the Transform header - ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.4f, 1.0f)); - bool transformOpen = ImGui::CollapsingHeader("Transform##Main", ImGuiTreeNodeFlags_DefaultOpen); - ImGui::PopStyleColor(); - - if (transformOpen && g_SelectedObject) //! Funny: I did not put a null check here and it broke everything. + const char *objectName = "No Object Selected"; + if (g_SelectedObject) { + objectName = g_SelectedObject->name.c_str(); + ImGui::Text("Editing Object: %s", objectName); + ImGui::Text("Components: %d", g_SelectedObject->GetComponentCount()); - Transform* transform = &g_SelectedObject->transform; - if (ImGui::IsItemHovered()) - { - ImGui::BeginTooltip(); - ImGui::TextUnformatted("Controls the object's Position, Rotation, and Scale."); - ImGui::EndTooltip(); - } - - // ----------------------------------- - // Position - // ----------------------------------- - ImGui::TextUnformatted("Position"); - ImGui::Spacing(); - - { - // We'll assign colors for X, Y, Z buttons - // (normal, hovered, active) - static const ImVec4 colX = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); - static const ImVec4 colXHover = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); - static const ImVec4 colXActive = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); - - static const ImVec4 colY = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); - static const ImVec4 colYHover = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); - static const ImVec4 colYActive = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); - - static const ImVec4 colZ = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); - static const ImVec4 colZHover = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); - static const ImVec4 colZActive = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); - - const char *axisNames[3] = {"X", "Y", "Z"}; - // We'll reference transform.position here - float *pos = glm::value_ptr(transform->position); - - ImGui::PushID("PositionRow"); - for (int i = 0; i < 3; i++) - { - // Determine color set - ImVec4 col, colH, colA; - if (i == 0) - { - col = colX; - colH = colXHover; - colA = colXActive; - } - else if (i == 1) - { - col = colY; - colH = colYHover; - colA = colYActive; - } - else - { - col = colZ; - colH = colZHover; - colA = colZActive; - } - - // Push color style for button - ImGui::PushStyleColor(ImGuiCol_Button, col); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); - - // Small button with the axis name - if (ImGui::Button(axisNames[i], ImVec2(20, 0))) - { - // No action on click, but we have a box with color - } - - ImGui::PopStyleColor(3); - - ImGui::SameLine(); - ImGui::SetNextItemWidth(60.0f); - ImGui::DragFloat((std::string("##Pos") + axisNames[i]).c_str(), &pos[i], 0.1f); - - if (i < 2) - ImGui::SameLine(0, 15); - } - ImGui::PopID(); - } - - ImGui::Spacing(); ImGui::Separator(); - - // ----------------------------------- - // Rotation - // ----------------------------------- - ImGui::TextUnformatted("Rotation"); ImGui::Spacing(); + // =========================== + // 1) TRANSFORM + // =========================== + // Color the Transform header + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.4f, 1.0f)); + bool transformOpen = ImGui::CollapsingHeader("Transform##Main", ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PopStyleColor(); + + if (transformOpen && g_SelectedObject) //! Funny: I did not put a null check here and it broke everything. { - // Same approach, but referencing transform.rotation - const char *axisNames[3] = {"X", "Y", "Z"}; - float *rot = glm::value_ptr(transform->rotation); - // We can reuse the same color sets - ImGui::PushID("RotationRow"); - for (int i = 0; i < 3; i++) + // Transform* transform = &g_SelectedObject->transform; + std::shared_ptr transform = g_SelectedObject->GetComponent(); + // printf("%p\n", &transform); + if (transform) { - // Decide color sets for X, Y, Z - ImVec4 col, colH, colA; - if (i == 0) + + if (ImGui::IsItemHovered()) { - col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); - colH = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); - colA = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); - } - else if (i == 1) - { - col = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); - colH = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); - colA = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); - } - else - { - col = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); - colH = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); - colA = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); + ImGui::BeginTooltip(); + ImGui::TextUnformatted("Controls the object's Position, Rotation, and Scale."); + ImGui::EndTooltip(); } - ImGui::PushStyleColor(ImGuiCol_Button, col); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); + // ----------------------------------- + // Position + // ----------------------------------- + ImGui::TextUnformatted("Position"); + ImGui::Spacing(); - if (ImGui::Button(axisNames[i], ImVec2(20, 0))) { - // No action + // We'll assign colors for X, Y, Z buttons + // (normal, hovered, active) + static const ImVec4 colX = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); + static const ImVec4 colXHover = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); + static const ImVec4 colXActive = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); + + static const ImVec4 colY = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); + static const ImVec4 colYHover = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); + static const ImVec4 colYActive = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); + + static const ImVec4 colZ = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); + static const ImVec4 colZHover = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); + static const ImVec4 colZActive = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); + + const char *axisNames[3] = {"X", "Y", "Z"}; + // We'll reference transform.position here + float *pos = glm::value_ptr(transform->position); + + ImGui::PushID("PositionRow"); + for (int i = 0; i < 3; i++) + { + // Determine color set + ImVec4 col, colH, colA; + if (i == 0) + { + col = colX; + colH = colXHover; + colA = colXActive; + } + else if (i == 1) + { + col = colY; + colH = colYHover; + colA = colYActive; + } + else + { + col = colZ; + colH = colZHover; + colA = colZActive; + } + + // Push color style for button + ImGui::PushStyleColor(ImGuiCol_Button, col); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); + + // Small button with the axis name + if (ImGui::Button(axisNames[i], ImVec2(20, 0))) + { + // No action on click, but we have a box with color + } + + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(60.0f); + ImGui::DragFloat((std::string("##Pos") + axisNames[i]).c_str(), &pos[i], 0.1f); + + if (i < 2) + ImGui::SameLine(0, 15); + } + ImGui::PopID(); } - ImGui::PopStyleColor(3); - ImGui::SameLine(); - ImGui::SetNextItemWidth(60.0f); - ImGui::DragFloat((std::string("##Rot") + axisNames[i]).c_str(), &rot[i], 0.1f); + ImGui::Spacing(); + ImGui::Separator(); - if (i < 2) - ImGui::SameLine(0, 15); + // ----------------------------------- + // Rotation + // ----------------------------------- + ImGui::TextUnformatted("Rotation"); + ImGui::Spacing(); + + { + // Same approach, but referencing transform.rotation + const char *axisNames[3] = {"X", "Y", "Z"}; + float *rot = glm::value_ptr(transform->rotation); + + // We can reuse the same color sets + ImGui::PushID("RotationRow"); + for (int i = 0; i < 3; i++) + { + // Decide color sets for X, Y, Z + ImVec4 col, colH, colA; + if (i == 0) + { + col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); + colH = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); + colA = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); + } + else if (i == 1) + { + col = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); + colH = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); + colA = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); + } + else + { + col = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); + colH = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); + colA = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); + } + + ImGui::PushStyleColor(ImGuiCol_Button, col); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); + + if (ImGui::Button(axisNames[i], ImVec2(20, 0))) + { + // No action + } + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(60.0f); + ImGui::DragFloat((std::string("##Rot") + axisNames[i]).c_str(), &rot[i], 0.1f); + + if (i < 2) + ImGui::SameLine(0, 15); + } + ImGui::PopID(); + } + + ImGui::Spacing(); + ImGui::Separator(); + + // ----------------------------------- + // Scale + // ----------------------------------- + ImGui::TextUnformatted("Scale"); + ImGui::Spacing(); + + { + const char *axisNames[3] = {"X", "Y", "Z"}; + float *scl = glm::value_ptr(transform->scale); + + ImGui::PushID("ScaleRow"); + for (int i = 0; i < 3; i++) + { + // same color approach + ImVec4 col, colH, colA; + if (i == 0) + { + col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); + colH = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); + colA = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); + } + else if (i == 1) + { + col = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); + colH = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); + colA = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); + } + else + { + col = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); + colH = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); + colA = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); + } + + ImGui::PushStyleColor(ImGuiCol_Button, col); + ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); + ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); + + if (ImGui::Button(axisNames[i], ImVec2(20, 0))) + { + // No action + } + ImGui::PopStyleColor(3); + + ImGui::SameLine(); + ImGui::SetNextItemWidth(60.0f); + ImGui::DragFloat((std::string("##Scl") + axisNames[i]).c_str(), &scl[i], 0.1f); + + if (i < 2) + ImGui::SameLine(0, 15); + } + ImGui::PopID(); + } + + ImGui::Spacing(); + ImGui::Separator(); + } + else + { + ImGui::Text("Error, Null Component"); } - ImGui::PopID(); } - ImGui::Spacing(); - ImGui::Separator(); - - // ----------------------------------- - // Scale - // ----------------------------------- - ImGui::TextUnformatted("Scale"); - ImGui::Spacing(); + ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.4f, 1.0f)); + bool meshOpen = ImGui::CollapsingHeader("Mesh##Main", ImGuiTreeNodeFlags_DefaultOpen); + ImGui::PopStyleColor(); + if (meshOpen && g_SelectedObject) //! Funny: I did not put a null check here and it broke everything. { - const char *axisNames[3] = {"X", "Y", "Z"}; - float *scl = glm::value_ptr(transform->scale); - ImGui::PushID("ScaleRow"); - for (int i = 0; i < 3; i++) + // Transform* transform = &g_SelectedObject->transform; + std::shared_ptr mesh = g_SelectedObject->GetComponent(); + // printf("%p\n", &transform); + if (mesh) { - // same color approach - ImVec4 col, colH, colA; - if (i == 0) + + int vao = static_cast(mesh->vao); + if (ImGui::DragInt("vao", &vao, 1, 0, 1024)) { - col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); - colH = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); - colA = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); - } - else if (i == 1) - { - col = ImVec4(0.4f, 1.0f, 0.4f, 1.0f); - colH = ImVec4(0.6f, 1.0f, 0.6f, 1.0f); - colA = ImVec4(0.2f, 1.0f, 0.2f, 1.0f); - } - else - { - col = ImVec4(0.4f, 0.4f, 1.0f, 1.0f); - colH = ImVec4(0.6f, 0.6f, 1.0f, 1.0f); - colA = ImVec4(0.2f, 0.2f, 1.0f, 1.0f); + mesh->vao = static_cast(vao); } - ImGui::PushStyleColor(ImGuiCol_Button, col); - ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); - ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); - - if (ImGui::Button(axisNames[i], ImVec2(20, 0))) + int indexCount = static_cast(mesh->indexCount); + if (ImGui::DragInt("indexCount", &indexCount, 1, 0, 1024)) { - // No action + mesh->indexCount = static_cast(indexCount); } - ImGui::PopStyleColor(3); - ImGui::SameLine(); - ImGui::SetNextItemWidth(60.0f); - ImGui::DragFloat((std::string("##Scl") + axisNames[i]).c_str(), &scl[i], 0.1f); - - if (i < 2) - ImGui::SameLine(0, 15); + int textureID = static_cast(mesh->textureID); + if (ImGui::DragInt("textureID", &textureID, 1, 0, 1024)) + { + mesh->textureID = static_cast(textureID); + } } - ImGui::PopID(); } - ImGui::Spacing(); - ImGui::Separator(); + + // =========================== + // 2) SCRIPT + // =========================== + // We keep script text in white + // if (ImGui::CollapsingHeader("Script##Main", ImGuiTreeNodeFlags_DefaultOpen)) + //{ + // if (ImGui::IsItemHovered()) + // { + // ImGui::BeginTooltip(); + // ImGui::TextUnformatted("Attach a script or logic component here."); + // ImGui::EndTooltip(); + // } + + // ImGui::TextUnformatted("Script Name:"); + // ImGui::SameLine(); + + // { + // char buffer[128]; + // std::snprintf(buffer, sizeof(buffer), "%s", script.scriptName.c_str()); + // ImGui::SetNextItemWidth(-1); + // if (ImGui::InputText("##ScriptName", buffer, sizeof(buffer))) + // { + // script.scriptName = buffer; + // } + // } + + // ImGui::Spacing(); + + // ImGui::TextUnformatted("Script Enabled:"); + // ImGui::SameLine(); + // ImGui::Checkbox("##ScriptEnabled", &script.enabled); + + // ImGui::Spacing(); + // ImGui::Separator(); + //} } + ImGui::End(); - ImGui::Spacing(); - - // =========================== - // 2) SCRIPT - // =========================== - // We keep script text in white - // if (ImGui::CollapsingHeader("Script##Main", ImGuiTreeNodeFlags_DefaultOpen)) - //{ - // if (ImGui::IsItemHovered()) - // { - // ImGui::BeginTooltip(); - // ImGui::TextUnformatted("Attach a script or logic component here."); - // ImGui::EndTooltip(); - // } - - // ImGui::TextUnformatted("Script Name:"); - // ImGui::SameLine(); - - // { - // char buffer[128]; - // std::snprintf(buffer, sizeof(buffer), "%s", script.scriptName.c_str()); - // ImGui::SetNextItemWidth(-1); - // if (ImGui::InputText("##ScriptName", buffer, sizeof(buffer))) - // { - // script.scriptName = buffer; - // } - // } - - // ImGui::Spacing(); - - // ImGui::TextUnformatted("Script Enabled:"); - // ImGui::SameLine(); - // ImGui::Checkbox("##ScriptEnabled", &script.enabled); - - // ImGui::Spacing(); - // ImGui::Separator(); - //} - ImGui::End(); - - } // + } // // Restore style ImGui::PopStyleVar(3); diff --git a/src/Windows/PerformanceWindow.cpp b/src/Windows/PerformanceWindow.cpp index 3ea75ad..b034bfe 100644 --- a/src/Windows/PerformanceWindow.cpp +++ b/src/Windows/PerformanceWindow.cpp @@ -7,6 +7,7 @@ extern int LoaddedAssets; +extern int g_GPU_Triangles_drawn_to_screen; // Initialize static members int PerformanceWindow::m_OpenGLCallCount = 0; @@ -41,6 +42,9 @@ void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangle { m_OpenGLCallCount = newCallCount; m_TriangleCount = newTriangleCount; + + g_GPU_Triangles_drawn_to_screen = 0; + } void PerformanceWindow::Show(float fps, float ms) @@ -138,14 +142,14 @@ void PerformanceWindow::Show(float fps, float ms) 300.0f, ImVec2(0, 50)); - ImGui::Text("Triangles: %d", m_TriangleCount); - ImGui::PlotHistogram("Triangles", + ImGui::Text("Indices: %d", m_TriangleCount); + ImGui::PlotHistogram("Indices", s_TriangleHistory, IM_ARRAYSIZE(s_TriangleHistory), 0, nullptr, 0.0f, - 5000.0f, + m_TriangleCount*2.5, ImVec2(0, 50)); ImGui::Separator(); diff --git a/src/Windows/RenderWindow.cpp b/src/Windows/RenderWindow.cpp index 8ab6042..30c36dc 100644 --- a/src/Windows/RenderWindow.cpp +++ b/src/Windows/RenderWindow.cpp @@ -8,18 +8,18 @@ #include #include "imgui.h" +#include "gcml.h" + #include "Componenets/GameObject.h" -#include "Componenets/Mesh.h" -#include "Componenets/Transform.h" +#include "Componenets/mesh.h" +#include "Componenets/transform.h" -extern std::vector g_GameObjects; - - -#define CAM_FOV 45.0f -#define CAM_NEAR_PLAIN 0.1f -#define CAM_FAR_PLAIN 1000.0f +extern std::vector> g_GameObjects; +#define CAM_FOV 45.0f +#define CAM_NEAR_PLAIN 0.1f +#define CAM_FAR_PLAIN 1000.0f // Include your AssetManager & Shader headers #include "Engine/AssetManager.h" @@ -28,64 +28,163 @@ extern std::vector g_GameObjects; // Extern reference to our global (or extern) asset manager extern AssetManager g_AssetManager; +extern int g_GPU_Triangles_drawn_to_screen; + + // Example cube data (position + UVs) static float g_CubeVertices[] = -{ - // FRONT (z=+1) - -1.f, -1.f, 1.f, 0.f, 0.f, - 1.f, -1.f, 1.f, 1.f, 0.f, - 1.f, 1.f, 1.f, 1.f, 1.f, - -1.f, 1.f, 1.f, 0.f, 1.f, + { + // FRONT (z=+1) + -1.f, + -1.f, + 1.f, + 0.f, + 0.f, + 1.f, + -1.f, + 1.f, + 1.f, + 0.f, + 1.f, + 1.f, + 1.f, + 1.f, + 1.f, + -1.f, + 1.f, + 1.f, + 0.f, + 1.f, - // BACK (z=-1) - -1.f, -1.f, -1.f, 1.f, 0.f, - 1.f, -1.f, -1.f, 0.f, 0.f, - 1.f, 1.f, -1.f, 0.f, 1.f, - -1.f, 1.f, -1.f, 1.f, 1.f, + // BACK (z=-1) + -1.f, + -1.f, + -1.f, + 1.f, + 0.f, + 1.f, + -1.f, + -1.f, + 0.f, + 0.f, + 1.f, + 1.f, + -1.f, + 0.f, + 1.f, + -1.f, + 1.f, + -1.f, + 1.f, + 1.f, - // LEFT (x=-1) - -1.f, -1.f, -1.f, 0.f, 0.f, - -1.f, -1.f, 1.f, 1.f, 0.f, - -1.f, 1.f, 1.f, 1.f, 1.f, - -1.f, 1.f, -1.f, 0.f, 1.f, + // LEFT (x=-1) + -1.f, + -1.f, + -1.f, + 0.f, + 0.f, + -1.f, + -1.f, + 1.f, + 1.f, + 0.f, + -1.f, + 1.f, + 1.f, + 1.f, + 1.f, + -1.f, + 1.f, + -1.f, + 0.f, + 1.f, - // RIGHT (x=+1) - 1.f, -1.f, -1.f, 1.f, 0.f, - 1.f, -1.f, 1.f, 0.f, 0.f, - 1.f, 1.f, 1.f, 0.f, 1.f, - 1.f, 1.f, -1.f, 1.f, 1.f, + // RIGHT (x=+1) + 1.f, + -1.f, + -1.f, + 1.f, + 0.f, + 1.f, + -1.f, + 1.f, + 0.f, + 0.f, + 1.f, + 1.f, + 1.f, + 0.f, + 1.f, + 1.f, + 1.f, + -1.f, + 1.f, + 1.f, - // TOP (y=+1) - -1.f, 1.f, -1.f, 0.f, 0.f, - 1.f, 1.f, -1.f, 1.f, 0.f, - 1.f, 1.f, 1.f, 1.f, 1.f, - -1.f, 1.f, 1.f, 0.f, 1.f, + // TOP (y=+1) + -1.f, + 1.f, + -1.f, + 0.f, + 0.f, + 1.f, + 1.f, + -1.f, + 1.f, + 0.f, + 1.f, + 1.f, + 1.f, + 1.f, + 1.f, + -1.f, + 1.f, + 1.f, + 0.f, + 1.f, - // BOTTOM (y=-1) - -1.f, -1.f, -1.f, 1.f, 0.f, - 1.f, -1.f, -1.f, 0.f, 0.f, - 1.f, -1.f, 1.f, 0.f, 1.f, - -1.f, -1.f, 1.f, 1.f, 1.f, + // BOTTOM (y=-1) + -1.f, + -1.f, + -1.f, + 1.f, + 0.f, + 1.f, + -1.f, + -1.f, + 0.f, + 0.f, + 1.f, + -1.f, + 1.f, + 0.f, + 1.f, + -1.f, + -1.f, + 1.f, + 1.f, + 1.f, }; static unsigned int g_CubeIndices[] = -{ - // Front - 0,1,2, 2,3,0, - // Back - 4,5,6, 6,7,4, - // Left - 8,9,10, 10,11,8, - // Right - 12,13,14, 14,15,12, - // Top - 16,17,18, 18,19,16, - // Bottom - 20,21,22, 22,23,20 -}; + { + // Front + 0, 1, 2, 2, 3, 0, + // Back + 4, 5, 6, 6, 7, 4, + // Left + 8, 9, 10, 10, 11, 8, + // Right + 12, 13, 14, 14, 15, 12, + // Top + 16, 17, 18, 18, 19, 16, + // Bottom + 20, 21, 22, 22, 23, 20}; void RenderWindow::Show() { + ImGui::Begin("OpenGL Output"); ImVec2 size = ImGui::GetContentRegionAvail(); @@ -98,18 +197,23 @@ void RenderWindow::Show() m_Initialized = true; } + + // If there's space, render to the FBO, then show it as an ImGui image + if (w > 0 && h > 0) { if (w != m_LastWidth || h != m_LastHeight) { + m_FBO.Create(w, h); - m_LastWidth = w; + m_LastWidth = w; m_LastHeight = h; } RenderSceneToFBO(); - ImGui::Image(m_FBO.GetTextureID(), size, ImVec2(0,0), ImVec2(1,1)); + + ImGui::Image(m_FBO.GetTextureID(), size, ImVec2(0, 0), ImVec2(1, 1)); } else { @@ -117,6 +221,7 @@ void RenderWindow::Show() } ImGui::End(); + } void RenderWindow::InitGLResources() @@ -124,15 +229,16 @@ void RenderWindow::InitGLResources() // ---------------------------------------------------- // 1) Load SHADER from the asset manager // ---------------------------------------------------- + { - void* shaderAsset = g_AssetManager.loadAsset(AssetType::SHADER, "assets/shaders/UnlitMaterial"); + void *shaderAsset = g_AssetManager.loadAsset(AssetType::SHADER, "assets/shaders/UnlitMaterial"); if (!shaderAsset) { fprintf(stderr, "[RenderWindow] Failed to load shader via AssetManager.\n"); return; } // Cast back to your Shader class - m_ShaderPtr = static_cast(shaderAsset); + m_ShaderPtr = static_cast(shaderAsset); } // ---------------------------------------------------- @@ -151,11 +257,11 @@ void RenderWindow::InitGLResources() // Position = location 0, UV = location 1 glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, - 5 * sizeof(float), (void*)0); + 5 * sizeof(float), (void *)0); glEnableVertexAttribArray(0); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, - 5 * sizeof(float), (void*)(3 * sizeof(float))); + 5 * sizeof(float), (void *)(3 * sizeof(float))); glEnableVertexAttribArray(1); glBindVertexArray(0); @@ -164,7 +270,7 @@ void RenderWindow::InitGLResources() // 3) Load TEXTURE from the asset manager // ---------------------------------------------------- { - void* texAsset = g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"); + void *texAsset = g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"); if (!texAsset) { fprintf(stderr, "[RenderWindow] Failed to load texture.\n"); @@ -179,13 +285,15 @@ void RenderWindow::InitGLResources() // ---------------------------------------------------- // 4) Initialize GameObjects // ---------------------------------------------------- - -} +} void RenderWindow::RenderSceneToFBO() { - m_RotationAngle += 0.1f; // spin per frame + + + + m_RotationAngle += 0.001f; // spin per frame // Bind the FBO m_FBO.Bind(); @@ -193,10 +301,11 @@ void RenderWindow::RenderSceneToFBO() glEnable(GL_DEPTH_TEST); - glClearColor(0.1f, 0.15f, 0.2f, 1.f); + glClearColor(0.f, 0.f, 0.f, 1.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Use our loaded shader + if (!m_ShaderPtr) return; // Can't render without a shader @@ -209,50 +318,76 @@ void RenderWindow::RenderSceneToFBO() glm::mat4 proj = glm::perspective(glm::radians(CAM_FOV), aspect, CAM_NEAR_PLAIN, CAM_FAR_PLAIN); // Iterate over each GameObject and render it - for (auto& obj : g_GameObjects) - { + + + for (auto &obj : g_GameObjects) + { + // ----------------------------------- - // 1) Build MVP from obj.transform + // 1) Build MVP from transform // ----------------------------------- glm::mat4 model = glm::mat4(1.f); - // Translate - model = glm::translate(model, obj.transform.position); - // Rotate around X, Y, Z - model = glm::rotate(model, glm::radians(obj.transform.rotation.x), glm::vec3(1.f, 0.f, 0.f)); - model = glm::rotate(model, glm::radians(obj.transform.rotation.y), glm::vec3(0.f, 1.f, 0.f)); - model = glm::rotate(model, glm::radians(obj.transform.rotation.z), glm::vec3(0.f, 0.f, 1.f)); + std::shared_ptr transform = obj->GetComponent(); - // Scale - model = glm::scale(model, obj.transform.scale); - // Compute MVP - glm::mat4 mvp = proj * view * model; - // Pass MVP to the shader - GLint mvpLoc = glGetUniformLocation(programID, "uMVP"); - glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp)); + std::shared_ptr mesh = obj->GetComponent(); - // ----------------------------------- - // 2) Bind the object's texture - // ----------------------------------- - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, obj.mesh.textureID); + if (!transform) { + DEBUG_PRINT("Could not find Transform Component"); + } - // Set the sampler uniform to texture unit 0 - GLint texLoc = glGetUniformLocation(programID, "uTexture"); - glUniform1i(texLoc, 0); - // ----------------------------------- - // 3) Draw the object's mesh - // ----------------------------------- - glBindVertexArray(obj.mesh.vao); - glDrawElements(GL_TRIANGLES, obj.mesh.indexCount, GL_UNSIGNED_INT, nullptr); + if (transform && mesh) + { + + // Translate - // Unbind for cleanliness - glBindVertexArray(0); - glBindTexture(GL_TEXTURE_2D, 0); + g_GPU_Triangles_drawn_to_screen = static_cast(mesh->indexCount); + + model = glm::translate(model, transform->position); + + // Rotate around X, Y, Z + + //transform->rotation.x += m_RotationAngle; + model = glm::rotate(model, glm::radians(transform->rotation.x), glm::vec3(1.f, 0.f, 0.f)); + model = glm::rotate(model, glm::radians(transform->rotation.y), glm::vec3(0.f, 1.f, 0.f)); + model = glm::rotate(model, glm::radians(transform->rotation.z), glm::vec3(0.f, 0.f, 1.f)); + + // Scale + model = glm::scale(model, transform->scale); + + + + // Compute MVP + glm::mat4 mvp = proj * view * model; + + // Pass MVP to the shader + GLint mvpLoc = glGetUniformLocation(programID, "uMVP"); + glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp)); + + // ----------------------------------- + // 2) Bind the object's texture + // ----------------------------------- + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, mesh->textureID); + + // Set the sampler uniform to texture unit 0 + GLint texLoc = glGetUniformLocation(programID, "uTexture"); + glUniform1i(texLoc, 0); + + // ----------------------------------- + // 3) Draw the object's mesh + // ----------------------------------- + glBindVertexArray(mesh->vao); + glDrawElements(GL_TRIANGLES, mesh->indexCount, GL_UNSIGNED_INT, nullptr); + + // Unbind for cleanliness + glBindVertexArray(0); + glBindTexture(GL_TEXTURE_2D, 0); + } } // Cleanup diff --git a/src/Windows/SceneWindow.cpp b/src/Windows/SceneWindow.cpp index e77d7ba..9d97b4a 100644 --- a/src/Windows/SceneWindow.cpp +++ b/src/Windows/SceneWindow.cpp @@ -5,35 +5,46 @@ // Include your asset manager and any other necessary headers #include "Engine/AssetManager.h" #include "TestModel.h" +#include "gcml.h" + +#include // Globals -extern std::vector g_GameObjects; -extern GameObject* g_SelectedObject; +extern std::vector> g_GameObjects; +extern std::shared_ptr g_SelectedObject; extern AssetManager g_AssetManager; -// Constructor - // Helper: Create a default cube GameObject -GameObject CreateDefaultCube() { - GameObject cube; - cube.name = "Cube"; - cube.transform.position = glm::vec3(0.f, 0.f, 0.f); - cube.transform.rotation = glm::vec3(0.f, 0.5f, 0.f); - cube.transform.scale = glm::vec3(1.f, 1.f, 1.f); - cube.mesh.vao = CreateCubeVAO(); // Implement your VAO creation logic - cube.mesh.indexCount = 36; - cube.mesh.textureID = static_cast(reinterpret_cast(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"))); - return cube; +std::shared_ptr CreateDefaultCube() +{ + // Pseudocode: + int newId = g_GameObjects.size(); + auto newGameObject = std::make_shared(newId, ("New GameObject")); + newGameObject->AddComponent(std::make_shared()); // Ensure each entity has a TransformComponent by default + newGameObject->AddComponent(std::make_shared()); // Ensure each entity has a TransformComponent by default + + // Suppose we loaded a VAO, an EBO with 36 indices for the cube, + // and a texture ID from the asset manager + std::shared_ptr mesh = newGameObject->GetComponent(); + + mesh->vao = CreateCubeVAO(); + mesh->indexCount = 36; + mesh->textureID = static_cast(reinterpret_cast(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"))); + + return newGameObject; } -// Show function implementation -void SceneWindow::Show() { - if (ImGui::Begin("Scene Window")) { +void SceneWindow::Show() +{ + if (ImGui::Begin("Scene Window")) + { // Add Button - if (ImGui::Button("Add Object")) { + if (ImGui::Button("Add Object")) + { AddGameObject(); + std::cout << "Added a new GameObject. Total objects: " << g_GameObjects.size() << std::endl; } ImGui::Separator(); @@ -41,25 +52,62 @@ void SceneWindow::Show() { // Begin child region for the list to make it scrollable ImGui::BeginChild("GameObjectList", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); - // List GameObjects - for (int index = 0; index < static_cast(g_GameObjects.size()); ++index) { - GameObject& obj = g_GameObjects[index]; - bool isSelected = (g_SelectedObject == &obj); + // Define TreeNode flags for better visuals and interaction + ImGuiTreeNodeFlags nodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth; - // Create a selectable item for each GameObject - if (ImGui::Selectable(obj.name.c_str(), isSelected)) { - g_SelectedObject = &obj; + // Iterate through GameObjects using index for unique identification + for (size_t i = 0; i < g_GameObjects.size(); ++i) + { + auto &obj = g_GameObjects[i]; + + // Determine flags based on selection + ImGuiTreeNodeFlags flags = nodeFlags; + if (g_SelectedObject == obj) + flags |= ImGuiTreeNodeFlags_Selected; + + // Unique identifier for each GameObject node using pointer to ensure uniqueness + // Alternatively, you can use the object's ID or address + std::string nodeLabel = obj->name; + bool nodeOpen = ImGui::TreeNodeEx((void *)(intptr_t)i, flags, nodeLabel.c_str()); + + // Handle selection + if (ImGui::IsItemClicked(ImGuiMouseButton_Left)) + { + g_SelectedObject = obj; + std::cout << "Selected GameObject: " << obj->name << " with ID: " << obj->id << std::endl; } - // Right-click context menu to remove GameObject - if (ImGui::BeginPopupContextItem()) { - if (ImGui::MenuItem("Remove")) { - RemoveGameObject(index); + // Right-click context menu for GameObject actions + if (ImGui::BeginPopupContextItem()) + { + // Delete GameObject Option + if (ImGui::MenuItem("Remove")) + { + std::cout << "Attempting to remove GameObject: " << obj->name << " with ID: " << obj->id << std::endl; + + RemoveGameObject(static_cast(i)); + std::cout << "Removed GameObject: " << obj->name << std::endl; + ImGui::EndPopup(); - break; // Exit the loop as the list has been modified + // Since we've erased the current entity, adjust the loop accordingly + // Decrement i to account for the removed element + --i; + continue; // Skip the rest of the loop iteration } + ImGui::EndPopup(); } + + // Optionally, implement double-click to rename or perform other actions + + // Close the tree node + if (nodeOpen) + { + // If you decide to add child nodes in the future, handle them here + // Currently, no additional handling is required + + ImGui::TreePop(); + } } ImGui::EndChild(); @@ -67,14 +115,13 @@ void SceneWindow::Show() { ImGui::Separator(); // Show currently selected object details at the bottom - if (g_SelectedObject) { + if (g_SelectedObject) + { ImGui::Text("Selected Object: %s", g_SelectedObject->name.c_str()); - // Optionally add details or editable fields here - // Example: - // ImGui::DragFloat3("Position", &g_SelectedObject->transform.position.x, 0.1f); - // ImGui::DragFloat3("Rotation", &g_SelectedObject->transform.rotation.x, 0.1f); - // ImGui::DragFloat3("Scale", &g_SelectedObject->transform.scale.x, 0.1f); - } else { + // Optionally, display more details or provide editing capabilities + } + else + { ImGui::Text("No Object Selected"); } } @@ -82,25 +129,38 @@ void SceneWindow::Show() { } // AddGameObject: Adds a new GameObject -void SceneWindow::AddGameObject() { - GameObject newObj = CreateDefaultCube(); - // Optionally, modify the name to ensure uniqueness - newObj.name += " " + std::to_string(g_GameObjects.size() + 1); +void SceneWindow::AddGameObject() +{ + std::shared_ptr newObj = CreateDefaultCube(); + // Modify the name to ensure uniqueness + newObj->name += " " + std::to_string(g_GameObjects.size()); g_GameObjects.push_back(newObj); + std::cout << "Added GameObject: " << newObj->name << " with ID: " << newObj->id << std::endl; } // RemoveGameObject: Removes a GameObject by index -void SceneWindow::RemoveGameObject(int index) { - if (index >= 0 && index < static_cast(g_GameObjects.size())) { +void SceneWindow::RemoveGameObject(int index) +{ + if (index >= 0 && index < static_cast(g_GameObjects.size())) + { // If the object to be removed is selected, clear the selection - if (g_SelectedObject == &g_GameObjects[index]) { + if (g_SelectedObject == g_GameObjects[index]) + { g_SelectedObject = nullptr; + std::cout << "Cleared selection as the selected GameObject was removed." << std::endl; } + + std::cout << "Removing GameObject: " << g_GameObjects[index]->name << " with ID: " << g_GameObjects[index]->id << std::endl; g_GameObjects.erase(g_GameObjects.begin() + index); } + else + { + std::cerr << "Attempted to remove GameObject with invalid index: " << index << std::endl; + } } // GetSelectedObject function implementation -GameObject* SceneWindow::GetSelectedObject() const { +std::shared_ptr SceneWindow::GetSelectedObject() const +{ return g_SelectedObject; } diff --git a/src/Windows/SceneWindow.h b/src/Windows/SceneWindow.h index afa37d8..94fd9e2 100644 --- a/src/Windows/SceneWindow.h +++ b/src/Windows/SceneWindow.h @@ -10,7 +10,7 @@ class SceneWindow { public: void Show(); - GameObject* GetSelectedObject() const; + std::shared_ptr GetSelectedObject() const; private: void AddGameObject(); // Adds a new game object diff --git a/src/main.cpp b/src/main.cpp index 8b45355..617d5e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,6 +5,7 @@ + int main() { DEBUG_PRINT("[START] Creating Global Engine ");