Updated Lighting and compont.
This commit is contained in:
parent
4dfd637972
commit
4ba7e8f888
17
build.log
17
build.log
@ -1,14 +1,15 @@
|
||||
[COMPILE] g++ -std=c++20 -Wall -Isrc/include -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -MMD -MP -c src\src\Renderer.cpp -o src\build\src\Renderer.oIn file included from C:/msys64/mingw64/include/yaml-cpp/parser.h:13,
|
||||
[COMPILE] g++ -std=c++20 -Wall -Isrc/include -Isrc/vendor -Isrc/vendor/imgui -IC:/msys64/mingw64/include -MMD -MP -c src\src\Engine.cpp -o src\build\src\Engine.oIn file included from C:/msys64/mingw64/include/yaml-cpp/parser.h:13,
|
||||
from C:/msys64/mingw64/include/yaml-cpp/yaml.h:10,
|
||||
from src\src\Components/Component.h:5,
|
||||
from src\src\Components/SpriteComponent.h:3,
|
||||
from src\src\Renderer.cpp:2:
|
||||
from src\src\Entitys/Object.h:7,
|
||||
from src\src\Engine.cpp:2:
|
||||
C:/msys64/mingw64/include/yaml-cpp/dll.h:22:65: note: '#pragma message: Defining YAML_CPP_API for DLL import'
|
||||
22 | # pragma message( "Defining YAML_CPP_API for DLL import" )
|
||||
| ^
|
||||
src\src\Engine.cpp: In function 'void DrawInspectorUI(std::shared_ptr<Object>)':
|
||||
src\src\Engine.cpp:219:13: warning: unused variable 'type' [-Wunused-variable]
|
||||
219 | int type = light->GetType();
|
||||
| ^~~~
|
||||
|
||||
[LINK] g++ src\build\src\Engine.o src\build\src\main.o src\build\src\Renderer.o src\build\src\Components\CameraComponent.o src\build\src\Components\SpriteComponent.o src\build\src\Entitys\Object.o src\build\src\utils\FileDialog.o src\build\src\utils\Shader.o src\build\vendor\imgui\imgui.o src\build\vendor\imgui\imgui_demo.o src\build\vendor\imgui\imgui_draw.o src\build\vendor\imgui\imgui_impl_glfw.o src\build\vendor\imgui\imgui_impl_opengl3.o src\build\vendor\imgui\imgui_tables.o src\build\vendor\imgui\imgui_widgets.o -o src\build\app.exe -LC:/msys64/mingw64/lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
[LINK] g++ src\build\src\Engine.o src\build\src\main.o src\build\src\Renderer.o src\build\src\Components\CameraComponent.o src\build\src\Components\LightComponent.o src\build\src\Components\SpriteComponent.o src\build\src\Entitys\Object.o src\build\src\utils\FileDialog.o src\build\src\utils\Logging.o src\build\src\utils\Shader.o src\build\src\utils\utils.o src\build\vendor\imgui\imgui.o src\build\vendor\imgui\imgui_demo.o src\build\vendor\imgui\imgui_draw.o src\build\vendor\imgui\imgui_impl_glfw.o src\build\vendor\imgui\imgui_impl_opengl3.o src\build\vendor\imgui\imgui_tables.o src\build\vendor\imgui\imgui_widgets.o -o src\build\app.exe -LC:/msys64/mingw64/lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
|
||||
[TIME] Build duration: 2.75s
|
||||
[ERROR] Runtime crash
|
||||
Command 'src\build\app.exe' returned non-zero exit status 1.
|
||||
[TIME] Build duration: 6.67s
|
||||
|
29
imgui.ini
29
imgui.ini
@ -15,9 +15,9 @@ Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=873,19
|
||||
Size=407,701
|
||||
Size=407,505
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
DockId=0x00000005,0
|
||||
|
||||
[Window][Scene Tree]
|
||||
Pos=0,19
|
||||
@ -27,19 +27,34 @@ DockId=0x00000001,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=265,19
|
||||
Size=606,701
|
||||
Size=606,412
|
||||
Collapsed=0
|
||||
DockId=0x00000002,0
|
||||
DockId=0x00000007,0
|
||||
|
||||
[Window][##MainMenuBar]
|
||||
Pos=0,0
|
||||
Size=1280,19
|
||||
Collapsed=0
|
||||
|
||||
[Window][Performance Info]
|
||||
Pos=873,526
|
||||
Size=407,194
|
||||
Collapsed=0
|
||||
DockId=0x00000006,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=265,433
|
||||
Size=606,287
|
||||
Collapsed=0
|
||||
DockId=0x00000008,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X
|
||||
DockNode ID=0x00000003 Parent=0x11111111 SizeRef=1511,1158 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x00000003 SizeRef=263,701 HiddenTabBar=1 Selected=0x12EF0F59
|
||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1246,701 CentralNode=1 Selected=0xC450F867
|
||||
DockNode ID=0x00000004 Parent=0x11111111 SizeRef=407,1158 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000002 Parent=0x00000003 SizeRef=1246,701 Split=Y Selected=0xC450F867
|
||||
DockNode ID=0x00000007 Parent=0x00000002 SizeRef=606,869 CentralNode=1 Selected=0xC450F867
|
||||
DockNode ID=0x00000008 Parent=0x00000002 SizeRef=606,287 Selected=0xEA83D666
|
||||
DockNode ID=0x00000004 Parent=0x11111111 SizeRef=407,1158 Split=Y Selected=0x36DC96AB
|
||||
DockNode ID=0x00000005 Parent=0x00000004 SizeRef=407,835 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
DockNode ID=0x00000006 Parent=0x00000004 SizeRef=407,321 HiddenTabBar=1 Selected=0x3FC1A724
|
||||
|
||||
|
@ -1,16 +1,17 @@
|
||||
engine_version: 0.1.0
|
||||
scene_name: test
|
||||
scene_hash: b3488ddfbb343e554cb1782c1b79598e15545d752cfec63be97f90c8d422aaf5
|
||||
scene_hash: beb59668150f92192118ae530ea3d931789cec7c937e2620b25516e0f88ac8a7
|
||||
format_version: 1
|
||||
objects:
|
||||
- name: Sprite Object
|
||||
position: [438, 0]
|
||||
position: [0, 0]
|
||||
layer: 0
|
||||
components:
|
||||
- type: CameraComponent
|
||||
fov: 45
|
||||
aspect: 1.76999998
|
||||
zoom: 1
|
||||
primary: true
|
||||
- type: SpriteComponent
|
||||
texture: C:\Users\spenc\OneDrive\Pictures\49555.jpg
|
||||
normalMap: ""
|
||||
@ -39,3 +40,17 @@ objects:
|
||||
texture: C:\Users\spenc\OneDrive\Pictures\49555.jpg
|
||||
normalMap: ""
|
||||
children: []
|
||||
- name: Light
|
||||
position: [-5000, -5000]
|
||||
layer: 1
|
||||
components:
|
||||
- type: LightComponent
|
||||
color:
|
||||
- 1
|
||||
- 1
|
||||
- 1
|
||||
intensity: 10
|
||||
radius: 100000000
|
||||
falloff: 0.100000001
|
||||
type: 0
|
||||
children: []
|
@ -1,9 +1,46 @@
|
||||
#version 330 core
|
||||
|
||||
in vec2 vUV;
|
||||
in vec2 vFragScreenPos;
|
||||
out vec4 FragColor;
|
||||
|
||||
uniform sampler2D uTex;
|
||||
uniform sampler2D uNormalMap;
|
||||
|
||||
void main() {
|
||||
FragColor = texture(uTex, vUV);
|
||||
uniform int uLightCount;
|
||||
uniform vec2 uLightPos[8];
|
||||
uniform vec3 uLightColor[8];
|
||||
uniform float uLightIntensity[8];
|
||||
uniform float uLightRadius[8];
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 texColor = texture(uTex, vUV);
|
||||
if (texColor.a < 0.1)
|
||||
discard;
|
||||
|
||||
vec3 normal = texture(uNormalMap, vUV).rgb * 2.0 - 1.0;
|
||||
normal = normalize(normal);
|
||||
|
||||
vec3 finalLight = vec3(0.0);
|
||||
|
||||
for (int i = 0; i < uLightCount; ++i)
|
||||
{
|
||||
vec2 lightVec = uLightPos[i] - vFragScreenPos;
|
||||
float dist = length(lightVec);
|
||||
|
||||
if (dist < uLightRadius[i])
|
||||
{
|
||||
vec2 lightDir2D = normalize(lightVec);
|
||||
vec3 lightDir = normalize(vec3(lightDir2D, 1.0)); // pseudo-3D
|
||||
|
||||
float attenuation = 1.0 - dist / uLightRadius[i];
|
||||
float diff = max(dot(normal, lightDir), 0.0);
|
||||
vec3 light = uLightColor[i] * diff * attenuation * uLightIntensity[i];
|
||||
finalLight += light;
|
||||
}
|
||||
}
|
||||
|
||||
vec3 result = texColor.rgb * finalLight;
|
||||
FragColor = vec4(result, texColor.a);
|
||||
}
|
@ -1,16 +1,25 @@
|
||||
#version 330 core
|
||||
|
||||
layout(location = 0) in vec2 aPos;
|
||||
layout(location = 1) in vec2 aUV;
|
||||
|
||||
out vec2 vUV;
|
||||
out vec2 vFragScreenPos;
|
||||
|
||||
uniform vec2 uPos;
|
||||
uniform vec2 uSize;
|
||||
uniform vec2 uScreen;
|
||||
|
||||
out vec2 vUV;
|
||||
void main()
|
||||
{
|
||||
vUV = aUV;
|
||||
|
||||
void main() {
|
||||
vec2 scaled = aPos * uSize + uPos;
|
||||
vec2 ndc = scaled / uScreen * 2.0 - 1.0;
|
||||
gl_Position = vec4(ndc.x, -ndc.y, 0.0, 1.0);
|
||||
vUV = vec2(aUV.x, 1.0 - aUV.y);
|
||||
vec2 worldPos = uPos + aPos * uSize;
|
||||
|
||||
vFragScreenPos = worldPos;
|
||||
|
||||
vec2 ndc = (worldPos / uScreen) * 2.0 - 1.0;
|
||||
ndc.y *= -1.0;
|
||||
|
||||
gl_Position = vec4(ndc, 0.0, 1.0);
|
||||
}
|
||||
|
@ -1,31 +0,0 @@
|
||||
[Window][WindowOverViewport_11111111]
|
||||
Pos=0,19
|
||||
Size=1280,701
|
||||
Collapsed=0
|
||||
|
||||
[Window][Debug##Default]
|
||||
Pos=60,60
|
||||
Size=400,400
|
||||
Collapsed=0
|
||||
|
||||
[Window][Scene Tree]
|
||||
Pos=60,60
|
||||
Size=128,48
|
||||
Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=1123,19
|
||||
Size=157,701
|
||||
Collapsed=0
|
||||
DockId=0x00000002,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=60,60
|
||||
Size=32,35
|
||||
Collapsed=0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x11111111 SizeRef=1121,701 CentralNode=1
|
||||
DockNode ID=0x00000002 Parent=0x11111111 SizeRef=157,701 Selected=0x36DC96AB
|
||||
|
32
src/src/Components/LightComponent.cpp
Normal file
32
src/src/Components/LightComponent.cpp
Normal file
@ -0,0 +1,32 @@
|
||||
#include "LightComponent.h"
|
||||
|
||||
LightComponent::LightComponent(Object* owner)
|
||||
: Component(owner) {}
|
||||
|
||||
void LightComponent::Save(YAML::Emitter& out) const
|
||||
{
|
||||
out << YAML::BeginMap;
|
||||
out << YAML::Key << "type" << YAML::Value << "LightComponent";
|
||||
out << YAML::Key << "color" << YAML::Value << std::vector<float>{ m_Color.r, m_Color.g, m_Color.b };
|
||||
out << YAML::Key << "intensity" << YAML::Value << m_Intensity;
|
||||
out << YAML::Key << "radius" << YAML::Value << m_Radius;
|
||||
out << YAML::Key << "falloff" << YAML::Value << m_Falloff;
|
||||
out << YAML::Key << "type" << YAML::Value << m_type;
|
||||
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
void LightComponent::Load(const YAML::Node& node)
|
||||
{
|
||||
if (node["color"])
|
||||
{
|
||||
auto vec = node["color"].as<std::vector<float>>();
|
||||
if (vec.size() == 3)
|
||||
m_Color = glm::vec3(vec[0], vec[1], vec[2]);
|
||||
}
|
||||
if (node["intensity"]) m_Intensity = node["intensity"].as<float>();
|
||||
if (node["radius"]) m_Radius = node["radius"].as<float>();
|
||||
if (node["falloff"]) m_Falloff = node["falloff"].as<float>();
|
||||
if (node["light_type"])m_type = node["light_type"].as<int>();
|
||||
|
||||
}
|
41
src/src/Components/LightComponent.h
Normal file
41
src/src/Components/LightComponent.h
Normal file
@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
#include "Component.h"
|
||||
#include <glm/glm.hpp>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
|
||||
|
||||
|
||||
class LightComponent : public Component
|
||||
{
|
||||
public:
|
||||
|
||||
|
||||
|
||||
LightComponent(Object* owner);
|
||||
|
||||
std::string GetName() const override { return "LightComponent"; }
|
||||
|
||||
void Save(YAML::Emitter& out) const override;
|
||||
void Load(const YAML::Node& node) override;
|
||||
|
||||
void SetColor(const glm::vec3& color) { m_Color = color; }
|
||||
void SetIntensity(float intensity) { m_Intensity = intensity; }
|
||||
void SetRadius(float radius) { m_Radius = radius; }
|
||||
void SetFalloff(float falloff) { m_Falloff = falloff; }
|
||||
void SetType(int type) { m_type = type; }
|
||||
|
||||
|
||||
glm::vec3 GetColor() const { return m_Color; }
|
||||
float GetIntensity() const { return m_Intensity; }
|
||||
float GetRadius() const { return m_Radius; }
|
||||
float GetFalloff() const { return m_Falloff; }
|
||||
int GetType() const { return m_type; }
|
||||
|
||||
|
||||
private:
|
||||
glm::vec3 m_Color {1.0f, 1.0f, 1.0f};
|
||||
float m_Intensity = 1.0f;
|
||||
float m_Radius = 300.0f;
|
||||
float m_Falloff = 1.0f;
|
||||
int m_type = 0;
|
||||
};
|
@ -3,15 +3,22 @@
|
||||
#include <stb_image.h>
|
||||
#include <GL/glew.h>
|
||||
#include <iostream>
|
||||
#include "../utils/Logging.h"
|
||||
#include "../utils/utils.h"
|
||||
|
||||
|
||||
SpriteComponent::SpriteComponent(Object* owner) : Component(owner) {}
|
||||
|
||||
unsigned int SpriteComponent::LoadTexture(const std::string& path) {
|
||||
int w, h, channels;
|
||||
stbi_set_flip_vertically_on_load(1);
|
||||
std::string filename = GetFilenameFromPath(path);
|
||||
stbi_set_flip_vertically_on_load(false);
|
||||
|
||||
unsigned char* data = stbi_load(path.c_str(), &w, &h, &channels, 4);
|
||||
if (!data) {
|
||||
std::cerr << "Failed to load image: " << path << "\nReason: " << stbi_failure_reason() << std::endl;
|
||||
Logger::LogError("Failed to load asset: '%s': %s", filename.c_str(), stbi_failure_reason());
|
||||
|
||||
texture_loaded = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -30,18 +37,29 @@ unsigned int SpriteComponent::LoadTexture(const std::string& path) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
||||
stbi_image_free(data);
|
||||
texture_loaded = true;
|
||||
Logger::LogDebug("Loaded Asset: %s, %d", filename.c_str(), id);
|
||||
textureID = id;
|
||||
return id;
|
||||
}
|
||||
|
||||
bool SpriteComponent::HasTexture()
|
||||
{
|
||||
return texture_loaded;
|
||||
}
|
||||
|
||||
|
||||
void SpriteComponent::SetTexture(const std::string& path) {
|
||||
if (path.empty()) return;
|
||||
texturePath = path;
|
||||
textureID = LoadTexture(path);
|
||||
LoadTexture(path);
|
||||
}
|
||||
|
||||
|
||||
void SpriteComponent::SetNormalMap(const std::string& path) {
|
||||
if (path.empty()) return;
|
||||
normalMapPath = path;
|
||||
normalMapID = LoadTexture(path);
|
||||
LoadTexture(path);
|
||||
}
|
||||
|
||||
unsigned int SpriteComponent::GetTextureID() const {
|
||||
@ -69,6 +87,10 @@ void SpriteComponent::Save(YAML::Emitter& out) const {
|
||||
}
|
||||
|
||||
void SpriteComponent::Load(const YAML::Node& node) {
|
||||
if (node["texture"]) SetTexture(node["texture"].as<std::string>());
|
||||
if (node["normalMap"]) SetNormalMap(node["normalMap"].as<std::string>());
|
||||
if (node["texture"] && !node["texture"].as<std::string>().empty())
|
||||
SetTexture(node["texture"].as<std::string>());
|
||||
|
||||
if (node["normalMap"] && !node["normalMap"].as<std::string>().empty())
|
||||
SetNormalMap(node["normalMap"].as<std::string>());
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,10 @@ public:
|
||||
std::string GetTexturePath() const;
|
||||
std::string GetNormalMapPath() const;
|
||||
|
||||
bool HasTexture();
|
||||
|
||||
|
||||
|
||||
virtual glm::vec2 GetSize() const { return size; }
|
||||
|
||||
virtual std::string GetName() const override { return "SpriteComponent"; }
|
||||
@ -33,6 +37,6 @@ private:
|
||||
std::string normalMapPath;
|
||||
unsigned int textureID = 0;
|
||||
unsigned int normalMapID = 0;
|
||||
|
||||
bool texture_loaded = false;
|
||||
unsigned int LoadTexture(const std::string& path);
|
||||
};
|
||||
|
@ -3,8 +3,10 @@
|
||||
#include "Renderer.h"
|
||||
#include "components/SpriteComponent.h"
|
||||
#include "components/CameraComponent.h"
|
||||
#include "components/LightComponent.h"
|
||||
|
||||
#include "utils/FileDialog.h"
|
||||
#include "utils/Logging.h"
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <GLFW/glfw3.h>
|
||||
@ -21,7 +23,6 @@
|
||||
#include <filesystem>
|
||||
#include <iostream>
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
#include <commdlg.h>
|
||||
#include <openssl/sha.h>
|
||||
@ -32,7 +33,6 @@ static bool playing = false;
|
||||
|
||||
static glm::vec2 cameraPos = {0, 0};
|
||||
static float cameraZoom = 1.0f;
|
||||
static bool isDragging = false;
|
||||
static ImVec2 lastMousePos = {};
|
||||
|
||||
GLFWwindow *window = nullptr;
|
||||
@ -47,6 +47,43 @@ Engine::~Engine()
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
void Engine::ShowDebugOverlay(float deltaTime)
|
||||
{
|
||||
static std::vector<float> fpsHistory;
|
||||
static const int maxHistory = 100;
|
||||
static float timer = 0;
|
||||
float fps = 1.0f / deltaTime;
|
||||
if (fpsHistory.size() >= maxHistory)
|
||||
fpsHistory.erase(fpsHistory.begin());
|
||||
if (timer >= 0.05)
|
||||
{
|
||||
timer = 0;
|
||||
fpsHistory.push_back(fps);
|
||||
}
|
||||
timer += deltaTime;
|
||||
|
||||
ImGui::Begin("Performance Info", nullptr,
|
||||
ImGuiWindowFlags_NoDecoration);
|
||||
|
||||
ImGui::TextColored(ImVec4(0.3f, 1.0f, 0.3f, 1.0f), "Performance");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("FPS: %.1f", fps);
|
||||
ImGui::Text("Delta Time: %.4f s", deltaTime);
|
||||
ImGui::Text("Frame Time: %.2f ms", deltaTime * 1000.0f);
|
||||
ImGui::PlotLines("##FPS", fpsHistory.data(), fpsHistory.size(), 0, "FPS History", 0.0f, 144.0f, ImVec2(-1, 50));
|
||||
|
||||
ImGui::Spacing();
|
||||
ImGui::TextColored(ImVec4(0.4f, 0.7f, 1.0f, 1.0f), "Renderer");
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Draw Calls: %d", Renderer::GetDrawCallCount());
|
||||
ImGui::Text("Reserved Draws: %d", m_Reserved_draws);
|
||||
|
||||
ImGui::Text("Camera Zoom: %.2f", cameraZoom);
|
||||
ImGui::Text("Camera Pos: (%.1f, %.1f)", cameraPos.x, cameraPos.y);
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
void Engine::Init()
|
||||
{
|
||||
glfwInit();
|
||||
@ -54,9 +91,9 @@ void Engine::Init()
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
|
||||
window = glfwCreateWindow(1280, 720, "2D Editor", nullptr, nullptr);
|
||||
window = glfwCreateWindow(1280, 720, "Create Editor", nullptr, nullptr);
|
||||
glfwMakeContextCurrent(window);
|
||||
glfwSwapInterval(1);
|
||||
glfwSwapInterval(0); // No VSync
|
||||
glewInit();
|
||||
|
||||
IMGUI_CHECKVERSION();
|
||||
@ -66,13 +103,137 @@ void Engine::Init()
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
m_Reserved_draws = 0;
|
||||
|
||||
Renderer::Init();
|
||||
|
||||
auto obj = std::make_shared<Object>("Sprite Object");
|
||||
auto obj = std::make_shared<Object>("Hello, Create");
|
||||
|
||||
objects.push_back(obj);
|
||||
selected = obj;
|
||||
Logger::LogInfo("Initialized Engine");
|
||||
}
|
||||
void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
{
|
||||
ImGui::Begin("Inspector");
|
||||
|
||||
if (!selected)
|
||||
{
|
||||
ImGui::Text("No object selected.");
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
// Static buffer and last-selected tracking
|
||||
static char nameBuffer[128] = "";
|
||||
static std::shared_ptr<Object> lastSelected = nullptr;
|
||||
|
||||
// If a new object is selected, refresh buffer
|
||||
if (selected != lastSelected)
|
||||
{
|
||||
strncpy(nameBuffer, selected->GetName().c_str(), sizeof(nameBuffer));
|
||||
nameBuffer[sizeof(nameBuffer) - 1] = '\0'; // null terminate
|
||||
lastSelected = selected;
|
||||
}
|
||||
|
||||
if (ImGui::InputText("Name", nameBuffer, sizeof(nameBuffer)))
|
||||
selected->SetName(nameBuffer);
|
||||
|
||||
glm::vec2 pos = selected->GetLocalPosition();
|
||||
if (ImGui::DragFloat2("Position", &pos.x))
|
||||
selected->SetLocalPosition(pos);
|
||||
|
||||
ImGui::InputInt("Layer", &selected->layer);
|
||||
|
||||
ImGui::SeparatorText("Add Components");
|
||||
|
||||
if (ImGui::Button("Add SpriteComponent"))
|
||||
{
|
||||
if (!selected->GetComponent<SpriteComponent>())
|
||||
selected->AddComponent<SpriteComponent>();
|
||||
}
|
||||
if (ImGui::Button("Add CameraComponent"))
|
||||
{
|
||||
if (!selected->GetComponent<CameraComponent>())
|
||||
selected->AddComponent<CameraComponent>();
|
||||
}
|
||||
if (ImGui::Button("Add LightComponent"))
|
||||
{
|
||||
if (!selected->GetComponent<LightComponent>())
|
||||
selected->AddComponent<LightComponent>();
|
||||
}
|
||||
|
||||
// Sprite UI...
|
||||
if (auto sprite = selected->GetComponent<SpriteComponent>())
|
||||
{
|
||||
ImGui::SeparatorText("Sprite Component");
|
||||
std::string tex = sprite->GetTexturePath();
|
||||
std::string norm = sprite->GetNormalMapPath();
|
||||
|
||||
ImGui::Text("Texture: %s", tex.c_str());
|
||||
if (ImGui::Button("Load Texture"))
|
||||
{
|
||||
auto path = OpenFileDialog(FileDialogType::Images);
|
||||
if (!path.empty())
|
||||
sprite->SetTexture(path);
|
||||
}
|
||||
|
||||
ImGui::Text("Normal Map: %s", norm.c_str());
|
||||
if (ImGui::Button("Load Normal Map"))
|
||||
{
|
||||
auto path = OpenFileDialog(FileDialogType::Images);
|
||||
if (!path.empty())
|
||||
sprite->SetNormalMap(path);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Remove SpriteComponent"))
|
||||
selected->RemoveComponent<SpriteComponent>();
|
||||
}
|
||||
|
||||
// Camera UI...
|
||||
if (auto cam = selected->GetComponent<CameraComponent>())
|
||||
{
|
||||
ImGui::SeparatorText("Camera Component");
|
||||
|
||||
float fov = cam->GetFOV();
|
||||
float aspect = cam->GetAspect();
|
||||
float zoom = cam->GetZoom();
|
||||
|
||||
if (ImGui::DragFloat("FOV", &fov, 0.1f, 1.0f, 179.0f)) cam->SetFOV(fov);
|
||||
if (ImGui::DragFloat("Aspect", &aspect, 0.01f, 0.1f, 5.0f)) cam->SetAspect(aspect);
|
||||
if (ImGui::DragFloat("Zoom", &zoom, 0.1f, 0.1f, 10.0f)) cam->SetZoom(zoom);
|
||||
|
||||
if (ImGui::Button("Remove CameraComponent"))
|
||||
selected->RemoveComponent<CameraComponent>();
|
||||
}
|
||||
|
||||
// Light UI...
|
||||
if (auto light = selected->GetComponent<LightComponent>())
|
||||
{
|
||||
ImGui::SeparatorText("Light Component");
|
||||
|
||||
glm::vec3 color = light->GetColor();
|
||||
float intensity = light->GetIntensity();
|
||||
float radius = light->GetRadius();
|
||||
float falloff = light->GetFalloff();
|
||||
int type = light->GetType();
|
||||
|
||||
if (ImGui::ColorEdit3("Color", &color.x)) light->SetColor(color);
|
||||
if (ImGui::DragFloat("Intensity", &intensity, 0.05f, 0.0f, 10.0f)) light->SetIntensity(intensity);
|
||||
if (ImGui::DragFloat("Radius", &radius, 1.0f, 10.0f, 1000.0f)) light->SetRadius(radius);
|
||||
if (ImGui::DragFloat("Falloff", &falloff, 0.05f, 0.1f, 5.0f)) light->SetFalloff(falloff);
|
||||
|
||||
//const char* types[] = { "Point", "Directional" };
|
||||
//if (ImGui::Combo("Type", &type, types, IM_ARRAYSIZE(types)))
|
||||
// light->SetType(type);
|
||||
|
||||
if (ImGui::Button("Remove LightComponent"))
|
||||
selected->RemoveComponent<LightComponent>();
|
||||
}
|
||||
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
|
||||
void Engine::Run()
|
||||
{
|
||||
@ -85,6 +246,14 @@ void Engine::Run()
|
||||
ImGui::NewFrame();
|
||||
ImGui::DockSpaceOverViewport(ImGui::GetMainViewport()->ID);
|
||||
|
||||
float currentTime = glfwGetTime();
|
||||
static float lastTime = currentTime;
|
||||
float deltaTime = currentTime - lastTime;
|
||||
lastTime = currentTime;
|
||||
|
||||
ShowDebugOverlay(deltaTime);
|
||||
Logger::Draw();
|
||||
|
||||
if (ImGui::BeginMainMenuBar())
|
||||
{
|
||||
if (ImGui::Button(playing ? "Stop" : "Play"))
|
||||
@ -141,93 +310,7 @@ void Engine::Run()
|
||||
|
||||
ImGui::End();
|
||||
|
||||
ImGui::Begin("Inspector");
|
||||
if (selected)
|
||||
{
|
||||
char buffer[128];
|
||||
strcpy(buffer, selected->GetName().c_str());
|
||||
if (ImGui::InputText("Name", buffer, sizeof(buffer)))
|
||||
selected->SetName(buffer);
|
||||
|
||||
glm::vec2 pos = selected->GetLocalPosition();
|
||||
if (ImGui::DragFloat2("Position", &pos.x))
|
||||
selected->SetLocalPosition(pos);
|
||||
|
||||
ImGui::InputInt("Layer", &selected->layer);
|
||||
|
||||
// Add SpriteComponent
|
||||
if (ImGui::Button("Add SpriteComponent"))
|
||||
{
|
||||
if (!selected->GetComponent<SpriteComponent>())
|
||||
selected->AddComponent<SpriteComponent>();
|
||||
}
|
||||
|
||||
// Add CameraComponent
|
||||
if (ImGui::Button("Add CameraComponent"))
|
||||
{
|
||||
if (!selected->GetComponent<CameraComponent>())
|
||||
selected->AddComponent<CameraComponent>();
|
||||
}
|
||||
|
||||
// Show SpriteComponent UI
|
||||
if (auto sprite = selected->GetComponent<SpriteComponent>())
|
||||
{
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Sprite Component");
|
||||
|
||||
std::string tex = sprite->GetTexturePath();
|
||||
std::string norm = sprite->GetNormalMapPath();
|
||||
|
||||
ImGui::Text("Texture: %s", tex.c_str());
|
||||
if (ImGui::Button("Load Texture"))
|
||||
{
|
||||
auto path = OpenFileDialog(FileDialogType::Images);
|
||||
if (!path.empty())
|
||||
sprite->SetTexture(path);
|
||||
}
|
||||
|
||||
ImGui::Text("Normal Map: %s", norm.c_str());
|
||||
if (ImGui::Button("Load Normal Map"))
|
||||
{
|
||||
auto path = OpenFileDialog(FileDialogType::Images);
|
||||
if (!path.empty())
|
||||
sprite->SetNormalMap(path);
|
||||
}
|
||||
|
||||
if (ImGui::Button("Remove SpriteComponent"))
|
||||
{
|
||||
selected->RemoveComponent<SpriteComponent>();
|
||||
}
|
||||
}
|
||||
|
||||
// Show CameraComponent UI
|
||||
if (auto cam = selected->GetComponent<CameraComponent>())
|
||||
{
|
||||
ImGui::Separator();
|
||||
ImGui::Text("Camera Component");
|
||||
|
||||
float fov = cam->GetFOV();
|
||||
float aspect = cam->GetAspect();
|
||||
float zoom = cam->GetZoom();
|
||||
|
||||
if (ImGui::DragFloat("FOV", &fov, 0.1f, 1.0f, 179.0f))
|
||||
cam->SetFOV(fov);
|
||||
if (ImGui::DragFloat("Aspect", &aspect, 0.01f, 0.1f, 5.0f))
|
||||
cam->SetAspect(aspect);
|
||||
if (ImGui::DragFloat("Zoom", &zoom, 0.1f, 0.1f, 10.0f))
|
||||
cam->SetZoom(zoom);
|
||||
|
||||
if (ImGui::Button("Remove CameraComponent"))
|
||||
{
|
||||
selected->RemoveComponent<CameraComponent>();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui::Text("No object selected.");
|
||||
}
|
||||
ImGui::End();
|
||||
DrawInspectorUI(selected);
|
||||
|
||||
// Viewport
|
||||
ImGui::Begin("Viewport", nullptr, ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse);
|
||||
@ -270,16 +353,28 @@ void Engine::Run()
|
||||
}
|
||||
|
||||
Renderer::Resize((int)size.x, (int)size.y);
|
||||
Renderer::Begin(); // assumes orthographic matrix is set up here
|
||||
Renderer::Begin();
|
||||
|
||||
std::vector<std::shared_ptr<Object>> toDraw;
|
||||
|
||||
Renderer::DrawEditorGrid(cameraPos, cameraZoom);
|
||||
toDraw.reserve(m_Reserved_draws);
|
||||
m_Reserved_draws = 0; // Reset
|
||||
|
||||
Renderer::DrawEditorGrid(cameraPos, cameraZoom);
|
||||
|
||||
std::function<void(const std::shared_ptr<Object> &)> collect = [&](const std::shared_ptr<Object> &obj)
|
||||
{
|
||||
toDraw.push_back(obj);
|
||||
m_Reserved_draws += 1;
|
||||
|
||||
if (auto light = obj->GetComponent<LightComponent>())
|
||||
{
|
||||
glm::vec2 world = obj->GetWorldPosition();
|
||||
glm::vec2 screen = (world - cameraPos) * cameraZoom + glm::vec2(Renderer::GetSize().x * 0.5f, Renderer::GetSize().y * 0.5f);
|
||||
|
||||
Renderer::AddLight(screen, light->GetColor(), light->GetIntensity(), light->GetRadius() * cameraZoom);
|
||||
}
|
||||
|
||||
for (const auto &child : obj->GetChildren())
|
||||
collect(child);
|
||||
};
|
||||
@ -289,7 +384,11 @@ void Engine::Run()
|
||||
collect(obj);
|
||||
|
||||
std::sort(toDraw.begin(), toDraw.end(), [](const auto &a, const auto &b)
|
||||
{ return a->layer < b->layer; });
|
||||
{
|
||||
if (a->layer != b->layer)
|
||||
return a->layer < b->layer;
|
||||
|
||||
return a->GetWorldPosition().y < b->GetWorldPosition().y; });
|
||||
|
||||
for (const auto &obj : toDraw)
|
||||
{
|
||||
@ -477,19 +576,19 @@ void Engine::LoadScene(const std::string &path)
|
||||
|
||||
if (!root["engine_version"] || !root["format_version"] || !root["scene_name"])
|
||||
{
|
||||
std::cerr << "[LoadScene] Missing required metadata!\n";
|
||||
Logger::LogError("[LoadScene] Missing required metadata!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (root["engine_version"].as<std::string>() != "0.1.0")
|
||||
{
|
||||
std::cerr << "[LoadScene] Version mismatch! Expected 0.1.0, got " << root["engine_version"].as<std::string>() << "\n";
|
||||
Logger::LogError("[LoadScene] Version mismatch! Expected 0.1.0, got %s", root["engine_version"].as<std::string>().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (!VerifySceneHash(root))
|
||||
{
|
||||
std::cerr << "[LoadScene] Scene hash does not match! File may be corrupted or tampered.\n";
|
||||
Logger::LogWarning("[LoadScene] Scene hash does not match! File may be corrupted or tampered.");
|
||||
}
|
||||
|
||||
objects.clear();
|
||||
@ -501,7 +600,7 @@ void Engine::LoadScene(const std::string &path)
|
||||
objects.push_back(obj);
|
||||
}
|
||||
|
||||
std::cout << "[LoadScene] Loaded scene: " << root["scene_name"].as<std::string>() << "\n";
|
||||
Logger::LogInfo("[LoadScene] Loaded scene: %s", root["scene_name"].as<std::string>().c_str());
|
||||
}
|
||||
|
||||
void Engine::Shutdown()
|
||||
|
@ -20,5 +20,8 @@ private:
|
||||
void DrawObjectNode(const std::shared_ptr<Object>& obj); // make sure this matches Engine.cpp
|
||||
void SaveScene(const std::string& path);
|
||||
void LoadScene(const std::string& path);
|
||||
void ShowDebugOverlay(float deltaTime);
|
||||
|
||||
|
||||
int m_Reserved_draws;
|
||||
};
|
||||
|
@ -1,7 +1,10 @@
|
||||
#include "Object.h"
|
||||
|
||||
#include "../Components/Component.h"
|
||||
#include "../Components/SpriteComponent.h"
|
||||
#include "../Components/CameraComponent.h"
|
||||
#include "../Components/LightComponent.h"
|
||||
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@ -84,6 +87,9 @@ void Object::Load(const YAML::Node& node) {
|
||||
} else if (type == "CameraComponent") {
|
||||
auto comp = AddComponent<CameraComponent>();
|
||||
comp->Load(compNode);
|
||||
} else if (type == "LightComponent") {
|
||||
auto comp = AddComponent<LightComponent>();
|
||||
comp->Load(compNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include "Renderer.h"
|
||||
#include "Components/SpriteComponent.h"
|
||||
#include "utils/Shader.h"
|
||||
#include "utils/Logging.h"
|
||||
|
||||
|
||||
#include <GL/glew.h>
|
||||
#include <glm/glm.hpp>
|
||||
@ -15,6 +17,12 @@ GLuint Renderer::quadVAO = 0;
|
||||
GLuint Renderer::quadVBO = 0;
|
||||
int Renderer::width = 1280;
|
||||
int Renderer::height = 720;
|
||||
int Renderer::s_DrawCalls = 0;
|
||||
std::vector<Light> Renderer::s_Lights;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void Renderer::InitQuad() {
|
||||
float vertices[] = {
|
||||
@ -64,6 +72,8 @@ void Renderer::Init() {
|
||||
InitQuad();
|
||||
|
||||
spriteShader.LoadFromFile("src/assets/shaders/sprite.vert", "src/assets/shaders/sprite.frag");
|
||||
|
||||
s_DrawCalls = 0;
|
||||
}
|
||||
|
||||
void Renderer::Resize(int w, int h) {
|
||||
@ -86,6 +96,8 @@ void Renderer::Begin() {
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
s_DrawCalls = 0;
|
||||
ClearLights();
|
||||
}
|
||||
|
||||
void Renderer::End() {
|
||||
@ -108,25 +120,66 @@ void Renderer::End() {
|
||||
//}
|
||||
|
||||
|
||||
void Renderer::ClearLights() {
|
||||
s_Lights.clear();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Renderer::AddLight(const glm::vec2& screenPos, const glm::vec3& color, float intensity, float radius) {
|
||||
if (s_Lights.size() >= 8) return;
|
||||
s_Lights.push_back({screenPos, color, intensity, radius});
|
||||
}
|
||||
|
||||
|
||||
void Renderer::DrawSprite(SpriteComponent* sprite, const glm::vec2& pos, float zoom, glm::vec2& CameraPos) {
|
||||
if (!sprite || sprite->GetTextureID() == 0) return;
|
||||
if (!sprite->HasTexture()) {
|
||||
Logger::LogWarning("Tried to draw sprite with no texture");
|
||||
return;
|
||||
}
|
||||
|
||||
spriteShader.Use();
|
||||
|
||||
glm::vec2 size = sprite->GetSize();
|
||||
glm::vec2 screenPos = (pos - CameraPos) * zoom + glm::vec2(size.x / 2, size.y / 2);
|
||||
glm::vec2 screenPos = (pos - CameraPos) * zoom + glm::vec2(width, height) * 0.5f - (size * zoom * 0.5f);
|
||||
|
||||
spriteShader.SetVec2("uPos", screenPos);
|
||||
spriteShader.SetVec2("uSize", size*zoom);
|
||||
spriteShader.SetVec2("uSize", size * zoom);
|
||||
spriteShader.SetVec2("uScreen", glm::vec2(width, height));
|
||||
|
||||
spriteShader.SetInt("uLightCount", static_cast<int>(s_Lights.size()));
|
||||
for (size_t i = 0; i < s_Lights.size(); ++i) {
|
||||
spriteShader.SetVec2(("uLightPos[" + std::to_string(i) + "]").c_str(), s_Lights[i].screenPos);
|
||||
spriteShader.SetVec3(("uLightColor[" + std::to_string(i) + "]").c_str(), s_Lights[i].color);
|
||||
spriteShader.SetFloat(("uLightIntensity[" + std::to_string(i) + "]").c_str(), s_Lights[i].intensity);
|
||||
spriteShader.SetFloat(("uLightRadius[" + std::to_string(i) + "]").c_str(), s_Lights[i].radius);
|
||||
}
|
||||
|
||||
spriteShader.SetInt("uTex", 0);
|
||||
spriteShader.SetInt("uNormalMap", 1);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
glBindTexture(GL_TEXTURE_2D, sprite->GetTextureID());
|
||||
|
||||
if (sprite->GetNormalMapID()) {
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, sprite->GetNormalMapID());
|
||||
}
|
||||
|
||||
glBindVertexArray(quadVAO);
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
glBindVertexArray(0);
|
||||
s_DrawCalls++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int Renderer::GetDrawCallCount()
|
||||
{
|
||||
return s_DrawCalls;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,9 +1,18 @@
|
||||
#pragma once
|
||||
#include <GL/glew.h>
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
|
||||
class SpriteComponent;
|
||||
|
||||
struct Light {
|
||||
glm::vec2 screenPos;
|
||||
glm::vec3 color;
|
||||
float intensity;
|
||||
float radius;
|
||||
};
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
static void Init();
|
||||
@ -11,14 +20,18 @@ public:
|
||||
static void Begin();
|
||||
static void End();
|
||||
static void DrawSprite(SpriteComponent* sprite, const glm::vec2& pos, float zoom, glm::vec2& CameraPos);
|
||||
static void AddLight(const glm::vec2& screenPos, const glm::vec3& color, float intensity, float radius);
|
||||
static void ClearLights();
|
||||
static void DrawEditorGrid(const glm::vec2& cameraPos, float zoom);
|
||||
static GLuint GetRenderTexture();
|
||||
static glm::ivec2 GetSize();
|
||||
static int GetDrawCallCount();
|
||||
|
||||
private:
|
||||
static std::vector<Light> s_Lights;
|
||||
static GLuint fbo, textureColorBuffer, rbo;
|
||||
static int width, height;
|
||||
|
||||
static int s_DrawCalls;
|
||||
static GLuint shader, quadVAO, quadVBO;
|
||||
static void InitQuad();
|
||||
static GLuint LoadShader(const char* vertexSrc, const char* fragmentSrc);
|
||||
|
141
src/src/utils/Logging.cpp
Normal file
141
src/src/utils/Logging.cpp
Normal file
@ -0,0 +1,141 @@
|
||||
#include "Logging.h"
|
||||
#include <imgui.h>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
|
||||
std::vector<Logger::LogMessage> Logger::s_Messages;
|
||||
bool Logger::s_AutoScroll = true;
|
||||
bool Logger::s_ShowInfo = true;
|
||||
bool Logger::s_ShowWarning = true;
|
||||
bool Logger::s_ShowError = true;
|
||||
bool Logger::s_ShowDebug = true;
|
||||
|
||||
const char* Logger::ToString(Level level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case Info: return "Info";
|
||||
case Warning: return "Warning";
|
||||
case Error: return "Error";
|
||||
case Debug: return "Debug";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
const char* Logger::GetAnsiColor(Level level)
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case Info: return "\033[0;37m"; // Gray
|
||||
case Warning: return "\033[1;33m"; // Yellow
|
||||
case Error: return "\033[1;31m"; // Red
|
||||
case Debug: return "\033[1;36m"; // Cyan
|
||||
default: return "\033[0m";
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::Log(Level level, const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
LogVA(level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::LogVA(Level level, const char* fmt, va_list args)
|
||||
{
|
||||
char buffer[1024];
|
||||
vsnprintf(buffer, sizeof(buffer), fmt, args);
|
||||
s_Messages.push_back({ buffer, level });
|
||||
|
||||
std::cout << GetAnsiColor(level)
|
||||
<< "[Logger][" << ToString(level) << "] "
|
||||
<< buffer << "\033[0m" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
void Logger::LogInfo(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
LogVA(Info, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::LogWarning(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
LogVA(Warning, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::LogError(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
LogVA(Error, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::LogDebug(const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
LogVA(Debug, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void Logger::Clear()
|
||||
{
|
||||
s_Messages.clear();
|
||||
}
|
||||
|
||||
void Logger::Draw(const char* title)
|
||||
{
|
||||
ImGui::Begin(title);
|
||||
|
||||
if (ImGui::Button("Clear")) Clear();
|
||||
ImGui::SameLine(); ImGui::Checkbox("Auto-scroll", &s_AutoScroll);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::Checkbox("Info", &s_ShowInfo); ImGui::SameLine();
|
||||
ImGui::Checkbox("Warning", &s_ShowWarning); ImGui::SameLine();
|
||||
ImGui::Checkbox("Error", &s_ShowError); ImGui::SameLine();
|
||||
ImGui::Checkbox("Debug", &s_ShowDebug);
|
||||
ImGui::Separator();
|
||||
|
||||
ImGui::BeginChild("LogMessages");
|
||||
|
||||
for (const auto& msg : s_Messages)
|
||||
{
|
||||
if ((msg.level == Info && !s_ShowInfo) ||
|
||||
(msg.level == Warning && !s_ShowWarning) ||
|
||||
(msg.level == Error && !s_ShowError) ||
|
||||
(msg.level == Debug && !s_ShowDebug))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
ImVec4 color;
|
||||
switch (msg.level)
|
||||
{
|
||||
case Info: color = ImVec4(0.8f, 0.8f, 0.8f, 1.0f); break;
|
||||
case Warning: color = ImVec4(1.0f, 0.85f, 0.3f, 1.0f); break;
|
||||
case Error: color = ImVec4(1.0f, 0.3f, 0.3f, 1.0f); break;
|
||||
case Debug: color = ImVec4(0.3f, 0.9f, 1.0f, 1.0f); break;
|
||||
default: color = ImVec4(1, 1, 1, 1); break;
|
||||
}
|
||||
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::Text("[%s] %s", ToString(msg.level), msg.text.c_str());
|
||||
ImGui::PopStyleColor();
|
||||
}
|
||||
|
||||
if (s_AutoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY())
|
||||
ImGui::SetScrollHereY(1.0f);
|
||||
|
||||
ImGui::EndChild();
|
||||
ImGui::End();
|
||||
}
|
43
src/src/utils/Logging.h
Normal file
43
src/src/utils/Logging.h
Normal file
@ -0,0 +1,43 @@
|
||||
#pragma once
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
|
||||
class Logger
|
||||
{
|
||||
public:
|
||||
enum Level
|
||||
{
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
Debug
|
||||
};
|
||||
static void Log(Level level, const char* fmt, ...);
|
||||
static void LogVA(Level level, const char* fmt, va_list args);
|
||||
|
||||
static void LogInfo(const char* fmt, ...);
|
||||
static void LogWarning(const char* fmt, ...);
|
||||
static void LogError(const char* fmt, ...);
|
||||
static void LogDebug(const char* fmt, ...);
|
||||
|
||||
static void Clear();
|
||||
static void Draw(const char* title = "Console");
|
||||
|
||||
private:
|
||||
struct LogMessage
|
||||
{
|
||||
std::string text;
|
||||
Level level;
|
||||
};
|
||||
|
||||
static std::vector<LogMessage> s_Messages;
|
||||
static bool s_AutoScroll;
|
||||
static bool s_ShowInfo;
|
||||
static bool s_ShowWarning;
|
||||
static bool s_ShowError;
|
||||
static bool s_ShowDebug;
|
||||
|
||||
static const char* ToString(Level level);
|
||||
static const char* GetAnsiColor(Level level);
|
||||
};
|
14
src/src/utils/utils.cpp
Normal file
14
src/src/utils/utils.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "utils.h"
|
||||
|
||||
std::string GetFilenameFromPath(const std::string& path)
|
||||
{
|
||||
// Find the last slash or backslash
|
||||
size_t lastSlash = path.find_last_of("/\\");
|
||||
std::string filename = (lastSlash == std::string::npos) ? path : path.substr(lastSlash + 1);
|
||||
|
||||
// Strip trailing slashes (if any)
|
||||
while (!filename.empty() && (filename.back() == '/' || filename.back() == '\\'))
|
||||
filename.pop_back();
|
||||
|
||||
return filename;
|
||||
}
|
4
src/src/utils/utils.h
Normal file
4
src/src/utils/utils.h
Normal file
@ -0,0 +1,4 @@
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
std::string GetFilenameFromPath(const std::string& path);
|
Loading…
Reference in New Issue
Block a user