Merge branch 'Dev'
This commit is contained in:
commit
037561d2a5
31
Makefile
31
Makefile
@ -2,38 +2,48 @@
|
||||
|
||||
# Compiler and Flags
|
||||
CXX := g++
|
||||
CXXFLAGS := -Wall -Wextra -std=c++17
|
||||
CXXFLAGS := -Wall -Wextra -std=c++17 -g
|
||||
|
||||
# Directories
|
||||
SRC_DIR := src
|
||||
VENDOR_DIRS := vendor/imgui-docking vendor/stb # Removed vendor/glad
|
||||
VENDOR_DIRS := vendor/imgui-docking vendor/stb
|
||||
BUILD_DIR := build
|
||||
|
||||
# Include Directories
|
||||
# Add GLFW include paths
|
||||
GLFW_INCLUDE := C:/libraries/glfw/include
|
||||
INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/stb/include # Removed vendor/glad/include
|
||||
INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/stb/include
|
||||
INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/gcml
|
||||
INCLUDES := $(addprefix -I, $(INCLUDE_DIRS))
|
||||
|
||||
# Update compiler flags with include paths
|
||||
CXXFLAGS += $(INCLUDES)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Source Files
|
||||
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp)
|
||||
# 1) Recursively gather *.cpp in src (including subfolders).
|
||||
# 2) Gather *.cpp from vendor/imgui-docking, vendor/stb, etc.
|
||||
# -------------------------------------------------------------------------
|
||||
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp) \
|
||||
$(wildcard $(SRC_DIR)/**/*.cpp)
|
||||
|
||||
VENDOR_SRC := $(foreach dir, $(VENDOR_DIRS), $(wildcard $(dir)/*.cpp))
|
||||
STB_SRC := $(wildcard vendor/stb/src/*.cpp) # If stb has .cpp files
|
||||
ALL_SRC := $(SRC_FILES) $(VENDOR_SRC) $(STB_SRC)
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Object Files
|
||||
# Convert each .cpp to a corresponding .o under the build/ directory.
|
||||
# For example:
|
||||
# src/Engine.cpp -> build/src/Engine.o
|
||||
# src/Windows/LoggerWindow.cpp -> build/src/Windows/LoggerWindow.o
|
||||
# -------------------------------------------------------------------------
|
||||
OBJ_FILES := $(patsubst %.cpp, $(BUILD_DIR)/%.o, $(ALL_SRC))
|
||||
# Removed GLAD object files
|
||||
# OBJ_FILES += $(patsubst %.c, $(BUILD_DIR)/%.o, $(GLAD_SRC)) # Removed
|
||||
|
||||
# Target executable name
|
||||
TARGET := TesseractEngine.exe
|
||||
|
||||
# Libraries
|
||||
LIBS := -LC:/libraries/glfw/lib -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid -lwinmm
|
||||
LIBS := -LC:/libraries/glfw/lib -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid -lwinmm -lglew32 -lglu32
|
||||
|
||||
# Phony Targets
|
||||
.PHONY: all clean copy_assets
|
||||
@ -52,6 +62,7 @@ $(TARGET): $(OBJ_FILES)
|
||||
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
|
||||
|
||||
# Pattern rule to compile .cpp files to .o files
|
||||
# Note the mkdir on the $(dir $@) ensures subfolders under build/ exist.
|
||||
$(BUILD_DIR)/%.o: %.cpp
|
||||
@mkdir "$(dir $@)" >nul 2>&1 || echo Directory exists
|
||||
@echo Compiling $<...
|
||||
@ -60,5 +71,5 @@ $(BUILD_DIR)/%.o: %.cpp
|
||||
# Clean build artifacts
|
||||
clean:
|
||||
@echo Cleaning up...
|
||||
rmdir /s /q "$(BUILD_DIR)"
|
||||
del /q "$(TARGET)"
|
||||
if exist "$(BUILD_DIR)" rmdir /s /q "$(BUILD_DIR)"
|
||||
if exist "$(TARGET)" del /q "$(TARGET)"
|
||||
|
14
README.md
Normal file
14
README.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Tesseract-Engine
|
||||
|
||||
A 3D Game engine for Small to Medium-sized games with a LUA Scripting interface. written in C++ with a simple, Good looking interface.
|
||||
|
||||
## Screen Shots
|
||||
|
||||
### Note: These screenshots are sorted by version.
|
||||
|
||||
|
||||
#### 0.0.23
|
||||
![](./assets/images/SS-Dev1_1.png)
|
||||
|
||||
#### 0.0.15
|
||||
![](./assets/images/SS-Dev1_0.png)
|
BIN
assets/images/SS-Dev1_0.png
Normal file
BIN
assets/images/SS-Dev1_0.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 64 KiB |
BIN
assets/images/SS-Dev1_1.png
Normal file
BIN
assets/images/SS-Dev1_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 198 KiB |
18
assets/shaders/UnlitMaterial.frag
Normal file
18
assets/shaders/UnlitMaterial.frag
Normal file
@ -0,0 +1,18 @@
|
||||
#version 330 core
|
||||
|
||||
in vec2 vUV; // UV from vertex shader
|
||||
out vec4 FragColor; // Final color output
|
||||
|
||||
uniform vec4 uColor; // A user-set solid color
|
||||
uniform sampler2D uTexture; // Optional texture
|
||||
|
||||
void main()
|
||||
{
|
||||
// Sample the texture. If you don't want texturing, remove this.
|
||||
vec4 texColor = texture(uTexture, vUV);
|
||||
|
||||
// Multiply the texture by our uniform color.
|
||||
// If you want a pure color (no texture), just do:
|
||||
// FragColor = uColor;
|
||||
FragColor = texColor * texColor;
|
||||
}
|
14
assets/shaders/UnlitMaterial.vert
Normal file
14
assets/shaders/UnlitMaterial.vert
Normal file
@ -0,0 +1,14 @@
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec3 aPos; // Vertex position
|
||||
layout(location = 1) in vec2 aUV; // Texture UV coordinate (optional)
|
||||
|
||||
uniform mat4 uMVP; // Combined Model-View-Projection matrix
|
||||
|
||||
out vec2 vUV; // Pass UV to the fragment shader
|
||||
|
||||
void main()
|
||||
{
|
||||
vUV = aUV;
|
||||
gl_Position = uMVP * vec4(aPos, 1.0);
|
||||
}
|
BIN
assets/textures/default.png
Normal file
BIN
assets/textures/default.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 138 B |
BIN
assets/textures/player_1.png
Normal file
BIN
assets/textures/player_1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
assets/textures/wood.png
Normal file
BIN
assets/textures/wood.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 765 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/src/main.o
BIN
build/src/main.o
Binary file not shown.
BIN
build/vendor/glad/src/glad.o
vendored
BIN
build/vendor/glad/src/glad.o
vendored
Binary file not shown.
BIN
build/vendor/imgui-docking/imgui.o
vendored
BIN
build/vendor/imgui-docking/imgui.o
vendored
Binary file not shown.
BIN
build/vendor/imgui-docking/imgui_demo.o
vendored
BIN
build/vendor/imgui-docking/imgui_demo.o
vendored
Binary file not shown.
BIN
build/vendor/imgui-docking/imgui_draw.o
vendored
BIN
build/vendor/imgui-docking/imgui_draw.o
vendored
Binary file not shown.
BIN
build/vendor/imgui-docking/imgui_impl_glfw.o
vendored
BIN
build/vendor/imgui-docking/imgui_impl_glfw.o
vendored
Binary file not shown.
BIN
build/vendor/imgui-docking/imgui_impl_opengl3.o
vendored
BIN
build/vendor/imgui-docking/imgui_impl_opengl3.o
vendored
Binary file not shown.
BIN
build/vendor/imgui-docking/imgui_tables.o
vendored
BIN
build/vendor/imgui-docking/imgui_tables.o
vendored
Binary file not shown.
BIN
build/vendor/imgui-docking/imgui_widgets.o
vendored
BIN
build/vendor/imgui-docking/imgui_widgets.o
vendored
Binary file not shown.
BIN
build/vendor/stb/src/stb_image.o
vendored
BIN
build/vendor/stb/src/stb_image.o
vendored
Binary file not shown.
46
imgui.ini
46
imgui.ini
@ -1,46 +0,0 @@
|
||||
[Window][DockSpace Demo]
|
||||
Size=1280,720
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
Pos=60,60
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][Hello, world!]
|
||||
Pos=642,30
|
||||
Size=630,682
|
||||
Collapsed=0
|
||||
DockId=0x00000002,0
|
||||
|
||||
[Window][Hello, world!]
|
||||
Pos=8,30
|
||||
Size=1264,682
|
||||
Collapsed=0
|
||||
DockId=0x00000001,0
|
||||
|
||||
[Window][DockSpace]
|
||||
Pos=0,0
|
||||
Size=1280,720
|
||||
Collapsed=0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=8,8
|
||||
Size=1264,352
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=8,362
|
||||
Size=1264,350
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,8 Size=1264,704 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000003 Parent=0x14621557 SizeRef=1264,352 CentralNode=1 Selected=0xC450F867
|
||||
DockNode ID=0x00000004 Parent=0x14621557 SizeRef=1264,350 Selected=0xEA83D666
|
||||
DockSpace ID=0xC0DFADC4 Pos=8,30 Size=1264,682 Split=X Selected=0x1FC7AC8C
|
||||
DockNode ID=0x00000001 Parent=0xC0DFADC4 SizeRef=632,685 CentralNode=1 Selected=0xAAD7FFD4
|
||||
DockNode ID=0x00000002 Parent=0xC0DFADC4 SizeRef=630,685 Selected=0x1FC7AC8C
|
||||
|
15
src/Componenets/GameObject.h
Normal file
15
src/Componenets/GameObject.h
Normal file
@ -0,0 +1,15 @@
|
||||
// src/Components/GameObject.h
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include "Transform.h"
|
||||
#include "Mesh.h"
|
||||
|
||||
|
||||
struct GameObject
|
||||
{
|
||||
std::string name; // Unique name for the GameObject
|
||||
Transform transform; // Position, Rotation, Scale
|
||||
Mesh mesh; // Rendering Mesh
|
||||
// Add other components as needed
|
||||
};
|
12
src/Componenets/Mesh.h
Normal file
12
src/Componenets/Mesh.h
Normal file
@ -0,0 +1,12 @@
|
||||
|
||||
// Mesh.h
|
||||
#pragma once
|
||||
#include <GL/glew.h>
|
||||
|
||||
// A simple mesh storing a VAO, index count, and texture ID
|
||||
struct Mesh
|
||||
{
|
||||
GLuint vao = 0; // Vertex Array Object
|
||||
GLuint indexCount = 0; // Number of indices to draw
|
||||
GLuint textureID = 0; // The texture handle
|
||||
};
|
14
src/Componenets/Transform.h
Normal file
14
src/Componenets/Transform.h
Normal file
@ -0,0 +1,14 @@
|
||||
// Transform.h
|
||||
#pragma once
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
// A simple transform with position, rotation, scale
|
||||
struct Transform
|
||||
{
|
||||
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};
|
||||
};
|
||||
|
||||
|
||||
|
389
src/Engine.cpp
Normal file
389
src/Engine.cpp
Normal file
@ -0,0 +1,389 @@
|
||||
// src/Engine.cpp
|
||||
|
||||
|
||||
|
||||
// Settings
|
||||
|
||||
#define VSync 0
|
||||
|
||||
#include "Engine.h"
|
||||
#include <cstdio>
|
||||
#include <chrono>
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
// Dear ImGui
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
|
||||
#include "Windows/RenderWindow.h"
|
||||
#include "Windows/PerformanceWindow.h"
|
||||
#include "Windows/LoggerWindow.h"
|
||||
#include "Windows/InspectorWindow.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
AssetManager g_AssetManager;
|
||||
|
||||
LoggerWindow *g_LoggerWindow;
|
||||
|
||||
std::vector<GameObject> m_GameObjects;
|
||||
|
||||
|
||||
bool MyEngine::Init(int width, int height, const std::string& title)
|
||||
{
|
||||
DEBUG_PRINT("[START] Engine Init");
|
||||
// ------------------------------------------
|
||||
// 1) Initialize GLFW
|
||||
// ------------------------------------------
|
||||
if (!glfwInit())
|
||||
{
|
||||
fprintf(stderr, "[Engine] Failed to initialize GLFW\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Setup hints for OpenGL 3.3 Core
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
// Create window
|
||||
m_Window = glfwCreateWindow(width, height, title.c_str(), nullptr, nullptr);
|
||||
if (!m_Window)
|
||||
{
|
||||
fprintf(stderr, "[Engine] Failed to create GLFW window\n");
|
||||
glfwTerminate();
|
||||
return false;
|
||||
}
|
||||
glfwMakeContextCurrent(m_Window);
|
||||
glfwSwapInterval(VSync); // vsync
|
||||
|
||||
// ------------------------------------------
|
||||
// 2) Initialize GLEW
|
||||
// ------------------------------------------
|
||||
if (glewInit() != GLEW_OK)
|
||||
{
|
||||
fprintf(stderr, "[Engine] Failed to initialize GLEW\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
// 3) Initialize ImGui
|
||||
// ------------------------------------------
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
(void)io;
|
||||
// Enable docking
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
|
||||
// (Optional) Multi-viewport
|
||||
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable;
|
||||
|
||||
// Style
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
// Platform/Renderer bindings
|
||||
ImGui_ImplGlfw_InitForOpenGL(m_Window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
|
||||
// Initialize windows
|
||||
m_RenderWindow = std::make_unique<RenderWindow>();
|
||||
m_PerformanceWindow = std::make_unique<PerformanceWindow>();
|
||||
m_LoggerWindow = std::make_unique<LoggerWindow>();
|
||||
m_InspectorWindow = std::make_unique<InspectorWindow>();
|
||||
|
||||
|
||||
|
||||
// Some initial logs
|
||||
m_LoggerWindow->AddLog("Engine initialized.");
|
||||
m_LoggerWindow->AddLog("Welcome to Tesseract Engine!");
|
||||
|
||||
g_LoggerWindow = m_LoggerWindow.get();
|
||||
|
||||
m_Running = true;
|
||||
m_LastTime = glfwGetTime();
|
||||
DEBUG_PRINT("[OK] Engine Init ");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GLuint CreateCubeVAO()
|
||||
{
|
||||
// Define cube vertices (Position + UVs)
|
||||
static float g_CubeVertices[] =
|
||||
{
|
||||
// Front face
|
||||
-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 face
|
||||
-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 face
|
||||
-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 face
|
||||
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 face
|
||||
-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 face
|
||||
-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,
|
||||
};
|
||||
|
||||
// Define cube indices
|
||||
static unsigned int g_CubeIndices[] =
|
||||
{
|
||||
// Front face
|
||||
0, 1, 2, 2, 3, 0,
|
||||
// Back face
|
||||
4, 5, 6, 6, 7, 4,
|
||||
// Left face
|
||||
8, 9, 10, 10, 11, 8,
|
||||
// Right face
|
||||
12, 13, 14, 14, 15, 12,
|
||||
// Top face
|
||||
16, 17, 18, 18, 19, 16,
|
||||
// Bottom face
|
||||
20, 21, 22, 22, 23, 20
|
||||
};
|
||||
|
||||
GLuint VAO, VBO, EBO;
|
||||
|
||||
// Generate and bind VAO
|
||||
glGenVertexArrays(1, &VAO);
|
||||
glBindVertexArray(VAO);
|
||||
|
||||
// Generate and bind VBO
|
||||
glGenBuffers(1, &VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(g_CubeVertices), g_CubeVertices, GL_STATIC_DRAW);
|
||||
|
||||
// Generate and bind EBO
|
||||
glGenBuffers(1, &EBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_CubeIndices), g_CubeIndices, GL_STATIC_DRAW);
|
||||
|
||||
// Define vertex attributes
|
||||
// Position attribute (location = 0)
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
|
||||
5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
// UV attribute (location = 1)
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
|
||||
5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
// Unbind VAO (not EBO!)
|
||||
glBindVertexArray(0);
|
||||
|
||||
// Optionally, unbind VBO and EBO for cleanliness
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
// Debug: Print VAO ID
|
||||
printf("[MeshUtils] Initialized CubeVAO with ID: %u\n", VAO);
|
||||
|
||||
return VAO;
|
||||
}
|
||||
|
||||
void MyEngine::Run()
|
||||
{
|
||||
DEBUG_PRINT("[START] Engine Run ");
|
||||
|
||||
|
||||
// Pseudocode:
|
||||
GameObject 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);
|
||||
|
||||
// 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<GLuint>(reinterpret_cast<uintptr_t>(g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png")));
|
||||
|
||||
m_GameObjects.push_back(cube);
|
||||
|
||||
// Possibly create more GameObjects with different positions or textures
|
||||
|
||||
|
||||
while (!glfwWindowShouldClose(m_Window) && m_Running)
|
||||
{
|
||||
// Poll
|
||||
glfwPollEvents();
|
||||
|
||||
// Calculate FPS
|
||||
double current_time = glfwGetTime();
|
||||
double delta = current_time - m_LastTime;
|
||||
m_FrameCount++;
|
||||
if (delta >= 0.1)
|
||||
{
|
||||
m_Fps = (float)(m_FrameCount / delta);
|
||||
m_Ms = 100.0f / m_Fps;
|
||||
m_FrameCount = 0;
|
||||
m_LastTime = current_time;
|
||||
}
|
||||
|
||||
// Start new frame
|
||||
BeginFrame();
|
||||
|
||||
// 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
|
||||
|
||||
// After rendering
|
||||
m_PerformanceWindow->UpdatePerformanceStats(-1, -1);
|
||||
|
||||
|
||||
// End frame
|
||||
EndFrame();
|
||||
}
|
||||
DEBUG_PRINT("[OK] Engine Run ");
|
||||
|
||||
}
|
||||
|
||||
void MyEngine::Cleanup()
|
||||
{
|
||||
DEBUG_PRINT("[START] Engine Cleanup ");
|
||||
|
||||
// ImGui cleanup
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
// GLFW cleanup
|
||||
if (m_Window)
|
||||
{
|
||||
glfwDestroyWindow(m_Window);
|
||||
m_Window = nullptr;
|
||||
}
|
||||
glfwTerminate();
|
||||
|
||||
m_Running = false;
|
||||
DEBUG_PRINT("[OK] Engine Cleanup ");
|
||||
|
||||
}
|
||||
|
||||
void MyEngine::BeginFrame()
|
||||
{
|
||||
// ImGui new frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
}
|
||||
|
||||
void MyEngine::EndFrame()
|
||||
{
|
||||
// Render ImGui
|
||||
ImGui::Render();
|
||||
|
||||
// Clear the default framebuffer
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(m_Window, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(0.05f, 0.05f, 0.06f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Draw the ImGui data
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
// (Optional) handle multi-viewport
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
{
|
||||
GLFWwindow* backup_current_context = glfwGetCurrentContext();
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
glfwMakeContextCurrent(backup_current_context);
|
||||
}
|
||||
|
||||
// Swap
|
||||
glfwSwapBuffers(m_Window);
|
||||
}
|
||||
|
||||
void MyEngine::ShowDockSpace()
|
||||
{
|
||||
static bool dockspaceOpen = true;
|
||||
static bool opt_fullscreen = true;
|
||||
static ImGuiDockNodeFlags dockspace_flags = ImGuiDockNodeFlags_None;
|
||||
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoDocking;
|
||||
if (opt_fullscreen)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Style
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
|
||||
ImGui::Begin("DockSpace", &dockspaceOpen, window_flags);
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
// Menu bar example
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("File"))
|
||||
{
|
||||
if (ImGui::MenuItem("Exit"))
|
||||
m_Running = false; // Stop the engine
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
// DockSpace
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
|
||||
{
|
||||
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), dockspace_flags);
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("Docking is not enabled. Set io.ConfigFlags |= ImGuiConfigFlags_DockingEnable.");
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
60
src/Engine.h
Normal file
60
src/Engine.h
Normal file
@ -0,0 +1,60 @@
|
||||
// src/Engine.h
|
||||
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include "Windows/RenderWindow.h"
|
||||
#include "Windows/PerformanceWindow.h"
|
||||
#include "Windows/LoggerWindow.h"
|
||||
#include "Engine/AssetManager.h"
|
||||
#include "Windows/InspectorWindow.h"
|
||||
|
||||
#include "Componenets/GameObject.h"
|
||||
#include "Componenets/Mesh.h"
|
||||
#include "Componenets/Transform.h"
|
||||
|
||||
#include "TestModel.h"
|
||||
|
||||
|
||||
//#define DEBUG
|
||||
#include "gcml.h"
|
||||
|
||||
// Forward declaration to avoid including GLFW in the header if you prefer
|
||||
struct GLFWwindow;
|
||||
|
||||
// The main engine class that owns the application loop
|
||||
class MyEngine
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
bool Init(int width, int height, const std::string& title);
|
||||
void Run();
|
||||
void Cleanup();
|
||||
|
||||
private:
|
||||
// Internal helpers
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
void ShowDockSpace();
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
GLFWwindow* m_Window = nullptr;
|
||||
bool m_Running = false;
|
||||
|
||||
// Windows
|
||||
std::unique_ptr<RenderWindow> m_RenderWindow;
|
||||
std::unique_ptr<PerformanceWindow> m_PerformanceWindow;
|
||||
std::unique_ptr<LoggerWindow> m_LoggerWindow;
|
||||
std::unique_ptr<InspectorWindow> m_InspectorWindow;
|
||||
|
||||
|
||||
// For FPS calculation
|
||||
float m_Fps = 0.0f;
|
||||
float m_Ms = 0.0f;
|
||||
double m_LastTime = 0.0;
|
||||
int m_FrameCount = 0;
|
||||
};
|
147
src/Engine/AssetManager.cpp
Normal file
147
src/Engine/AssetManager.cpp
Normal file
@ -0,0 +1,147 @@
|
||||
#include "Engine/AssetManager.h"
|
||||
#include <iostream>
|
||||
|
||||
// Include your Shader class
|
||||
#include "Rendering/Shader.h"
|
||||
|
||||
#include "Windows/LoggerWindow.h"
|
||||
|
||||
// Include OpenGL loader (GLEW) for texture creation
|
||||
#include <GL/glew.h>
|
||||
|
||||
// For texture loading
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb/stb_image.h"
|
||||
|
||||
int LoaddedAssets = 0;
|
||||
|
||||
extern LoggerWindow *g_LoggerWindow;
|
||||
|
||||
void* AssetManager::loadAsset(AssetType type, const std::string& path)
|
||||
{
|
||||
// 1) Create a unique key for cache lookup
|
||||
std::string key = generateKey(type, path);
|
||||
|
||||
// 2) Check if it’s already loaded
|
||||
auto it = m_AssetMap.find(key);
|
||||
if (it != m_AssetMap.end())
|
||||
{
|
||||
// Return existing pointer
|
||||
return it->second.data;
|
||||
}
|
||||
|
||||
// 3) Not loaded yet, load from disk
|
||||
void* assetData = loadAssetFromDisk(type, path);
|
||||
if (!assetData)
|
||||
{
|
||||
std::cerr << "[AssetManager] Failed to load asset: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// 4) Store in cache
|
||||
GenericAsset newAsset;
|
||||
newAsset.data = assetData;
|
||||
m_AssetMap[key] = newAsset;
|
||||
|
||||
LoaddedAssets += 1;
|
||||
|
||||
g_LoggerWindow->AddLog("Loadded Asset: %s", path.c_str());
|
||||
|
||||
// 5) Return pointer
|
||||
return assetData;
|
||||
}
|
||||
|
||||
std::string AssetManager::generateKey(AssetType type, const std::string& path)
|
||||
{
|
||||
return std::to_string(static_cast<int>(type)) + ":" + path;
|
||||
}
|
||||
|
||||
void* AssetManager::loadAssetFromDisk(AssetType type, const std::string& path)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case AssetType::TEXTURE:
|
||||
{
|
||||
// --------------------------------------------
|
||||
// Load a texture with stb_image
|
||||
// --------------------------------------------
|
||||
std::cout << "[AssetManager] Loading TEXTURE from: " << path << std::endl;
|
||||
|
||||
int width, height, channels;
|
||||
unsigned char* data = stbi_load(path.c_str(), &width, &height, &channels, 0);
|
||||
if (!data)
|
||||
{
|
||||
std::cerr << "[AssetManager] stb_image failed for: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GLenum format = GL_RGBA;
|
||||
if (channels == 1) format = GL_RED;
|
||||
else if (channels == 3) format = GL_RGB;
|
||||
// if channels == 4, already GL_RGBA
|
||||
|
||||
GLuint texID = 0;
|
||||
glGenTextures(1, &texID);
|
||||
glBindTexture(GL_TEXTURE_2D, texID);
|
||||
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0,
|
||||
format, GL_UNSIGNED_BYTE, data);
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
// Set texture params
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
// Cleanup
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
stbi_image_free(data);
|
||||
|
||||
// Return as void*
|
||||
return reinterpret_cast<void*>(static_cast<uintptr_t>(texID));
|
||||
}
|
||||
|
||||
case AssetType::SHADER:
|
||||
{
|
||||
// --------------------------------------------
|
||||
// Load a shader using your existing "Shader" class
|
||||
// --------------------------------------------
|
||||
// Example usage: path = "shaders/UnlitMaterial" =>
|
||||
// loads "shaders/UnlitMaterial.vert" and "shaders/UnlitMaterial.frag"
|
||||
std::cout << "[AssetManager] Loading SHADER from: " << path << std::endl;
|
||||
|
||||
// Create a new Shader object on the heap
|
||||
Shader* newShader = new Shader();
|
||||
|
||||
// Build actual paths from the base path
|
||||
std::string vertPath = path + ".vert";
|
||||
std::string fragPath = path + ".frag";
|
||||
|
||||
// Attempt to load
|
||||
if (!newShader->Load(vertPath, fragPath))
|
||||
{
|
||||
std::cerr << "[AssetManager] Could not load shader: "
|
||||
<< vertPath << " / " << fragPath << std::endl;
|
||||
delete newShader; // Cleanup
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Return as void*
|
||||
return reinterpret_cast<void*>(newShader);
|
||||
}
|
||||
|
||||
case AssetType::SOUND:
|
||||
{
|
||||
std::cout << "[AssetManager] Loading SOUND from: " << path << std::endl;
|
||||
// Stub or real code to load .wav / .ogg
|
||||
return (void*)0xAAAA8888; // placeholder
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
std::cerr << "[AssetManager] Unknown asset type for: " << path << std::endl;
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
}
|
47
src/Engine/AssetManager.h
Normal file
47
src/Engine/AssetManager.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
// Forward-declare your Shader class
|
||||
class Shader;
|
||||
|
||||
// Define types of assets
|
||||
enum class AssetType
|
||||
{
|
||||
TEXTURE,
|
||||
SHADER,
|
||||
SOUND,
|
||||
// Add more as you need
|
||||
};
|
||||
|
||||
// A simple struct to hold the generic pointer
|
||||
struct GenericAsset
|
||||
{
|
||||
void* data = nullptr;
|
||||
};
|
||||
|
||||
// The main AssetManager
|
||||
class AssetManager
|
||||
{
|
||||
public:
|
||||
AssetManager() = default;
|
||||
~AssetManager() = default;
|
||||
|
||||
// Load an asset from disk (texture, shader, etc.)
|
||||
// Returns a void* pointer to the loaded resource.
|
||||
// - For TEXTURE, cast to (GLuint)
|
||||
// - For SHADER, cast to (Shader*)
|
||||
// - For SOUND, cast to whatever you store
|
||||
void* loadAsset(AssetType type, const std::string& path);
|
||||
|
||||
private:
|
||||
// Cache of already loaded assets: key = "type + path"
|
||||
std::unordered_map<std::string, GenericAsset> m_AssetMap;
|
||||
|
||||
// Generate the unique key
|
||||
std::string generateKey(AssetType type, const std::string& path);
|
||||
|
||||
// Actual loading from disk
|
||||
void* loadAssetFromDisk(AssetType type, const std::string& path);
|
||||
};
|
81
src/Rendering/FBO.cpp
Normal file
81
src/Rendering/FBO.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
// src/Rendering/FBO.cpp
|
||||
|
||||
#include "FBO.h"
|
||||
#include <cstdio>
|
||||
|
||||
bool FBO::Create(int width, int height)
|
||||
{
|
||||
Cleanup(); // In case we already had one
|
||||
|
||||
m_Width = width;
|
||||
m_Height = height;
|
||||
|
||||
// 1) Generate FBO
|
||||
glGenFramebuffers(1, &m_FBO);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
|
||||
|
||||
// 2) Create Texture
|
||||
glGenTextures(1, &m_TextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, m_TextureID);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0,
|
||||
GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
|
||||
GL_TEXTURE_2D, m_TextureID, 0);
|
||||
|
||||
// 3) Create RBO for depth/stencil
|
||||
glGenRenderbuffers(1, &m_RBO);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, m_RBO);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, width, height);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
|
||||
GL_RENDERBUFFER, m_RBO);
|
||||
|
||||
// 4) Check completeness
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
fprintf(stderr, "[FBO] Framebuffer not complete!\n");
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
Cleanup();
|
||||
return false;
|
||||
}
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FBO::Cleanup()
|
||||
{
|
||||
if (m_TextureID)
|
||||
{
|
||||
glDeleteTextures(1, &m_TextureID);
|
||||
m_TextureID = 0;
|
||||
}
|
||||
if (m_RBO)
|
||||
{
|
||||
glDeleteRenderbuffers(1, &m_RBO);
|
||||
m_RBO = 0;
|
||||
}
|
||||
if (m_FBO)
|
||||
{
|
||||
glDeleteFramebuffers(1, &m_FBO);
|
||||
m_FBO = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void FBO::Bind()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_FBO);
|
||||
}
|
||||
|
||||
void FBO::Unbind()
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
ImTextureID FBO::GetTextureID() const
|
||||
{
|
||||
// For OpenGL + ImGui, typically cast GLuint to (ImTextureID) via uintptr_t
|
||||
return (ImTextureID)(uintptr_t)m_TextureID;
|
||||
}
|
37
src/Rendering/FBO.h
Normal file
37
src/Rendering/FBO.h
Normal file
@ -0,0 +1,37 @@
|
||||
// src/Rendering/FBO.h
|
||||
|
||||
#pragma once
|
||||
#include <GL/glew.h>
|
||||
#include "imgui.h"
|
||||
|
||||
// A simple FBO wrapper
|
||||
class FBO
|
||||
{
|
||||
public:
|
||||
FBO() = default;
|
||||
~FBO() { Cleanup(); }
|
||||
|
||||
// Create the FBO with a given size
|
||||
bool Create(int width, int height);
|
||||
|
||||
// Cleanup
|
||||
void Cleanup();
|
||||
|
||||
// Bind / Unbind
|
||||
void Bind();
|
||||
static void Unbind();
|
||||
|
||||
// The texture ID to use in ImGui::Image()
|
||||
ImTextureID GetTextureID() const;
|
||||
|
||||
// Size info
|
||||
int GetWidth() const { return m_Width; }
|
||||
int GetHeight() const { return m_Height; }
|
||||
|
||||
private:
|
||||
GLuint m_FBO = 0;
|
||||
GLuint m_TextureID = 0;
|
||||
GLuint m_RBO = 0;
|
||||
int m_Width = 0;
|
||||
int m_Height = 0;
|
||||
};
|
95
src/Rendering/Shader.cpp
Normal file
95
src/Rendering/Shader.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
#include "Shader.h"
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
|
||||
Shader::~Shader()
|
||||
{
|
||||
if (m_ProgramID)
|
||||
glDeleteProgram(m_ProgramID);
|
||||
}
|
||||
|
||||
bool Shader::Load(const std::string& vertexPath, const std::string& fragmentPath)
|
||||
{
|
||||
// 1) Create shader objects
|
||||
GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
|
||||
GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
|
||||
// 2) Load sources
|
||||
std::string vertSource = LoadSourceFromFile(vertexPath);
|
||||
std::string fragSource = LoadSourceFromFile(fragmentPath);
|
||||
if (vertSource.empty() || fragSource.empty())
|
||||
{
|
||||
std::cerr << "[Shader] Failed to read shader files." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3) Compile vertex shader
|
||||
{
|
||||
const char* src = vertSource.c_str();
|
||||
glShaderSource(vertexShader, 1, &src, nullptr);
|
||||
glCompileShader(vertexShader);
|
||||
if (!CompileShader(vertexShader, vertexPath))
|
||||
return false;
|
||||
}
|
||||
|
||||
// 4) Compile fragment shader
|
||||
{
|
||||
const char* src = fragSource.c_str();
|
||||
glShaderSource(fragmentShader, 1, &src, nullptr);
|
||||
glCompileShader(fragmentShader);
|
||||
if (!CompileShader(fragmentShader, fragmentPath))
|
||||
return false;
|
||||
}
|
||||
|
||||
// 5) Create program and link
|
||||
m_ProgramID = glCreateProgram();
|
||||
glAttachShader(m_ProgramID, vertexShader);
|
||||
glAttachShader(m_ProgramID, fragmentShader);
|
||||
glLinkProgram(m_ProgramID);
|
||||
|
||||
// Check link status
|
||||
GLint success;
|
||||
glGetProgramiv(m_ProgramID, GL_LINK_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
char infoLog[1024];
|
||||
glGetProgramInfoLog(m_ProgramID, 1024, nullptr, infoLog);
|
||||
std::cerr << "[Shader] Program linking failed:\n" << infoLog << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Cleanup shader objects after linking
|
||||
glDeleteShader(vertexShader);
|
||||
glDeleteShader(fragmentShader);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Shader::CompileShader(GLuint shaderID, const std::string& filePath)
|
||||
{
|
||||
GLint success;
|
||||
glGetShaderiv(shaderID, GL_COMPILE_STATUS, &success);
|
||||
if (!success)
|
||||
{
|
||||
char infoLog[1024];
|
||||
glGetShaderInfoLog(shaderID, 1024, nullptr, infoLog);
|
||||
std::cerr << "[Shader] Compilation error in " << filePath << ":\n"
|
||||
<< infoLog << std::endl;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Shader::LoadSourceFromFile(const std::string& filePath)
|
||||
{
|
||||
std::ifstream file(filePath);
|
||||
if (!file.is_open())
|
||||
{
|
||||
std::cerr << "[Shader] Could not open file: " << filePath << std::endl;
|
||||
return "";
|
||||
}
|
||||
std::stringstream buffer;
|
||||
buffer << file.rdbuf();
|
||||
return buffer.str();
|
||||
}
|
25
src/Rendering/Shader.h
Normal file
25
src/Rendering/Shader.h
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <GL/glew.h>
|
||||
|
||||
class Shader
|
||||
{
|
||||
public:
|
||||
Shader() = default;
|
||||
~Shader();
|
||||
|
||||
// Load & compile from files (vertex & fragment)
|
||||
bool Load(const std::string& vertexPath, const std::string& fragmentPath);
|
||||
|
||||
void Use() const { glUseProgram(m_ProgramID); }
|
||||
|
||||
// Uniform helper
|
||||
GLuint GetProgramID() const { return m_ProgramID; }
|
||||
|
||||
private:
|
||||
bool CompileShader(GLuint shaderID, const std::string& source);
|
||||
std::string LoadSourceFromFile(const std::string& filePath);
|
||||
|
||||
private:
|
||||
GLuint m_ProgramID = 0;
|
||||
};
|
0
src/TestModel.h
Normal file
0
src/TestModel.h
Normal file
279
src/Windows/InspectorWindow.cpp
Normal file
279
src/Windows/InspectorWindow.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
#include "InspectorWindow.h"
|
||||
#include <cstdio> // for debugging or printing if needed
|
||||
#include <cstring> // for strcpy, if needed
|
||||
|
||||
#include <glm/gtc/type_ptr.hpp> // Required for glm::value_ptr
|
||||
|
||||
#include <vector>
|
||||
|
||||
extern std::vector<GameObject> m_GameObjects;
|
||||
|
||||
void InspectorWindow::Show()
|
||||
{
|
||||
// Increase window/item spacing for a cleaner look
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12, 12));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6, 4));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(10, 10));
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
Transform* transform = &m_GameObjects[0].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();
|
||||
|
||||
{
|
||||
// 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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
35
src/Windows/InspectorWindow.h
Normal file
35
src/Windows/InspectorWindow.h
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <glm/glm.hpp> // or <glm/vec3.hpp> if you prefer
|
||||
#include "imgui.h"
|
||||
|
||||
#include "Componenets/GameObject.h"
|
||||
#include "Componenets/Mesh.h"
|
||||
#include "Componenets/Transform.h"
|
||||
|
||||
|
||||
// Example struct for a Script component
|
||||
struct Script
|
||||
{
|
||||
std::string scriptName = "MyBehavior.lua";
|
||||
bool enabled = true;
|
||||
};
|
||||
|
||||
// The Inspector window class
|
||||
class InspectorWindow
|
||||
{
|
||||
public:
|
||||
// Constructor / Destructor
|
||||
InspectorWindow() = default;
|
||||
~InspectorWindow() = default;
|
||||
|
||||
// Show the window (call each frame)
|
||||
// Pass references to your components, so any changes get applied to them.
|
||||
void Show();
|
||||
|
||||
private:
|
||||
|
||||
// You can store additional state or styling here if needed
|
||||
// e.g. bool m_SomeInternalFlag = false;
|
||||
};
|
31
src/Windows/LoggerWindow.cpp
Normal file
31
src/Windows/LoggerWindow.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
// src/Windows/LoggerWindow.cpp
|
||||
|
||||
#include "LoggerWindow.h"
|
||||
#include "imgui.h"
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
void LoggerWindow::AddLog(const char* fmt, ...)
|
||||
{
|
||||
char buffer[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
va_end(args);
|
||||
|
||||
m_Logs.push_back(buffer);
|
||||
}
|
||||
|
||||
void LoggerWindow::Show()
|
||||
{
|
||||
ImGui::Begin("Logger");
|
||||
|
||||
if (ImGui::Button("Clear"))
|
||||
m_Logs.clear();
|
||||
|
||||
ImGui::Separator();
|
||||
for (const auto& logLine : m_Logs)
|
||||
ImGui::TextUnformatted(logLine.c_str());
|
||||
|
||||
ImGui::End();
|
||||
}
|
18
src/Windows/LoggerWindow.h
Normal file
18
src/Windows/LoggerWindow.h
Normal file
@ -0,0 +1,18 @@
|
||||
// src/Windows/LoggerWindow.h
|
||||
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
class LoggerWindow
|
||||
{
|
||||
public:
|
||||
// Add logs from anywhere
|
||||
void AddLog(const char* fmt, ...);
|
||||
|
||||
// Show the ImGui window
|
||||
void Show();
|
||||
|
||||
private:
|
||||
std::vector<std::string> m_Logs;
|
||||
};
|
152
src/Windows/PerformanceWindow.cpp
Normal file
152
src/Windows/PerformanceWindow.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "PerformanceWindow.h"
|
||||
#include "imgui.h"
|
||||
#include <algorithm> // for std::max_element, etc.
|
||||
|
||||
extern int LoaddedAssets;
|
||||
|
||||
// Initialize static members
|
||||
int PerformanceWindow::m_OpenGLCallCount = 0;
|
||||
int PerformanceWindow::m_TriangleCount = 0;
|
||||
|
||||
// We'll store up to 60 data points for each stat.
|
||||
static float s_FpsHistory[60] = {0.0f};
|
||||
static float s_MsHistory[60] = {0.0f};
|
||||
static float s_CallsHistory[60] = {0.0f};
|
||||
static float s_TriangleHistory[60] = {0.0f};
|
||||
|
||||
// Current dynamic max scale for FPS and ms
|
||||
static float s_FpsScale = 120.0f; // default starting scale for FPS
|
||||
static float s_MsScale = 25.0f; // default starting scale for ms
|
||||
|
||||
// This function shifts the old values left and appends a new value at the end.
|
||||
static void PushValueToHistory(float* historyArray, int historySize, float newValue)
|
||||
{
|
||||
for (int i = 0; i < historySize - 1; i++)
|
||||
historyArray[i] = historyArray[i + 1];
|
||||
historyArray[historySize - 1] = newValue;
|
||||
}
|
||||
|
||||
// We'll track when we last pushed data to our history.
|
||||
static double s_LastPushTime = 0.0;
|
||||
|
||||
// We'll also track when we last updated the scale
|
||||
static double s_LastScaleUpdate = 0.0;
|
||||
|
||||
// Update counters from the outside
|
||||
void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangleCount)
|
||||
{
|
||||
m_OpenGLCallCount = newCallCount;
|
||||
m_TriangleCount = newTriangleCount;
|
||||
}
|
||||
|
||||
void PerformanceWindow::Show(float fps, float ms)
|
||||
{
|
||||
// 1) Get current time from ImGui's internal clock
|
||||
double currentTime = ImGui::GetTime();
|
||||
|
||||
// 2) If at least 0.05s has passed, push new data (about 20 updates per second)
|
||||
if ((currentTime - s_LastPushTime) >= 0.05)
|
||||
{
|
||||
s_LastPushTime = currentTime;
|
||||
|
||||
// Push new values into our history arrays
|
||||
PushValueToHistory(s_FpsHistory, 60, fps);
|
||||
PushValueToHistory(s_MsHistory, 60, ms);
|
||||
PushValueToHistory(s_CallsHistory, 60, (float)m_OpenGLCallCount);
|
||||
PushValueToHistory(s_TriangleHistory, 60, (float)m_TriangleCount);
|
||||
}
|
||||
|
||||
// 3) Every 1 second, recalculate the max scale for FPS and ms
|
||||
if ((currentTime - s_LastScaleUpdate) >= 1.0)
|
||||
{
|
||||
s_LastScaleUpdate = currentTime;
|
||||
|
||||
// Find the maximum in s_FpsHistory
|
||||
float maxFps = 0.0f;
|
||||
for (int i = 0; i < 60; i++)
|
||||
{
|
||||
if (s_FpsHistory[i] > maxFps)
|
||||
maxFps = s_FpsHistory[i];
|
||||
}
|
||||
// Scale it by +15%, ensure it's not below 1.0
|
||||
maxFps *= 1.15f;
|
||||
if (maxFps < 1.0f) maxFps = 1.0f;
|
||||
s_FpsScale = maxFps;
|
||||
|
||||
// Find the maximum in s_MsHistory
|
||||
float maxMs = 0.0f;
|
||||
for (int i = 0; i < 60; i++)
|
||||
{
|
||||
if (s_MsHistory[i] > maxMs)
|
||||
maxMs = s_MsHistory[i];
|
||||
}
|
||||
// Scale it by +15%, ensure it's not below 1.0
|
||||
maxMs *= 1.15f;
|
||||
if (maxMs < 1.0f) maxMs = 1.0f;
|
||||
s_MsScale = maxMs;
|
||||
}
|
||||
|
||||
// Optional style adjustments
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
|
||||
ImGui::Begin("Performance");
|
||||
|
||||
// Colored header
|
||||
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats");
|
||||
ImGui::Separator();
|
||||
|
||||
// Show current FPS/ms
|
||||
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "FPS: %.1f", fps);
|
||||
ImGui::SameLine();
|
||||
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.8f, 1.0f), "| ms: %.3f", ms);
|
||||
|
||||
// Graphs for FPS + MS
|
||||
// min = 0, max = s_FpsScale or s_MsScale
|
||||
ImGui::PlotLines("FPS",
|
||||
s_FpsHistory,
|
||||
IM_ARRAYSIZE(s_FpsHistory),
|
||||
0,
|
||||
nullptr,
|
||||
0.0f,
|
||||
s_FpsScale,
|
||||
ImVec2(0, 60));
|
||||
|
||||
ImGui::PlotHistogram("ms/frame",
|
||||
s_MsHistory,
|
||||
IM_ARRAYSIZE(s_MsHistory),
|
||||
0,
|
||||
nullptr,
|
||||
0.0f,
|
||||
s_MsScale,
|
||||
ImVec2(0, 60));
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Show OpenGL calls + Triangles
|
||||
ImGui::Text("OpenGL Calls: %d", m_OpenGLCallCount);
|
||||
ImGui::PlotLines("GL Calls",
|
||||
s_CallsHistory,
|
||||
IM_ARRAYSIZE(s_CallsHistory),
|
||||
0,
|
||||
nullptr,
|
||||
0.0f,
|
||||
300.0f,
|
||||
ImVec2(0, 50));
|
||||
|
||||
ImGui::Text("Triangles: %d", m_TriangleCount);
|
||||
ImGui::PlotHistogram("Triangles",
|
||||
s_TriangleHistory,
|
||||
IM_ARRAYSIZE(s_TriangleHistory),
|
||||
0,
|
||||
nullptr,
|
||||
0.0f,
|
||||
5000.0f,
|
||||
ImVec2(0, 50));
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
// Show asset count
|
||||
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "Assets: %d", LoaddedAssets);
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleVar();
|
||||
}
|
22
src/Windows/PerformanceWindow.h
Normal file
22
src/Windows/PerformanceWindow.h
Normal file
@ -0,0 +1,22 @@
|
||||
// src/Windows/PerformanceWindow.h
|
||||
|
||||
#pragma once
|
||||
|
||||
class PerformanceWindow
|
||||
{
|
||||
public:
|
||||
// Displays the performance window in ImGui.
|
||||
// fps = frames per second
|
||||
// ms = milliseconds per frame
|
||||
void Show(float fps, float ms);
|
||||
|
||||
// Updates the counters for OpenGL calls and triangle count.
|
||||
void UpdatePerformanceStats(int newCallCount, int newTriangleCount);
|
||||
|
||||
private:
|
||||
|
||||
float max_ms;
|
||||
// These are static so they're shared across all instances
|
||||
static int m_OpenGLCallCount;
|
||||
static int m_TriangleCount;
|
||||
};
|
261
src/Windows/RenderWindow.cpp
Normal file
261
src/Windows/RenderWindow.cpp
Normal file
@ -0,0 +1,261 @@
|
||||
// RenderWindow.cpp
|
||||
|
||||
#include "RenderWindow.h"
|
||||
#include <vector> // Add this line
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
#include "imgui.h"
|
||||
|
||||
|
||||
#include "Componenets/GameObject.h"
|
||||
#include "Componenets/Mesh.h"
|
||||
#include "Componenets/Transform.h"
|
||||
|
||||
extern std::vector<GameObject> m_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"
|
||||
#include "Rendering/Shader.h"
|
||||
|
||||
// Extern reference to our global (or extern) asset manager
|
||||
extern AssetManager g_AssetManager;
|
||||
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
|
||||
// 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,
|
||||
|
||||
// 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
|
||||
};
|
||||
|
||||
void RenderWindow::Show()
|
||||
{
|
||||
ImGui::Begin("OpenGL Output");
|
||||
|
||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||
int w = static_cast<int>(size.x);
|
||||
int h = static_cast<int>(size.y);
|
||||
|
||||
if (!m_Initialized)
|
||||
{
|
||||
InitGLResources();
|
||||
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_LastHeight = h;
|
||||
}
|
||||
|
||||
RenderSceneToFBO();
|
||||
ImGui::Image(m_FBO.GetTextureID(), size, ImVec2(0,0), ImVec2(1,1));
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("No space to render.");
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void RenderWindow::InitGLResources()
|
||||
{
|
||||
// ----------------------------------------------------
|
||||
// 1) Load SHADER from the asset manager
|
||||
// ----------------------------------------------------
|
||||
{
|
||||
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<Shader*>(shaderAsset);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// 2) Create VAO/VBO/EBO for the cube
|
||||
// ----------------------------------------------------
|
||||
glGenVertexArrays(1, &m_VAO);
|
||||
glBindVertexArray(m_VAO);
|
||||
|
||||
glGenBuffers(1, &m_VBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_VBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(g_CubeVertices), g_CubeVertices, GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &m_EBO);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_EBO);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(g_CubeIndices), g_CubeIndices, GL_STATIC_DRAW);
|
||||
|
||||
// Position = location 0, UV = location 1
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE,
|
||||
5 * sizeof(float), (void*)0);
|
||||
glEnableVertexAttribArray(0);
|
||||
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE,
|
||||
5 * sizeof(float), (void*)(3 * sizeof(float)));
|
||||
glEnableVertexAttribArray(1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
|
||||
// ----------------------------------------------------
|
||||
// 3) Load TEXTURE from the asset manager
|
||||
// ----------------------------------------------------
|
||||
{
|
||||
void* texAsset = g_AssetManager.loadAsset(AssetType::TEXTURE, "assets/textures/wood.png");
|
||||
if (!texAsset)
|
||||
{
|
||||
fprintf(stderr, "[RenderWindow] Failed to load texture.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cast from void* to GLuint
|
||||
m_TextureID = static_cast<GLuint>(reinterpret_cast<uintptr_t>(texAsset));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------
|
||||
// 4) Initialize GameObjects
|
||||
// ----------------------------------------------------
|
||||
|
||||
}
|
||||
|
||||
|
||||
void RenderWindow::RenderSceneToFBO()
|
||||
{
|
||||
m_RotationAngle += 0.1f; // spin per frame
|
||||
|
||||
// Bind the FBO
|
||||
m_FBO.Bind();
|
||||
glViewport(0, 0, m_LastWidth, m_LastHeight);
|
||||
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glClearColor(0.1f, 0.15f, 0.2f, 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
|
||||
|
||||
m_ShaderPtr->Use();
|
||||
GLuint programID = m_ShaderPtr->GetProgramID();
|
||||
|
||||
// Define view and projection matrices once
|
||||
glm::mat4 view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -5.f));
|
||||
float aspect = (m_LastHeight != 0) ? (float)m_LastWidth / (float)m_LastHeight : 1.0f;
|
||||
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 : m_GameObjects)
|
||||
{
|
||||
// -----------------------------------
|
||||
// 1) Build MVP from obj.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));
|
||||
|
||||
// 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));
|
||||
|
||||
// -----------------------------------
|
||||
// 2) Bind the object's texture
|
||||
// -----------------------------------
|
||||
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);
|
||||
|
||||
// -----------------------------------
|
||||
// 3) Draw the object's mesh
|
||||
// -----------------------------------
|
||||
glBindVertexArray(obj.mesh.vao);
|
||||
glDrawElements(GL_TRIANGLES, obj.mesh.indexCount, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
// Unbind for cleanliness
|
||||
glBindVertexArray(0);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
// Cleanup
|
||||
glUseProgram(0);
|
||||
m_FBO.Unbind();
|
||||
}
|
38
src/Windows/RenderWindow.h
Normal file
38
src/Windows/RenderWindow.h
Normal file
@ -0,0 +1,38 @@
|
||||
#pragma once
|
||||
|
||||
#include "../Rendering/FBO.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Rendering/Shader.h" //
|
||||
|
||||
class RenderWindow
|
||||
{
|
||||
public:
|
||||
void Show();
|
||||
|
||||
private:
|
||||
void InitGLResources();
|
||||
void RenderSceneToFBO();
|
||||
|
||||
// Offscreen render target
|
||||
FBO m_FBO;
|
||||
|
||||
// Keep track if we've initialized
|
||||
bool m_Initialized = false;
|
||||
|
||||
// GL objects for the cube
|
||||
unsigned int m_VAO = 0;
|
||||
unsigned int m_VBO = 0;
|
||||
unsigned int m_EBO = 0;
|
||||
|
||||
// Spin
|
||||
float m_RotationAngle = 0.f;
|
||||
int m_LastWidth = 0;
|
||||
int m_LastHeight = 0;
|
||||
|
||||
// The loaded texture
|
||||
unsigned int m_TextureID = 0;
|
||||
|
||||
// The loaded shader program (via AssetManager)
|
||||
Shader* m_ShaderPtr = nullptr;
|
||||
};
|
339
src/main.cpp
339
src/main.cpp
@ -1,344 +1,29 @@
|
||||
// src/main.cpp
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
|
||||
#include "imgui.h"
|
||||
#include "imgui_impl_glfw.h"
|
||||
#include "imgui_impl_opengl3.h"
|
||||
#include "../IconsFontAwesome6.h" // Include the Font Awesome icons header
|
||||
#include <cstdio>
|
||||
#include "Engine.h"
|
||||
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#define DEBUG 1
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOGPOINT(msg) std::cout << "[TESRCT] [" << __func__ << ":" << __LINE__ << "] " << (msg) << std::endl;
|
||||
#else
|
||||
#define LOGPOINT(msg)
|
||||
#endif
|
||||
|
||||
// Logger Implementation
|
||||
enum class LogLevel { INFO, WARNING, ERROR };
|
||||
|
||||
struct LogEntry {
|
||||
LogLevel level;
|
||||
std::string message;
|
||||
};
|
||||
|
||||
class Logger {
|
||||
public:
|
||||
static Logger& GetInstance() {
|
||||
static Logger instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
void Log(LogLevel level, const std::string& message) {
|
||||
entries.emplace_back(LogEntry{ level, message });
|
||||
if (entries.size() > max_entries)
|
||||
entries.erase(entries.begin());
|
||||
}
|
||||
|
||||
const std::vector<LogEntry>& GetEntries() const { return entries; }
|
||||
|
||||
void Clear() { // Added Clear method
|
||||
entries.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
Logger() : max_entries(1000) {}
|
||||
std::vector<LogEntry> entries;
|
||||
size_t max_entries;
|
||||
};
|
||||
|
||||
|
||||
// Function Declarations
|
||||
void ShowMainMenuBar();
|
||||
void ShowViewport();
|
||||
void ShowConsole(bool* p_open);
|
||||
|
||||
// Callback for GLFW errors
|
||||
static void glfw_error_callback(int error, const char* description)
|
||||
int main()
|
||||
{
|
||||
fprintf(stderr, "GLFW Error %d: %s\n", error, description);
|
||||
}
|
||||
DEBUG_PRINT("[START] Creating Global Engine ");
|
||||
|
||||
// Helper function to get color based on log level
|
||||
ImVec4 GetColorForLogLevel(LogLevel level)
|
||||
{
|
||||
switch (level)
|
||||
MyEngine engine;
|
||||
DEBUG_PRINT("[OK] Creating Global Engine ");
|
||||
|
||||
// Initialize the engine (creates GLFW window, sets up ImGui, etc.)
|
||||
if (!engine.Init(1280, 720, "Tesseract Engine"))
|
||||
{
|
||||
case LogLevel::INFO:
|
||||
return ImVec4(1.0f, 1.0f, 1.0f, 1.0f); // White
|
||||
case LogLevel::WARNING:
|
||||
return ImVec4(1.0f, 1.0f, 0.0f, 1.0f); // Yellow
|
||||
case LogLevel::ERROR:
|
||||
return ImVec4(1.0f, 0.0f, 0.0f, 1.0f); // Red
|
||||
default:
|
||||
return ImVec4(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int, char**)
|
||||
{
|
||||
LOGPOINT("Loading Engine");
|
||||
Logger::GetInstance().Log(LogLevel::INFO, "Loading engine...");
|
||||
|
||||
// Setup GLFW error callback
|
||||
glfwSetErrorCallback(glfw_error_callback);
|
||||
|
||||
// Initialize GLFW
|
||||
if (!glfwInit())
|
||||
return 1;
|
||||
|
||||
// GL 3.0 + GLSL 130
|
||||
const char* glsl_version = "#version 330";
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);
|
||||
|
||||
// Create window with graphics context
|
||||
GLFWwindow* window = glfwCreateWindow(1280, 720, "Tesseract Engine", NULL, NULL);
|
||||
if (window == NULL)
|
||||
return 1;
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(1); // Enable vsync
|
||||
|
||||
|
||||
|
||||
// Setup Dear ImGui context
|
||||
IMGUI_CHECKVERSION();
|
||||
ImGui::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO(); (void)io;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
|
||||
// io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport (optional)
|
||||
|
||||
// Load Fonts
|
||||
ImFontConfig config;
|
||||
config.MergeMode = true;
|
||||
config.PixelSnapH = true;
|
||||
|
||||
// Path to your fonts
|
||||
const char* font_path = "./assets/fonts/Roboto-Medium.ttf"; // Replace with your default font
|
||||
const char* fa_font_path = "./assets/fonts/fa-solid-900.ttf"; // Replace with your Font Awesome font
|
||||
|
||||
// Load default font
|
||||
ImFont* default_font = io.Fonts->AddFontFromFileTTF(font_path, 16.0f);
|
||||
if (!default_font)
|
||||
{
|
||||
fprintf(stderr, "Failed to load default font!\n");
|
||||
fprintf(stderr, "Failed to initialize engine.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Define the Font Awesome icon range
|
||||
static const ImWchar icons_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 };
|
||||
|
||||
// Merge Font Awesome icons
|
||||
config.GlyphMinAdvanceX = 13.0f; // Adjust if necessary
|
||||
ImFont* fa_font = io.Fonts->AddFontFromFileTTF(fa_font_path, 16.0f, &config, icons_ranges);
|
||||
|
||||
if (!fa_font)
|
||||
{
|
||||
fprintf(stderr, "Failed to load Font Awesome font!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Build the font atlas
|
||||
io.Fonts->Build();
|
||||
|
||||
// Setup Dear ImGui style
|
||||
ImGui::StyleColorsDark();
|
||||
// ImGui::StyleColorsClassic(); // Alternative theme
|
||||
|
||||
// When viewports are enabled, tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
|
||||
/*
|
||||
ImGuiStyle& style = ImGui::GetStyle();
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
{
|
||||
style.WindowRounding = 0.0f;
|
||||
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
|
||||
}
|
||||
*/
|
||||
|
||||
// Setup Platform/Renderer backends
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init(glsl_version);
|
||||
|
||||
// Example log messages
|
||||
//Logger::GetInstance().Log(LogLevel::INFO, "Engine initialized successfully.");
|
||||
//Logger::GetInstance().Log(LogLevel::WARNING, "This is a warning message.");
|
||||
//Logger::GetInstance().Log(LogLevel::ERROR, "This is an error message.");
|
||||
Logger::GetInstance().Log(LogLevel::INFO, "Done!");
|
||||
|
||||
// Variables for Console
|
||||
bool show_console = true;
|
||||
|
||||
// Main loop
|
||||
while (!glfwWindowShouldClose(window))
|
||||
{
|
||||
// Poll and handle events (inputs, window resize, etc.)
|
||||
glfwPollEvents();
|
||||
|
||||
// Start the Dear ImGui frame
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
ImGui::NewFrame();
|
||||
|
||||
// Create DockSpace
|
||||
ImGuiWindowFlags dockspace_flags = ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
|
||||
ImGuiWindowFlags_NoBringToFrontOnFocus | ImGuiWindowFlags_NoNavFocus;
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImGui::SetNextWindowPos(viewport->Pos);
|
||||
ImGui::SetNextWindowSize(viewport->Size);
|
||||
ImGui::SetNextWindowViewport(viewport->ID);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f);
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0.0f);
|
||||
ImGui::Begin("DockSpace", nullptr, dockspace_flags);
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
// DockSpace
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_DockingEnable)
|
||||
{
|
||||
ImGuiID dockspace_id = ImGui::GetID("MyDockSpace");
|
||||
ImGui::DockSpace(dockspace_id, ImVec2(0.0f, 0.0f), ImGuiDockNodeFlags_None);
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
|
||||
// Show GUI windows
|
||||
ShowMainMenuBar();
|
||||
ShowViewport();
|
||||
ShowConsole(&show_console);
|
||||
|
||||
// Rendering
|
||||
ImGui::Render();
|
||||
int display_w, display_h;
|
||||
glfwGetFramebufferSize(window, &display_w, &display_h);
|
||||
glViewport(0, 0, display_w, display_h);
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Dark background
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
// Update and Render additional Platform Windows (for multi-viewport)
|
||||
/*
|
||||
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
|
||||
{
|
||||
GLFWwindow* backup_current_context = glfwGetCurrentContext();
|
||||
ImGui::UpdatePlatformWindows();
|
||||
ImGui::RenderPlatformWindowsDefault();
|
||||
glfwMakeContextCurrent(backup_current_context);
|
||||
}
|
||||
*/
|
||||
|
||||
glfwSwapBuffers(window);
|
||||
}
|
||||
engine.Run();
|
||||
|
||||
// Cleanup
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
glfwDestroyWindow(window);
|
||||
glfwTerminate();
|
||||
engine.Cleanup();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Function Definitions
|
||||
|
||||
// 1. Main Menu Bar
|
||||
void ShowMainMenuBar()
|
||||
{
|
||||
if (ImGui::BeginMainMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("File"))
|
||||
{
|
||||
if (ImGui::MenuItem("New", "Ctrl+N")) { /* Handle New */ }
|
||||
if (ImGui::MenuItem("Open", "Ctrl+O")) { /* Handle Open */ }
|
||||
if (ImGui::MenuItem("Save", "Ctrl+S")) { /* Handle Save */ }
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Exit")) { /* Handle Exit */ }
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Edit"))
|
||||
{
|
||||
if (ImGui::MenuItem("Undo", "Ctrl+Z")) { /* Handle Undo */ }
|
||||
if (ImGui::MenuItem("Redo", "Ctrl+Y")) { /* Handle Redo */ }
|
||||
ImGui::Separator();
|
||||
if (ImGui::MenuItem("Copy", "Ctrl+C")) { /* Handle Copy */ }
|
||||
if (ImGui::MenuItem("Paste", "Ctrl+V")) { /* Handle Paste */ }
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("View"))
|
||||
{
|
||||
if (ImGui::MenuItem("Show Console", NULL, true)) { /* Toggle Console */ }
|
||||
if (ImGui::MenuItem("Toggle Viewport")) { /* Toggle Viewport */ }
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMainMenuBar();
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Viewport Panel
|
||||
void ShowViewport()
|
||||
{
|
||||
ImGui::Begin("Viewport", NULL, ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
// Get the size of the viewport
|
||||
ImVec2 viewport_size = ImGui::GetContentRegionAvail();
|
||||
|
||||
// For demonstration, we'll render a colored rectangle
|
||||
// In a real engine, you'd render your scene here
|
||||
|
||||
// Calculate the center position
|
||||
ImVec2 pos = ImGui::GetCursorScreenPos();
|
||||
|
||||
// Define rectangle dimensions
|
||||
ImVec2 rect_min = pos;
|
||||
ImVec2 rect_max = ImVec2(pos.x + viewport_size.x, pos.y + viewport_size.y);
|
||||
|
||||
// Render a colored rectangle
|
||||
ImGui::GetWindowDrawList()->AddRectFilled(rect_min, rect_max, IM_COL32(100, 100, 200, 255));
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
// 3. Console Panel
|
||||
void ShowConsole(bool* p_open)
|
||||
{
|
||||
ImGui::Begin("Console", p_open, ImGuiWindowFlags_NoCollapse);
|
||||
|
||||
// Options menu
|
||||
if (ImGui::BeginPopupContextWindow())
|
||||
{
|
||||
if (ImGui::MenuItem("Clear")) {
|
||||
Logger::GetInstance().Clear();
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
// Reserve enough left-over height for 1 separator and 1 input text
|
||||
ImGui::Separator();
|
||||
|
||||
// Begin child region for scrolling
|
||||
ImGui::BeginChild("ConsoleChild", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
|
||||
|
||||
// Iterate through log entries
|
||||
for (const auto& entry : Logger::GetInstance().GetEntries())
|
||||
{
|
||||
ImVec4 color = GetColorForLogLevel(entry.level);
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::TextUnformatted(entry.message.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
// Auto-scroll to the bottom
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
|
||||
ImGui::EndChild();
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
455
vendor/gcml/gcml.h
vendored
Normal file
455
vendor/gcml/gcml.h
vendored
Normal file
@ -0,0 +1,455 @@
|
||||
#ifndef GCML_H
|
||||
#define GCML_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
// -------------------------
|
||||
// General Utility Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Returns the minimum of two values.
|
||||
*/
|
||||
#define MIN(a, b) (( (a) < (b) ) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* @brief Returns the maximum of two values.
|
||||
*/
|
||||
#define MAX(a, b) (( (a) > (b) ) ? (a) : (b))
|
||||
|
||||
/**
|
||||
* @brief Calculates the number of elements in an array.
|
||||
*/
|
||||
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
||||
|
||||
/**
|
||||
* @brief Suppresses compiler warnings for unused variables.
|
||||
*/
|
||||
#define UNUSED(x) (void)(x)
|
||||
|
||||
/**
|
||||
* @brief Aligns a value `x` up to the nearest multiple of `align`.
|
||||
*/
|
||||
#define ALIGN_UP(x, align) (((x) + ((align)-1)) & ~((align)-1))
|
||||
|
||||
/**
|
||||
* @brief Aligns a value `x` down to the nearest multiple of `align`.
|
||||
*/
|
||||
#define ALIGN_DOWN(x, align) ((x) & ~((align)-1))
|
||||
|
||||
// -------------------------
|
||||
// Debugging and Logging Macros
|
||||
// -------------------------
|
||||
|
||||
#ifdef DEBUG
|
||||
/**
|
||||
* @brief Prints debug messages with file name, line number, and function name.
|
||||
*/
|
||||
#define DEBUG_PRINT(fmt, ...) \
|
||||
fprintf(stderr, "%s:%d:%s(): " fmt "\n", \
|
||||
__FILE__, __LINE__, __func__, ##__VA_ARGS__)
|
||||
#else
|
||||
#define DEBUG_PRINT(fmt, ...) // No operation in release builds
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Logs informational messages.
|
||||
*/
|
||||
#define LOG_INFO(fmt, ...) \
|
||||
fprintf(stdout, "INFO: " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Logs warning messages.
|
||||
*/
|
||||
#define LOG_WARN(fmt, ...) \
|
||||
fprintf(stderr, "WARNING: " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Logs error messages.
|
||||
*/
|
||||
#define LOG_ERROR(fmt, ...) \
|
||||
fprintf(stderr, "ERROR: " fmt "\n", ##__VA_ARGS__)
|
||||
|
||||
/**
|
||||
* @brief Logs fatal error messages and exits the program.
|
||||
*/
|
||||
#define LOG_FATAL(fmt, ...) do { \
|
||||
fprintf(stderr, "FATAL: " fmt "\n", ##__VA_ARGS__); \
|
||||
exit(EXIT_FAILURE); \
|
||||
} while (0)
|
||||
|
||||
// -------------------------
|
||||
// Assertion Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Asserts a condition and logs an error message if the condition is false.
|
||||
*/
|
||||
#ifndef NDEBUG
|
||||
#define ASSERT(cond, fmt, ...) do { \
|
||||
if (!(cond)) { \
|
||||
fprintf(stderr, "Assertion failed: (%s), function %s, file %s, line %d.\n", \
|
||||
#cond, __func__, __FILE__, __LINE__); \
|
||||
fprintf(stderr, fmt "\n", ##__VA_ARGS__); \
|
||||
abort(); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define ASSERT(cond, fmt, ...) ((void)0)
|
||||
#endif
|
||||
|
||||
// -------------------------
|
||||
// Stringification Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Converts a macro argument to a string.
|
||||
*/
|
||||
#define STRINGIFY(x) #x
|
||||
#define TOSTRING(x) STRINGIFY(x)
|
||||
|
||||
// -------------------------
|
||||
// Token Pasting Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Concatenates two tokens.
|
||||
*/
|
||||
#define CONCAT(a, b) a ## b
|
||||
|
||||
/**
|
||||
* @brief Concatenates three tokens.
|
||||
*/
|
||||
#define CONCAT3(a, b, c) a ## b ## c
|
||||
|
||||
// -------------------------
|
||||
// Memory Management Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Allocates memory and checks for allocation failure.
|
||||
* @param ptr The pointer to assign the allocated memory.
|
||||
* @param size The size in bytes to allocate.
|
||||
*/
|
||||
#define SAFE_MALLOC(ptr, size) do { \
|
||||
(ptr) = malloc(size); \
|
||||
if ((ptr) == NULL) { \
|
||||
LOG_FATAL("Memory allocation failed for size %zu", (size_t)(size)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Allocates zero-initialized memory and checks for allocation failure.
|
||||
* @param ptr The pointer to assign the allocated memory.
|
||||
* @param count The number of elements to allocate.
|
||||
* @param type The type of each element.
|
||||
*/
|
||||
#define SAFE_CALLOC(ptr, count, type) do { \
|
||||
(ptr) = calloc((count), sizeof(type)); \
|
||||
if ((ptr) == NULL) { \
|
||||
LOG_FATAL("Memory allocation (calloc) failed for count %zu of type %s", \
|
||||
(size_t)(count), #type); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Frees memory and sets the pointer to NULL.
|
||||
* @param ptr The pointer to free.
|
||||
*/
|
||||
#define SAFE_FREE(ptr) do { \
|
||||
free(ptr); \
|
||||
ptr = NULL; \
|
||||
} while(0)
|
||||
|
||||
// -------------------------
|
||||
// Type Casting Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Safely casts a pointer to a specific type.
|
||||
* @param ptr The pointer to cast.
|
||||
* @param type The target type.
|
||||
*/
|
||||
#define SAFE_CAST(ptr, type) ((type)(ptr))
|
||||
|
||||
// -------------------------
|
||||
// Bit Manipulation Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Sets a bit at a specific position.
|
||||
* @param x The variable.
|
||||
* @param pos The bit position.
|
||||
*/
|
||||
#define SET_BIT(x, pos) ((x) |= (1U << (pos)))
|
||||
|
||||
/**
|
||||
* @brief Clears a bit at a specific position.
|
||||
* @param x The variable.
|
||||
* @param pos The bit position.
|
||||
*/
|
||||
#define CLEAR_BIT(x, pos) ((x) &= ~(1U << (pos)))
|
||||
|
||||
/**
|
||||
* @brief Toggles a bit at a specific position.
|
||||
* @param x The variable.
|
||||
* @param pos The bit position.
|
||||
*/
|
||||
#define TOGGLE_BIT(x, pos) ((x) ^= (1U << (pos)))
|
||||
|
||||
/**
|
||||
* @brief Checks if a bit at a specific position is set.
|
||||
* @param x The variable.
|
||||
* @param pos The bit position.
|
||||
* @return Non-zero if the bit is set, zero otherwise.
|
||||
*/
|
||||
#define CHECK_BIT(x, pos) (((x) >> (pos)) & 1U)
|
||||
|
||||
// -------------------------
|
||||
// Compile-Time Assertion Macro
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Performs a compile-time assertion.
|
||||
* @param expr The expression to evaluate.
|
||||
* @param msg The message to display if the assertion fails.
|
||||
*/
|
||||
#define STATIC_ASSERT(expr, msg) _Static_assert(expr, msg)
|
||||
|
||||
// -------------------------
|
||||
// Deprecation Warning Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Marks a function as deprecated with a custom message.
|
||||
*/
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
#define DEPRECATED(msg) __attribute__((deprecated(msg)))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEPRECATED(msg) __declspec(deprecated(msg))
|
||||
#else
|
||||
#pragma message("WARNING: DEPRECATED macro is not supported for this compiler.")
|
||||
#define DEPRECATED(msg)
|
||||
#endif
|
||||
|
||||
// -------------------------
|
||||
// Loop Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Iterates over each element in an array.
|
||||
* @param item The loop variable.
|
||||
* @param array The array to iterate over.
|
||||
*/
|
||||
#define FOREACH(item, array) \
|
||||
for (size_t keep = 1, \
|
||||
count = ARRAY_SIZE(array), \
|
||||
i = 0; \
|
||||
keep && i < count; \
|
||||
keep = !keep, i++) \
|
||||
for (item = (array) + i; keep; keep = !keep)
|
||||
|
||||
/**
|
||||
* @brief Repeats a block of code `n` times.
|
||||
* @param n The number of times to repeat.
|
||||
* @param block The block of code to execute.
|
||||
*/
|
||||
#define REPEAT(n, block) \
|
||||
for (size_t _i = 0; _i < (n); ++_i) { block; }
|
||||
|
||||
// -------------------------
|
||||
// Swap Macro
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Swaps two variables of the same type.
|
||||
* @param a The first variable.
|
||||
* @param b The second variable.
|
||||
*/
|
||||
#define SWAP(a, b) do { \
|
||||
typeof(a) _swap_temp = (a); \
|
||||
(a) = (b); \
|
||||
(b) = _swap_temp; \
|
||||
} while (0)
|
||||
|
||||
// -------------------------
|
||||
// Execute Once Macro
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Executes a block of code only once.
|
||||
* @param block The block of code to execute.
|
||||
*/
|
||||
#define DO_ONCE(block) \
|
||||
do { \
|
||||
static int _do_once_flag = 0; \
|
||||
if (!_do_once_flag) { \
|
||||
_do_once_flag = 1; \
|
||||
block \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// -------------------------
|
||||
// Utility Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Calculates the offset of a member within a struct.
|
||||
* @param type The struct type.
|
||||
* @param member The member within the struct.
|
||||
*/
|
||||
#define OFFSET_OF(type, member) ((size_t) &(((type *)0)->member))
|
||||
|
||||
/**
|
||||
* @brief Retrieves the containing struct from a member pointer.
|
||||
* @param ptr The pointer to the member.
|
||||
* @param type The type of the containing struct.
|
||||
* @param member The member within the struct.
|
||||
*/
|
||||
#define CONTAINER_OF(ptr, type, member) \
|
||||
((type *)((char *)(ptr) - OFFSET_OF(type, member)))
|
||||
|
||||
|
||||
// -------------------------
|
||||
// Additional Utility Macros
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Safely reallocates memory and checks for allocation failure.
|
||||
* @param ptr The pointer to the previously allocated memory.
|
||||
* @param size The new size in bytes to allocate.
|
||||
*/
|
||||
#define SAFE_REALLOC(ptr, size) do { \
|
||||
void* _tmp = realloc((ptr), (size)); \
|
||||
if ((_tmp) == NULL) { \
|
||||
LOG_FATAL("Memory reallocation failed for size %zu", (size_t)(size)); \
|
||||
} else { \
|
||||
(ptr) = _tmp; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/**
|
||||
* @brief Marks a function as unused to suppress compiler warnings.
|
||||
*/
|
||||
#define UNUSED_FUNCTION __attribute__((unused))
|
||||
|
||||
/**
|
||||
* @brief Converts a value to a string at compile time.
|
||||
* @param value The value to stringify.
|
||||
* @return The string representation of the value.
|
||||
*/
|
||||
#define TO_STRING(value) TOSTRING(value)
|
||||
|
||||
/**
|
||||
* @brief Generates a unique identifier by appending the line number.
|
||||
* @param prefix The prefix for the identifier.
|
||||
* @return A unique identifier.
|
||||
*/
|
||||
#define UNIQUE_ID(prefix) CONCAT(prefix, __LINE__)
|
||||
|
||||
/**
|
||||
* @brief Forces a value to evaluate to a specific type without altering its binary representation.
|
||||
* @param value The value to cast.
|
||||
* @param type The target type.
|
||||
* @return The value cast to the specified type.
|
||||
*/
|
||||
#define FORCE_CAST(value, type) (*(type*)&(value))
|
||||
|
||||
/**
|
||||
* @brief Creates a do-while loop that executes exactly once.
|
||||
* @param block The block of code to execute.
|
||||
*/
|
||||
#define EXECUTE_ONCE(block) do { block } while(0)
|
||||
|
||||
/**
|
||||
* @brief Checks if a pointer is aligned to a specified boundary.
|
||||
* @param ptr The pointer to check.
|
||||
* @param align The alignment boundary (must be a power of two).
|
||||
* @return Non-zero if aligned, zero otherwise.
|
||||
*/
|
||||
#define IS_ALIGNED(ptr, align) ((((uintptr_t)(const void*)(ptr)) & ((align) - 1)) == 0)
|
||||
|
||||
/**
|
||||
* @brief Calculates the number of bits set to 1 in a variable.
|
||||
* @param x The variable to count bits in.
|
||||
* @return The number of bits set to 1.
|
||||
*/
|
||||
#define COUNT_SET_BITS(x) (__builtin_popcount(x))
|
||||
|
||||
/**
|
||||
* @brief Calculates the ceiling of a division between two integers.
|
||||
* @param numerator The numerator.
|
||||
* @param denominator The denominator.
|
||||
* @return The ceiling of the division.
|
||||
*/
|
||||
#define CEIL_DIV(numerator, denominator) (((numerator) + (denominator) - 1) / (denominator))
|
||||
|
||||
/**
|
||||
* @brief Concatenates two tokens with an underscore.
|
||||
* @param a The first token.
|
||||
* @param b The second token.
|
||||
* @return The concatenated token separated by an underscore.
|
||||
*/
|
||||
#define CONCAT_WITH_UNDERSCORE(a, b) CONCAT(a, _##b)
|
||||
|
||||
/**
|
||||
* @brief Swaps two variables without using a temporary variable (only for integer types).
|
||||
* @param a The first variable.
|
||||
* @param b The second variable.
|
||||
*/
|
||||
#define SWAP_INPLACE(a, b) do { \
|
||||
(a) ^= (b); \
|
||||
(b) ^= (a); \
|
||||
(a) ^= (b); \
|
||||
} while (0)
|
||||
|
||||
// -------------------------
|
||||
// Safe Reallocation Macro
|
||||
// -------------------------
|
||||
|
||||
/**
|
||||
* @brief Safely reallocates memory and checks for allocation failure.
|
||||
* @param ptr The pointer to the previously allocated memory.
|
||||
* @param size The new size in bytes to allocate.
|
||||
*/
|
||||
#define SAFE_REALLOC(ptr, size) do { \
|
||||
void* _tmp = realloc((ptr), (size)); \
|
||||
if ((_tmp) == NULL) { \
|
||||
LOG_FATAL("Memory reallocation failed for size %zu", (size_t)(size)); \
|
||||
} else { \
|
||||
(ptr) = _tmp; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#define MAX_OF(...) MAX_OF_IMPL(__VA_ARGS__, MAX_OF_RSEQ_N())
|
||||
#define MAX_OF_IMPL(...) MAX_OF_ARG_N(__VA_ARGS__)
|
||||
#define MAX_OF_ARG_N(_1, _2, _3, _4, _5, N, ...) N
|
||||
#define MAX_OF_RSEQ_N() 5,4,3,2,1,0
|
||||
|
||||
#define MIN_OF(...) MIN_OF_IMPL(__VA_ARGS__, MIN_OF_RSEQ_N())
|
||||
#define MIN_OF_IMPL(...) MIN_OF_ARG_N(__VA_ARGS__)
|
||||
#define MIN_OF_ARG_N(_1, _2, _3, _4, _5, N, ...) N
|
||||
#define MIN_OF_RSEQ_N() 5,4,3,2,1,0
|
||||
|
||||
|
||||
#define ZERO_STRUCT(s) memset(&(s), 0, sizeof(s))
|
||||
|
||||
|
||||
#define PRINT_VAR(var) LOG_INFO(#var " = %d", var)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // GCML_H
|
||||
|
||||
|
||||
|
6
vendor/glad/CMakeLists.txt
vendored
6
vendor/glad/CMakeLists.txt
vendored
@ -1,6 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
project(glad)
|
||||
|
||||
add_library(glad)
|
||||
target_sources(glad PRIVATE src/glad.c)
|
||||
target_include_directories(glad PUBLIC include)
|
11
vendor/stb/CMakeLists.txt
vendored
11
vendor/stb/CMakeLists.txt
vendored
@ -1,11 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
project(stb)
|
||||
|
||||
file(GLOB_RECURSE SOURCES src/*.cpp)
|
||||
|
||||
add_library(stb)
|
||||
|
||||
target_include_directories(stb PUBLIC include)
|
||||
|
||||
target_sources(stb PRIVATE ${SOURCES})
|
4
vendor/stb/include/stb_image.h
vendored
4
vendor/stb/include/stb_image.h
vendored
@ -1,5 +1,4 @@
|
||||
#ifndef STB_IMAG_H
|
||||
#define STB_IMAG_H
|
||||
#pragma once
|
||||
|
||||
/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb
|
||||
no warranty implied; use at your own risk
|
||||
@ -7990,4 +7989,3 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#endif
|
2
vendor/stb/src/stb_image.cpp
vendored
2
vendor/stb/src/stb_image.cpp
vendored
@ -1,2 +0,0 @@
|
||||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include <stb_image.h>
|
Loading…
Reference in New Issue
Block a user