Converted Gameobjects and componenets to Classes, added texture and mesh inspectors

This commit is contained in:
OusmBlueNinja 2024-12-26 19:34:34 -06:00
parent d71876544a
commit 9ad51f97b7
17 changed files with 1010 additions and 460 deletions

View File

@ -2,7 +2,7 @@
# Compiler and Flags # Compiler and Flags
CXX := g++ CXX := g++
CXXFLAGS := -Wall -Wextra -std=c++17 -g CXXFLAGS := -Wall -Wextra -std=c++17 -g -DDEBUG
# Directories # Directories
SRC_DIR := src SRC_DIR := src
@ -11,7 +11,7 @@ BUILD_DIR := build
# Include Directories # Include Directories
GLFW_INCLUDE := C:/libraries/glfw/include 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 INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/gcml
INCLUDES := $(addprefix -I, $(INCLUDE_DIRS)) INCLUDES := $(addprefix -I, $(INCLUDE_DIRS))
@ -43,7 +43,7 @@ OBJ_FILES := $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(ALL_SRC))
TARGET := TesseractEngine.exe TARGET := TesseractEngine.exe
# Libraries # 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 Targets
.PHONY: all clean copy_assets .PHONY: all clean copy_assets

View File

@ -10,7 +10,7 @@ Collapsed=0
[Window][Inspector] [Window][Inspector]
Pos=1588,27 Pos=1588,27
Size=324,772 Size=324,587
Collapsed=0 Collapsed=0
DockId=0x00000005,0 DockId=0x00000005,0
@ -21,8 +21,8 @@ Collapsed=0
DockId=0x00000003,0 DockId=0x00000003,0
[Window][Performance] [Window][Performance]
Pos=1588,801 Pos=1588,616
Size=324,368 Size=324,553
Collapsed=0 Collapsed=0
DockId=0x00000006,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=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=0x00000004 Parent=0x00000001 SizeRef=1578,370 HiddenTabBar=1 Selected=0x9DD4E196
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=324,1142 Split=Y Selected=0x36DC96AB 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=0x00000005 Parent=0x00000002 SizeRef=324,587 HiddenTabBar=1 Selected=0x36DC96AB
DockNode ID=0x00000006 Parent=0x00000002 SizeRef=324,368 HiddenTabBar=1 Selected=0x726D8899 DockNode ID=0x00000006 Parent=0x00000002 SizeRef=324,553 HiddenTabBar=1 Selected=0x726D8899

View File

@ -1,7 +1,7 @@
#pragma once #pragma once
#include <string> #include <string>
//#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
class Component class Component
{ {
@ -11,6 +11,6 @@ public:
// Serialization methods // Serialization methods
//virtual YAML::Node Serialize() = 0; virtual YAML::Node Serialize() = 0;
//virtual void Deserialize(const YAML::Node& node) = 0; virtual void Deserialize(const YAML::Node& node) = 0;
}; };

View File

@ -0,0 +1,99 @@
#include "GameObject.h"
#include "Transform.h"
#include <iostream>
GameObject::GameObject(int id, const std::string &name)
: id(id), name(name)
{
}
int GameObject::GetComponentCount() const
{
return static_cast<int>(components.size());
}
void GameObject::AddComponent(const std::shared_ptr<Component> &component)
{
components[component->GetName()] = component;
//std::cout << "Added " << component->GetName() << std::endl;
}
std::shared_ptr<Component> 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> 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<int>();
}
if (node["Name"])
{
name = node["Name"].as<std::string>();
}
if (node["Components"])
{
YAML::Node componentsNode = node["Components"];
for (auto it = componentsNode.begin(); it != componentsNode.end(); ++it)
{
std::string compName = it->first.as<std::string>();
YAML::Node compNode = it->second;
if (compName == TransformComponent::GetStaticName())
{
auto transform = std::make_shared<TransformComponent>();
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<MeshComponent>();
// render->Deserialize(compNode);
// AddComponent(render);
//}
//else if (compName == MeshComponent::GetStaticName())
//{
// auto render = std::make_shared<MeshComponent>();
// render->Deserialize(compNode);
// AddComponent(render);

View File

@ -2,14 +2,43 @@
#pragma once #pragma once
#include <string> #include <string>
#include <unordered_map>
#include <memory>
#include "Component.h"
#include "Transform.h" #include "Transform.h"
#include "Mesh.h" #include "Mesh.h"
#include <yaml-cpp/yaml.h>
struct GameObject // GetComponent<CameraComponent>()
class GameObject
{ {
std::string name; // Unique name for the GameObject public:
Transform transform; // Position, Rotation, Scale int id;
Mesh mesh; // Rendering Mesh std::string name;
// Add other components as needed std::unordered_map<std::string, std::shared_ptr<Component>> components;
int GetComponentCount() const;
GameObject(int id, const std::string &name);
void AddComponent(const std::shared_ptr<Component> &component);
std::shared_ptr<Component> GetComponentByName(const std::string &name) const;
template <typename T>
std::shared_ptr<T> GetComponent()
{
auto it = components.find(T::GetStaticName());
if (it != components.end())
{
return std::dynamic_pointer_cast<T>(it->second);
}
return nullptr;
}
// Serialization methods
YAML::Node Serialize();
void Deserialize(const YAML::Node &node);
}; };

48
src/Componenets/Mesh.cpp Normal file
View File

@ -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<int>(vao);
node["indexCount"] = static_cast<int>(indexCount);
node["textureID"] = static_cast<int>(textureID);
return node;
}
void MeshComponent::Deserialize(const YAML::Node& node)
{
if (node["vao"])
{
vao = static_cast<int>(node["vao"].as<int>());
}
if (node["indexCount"])
{
indexCount = static_cast<int>(node["indexCount"].as<int>());
}
if (node["textureID"])
{
textureID = static_cast<int>(node["textureID"].as<int>());
}
}

View File

@ -1,12 +1,28 @@
// Mesh.h // Mesh.h
#pragma once #pragma once
#include <GL/glew.h>
// A simple mesh storing a VAO, index count, and texture ID #include "Component.h"
struct Mesh
#include <GL/glew.h>
#include <glm/glm.hpp>
#include <yaml-cpp/yaml.h>
class MeshComponent : public Component
{ {
public:
GLuint vao = 0; // Vertex Array Object GLuint vao = 0; // Vertex Array Object
GLuint indexCount = 0; // Number of indices to draw GLuint indexCount = 0; // Number of indices to draw
GLuint textureID = 0; // The texture handle GLuint textureID = 0; // The texture handle
};
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;
};

View File

@ -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<std::vector<float>>();
if (pos.size() == 3)
position = glm::vec3(pos[0], pos[1], pos[2]);
}
if (node["Rotation"])
{
auto rot = node["Rotation"].as<std::vector<float>>();
if (rot.size() == 3)
rotation = glm::vec3(rot[0], rot[1], rot[2]);
}
if (node["Scale"])
{
auto scl = node["Scale"].as<std::vector<float>>();
if (scl.size() == 3)
scale = glm::vec3(scl[0], scl[1], scl[2]);
}
}

View File

@ -1,14 +1,25 @@
// Transform.h // Transform.h
#pragma once #pragma once
#include "Component.h"
#include <glm/glm.hpp> #include <glm/glm.hpp>
#include <yaml-cpp/yaml.h>
// A simple transform with position, rotation, scale class TransformComponent : public Component
struct Transform
{ {
glm::vec3 position {0.f, 0.f, 0.f}; public:
glm::vec3 rotation {0.f, 0.f, 0.f}; // Euler angles, in degrees or radians glm::vec3 position;
glm::vec3 scale {1.f, 1.f, 1.f}; 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;
}; };

View File

@ -1,7 +1,5 @@
// src/Engine.cpp // src/Engine.cpp
// Settings // Settings
#define VSync 1 #define VSync 1
@ -11,6 +9,7 @@
#include <chrono> #include <chrono>
#include <GL/glew.h> #include <GL/glew.h>
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <string>
// Dear ImGui // Dear ImGui
#include "imgui.h" #include "imgui.h"
@ -23,36 +22,25 @@
#include "Windows/InspectorWindow.h" #include "Windows/InspectorWindow.h"
#include "Windows/SceneWindow.h" #include "Windows/SceneWindow.h"
#include "Engine/ThemeManager.h" #include "Engine/ThemeManager.h"
// #define YAML_CPP_STATIC_DEFINE
#define YAML_CPP_STATIC_DEFINE
#include <yaml-cpp/yaml.h> #include <yaml-cpp/yaml.h>
#include "TestModel.h" #include "TestModel.h"
AssetManager g_AssetManager; AssetManager g_AssetManager;
LoggerWindow *g_LoggerWindow; LoggerWindow *g_LoggerWindow;
std::vector<GameObject> g_GameObjects; std::vector<std::shared_ptr<GameObject>> 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"); DEBUG_PRINT("[START] Engine Init");
// ------------------------------------------ // ------------------------------------------
@ -94,7 +82,7 @@ bool MyEngine::Init(int width, int height, const std::string& title)
// ------------------------------------------ // ------------------------------------------
IMGUI_CHECKVERSION(); IMGUI_CHECKVERSION();
ImGui::CreateContext(); ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
(void)io; (void)io;
// Enable docking // Enable docking
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
@ -104,18 +92,16 @@ bool MyEngine::Init(int width, int height, const std::string& title)
// Style // Style
ImGui::StyleColorsDark(); ImGui::StyleColorsDark();
// Platform/Renderer bindings // Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(m_Window, true); ImGui_ImplGlfw_InitForOpenGL(m_Window, true);
ImGui_ImplOpenGL3_Init("#version 330"); ImGui_ImplOpenGL3_Init("#version 330");
// Initialize windows // Initialize windows
m_RenderWindow = std::make_unique<RenderWindow>(); m_RenderWindow = std::make_unique<RenderWindow>();
m_PerformanceWindow = std::make_unique<PerformanceWindow>(); m_PerformanceWindow = std::make_unique<PerformanceWindow>();
m_LoggerWindow = std::make_unique<LoggerWindow>(); m_LoggerWindow = std::make_unique<LoggerWindow>();
m_InspectorWindow = std::make_unique<InspectorWindow>(); m_InspectorWindow = std::make_unique<InspectorWindow>();
m_SceneWindow = std::make_unique<SceneWindow>(); m_SceneWindow = std::make_unique<SceneWindow>();
// Some initial logs // Some initial logs
m_LoggerWindow->AddLog("Engine initialized."); m_LoggerWindow->AddLog("Engine initialized.");
@ -130,36 +116,70 @@ bool MyEngine::Init(int width, int height, const std::string& title)
return true; return true;
} }
void MyEngine::Run() void MyEngine::Run()
{ {
DEBUG_PRINT("[START] Engine Run "); DEBUG_PRINT("[START] Engine Run ");
DEBUG_PRINT("Transition to Editor");
// Pseudocode: // Pseudocode:
GameObject cube; int newId = g_GameObjects.size();
auto newGameObject = std::make_shared<GameObject>(newId, ("Default"));
cube.name = std::string("Default"); DEBUG_PRINT("Created Default GameObject");
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);
// Suppose we loaded a VAO, an EBO with 36 indices for the cube, newGameObject->AddComponent(std::make_shared<TransformComponent>());
newGameObject->AddComponent(std::make_shared<MeshComponent>());
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 // and a texture ID from the asset manager
cube.mesh.vao = CreateCubeVAO(); auto mesh = newGameObject->GetComponent<MeshComponent>();
cube.mesh.indexCount = 36; auto transform = newGameObject->GetComponent<TransformComponent>();
cube.mesh.textureID = static_cast<GLuint>(reinterpret_cast<uintptr_t>(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png")));
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<GLuint>(reinterpret_cast<uintptr_t>(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 // Possibly create more GameObjects with different positions or textures
ThemeManager_ChangeTheme(2); ThemeManager_ChangeTheme(2);
DEBUG_PRINT("Changed Theme to default");
while (!glfwWindowShouldClose(m_Window) && m_Running) while (!glfwWindowShouldClose(m_Window) && m_Running)
{ {
// Poll // Poll
@ -172,7 +192,7 @@ void MyEngine::Run()
if (delta >= 0.1) if (delta >= 0.1)
{ {
m_Fps = (float)(m_FrameCount / delta); m_Fps = (float)(m_FrameCount / delta);
m_Ms = 100.0f / m_Fps; m_Ms = 100.0f / m_Fps;
m_FrameCount = 0; m_FrameCount = 0;
m_LastTime = current_time; m_LastTime = current_time;
} }
@ -183,31 +203,31 @@ void MyEngine::Run()
// Show main DockSpace // Show main DockSpace
ShowDockSpace(); ShowDockSpace();
m_InspectorWindow->Show(); m_InspectorWindow->Show();
// Show our windows // Show our windows
m_RenderWindow->Show(); // The spinning triangle as ImGui::Image m_RenderWindow->Show(); // The spinning triangle as ImGui::Image
m_PerformanceWindow->Show(m_Fps, m_Ms); // FPS & ms
m_LoggerWindow->Show(); // Logs m_PerformanceWindow->Show(m_Fps, m_Ms); // FPS & ms
m_LoggerWindow->Show(); // Logs
m_SceneWindow->Show(); m_SceneWindow->Show();
// After rendering // After rendering
m_PerformanceWindow->UpdatePerformanceStats(-1, -1);
m_PerformanceWindow->UpdatePerformanceStats(-1, g_GPU_Triangles_drawn_to_screen);
// End frame // End frame
EndFrame(); EndFrame();
} }
DEBUG_PRINT("[OK] Engine Run "); DEBUG_PRINT("[OK] Engine Run ");
} }
void MyEngine::Cleanup() void MyEngine::Cleanup()
{ {
DEBUG_PRINT("[START] Engine Cleanup "); DEBUG_PRINT("[START] Engine Cleanup ");
// ImGui cleanup // ImGui cleanup
ImGui_ImplOpenGL3_Shutdown(); ImGui_ImplOpenGL3_Shutdown();
ImGui_ImplGlfw_Shutdown(); ImGui_ImplGlfw_Shutdown();
@ -223,7 +243,6 @@ void MyEngine::Cleanup()
m_Running = false; m_Running = false;
DEBUG_PRINT("[OK] Engine Cleanup "); DEBUG_PRINT("[OK] Engine Cleanup ");
} }
void MyEngine::BeginFrame() void MyEngine::BeginFrame()
@ -250,10 +269,10 @@ void MyEngine::EndFrame()
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
// (Optional) handle multi-viewport // (Optional) handle multi-viewport
ImGuiIO& io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable) if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{ {
GLFWwindow* backup_current_context = glfwGetCurrentContext(); GLFWwindow *backup_current_context = glfwGetCurrentContext();
ImGui::UpdatePlatformWindows(); ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault(); ImGui::RenderPlatformWindowsDefault();
glfwMakeContextCurrent(backup_current_context); glfwMakeContextCurrent(backup_current_context);
@ -267,31 +286,28 @@ void MyEngine::ShowDockSpace()
{ {
static bool dockspaceOpen = true; static bool dockspaceOpen = true;
static bool opt_fullscreen = 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; ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
if (opt_fullscreen) if (opt_fullscreen)
{ {
ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGuiViewport *viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->WorkPos); ImGui::SetNextWindowPos(viewport->WorkPos);
ImGui::SetNextWindowSize(viewport->WorkSize); ImGui::SetNextWindowSize(viewport->WorkSize);
ImGui::SetNextWindowViewport(viewport->ID); ImGui::SetNextWindowViewport(viewport->ID);
window_flags |= ImGuiWindowFlags_NoTitleBar window_flags |= ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove;
| ImGuiWindowFlags_NoCollapse window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
| ImGuiWindowFlags_NoResize
| ImGuiWindowFlags_NoMove;
window_flags |= ImGuiWindowFlags_NoBringToFrontOnFocus
| ImGuiWindowFlags_NoNavFocus;
} }
// Style // Style adjustments
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
ImGui::Begin("DockSpace", &dockspaceOpen, window_flags); ImGui::Begin("DockSpace", &dockspaceOpen, window_flags);
ImGui::PopStyleVar(2); ImGui::PopStyleVar(2);
// Menu bar example // Menu bar
if (ImGui::BeginMenuBar()) if (ImGui::BeginMenuBar())
{ {
if (ImGui::BeginMenu("File")) if (ImGui::BeginMenu("File"))
@ -304,9 +320,12 @@ void MyEngine::ShowDockSpace()
} }
// DockSpace // DockSpace
ImGuiIO& io = ImGui::GetIO(); ImGuiIO &io = ImGui::GetIO();
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable) if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
{ {
// Optional: Log the flags for debugging
// DEBUG_PRINT("DockSpace Flags: %d", dockspace_flags);
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace"); ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags); ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
} }

View File

@ -18,7 +18,7 @@
#include "TestModel.h" #include "TestModel.h"
//#define DEBUG
#include "gcml.h" #include "gcml.h"
// Forward declaration to avoid including GLFW in the header if you prefer // Forward declaration to avoid including GLFW in the header if you prefer

View File

@ -7,10 +7,7 @@
#include <vector> #include <vector>
extern std::vector<GameObject> g_GameObjects; extern std::vector<GameObject> 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() void InspectorWindow::Show()
{ {
@ -22,261 +19,310 @@ void InspectorWindow::Show()
if (ImGui::Begin("Inspector")) if (ImGui::Begin("Inspector"))
{ {
// Title label (white text) // Title label (white text)
ImGui::TextUnformatted("Selected Object Inspector"); const char *objectName = "No Object Selected";
ImGui::Separator(); if (g_SelectedObject)
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.
{ {
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(); ImGui::Separator();
// -----------------------------------
// Rotation
// -----------------------------------
ImGui::TextUnformatted("Rotation");
ImGui::Spacing(); 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 // Transform* transform = &g_SelectedObject->transform;
ImGui::PushID("RotationRow"); std::shared_ptr<TransformComponent> transform = g_SelectedObject->GetComponent<TransformComponent>();
for (int i = 0; i < 3; i++) // printf("%p\n", &transform);
if (transform)
{ {
// Decide color sets for X, Y, Z
ImVec4 col, colH, colA; if (ImGui::IsItemHovered())
if (i == 0)
{ {
col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); ImGui::BeginTooltip();
colH = ImVec4(1.0f, 0.6f, 0.6f, 1.0f); ImGui::TextUnformatted("Controls the object's Position, Rotation, and Scale.");
colA = ImVec4(1.0f, 0.2f, 0.2f, 1.0f); ImGui::EndTooltip();
}
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); // Position
ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA); // -----------------------------------
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::Spacing();
ImGui::SetNextItemWidth(60.0f); ImGui::Separator();
ImGui::DragFloat((std::string("##Rot") + axisNames[i]).c_str(), &rot[i], 0.1f);
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::PushStyleColor(ImGuiCol_Text, ImVec4(1.0f, 1.0f, 0.4f, 1.0f));
ImGui::Separator(); bool meshOpen = ImGui::CollapsingHeader("Mesh##Main", ImGuiTreeNodeFlags_DefaultOpen);
ImGui::PopStyleColor();
// -----------------------------------
// Scale
// -----------------------------------
ImGui::TextUnformatted("Scale");
ImGui::Spacing();
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"); // Transform* transform = &g_SelectedObject->transform;
for (int i = 0; i < 3; i++) std::shared_ptr<MeshComponent> mesh = g_SelectedObject->GetComponent<MeshComponent>();
// printf("%p\n", &transform);
if (mesh)
{ {
// same color approach
ImVec4 col, colH, colA; int vao = static_cast<int>(mesh->vao);
if (i == 0) if (ImGui::DragInt("vao", &vao, 1, 0, 1024))
{ {
col = ImVec4(1.0f, 0.4f, 0.4f, 1.0f); mesh->vao = static_cast<GLuint>(vao);
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); int indexCount = static_cast<int>(mesh->indexCount);
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, colH); if (ImGui::DragInt("indexCount", &indexCount, 1, 0, 1024))
ImGui::PushStyleColor(ImGuiCol_ButtonActive, colA);
if (ImGui::Button(axisNames[i], ImVec2(20, 0)))
{ {
// No action mesh->indexCount = static_cast<GLuint>(indexCount);
} }
ImGui::PopStyleColor(3);
ImGui::SameLine(); int textureID = static_cast<int>(mesh->textureID);
ImGui::SetNextItemWidth(60.0f); if (ImGui::DragInt("textureID", &textureID, 1, 0, 1024))
ImGui::DragFloat((std::string("##Scl") + axisNames[i]).c_str(), &scl[i], 0.1f); {
mesh->textureID = static_cast<GLuint>(textureID);
if (i < 2) }
ImGui::SameLine(0, 15);
} }
ImGui::PopID();
} }
ImGui::Spacing(); 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 // Restore style
ImGui::PopStyleVar(3); ImGui::PopStyleVar(3);

View File

@ -7,6 +7,7 @@
extern int LoaddedAssets; extern int LoaddedAssets;
extern int g_GPU_Triangles_drawn_to_screen;
// Initialize static members // Initialize static members
int PerformanceWindow::m_OpenGLCallCount = 0; int PerformanceWindow::m_OpenGLCallCount = 0;
@ -41,6 +42,9 @@ void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangle
{ {
m_OpenGLCallCount = newCallCount; m_OpenGLCallCount = newCallCount;
m_TriangleCount = newTriangleCount; m_TriangleCount = newTriangleCount;
g_GPU_Triangles_drawn_to_screen = 0;
} }
void PerformanceWindow::Show(float fps, float ms) void PerformanceWindow::Show(float fps, float ms)
@ -138,14 +142,14 @@ void PerformanceWindow::Show(float fps, float ms)
300.0f, 300.0f,
ImVec2(0, 50)); ImVec2(0, 50));
ImGui::Text("Triangles: %d", m_TriangleCount); ImGui::Text("Indices: %d", m_TriangleCount);
ImGui::PlotHistogram("Triangles", ImGui::PlotHistogram("Indices",
s_TriangleHistory, s_TriangleHistory,
IM_ARRAYSIZE(s_TriangleHistory), IM_ARRAYSIZE(s_TriangleHistory),
0, 0,
nullptr, nullptr,
0.0f, 0.0f,
5000.0f, m_TriangleCount*2.5,
ImVec2(0, 50)); ImVec2(0, 50));
ImGui::Separator(); ImGui::Separator();

View File

@ -8,18 +8,18 @@
#include <glm/gtc/type_ptr.hpp> #include <glm/gtc/type_ptr.hpp>
#include "imgui.h" #include "imgui.h"
#include "gcml.h"
#include "Componenets/GameObject.h" #include "Componenets/GameObject.h"
#include "Componenets/Mesh.h" #include "Componenets/mesh.h"
#include "Componenets/Transform.h" #include "Componenets/transform.h"
extern std::vector<GameObject> g_GameObjects; extern std::vector<std::shared_ptr<GameObject>> g_GameObjects;
#define CAM_FOV 45.0f
#define CAM_NEAR_PLAIN 0.1f
#define CAM_FAR_PLAIN 1000.0f
#define CAM_FOV 45.0f
#define CAM_NEAR_PLAIN 0.1f
#define CAM_FAR_PLAIN 1000.0f
// Include your AssetManager & Shader headers // Include your AssetManager & Shader headers
#include "Engine/AssetManager.h" #include "Engine/AssetManager.h"
@ -28,64 +28,163 @@ extern std::vector<GameObject> g_GameObjects;
// Extern reference to our global (or extern) asset manager // Extern reference to our global (or extern) asset manager
extern AssetManager g_AssetManager; extern AssetManager g_AssetManager;
extern int g_GPU_Triangles_drawn_to_screen;
// Example cube data (position + UVs) // Example cube data (position + UVs)
static float g_CubeVertices[] = static float g_CubeVertices[] =
{ {
// FRONT (z=+1) // FRONT (z=+1)
-1.f, -1.f, 1.f, 0.f, 0.f, -1.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, 1.f, 1.f, 0.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) // BACK (z=-1)
-1.f, -1.f, -1.f, 1.f, 0.f, -1.f,
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,
-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) // LEFT (x=-1)
-1.f, -1.f, -1.f, 0.f, 0.f, -1.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, 1.f, -1.f, 0.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) // RIGHT (x=+1)
1.f, -1.f, -1.f, 1.f, 0.f, 1.f,
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,
-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) // TOP (y=+1)
-1.f, 1.f, -1.f, 0.f, 0.f, -1.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, 1.f, 1.f, 0.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) // BOTTOM (y=-1)
-1.f, -1.f, -1.f, 1.f, 0.f, -1.f,
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,
-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[] = static unsigned int g_CubeIndices[] =
{ {
// Front // Front
0,1,2, 2,3,0, 0, 1, 2, 2, 3, 0,
// Back // Back
4,5,6, 6,7,4, 4, 5, 6, 6, 7, 4,
// Left // Left
8,9,10, 10,11,8, 8, 9, 10, 10, 11, 8,
// Right // Right
12,13,14, 14,15,12, 12, 13, 14, 14, 15, 12,
// Top // Top
16,17,18, 18,19,16, 16, 17, 18, 18, 19, 16,
// Bottom // Bottom
20,21,22, 22,23,20 20, 21, 22, 22, 23, 20};
};
void RenderWindow::Show() void RenderWindow::Show()
{ {
ImGui::Begin("OpenGL Output"); ImGui::Begin("OpenGL Output");
ImVec2 size = ImGui::GetContentRegionAvail(); ImVec2 size = ImGui::GetContentRegionAvail();
@ -98,18 +197,23 @@ void RenderWindow::Show()
m_Initialized = true; m_Initialized = true;
} }
// If there's space, render to the FBO, then show it as an ImGui image // If there's space, render to the FBO, then show it as an ImGui image
if (w > 0 && h > 0) if (w > 0 && h > 0)
{ {
if (w != m_LastWidth || h != m_LastHeight) if (w != m_LastWidth || h != m_LastHeight)
{ {
m_FBO.Create(w, h); m_FBO.Create(w, h);
m_LastWidth = w; m_LastWidth = w;
m_LastHeight = h; m_LastHeight = h;
} }
RenderSceneToFBO(); 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 else
{ {
@ -117,6 +221,7 @@ void RenderWindow::Show()
} }
ImGui::End(); ImGui::End();
} }
void RenderWindow::InitGLResources() void RenderWindow::InitGLResources()
@ -124,15 +229,16 @@ void RenderWindow::InitGLResources()
// ---------------------------------------------------- // ----------------------------------------------------
// 1) Load SHADER from the asset manager // 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) if (!shaderAsset)
{ {
fprintf(stderr, "[RenderWindow] Failed to load shader via AssetManager.\n"); fprintf(stderr, "[RenderWindow] Failed to load shader via AssetManager.\n");
return; return;
} }
// Cast back to your Shader class // Cast back to your Shader class
m_ShaderPtr = static_cast<Shader*>(shaderAsset); m_ShaderPtr = static_cast<Shader *>(shaderAsset);
} }
// ---------------------------------------------------- // ----------------------------------------------------
@ -151,11 +257,11 @@ void RenderWindow::InitGLResources()
// Position = location 0, UV = location 1 // Position = location 0, UV = location 1
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
5 * sizeof(float), (void*)0); 5 * sizeof(float), (void *)0);
glEnableVertexAttribArray(0); glEnableVertexAttribArray(0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
5 * sizeof(float), (void*)(3 * sizeof(float))); 5 * sizeof(float), (void *)(3 * sizeof(float)));
glEnableVertexAttribArray(1); glEnableVertexAttribArray(1);
glBindVertexArray(0); glBindVertexArray(0);
@ -164,7 +270,7 @@ void RenderWindow::InitGLResources()
// 3) Load TEXTURE from the asset manager // 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) if (!texAsset)
{ {
fprintf(stderr, "[RenderWindow] Failed to load texture.\n"); fprintf(stderr, "[RenderWindow] Failed to load texture.\n");
@ -179,13 +285,15 @@ void RenderWindow::InitGLResources()
// ---------------------------------------------------- // ----------------------------------------------------
// 4) Initialize GameObjects // 4) Initialize GameObjects
// ---------------------------------------------------- // ----------------------------------------------------
}
}
void RenderWindow::RenderSceneToFBO() void RenderWindow::RenderSceneToFBO()
{ {
m_RotationAngle += 0.1f; // spin per frame
m_RotationAngle += 0.001f; // spin per frame
// Bind the FBO // Bind the FBO
m_FBO.Bind(); m_FBO.Bind();
@ -193,10 +301,11 @@ void RenderWindow::RenderSceneToFBO()
glEnable(GL_DEPTH_TEST); 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); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Use our loaded shader // Use our loaded shader
if (!m_ShaderPtr) if (!m_ShaderPtr)
return; // Can't render without a shader 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); glm::mat4 proj = glm::perspective(glm::radians(CAM_FOV), aspect, CAM_NEAR_PLAIN, CAM_FAR_PLAIN);
// Iterate over each GameObject and render it // 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); glm::mat4 model = glm::mat4(1.f);
// Translate
model = glm::translate(model, obj.transform.position);
// Rotate around X, Y, Z std::shared_ptr<TransformComponent> transform = obj->GetComponent<TransformComponent>();
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));
// Scale
model = glm::scale(model, obj.transform.scale);
// Compute MVP
glm::mat4 mvp = proj * view * model;
// Pass MVP to the shader std::shared_ptr<MeshComponent> mesh = obj->GetComponent<MeshComponent>();
GLint mvpLoc = glGetUniformLocation(programID, "uMVP");
glUniformMatrix4fv(mvpLoc, 1, GL_FALSE, glm::value_ptr(mvp));
// ----------------------------------- if (!transform) {
// 2) Bind the object's texture DEBUG_PRINT("Could not find Transform Component");
// ----------------------------------- }
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, obj.mesh.textureID);
// Set the sampler uniform to texture unit 0
GLint texLoc = glGetUniformLocation(programID, "uTexture");
glUniform1i(texLoc, 0);
// ----------------------------------- if (transform && mesh)
// 3) Draw the object's mesh {
// -----------------------------------
glBindVertexArray(obj.mesh.vao); // Translate
glDrawElements(GL_TRIANGLES, obj.mesh.indexCount, GL_UNSIGNED_INT, nullptr);
// Unbind for cleanliness g_GPU_Triangles_drawn_to_screen = static_cast<int>(mesh->indexCount);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0); 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 // Cleanup

View File

@ -5,35 +5,46 @@
// Include your asset manager and any other necessary headers // Include your asset manager and any other necessary headers
#include "Engine/AssetManager.h" #include "Engine/AssetManager.h"
#include "TestModel.h" #include "TestModel.h"
#include "gcml.h"
#include <iostream>
// Globals // Globals
extern std::vector<GameObject> g_GameObjects; extern std::vector<std::shared_ptr<GameObject>> g_GameObjects;
extern GameObject* g_SelectedObject; extern std::shared_ptr<GameObject> g_SelectedObject;
extern AssetManager g_AssetManager; extern AssetManager g_AssetManager;
// Constructor
// Helper: Create a default cube GameObject // Helper: Create a default cube GameObject
GameObject CreateDefaultCube() { std::shared_ptr<GameObject> CreateDefaultCube()
GameObject cube; {
cube.name = "Cube"; // Pseudocode:
cube.transform.position = glm::vec3(0.f, 0.f, 0.f); int newId = g_GameObjects.size();
cube.transform.rotation = glm::vec3(0.f, 0.5f, 0.f); auto newGameObject = std::make_shared<GameObject>(newId, ("New GameObject"));
cube.transform.scale = glm::vec3(1.f, 1.f, 1.f); newGameObject->AddComponent(std::make_shared<TransformComponent>()); // Ensure each entity has a TransformComponent by default
cube.mesh.vao = CreateCubeVAO(); // Implement your VAO creation logic newGameObject->AddComponent(std::make_shared<MeshComponent>()); // Ensure each entity has a TransformComponent by default
cube.mesh.indexCount = 36;
cube.mesh.textureID = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png"))); // Suppose we loaded a VAO, an EBO with 36 indices for the cube,
return cube; // and a texture ID from the asset manager
std::shared_ptr<MeshComponent> mesh = newGameObject->GetComponent<MeshComponent>();
mesh->vao = CreateCubeVAO();
mesh->indexCount = 36;
mesh->textureID = static_cast<GLuint>(reinterpret_cast<uintptr_t>(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png")));
return newGameObject;
} }
// Show function implementation void SceneWindow::Show()
void SceneWindow::Show() { {
if (ImGui::Begin("Scene Window")) { if (ImGui::Begin("Scene Window"))
{
// Add Button // Add Button
if (ImGui::Button("Add Object")) { if (ImGui::Button("Add Object"))
{
AddGameObject(); AddGameObject();
std::cout << "Added a new GameObject. Total objects: " << g_GameObjects.size() << std::endl;
} }
ImGui::Separator(); ImGui::Separator();
@ -41,25 +52,62 @@ void SceneWindow::Show() {
// Begin child region for the list to make it scrollable // Begin child region for the list to make it scrollable
ImGui::BeginChild("GameObjectList", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar); ImGui::BeginChild("GameObjectList", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar);
// List GameObjects // Define TreeNode flags for better visuals and interaction
for (int index = 0; index < static_cast<int>(g_GameObjects.size()); ++index) { ImGuiTreeNodeFlags nodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_SpanAvailWidth;
GameObject& obj = g_GameObjects[index];
bool isSelected = (g_SelectedObject == &obj);
// Create a selectable item for each GameObject // Iterate through GameObjects using index for unique identification
if (ImGui::Selectable(obj.name.c_str(), isSelected)) { for (size_t i = 0; i < g_GameObjects.size(); ++i)
g_SelectedObject = &obj; {
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 // Right-click context menu for GameObject actions
if (ImGui::BeginPopupContextItem()) { if (ImGui::BeginPopupContextItem())
if (ImGui::MenuItem("Remove")) { {
RemoveGameObject(index); // Delete GameObject Option
if (ImGui::MenuItem("Remove"))
{
std::cout << "Attempting to remove GameObject: " << obj->name << " with ID: " << obj->id << std::endl;
RemoveGameObject(static_cast<int>(i));
std::cout << "Removed GameObject: " << obj->name << std::endl;
ImGui::EndPopup(); 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(); 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(); ImGui::EndChild();
@ -67,14 +115,13 @@ void SceneWindow::Show() {
ImGui::Separator(); ImGui::Separator();
// Show currently selected object details at the bottom // Show currently selected object details at the bottom
if (g_SelectedObject) { if (g_SelectedObject)
{
ImGui::Text("Selected Object: %s", g_SelectedObject->name.c_str()); ImGui::Text("Selected Object: %s", g_SelectedObject->name.c_str());
// Optionally add details or editable fields here // Optionally, display more details or provide editing capabilities
// Example: }
// ImGui::DragFloat3("Position", &g_SelectedObject->transform.position.x, 0.1f); else
// ImGui::DragFloat3("Rotation", &g_SelectedObject->transform.rotation.x, 0.1f); {
// ImGui::DragFloat3("Scale", &g_SelectedObject->transform.scale.x, 0.1f);
} else {
ImGui::Text("No Object Selected"); ImGui::Text("No Object Selected");
} }
} }
@ -82,25 +129,38 @@ void SceneWindow::Show() {
} }
// AddGameObject: Adds a new GameObject // AddGameObject: Adds a new GameObject
void SceneWindow::AddGameObject() { void SceneWindow::AddGameObject()
GameObject newObj = CreateDefaultCube(); {
// Optionally, modify the name to ensure uniqueness std::shared_ptr<GameObject> newObj = CreateDefaultCube();
newObj.name += " " + std::to_string(g_GameObjects.size() + 1); // Modify the name to ensure uniqueness
newObj->name += " " + std::to_string(g_GameObjects.size());
g_GameObjects.push_back(newObj); g_GameObjects.push_back(newObj);
std::cout << "Added GameObject: " << newObj->name << " with ID: " << newObj->id << std::endl;
} }
// RemoveGameObject: Removes a GameObject by index // RemoveGameObject: Removes a GameObject by index
void SceneWindow::RemoveGameObject(int index) { void SceneWindow::RemoveGameObject(int index)
if (index >= 0 && index < static_cast<int>(g_GameObjects.size())) { {
if (index >= 0 && index < static_cast<int>(g_GameObjects.size()))
{
// If the object to be removed is selected, clear the selection // 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; 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); g_GameObjects.erase(g_GameObjects.begin() + index);
} }
else
{
std::cerr << "Attempted to remove GameObject with invalid index: " << index << std::endl;
}
} }
// GetSelectedObject function implementation // GetSelectedObject function implementation
GameObject* SceneWindow::GetSelectedObject() const { std::shared_ptr<GameObject> SceneWindow::GetSelectedObject() const
{
return g_SelectedObject; return g_SelectedObject;
} }

View File

@ -10,7 +10,7 @@
class SceneWindow { class SceneWindow {
public: public:
void Show(); void Show();
GameObject* GetSelectedObject() const; std::shared_ptr<GameObject> GetSelectedObject() const;
private: private:
void AddGameObject(); // Adds a new game object void AddGameObject(); // Adds a new game object

View File

@ -5,6 +5,7 @@
int main() int main()
{ {
DEBUG_PRINT("[START] Creating Global Engine "); DEBUG_PRINT("[START] Creating Global Engine ");