Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
95b15827d6 | ||
|
24a5a4fbbe | ||
|
a428ba3a0e | ||
|
dd17ed8df5 | ||
|
d373951d91 | ||
|
99d99280cc | ||
|
6d356f5597 | ||
|
2095152251 | ||
|
71659be98e | ||
|
e1b2d25fa7 | ||
|
3ed1dd9421 | ||
|
f8e60f05bf | ||
|
1be66c754a | ||
|
d375f8cd98 | ||
|
f90e601396 | ||
|
229c4abc0f | ||
|
b9bd335198 | ||
|
611bc36ad6 | ||
|
1bd5f34e21 | ||
394f030403 | |||
|
c8acf2b10d | ||
|
2dd88a870d | ||
|
9b64f2cf50 | ||
|
ecb6c4951f | ||
|
77c834fa82 | ||
|
fa4252b593 | ||
|
91133a0396 | ||
|
22a5b729e7 | ||
|
f6adf1f37d | ||
|
f567fb8ee9 |
151
Makefile
151
Makefile
@ -1,27 +1,95 @@
|
|||||||
# Makefile
|
# ---------------------------------------------------------------------------
|
||||||
|
# Compiler and Base Flags
|
||||||
# Compiler and Flags
|
# ---------------------------------------------------------------------------
|
||||||
CXX := g++
|
CXX := g++
|
||||||
CXXFLAGS := -Wall -Wextra -std=c++17 -g -DDEBUG -DTIMERS
|
|
||||||
|
|
||||||
|
# Common flags (for both Debug and Release)
|
||||||
|
CXXFLAGS_BASE := -Wall -Wextra -std=c++17
|
||||||
|
|
||||||
|
# Debug flags (includes TIMERS and DEBUG, plus -g)
|
||||||
|
CXXFLAGS_DEBUG := $(CXXFLAGS_BASE) -g -DDEBUG -DTIMERS
|
||||||
|
|
||||||
|
# Release flags (optimized, no debug macros, no timers)
|
||||||
|
CXXFLAGS_RELEASE := $(CXXFLAGS_BASE) -O2 -DNDEBUG
|
||||||
|
|
||||||
|
# By default, we build in Debug mode:
|
||||||
|
BUILD_TYPE ?= debug
|
||||||
|
|
||||||
|
# We’ll dynamically set BUILD_DIR and CXXFLAGS based on BUILD_TYPE
|
||||||
|
ifeq ($(BUILD_TYPE),debug)
|
||||||
|
BUILD_DIR := build
|
||||||
|
CXXFLAGS := $(CXXFLAGS_DEBUG)
|
||||||
|
else ifeq ($(BUILD_TYPE),release)
|
||||||
|
BUILD_DIR := release
|
||||||
|
CXXFLAGS := $(CXXFLAGS_RELEASE)
|
||||||
|
else
|
||||||
|
$(error Unknown BUILD_TYPE '$(BUILD_TYPE)'. Valid options: debug or release)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Detect Platform
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
# -------------------- Windows --------------------
|
||||||
|
EXE_EXT := .exe
|
||||||
|
|
||||||
|
# Example paths (adjust if you have your libs somewhere else):
|
||||||
|
GLFW_INCLUDE := C:/libs/glfw/include
|
||||||
|
GLEW_INCLUDE := C:/libs/glew/include
|
||||||
|
|
||||||
|
LIB_PATHS := -LC:/libs/glfw/lib \
|
||||||
|
-LC:/libs/glew/lib \
|
||||||
|
-Llib
|
||||||
|
|
||||||
|
LIBS := -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid \
|
||||||
|
-lwinmm -lglew32 -lglu32 -lyaml-cpp -llua54
|
||||||
|
|
||||||
|
define MKDIR_P
|
||||||
|
if not exist "$(1)" mkdir "$(1)" >nul 2>&1
|
||||||
|
endef
|
||||||
|
|
||||||
|
else
|
||||||
|
# -------------------- Linux (or other Unix-likes) --------------------
|
||||||
|
EXE_EXT :=
|
||||||
|
|
||||||
|
GLFW_INCLUDE := /usr/include
|
||||||
|
GLEW_INCLUDE := /usr/include
|
||||||
|
|
||||||
|
LIB_PATHS :=
|
||||||
|
|
||||||
|
LIBS := -lglfw -lGL -lGLEW -lGLU -lyaml-cpp -llua
|
||||||
|
|
||||||
|
define MKDIR_P
|
||||||
|
mkdir -p "$(1)"
|
||||||
|
endef
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
# Directories
|
# Directories
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
SRC_DIR := src
|
SRC_DIR := src
|
||||||
VENDOR_DIRS := vendor/imgui-docking vendor/stb
|
VENDOR_DIRS := vendor/imgui-docking vendor/stb vendor/ImGuizmo
|
||||||
BUILD_DIR := build
|
# BUILD_DIR is determined by $(BUILD_TYPE) above: either `build` or `release`
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
# Include Directories
|
# Include Directories
|
||||||
GLFW_INCLUDE := C:/libraries/glfw/include
|
# ---------------------------------------------------------------------------
|
||||||
INCLUDE_DIRS := $(SRC_DIR) $(VENDOR_DIRS) $(GLFW_INCLUDE) vendor/stb/include C:\msys64\mingw64\include vendor/lua vendor/gcml
|
INCLUDE_DIRS := \
|
||||||
INCLUDES := $(addprefix -I, $(INCLUDE_DIRS))
|
$(SRC_DIR) \
|
||||||
|
$(VENDOR_DIRS) \
|
||||||
|
$(GLFW_INCLUDE) \
|
||||||
|
$(GLEW_INCLUDE) \
|
||||||
|
vendor/stb/include \
|
||||||
|
vendor/lua \
|
||||||
|
vendor/ImGuizmo \
|
||||||
|
vendor/gcml
|
||||||
|
|
||||||
# Update compiler flags with include paths
|
CXXFLAGS += $(foreach inc,$(INCLUDE_DIRS),-I$(inc))
|
||||||
CXXFLAGS += $(INCLUDES)
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Source Files
|
# Source Files
|
||||||
# 1) Recursively gather *.cpp in src (including subfolders).
|
# ---------------------------------------------------------------------------
|
||||||
# 2) Gather *.cpp from vendor/imgui-docking, vendor/stb, etc.
|
|
||||||
# -------------------------------------------------------------------------
|
|
||||||
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp) \
|
SRC_FILES := $(wildcard $(SRC_DIR)/*.cpp) \
|
||||||
$(wildcard $(SRC_DIR)/**/*.cpp)
|
$(wildcard $(SRC_DIR)/**/*.cpp)
|
||||||
|
|
||||||
@ -29,46 +97,51 @@ VENDOR_SRC := $(foreach dir, $(VENDOR_DIRS), $(wildcard $(dir)/*.cpp))
|
|||||||
STB_SRC := $(wildcard vendor/stb/src/*.cpp) # If stb has .cpp files
|
STB_SRC := $(wildcard vendor/stb/src/*.cpp) # If stb has .cpp files
|
||||||
ALL_SRC := $(SRC_FILES) $(VENDOR_SRC) $(STB_SRC)
|
ALL_SRC := $(SRC_FILES) $(VENDOR_SRC) $(STB_SRC)
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Object Files
|
# Object Files
|
||||||
# Convert each .cpp to a corresponding .o under the build/ directory.
|
# ---------------------------------------------------------------------------
|
||||||
# For example:
|
OBJ_FILES := $(patsubst %.cpp,$(BUILD_DIR)/%.o,$(ALL_SRC))
|
||||||
# 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))
|
|
||||||
|
|
||||||
# Target executable name
|
# ---------------------------------------------------------------------------
|
||||||
TARGET := TesseractEngine.exe
|
# Target (goes into the same directory as object files)
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
# Libraries
|
TARGET := $(BUILD_DIR)/TesseractEngine$(EXE_EXT)
|
||||||
LIBS := -LC:/libraries/glfw/lib -Llib -lglfw3 -lopengl32 -lgdi32 -limm32 -lole32 -loleaut32 -luuid -lwinmm -lglew32 -lglu32 -lyaml-cpp -llua54
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
# Phony Targets
|
# Phony Targets
|
||||||
.PHONY: all clean copy_assets
|
# ---------------------------------------------------------------------------
|
||||||
|
.PHONY: all clean debug release
|
||||||
|
|
||||||
# Default target
|
# Default target uses whatever BUILD_TYPE is (default = debug)
|
||||||
all: copy_assets $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
# Copy assets/fonts to build/assets/fonts
|
## "debug" target => override BUILD_TYPE
|
||||||
copy_assets:
|
debug:
|
||||||
@echo Copying font assets...
|
@$(MAKE) BUILD_TYPE=debug all
|
||||||
xcopy /E /I /Y "assets\fonts" "$(BUILD_DIR)\assets\fonts" >nul
|
|
||||||
|
|
||||||
|
## "release" target => override BUILD_TYPE
|
||||||
|
release:
|
||||||
|
@$(MAKE) BUILD_TYPE=release all
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
# Link all object files to create the executable
|
# Link all object files to create the executable
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
$(TARGET): $(OBJ_FILES)
|
$(TARGET): $(OBJ_FILES)
|
||||||
@echo Linking $@...
|
@echo Linking $@...
|
||||||
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIBS)
|
$(CXX) $(CXXFLAGS) -o $@ $^ $(LIB_PATHS) $(LIBS)
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
# Pattern rule to compile .cpp files to .o files
|
# Pattern rule to compile .cpp files to .o files
|
||||||
# Note the mkdir on the $(dir $@) ensures subfolders under build/ exist.
|
# ---------------------------------------------------------------------------
|
||||||
$(BUILD_DIR)/%.o: %.cpp
|
$(BUILD_DIR)/%.o: %.cpp
|
||||||
@mkdir "$(dir $@)" >nul 2>&1 || echo Directory exists
|
@$(call MKDIR_P,$(dir $@))
|
||||||
@echo Compiling $<...
|
@echo Compiling $<...
|
||||||
$(CXX) $(CXXFLAGS) -c $< -o $@
|
$(CXX) $(CXXFLAGS) -c $< -o $@
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
# Clean build artifacts
|
# Clean build artifacts
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@echo Cleaning up...
|
@echo Cleaning up...
|
||||||
if exist "$(BUILD_DIR)" rmdir /s /q "$(BUILD_DIR)"
|
rm -rf build
|
||||||
if exist "$(TARGET)" del /q "$(TARGET)"
|
rm -rf release
|
||||||
|
16
README.md
16
README.md
@ -34,6 +34,22 @@ Join The Discord!
|
|||||||
### Note: Screenshots are sorted by version.
|
### Note: Screenshots are sorted by version.
|
||||||
|
|
||||||
|
|
||||||
|
## **Version 0.0.131**
|
||||||
|
**Updates:**
|
||||||
|
- Added Guizmos
|
||||||
|
- Added Mesh Visualisers
|
||||||
|
- Added Global Settings
|
||||||
|
- Lua Changes
|
||||||
|
- Added Intelisence Headers for Engine and KeyCodes
|
||||||
|
- Changed Lua `require` to not need a path
|
||||||
|
- Added Culling
|
||||||
|
- Fixed GLCalls Count
|
||||||
|
- Removed Unused Code (TestMesh.cpp)
|
||||||
|
|
||||||
|
**Screenshot:**
|
||||||
|
|
||||||
|
![](./assets/images/SS-Dev2_5-Fixed.png)
|
||||||
|
|
||||||
## **Version 0.0.102**
|
## **Version 0.0.102**
|
||||||
**Updates:**
|
**Updates:**
|
||||||
- Added More Themes
|
- Added More Themes
|
||||||
|
BIN
assets/images/SS-Dev2_5-Fixed.png
Normal file
BIN
assets/images/SS-Dev2_5-Fixed.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.5 MiB |
@ -1,6 +1,6 @@
|
|||||||
-- script.lua
|
-- script.lua
|
||||||
local Math = require("./assets/scripts/math") -- Require the enhanced math module
|
local Math = require("math") -- Require the enhanced math module
|
||||||
local Engine = require("./assets/scripts/engine")
|
local Engine = require("engine")
|
||||||
|
|
||||||
|
|
||||||
local GameObjectName = "Bacround"
|
local GameObjectName = "Bacround"
|
||||||
|
@ -1,60 +1,118 @@
|
|||||||
local Engine = require("./assets/scripts/engine")
|
local Engine = require("engine")
|
||||||
local KeyCode = require("./assets/scripts/keycode")
|
local KeyCode = require("keycode")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local transform = nil
|
local transform = nil
|
||||||
|
|
||||||
local new_rotation = 0
|
local currentRotation = 0 -- Current Y-axis rotation in degrees
|
||||||
|
|
||||||
local new_rotationSpeed = 15
|
local rotationSpeed = 240 -- Degrees per second
|
||||||
local Move_Speec = 300
|
local moveSpeed = 600 -- Units per second
|
||||||
|
|
||||||
function OnInit()
|
function OnInit()
|
||||||
local gameObject = Engine.GetGameObjectByTag("Camera")
|
local gameObject = Engine.GetGameObjectByTag("Camera")
|
||||||
transform = gameObject:GetComponent("Transform")
|
if not gameObject then
|
||||||
Engine.Expose("Position X", "nil")
|
Engine.Log("Error: Camera GameObject not found!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
Engine.Log("Init Done")
|
transform = gameObject:GetComponent("Transform")
|
||||||
|
if not transform then
|
||||||
|
Engine.Log("Error: Transform component not found on Camera!")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Initialize currentRotation based on the transform's current rotation
|
||||||
|
local rotation = transform:GetRotation()
|
||||||
|
currentRotation = rotation.y
|
||||||
|
|
||||||
|
Engine.Expose("Position X", rotation.x)
|
||||||
|
Engine.Expose("Position Z", rotation.z)
|
||||||
|
Engine.Expose("Rotation Y", currentRotation)
|
||||||
|
Engine.Log("Init Done", {0,1,0,1})
|
||||||
end
|
end
|
||||||
|
|
||||||
function OnUpdate(deltaTime)
|
function OnUpdate(deltaTime)
|
||||||
local gameObject = Engine.GetGameObjectByTag("Camera")
|
if not transform then
|
||||||
transform = gameObject:GetComponent("Transform")
|
Engine.Log("Warning: Transform is not initialized.")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
local old_rotation = transform:GetRotation()
|
-- Retrieve current rotation and position
|
||||||
|
local rotation = transform:GetRotation()
|
||||||
|
local position = transform:GetPosition()
|
||||||
|
|
||||||
|
-- Update currentRotation based on input
|
||||||
|
if Engine.KeyDown(KeyCode.Q) then
|
||||||
|
currentRotation = currentRotation - (deltaTime * rotationSpeed)
|
||||||
|
end
|
||||||
|
if Engine.KeyDown(KeyCode.E) then
|
||||||
|
currentRotation = currentRotation + (deltaTime * rotationSpeed)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Normalize rotation to [0, 360) degrees
|
||||||
|
if currentRotation >= 360 then
|
||||||
|
currentRotation = currentRotation - 360
|
||||||
|
elseif currentRotation < 0 then
|
||||||
|
currentRotation = currentRotation + 360
|
||||||
|
end
|
||||||
|
|
||||||
local Position = transform:GetPosition()
|
-- Apply the updated rotation to the Transform component
|
||||||
|
local newRotation = {
|
||||||
|
x = rotation.x, -- Preserving existing rotation on X-axis
|
||||||
|
y = currentRotation, -- Updated rotation on Y-axis
|
||||||
|
z = rotation.z -- Preserving existing rotation on Z-axis
|
||||||
|
}
|
||||||
|
transform:SetRotation(newRotation)
|
||||||
|
|
||||||
|
-- Calculate movement direction based on currentRotation
|
||||||
|
local rotationRad = math.rad(currentRotation)
|
||||||
|
|
||||||
|
-- Forward vector (positive Z direction)
|
||||||
|
local forward = {
|
||||||
|
x = math.cos(rotationRad),
|
||||||
|
z = math.sin(rotationRad)
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Right vector (positive X direction)
|
||||||
|
local right = {
|
||||||
|
x = math.sin(rotationRad),
|
||||||
|
z = -math.cos(rotationRad)
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Initialize movement deltas
|
||||||
|
local deltaX = 0
|
||||||
|
local deltaZ = 0
|
||||||
|
|
||||||
if Engine.KeyDown(KeyCode.W) then
|
if Engine.KeyDown(KeyCode.W) then
|
||||||
Position.x = Position.x + (deltaTime * Move_Speec)
|
-- Move forward
|
||||||
|
deltaX = deltaX + forward.x * moveSpeed * deltaTime
|
||||||
|
deltaZ = deltaZ + forward.z * moveSpeed * deltaTime
|
||||||
end
|
end
|
||||||
if Engine.KeyDown(KeyCode.S) then
|
if Engine.KeyDown(KeyCode.S) then
|
||||||
Position.x = Position.x - (deltaTime * Move_Speec)
|
-- Move backward
|
||||||
end
|
deltaX = deltaX - forward.x * moveSpeed * deltaTime
|
||||||
if Engine.KeyDown(KeyCode.D) then
|
deltaZ = deltaZ - forward.z * moveSpeed * deltaTime
|
||||||
Position.z = Position.z + (deltaTime * Move_Speec)
|
|
||||||
end
|
end
|
||||||
if Engine.KeyDown(KeyCode.A) then
|
if Engine.KeyDown(KeyCode.A) then
|
||||||
Position.z = Position.z - (deltaTime * Move_Speec)
|
-- Move right
|
||||||
|
deltaX = deltaX + right.x * moveSpeed * deltaTime
|
||||||
|
deltaZ = deltaZ + right.z * moveSpeed * deltaTime
|
||||||
|
end
|
||||||
|
if Engine.KeyDown(KeyCode.D) then
|
||||||
|
-- Move left
|
||||||
|
deltaX = deltaX - right.x * moveSpeed * deltaTime
|
||||||
|
deltaZ = deltaZ - right.z * moveSpeed * deltaTime
|
||||||
end
|
end
|
||||||
|
|
||||||
transform:SetPosition(Position)
|
-- Update position based on calculated deltas
|
||||||
|
position.x = position.x + deltaX
|
||||||
|
position.z = position.z + deltaZ
|
||||||
|
transform:SetPosition(position)
|
||||||
|
|
||||||
Engine.Expose("Position X", Position.x)
|
-- Expose updated position and rotation
|
||||||
|
Engine.Expose("Position X", position.x)
|
||||||
|
Engine.Expose("Position Z", rotation.z)
|
||||||
|
Engine.Expose("Rotation Y", currentRotation)
|
||||||
local rotation = {
|
|
||||||
x = old_rotation.x, -- Preserving existing new_rotation on X-axis
|
|
||||||
y = new_rotation, -- Updated new_rotation on Y-axis for spinning
|
|
||||||
z = old_rotation.z -- Preserving existing new_rotation on Z-axis
|
|
||||||
}
|
|
||||||
-- Apply the new new_rotation to the Transform component
|
|
||||||
transform:SetRotation(rotation)
|
|
||||||
new_rotation = new_rotation + (deltaTime * new_rotationSpeed)
|
|
||||||
if new_rotation >= 360 then
|
|
||||||
new_rotation = 0
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
@ -1 +1,76 @@
|
|||||||
return _T_Engine_Table -- This just returns the Global Table that the engine creates
|
--@module Engine
|
||||||
|
|
||||||
|
--[[
|
||||||
|
Engine.lua serves as the Lua interface for your engine's functionalities.
|
||||||
|
It maps C++ bound functions from `_T_Engine_Table` to a Lua `Engine` table,
|
||||||
|
enriched with EmmyLua annotations for enhanced IntelliSense support.
|
||||||
|
]]
|
||||||
|
|
||||||
|
---@class Color
|
||||||
|
---@field r number Red component (0-1)
|
||||||
|
---@field g number Green component (0-1)
|
||||||
|
---@field b number Blue component (0-1)
|
||||||
|
---@field a number Alpha component (0-1)
|
||||||
|
|
||||||
|
---@class Vector3
|
||||||
|
---@field x number
|
||||||
|
---@field y number
|
||||||
|
---@field z number
|
||||||
|
|
||||||
|
---@class Transform
|
||||||
|
---@field position Vector3 The position of the Transform.
|
||||||
|
---@field rotation Vector3 The rotation of the Transform.
|
||||||
|
---@field scale Vector3 The scale of the Transform.
|
||||||
|
|
||||||
|
---@class Camera
|
||||||
|
---@field fieldOfView number The camera's field of view.
|
||||||
|
---@field nearClipPlane number The near clipping plane distance.
|
||||||
|
---@field farClipPlane number The far clipping plane distance.
|
||||||
|
|
||||||
|
---@class Mesh
|
||||||
|
---@field vertices Vector3[] The vertices of the mesh.
|
||||||
|
---@field indices number[] The indices defining the mesh's triangles.
|
||||||
|
|
||||||
|
---@class GameObject
|
||||||
|
local GameObject = {}
|
||||||
|
|
||||||
|
---Retrieves a component attached to the GameObject.
|
||||||
|
---@param componentName string The name of the component to retrieve ("Transform", "Camera", "Mesh")
|
||||||
|
---@return Transform|Camera|Mesh|nil The requested component or `nil` if not found.
|
||||||
|
function GameObject:GetComponent(componentName)
|
||||||
|
-- The actual implementation is bound in C++.
|
||||||
|
-- This is just for IntelliSense support.
|
||||||
|
end
|
||||||
|
|
||||||
|
---@class Engine
|
||||||
|
local Engine = {}
|
||||||
|
|
||||||
|
---Logs a message with an optional color and alpha.
|
||||||
|
---@param message string The message to log.
|
||||||
|
---@param color? Color Optional color and alpha for the log message.
|
||||||
|
---@return void
|
||||||
|
Engine.Log = _T_Engine_Table.Log
|
||||||
|
|
||||||
|
---Exposes a variable to the engine.
|
||||||
|
---@param name string The identifier name of the variable.
|
||||||
|
---@param label string A human-readable label for the variable.
|
||||||
|
---@param value number|string|boolean|nil The value to expose (int, float, bool, string, nil).
|
||||||
|
---@return void
|
||||||
|
Engine.Expose = _T_Engine_Table.Expose
|
||||||
|
|
||||||
|
---Checks if a specific key is currently pressed.
|
||||||
|
---@param keyCode KeyCode The key code to check.
|
||||||
|
---@return boolean True if the key is pressed, false otherwise.
|
||||||
|
Engine.KeyDown = _T_Engine_Table.KeyDown
|
||||||
|
|
||||||
|
---Retrieves the name of the current script.
|
||||||
|
---@return string The name of the script.
|
||||||
|
Engine.ScriptName = _T_Engine_Table.ScriptName
|
||||||
|
|
||||||
|
---Gets a GameObject by its tag.
|
||||||
|
---@param tag string The tag associated with the GameObject.
|
||||||
|
---@return GameObject|nil The GameObject with the specified tag, or `nil` if not found.
|
||||||
|
Engine.GetGameObjectByTag = _T_Engine_Table.GetGameObjectByTag
|
||||||
|
|
||||||
|
|
||||||
|
return Engine
|
||||||
|
@ -1 +1,249 @@
|
|||||||
return _T_KeyCode_Table
|
--@module KeyCodes
|
||||||
|
|
||||||
|
local _Engine_KeyCodes = _T_KeyCode_Table
|
||||||
|
|
||||||
|
---@class KeyCode
|
||||||
|
---@field Space number
|
||||||
|
---@field Apostrophe number
|
||||||
|
---@field Comma number
|
||||||
|
---@field Minus number
|
||||||
|
---@field Period number
|
||||||
|
---@field Slash number
|
||||||
|
---@field D0 number
|
||||||
|
---@field D1 number
|
||||||
|
---@field D2 number
|
||||||
|
---@field D3 number
|
||||||
|
---@field D4 number
|
||||||
|
---@field D5 number
|
||||||
|
---@field D6 number
|
||||||
|
---@field D7 number
|
||||||
|
---@field D8 number
|
||||||
|
---@field D9 number
|
||||||
|
---@field Semicolon number
|
||||||
|
---@field Equal number
|
||||||
|
---@field A number
|
||||||
|
---@field B number
|
||||||
|
---@field C number
|
||||||
|
---@field D number
|
||||||
|
---@field E number
|
||||||
|
---@field F number
|
||||||
|
---@field G number
|
||||||
|
---@field H number
|
||||||
|
---@field I number
|
||||||
|
---@field J number
|
||||||
|
---@field K number
|
||||||
|
---@field L number
|
||||||
|
---@field M number
|
||||||
|
---@field N number
|
||||||
|
---@field O number
|
||||||
|
---@field P number
|
||||||
|
---@field Q number
|
||||||
|
---@field R number
|
||||||
|
---@field S number
|
||||||
|
---@field T number
|
||||||
|
---@field U number
|
||||||
|
---@field V number
|
||||||
|
---@field W number
|
||||||
|
---@field X number
|
||||||
|
---@field Y number
|
||||||
|
---@field Z number
|
||||||
|
---@field LeftBracket number
|
||||||
|
---@field Backslash number
|
||||||
|
---@field RightBracket number
|
||||||
|
---@field GraveAccent number
|
||||||
|
---@field World1 number
|
||||||
|
---@field World2 number
|
||||||
|
---@field Escape number
|
||||||
|
---@field Enter number
|
||||||
|
---@field Tab number
|
||||||
|
---@field Backspace number
|
||||||
|
---@field Insert number
|
||||||
|
---@field Delete number
|
||||||
|
---@field Right number
|
||||||
|
---@field Left number
|
||||||
|
---@field Down number
|
||||||
|
---@field Up number
|
||||||
|
---@field PageUp number
|
||||||
|
---@field PageDown number
|
||||||
|
---@field Home number
|
||||||
|
---@field End number
|
||||||
|
---@field CapsLock number
|
||||||
|
---@field ScrollLock number
|
||||||
|
---@field NumLock number
|
||||||
|
---@field PrintScreen number
|
||||||
|
---@field Pause number
|
||||||
|
---@field F1 number
|
||||||
|
---@field F2 number
|
||||||
|
---@field F3 number
|
||||||
|
---@field F4 number
|
||||||
|
---@field F5 number
|
||||||
|
---@field F6 number
|
||||||
|
---@field F7 number
|
||||||
|
---@field F8 number
|
||||||
|
---@field F9 number
|
||||||
|
---@field F10 number
|
||||||
|
---@field F11 number
|
||||||
|
---@field F12 number
|
||||||
|
---@field F13 number
|
||||||
|
---@field F14 number
|
||||||
|
---@field F15 number
|
||||||
|
---@field F16 number
|
||||||
|
---@field F17 number
|
||||||
|
---@field F18 number
|
||||||
|
---@field F19 number
|
||||||
|
---@field F20 number
|
||||||
|
---@field F21 number
|
||||||
|
---@field F22 number
|
||||||
|
---@field F23 number
|
||||||
|
---@field F24 number
|
||||||
|
---@field F25 number
|
||||||
|
---@field KP0 number
|
||||||
|
---@field KP1 number
|
||||||
|
---@field KP2 number
|
||||||
|
---@field KP3 number
|
||||||
|
---@field KP4 number
|
||||||
|
---@field KP5 number
|
||||||
|
---@field KP6 number
|
||||||
|
---@field KP7 number
|
||||||
|
---@field KP8 number
|
||||||
|
---@field KP9 number
|
||||||
|
---@field KPDecimal number
|
||||||
|
---@field KPDivide number
|
||||||
|
---@field KPMultiply number
|
||||||
|
---@field KPSubtract number
|
||||||
|
---@field KPAdd number
|
||||||
|
---@field KPEnter number
|
||||||
|
---@field KPEqual number
|
||||||
|
---@field LeftShift number
|
||||||
|
---@field LeftControl number
|
||||||
|
---@field LeftAlt number
|
||||||
|
---@field LeftSuper number
|
||||||
|
---@field RightShift number
|
||||||
|
---@field RightControl number
|
||||||
|
---@field RightAlt number
|
||||||
|
---@field RightSuper number
|
||||||
|
---@field Menu number
|
||||||
|
local KeyCodes = {
|
||||||
|
Space = _Engine_KeyCodes.Space,
|
||||||
|
Apostrophe = _Engine_KeyCodes.Apostrophe,
|
||||||
|
Comma = _Engine_KeyCodes.Comma,
|
||||||
|
Minus = _Engine_KeyCodes.Minus,
|
||||||
|
Period = _Engine_KeyCodes.Period,
|
||||||
|
Slash = _Engine_KeyCodes.Slash,
|
||||||
|
D0 = _Engine_KeyCodes.D0,
|
||||||
|
D1 = _Engine_KeyCodes.D1,
|
||||||
|
D2 = _Engine_KeyCodes.D2,
|
||||||
|
D3 = _Engine_KeyCodes.D3,
|
||||||
|
D4 = _Engine_KeyCodes.D4,
|
||||||
|
D5 = _Engine_KeyCodes.D5,
|
||||||
|
D6 = _Engine_KeyCodes.D6,
|
||||||
|
D7 = _Engine_KeyCodes.D7,
|
||||||
|
D8 = _Engine_KeyCodes.D8,
|
||||||
|
D9 = _Engine_KeyCodes.D9,
|
||||||
|
Semicolon = _Engine_KeyCodes.Semicolon,
|
||||||
|
Equal = _Engine_KeyCodes.Equal,
|
||||||
|
A = _Engine_KeyCodes.A,
|
||||||
|
B = _Engine_KeyCodes.B,
|
||||||
|
C = _Engine_KeyCodes.C,
|
||||||
|
D = _Engine_KeyCodes.D,
|
||||||
|
E = _Engine_KeyCodes.E,
|
||||||
|
F = _Engine_KeyCodes.F,
|
||||||
|
G = _Engine_KeyCodes.G,
|
||||||
|
H = _Engine_KeyCodes.H,
|
||||||
|
I = _Engine_KeyCodes.I,
|
||||||
|
J = _Engine_KeyCodes.J,
|
||||||
|
K = _Engine_KeyCodes.K,
|
||||||
|
L = _Engine_KeyCodes.L,
|
||||||
|
M = _Engine_KeyCodes.M,
|
||||||
|
N = _Engine_KeyCodes.N,
|
||||||
|
O = _Engine_KeyCodes.O,
|
||||||
|
P = _Engine_KeyCodes.P,
|
||||||
|
Q = _Engine_KeyCodes.Q,
|
||||||
|
R = _Engine_KeyCodes.R,
|
||||||
|
S = _Engine_KeyCodes.S,
|
||||||
|
T = _Engine_KeyCodes.T,
|
||||||
|
U = _Engine_KeyCodes.U,
|
||||||
|
V = _Engine_KeyCodes.V,
|
||||||
|
W = _Engine_KeyCodes.W,
|
||||||
|
X = _Engine_KeyCodes.X,
|
||||||
|
Y = _Engine_KeyCodes.Y,
|
||||||
|
Z = _Engine_KeyCodes.Z,
|
||||||
|
LeftBracket = _Engine_KeyCodes.LeftBracket,
|
||||||
|
Backslash = _Engine_KeyCodes.Backslash,
|
||||||
|
RightBracket = _Engine_KeyCodes.RightBracket,
|
||||||
|
GraveAccent = _Engine_KeyCodes.GraveAccent,
|
||||||
|
World1 = _Engine_KeyCodes.World1,
|
||||||
|
World2 = _Engine_KeyCodes.World2,
|
||||||
|
Escape = _Engine_KeyCodes.Escape,
|
||||||
|
Enter = _Engine_KeyCodes.Enter,
|
||||||
|
Tab = _Engine_KeyCodes.Tab,
|
||||||
|
Backspace = _Engine_KeyCodes.Backspace,
|
||||||
|
Insert = _Engine_KeyCodes.Insert,
|
||||||
|
Delete = _Engine_KeyCodes.Delete,
|
||||||
|
Right = _Engine_KeyCodes.Right,
|
||||||
|
Left = _Engine_KeyCodes.Left,
|
||||||
|
Down = _Engine_KeyCodes.Down,
|
||||||
|
Up = _Engine_KeyCodes.Up,
|
||||||
|
PageUp = _Engine_KeyCodes.PageUp,
|
||||||
|
PageDown = _Engine_KeyCodes.PageDown,
|
||||||
|
Home = _Engine_KeyCodes.Home,
|
||||||
|
End = _Engine_KeyCodes.End,
|
||||||
|
CapsLock = _Engine_KeyCodes.CapsLock,
|
||||||
|
ScrollLock = _Engine_KeyCodes.ScrollLock,
|
||||||
|
NumLock = _Engine_KeyCodes.NumLock,
|
||||||
|
PrintScreen = _Engine_KeyCodes.PrintScreen,
|
||||||
|
Pause = _Engine_KeyCodes.Pause,
|
||||||
|
F1 = _Engine_KeyCodes.F1,
|
||||||
|
F2 = _Engine_KeyCodes.F2,
|
||||||
|
F3 = _Engine_KeyCodes.F3,
|
||||||
|
F4 = _Engine_KeyCodes.F4,
|
||||||
|
F5 = _Engine_KeyCodes.F5,
|
||||||
|
F6 = _Engine_KeyCodes.F6,
|
||||||
|
F7 = _Engine_KeyCodes.F7,
|
||||||
|
F8 = _Engine_KeyCodes.F8,
|
||||||
|
F9 = _Engine_KeyCodes.F9,
|
||||||
|
F10 = _Engine_KeyCodes.F10,
|
||||||
|
F11 = _Engine_KeyCodes.F11,
|
||||||
|
F12 = _Engine_KeyCodes.F12,
|
||||||
|
F13 = _Engine_KeyCodes.F13,
|
||||||
|
F14 = _Engine_KeyCodes.F14,
|
||||||
|
F15 = _Engine_KeyCodes.F15,
|
||||||
|
F16 = _Engine_KeyCodes.F16,
|
||||||
|
F17 = _Engine_KeyCodes.F17,
|
||||||
|
F18 = _Engine_KeyCodes.F18,
|
||||||
|
F19 = _Engine_KeyCodes.F19,
|
||||||
|
F20 = _Engine_KeyCodes.F20,
|
||||||
|
F21 = _Engine_KeyCodes.F21,
|
||||||
|
F22 = _Engine_KeyCodes.F22,
|
||||||
|
F23 = _Engine_KeyCodes.F23,
|
||||||
|
F24 = _Engine_KeyCodes.F24,
|
||||||
|
F25 = _Engine_KeyCodes.F25,
|
||||||
|
KP0 = _Engine_KeyCodes.KP0,
|
||||||
|
KP1 = _Engine_KeyCodes.KP1,
|
||||||
|
KP2 = _Engine_KeyCodes.KP2,
|
||||||
|
KP3 = _Engine_KeyCodes.KP3,
|
||||||
|
KP4 = _Engine_KeyCodes.KP4,
|
||||||
|
KP5 = _Engine_KeyCodes.KP5,
|
||||||
|
KP6 = _Engine_KeyCodes.KP6,
|
||||||
|
KP7 = _Engine_KeyCodes.KP7,
|
||||||
|
KP8 = _Engine_KeyCodes.KP8,
|
||||||
|
KP9 = _Engine_KeyCodes.KP9,
|
||||||
|
KPDecimal = _Engine_KeyCodes.KPDecimal,
|
||||||
|
KPDivide = _Engine_KeyCodes.KPDivide,
|
||||||
|
KPMultiply = _Engine_KeyCodes.KPMultiply,
|
||||||
|
KPSubtract = _Engine_KeyCodes.KPSubtract,
|
||||||
|
KPAdd = _Engine_KeyCodes.KPAdd,
|
||||||
|
KPEnter = _Engine_KeyCodes.KPEnter,
|
||||||
|
KPEqual = _Engine_KeyCodes.KPEqual,
|
||||||
|
LeftShift = _Engine_KeyCodes.LeftShift,
|
||||||
|
LeftControl = _Engine_KeyCodes.LeftControl,
|
||||||
|
LeftAlt = _Engine_KeyCodes.LeftAlt,
|
||||||
|
LeftSuper = _Engine_KeyCodes.LeftSuper,
|
||||||
|
RightShift = _Engine_KeyCodes.RightShift,
|
||||||
|
RightControl = _Engine_KeyCodes.RightControl,
|
||||||
|
RightAlt = _Engine_KeyCodes.RightAlt,
|
||||||
|
RightSuper = _Engine_KeyCodes.RightSuper,
|
||||||
|
Menu = _Engine_KeyCodes.Menu
|
||||||
|
}
|
||||||
|
|
||||||
|
return KeyCodes
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
-- script.lua
|
-- script.lua
|
||||||
|
|
||||||
local Math = require("./assets/scripts/math")
|
local Engine = require("engine")
|
||||||
local Engine = require("./assets/scripts/engine")
|
|
||||||
|
|
||||||
local itterator = 0
|
|
||||||
local ticks = 0
|
|
||||||
local new_rotation = 0
|
local new_rotation = 0
|
||||||
local speed = 50
|
local speed = 50
|
||||||
|
|
||||||
|
@ -1,240 +0,0 @@
|
|||||||
-- unitTests.lua
|
|
||||||
-- Unit Tests for C++ Lua API and Game Engine
|
|
||||||
|
|
||||||
local Math = require("./assets/scripts/math")
|
|
||||||
local Engine = require("./assets/scripts/engine")
|
|
||||||
|
|
||||||
|
|
||||||
local function OnInit()
|
|
||||||
-- Log a message with a custom red color
|
|
||||||
Engine.Log("This is a red message.", {1.0, 0.0, 0.0, 1.0})
|
|
||||||
|
|
||||||
-- Log a message with a custom green color
|
|
||||||
Engine.Log("This is a green message.", {0.0, 1.0, 0.0, 1.0})
|
|
||||||
|
|
||||||
-- Log a message with a custom blue color
|
|
||||||
Engine.Log("This is a blue message.", {0.0, 0.0, 1.0, 1.0})
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Simple Test Framework
|
|
||||||
|
|
||||||
local Tests = {}
|
|
||||||
local passed = 0
|
|
||||||
local failed = 0
|
|
||||||
|
|
||||||
-- Assertion Functions
|
|
||||||
local function assertEquals(expected, actual, message)
|
|
||||||
if expected ~= actual then
|
|
||||||
error(message or string.format("Assertion Failed: expected '%s', got '%s'", tostring(expected), tostring(actual)))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function assertTableEquals(expected, actual, message)
|
|
||||||
if type(expected) ~= "table" or type(actual) ~= "table" then
|
|
||||||
error(message or "Assertion Failed: One of the values is not a table.")
|
|
||||||
end
|
|
||||||
for k, v in pairs(expected) do
|
|
||||||
if actual[k] ~= v then
|
|
||||||
error(message or string.format("Assertion Failed: For key '%s', expected '%s', got '%s'", tostring(k), tostring(v), tostring(actual[k])))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function assertNotNil(value, message)
|
|
||||||
if value == nil then
|
|
||||||
error(message or "Assertion Failed: value is nil.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
local function assertTrue(condition, message)
|
|
||||||
if not condition then
|
|
||||||
error(message or "Assertion Failed: condition is not true.")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Helper Function to Capture Logs
|
|
||||||
local capturedLogs = {}
|
|
||||||
local originalLog = Engine.Log
|
|
||||||
|
|
||||||
local function mockLog(message, color)
|
|
||||||
table.insert(capturedLogs, {message = message, color = color})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Register Test Cases
|
|
||||||
function Tests.testEngineLog()
|
|
||||||
-- Replace Engine.Log with mockLog
|
|
||||||
Engine.Log = mockLog
|
|
||||||
|
|
||||||
-- Call OnInit to generate logs
|
|
||||||
OnInit()
|
|
||||||
|
|
||||||
-- Restore original Engine.Log
|
|
||||||
Engine.Log = originalLog
|
|
||||||
|
|
||||||
-- Assertions
|
|
||||||
assertEquals(3, #capturedLogs, "OnInit should log exactly 3 messages.")
|
|
||||||
|
|
||||||
-- Check first log (Red Message)
|
|
||||||
assertEquals("This is a red message.", capturedLogs[1].message)
|
|
||||||
assertTableEquals({1.0, 0.0, 0.0, 1.0}, capturedLogs[1].color, "First log color mismatch.")
|
|
||||||
|
|
||||||
-- Check second log (Green Message)
|
|
||||||
assertEquals("This is a green message.", capturedLogs[2].message)
|
|
||||||
assertTableEquals({0.0, 1.0, 0.0, 1.0}, capturedLogs[2].color, "Second log color mismatch.")
|
|
||||||
|
|
||||||
-- Check third log (Blue Message)
|
|
||||||
assertEquals("This is a blue message.", capturedLogs[3].message)
|
|
||||||
assertTableEquals({0.0, 0.0, 1.0, 1.0}, capturedLogs[3].color, "Third log color mismatch.")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tests.testGetGameObjectByTag()
|
|
||||||
-- Assume "Player" and "Gun" GameObjects exist
|
|
||||||
local player = Engine.GetGameObjectByTag("Player")
|
|
||||||
assertNotNil(player, "Player GameObject should exist.")
|
|
||||||
|
|
||||||
local gun = Engine.GetGameObjectByTag("Gun")
|
|
||||||
assertNotNil(gun, "Gun GameObject should exist.")
|
|
||||||
|
|
||||||
-- Test for a non-existent tag
|
|
||||||
local nonExistent = Engine.GetGameObjectByTag("NonExistentTag")
|
|
||||||
assertEquals(nil, nonExistent, "Non-existent GameObject should return nil.")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tests.testGameObjectGetName()
|
|
||||||
local player = Engine.GetGameObjectByTag("Player")
|
|
||||||
assertNotNil(player, "Player GameObject should exist.")
|
|
||||||
|
|
||||||
local name = player:GetName()
|
|
||||||
assertEquals("Player", name, "Player GameObject name should be 'Player'.")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tests.testGameObjectGetComponent()
|
|
||||||
local player = Engine.GetGameObjectByTag("Player")
|
|
||||||
assertNotNil(player, "Player GameObject should exist.")
|
|
||||||
|
|
||||||
local transform = player:GetComponent("Transform")
|
|
||||||
assertNotNil(transform, "Player should have a Transform component.")
|
|
||||||
|
|
||||||
local nonExistentComponent = player:GetComponent("NonExistentComponent")
|
|
||||||
assertEquals(nil, nonExistentComponent, "Non-existent component should return nil.")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tests.testTransformComponentPosition()
|
|
||||||
local player = Engine.GetGameObjectByTag("Player")
|
|
||||||
assertNotNil(player, "Player GameObject should exist.")
|
|
||||||
|
|
||||||
local transform = player:GetComponent("Transform")
|
|
||||||
assertNotNil(transform, "Player should have a Transform component.")
|
|
||||||
|
|
||||||
-- Get initial position
|
|
||||||
local position = transform:GetPosition()
|
|
||||||
assertNotNil(position, "Transform:GetPosition should return a position table.")
|
|
||||||
assertEquals(0.0, position.x, "Initial X position should be 0.0.")
|
|
||||||
assertEquals(2.0, position.y, "Initial Y position should be 2.0.")
|
|
||||||
assertEquals(-12.0, position.z, "Initial Z position should be -12.0.")
|
|
||||||
|
|
||||||
-- Set new position
|
|
||||||
local newPosition = {x = 5.0, y = 10.0, z = -15.0}
|
|
||||||
transform:SetPosition(newPosition)
|
|
||||||
|
|
||||||
-- Get updated position
|
|
||||||
local updatedPosition = transform:GetPosition()
|
|
||||||
assertTableEquals(newPosition, updatedPosition, "Transform:SetPosition did not update position correctly.")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tests.testTransformComponentRotation()
|
|
||||||
local player = Engine.GetGameObjectByTag("Player")
|
|
||||||
assertNotNil(player, "Player GameObject should exist.")
|
|
||||||
|
|
||||||
local transform = player:GetComponent("Transform")
|
|
||||||
assertNotNil(transform, "Player should have a Transform component.")
|
|
||||||
|
|
||||||
-- Get initial rotation
|
|
||||||
local rotation = transform:GetRotation()
|
|
||||||
assertNotNil(rotation, "Transform:GetRotation should return a rotation table.")
|
|
||||||
|
|
||||||
-- Set new rotation
|
|
||||||
local newRotation = {x = 45.0, y = 90.0, z = 135.0}
|
|
||||||
transform:SetRotation(newRotation)
|
|
||||||
|
|
||||||
-- Get updated rotation
|
|
||||||
local updatedRotation = transform:GetRotation()
|
|
||||||
assertTableEquals(newRotation, updatedRotation, "Transform:SetRotation did not update rotation correctly.")
|
|
||||||
end
|
|
||||||
|
|
||||||
function Tests.testOnUpdateFunctionality()
|
|
||||||
-- Mock GameObject and Transform
|
|
||||||
local mockPlayer = {
|
|
||||||
GetName = function() return "Player" end,
|
|
||||||
GetComponent = function(componentName)
|
|
||||||
if componentName == "Transform" then
|
|
||||||
return {
|
|
||||||
GetRotation = function()
|
|
||||||
return {x = new_rotation, y = new_rotation, z = new_rotation}
|
|
||||||
end,
|
|
||||||
SetRotation = function(rotation)
|
|
||||||
new_rotation = rotation.x
|
|
||||||
end
|
|
||||||
}
|
|
||||||
end
|
|
||||||
return nil
|
|
||||||
end
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Replace Engine.GetGameObjectByTag to return mockPlayer
|
|
||||||
local originalGetGameObjectByTag = Engine.GetGameObjectByTag
|
|
||||||
Engine.GetGameObjectByTag = function(tag)
|
|
||||||
if tag == "Player" then
|
|
||||||
return mockPlayer
|
|
||||||
end
|
|
||||||
return originalGetGameObjectByTag(tag)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Initialize rotation
|
|
||||||
new_rotation = 0
|
|
||||||
speed = 50
|
|
||||||
|
|
||||||
-- Call OnUpdate with deltaTime = 1
|
|
||||||
OnUpdate(1)
|
|
||||||
|
|
||||||
-- Check new_rotation
|
|
||||||
assertEquals(50, new_rotation, "After first OnUpdate, new_rotation should be 50.")
|
|
||||||
|
|
||||||
-- Call OnUpdate with deltaTime = 14 (to exceed 720)
|
|
||||||
OnUpdate(14)
|
|
||||||
|
|
||||||
-- new_rotation should reset to 0 after exceeding 720
|
|
||||||
assertEquals(720 + 50 - 720, new_rotation, "After exceeding 720, new_rotation should reset appropriately.")
|
|
||||||
|
|
||||||
-- Restore original Engine.GetGameObjectByTag
|
|
||||||
Engine.GetGameObjectByTag = originalGetGameObjectByTag
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Add more test functions below as needed
|
|
||||||
|
|
||||||
-- Test Runner
|
|
||||||
local function runTests()
|
|
||||||
print("Starting Unit Tests...\n")
|
|
||||||
for testName, testFunc in pairs(Tests) do
|
|
||||||
io.write(string.format("Running %s... ", testName))
|
|
||||||
local status, err = pcall(testFunc)
|
|
||||||
if status then
|
|
||||||
print("PASSED")
|
|
||||||
passed = passed + 1
|
|
||||||
else
|
|
||||||
print("FAILED")
|
|
||||||
print(" Error:", err)
|
|
||||||
failed = failed + 1
|
|
||||||
end
|
|
||||||
end
|
|
||||||
print(string.format("\nUnit Tests Completed: %d Passed, %d Failed", passed, failed))
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Execute Tests
|
|
||||||
runTests()
|
|
6
assets/shaders/Line.frag
Normal file
6
assets/shaders/Line.frag
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#version 330 core
|
||||||
|
out vec4 FragColor;
|
||||||
|
uniform vec4 uColor;
|
||||||
|
void main() {
|
||||||
|
FragColor = uColor;
|
||||||
|
}
|
8
assets/shaders/Line.vert
Normal file
8
assets/shaders/Line.vert
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#version 330 core
|
||||||
|
layout (location = 0) in vec3 aPos;
|
||||||
|
uniform mat4 uMVP;
|
||||||
|
void main() {
|
||||||
|
gl_Position = uMVP * vec4(aPos, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
|||||||
--
|
|
||||||
-- This lua makes a Game object bounce a nd spin like a minecraft item.
|
|
||||||
local GameObjectName = "Gun" -- This is the tag of the game object you want it to modify
|
|
||||||
--
|
|
||||||
--
|
|
||||||
--
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local Math = require("./assets/scripts/math") -- Require the enhanced math module
|
|
||||||
local Engine = require("./assets/scripts/engine")
|
|
||||||
|
|
||||||
|
|
||||||
-- Variables to track elapsed time and rotation
|
|
||||||
local elapsedTime = 0
|
|
||||||
local rotationSpeed = 90 -- Degrees per second for spinning
|
|
||||||
local new_rotation = 0
|
|
||||||
|
|
||||||
-- Variables for bobbing effect
|
|
||||||
local initial_position = {x = 0, y = 0, z = 0} -- To store the gun's initial position
|
|
||||||
local bobAmplitude = 0.1 -- Amplitude of the bobbing (units)
|
|
||||||
local bobFrequency = 0.5 -- Frequency of the bobbing (oscillations per second)
|
|
||||||
|
|
||||||
-- Reference to the Gun GameObject and its Transform component
|
|
||||||
local gun = nil
|
|
||||||
local transform = nil
|
|
||||||
|
|
||||||
local TAU = Math.constants.TAU
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- Update function called every frame
|
|
||||||
function OnUpdate(deltaTime)
|
|
||||||
-- Ensure that the Gun and its Transform component are valid
|
|
||||||
-- this was made after OnInit was depricated
|
|
||||||
if not gun then
|
|
||||||
gun = Engine.GetGameObjectByTag(GameObjectName)
|
|
||||||
if gun then
|
|
||||||
transform = gun:GetComponent("Transform")
|
|
||||||
if transform then
|
|
||||||
local pos = transform:GetPosition()
|
|
||||||
initial_position = {x = pos.x, y = pos.y, z = pos.z}
|
|
||||||
Engine.Log("Gun found and initial position updated.", {1, 1, 1, 1})
|
|
||||||
else
|
|
||||||
Engine.Log("Transform component not found on Gun.", {1, 1, 0, 1})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
else
|
|
||||||
Engine.Log("Gun GameObject still not found.", {1, 1, 0, 1})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
elseif not transform then
|
|
||||||
transform = gun:GetComponent("Transform")
|
|
||||||
if transform then
|
|
||||||
local pos = transform:GetPosition()
|
|
||||||
initial_position = {x = pos.x, y = pos.y, z = pos.z}
|
|
||||||
Engine.Log("Transform component found and initial position updated.", {1, 1, 1, 1})
|
|
||||||
else
|
|
||||||
Engine.Log("Transform component still not found on Gun.", {1, 1, 0, 1})
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Increment elapsed time
|
|
||||||
elapsedTime = elapsedTime + deltaTime
|
|
||||||
|
|
||||||
-- === Spinning the Gun ===
|
|
||||||
-- Update the rotation angle based on rotationSpeed and deltaTime
|
|
||||||
new_rotation = new_rotation + (deltaTime * rotationSpeed)
|
|
||||||
|
|
||||||
-- Keep the rotation angle within 0-360 degrees to prevent overflow
|
|
||||||
if new_rotation >= 360 then
|
|
||||||
new_rotation = new_rotation - 360
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Define the new rotation (spinning around the Y-axis)
|
|
||||||
local rotation = {
|
|
||||||
x = -180, -- Preserving existing rotation on X-axis
|
|
||||||
y = new_rotation, -- Updated rotation on Y-axis for spinning
|
|
||||||
z = 0 -- Preserving existing rotation on Z-axis
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Apply the new rotation to the Transform component
|
|
||||||
transform:SetRotation(rotation)
|
|
||||||
|
|
||||||
-- === Bobbing the Gun Up and Down ===
|
|
||||||
-- Calculate the bobbing offset using a sine wave
|
|
||||||
local bobOffset = bobAmplitude * math.sin(TAU * bobFrequency * elapsedTime)
|
|
||||||
|
|
||||||
-- Define the new position by adding the bobbing offset to the initial Y position
|
|
||||||
local new_position = {
|
|
||||||
x = initial_position.x, -- No change on X-axis
|
|
||||||
y = initial_position.y + bobOffset, -- Bouncing up and down on Y-axis
|
|
||||||
z = initial_position.z -- No change on Z-axis
|
|
||||||
}
|
|
||||||
|
|
||||||
-- Apply the new position to the Transform component
|
|
||||||
transform:SetPosition(new_position)
|
|
||||||
|
|
||||||
-- === Optional: Log Current Rotation and Position ===
|
|
||||||
-- Uncomment the following lines if you wish to log the gun's current rotation and position
|
|
||||||
-- local current_rotation = transform:GetRotation()
|
|
||||||
-- Engine.Log(string.format("Gun Rotation: (X: %.2f, Y: %.2f, Z: %.2f)", current_rotation.x, current_rotation.y, current_rotation.z), {1, 1, 1, 1})
|
|
||||||
|
|
||||||
-- local current_position = transform:GetPosition()
|
|
||||||
-- Engine.Log(string.format("Gun Position: (X: %.2f, Y: %.2f, Z: %.2f)", current_position.x, current_position.y, current_position.z), {1, 1, 1, 1})
|
|
||||||
end
|
|
127
imgui.ini
127
imgui.ini
@ -1,10 +1,10 @@
|
|||||||
[Window][DockSpace]
|
[Window][DockSpace]
|
||||||
Pos=0,0
|
Pos=0,0
|
||||||
Size=1920,1177
|
Size=1280,720
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
|
|
||||||
[Window][Debug##Default]
|
[Window][Debug##Default]
|
||||||
ViewportPos=926,1030
|
ViewportPos=1168,966
|
||||||
ViewportId=0x16723995
|
ViewportId=0x16723995
|
||||||
Size=400,400
|
Size=400,400
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
@ -80,8 +80,8 @@ Collapsed=0
|
|||||||
DockId=0x0000001F,0
|
DockId=0x0000001F,0
|
||||||
|
|
||||||
[Window][Performance##performance]
|
[Window][Performance##performance]
|
||||||
Pos=8,702
|
Pos=8,360
|
||||||
Size=335,467
|
Size=335,352
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000001C,0
|
DockId=0x0000001C,0
|
||||||
|
|
||||||
@ -95,7 +95,7 @@ DockId=0x00000019,0
|
|||||||
Pos=8,27
|
Pos=8,27
|
||||||
Size=322,732
|
Size=322,732
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000023,0
|
DockId=0x0000001B,0
|
||||||
|
|
||||||
[Window][Scene Window@SceneWindow]
|
[Window][Scene Window@SceneWindow]
|
||||||
Pos=8,27
|
Pos=8,27
|
||||||
@ -105,9 +105,9 @@ DockId=0x0000000F,0
|
|||||||
|
|
||||||
[Window][Scene Window##SceneWindow]
|
[Window][Scene Window##SceneWindow]
|
||||||
Pos=8,28
|
Pos=8,28
|
||||||
Size=335,672
|
Size=335,330
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000023,0
|
DockId=0x0000001B,0
|
||||||
|
|
||||||
[Window][Game Objects]
|
[Window][Game Objects]
|
||||||
Pos=182,27
|
Pos=182,27
|
||||||
@ -134,28 +134,34 @@ Collapsed=0
|
|||||||
DockId=0x0000001E,0
|
DockId=0x0000001E,0
|
||||||
|
|
||||||
[Window][ Logger##logger]
|
[Window][ Logger##logger]
|
||||||
Pos=345,846
|
Pos=345,282
|
||||||
Size=1189,323
|
Size=265,430
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000025,0
|
DockId=0x00000021,0
|
||||||
|
|
||||||
[Window][ Editor##EditorWindow]
|
[Window][ Editor##EditorWindow]
|
||||||
Pos=345,28
|
Pos=345,28
|
||||||
Size=1189,816
|
Size=530,252
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x0000001F,0
|
DockId=0x0000001F,0
|
||||||
|
|
||||||
[Window][ Inspector##InspectorWindow]
|
[Window][ Inspector##InspectorWindow]
|
||||||
Pos=1536,28
|
Pos=877,28
|
||||||
Size=376,1141
|
Size=395,684
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000022,0
|
DockId=0x00000022,0
|
||||||
|
|
||||||
[Window][ Profiler]
|
[Window][ Profiler]
|
||||||
Pos=-344,52
|
Pos=612,282
|
||||||
Size=335,199
|
Size=263,430
|
||||||
Collapsed=0
|
Collapsed=0
|
||||||
DockId=0x00000024,0
|
DockId=0x00000023,0
|
||||||
|
|
||||||
|
[Window][Logger Window]
|
||||||
|
Pos=345,282
|
||||||
|
Size=530,430
|
||||||
|
Collapsed=0
|
||||||
|
DockId=0x00000023,1
|
||||||
|
|
||||||
[Table][0xE9E836E4,4]
|
[Table][0xE9E836E4,4]
|
||||||
Column 0 Weight=1.2999
|
Column 0 Weight=1.2999
|
||||||
@ -164,48 +170,53 @@ Column 2 Weight=0.6474
|
|||||||
Column 3 Weight=1.0088
|
Column 3 Weight=1.0088
|
||||||
|
|
||||||
[Table][0x08173DEA,4]
|
[Table][0x08173DEA,4]
|
||||||
Column 0 Weight=1.4321
|
Column 0 Weight=1.4299
|
||||||
Column 1 Weight=0.8821
|
Column 1 Weight=0.9086
|
||||||
Column 2 Weight=0.9929
|
Column 2 Weight=0.9665
|
||||||
Column 3 Weight=0.6929
|
Column 3 Weight=0.6950
|
||||||
|
|
||||||
|
[Table][0x801835C4,2]
|
||||||
|
RefScale=16
|
||||||
|
Column 0 Width=30
|
||||||
|
Column 1 Weight=1.0000
|
||||||
|
|
||||||
[Docking][Data]
|
[Docking][Data]
|
||||||
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=8,51 Size=1904,1141 Split=X Selected=0xF7365A5A
|
DockSpace ID=0x14621557 Window=0x3DA2F1DE Pos=250,293 Size=1264,684 Split=X Selected=0xF7365A5A
|
||||||
DockNode ID=0x00000020 Parent=0x14621557 SizeRef=886,684 Split=X
|
DockNode ID=0x00000020 Parent=0x14621557 SizeRef=884,684 Split=X
|
||||||
DockNode ID=0x00000013 Parent=0x00000020 SizeRef=335,1142 Split=Y Selected=0x818D04BB
|
DockNode ID=0x00000013 Parent=0x00000020 SizeRef=335,1142 Split=Y Selected=0x818D04BB
|
||||||
DockNode ID=0x0000001B Parent=0x00000013 SizeRef=264,672 Split=Y Selected=0x1D5D92B6
|
DockNode ID=0x0000001B Parent=0x00000013 SizeRef=264,551 HiddenTabBar=1 Selected=0x1D5D92B6
|
||||||
DockNode ID=0x00000023 Parent=0x0000001B SizeRef=335,337 HiddenTabBar=1 Selected=0x1D5D92B6
|
DockNode ID=0x0000001C Parent=0x00000013 SizeRef=264,588 HiddenTabBar=1 Selected=0x818D04BB
|
||||||
DockNode ID=0x00000024 Parent=0x0000001B SizeRef=335,333 Selected=0x7A66B86B
|
DockNode ID=0x00000014 Parent=0x00000020 SizeRef=547,1142 Split=X
|
||||||
DockNode ID=0x0000001C Parent=0x00000013 SizeRef=264,467 HiddenTabBar=1 Selected=0x818D04BB
|
DockNode ID=0x00000015 Parent=0x00000014 SizeRef=1158,1142 Split=X
|
||||||
DockNode ID=0x00000014 Parent=0x00000020 SizeRef=1567,1142 Split=X
|
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
|
||||||
DockNode ID=0x00000015 Parent=0x00000014 SizeRef=1158,1142 Split=X
|
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
|
||||||
DockNode ID=0x00000011 Parent=0x00000015 SizeRef=265,1142 Selected=0x1D5D92B6
|
DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F
|
||||||
DockNode ID=0x00000012 Parent=0x00000015 SizeRef=1259,1142 Split=X
|
DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F
|
||||||
DockNode ID=0x00000009 Parent=0x00000012 SizeRef=364,1142 Split=Y Selected=0x3DC5AC3F
|
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F
|
||||||
DockNode ID=0x00000005 Parent=0x00000009 SizeRef=364,745 Split=Y Selected=0x3DC5AC3F
|
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A
|
||||||
DockNode ID=0x0000000B Parent=0x00000005 SizeRef=364,452 HiddenTabBar=1 Selected=0x3DC5AC3F
|
DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899
|
||||||
DockNode ID=0x0000000C Parent=0x00000005 SizeRef=364,291 Selected=0xAE3C694A
|
DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X
|
||||||
DockNode ID=0x00000006 Parent=0x00000009 SizeRef=364,395 HiddenTabBar=1 Selected=0x726D8899
|
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2
|
||||||
DockNode ID=0x0000000A Parent=0x00000012 SizeRef=1538,1142 Split=X
|
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X
|
||||||
DockNode ID=0x00000007 Parent=0x0000000A SizeRef=357,1142 Selected=0x7737E8B2
|
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458
|
||||||
DockNode ID=0x00000008 Parent=0x0000000A SizeRef=1545,1142 Split=X
|
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458
|
||||||
DockNode ID=0x00000001 Parent=0x00000008 SizeRef=1202,1142 Split=Y Selected=0xDF0EC458
|
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
|
||||||
DockNode ID=0x00000003 Parent=0x00000001 SizeRef=1202,849 Split=Y Selected=0xDF0EC458
|
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1202,776 Split=Y Selected=0xDFF75B3F
|
||||||
DockNode ID=0x0000000D Parent=0x00000003 SizeRef=1202,571 Split=Y Selected=0xDFF75B3F
|
DockNode ID=0x0000001D Parent=0x00000017 SizeRef=518,720 Split=Y Selected=0x9A7B23B9
|
||||||
DockNode ID=0x00000017 Parent=0x0000000D SizeRef=1202,776 Split=Y Selected=0xDFF75B3F
|
DockNode ID=0x0000001F Parent=0x0000001D SizeRef=549,709 CentralNode=1 HiddenTabBar=1 Selected=0x9A7B23B9
|
||||||
DockNode ID=0x0000001D Parent=0x00000017 SizeRef=518,720 Split=Y Selected=0x9A7B23B9
|
DockNode ID=0x00000025 Parent=0x0000001D SizeRef=549,430 Split=X Selected=0x1F29F1F5
|
||||||
DockNode ID=0x0000001F Parent=0x0000001D SizeRef=549,359 CentralNode=1 Selected=0x9A7B23B9
|
DockNode ID=0x00000021 Parent=0x00000025 SizeRef=586,323 Selected=0x1F29F1F5
|
||||||
DockNode ID=0x00000025 Parent=0x0000001D SizeRef=549,323 Selected=0x1F29F1F5
|
DockNode ID=0x00000023 Parent=0x00000025 SizeRef=582,323 Selected=0x7A66B86B
|
||||||
DockNode ID=0x0000001E Parent=0x00000017 SizeRef=518,417 Selected=0xC74E1AEE
|
DockNode ID=0x0000001E Parent=0x00000017 SizeRef=518,417 Selected=0xC74E1AEE
|
||||||
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1202,364 Split=X Selected=0x1C0788A1
|
DockNode ID=0x00000018 Parent=0x0000000D SizeRef=1202,364 Split=X Selected=0x1C0788A1
|
||||||
DockNode ID=0x00000019 Parent=0x00000018 SizeRef=601,364 Selected=0x1C0788A1
|
DockNode ID=0x00000019 Parent=0x00000018 SizeRef=601,364 Selected=0x1C0788A1
|
||||||
DockNode ID=0x0000001A Parent=0x00000018 SizeRef=599,364 Selected=0x9B5D3198
|
DockNode ID=0x0000001A Parent=0x00000018 SizeRef=599,364 Selected=0x9B5D3198
|
||||||
DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5
|
DockNode ID=0x0000000E Parent=0x00000003 SizeRef=1202,569 Selected=0xE98146C5
|
||||||
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
|
DockNode ID=0x00000004 Parent=0x00000001 SizeRef=1202,291 Selected=0x9DD4E196
|
||||||
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
|
DockNode ID=0x00000002 Parent=0x00000008 SizeRef=334,1142 HiddenTabBar=1 Selected=0x36DC96AB
|
||||||
DockNode ID=0x00000016 Parent=0x00000014 SizeRef=420,1142 Selected=0x8D0E8380
|
DockNode ID=0x00000016 Parent=0x00000014 SizeRef=420,1142 Selected=0x8D0E8380
|
||||||
DockNode ID=0x00000022 Parent=0x14621557 SizeRef=376,684 Selected=0xD1D25642
|
DockNode ID=0x00000022 Parent=0x14621557 SizeRef=395,684 HiddenTabBar=1 Selected=0xD1D25642
|
||||||
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
|
DockSpace ID=0xC6145A92 Pos=8,27 Size=1904,1142 Split=X
|
||||||
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
|
DockNode ID=0x0000000F Parent=0xC6145A92 SizeRef=301,1142 Selected=0xA8433A03
|
||||||
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1
|
DockNode ID=0x00000010 Parent=0xC6145A92 SizeRef=1601,1142 CentralNode=1
|
||||||
|
|
||||||
|
@ -2,6 +2,10 @@ Entities:
|
|||||||
- ID: 0
|
- ID: 0
|
||||||
Name: Bacround
|
Name: Bacround
|
||||||
Components:
|
Components:
|
||||||
|
Transform:
|
||||||
|
Position: [0, 300, 0]
|
||||||
|
Rotation: [0, 0, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
Mesh:
|
Mesh:
|
||||||
MeshPath: assets/models/sponza.obj
|
MeshPath: assets/models/sponza.obj
|
||||||
submeshes_len: 26
|
submeshes_len: 26
|
||||||
@ -12,167 +16,177 @@ Entities:
|
|||||||
- id: 24
|
- id: 24
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_roof_diff.tga
|
path: textures/sponza_roof_diff.tga
|
||||||
- vao: 2
|
- vao: 3
|
||||||
indexCount: 27552
|
indexCount: 27552
|
||||||
textures:
|
textures:
|
||||||
- id: 25
|
- id: 25
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/vase_dif.tga
|
path: textures/vase_dif.tga
|
||||||
- vao: 3
|
- vao: 5
|
||||||
indexCount: 33024
|
indexCount: 33024
|
||||||
textures:
|
textures:
|
||||||
- id: 15
|
- id: 15
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_fabric_diff.tga
|
path: textures/sponza_fabric_diff.tga
|
||||||
- vao: 4
|
- vao: 7
|
||||||
indexCount: 54
|
indexCount: 54
|
||||||
textures: ~
|
textures: ~
|
||||||
- vao: 5
|
- vao: 9
|
||||||
indexCount: 12258
|
indexCount: 12258
|
||||||
textures:
|
textures:
|
||||||
- id: 5
|
- id: 5
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/background.tga
|
path: textures/background.tga
|
||||||
- vao: 6
|
- vao: 11
|
||||||
indexCount: 10416
|
indexCount: 10416
|
||||||
textures:
|
textures:
|
||||||
- id: 6
|
- id: 6
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/vase_plant.tga
|
path: textures/vase_plant.tga
|
||||||
- vao: 7
|
- vao: 13
|
||||||
indexCount: 49536
|
indexCount: 49536
|
||||||
textures:
|
textures:
|
||||||
- id: 17
|
- id: 17
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_fabric_blue_diff.tga
|
path: textures/sponza_fabric_blue_diff.tga
|
||||||
- vao: 8
|
- vao: 15
|
||||||
indexCount: 94308
|
indexCount: 94308
|
||||||
textures:
|
textures:
|
||||||
- id: 23
|
- id: 23
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_thorn_diff.tga
|
path: textures/sponza_thorn_diff.tga
|
||||||
- vao: 9
|
- vao: 17
|
||||||
indexCount: 49536
|
indexCount: 49536
|
||||||
textures:
|
textures:
|
||||||
- id: 18
|
- id: 18
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_fabric_green_diff.tga
|
path: textures/sponza_fabric_green_diff.tga
|
||||||
- vao: 10
|
- vao: 19
|
||||||
indexCount: 17628
|
indexCount: 17628
|
||||||
textures:
|
textures:
|
||||||
- id: 9
|
- id: 9
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_ceiling_a_diff.tga
|
path: textures/sponza_ceiling_a_diff.tga
|
||||||
- vao: 11
|
- vao: 21
|
||||||
indexCount: 30504
|
indexCount: 30504
|
||||||
textures:
|
textures:
|
||||||
- id: 7
|
- id: 7
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_arch_diff.tga
|
path: textures/sponza_arch_diff.tga
|
||||||
- vao: 12
|
- vao: 23
|
||||||
indexCount: 53064
|
indexCount: 53064
|
||||||
textures:
|
textures:
|
||||||
- id: 27
|
- id: 27
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/vase_round.tga
|
path: textures/vase_round.tga
|
||||||
- vao: 13
|
- vao: 25
|
||||||
indexCount: 69624
|
indexCount: 69624
|
||||||
textures:
|
textures:
|
||||||
- id: 12
|
- id: 12
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_column_b_diff.tga
|
path: textures/sponza_column_b_diff.tga
|
||||||
- vao: 14
|
- vao: 27
|
||||||
indexCount: 2640
|
indexCount: 2640
|
||||||
textures:
|
textures:
|
||||||
- id: 14
|
- id: 14
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_details_diff.tga
|
path: textures/sponza_details_diff.tga
|
||||||
- vao: 15
|
- vao: 29
|
||||||
indexCount: 43008
|
indexCount: 43008
|
||||||
textures:
|
textures:
|
||||||
- id: 20
|
- id: 20
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_curtain_blue_diff.tga
|
path: textures/sponza_curtain_blue_diff.tga
|
||||||
- vao: 16
|
- vao: 31
|
||||||
indexCount: 0
|
indexCount: 0
|
||||||
textures: ~
|
textures: ~
|
||||||
- vao: 17
|
- vao: 33
|
||||||
indexCount: 2388
|
indexCount: 2388
|
||||||
textures:
|
textures:
|
||||||
- id: 8
|
- id: 8
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/spnza_bricks_a_diff.tga
|
path: textures/spnza_bricks_a_diff.tga
|
||||||
- vao: 18
|
- vao: 35
|
||||||
indexCount: 21264
|
indexCount: 21264
|
||||||
textures:
|
textures:
|
||||||
- id: 13
|
- id: 13
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_column_c_diff.tga
|
path: textures/sponza_column_c_diff.tga
|
||||||
- vao: 19
|
- vao: 37
|
||||||
indexCount: 63
|
indexCount: 63
|
||||||
textures:
|
textures:
|
||||||
- id: 22
|
- id: 22
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_floor_a_diff.tga
|
path: textures/sponza_floor_a_diff.tga
|
||||||
- vao: 20
|
- vao: 39
|
||||||
indexCount: 43008
|
indexCount: 43008
|
||||||
textures:
|
textures:
|
||||||
- id: 19
|
- id: 19
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_curtain_green_diff.tga
|
path: textures/sponza_curtain_green_diff.tga
|
||||||
- vao: 21
|
- vao: 41
|
||||||
indexCount: 9126
|
indexCount: 9126
|
||||||
textures:
|
textures:
|
||||||
- id: 4
|
- id: 4
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/lion.tga
|
path: textures/lion.tga
|
||||||
- vao: 22
|
- vao: 43
|
||||||
indexCount: 96
|
indexCount: 96
|
||||||
textures:
|
textures:
|
||||||
- id: 10
|
- id: 10
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/chain_texture.tga
|
path: textures/chain_texture.tga
|
||||||
- vao: 23
|
- vao: 45
|
||||||
indexCount: 56832
|
indexCount: 56832
|
||||||
textures:
|
textures:
|
||||||
- id: 16
|
- id: 16
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_curtain_diff.tga
|
path: textures/sponza_curtain_diff.tga
|
||||||
- vao: 24
|
- vao: 47
|
||||||
indexCount: 8448
|
indexCount: 8448
|
||||||
textures:
|
textures:
|
||||||
- id: 11
|
- id: 11
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_column_a_diff.tga
|
path: textures/sponza_column_a_diff.tga
|
||||||
- vao: 25
|
- vao: 49
|
||||||
indexCount: 49488
|
indexCount: 49488
|
||||||
textures:
|
textures:
|
||||||
- id: 21
|
- id: 21
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/sponza_flagpole_diff.tga
|
path: textures/sponza_flagpole_diff.tga
|
||||||
- vao: 26
|
- vao: 51
|
||||||
indexCount: 59484
|
indexCount: 59484
|
||||||
textures:
|
textures:
|
||||||
- id: 26
|
- id: 26
|
||||||
type: texture_diffuse
|
type: texture_diffuse
|
||||||
path: textures/vase_hanging.tga
|
path: textures/vase_hanging.tga
|
||||||
Transform:
|
|
||||||
Position: [0, 300, 0]
|
|
||||||
Rotation: [0, 0, 0]
|
|
||||||
Scale: [1, 1, 1]
|
|
||||||
- ID: 1
|
- ID: 1
|
||||||
Name: Camera
|
Name: Camera
|
||||||
Components:
|
Components:
|
||||||
|
ScriptComponent:
|
||||||
|
ScriptPath: assets/scripts/camera.lua
|
||||||
|
Transform:
|
||||||
|
Position: [881.214233, 200, -162.832016]
|
||||||
|
Rotation: [0, 170.205078, 0]
|
||||||
|
Scale: [1, 1, 1]
|
||||||
CameraComponent:
|
CameraComponent:
|
||||||
IsPerspective: true
|
IsPerspective: true
|
||||||
DefaultRuntimeCamera: true
|
DefaultRuntimeCamera: true
|
||||||
FOV: 45
|
FOV: 45
|
||||||
AspectRatio: 1
|
AspectRatio: 1.75
|
||||||
NearPlane: 0.100000001
|
NearPlane: 0.100000001
|
||||||
FarPlane: 7000
|
FarPlane: 7000
|
||||||
ScriptComponent:
|
- ID: 2
|
||||||
ScriptPath: assets/scripts/camera.lua
|
Name: Grey Cube
|
||||||
|
Components:
|
||||||
|
Mesh:
|
||||||
|
MeshPath: assets/models/DefaultMesh.obj
|
||||||
|
submeshes_len: 1
|
||||||
|
submeshes:
|
||||||
|
- vao: 53
|
||||||
|
indexCount: 36
|
||||||
|
textures: ~
|
||||||
Transform:
|
Transform:
|
||||||
Position: [0, 200, 0]
|
Position: [-3.43110847, 248.891235, 0]
|
||||||
Rotation: [0, 267.034973, 0]
|
Rotation: [0, -0, 0]
|
||||||
Scale: [1, 1, 1]
|
Scale: [25, 25, 25]
|
@ -1,88 +0,0 @@
|
|||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TransformComponent::Update(float _deltaTime)
|
|
||||||
{
|
|
||||||
(void)_deltaTime; // Suppress unused parameter warning
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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]);
|
|
||||||
}
|
|
||||||
}
|
|
@ -140,7 +140,7 @@ void MeshComponent::Deserialize(const YAML::Node &node)
|
|||||||
|
|
||||||
if (submeshes_len != static_cast<int>(model->submeshes.size()))
|
if (submeshes_len != static_cast<int>(model->submeshes.size()))
|
||||||
{
|
{
|
||||||
g_LoggerWindow->AddLog("[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size()));
|
g_LoggerWindow->AddLog(LogLevel::Error, "[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size()));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assign submeshes
|
// Assign submeshes
|
||||||
@ -182,7 +182,7 @@ void MeshComponent::Deserialize(const YAML::Node &node)
|
|||||||
}
|
}
|
||||||
if (submeshes_len != static_cast<int>(submeshes.size()))
|
if (submeshes_len != static_cast<int>(submeshes.size()))
|
||||||
{
|
{
|
||||||
g_LoggerWindow->AddLog("[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size()));
|
g_LoggerWindow->AddLog(LogLevel::Error,"[Mesh] Size Mismatch [%d:%d]: Check for Curupted Scene Files", submeshes_len, static_cast<int>(submeshes.size()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
155
src/Components/Transform.cpp
Normal file
155
src/Components/Transform.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
// TransformComponent.cpp
|
||||||
|
#include "Transform.h"
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
#include <glm/gtc/quaternion.hpp>
|
||||||
|
#include <glm/gtx/quaternion.hpp>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformComponent::Update(float _deltaTime)
|
||||||
|
{
|
||||||
|
(void)_deltaTime; // Suppress unused parameter warning
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformComponent::LookAt(const glm::vec3& target, const glm::vec3& up) {
|
||||||
|
// Calculate the direction vector from position to target
|
||||||
|
glm::vec3 direction = glm::normalize(target - position);
|
||||||
|
|
||||||
|
// Handle the case when direction is parallel to up vector
|
||||||
|
if (glm::length(direction) == 0.0f) {
|
||||||
|
// Cannot look at the same position; no rotation needed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a lookAt matrix
|
||||||
|
glm::mat4 lookAtMatrix = glm::lookAt(position, target, up);
|
||||||
|
|
||||||
|
// Extract the rotation part of the matrix
|
||||||
|
glm::mat4 rotationMatrix = glm::mat4(glm::mat3(lookAtMatrix));
|
||||||
|
|
||||||
|
// Convert the rotation matrix to a quaternion
|
||||||
|
glm::quat rotationQuat = glm::quat_cast(rotationMatrix);
|
||||||
|
|
||||||
|
// Extract Euler angles from the quaternion
|
||||||
|
glm::vec3 eulerRadians = glm::eulerAngles(rotationQuat);
|
||||||
|
|
||||||
|
// Convert radians to degrees and set the rotation
|
||||||
|
rotation = glm::degrees(eulerRadians);
|
||||||
|
}
|
||||||
|
|
||||||
|
// New Methods
|
||||||
|
glm::mat4 TransformComponent::GetTransformMatrix() const
|
||||||
|
{
|
||||||
|
glm::mat4 translation = glm::translate(glm::mat4(1.0f), position);
|
||||||
|
|
||||||
|
// Convert Euler angles (in degrees) to a quaternion and then to a rotation matrix
|
||||||
|
glm::quat quatRotation = glm::quat(glm::radians(rotation));
|
||||||
|
glm::mat4 rotationMatrix = glm::toMat4(quatRotation);
|
||||||
|
|
||||||
|
glm::mat4 scaling = glm::scale(glm::mat4(1.0f), scale);
|
||||||
|
|
||||||
|
// Note: The order is Scale -> Rotate -> Translate
|
||||||
|
return translation * rotationMatrix * scaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransformComponent::SetTransformMatrix(const glm::mat4 &transform)
|
||||||
|
{
|
||||||
|
// Extract translation
|
||||||
|
position = glm::vec3(transform[3]);
|
||||||
|
|
||||||
|
// Extract scale factors
|
||||||
|
scale.x = glm::length(glm::vec3(transform[0]));
|
||||||
|
scale.y = glm::length(glm::vec3(transform[1]));
|
||||||
|
scale.z = glm::length(glm::vec3(transform[2]));
|
||||||
|
|
||||||
|
// Remove scale from rotation matrix
|
||||||
|
glm::mat4 rotationMatrix = transform;
|
||||||
|
rotationMatrix[0] /= scale.x;
|
||||||
|
rotationMatrix[1] /= scale.y;
|
||||||
|
rotationMatrix[2] /= scale.z;
|
||||||
|
|
||||||
|
// Convert rotation matrix to quaternion and then to Euler angles (in degrees)
|
||||||
|
glm::quat quatRotation = glm::quat_cast(rotationMatrix);
|
||||||
|
glm::vec3 euler = glm::degrees(glm::eulerAngles(quatRotation));
|
||||||
|
rotation = euler;
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,23 @@
|
|||||||
// Transform.h
|
// Transform.h
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#define GLM_ENABLE_EXPERIMENTAL
|
||||||
#include "Component.h"
|
#include "Component.h"
|
||||||
#include <glm/glm.hpp>
|
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <glm/gtc/matrix_transform.hpp> // For glm::lookAt
|
||||||
|
#include <glm/gtc/quaternion.hpp> // For glm::quat
|
||||||
|
#include <glm/gtx/quaternion.hpp> // For glm::quat_cast
|
||||||
|
#include <glm/gtc/constants.hpp> // For glm::pi
|
||||||
|
#include <glm/gtc/matrix_access.hpp> // For glm::eulerAngles
|
||||||
|
|
||||||
|
|
||||||
class TransformComponent : public Component
|
class TransformComponent : public Component
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
glm::vec3 position;
|
glm::vec3 position;
|
||||||
glm::vec3 rotation;
|
glm::vec3 rotation;
|
||||||
glm::vec3 scale;
|
glm::vec3 scale;
|
||||||
|
|
||||||
glm::vec3 GetPosition() const
|
glm::vec3 GetPosition() const
|
||||||
@ -32,6 +40,14 @@ public:
|
|||||||
rotation = {x, y, z};
|
rotation = {x, y, z};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Orients the transform to face the target position.
|
||||||
|
*
|
||||||
|
* @param target The target position to look at.
|
||||||
|
* @param up The up vector to use for orientation.
|
||||||
|
*/
|
||||||
|
void LookAt(const glm::vec3& target, const glm::vec3& up);
|
||||||
|
|
||||||
TransformComponent();
|
TransformComponent();
|
||||||
virtual const std::string &GetName() const override;
|
virtual const std::string &GetName() const override;
|
||||||
static const std::string &GetStaticName();
|
static const std::string &GetStaticName();
|
||||||
@ -41,6 +57,8 @@ public:
|
|||||||
// Serialization methods
|
// Serialization methods
|
||||||
virtual YAML::Node Serialize() override;
|
virtual YAML::Node Serialize() override;
|
||||||
virtual void Deserialize(const YAML::Node &node) override;
|
virtual void Deserialize(const YAML::Node &node) override;
|
||||||
|
glm::mat4 GetTransformMatrix() const;
|
||||||
|
void SetTransformMatrix(const glm::mat4& transform);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const std::string name;
|
static const std::string name;
|
@ -36,11 +36,11 @@
|
|||||||
#include "Engine/InputManager.h"
|
#include "Engine/InputManager.h"
|
||||||
#include "Engine/ScopedTimer.h"
|
#include "Engine/ScopedTimer.h"
|
||||||
#include "Engine/Profiler.h"
|
#include "Engine/Profiler.h"
|
||||||
|
#include "Engine/Settings.h"
|
||||||
|
|
||||||
// #define YAML_CPP_STATIC_DEFINE
|
// #define YAML_CPP_STATIC_DEFINE
|
||||||
#include <yaml-cpp/yaml.h>
|
#include <yaml-cpp/yaml.h>
|
||||||
|
|
||||||
#include "TestModel.h"
|
|
||||||
|
|
||||||
AssetManager g_AssetManager;
|
AssetManager g_AssetManager;
|
||||||
|
|
||||||
@ -50,12 +50,16 @@ SceneManager g_SceneManager;
|
|||||||
|
|
||||||
InputManager g_InputManager;
|
InputManager g_InputManager;
|
||||||
|
|
||||||
|
Settings g_SettingsManager;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<GameObject>> g_GameObjects;
|
std::vector<std::shared_ptr<GameObject>> g_GameObjects;
|
||||||
|
|
||||||
std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
|
std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
|
||||||
|
|
||||||
int g_GPU_Triangles_drawn_to_screen = 0;
|
int g_GPU_Triangles_drawn_to_screen = 0;
|
||||||
|
int g_GPU_Draw_Calls = 0;
|
||||||
|
|
||||||
|
bool DrawBBBO;
|
||||||
|
|
||||||
GameObject *g_SelectedObject; // Pointer to the currently selected object
|
GameObject *g_SelectedObject; // Pointer to the currently selected object
|
||||||
|
|
||||||
@ -64,6 +68,10 @@ int m_GameRunning = 0;
|
|||||||
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");
|
||||||
|
|
||||||
|
g_SettingsManager.S_LineColor = glm::vec4(1.0f, 0.27058823529f, 0.0f, 1.0f);
|
||||||
|
|
||||||
|
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
// 1) Initialize GLFW
|
// 1) Initialize GLFW
|
||||||
// ------------------------------------------
|
// ------------------------------------------
|
||||||
@ -110,6 +118,7 @@ bool MyEngine::Init(int width, int height, const std::string &title)
|
|||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable;
|
ImGui::GetIO().ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_ViewportsEnable;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Path to your font files
|
// Path to your font files
|
||||||
@ -169,18 +178,24 @@ bool MyEngine::Init(int width, int height, const std::string &title)
|
|||||||
m_FirstTickGameRunning = true;
|
m_FirstTickGameRunning = true;
|
||||||
m_showProfiler = true;
|
m_showProfiler = true;
|
||||||
|
|
||||||
|
DrawBBBO = false;
|
||||||
|
|
||||||
g_LoggerWindow = m_LoggerWindow.get();
|
g_LoggerWindow = m_LoggerWindow.get();
|
||||||
|
|
||||||
// Optionally, call 'onInit' Lua function
|
// Optionally, call 'onInit' Lua function
|
||||||
|
|
||||||
// Some initial logs
|
// Some initial logs
|
||||||
m_LoggerWindow->AddLog("Engine initialized.");
|
|
||||||
m_LoggerWindow->AddLog("Welcome to Tesseract Engine!");
|
m_LoggerWindow->AddLog("Welcome to Tesseract Engine!");
|
||||||
|
|
||||||
m_Running = true;
|
m_Running = true;
|
||||||
m_LastTime = glfwGetTime();
|
m_LastTime = glfwGetTime();
|
||||||
DEBUG_PRINT("[OK] Engine Init ");
|
DEBUG_PRINT("[OK] Engine Init ");
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
g_LoggerWindow->AddLog(LogLevel::Warning, "Warning: You are in Debug Mode. Switch to Releace for more performance");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -205,8 +220,6 @@ void MyEngine::Run()
|
|||||||
glfwPollEvents();
|
glfwPollEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
SCOPE_TIMER("InputManagerUpdate");
|
SCOPE_TIMER("InputManagerUpdate");
|
||||||
g_InputManager.Update(m_Window);
|
g_InputManager.Update(m_Window);
|
||||||
@ -291,7 +304,7 @@ void MyEngine::Run()
|
|||||||
{
|
{
|
||||||
ScopedTimer timer("RenderGame");
|
ScopedTimer timer("RenderGame");
|
||||||
|
|
||||||
m_RenderWindow->Show(&m_GameRunning); // The spinning triangle as ImGui::Image
|
m_RenderWindow->Show(&m_GameRunning, m_Ms); // The spinning triangle as ImGui::Image
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
ScopedTimer timer("ShowEditor");
|
ScopedTimer timer("ShowEditor");
|
||||||
@ -309,7 +322,7 @@ void MyEngine::Run()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// After rendering
|
// After rendering
|
||||||
m_PerformanceWindow->UpdatePerformanceStats(-1, g_GPU_Triangles_drawn_to_screen);
|
m_PerformanceWindow->UpdatePerformanceStats(g_GPU_Draw_Calls, g_GPU_Triangles_drawn_to_screen);
|
||||||
|
|
||||||
// End frame
|
// End frame
|
||||||
EndFrame();
|
EndFrame();
|
||||||
@ -431,6 +444,24 @@ void MyEngine::ShowDockSpace()
|
|||||||
ImGui::Checkbox("Show Profiler", &m_showProfiler); // Add a checkbox to toggle the profiler
|
ImGui::Checkbox("Show Profiler", &m_showProfiler); // Add a checkbox to toggle the profiler
|
||||||
ImGui::EndMenu();
|
ImGui::EndMenu();
|
||||||
}
|
}
|
||||||
|
if (ImGui::BeginMenu("Settings"))
|
||||||
|
{
|
||||||
|
// A checkbox to enable/disable bounding boxes
|
||||||
|
ImGui::Checkbox("Show Submeshs", &DrawBBBO);
|
||||||
|
|
||||||
|
// On the same line, we place a small color edit widget
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::ColorEdit4("Box Color",
|
||||||
|
reinterpret_cast<float *>(&g_SettingsManager.S_LineColor),
|
||||||
|
ImGuiColorEditFlags_NoInputs | ImGuiColorEditFlags_NoLabel);
|
||||||
|
|
||||||
|
|
||||||
|
// Explanation of Flags:
|
||||||
|
// - ImGuiColorEditFlags_NoInputs hides numeric RGBA input fields
|
||||||
|
// - ImGuiColorEditFlags_NoLabel hides the default label, since we already have "Box Color"
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Engine"))
|
if (ImGui::BeginMenu("Engine"))
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -12,9 +12,9 @@
|
|||||||
#include "Windows/LuaEditorWindow.h"
|
#include "Windows/LuaEditorWindow.h"
|
||||||
#include "Windows/ProfilerWindow.h"
|
#include "Windows/ProfilerWindow.h"
|
||||||
|
|
||||||
#include "Componenets/GameObject.h"
|
#include "Components/GameObject.h"
|
||||||
#include "Componenets/Mesh.h"
|
#include "Components/Mesh.h"
|
||||||
#include "Componenets/Transform.h"
|
#include "Components/Transform.h"
|
||||||
|
|
||||||
#include "Engine/AssetManager.h"
|
#include "Engine/AssetManager.h"
|
||||||
#include "Engine/ThemeManager.h"
|
#include "Engine/ThemeManager.h"
|
||||||
@ -22,7 +22,6 @@
|
|||||||
#include "Engine/LuaAPI.h"
|
#include "Engine/LuaAPI.h"
|
||||||
#include "Engine/Utilitys.h"
|
#include "Engine/Utilitys.h"
|
||||||
|
|
||||||
#include "TestModel.h"
|
|
||||||
|
|
||||||
#include "gcml.h"
|
#include "gcml.h"
|
||||||
|
|
||||||
|
@ -520,6 +520,7 @@ Model *LoadModelFromList(const std::string &path)
|
|||||||
|
|
||||||
// Initialize OpenGL buffers for the submesh
|
// Initialize OpenGL buffers for the submesh
|
||||||
submesh.Initialize();
|
submesh.Initialize();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (materialToSubmesh.empty())
|
if (materialToSubmesh.empty())
|
||||||
|
@ -82,10 +82,31 @@ struct Submesh
|
|||||||
std::vector<unsigned int> indices;
|
std::vector<unsigned int> indices;
|
||||||
std::vector<Texture> textures;
|
std::vector<Texture> textures;
|
||||||
GLuint vao = 0, vbo = 0, ebo = 0;
|
GLuint vao = 0, vbo = 0, ebo = 0;
|
||||||
|
unsigned int bboxVAO, bboxVBO;
|
||||||
|
GLsizei bboxVertexCount;
|
||||||
|
|
||||||
|
glm::vec3 minExtents;
|
||||||
|
glm::vec3 maxExtents;
|
||||||
|
|
||||||
// Initialize OpenGL buffers for the submesh
|
// Initialize OpenGL buffers for the submesh
|
||||||
void Initialize()
|
void Initialize()
|
||||||
{
|
{
|
||||||
|
glm::vec3 minExtents(FLT_MAX);
|
||||||
|
glm::vec3 maxExtents(-FLT_MAX);
|
||||||
|
for (auto &v : vertices)
|
||||||
|
{
|
||||||
|
minExtents.x = std::min(minExtents.x, v.position[0]);
|
||||||
|
minExtents.y = std::min(minExtents.y, v.position[1]);
|
||||||
|
minExtents.z = std::min(minExtents.z, v.position[2]);
|
||||||
|
|
||||||
|
maxExtents.x = std::max(maxExtents.x, v.position[0]);
|
||||||
|
maxExtents.y = std::max(maxExtents.y, v.position[1]);
|
||||||
|
maxExtents.z = std::max(maxExtents.z, v.position[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store in the submesh
|
||||||
|
this->minExtents = minExtents;
|
||||||
|
this->maxExtents = maxExtents;
|
||||||
glGenVertexArrays(1, &vao);
|
glGenVertexArrays(1, &vao);
|
||||||
glGenBuffers(1, &vbo);
|
glGenBuffers(1, &vbo);
|
||||||
glGenBuffers(1, &ebo);
|
glGenBuffers(1, &ebo);
|
||||||
@ -109,6 +130,58 @@ struct Submesh
|
|||||||
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(5 * sizeof(float)));
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void *)(5 * sizeof(float)));
|
||||||
|
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
std::vector<glm::vec3> bboxLines = {
|
||||||
|
// bottom face
|
||||||
|
{minExtents.x, minExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, minExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, minExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, minExtents.y, maxExtents.z},
|
||||||
|
{maxExtents.x, minExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, minExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, minExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, minExtents.y, minExtents.z},
|
||||||
|
// top face
|
||||||
|
{minExtents.x, maxExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, maxExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, maxExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, maxExtents.y, maxExtents.z},
|
||||||
|
{maxExtents.x, maxExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, maxExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, maxExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, maxExtents.y, minExtents.z},
|
||||||
|
// vertical edges
|
||||||
|
{minExtents.x, minExtents.y, minExtents.z},
|
||||||
|
{minExtents.x, maxExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, minExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, maxExtents.y, minExtents.z},
|
||||||
|
{maxExtents.x, minExtents.y, maxExtents.z},
|
||||||
|
{maxExtents.x, maxExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, minExtents.y, maxExtents.z},
|
||||||
|
{minExtents.x, maxExtents.y, maxExtents.z}};
|
||||||
|
|
||||||
|
glGenVertexArrays(1, &bboxVAO);
|
||||||
|
glGenBuffers(1, &bboxVBO);
|
||||||
|
|
||||||
|
glBindVertexArray(bboxVAO);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, bboxVBO);
|
||||||
|
glBufferData(
|
||||||
|
GL_ARRAY_BUFFER,
|
||||||
|
bboxLines.size() * sizeof(glm::vec3),
|
||||||
|
bboxLines.data(),
|
||||||
|
GL_STATIC_DRAW);
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(
|
||||||
|
0, 3, GL_FLOAT, GL_FALSE,
|
||||||
|
sizeof(glm::vec3), (void *)0);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
|
||||||
|
bboxVAO = bboxVAO;
|
||||||
|
bboxVBO = bboxVBO;
|
||||||
|
bboxVertexCount = (GLsizei)bboxLines.size();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render the submesh
|
// Render the submesh
|
||||||
@ -200,9 +273,9 @@ public:
|
|||||||
// Debug: Log the variant type
|
// Debug: Log the variant type
|
||||||
if (std::holds_alternative<std::shared_ptr<T>>(it->second))
|
if (std::holds_alternative<std::shared_ptr<T>>(it->second))
|
||||||
{
|
{
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
DebugAssetMap();
|
DebugAssetMap();
|
||||||
#endif
|
#endif
|
||||||
std::cout << "[AssetManager] Retrieved asset from cache: " << key << std::endl;
|
std::cout << "[AssetManager] Retrieved asset from cache: " << key << std::endl;
|
||||||
return std::get<std::shared_ptr<T>>(it->second);
|
return std::get<std::shared_ptr<T>>(it->second);
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,92 @@
|
|||||||
// InputManager.cpp
|
// InputManager.cpp
|
||||||
#include "InputManager.h"
|
#include "InputManager.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <algorithm> // For std::clamp
|
||||||
|
|
||||||
|
// Constructor
|
||||||
|
InputManager::InputManager()
|
||||||
void InputManager::Update(GLFWwindow* window)
|
: m_MouseDeltaX(0.0f), m_MouseDeltaY(0.0f), m_ScrollDelta(0.0f)
|
||||||
{
|
{
|
||||||
if (!window)
|
Initialize();
|
||||||
{
|
}
|
||||||
|
|
||||||
|
// Initialize method to set up state vectors
|
||||||
|
void InputManager::Initialize() {
|
||||||
|
// Initialize key states
|
||||||
|
m_KeyStates.resize(GLFW_KEY_LAST + 1, false);
|
||||||
|
m_PreviousKeyStates.resize(GLFW_KEY_LAST + 1, false);
|
||||||
|
|
||||||
|
// Initialize mouse button states
|
||||||
|
m_MouseButtonStates.resize(GLFW_MOUSE_BUTTON_LAST + 1, false);
|
||||||
|
m_PreviousMouseButtonStates.resize(GLFW_MOUSE_BUTTON_LAST + 1, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update method to poll input states
|
||||||
|
void InputManager::Update(GLFWwindow* window) {
|
||||||
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the state of each key
|
// Update previous key states
|
||||||
for (int key = 0; key <= GLFW_KEY_LAST; ++key)
|
m_PreviousKeyStates = m_KeyStates;
|
||||||
{
|
|
||||||
|
// Update current key states
|
||||||
|
for (int key = 0; key <= GLFW_KEY_LAST; ++key) {
|
||||||
m_KeyStates[key] = glfwGetKey(window, key) == GLFW_PRESS;
|
m_KeyStates[key] = glfwGetKey(window, key) == GLFW_PRESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update previous mouse button states
|
||||||
|
m_PreviousMouseButtonStates = m_MouseButtonStates;
|
||||||
|
|
||||||
|
// Update current mouse button states
|
||||||
|
for (int button = 0; button <= GLFW_MOUSE_BUTTON_LAST; ++button) {
|
||||||
|
m_MouseButtonStates[button] = glfwGetMouseButton(window, button) == GLFW_PRESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset mouse deltas and scroll delta for this frame
|
||||||
|
m_MouseDeltaX = 0.0f;
|
||||||
|
m_MouseDeltaY = 0.0f;
|
||||||
|
m_ScrollDelta = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InputManager::IsKeyPressed(KeyCode key) const
|
// Keyboard input query
|
||||||
{
|
bool InputManager::IsKeyPressed(KeyCode key) const {
|
||||||
int keyInt = static_cast<int>(key);
|
int keyInt = static_cast<int>(key);
|
||||||
if (keyInt >= 0 && keyInt <= GLFW_KEY_LAST)
|
if (keyInt >= 0 && keyInt <= GLFW_KEY_LAST) {
|
||||||
{
|
|
||||||
return m_KeyStates[keyInt];
|
return m_KeyStates[keyInt];
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mouse button input query
|
||||||
|
bool InputManager::IsMouseButtonPressed(MouseButton button) const {
|
||||||
|
int buttonInt = static_cast<int>(button);
|
||||||
|
if (buttonInt >= 0 && buttonInt <= GLFW_MOUSE_BUTTON_LAST) {
|
||||||
|
return m_MouseButtonStates[buttonInt];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse button just pressed (edge detection)
|
||||||
|
bool InputManager::IsMouseButtonJustPressed(MouseButton button) const {
|
||||||
|
int buttonInt = static_cast<int>(button);
|
||||||
|
if (buttonInt >= 0 && buttonInt <= GLFW_MOUSE_BUTTON_LAST) {
|
||||||
|
return m_MouseButtonStates[buttonInt] && !m_PreviousMouseButtonStates[buttonInt];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mouse button just released (edge detection)
|
||||||
|
bool InputManager::IsMouseButtonJustReleased(MouseButton button) const {
|
||||||
|
int buttonInt = static_cast<int>(button);
|
||||||
|
if (buttonInt >= 0 && buttonInt <= GLFW_MOUSE_BUTTON_LAST) {
|
||||||
|
return !m_MouseButtonStates[buttonInt] && m_PreviousMouseButtonStates[buttonInt];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset deltas after handling input
|
||||||
|
void InputManager::ResetDeltas() {
|
||||||
|
m_MouseDeltaX = 0.0f;
|
||||||
|
m_MouseDeltaY = 0.0f;
|
||||||
|
m_ScrollDelta = 0.0f;
|
||||||
|
}
|
||||||
|
@ -3,18 +3,50 @@
|
|||||||
|
|
||||||
#include "KeyCode.h"
|
#include "KeyCode.h"
|
||||||
#include <GLFW/glfw3.h>
|
#include <GLFW/glfw3.h>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class InputManager {
|
||||||
class InputManager
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
// Update key states (to be called every frame)
|
// Constructor
|
||||||
|
InputManager();
|
||||||
|
|
||||||
|
// Update method to poll input states
|
||||||
void Update(GLFWwindow* window);
|
void Update(GLFWwindow* window);
|
||||||
|
|
||||||
// Check if a key is pressed
|
// Keyboard input query
|
||||||
bool IsKeyPressed(KeyCode key) const;
|
bool IsKeyPressed(KeyCode key) const;
|
||||||
|
|
||||||
|
// Mouse button input queries
|
||||||
|
bool IsMouseButtonPressed(MouseButton button) const;
|
||||||
|
bool IsMouseButtonJustPressed(MouseButton button) const;
|
||||||
|
bool IsMouseButtonJustReleased(MouseButton button) const;
|
||||||
|
|
||||||
|
// Mouse movement deltas
|
||||||
|
float GetMouseDeltaX() const { return m_MouseDeltaX; }
|
||||||
|
float GetMouseDeltaY() const { return m_MouseDeltaY; }
|
||||||
|
|
||||||
|
// Scroll delta
|
||||||
|
float GetScrollDelta() const { return m_ScrollDelta; }
|
||||||
|
|
||||||
|
// Call this after handling input to reset deltas
|
||||||
|
void ResetDeltas();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Array or map storing key states
|
// Storage for key states
|
||||||
bool m_KeyStates[GLFW_KEY_LAST + 1] = { false };
|
std::vector<bool> m_KeyStates;
|
||||||
};
|
std::vector<bool> m_PreviousKeyStates;
|
||||||
|
|
||||||
|
// Storage for mouse button states
|
||||||
|
std::vector<bool> m_MouseButtonStates;
|
||||||
|
std::vector<bool> m_PreviousMouseButtonStates;
|
||||||
|
|
||||||
|
// Mouse movement deltas
|
||||||
|
float m_MouseDeltaX;
|
||||||
|
float m_MouseDeltaY;
|
||||||
|
|
||||||
|
// Scroll delta
|
||||||
|
float m_ScrollDelta;
|
||||||
|
|
||||||
|
// Initialization helper
|
||||||
|
void Initialize();
|
||||||
|
};
|
@ -126,3 +126,16 @@ enum class KeyCode
|
|||||||
RightSuper = GLFW_KEY_RIGHT_SUPER,
|
RightSuper = GLFW_KEY_RIGHT_SUPER,
|
||||||
Menu = GLFW_KEY_MENU
|
Menu = GLFW_KEY_MENU
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Enum for mouse buttons
|
||||||
|
enum class MouseButton {
|
||||||
|
LEFT = GLFW_MOUSE_BUTTON_LEFT,
|
||||||
|
RIGHT = GLFW_MOUSE_BUTTON_RIGHT,
|
||||||
|
MIDDLE = GLFW_MOUSE_BUTTON_MIDDLE,
|
||||||
|
BUTTON4 = GLFW_MOUSE_BUTTON_4,
|
||||||
|
BUTTON5 = GLFW_MOUSE_BUTTON_5,
|
||||||
|
BUTTON6 = GLFW_MOUSE_BUTTON_6,
|
||||||
|
BUTTON7 = GLFW_MOUSE_BUTTON_7,
|
||||||
|
BUTTON8 = GLFW_MOUSE_BUTTON_8,
|
||||||
|
LAST = GLFW_MOUSE_BUTTON_LAST
|
||||||
|
};
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
#include "LuaAPI.h"
|
#include "LuaAPI.h"
|
||||||
#include "LuaMacros.h" // Include the macros for binding
|
#include "LuaMacros.h" // Include the macros for binding
|
||||||
#include "gcml.h" // Include gcml.h for DEBUG_PRINT macros
|
#include "gcml.h" // Include gcml.h for DEBUG_PRINT macros
|
||||||
#include "Componenets/Component.h"
|
#include "Components/Component.h"
|
||||||
#include "Componenets/Transform.h"
|
#include "Components/Transform.h"
|
||||||
#include "Componenets/Mesh.h"
|
#include "Components/Mesh.h"
|
||||||
#include "Componenets/ScriptComponent.h"
|
#include "Components/ScriptComponent.h"
|
||||||
#include "Componenets/GameObject.h"
|
#include "Components/GameObject.h"
|
||||||
#include "Windows/LoggerWindow.h"
|
#include "Windows/LoggerWindow.h"
|
||||||
#include "Engine/InputManager.h"
|
#include "Engine/InputManager.h"
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ struct ProfileResult {
|
|||||||
|
|
||||||
class Profiler {
|
class Profiler {
|
||||||
public:
|
public:
|
||||||
static Profiler& Get() {
|
static Profiler& Get() { // Singleton ... LLLLLL
|
||||||
static Profiler instance;
|
static Profiler instance;
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
#include "SceneManager.h"
|
#include "SceneManager.h"
|
||||||
|
|
||||||
#include "./Componenets/Component.h"
|
#include "./Components/Component.h"
|
||||||
#include "./Componenets/Transform.h"
|
#include "./Components/Transform.h"
|
||||||
#include "./Componenets/Mesh.h"
|
#include "./Components/Mesh.h"
|
||||||
#include "./Componenets/GameObject.h"
|
#include "./Components/GameObject.h"
|
||||||
|
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "Componenets/GameObject.h"
|
#include "Components/GameObject.h"
|
||||||
|
|
||||||
|
|
||||||
class SceneManager
|
class SceneManager
|
||||||
|
6
src/Engine/Settings.h
Normal file
6
src/Engine/Settings.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "imgui.h"
|
||||||
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
||||||
|
struct Settings {
|
||||||
|
glm::vec4 S_LineColor;
|
||||||
|
};
|
@ -152,6 +152,12 @@ void Shader::SetVec3(const std::string &name, const glm::vec3 &value) const
|
|||||||
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
|
glUniform3fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Shader::SetVec4(const std::string &name, const glm::vec4 &value) const
|
||||||
|
{
|
||||||
|
glUseProgram(ID); // Ensure the shader program is active
|
||||||
|
glUniform4fv(glGetUniformLocation(ID, name.c_str()), 1, &value[0]);
|
||||||
|
}
|
||||||
void Shader::SetSampler2D(const std::string &name, int textureUnit) const
|
void Shader::SetSampler2D(const std::string &name, int textureUnit) const
|
||||||
{
|
{
|
||||||
glUseProgram(ID); // Ensure the shader program is active
|
glUseProgram(ID); // Ensure the shader program is active
|
||||||
|
@ -26,6 +26,8 @@ public:
|
|||||||
void SetMat4(const std::string &name, const glm::mat4 &mat) const; // For setting 4x4 matrices
|
void SetMat4(const std::string &name, const glm::mat4 &mat) const; // For setting 4x4 matrices
|
||||||
void SetSampler2D(const std::string &name, int textureUnit) const;
|
void SetSampler2D(const std::string &name, int textureUnit) const;
|
||||||
void SetVec3(const std::string &name, const glm::vec3 &value) const;
|
void SetVec3(const std::string &name, const glm::vec3 &value) const;
|
||||||
|
void SetVec4(const std::string &name, const glm::vec4 &value) const;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Caching uniform locations for performance
|
// Caching uniform locations for performance
|
||||||
|
@ -1,103 +0,0 @@
|
|||||||
#include "TestModel.h"
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
#pragma once //
|
|
||||||
#include <GL/glew.h>
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
|
|
||||||
GLuint CreateCubeVAO();
|
|
@ -5,11 +5,11 @@
|
|||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include "gcml.h"
|
#include "gcml.h"
|
||||||
|
|
||||||
#include "Componenets/GameObject.h"
|
#include "Components/GameObject.h"
|
||||||
#include "Componenets/Mesh.h"
|
#include "Components/Mesh.h"
|
||||||
#include "Componenets/Transform.h"
|
#include "Components/Transform.h"
|
||||||
#include "Componenets/ScriptComponent.h"
|
#include "Components/ScriptComponent.h"
|
||||||
#include "Componenets/CameraComponent.h"
|
#include "Components/CameraComponent.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include "Icons.h"
|
#include "Icons.h"
|
||||||
#include "Engine/ScopedTimer.h"
|
#include "Engine/ScopedTimer.h"
|
||||||
|
#include "Icons.h"
|
||||||
|
|
||||||
|
|
||||||
// Helper function to format strings
|
|
||||||
static std::string FormatString(const char *fmt, va_list args)
|
static std::string FormatString(const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
char buffer[1024];
|
char buffer[1024];
|
||||||
@ -15,6 +16,48 @@ static std::string FormatString(const char *fmt, va_list args)
|
|||||||
return std::string(buffer);
|
return std::string(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Choose a default icon for each LogLevel
|
||||||
|
static const char* GetIconForLevel(LogLevel level)
|
||||||
|
{
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case LogLevel::Warning: return ICON_FA_TRIANGLE_EXCLAMATION;
|
||||||
|
case LogLevel::Error: return ICON_FA_CIRCLE_EXCLAMATION;
|
||||||
|
case LogLevel::Info:
|
||||||
|
default: return ICON_FA_INFO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Choose a default color for each LogLevel if none is specified.
|
||||||
|
static ImVec4 GetDefaultColorForLevel(LogLevel level)
|
||||||
|
{
|
||||||
|
switch (level)
|
||||||
|
{
|
||||||
|
case LogLevel::Warning: return ImVec4(1.0f, 0.8f, 0.0f, 1.0f); // Yellow-ish
|
||||||
|
case LogLevel::Error: return ImVec4(1.0f, 0.2f, 0.2f, 1.0f); // Reddish
|
||||||
|
case LogLevel::Info:
|
||||||
|
default: return ImVec4(0.8f, 0.8f, 0.8f, 1.0f); // Light gray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoggerWindow::AddLog(const char *fmt, std::optional<ImVec4> color, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
std::string formatted = FormatString(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
LogEntry entry;
|
||||||
|
entry.text = formatted;
|
||||||
|
entry.level = LogLevel::Info;
|
||||||
|
entry.color = color;
|
||||||
|
entry.icon = GetIconForLevel(entry.level);
|
||||||
|
|
||||||
|
m_Logs.emplace_back(entry);
|
||||||
|
m_ScrollToBottom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1) Existing method (no LogLevel) — default to Info
|
||||||
void LoggerWindow::AddLog(const char *fmt, ...)
|
void LoggerWindow::AddLog(const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
@ -22,27 +65,62 @@ void LoggerWindow::AddLog(const char *fmt, ...)
|
|||||||
std::string formatted = FormatString(fmt, args);
|
std::string formatted = FormatString(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
m_Logs.emplace_back(formatted);
|
LogEntry entry;
|
||||||
|
entry.text = formatted;
|
||||||
|
entry.level = LogLevel::Info;
|
||||||
|
entry.color = std::nullopt; // We'll use the default color
|
||||||
|
entry.icon = GetIconForLevel(entry.level);
|
||||||
|
|
||||||
|
m_Logs.emplace_back(entry);
|
||||||
m_ScrollToBottom = true;
|
m_ScrollToBottom = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LoggerWindow::AddLog(const char *fmt, std::optional<ImVec4> color, ...)
|
// 2) New method for specifying LogLevel
|
||||||
|
void LoggerWindow::AddLog(LogLevel level, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, color);
|
va_start(args, fmt);
|
||||||
std::string formatted = FormatString(fmt, args);
|
std::string formatted = FormatString(fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
m_Logs.emplace_back(formatted, color);
|
LogEntry entry;
|
||||||
|
entry.text = formatted;
|
||||||
|
entry.level = level;
|
||||||
|
entry.color = std::nullopt; // Use default color for this level
|
||||||
|
entry.icon = GetIconForLevel(level);
|
||||||
|
|
||||||
|
m_Logs.emplace_back(entry);
|
||||||
m_ScrollToBottom = true;
|
m_ScrollToBottom = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 3) New method for specifying LogLevel + an explicit color override
|
||||||
|
void LoggerWindow::AddLog(LogLevel level, const ImVec4 &color, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, fmt);
|
||||||
|
std::string formatted = FormatString(fmt, args);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
LogEntry entry;
|
||||||
|
entry.text = formatted;
|
||||||
|
entry.level = level;
|
||||||
|
entry.color = color; // Explicit color override
|
||||||
|
entry.icon = GetIconForLevel(level);
|
||||||
|
|
||||||
|
m_Logs.emplace_back(entry);
|
||||||
|
m_ScrollToBottom = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void LoggerWindow::Show()
|
void LoggerWindow::Show()
|
||||||
{
|
{
|
||||||
SCOPE_TIMER("LoggerWindow::Show");
|
SCOPE_TIMER("LoggerWindow::Show");
|
||||||
|
|
||||||
|
// Window with an icon in the title
|
||||||
ImGui::Begin(ICON_FA_TERMINAL " Logger##logger");
|
ImGui::Begin(ICON_FA_TERMINAL " Logger##logger");
|
||||||
|
|
||||||
|
// Clear button
|
||||||
if (ImGui::Button("Clear"))
|
if (ImGui::Button("Clear"))
|
||||||
{
|
{
|
||||||
m_Logs.clear();
|
m_Logs.clear();
|
||||||
@ -50,24 +128,44 @@ void LoggerWindow::Show()
|
|||||||
|
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
|
|
||||||
// Begin a child region to enable scrolling
|
// Child region for scrollable area
|
||||||
ImGui::BeginChild("LoggerScrollRegion", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
|
ImGui::BeginChild("LoggerScrollRegion", ImVec2(0, 0), false,
|
||||||
|
ImGuiWindowFlags_HorizontalScrollbar);
|
||||||
|
|
||||||
for (const auto &logEntry : m_Logs)
|
if (ImGui::BeginTable("LogTable", 2,
|
||||||
|
ImGuiTableFlags_SizingFixedFit |
|
||||||
|
ImGuiTableFlags_Borders |
|
||||||
|
ImGuiTableFlags_RowBg |
|
||||||
|
ImGuiTableFlags_Resizable))
|
||||||
{
|
{
|
||||||
if (logEntry.color.has_value())
|
// Optionally set up columns (width, name, etc.)
|
||||||
{
|
ImGui::TableSetupColumn("Icon", ImGuiTableColumnFlags_WidthFixed, 30.0f);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, logEntry.color.value());
|
ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_WidthStretch);
|
||||||
ImGui::TextUnformatted(logEntry.text.c_str());
|
|
||||||
ImGui::PopStyleColor();
|
// Loop over log entries
|
||||||
}
|
for (const auto &logEntry : m_Logs)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
|
ImVec4 color = logEntry.color.value_or(GetDefaultColorForLevel(logEntry.level));
|
||||||
|
|
||||||
|
// Start a new row
|
||||||
|
ImGui::TableNextRow();
|
||||||
|
|
||||||
|
// Column 0: Icon
|
||||||
|
ImGui::TableNextColumn();
|
||||||
|
ImGui::TextColored(color, "%s", logEntry.icon.c_str());
|
||||||
|
|
||||||
|
// Column 1: Text
|
||||||
|
ImGui::TableNextColumn();
|
||||||
ImGui::TextUnformatted(logEntry.text.c_str());
|
ImGui::TextUnformatted(logEntry.text.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImGui::EndTable();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auto-scroll to bottom if new logs are added
|
// If you used PushStyleVar above, pop it here:
|
||||||
|
// ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
// Auto-scroll to bottom if needed
|
||||||
if (m_ScrollToBottom)
|
if (m_ScrollToBottom)
|
||||||
{
|
{
|
||||||
ImGui::SetScrollHereY(1.0f);
|
ImGui::SetScrollHereY(1.0f);
|
||||||
@ -75,6 +173,6 @@ void LoggerWindow::Show()
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImGui::EndChild();
|
ImGui::EndChild();
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,19 +6,31 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
|
#include "Icons.h"
|
||||||
|
|
||||||
struct LogEntry {
|
// Example: Different severity levels
|
||||||
std::string text;
|
enum class LogLevel
|
||||||
std::optional<ImVec4> color;
|
{
|
||||||
|
Info,
|
||||||
|
Warning,
|
||||||
|
Error
|
||||||
|
};
|
||||||
|
|
||||||
LogEntry(const std::string& msg, std::optional<ImVec4> col = std::nullopt)
|
struct LogEntry
|
||||||
: text(msg), color(col) {}
|
{
|
||||||
|
std::string text ;
|
||||||
|
LogLevel level;
|
||||||
|
std::optional<ImVec4> color;
|
||||||
|
std::string icon ;
|
||||||
};
|
};
|
||||||
|
|
||||||
class LoggerWindow {
|
class LoggerWindow {
|
||||||
public:
|
public:
|
||||||
void AddLog(const char* fmt, ...);
|
void AddLog(const char* fmt, ...);
|
||||||
void AddLog(const char* fmt, std::optional<ImVec4> color, ...);
|
void AddLog(const char* fmt, std::optional<ImVec4> color, ...);
|
||||||
|
void AddLog(LogLevel level, const char *fmt, ...);
|
||||||
|
void AddLog(LogLevel level, const ImVec4 &color, const char *fmt, ...);
|
||||||
|
|
||||||
void Show();
|
void Show();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -1,52 +1,54 @@
|
|||||||
#include "PerformanceWindow.h"
|
#include "PerformanceWindow.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
#include <algorithm> // for std::max_element, etc.
|
#include <algorithm> // for std::max
|
||||||
|
#include <float.h> // for FLT_MAX
|
||||||
#include "Engine/ThemeManager.h"
|
#include "Engine/ThemeManager.h"
|
||||||
#include "Engine/ScopedTimer.h"
|
#include "Engine/ScopedTimer.h"
|
||||||
|
|
||||||
extern int LoadedAssets;
|
extern int LoadedAssets;
|
||||||
extern int g_GPU_Triangles_drawn_to_screen;
|
extern int g_GPU_Triangles_drawn_to_screen;
|
||||||
|
extern int g_GPU_Draw_Calls;
|
||||||
|
|
||||||
const char *polygonModeOptions[] = {"Fill", "Wireframe", "Points"};
|
const char *polygonModeOptions[] = {"Fill", "Wireframe", "Points"};
|
||||||
const int numPolygonModes = sizeof(polygonModeOptions) / sizeof(polygonModeOptions[0]);
|
static int polygonMode = 0;
|
||||||
|
|
||||||
int polygonMode = 0;
|
|
||||||
|
|
||||||
// Initialize static members
|
// Initialize static members
|
||||||
int PerformanceWindow::m_OpenGLCallCount = 0;
|
int PerformanceWindow::m_OpenGLCallCount = 0;
|
||||||
int PerformanceWindow::m_TriangleCount = 0;
|
int PerformanceWindow::m_TriangleCount = 0;
|
||||||
|
|
||||||
// We'll store up to 60 data points for each stat.
|
// We'll store up to 60 data points for each stat.
|
||||||
static float s_FpsHistory[60] = {0.0f};
|
static float s_FpsHistory[60] = {0.0f};
|
||||||
static float s_MsHistory[60] = {0.0f};
|
static float s_MsHistory[60] = {0.0f};
|
||||||
static float s_CallsHistory[60] = {0.0f};
|
static float s_CallsHistory[60] = {0.0f};
|
||||||
static float s_TriangleHistory[60] = {0.0f};
|
static float s_TriangleHistory[60] = {0.0f};
|
||||||
|
|
||||||
// Current dynamic max scale for FPS and ms
|
// Current dynamic max scale for FPS and ms
|
||||||
static float s_FpsScale = 120.0f; // default starting scale for FPS
|
static float s_FpsScale = 120.0f; // default starting scale for FPS
|
||||||
static float s_MsScale = 25.0f; // default starting scale for ms
|
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.
|
// Push new value into history, shifting old values left
|
||||||
static void PushValueToHistory(float *historyArray, int historySize, float newValue)
|
static void PushValueToHistory(float* historyArray, int historySize, float newValue)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < historySize - 1; i++)
|
for (int i = 0; i < historySize - 1; i++)
|
||||||
|
{
|
||||||
historyArray[i] = historyArray[i + 1];
|
historyArray[i] = historyArray[i + 1];
|
||||||
|
}
|
||||||
historyArray[historySize - 1] = newValue;
|
historyArray[historySize - 1] = newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll track when we last pushed data to our history.
|
// We'll track when we last pushed data to our history.
|
||||||
static double s_LastPushTime = 0.0;
|
static double s_LastPushTime = 0.0;
|
||||||
|
|
||||||
// We'll also track when we last updated the scale
|
// We'll also track when we last updated the scale
|
||||||
static double s_LastScaleUpdate = 0.0;
|
static double s_LastScaleUpdate = 0.0;
|
||||||
|
|
||||||
// Update counters from the outside
|
|
||||||
void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangleCount)
|
void PerformanceWindow::UpdatePerformanceStats(int newCallCount, int newTriangleCount)
|
||||||
{
|
{
|
||||||
m_OpenGLCallCount = newCallCount;
|
m_OpenGLCallCount = newCallCount;
|
||||||
m_TriangleCount = newTriangleCount;
|
m_TriangleCount = newTriangleCount;
|
||||||
|
|
||||||
|
// Reset GPU counters each frame, or each time you show
|
||||||
g_GPU_Triangles_drawn_to_screen = 0;
|
g_GPU_Triangles_drawn_to_screen = 0;
|
||||||
|
g_GPU_Draw_Calls = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerformanceWindow::Show(float fps, float ms)
|
void PerformanceWindow::Show(float fps, float ms)
|
||||||
@ -56,7 +58,7 @@ void PerformanceWindow::Show(float fps, float ms)
|
|||||||
// 1) Get current time from ImGui's internal clock
|
// 1) Get current time from ImGui's internal clock
|
||||||
double currentTime = ImGui::GetTime();
|
double currentTime = ImGui::GetTime();
|
||||||
|
|
||||||
// 2) If at least 0.05s has passed, push new data (about 20 updates per second)
|
// 2) If at least 0.05s has passed, push new data (~20 times a second)
|
||||||
if ((currentTime - s_LastPushTime) >= 0.05)
|
if ((currentTime - s_LastPushTime) >= 0.05)
|
||||||
{
|
{
|
||||||
s_LastPushTime = currentTime;
|
s_LastPushTime = currentTime;
|
||||||
@ -68,141 +70,239 @@ void PerformanceWindow::Show(float fps, float ms)
|
|||||||
PushValueToHistory(s_TriangleHistory, 60, (float)m_TriangleCount);
|
PushValueToHistory(s_TriangleHistory, 60, (float)m_TriangleCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3) Every 1 second, recalculate the max scale for FPS and ms
|
// We'll calculate a fallback max for calls
|
||||||
|
static float callsMax = 300.0f;
|
||||||
|
|
||||||
|
// 3) Every 1 second, recalculate the max scale for FPS, ms, and calls
|
||||||
if ((currentTime - s_LastScaleUpdate) >= 1.0)
|
if ((currentTime - s_LastScaleUpdate) >= 1.0)
|
||||||
{
|
{
|
||||||
s_LastScaleUpdate = currentTime;
|
s_LastScaleUpdate = currentTime;
|
||||||
|
|
||||||
// Find the maximum in s_FpsHistory
|
// Recompute s_FpsScale
|
||||||
float maxFps = 0.0f;
|
float maxFps = 0.0f;
|
||||||
for (int i = 0; i < 60; i++)
|
for (int i = 0; i < 60; i++)
|
||||||
{
|
maxFps = std::max(maxFps, s_FpsHistory[i]);
|
||||||
if (s_FpsHistory[i] > maxFps)
|
maxFps = std::max(1.0f, maxFps * 1.15f); // add ~15% headroom
|
||||||
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;
|
s_FpsScale = maxFps;
|
||||||
|
|
||||||
// Find the maximum in s_MsHistory
|
// Recompute s_MsScale
|
||||||
float maxMs = 0.0f;
|
float maxMs = 0.0f;
|
||||||
for (int i = 0; i < 60; i++)
|
for (int i = 0; i < 60; i++)
|
||||||
{
|
maxMs = std::max(maxMs, s_MsHistory[i]);
|
||||||
if (s_MsHistory[i] > maxMs)
|
maxMs = std::max(1.0f, maxMs * 1.15f);
|
||||||
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;
|
s_MsScale = maxMs;
|
||||||
|
|
||||||
|
// Recompute callsMax
|
||||||
|
float localMax = 0.0f;
|
||||||
|
for (int i = 0; i < 60; i++)
|
||||||
|
localMax = std::max(localMax, s_CallsHistory[i]);
|
||||||
|
if (localMax > 0.0f)
|
||||||
|
callsMax = localMax * 1.2f; // 20% headroom
|
||||||
|
else
|
||||||
|
callsMax = 300.0f; // default
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optional style adjustments
|
// Optional style adjustments
|
||||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
|
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(10, 10));
|
||||||
|
|
||||||
|
// Optionally make the window auto-resize or set constraints:
|
||||||
|
// ImGui::SetNextWindowSizeConstraints(ImVec2(350, 300), ImVec2(FLT_MAX, FLT_MAX));
|
||||||
|
// ImGui::Begin("Performance##performance", nullptr, ImGuiWindowFlags_AlwaysAutoResize);
|
||||||
|
|
||||||
ImGui::Begin("Performance##performance");
|
ImGui::Begin("Performance##performance");
|
||||||
|
|
||||||
// Colored header
|
// A color-coded main header
|
||||||
|
#ifdef DEBUG
|
||||||
|
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats (DEBUG)");
|
||||||
|
#else
|
||||||
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats");
|
ImGui::TextColored(ImVec4(1.0f, 0.8f, 0.2f, 1.0f), "Performance Stats");
|
||||||
ImGui::Separator();
|
#endif
|
||||||
|
|
||||||
// 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();
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
// Show OpenGL calls + Triangles
|
// Show current FPS / ms in color
|
||||||
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("Indices: %d", m_TriangleCount);
|
|
||||||
ImGui::PlotHistogram("Indices",
|
|
||||||
s_TriangleHistory,
|
|
||||||
IM_ARRAYSIZE(s_TriangleHistory),
|
|
||||||
0,
|
|
||||||
nullptr,
|
|
||||||
0.0f,
|
|
||||||
m_TriangleCount * 2.5,
|
|
||||||
ImVec2(0, 50));
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
// Show asset count
|
|
||||||
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "Assets: %d", LoadedAssets);
|
|
||||||
|
|
||||||
ImGui::Separator();
|
|
||||||
|
|
||||||
const char *options[] = {"Bootsrap", "Duck Red", "Windark", "Deep Dark", "Tesseract Black"};
|
|
||||||
static int current_option = -1; // No selection initially
|
|
||||||
|
|
||||||
const char *preview_value = (current_option >= 0 && current_option < 3) ? options[current_option] : "Select an option";
|
|
||||||
if (ImGui::BeginCombo("Theme", preview_value))
|
|
||||||
{
|
{
|
||||||
for (int n = 0; n < IM_ARRAYSIZE(options); n++)
|
// Line 1: FPS (green) + MS (teal)
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Collapsible header for the performance graphs
|
||||||
|
if (ImGui::CollapsingHeader("Performance Graphs", ImGuiTreeNodeFlags_DefaultOpen))
|
||||||
|
{
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// --------- FPS & MS side by side ----------
|
||||||
|
ImGui::BeginGroup(); // left group
|
||||||
{
|
{
|
||||||
bool is_selected = (current_option == n);
|
ImGui::Text("FPS");
|
||||||
if (ImGui::Selectable(options[n], is_selected))
|
ImGui::PushStyleColor(ImGuiCol_PlotLines, IM_COL32(0, 255, 0, 255)); // green
|
||||||
|
ImGui::PushStyleColor(ImGuiCol_PlotLinesHovered, IM_COL32(255, 0, 0, 255)); // red on hover
|
||||||
|
|
||||||
|
ImGui::PlotLines("##FPS", // hidden label
|
||||||
|
s_FpsHistory, IM_ARRAYSIZE(s_FpsHistory),
|
||||||
|
0, // offset
|
||||||
|
nullptr, // overlay
|
||||||
|
0.0f,
|
||||||
|
s_FpsScale,
|
||||||
|
ImVec2(150, 60));
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
{
|
{
|
||||||
current_option = n; // Update current option
|
ImGui::BeginTooltip();
|
||||||
ThemeManager_ChangeTheme(n); // Call the function with the selected option
|
ImGui::Text("Frames per second over time");
|
||||||
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
// Set the initial focus when opening the combo (optional)
|
|
||||||
if (is_selected)
|
ImGui::PopStyleColor(2);
|
||||||
ImGui::SetItemDefaultFocus();
|
|
||||||
}
|
}
|
||||||
ImGui::EndCombo();
|
ImGui::EndGroup();
|
||||||
}
|
|
||||||
if (ImGui::Combo("Polygon Mode", &polygonMode, polygonModeOptions, numPolygonModes))
|
ImGui::SameLine();
|
||||||
{
|
|
||||||
switch (polygonMode)
|
ImGui::BeginGroup(); // right group
|
||||||
{
|
{
|
||||||
case 0:
|
ImGui::Text("ms/frame");
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
ImGui::PlotHistogram("##ms/frame",
|
||||||
break;
|
s_MsHistory,
|
||||||
case 1:
|
IM_ARRAYSIZE(s_MsHistory),
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
0,
|
||||||
break;
|
nullptr,
|
||||||
case 2:
|
0.0f,
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
s_MsScale,
|
||||||
break;
|
ImVec2(150, 60));
|
||||||
default:
|
|
||||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
if (ImGui::IsItemHovered())
|
||||||
break;
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Frame time in milliseconds");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndGroup();
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// --------- OpenGL Calls & Indices -----------
|
||||||
|
// 1) GL Calls
|
||||||
|
ImGui::Text("OpenGL Calls: %d", m_OpenGLCallCount);
|
||||||
|
|
||||||
|
ImGui::PlotLines("##GL Calls",
|
||||||
|
s_CallsHistory,
|
||||||
|
IM_ARRAYSIZE(s_CallsHistory),
|
||||||
|
0, // offset
|
||||||
|
nullptr, // overlay text
|
||||||
|
0.0f,
|
||||||
|
callsMax,
|
||||||
|
ImVec2(-1, 50)); // auto-fill width, fixed height=50
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Number of GL draw calls per frame");
|
||||||
|
ImGui::EndTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// 2) Indices
|
||||||
|
ImGui::Text("Indices: %d", m_TriangleCount);
|
||||||
|
|
||||||
|
// For Indices, we use a histogram. We could also do dynamic range like callsMax.
|
||||||
|
float indexHistMax = std::max(1.0f, (float)m_TriangleCount * 2.5f);
|
||||||
|
|
||||||
|
ImGui::PlotHistogram("##Indices",
|
||||||
|
s_TriangleHistory,
|
||||||
|
IM_ARRAYSIZE(s_TriangleHistory),
|
||||||
|
0,
|
||||||
|
nullptr,
|
||||||
|
0.0f,
|
||||||
|
indexHistMax,
|
||||||
|
ImVec2(-1, 50)); // auto-size width, height=50
|
||||||
|
|
||||||
|
if (ImGui::IsItemHovered())
|
||||||
|
{
|
||||||
|
ImGui::BeginTooltip();
|
||||||
|
ImGui::Text("Number of indices being rendered per frame");
|
||||||
|
ImGui::EndTooltip();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// -------------- Asset Count --------------
|
||||||
|
{
|
||||||
|
ImGui::Text("Loaded Assets: ");
|
||||||
|
ImGui::SameLine();
|
||||||
|
ImGui::TextColored(ImVec4(0.4f, 1.0f, 0.4f, 1.0f), "%d", LoadedAssets);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
ImGui::Separator();
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// -------------- Theme Combo Box --------------
|
||||||
|
{
|
||||||
|
const char* options[] = {"Bootstrap", "Duck Red", "Windark", "Deep Dark", "Tesseract Black"};
|
||||||
|
static int current_option = -1;
|
||||||
|
const char* preview_value = (current_option >= 0 && current_option < IM_ARRAYSIZE(options))
|
||||||
|
? options[current_option]
|
||||||
|
: "Select an option";
|
||||||
|
|
||||||
|
ImGui::Text("Theme: ");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::BeginCombo("##ThemeCombo", preview_value))
|
||||||
|
{
|
||||||
|
for (int n = 0; n < IM_ARRAYSIZE(options); n++)
|
||||||
|
{
|
||||||
|
bool is_selected = (current_option == n);
|
||||||
|
if (ImGui::Selectable(options[n], is_selected))
|
||||||
|
{
|
||||||
|
current_option = n;
|
||||||
|
// Switch theme
|
||||||
|
ThemeManager_ChangeTheme(n);
|
||||||
|
}
|
||||||
|
if (is_selected)
|
||||||
|
ImGui::SetItemDefaultFocus();
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::Spacing();
|
||||||
|
|
||||||
|
// -------------- Polygon Mode Combo Box --------------
|
||||||
|
{
|
||||||
|
ImGui::Text("Polygon Mode: ");
|
||||||
|
ImGui::SameLine();
|
||||||
|
if (ImGui::Combo("##PolygonMode", &polygonMode, polygonModeOptions, IM_ARRAYSIZE(polygonModeOptions)))
|
||||||
|
{
|
||||||
|
switch (polygonMode)
|
||||||
|
{
|
||||||
|
case 0: // Fill
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
break;
|
||||||
|
case 1: // Wireframe
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||||
|
break;
|
||||||
|
case 2: // Points
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ImGui::End(); // End of "Performance##performance"
|
||||||
|
|
||||||
|
// Pop the style var
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
}
|
}
|
||||||
|
@ -1,37 +1,175 @@
|
|||||||
// RenderWindow.cpp
|
|
||||||
|
|
||||||
#include "RenderWindow.h"
|
#include "RenderWindow.h"
|
||||||
#include <vector> // Add this line
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
#include <GL/glew.h>
|
#include <GL/glew.h>
|
||||||
|
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
#include <glm/gtc/type_ptr.hpp>
|
#include <glm/gtc/type_ptr.hpp>
|
||||||
|
|
||||||
|
#include "Components/GameObject.h"
|
||||||
|
#include "Components/mesh.h"
|
||||||
|
#include "Components/transform.h"
|
||||||
|
#include "Components/CameraComponent.h"
|
||||||
|
|
||||||
|
#include "Engine/AssetManager.h"
|
||||||
|
#include "Engine/Settings.h"
|
||||||
|
#include "Engine/InputManager.h"
|
||||||
|
#include "Engine/KeyCode.h"
|
||||||
|
|
||||||
|
#include "Rendering/Shader.h"
|
||||||
|
|
||||||
|
#include "ImGuizmo.h"
|
||||||
|
#include "gcml.h"
|
||||||
|
#include "Icons.h"
|
||||||
#include "imgui.h"
|
#include "imgui.h"
|
||||||
|
|
||||||
#include "gcml.h"
|
|
||||||
|
|
||||||
#include "Componenets/GameObject.h"
|
|
||||||
#include "Componenets/mesh.h"
|
|
||||||
#include "Componenets/transform.h"
|
|
||||||
|
|
||||||
extern std::vector<std::shared_ptr<GameObject>> g_GameObjects;
|
|
||||||
|
|
||||||
#define CAM_FOV 45.0f
|
#define CAM_FOV 45.0f
|
||||||
#define CAM_NEAR_PLAIN 0.1f
|
#define CAM_NEAR_PLAIN 0.1f
|
||||||
#define CAM_FAR_PLAIN 2048.0f
|
#define CAM_FAR_PLAIN 2048.0f
|
||||||
|
|
||||||
// Include your AssetManager & Shader headers
|
float editorYaw = -90.0f; // Horizontal angle, initialized to face along negative Z-axis
|
||||||
#include "Engine/AssetManager.h"
|
float editorPitch = 0.0f; // Vertical angle
|
||||||
#include "Rendering/Shader.h"
|
float editorDistance = 5.0f; // Distance from the target
|
||||||
|
glm::vec3 editorTarget(0.0f, 0.0f, 0.0f); // The point the camera orbits around
|
||||||
|
|
||||||
#include "Icons.h"
|
// Configuration Parameters
|
||||||
|
const float rotationSpeed = 0.1f; // Sensitivity for mouse rotation
|
||||||
|
const float zoomSpeed = 2.0f; // Sensitivity for zooming
|
||||||
|
const float movementSpeed = 5.0f; // Speed for panning
|
||||||
|
const float minZoom = 2.0f; // Minimum zoom distance
|
||||||
|
const float maxZoom = 20.0f; // Maximum zoom distance
|
||||||
|
|
||||||
// Extern reference to our global (or extern) asset manager
|
// Managers
|
||||||
extern AssetManager g_AssetManager;
|
extern AssetManager g_AssetManager;
|
||||||
|
extern Settings g_SettingsManager;
|
||||||
|
extern InputManager g_InputManager;
|
||||||
|
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
extern bool DrawBBBO;
|
||||||
|
|
||||||
|
// GameObjects
|
||||||
|
extern std::vector<std::shared_ptr<GameObject>> g_GameObjects;
|
||||||
extern std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
|
extern std::shared_ptr<CameraComponent> g_RuntimeCameraObject;
|
||||||
|
extern GameObject *g_SelectedObject;
|
||||||
|
|
||||||
|
// Profilers
|
||||||
extern int g_GPU_Triangles_drawn_to_screen;
|
extern int g_GPU_Triangles_drawn_to_screen;
|
||||||
|
extern int g_GPU_Draw_Calls;
|
||||||
|
|
||||||
|
// Simple container for six planes
|
||||||
|
struct FrustumPlanes
|
||||||
|
{
|
||||||
|
glm::vec4 planes[6]; // Each plane is (A,B,C,D)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extract 6 planes from the combined view-projection matrix
|
||||||
|
inline FrustumPlanes ExtractFrustumPlanes(const glm::mat4 &vp)
|
||||||
|
{
|
||||||
|
FrustumPlanes frustum;
|
||||||
|
|
||||||
|
// Left
|
||||||
|
frustum.planes[0] = glm::vec4(
|
||||||
|
vp[0][3] + vp[0][0],
|
||||||
|
vp[1][3] + vp[1][0],
|
||||||
|
vp[2][3] + vp[2][0],
|
||||||
|
vp[3][3] + vp[3][0]);
|
||||||
|
|
||||||
|
// Right
|
||||||
|
frustum.planes[1] = glm::vec4(
|
||||||
|
vp[0][3] - vp[0][0],
|
||||||
|
vp[1][3] - vp[1][0],
|
||||||
|
vp[2][3] - vp[2][0],
|
||||||
|
vp[3][3] - vp[3][0]);
|
||||||
|
|
||||||
|
// Bottom
|
||||||
|
frustum.planes[2] = glm::vec4(
|
||||||
|
vp[0][3] + vp[0][1],
|
||||||
|
vp[1][3] + vp[1][1],
|
||||||
|
vp[2][3] + vp[2][1],
|
||||||
|
vp[3][3] + vp[3][1]);
|
||||||
|
|
||||||
|
// Top
|
||||||
|
frustum.planes[3] = glm::vec4(
|
||||||
|
vp[0][3] - vp[0][1],
|
||||||
|
vp[1][3] - vp[1][1],
|
||||||
|
vp[2][3] - vp[2][1],
|
||||||
|
vp[3][3] - vp[3][1]);
|
||||||
|
|
||||||
|
// Near
|
||||||
|
frustum.planes[4] = glm::vec4(
|
||||||
|
vp[0][3] + vp[0][2],
|
||||||
|
vp[1][3] + vp[1][2],
|
||||||
|
vp[2][3] + vp[2][2],
|
||||||
|
vp[3][3] + vp[3][2]);
|
||||||
|
|
||||||
|
// Far
|
||||||
|
frustum.planes[5] = glm::vec4(
|
||||||
|
vp[0][3] - vp[0][2],
|
||||||
|
vp[1][3] - vp[1][2],
|
||||||
|
vp[2][3] - vp[2][2],
|
||||||
|
vp[3][3] - vp[3][2]);
|
||||||
|
|
||||||
|
// Normalize planes (optional but recommended)
|
||||||
|
for (int i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
float length = glm::length(glm::vec3(
|
||||||
|
frustum.planes[i].x,
|
||||||
|
frustum.planes[i].y,
|
||||||
|
frustum.planes[i].z));
|
||||||
|
if (length > 0.0f)
|
||||||
|
{
|
||||||
|
frustum.planes[i] /= length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return frustum;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool IsBoxInFrustum(const glm::vec3 &bmin,
|
||||||
|
const glm::vec3 &bmax,
|
||||||
|
const FrustumPlanes &frustum)
|
||||||
|
{
|
||||||
|
// Build the 8 corners in world space
|
||||||
|
// (We assume bmin/bmax are already in world space.)
|
||||||
|
std::array<glm::vec3, 8> corners = {
|
||||||
|
glm::vec3(bmin.x, bmin.y, bmin.z),
|
||||||
|
glm::vec3(bmin.x, bmin.y, bmax.z),
|
||||||
|
glm::vec3(bmin.x, bmax.y, bmin.z),
|
||||||
|
glm::vec3(bmin.x, bmax.y, bmax.z),
|
||||||
|
glm::vec3(bmax.x, bmin.y, bmin.z),
|
||||||
|
glm::vec3(bmax.x, bmin.y, bmax.z),
|
||||||
|
glm::vec3(bmax.x, bmax.y, bmin.z),
|
||||||
|
glm::vec3(bmax.x, bmax.y, bmax.z)};
|
||||||
|
|
||||||
|
// For each plane, check if all corners are behind it.
|
||||||
|
// If yes => box is completely outside.
|
||||||
|
for (int p = 0; p < 6; p++)
|
||||||
|
{
|
||||||
|
const glm::vec4 &plane = frustum.planes[p];
|
||||||
|
int outCount = 0;
|
||||||
|
|
||||||
|
for (const auto &corner : corners)
|
||||||
|
{
|
||||||
|
// Plane eq: A*x + B*y + C*z + D
|
||||||
|
float distance = plane.x * corner.x +
|
||||||
|
plane.y * corner.y +
|
||||||
|
plane.z * corner.z +
|
||||||
|
plane.w;
|
||||||
|
|
||||||
|
if (distance < 0.0f)
|
||||||
|
outCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If all corners are 'behind' the plane, box is outside
|
||||||
|
if (outCount == 8)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Otherwise, it's at least partially inside
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool PlayPauseButton(const char *label, bool *isPlaying, ImVec2 Size)
|
bool PlayPauseButton(const char *label, bool *isPlaying, ImVec2 Size)
|
||||||
{
|
{
|
||||||
@ -94,23 +232,43 @@ bool PlayPauseButton(const char *label, bool *isPlaying, ImVec2 Size)
|
|||||||
return false; // No toggle occurred
|
return false; // No toggle occurred
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderWindow::Show(bool *GameRunning)
|
// Enum for gizmo operations
|
||||||
|
enum GizmoOperation
|
||||||
{
|
{
|
||||||
|
GIZMO_TRANSLATE,
|
||||||
|
GIZMO_ROTATE,
|
||||||
|
GIZMO_SCALE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize with a default operation
|
||||||
|
GizmoOperation currentOperation = GIZMO_TRANSLATE;
|
||||||
|
|
||||||
|
void RenderWindow::Show(bool *GameRunning, double deltaTime)
|
||||||
|
{
|
||||||
|
// Begin the ImGui window with an icon and label
|
||||||
ImGui::Begin(ICON_FA_GAMEPAD " Editor##EditorWindow");
|
ImGui::Begin(ICON_FA_GAMEPAD " Editor##EditorWindow");
|
||||||
|
|
||||||
|
ImGuizmo::BeginFrame();
|
||||||
|
|
||||||
|
ImGuizmo::SetOrthographic(false);
|
||||||
|
ImGuizmo::SetDrawlist();
|
||||||
|
|
||||||
|
// Initialize OpenGL resources if not already done
|
||||||
if (!m_Initialized)
|
if (!m_Initialized)
|
||||||
{
|
{
|
||||||
InitGLResources();
|
InitGLResources();
|
||||||
m_Initialized = true;
|
m_Initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the available size for rendering within the window
|
||||||
ImVec2 size = ImGui::GetContentRegionAvail();
|
ImVec2 size = ImGui::GetContentRegionAvail();
|
||||||
int w = static_cast<int>(size.x);
|
int w = static_cast<int>(size.x);
|
||||||
int h = static_cast<int>(size.y);
|
int h = static_cast<int>(size.y);
|
||||||
|
|
||||||
// If there's space, render to the FBO, then show it as an ImGui image
|
// Check if there's space to render
|
||||||
if (w > 0 && h > 0)
|
if (w > 0 && h > 0)
|
||||||
{
|
{
|
||||||
|
// Resize the FBO if the window size has changed
|
||||||
if (w != m_LastWidth || h != m_LastHeight)
|
if (w != m_LastWidth || h != m_LastHeight)
|
||||||
{
|
{
|
||||||
m_FBO.Create(w, h);
|
m_FBO.Create(w, h);
|
||||||
@ -118,33 +276,176 @@ void RenderWindow::Show(bool *GameRunning)
|
|||||||
m_LastHeight = h;
|
m_LastHeight = h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Render the 3D scene to the FBO
|
||||||
RenderSceneToFBO(GameRunning);
|
RenderSceneToFBO(GameRunning);
|
||||||
|
|
||||||
// Render the image first
|
// Display the rendered scene as an image in ImGui
|
||||||
|
// Correctly cast the texture ID for OpenGL
|
||||||
ImGui::Image(m_FBO.GetTextureID(), size, ImVec2(0, 0), ImVec2(1, 1));
|
ImGui::Image(m_FBO.GetTextureID(), size, ImVec2(0, 0), ImVec2(1, 1));
|
||||||
|
|
||||||
// Calculate button position to place it slightly right and down from the top-left of the image
|
// Calculate button position to place it slightly right and down from the top-left of the image
|
||||||
ImVec2 imagePos = ImGui::GetItemRectMin();
|
ImVec2 imagePos = ImGui::GetItemRectMin();
|
||||||
|
|
||||||
// Add an offset to position the button
|
// Add an offset to position the button
|
||||||
ImVec2 buttonOffset(10.0f, 10.0f); // Adjust these values as needed for the desired offset
|
ImVec2 buttonOffset(10.0f, 10.0f); // 10 pixels right and 10 pixels down
|
||||||
ImVec2 buttonPos = ImVec2(imagePos.x + buttonOffset.x, imagePos.y + buttonOffset.y);
|
ImVec2 buttonPos = ImVec2(imagePos.x + buttonOffset.x, imagePos.y + buttonOffset.y);
|
||||||
|
|
||||||
// Set cursor position for the button
|
// Set cursor position for the button
|
||||||
ImGui::SetCursorScreenPos(buttonPos);
|
ImGui::SetCursorScreenPos(buttonPos);
|
||||||
|
|
||||||
// Dynamically calculate button size based on window size
|
// Dynamically calculate button size based on window size
|
||||||
float buttonWidth = size.x * 0.03f; // 5% of the window width
|
float buttonWidth = size.x * 0.05f; // 5% of the window width
|
||||||
ImVec2 buttonSize = ImVec2(buttonWidth, buttonWidth);
|
ImVec2 buttonSize = ImVec2(buttonWidth, buttonWidth);
|
||||||
|
|
||||||
// Render the Play/Pause button with the calculated size
|
// Render the Play/Pause button with the calculated size
|
||||||
PlayPauseButton("##PlayPauseButton", GameRunning, buttonSize);
|
PlayPauseButton("##PlayPauseButton", GameRunning, buttonSize);
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
// *** Gizmo Operation Selection UI ***
|
||||||
|
// ---------------------------------------------------
|
||||||
|
|
||||||
|
// ---------------------------------------------------
|
||||||
|
// *** Integrate ImGuizmo for Manipulating Objects ***
|
||||||
|
// ---------------------------------------------------
|
||||||
|
|
||||||
|
// Ensure a GameObject is selected
|
||||||
|
if (g_SelectedObject)
|
||||||
|
{
|
||||||
|
// Retrieve the TransformComponent from the selected object
|
||||||
|
auto transform = g_SelectedObject->GetComponent<TransformComponent>();
|
||||||
|
if (transform)
|
||||||
|
{
|
||||||
|
// Get the current transformation matrix
|
||||||
|
glm::mat4 modelMatrix = transform->GetTransformMatrix();
|
||||||
|
|
||||||
|
// Obtain view and projection matrices from the active camera
|
||||||
|
glm::mat4 viewMatrix;
|
||||||
|
glm::mat4 projectionMatrix;
|
||||||
|
// Camera Selection and Setup Logic (e.g., within your rendering or update function)
|
||||||
|
|
||||||
|
if (m_ActiveCamera)
|
||||||
|
{
|
||||||
|
// Use the existing active camera
|
||||||
|
viewMatrix = m_ActiveCamera->GetViewMatrix();
|
||||||
|
projectionMatrix = m_ActiveCamera->GetProjectionMatrix();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_ActiveCamera = m_EditorCamera->GetComponent<CameraComponent>();
|
||||||
|
|
||||||
|
// 1. Mouse Input for Rotation
|
||||||
|
if (g_InputManager.IsMouseButtonPressed(MouseButton::RIGHT))
|
||||||
|
{
|
||||||
|
float deltaX = g_InputManager.GetMouseDeltaX();
|
||||||
|
float deltaY = g_InputManager.GetMouseDeltaY();
|
||||||
|
|
||||||
|
editorYaw += deltaX * rotationSpeed;
|
||||||
|
editorPitch += deltaY * rotationSpeed;
|
||||||
|
|
||||||
|
// Clamp the pitch to prevent flipping
|
||||||
|
if (editorPitch > 89.0f)
|
||||||
|
editorPitch = 89.0f;
|
||||||
|
if (editorPitch < -89.0f)
|
||||||
|
editorPitch = -89.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Scroll Input for Zooming
|
||||||
|
float scrollDelta = g_InputManager.GetScrollDelta();
|
||||||
|
editorDistance -= scrollDelta * zoomSpeed;
|
||||||
|
editorDistance = glm::clamp(editorDistance, minZoom, maxZoom);
|
||||||
|
|
||||||
|
// 3. Keyboard Input for Panning (WASD)
|
||||||
|
glm::vec3 forward = glm::normalize(editorTarget - m_EditorCamera->GetComponent<TransformComponent>()->GetPosition());
|
||||||
|
glm::vec3 right = glm::normalize(glm::cross(forward, glm::vec3(0.0f, 1.0f, 0.0f)));
|
||||||
|
glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||||
|
|
||||||
|
deltaTime = static_cast<float>(deltaTime);
|
||||||
|
|
||||||
|
if (g_InputManager.IsKeyPressed(KeyCode::W))
|
||||||
|
editorTarget += up.y * movementSpeed * deltaTime;
|
||||||
|
if (g_InputManager.IsKeyPressed(KeyCode::S))
|
||||||
|
editorTarget -= up.y * movementSpeed * deltaTime;
|
||||||
|
if (g_InputManager.IsKeyPressed(KeyCode::A))
|
||||||
|
editorTarget -= right.x * movementSpeed * deltaTime;
|
||||||
|
if (g_InputManager.IsKeyPressed(KeyCode::D))
|
||||||
|
editorTarget += right.x * movementSpeed * deltaTime;
|
||||||
|
|
||||||
|
// 4. Calculate the New Camera Position
|
||||||
|
glm::vec3 direction;
|
||||||
|
direction.x = cos(glm::radians(editorYaw)) * cos(glm::radians(editorPitch));
|
||||||
|
direction.y = sin(glm::radians(editorPitch));
|
||||||
|
direction.z = sin(glm::radians(editorYaw)) * cos(glm::radians(editorPitch));
|
||||||
|
direction = glm::normalize(direction);
|
||||||
|
|
||||||
|
glm::vec3 newPosition = editorTarget - direction * editorDistance;
|
||||||
|
|
||||||
|
// 5. Update the Editor Camera's Transform
|
||||||
|
auto editorTransform = m_EditorCamera->GetComponent<TransformComponent>();
|
||||||
|
editorTransform->SetPosition(newPosition.x,newPosition.y,newPosition.z);
|
||||||
|
editorTransform->LookAt(editorTarget, up);
|
||||||
|
|
||||||
|
// 6. Retrieve Updated Matrices
|
||||||
|
viewMatrix = m_ActiveCamera->GetViewMatrix();
|
||||||
|
projectionMatrix = m_ActiveCamera->GetProjectionMatrix();
|
||||||
|
|
||||||
|
static ImGuizmo::OPERATION currentOperation = ImGuizmo::TRANSLATE;
|
||||||
|
|
||||||
|
if (ImGui::IsWindowFocused() && ImGui::IsWindowHovered())
|
||||||
|
{
|
||||||
|
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_T))
|
||||||
|
{
|
||||||
|
currentOperation = ImGuizmo::TRANSLATE;
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_R))
|
||||||
|
{
|
||||||
|
currentOperation = ImGuizmo::ROTATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_S))
|
||||||
|
{
|
||||||
|
currentOperation = ImGuizmo::SCALE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define snap settings
|
||||||
|
bool snap = false; // Enable snapping if needed
|
||||||
|
float snapValue = 0.1f; // Snap increment
|
||||||
|
|
||||||
|
// Set the ImGuizmo rectangle to the window's position and size
|
||||||
|
ImVec2 windowPos = ImGui::GetWindowPos();
|
||||||
|
ImVec2 windowSize = ImGui::GetWindowSize();
|
||||||
|
ImGuizmo::SetRect(windowPos.x, windowPos.y, windowSize.x, windowSize.y);
|
||||||
|
|
||||||
|
// Render the gizmo and handle user interaction
|
||||||
|
projectionMatrix[1][1] *= -1.0f; // Flip Image Internaly
|
||||||
|
ImGuizmo::Manipulate(
|
||||||
|
glm::value_ptr(viewMatrix),
|
||||||
|
glm::value_ptr(projectionMatrix),
|
||||||
|
currentOperation,
|
||||||
|
ImGuizmo::LOCAL,
|
||||||
|
glm::value_ptr(modelMatrix),
|
||||||
|
nullptr, // Optional delta matrix
|
||||||
|
snap ? &snapValue : nullptr // Optional snap values
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if the gizmo is being used (i.e., if the user is interacting with it)
|
||||||
|
if (ImGuizmo::IsUsing())
|
||||||
|
{
|
||||||
|
// Update the TransformComponent with the modified matrix
|
||||||
|
transform->SetTransformMatrix(modelMatrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// Display message if there's insufficient space to render the scene
|
||||||
ImGui::Text("No space to render.");
|
ImGui::Text("No space to render.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// End the ImGui window
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,6 +455,15 @@ void RenderWindow::InitGLResources()
|
|||||||
// 1) Load SHADER from the asset manager
|
// 1) Load SHADER from the asset manager
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
|
|
||||||
|
// throw this in here cus we dont have a constructor
|
||||||
|
m_ActiveCamera = nullptr;
|
||||||
|
|
||||||
|
m_EditorCamera = std::make_shared<GameObject>(-1, "EditorCamera");
|
||||||
|
|
||||||
|
// Setup the editor camera
|
||||||
|
m_EditorCamera->AddComponent(std::make_shared<CameraComponent>());
|
||||||
|
m_EditorCamera->AddComponent(std::make_shared<TransformComponent>());
|
||||||
|
|
||||||
{
|
{
|
||||||
std::shared_ptr<Shader> shaderAsset = g_AssetManager.loadAsset<Shader>(AssetType::SHADER, "assets/shaders/UnlitMaterial");
|
std::shared_ptr<Shader> shaderAsset = g_AssetManager.loadAsset<Shader>(AssetType::SHADER, "assets/shaders/UnlitMaterial");
|
||||||
if (!shaderAsset)
|
if (!shaderAsset)
|
||||||
@ -165,6 +475,17 @@ void RenderWindow::InitGLResources()
|
|||||||
m_ShaderPtr = shaderAsset.get();
|
m_ShaderPtr = shaderAsset.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::shared_ptr<Shader> shaderAsset = g_AssetManager.loadAsset<Shader>(AssetType::SHADER, "assets/shaders/Line");
|
||||||
|
if (!shaderAsset)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "[RenderWindow] Failed to load shader via AssetManager.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Cast back to your Shader class
|
||||||
|
m_LineShaderPtr = shaderAsset.get();
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
// 3) Load TEXTURE from the asset manager
|
// 3) Load TEXTURE from the asset manager
|
||||||
// ----------------------------------------------------
|
// ----------------------------------------------------
|
||||||
@ -203,12 +524,11 @@ void CheckOpenGLError(const std::string &location)
|
|||||||
|
|
||||||
#include <glm/gtc/type_ptr.hpp> // For glm::value_ptr
|
#include <glm/gtc/type_ptr.hpp> // For glm::value_ptr
|
||||||
#include <algorithm> // Ensure <algorithm> is included
|
#include <algorithm> // Ensure <algorithm> is included
|
||||||
|
|
||||||
void RenderWindow::RenderSceneToFBO(bool *GameRunning)
|
void RenderWindow::RenderSceneToFBO(bool *GameRunning)
|
||||||
{
|
{
|
||||||
m_RotationAngle += 0.001f; // Spin per frame
|
m_RotationAngle += 0.001f; // Spin per frame
|
||||||
|
|
||||||
// Bind the FBO
|
// 1) Bind the FBO and set up viewport
|
||||||
m_FBO.Bind();
|
m_FBO.Bind();
|
||||||
glViewport(0, 0, m_LastWidth, m_LastHeight);
|
glViewport(0, 0, m_LastWidth, m_LastHeight);
|
||||||
|
|
||||||
@ -222,135 +542,191 @@ void RenderWindow::RenderSceneToFBO(bool *GameRunning)
|
|||||||
glClearColor(0.f, 0.f, 0.f, 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
|
// 2) Check our main rendering shader
|
||||||
if (!m_ShaderPtr)
|
if (!m_ShaderPtr)
|
||||||
{
|
{
|
||||||
DEBUG_PRINT("[RenderWindow] Shader pointer is null. Cannot render.");
|
DEBUG_PRINT("[RenderWindow] Shader pointer is null. Cannot render.");
|
||||||
m_FBO.Unbind();
|
m_FBO.Unbind();
|
||||||
return; // Can't render without a shader
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_ShaderPtr->Use();
|
m_ShaderPtr->Use();
|
||||||
|
|
||||||
// Define view and projection matrices once
|
// 3) Obtain view/projection from the active camera (or fallback)
|
||||||
std::shared_ptr<CameraComponent> activeCamera = nullptr;
|
std::shared_ptr<CameraComponent> activeCamera = nullptr;
|
||||||
|
glm::mat4 view, proj;
|
||||||
glm::mat4 view;
|
|
||||||
glm::mat4 proj;
|
|
||||||
|
|
||||||
if (*GameRunning && g_RuntimeCameraObject)
|
if (*GameRunning && g_RuntimeCameraObject)
|
||||||
{
|
{
|
||||||
activeCamera = g_RuntimeCameraObject;
|
activeCamera = g_RuntimeCameraObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that an active camera is available
|
|
||||||
if (activeCamera)
|
if (activeCamera)
|
||||||
{
|
{
|
||||||
// Obtain view and projection matrices from the active camera
|
// TODO: Add camera Movement in editor
|
||||||
view = activeCamera->GetViewMatrix();
|
view = activeCamera->GetViewMatrix();
|
||||||
proj = activeCamera->GetProjectionMatrix();
|
proj = activeCamera->GetProjectionMatrix();
|
||||||
|
m_ActiveCamera = activeCamera;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Fallback to default view and projection if no camera is available
|
// Fallback if no camera
|
||||||
view = glm::translate(glm::mat4(1.f), glm::vec3(0.f, 0.f, -5.f));
|
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;
|
float aspect = (m_LastHeight != 0) ? (float)m_LastWidth / (float)m_LastHeight : 1.0f;
|
||||||
proj = glm::perspective(glm::radians(CAM_FOV), aspect, CAM_NEAR_PLAIN, CAM_FAR_PLAIN);
|
proj = glm::perspective(glm::radians(CAM_FOV), aspect, CAM_NEAR_PLAIN, CAM_FAR_PLAIN);
|
||||||
|
m_ActiveCamera = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Iterate over each GameObject and render it
|
// 4) Extract frustum planes for culling
|
||||||
|
glm::mat4 vp = proj * view;
|
||||||
|
FrustumPlanes frustum = ExtractFrustumPlanes(vp);
|
||||||
|
|
||||||
|
// 5) Iterate over each GameObject and render
|
||||||
|
glm::vec4 LineColor = g_SettingsManager.S_LineColor;
|
||||||
|
|
||||||
for (auto &obj : g_GameObjects)
|
for (auto &obj : g_GameObjects)
|
||||||
{
|
{
|
||||||
glm::mat4 model = glm::mat4(1.f);
|
glm::mat4 model = glm::mat4(1.f);
|
||||||
|
|
||||||
std::shared_ptr<TransformComponent> transform = obj->GetComponent<TransformComponent>();
|
auto transform = obj->GetComponent<TransformComponent>();
|
||||||
std::shared_ptr<MeshComponent> mesh = obj->GetComponent<MeshComponent>();
|
auto mesh = obj->GetComponent<MeshComponent>();
|
||||||
|
|
||||||
if (transform && mesh && mesh)
|
if (transform && mesh)
|
||||||
{
|
{
|
||||||
// Apply transformations
|
// 5A) Build the Model matrix
|
||||||
model = glm::translate(model, transform->position);
|
model = glm::translate(model, transform->position);
|
||||||
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.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.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));
|
model = glm::rotate(model, glm::radians(transform->rotation.z), glm::vec3(0.f, 0.f, 1.f));
|
||||||
model = glm::scale(model, transform->scale);
|
model = glm::scale(model, transform->scale);
|
||||||
|
|
||||||
// Compute MVP matrix
|
// 5B) For each submesh
|
||||||
glm::mat4 mvp = proj * view * model;
|
for (auto &submesh : mesh->submeshes)
|
||||||
|
|
||||||
// Pass MVP and Model matrices to the shader
|
|
||||||
m_ShaderPtr->SetMat4("uMVP", mvp);
|
|
||||||
m_ShaderPtr->SetMat4("uModel", model);
|
|
||||||
|
|
||||||
// Iterate through each submesh
|
|
||||||
for (const auto &submesh : mesh->submeshes)
|
|
||||||
{
|
{
|
||||||
// Validate VAO
|
// Check if VAO is valid
|
||||||
if (submesh.vao == 0)
|
if (submesh.vao == 0)
|
||||||
{
|
{
|
||||||
DEBUG_PRINT("[RenderWindow] Warning: Submesh VAO is not initialized.");
|
DEBUG_PRINT("[RenderWindow] Warning: Submesh VAO is not initialized.");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update triangle count
|
// -------------------------
|
||||||
|
// *** FRUSTUM CULLING ***
|
||||||
|
// Transform submesh bounding box from local -> world space
|
||||||
|
glm::vec3 worldMin(FLT_MAX), worldMax(-FLT_MAX);
|
||||||
|
std::array<glm::vec3, 8> corners = {
|
||||||
|
glm::vec3(submesh.minExtents.x, submesh.minExtents.y, submesh.minExtents.z),
|
||||||
|
glm::vec3(submesh.minExtents.x, submesh.minExtents.y, submesh.maxExtents.z),
|
||||||
|
glm::vec3(submesh.minExtents.x, submesh.maxExtents.y, submesh.minExtents.z),
|
||||||
|
glm::vec3(submesh.minExtents.x, submesh.maxExtents.y, submesh.maxExtents.z),
|
||||||
|
glm::vec3(submesh.maxExtents.x, submesh.minExtents.y, submesh.minExtents.z),
|
||||||
|
glm::vec3(submesh.maxExtents.x, submesh.minExtents.y, submesh.maxExtents.z),
|
||||||
|
glm::vec3(submesh.maxExtents.x, submesh.maxExtents.y, submesh.minExtents.z),
|
||||||
|
glm::vec3(submesh.maxExtents.x, submesh.maxExtents.y, submesh.maxExtents.z)};
|
||||||
|
|
||||||
|
for (auto &c : corners)
|
||||||
|
{
|
||||||
|
// Transform corner by the model matrix
|
||||||
|
glm::vec4 worldPos = model * glm::vec4(c, 1.0f);
|
||||||
|
|
||||||
|
// Expand worldMin / worldMax
|
||||||
|
worldMin.x = std::min(worldMin.x, worldPos.x);
|
||||||
|
worldMin.y = std::min(worldMin.y, worldPos.y);
|
||||||
|
worldMin.z = std::min(worldMin.z, worldPos.z);
|
||||||
|
|
||||||
|
worldMax.x = std::max(worldMax.x, worldPos.x);
|
||||||
|
worldMax.y = std::max(worldMax.y, worldPos.y);
|
||||||
|
worldMax.z = std::max(worldMax.z, worldPos.z);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now test that box against frustum
|
||||||
|
if (!IsBoxInFrustum(worldMin, worldMax, frustum))
|
||||||
|
{
|
||||||
|
// The submesh is completely outside the camera's view => skip
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// -------------------------
|
||||||
|
|
||||||
|
// 5C) Compute MVP and pass to shader
|
||||||
|
glm::mat4 mvp = vp * model;
|
||||||
|
m_ShaderPtr->SetMat4("uMVP", mvp);
|
||||||
|
m_ShaderPtr->SetMat4("uModel", model);
|
||||||
|
|
||||||
|
// 5D) Update tri count
|
||||||
g_GPU_Triangles_drawn_to_screen += static_cast<int>(submesh.indices.size() / 3);
|
g_GPU_Triangles_drawn_to_screen += static_cast<int>(submesh.indices.size() / 3);
|
||||||
|
|
||||||
// Bind textures for the submesh
|
// 5E) Bind textures
|
||||||
// Assuming the shader has uniform arrays like uTextures.texture_diffuse[32]
|
const int MAX_DIFFUSE = 32;
|
||||||
const int MAX_DIFFUSE = 32; // Must match the shader's MAX_DIFFUSE
|
|
||||||
int textureUnit = 0;
|
int textureUnit = 0;
|
||||||
|
for (auto &texture : submesh.textures)
|
||||||
// Iterate through all textures and bind those with type "texture_diffuse"
|
|
||||||
for (const auto &texture : submesh.textures)
|
|
||||||
{
|
{
|
||||||
if (texture.type == "texture_diffuse")
|
if (texture.type == "texture_diffuse")
|
||||||
{
|
{
|
||||||
if (textureUnit >= MAX_DIFFUSE)
|
if (textureUnit >= MAX_DIFFUSE)
|
||||||
{
|
{
|
||||||
DEBUG_PRINT("[RenderWindow] Warning: Exceeded maximum number of diffuse textures (%d) for shader.", MAX_DIFFUSE);
|
DEBUG_PRINT("[RenderWindow] Warning: Exceeded maximum diffuse textures.");
|
||||||
break; // Prevent exceeding the array bounds in the shader
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Activate the appropriate texture unit
|
|
||||||
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
glActiveTexture(GL_TEXTURE0 + textureUnit);
|
||||||
glBindTexture(GL_TEXTURE_2D, texture.id);
|
glBindTexture(GL_TEXTURE_2D, texture.id);
|
||||||
|
|
||||||
// Construct the uniform name dynamically (e.g., "uTextures.texture_diffuse[0]")
|
|
||||||
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(textureUnit) + "]";
|
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(textureUnit) + "]";
|
||||||
m_ShaderPtr->SetInt(uniformName, textureUnit);
|
m_ShaderPtr->SetInt(uniformName, textureUnit);
|
||||||
|
|
||||||
textureUnit++;
|
textureUnit++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Assign default texture to unused slots
|
||||||
// Assign default texture to unused texture slots to prevent shader errors
|
|
||||||
for (int i = textureUnit; i < MAX_DIFFUSE; ++i)
|
for (int i = textureUnit; i < MAX_DIFFUSE; ++i)
|
||||||
{
|
{
|
||||||
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(i) + "]";
|
std::string uniformName = "uTextures.texture_diffuse[" + std::to_string(i) + "]";
|
||||||
m_ShaderPtr->SetInt(uniformName, 0); // Assign texture unit 0 (ensure texture 0 is a valid default)
|
m_ShaderPtr->SetInt(uniformName, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the number of active diffuse textures
|
|
||||||
m_ShaderPtr->SetInt("uNumDiffuseTextures", textureUnit);
|
m_ShaderPtr->SetInt("uNumDiffuseTextures", textureUnit);
|
||||||
|
|
||||||
// Draw the submesh
|
// 5F) Draw submesh (filled)
|
||||||
glBindVertexArray(submesh.vao);
|
glBindVertexArray(submesh.vao);
|
||||||
glDrawElements(GL_TRIANGLES, static_cast<GLsizei>(submesh.indices.size()), GL_UNSIGNED_INT, nullptr);
|
glDrawElements(GL_TRIANGLES,
|
||||||
|
static_cast<GLsizei>(submesh.indices.size()),
|
||||||
|
GL_UNSIGNED_INT,
|
||||||
|
nullptr);
|
||||||
|
g_GPU_Draw_Calls++;
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
|
|
||||||
// Reset active texture to default
|
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// 5G) OPTIONAL: Draw a bounding box outline
|
||||||
|
// ----------------------------------------
|
||||||
|
if (DrawBBBO && m_LineShaderPtr && submesh.bboxVAO != 0)
|
||||||
|
{
|
||||||
|
// Use a simpler line shader that doesn't rely on textures
|
||||||
|
m_LineShaderPtr->Use();
|
||||||
|
|
||||||
|
// Recompute the MVP for the bounding box (same model, same vp)
|
||||||
|
glm::mat4 bboxMVP = vp * model;
|
||||||
|
m_LineShaderPtr->SetMat4("uMVP", bboxMVP);
|
||||||
|
m_LineShaderPtr->SetVec4("uColor", LineColor);
|
||||||
|
glLineWidth(2.0f);
|
||||||
|
|
||||||
|
// If your line shader has a uniform color:
|
||||||
|
// m_LineShaderPtr->SetVec4("uColor", glm::vec4(1,1,0,1)); // e.g., yellow
|
||||||
|
|
||||||
|
// Draw the bounding box in wireframe lines
|
||||||
|
glBindVertexArray(submesh.bboxVAO);
|
||||||
|
// We assume submesh.bboxVertexCount is the number of line-vertices
|
||||||
|
glDrawArrays(GL_LINES, 0, submesh.bboxVertexCount);
|
||||||
|
|
||||||
|
glBindVertexArray(0);
|
||||||
|
glUseProgram(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cleanup: Unbind the shader program
|
|
||||||
#if TRANSPERANCY
|
#if TRANSPERANCY
|
||||||
|
|
||||||
glDisable(GL_BLEND);
|
glDisable(GL_BLEND);
|
||||||
#endif
|
#endif
|
||||||
glUseProgram(0);
|
glUseProgram(0);
|
||||||
|
|
||||||
// Unbind the FBO
|
// 6) Unbind the FBO
|
||||||
m_FBO.Unbind();
|
m_FBO.Unbind();
|
||||||
}
|
}
|
||||||
|
@ -2,18 +2,23 @@
|
|||||||
|
|
||||||
#include "../Rendering/FBO.h"
|
#include "../Rendering/FBO.h"
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
#include <memory>
|
||||||
#include "Rendering/Shader.h" //
|
#include "Rendering/Shader.h" //
|
||||||
|
#include "Components/CameraComponent.h"
|
||||||
|
#include "Components/GameObject.h"
|
||||||
|
#include "Engine/InputManager.h"
|
||||||
|
|
||||||
class RenderWindow
|
class RenderWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void Show(bool *GameRunning);
|
void Show(bool *GameRunning, double deltaTime);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void InitGLResources();
|
void InitGLResources();
|
||||||
void RenderSceneToFBO(bool *GameRunning);
|
void RenderSceneToFBO(bool *GameRunning);
|
||||||
|
|
||||||
|
std::shared_ptr<CameraComponent> m_ActiveCamera;
|
||||||
|
|
||||||
// Offscreen render target
|
// Offscreen render target
|
||||||
FBO m_FBO;
|
FBO m_FBO;
|
||||||
|
|
||||||
@ -35,4 +40,15 @@ private:
|
|||||||
|
|
||||||
// The loaded shader program (via AssetManager)
|
// The loaded shader program (via AssetManager)
|
||||||
Shader* m_ShaderPtr = nullptr;
|
Shader* m_ShaderPtr = nullptr;
|
||||||
|
Shader* m_LineShaderPtr = nullptr;
|
||||||
|
|
||||||
|
std::shared_ptr<GameObject> m_EditorCamera;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct Ray
|
||||||
|
{
|
||||||
|
glm::vec3 origin;
|
||||||
|
glm::vec3 direction; // Should be normalized
|
||||||
|
};
|
||||||
|
|
||||||
|
@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
// 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 "gcml.h"
|
#include "gcml.h"
|
||||||
#include "Engine/ScopedTimer.h"
|
#include "Engine/ScopedTimer.h"
|
||||||
|
|
||||||
@ -30,6 +29,13 @@ std::shared_ptr<GameObject> CreateDefaultCube()
|
|||||||
void SceneWindow::Show()
|
void SceneWindow::Show()
|
||||||
{
|
{
|
||||||
SCOPE_TIMER("SceneWindow::Show");
|
SCOPE_TIMER("SceneWindow::Show");
|
||||||
|
|
||||||
|
if (g_SelectedObject) {
|
||||||
|
if (ImGui::IsKeyPressed(ImGuiKey_Escape)) {
|
||||||
|
g_SelectedObject = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (ImGui::Begin("Scene Window##SceneWindow"))
|
if (ImGui::Begin("Scene Window##SceneWindow"))
|
||||||
{
|
{
|
||||||
// Add Button
|
// Add Button
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "Componenets/GameObject.h"
|
#include "Components/GameObject.h"
|
||||||
|
|
||||||
|
|
||||||
// SceneWindow class declaration
|
// SceneWindow class declaration
|
||||||
|
@ -12,9 +12,14 @@ int main()
|
|||||||
// Small error where the constuctor would crash
|
// Small error where the constuctor would crash
|
||||||
MyEngine engine;
|
MyEngine engine;
|
||||||
DEBUG_PRINT("[OK] Creating Global Engine ");
|
DEBUG_PRINT("[OK] Creating Global Engine ");
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
std::string title = "Tesseract Engine (DEBUG)";
|
||||||
|
#else
|
||||||
|
std::string title = "Tesseract Engine";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (!engine.Init(1280, 720, title))
|
||||||
if (!engine.Init(1280, 720, "Tesseract Engine"))
|
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Failed to initialize engine.\n");
|
fprintf(stderr, "Failed to initialize engine.\n");
|
||||||
return 1;
|
return 1;
|
||||||
|
Loading…
Reference in New Issue
Block a user