Added Particles ish, untested
This commit is contained in:
parent
a5fd89168b
commit
549dac776a
34
imgui.ini
34
imgui.ini
@ -10,40 +10,40 @@ Collapsed=1
|
||||
|
||||
[Window][WindowOverViewport_11111111]
|
||||
Pos=0,19
|
||||
Size=1280,701
|
||||
Size=1920,1158
|
||||
Collapsed=0
|
||||
|
||||
[Window][Inspector]
|
||||
Pos=0,421
|
||||
Size=342,299
|
||||
Pos=0,683
|
||||
Size=342,494
|
||||
Collapsed=0
|
||||
DockId=0x0000000A,0
|
||||
|
||||
[Window][Scene Tree]
|
||||
Pos=0,19
|
||||
Size=342,400
|
||||
Size=342,662
|
||||
Collapsed=0
|
||||
DockId=0x00000009,0
|
||||
|
||||
[Window][Viewport]
|
||||
Pos=344,19
|
||||
Size=936,78
|
||||
Size=1576,535
|
||||
Collapsed=0
|
||||
DockId=0x0000000B,0
|
||||
|
||||
[Window][##MainMenuBar]
|
||||
Size=1280,19
|
||||
Size=1920,19
|
||||
Collapsed=0
|
||||
|
||||
[Window][Performance Info]
|
||||
Pos=1083,383
|
||||
Size=197,118
|
||||
Pos=1588,840
|
||||
Size=332,118
|
||||
Collapsed=0
|
||||
DockId=0x00000003,0
|
||||
|
||||
[Window][Console]
|
||||
Pos=344,383
|
||||
Size=363,337
|
||||
Pos=344,840
|
||||
Size=612,337
|
||||
Collapsed=0
|
||||
DockId=0x0000000D,0
|
||||
|
||||
@ -54,8 +54,8 @@ Collapsed=0
|
||||
DockId=0x0000000B,1
|
||||
|
||||
[Window][Profiler]
|
||||
Pos=344,99
|
||||
Size=936,282
|
||||
Pos=344,556
|
||||
Size=1576,282
|
||||
Collapsed=0
|
||||
DockId=0x0000000C,0
|
||||
|
||||
@ -78,19 +78,19 @@ Collapsed=0
|
||||
DockId=0x00000005,1
|
||||
|
||||
[Window][Color Correction]
|
||||
Pos=1083,503
|
||||
Size=197,217
|
||||
Pos=1588,960
|
||||
Size=332,217
|
||||
Collapsed=0
|
||||
DockId=0x00000004,0
|
||||
|
||||
[Window][Asset Browser]
|
||||
Pos=709,383
|
||||
Size=372,337
|
||||
Pos=958,840
|
||||
Size=628,337
|
||||
Collapsed=0
|
||||
DockId=0x0000000E,0
|
||||
|
||||
[Docking][Data]
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X
|
||||
DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X
|
||||
DockNode ID=0x00000001 Parent=0x11111111 SizeRef=342,701 Split=Y Selected=0x12EF0F59
|
||||
DockNode ID=0x00000009 Parent=0x00000001 SizeRef=385,662 HiddenTabBar=1 Selected=0x12EF0F59
|
||||
DockNode ID=0x0000000A Parent=0x00000001 SizeRef=385,494 HiddenTabBar=1 Selected=0x36DC96AB
|
||||
|
@ -1,3 +1,2 @@
|
||||
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\core\utils\Profiler.cpp -o src\build\core\utils\Profiler.o
|
||||
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\utils\AssetLoader.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
[RUN] Executed app.exe successfully.
|
||||
[COMPILE] g++ -std=c++20 -Wall -g -Isrc/include -Isrc/include/lua -Isrc/vendor -Isrc/vendor/imgui -Isrc/vendor/box2d -IC:/msys64/mingw64/include -Isrc\vendor\imgui -IC:\msys64\mingw64\lib\libyaml-cpp.a -MMD -MP -c src\src\Engine.cpp -o src\build\Engine.o
|
||||
[LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\CameraComponent.o src\build\Components\LightComponent.o src\build\Components\ParticleComponent.o src\build\Components\PhysicsComponent.o src\build\Components\ScriptComponent.o src\build\Components\SpriteComponent.o src\build\Components\TextComonent.o src\build\Components\TilemapComponent.o src\build\core\utils\AssetLoader.o src\build\core\utils\EngineConfig.o src\build\core\utils\ExceptionHandler.o src\build\core\utils\FileDialog.o src\build\core\utils\input.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\utils.o src\build\editor\windows\AssetBrowser.o src\build\editor\windows\Inspector.o src\build\Entitys\Object.o src\build\utils\GameObjectsList.o src\build\utils\Shader.o src\build\utils\UID.o src\build\lapi.o src\build\lauxlib.o src\build\lbaselib.o src\build\lcode.o src\build\lcorolib.o src\build\lctype.o src\build\ldblib.o src\build\ldebug.o src\build\ldo.o src\build\ldump.o src\build\lfunc.o src\build\lgc.o src\build\linit.o src\build\liolib.o src\build\llex.o src\build\lmathlib.o src\build\lmem.o src\build\loadlib.o src\build\lobject.o src\build\lopcodes.o src\build\loslib.o src\build\lparser.o src\build\lstate.o src\build\lstring.o src\build\lstrlib.o src\build\ltable.o src\build\ltablib.o src\build\ltm.o src\build\lua.o src\build\luac.o src\build\lundump.o src\build\lutf8lib.o src\build\lvm.o src\build\lzio.o src\build\imgui.o src\build\imgui_demo.o src\build\imgui_draw.o src\build\imgui_impl_glfw.o src\build\imgui_impl_opengl3.o src\build\imgui_tables.o src\build\imgui_widgets.o src\build\aabb.o src\build\arena_allocator.o src\build\array.o src\build\bitset.o src\build\body.o src\build\broad_phase.o src\build\constraint_graph.o src\build\contact.o src\build\contact_solver.o src\build\core.o src\build\distance.o src\build\distance_joint.o src\build\dynamic_tree.o src\build\geometry.o src\build\hull.o src\build\id_pool.o src\build\island.o src\build\joint.o src\build\manifold.o src\build\math_functions.o src\build\motor_joint.o src\build\mouse_joint.o src\build\mover.o src\build\prismatic_joint.o src\build\revolute_joint.o src\build\sensor.o src\build\shape.o src\build\solver.o src\build\solver_set.o src\build\table.o src\build\timer.o src\build\types.o src\build\weld_joint.o src\build\wheel_joint.o src\build\world.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto
|
||||
|
12
src/assets/shaders/unlit_quad.frag
Normal file
12
src/assets/shaders/unlit_quad.frag
Normal file
@ -0,0 +1,12 @@
|
||||
#version 330 core
|
||||
|
||||
in vec4 vColor;
|
||||
out vec4 FragColor;
|
||||
|
||||
void main() {
|
||||
// Optional: kill particles with near-zero alpha (optional)
|
||||
if (vColor.a < 0.01)
|
||||
discard;
|
||||
|
||||
FragColor = vColor;
|
||||
}
|
28
src/assets/shaders/unlit_quad.vert
Normal file
28
src/assets/shaders/unlit_quad.vert
Normal file
@ -0,0 +1,28 @@
|
||||
#version 330 core
|
||||
|
||||
layout (location = 0) in vec2 aPos;
|
||||
|
||||
layout (location = 1) in vec2 iPos;
|
||||
layout (location = 2) in vec2 iSize;
|
||||
layout (location = 3) in float iRot;
|
||||
layout (location = 4) in vec4 iColor;
|
||||
|
||||
uniform vec2 uScreen;
|
||||
|
||||
out vec4 vColor;
|
||||
|
||||
void main() {
|
||||
float cosR = cos(iRot);
|
||||
float sinR = sin(iRot);
|
||||
|
||||
vec2 scaled = aPos * iSize;
|
||||
vec2 rotated = vec2(
|
||||
scaled.x * cosR - scaled.y * sinR,
|
||||
scaled.x * sinR + scaled.y * cosR
|
||||
);
|
||||
|
||||
vec2 finalPos = iPos + rotated;
|
||||
|
||||
gl_Position = vec4((finalPos / uScreen * 2.0 - 1.0) * vec2(1, -1), 0.0, 1.0);
|
||||
vColor = iColor;
|
||||
}
|
162
src/src/Components/ParticleComponent.cpp
Normal file
162
src/src/Components/ParticleComponent.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
#include "ParticleComponent.h"
|
||||
#include "../Renderer.h" // Adjust if needed
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
using namespace core::types;
|
||||
|
||||
static std::mt19937 rng{std::random_device{}()};
|
||||
|
||||
static float randRange(float a, float b)
|
||||
{
|
||||
return std::uniform_real_distribution<float>(a, b)(rng);
|
||||
}
|
||||
|
||||
void ParticleComponent::SetEmitterSettings(const ParticleEmitterSettings &s)
|
||||
{
|
||||
settings = s;
|
||||
}
|
||||
|
||||
void ParticleComponent::Emit()
|
||||
{
|
||||
for (int i = 0; i < settings.maxParticles; ++i)
|
||||
SpawnParticle();
|
||||
}
|
||||
|
||||
void ParticleComponent::Update(float dt)
|
||||
{
|
||||
emitAccumulator += dt;
|
||||
float emitInterval = 1.0f / settings.emissionRate;
|
||||
|
||||
if (!settings.burst)
|
||||
{
|
||||
while (emitAccumulator >= emitInterval)
|
||||
{
|
||||
if ((int)particles.size() < settings.maxParticles)
|
||||
SpawnParticle();
|
||||
emitAccumulator -= emitInterval;
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &p : particles)
|
||||
{
|
||||
p.life -= dt;
|
||||
if (p.life > 0)
|
||||
{
|
||||
p.position += p.velocity * dt;
|
||||
p.rotation += dt * 2.0f;
|
||||
}
|
||||
}
|
||||
|
||||
particles.erase(
|
||||
std::remove_if(particles.begin(), particles.end(),
|
||||
[](const Particle &p)
|
||||
{ return p.life <= 0.0f; }),
|
||||
particles.end());
|
||||
}
|
||||
|
||||
void ParticleComponent::Render()
|
||||
{
|
||||
for (const auto &p : particles)
|
||||
{
|
||||
float t = std::clamp(1.0f - (p.life / settings.lifeMax), 0.0f, 1.0f);
|
||||
Color color = core::types::Color::Lerp(settings.startColor, settings.endColor, t);
|
||||
Renderer::DrawQuad(
|
||||
p.position,
|
||||
core::types::Vec2(p.size, p.size),
|
||||
p.rotation,
|
||||
color);
|
||||
}
|
||||
}
|
||||
|
||||
void ParticleComponent::SpawnParticle()
|
||||
{
|
||||
Particle p;
|
||||
p.life = randRange(settings.lifeMin, settings.lifeMax);
|
||||
p.size = randRange(settings.sizeMin, settings.sizeMax);
|
||||
|
||||
float angle = std::atan2(settings.direction.y, settings.direction.x) +
|
||||
randRange(-settings.spread * 0.5f, settings.spread * 0.5f);
|
||||
float speed = randRange(settings.speedMin, settings.speedMax);
|
||||
p.velocity = Vec2(std::cos(angle), std::sin(angle)) * speed;
|
||||
|
||||
p.position = Vec2(0.0f, 0.0f);
|
||||
p.rotation = randRange(0.0f, 6.28318f); // 2π
|
||||
p.color = settings.startColor;
|
||||
|
||||
particles.push_back(p);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ParticleComponent::Save(YAML::Emitter &out) const
|
||||
{
|
||||
out << YAML::Key << "ParticleComponent" << YAML::Value << YAML::BeginMap;
|
||||
|
||||
out << YAML::Key << "maxParticles" << YAML::Value << settings.maxParticles;
|
||||
out << YAML::Key << "emissionRate" << YAML::Value << settings.emissionRate;
|
||||
out << YAML::Key << "lifeMin" << YAML::Value << settings.lifeMin;
|
||||
out << YAML::Key << "lifeMax" << YAML::Value << settings.lifeMax;
|
||||
out << YAML::Key << "sizeMin" << YAML::Value << settings.sizeMin;
|
||||
out << YAML::Key << "sizeMax" << YAML::Value << settings.sizeMax;
|
||||
out << YAML::Key << "speedMin" << YAML::Value << settings.speedMin;
|
||||
out << YAML::Key << "speedMax" << YAML::Value << settings.speedMax;
|
||||
|
||||
out << YAML::Key << "direction" << YAML::Value << YAML::Flow << YAML::BeginSeq << settings.direction.x << settings.direction.y << YAML::EndSeq;
|
||||
out << YAML::Key << "spread" << YAML::Value << settings.spread;
|
||||
|
||||
auto writeColor = [](const Color &c, YAML::Emitter &out)
|
||||
{
|
||||
out << YAML::Flow << YAML::BeginSeq << c.r << c.g << c.b << c.a << YAML::EndSeq;
|
||||
};
|
||||
out << YAML::Key << "startColor" << YAML::Value;
|
||||
writeColor(settings.startColor, out);
|
||||
out << YAML::Key << "endColor" << YAML::Value;
|
||||
writeColor(settings.endColor, out);
|
||||
|
||||
out << YAML::Key << "loop" << YAML::Value << settings.loop;
|
||||
out << YAML::Key << "burst" << YAML::Value << settings.burst;
|
||||
|
||||
out << YAML::EndMap;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ParticleComponent::Load(const YAML::Node &node)
|
||||
{
|
||||
if (!node["ParticleComponent"] || !node["ParticleComponent"].IsMap())
|
||||
return;
|
||||
|
||||
const YAML::Node &comp = node["ParticleComponent"];
|
||||
|
||||
auto vec2 = [](const YAML::Node &n)
|
||||
{
|
||||
if (!n || !n.IsSequence() || n.size() != 2)
|
||||
return Vec2{};
|
||||
return Vec2(n[0].as<float>(), n[1].as<float>());
|
||||
};
|
||||
|
||||
auto color = [](const YAML::Node &n)
|
||||
{
|
||||
if (!n || !n.IsSequence() || n.size() != 4)
|
||||
return Color{};
|
||||
return Color(n[0].as<float>(), n[1].as<float>(), n[2].as<float>(), n[3].as<float>());
|
||||
};
|
||||
|
||||
if (comp["maxParticles"]) settings.maxParticles = comp["maxParticles"].as<int>();
|
||||
if (comp["emissionRate"]) settings.emissionRate = comp["emissionRate"].as<float>();
|
||||
if (comp["lifeMin"]) settings.lifeMin = comp["lifeMin"].as<float>();
|
||||
if (comp["lifeMax"]) settings.lifeMax = comp["lifeMax"].as<float>();
|
||||
if (comp["sizeMin"]) settings.sizeMin = comp["sizeMin"].as<float>();
|
||||
if (comp["sizeMax"]) settings.sizeMax = comp["sizeMax"].as<float>();
|
||||
if (comp["speedMin"]) settings.speedMin = comp["speedMin"].as<float>();
|
||||
if (comp["speedMax"]) settings.speedMax = comp["speedMax"].as<float>();
|
||||
if (comp["direction"]) settings.direction = vec2(comp["direction"]);
|
||||
if (comp["spread"]) settings.spread = comp["spread"].as<float>();
|
||||
if (comp["startColor"]) settings.startColor = color(comp["startColor"]);
|
||||
if (comp["endColor"]) settings.endColor = color(comp["endColor"]);
|
||||
if (comp["loop"]) settings.loop = comp["loop"].as<bool>();
|
||||
if (comp["burst"]) settings.burst = comp["burst"].as<bool>();
|
||||
}
|
69
src/src/Components/ParticleComponent.h
Normal file
69
src/src/Components/ParticleComponent.h
Normal file
@ -0,0 +1,69 @@
|
||||
|
||||
|
||||
#pragma once
|
||||
#include "Component.h"
|
||||
#include "../Entitys/Object.h"
|
||||
|
||||
#include "../core/types/vec2.h"
|
||||
#include "../core/types/vec4.h"
|
||||
#include "../core/types/color.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <vector>
|
||||
|
||||
#include <string>
|
||||
#include <yaml-cpp/yaml.h>
|
||||
struct Particle
|
||||
{
|
||||
core::types::Vec2 position;
|
||||
core::types::Vec2 velocity;
|
||||
float life;
|
||||
float size;
|
||||
float rotation;
|
||||
core::types::Color color;
|
||||
};
|
||||
|
||||
struct ParticleEmitterSettings
|
||||
{
|
||||
int maxParticles = 1000;
|
||||
float emissionRate = 100.0f; // particle/s
|
||||
float lifeMin = 0.5f;
|
||||
float lifeMax = 1.5f;
|
||||
float sizeMin = 5.0f;
|
||||
float sizeMax = 10.0f;
|
||||
float speedMin = 100.0f;
|
||||
float speedMax = 300.0f;
|
||||
core::types::Vec2 direction = {1.0f, 0.0f};
|
||||
float spread = 1.57f; // radians
|
||||
core::types::Color startColor = {1, 1, 1, 1};
|
||||
core::types::Color endColor = {1, 1, 1, 0};
|
||||
bool loop = true;
|
||||
bool burst = false;
|
||||
};
|
||||
|
||||
class ParticleComponent : public Component
|
||||
{
|
||||
public:
|
||||
ParticleComponent(Object *owner) : Component(owner) {}
|
||||
|
||||
std::string GetName() const override { return "ParticleComponent"; }
|
||||
|
||||
void Save(YAML::Emitter &out) const override;
|
||||
void Load(const YAML::Node &node) override;
|
||||
|
||||
void SetEmitterSettings(const ParticleEmitterSettings &settings);
|
||||
const ParticleEmitterSettings &GetEmitterSettings() const { return settings; }
|
||||
const std::vector<Particle> &GetParticles() const { return particles; }
|
||||
const ParticleEmitterSettings &GetSettings() const { return settings; }
|
||||
|
||||
void Emit();
|
||||
void Update(float dt);
|
||||
void Render();
|
||||
|
||||
private:
|
||||
std::vector<Particle> particles;
|
||||
ParticleEmitterSettings settings;
|
||||
float emitAccumulator = 0.0f;
|
||||
|
||||
void SpawnParticle();
|
||||
};
|
@ -7,6 +7,7 @@
|
||||
#include "components/TilemapComponent.h"
|
||||
#include "components/ScriptComponent.h"
|
||||
#include "components/PhysicsComponent.h"
|
||||
#include "components/ParticleComponent.h"
|
||||
|
||||
#include "core/utils/FileDialog.h"
|
||||
#include "core/utils/Logging.h"
|
||||
@ -437,6 +438,7 @@ void Engine::Init()
|
||||
m_scriptUpdates.reserve(256);
|
||||
m_collectStack.reserve(1024);
|
||||
m_physicsUpdates.reserve(1024);
|
||||
m_particleUpdates.reserve(1024);
|
||||
|
||||
Logger::LogInfo("Initialized Engine");
|
||||
}
|
||||
@ -448,6 +450,7 @@ void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom
|
||||
m_collectStack.clear();
|
||||
m_activeCamera = nullptr;
|
||||
m_physicsUpdates.clear();
|
||||
m_particleUpdates.clear(); // <-- Add this
|
||||
|
||||
const glm::vec2 screenSize = glm::vec2(Renderer::GetSize());
|
||||
|
||||
@ -481,6 +484,9 @@ void Engine::collectObjects(bool playing, const glm::vec2 &camPos, float camZoom
|
||||
}
|
||||
}
|
||||
|
||||
if (auto particles = obj->GetComponent<ParticleComponent>())
|
||||
m_particleUpdates.push_back(particles.get()); // <-- Collect particle components
|
||||
|
||||
if (playing)
|
||||
{
|
||||
if (auto script = obj->GetComponent<ScriptComponent>())
|
||||
@ -777,6 +783,7 @@ void Engine::Run()
|
||||
m_Reserved_draws = 0;
|
||||
m_toDraw.clear();
|
||||
m_scriptUpdates.clear();
|
||||
m_particleUpdates.clear();
|
||||
profiler.EndEngineSection();
|
||||
|
||||
// profiler.BeginEngineSection("Draw Editor Grid");
|
||||
@ -822,9 +829,11 @@ void Engine::Run()
|
||||
}
|
||||
profiler.EndSection();
|
||||
|
||||
|
||||
profiler.BeginSection("Render");
|
||||
for (auto *obj : m_toDraw)
|
||||
{
|
||||
// --- Sprite rendering ---
|
||||
if (auto spritePtr = obj->GetComponent<SpriteComponent>())
|
||||
{
|
||||
profiler.BeginSection("Draw Sprite: " + obj->GetName());
|
||||
@ -834,6 +843,27 @@ void Engine::Run()
|
||||
cameraPos);
|
||||
profiler.EndSection();
|
||||
}
|
||||
|
||||
// --- Particle rendering ---
|
||||
if (auto particle = obj->GetComponent<ParticleComponent>())
|
||||
{
|
||||
profiler.BeginSection("Draw Particles" + obj->GetName());
|
||||
const auto &particles = particle->GetParticles();
|
||||
const auto &settings = particle->GetSettings();
|
||||
|
||||
for (const auto &p : particles)
|
||||
{
|
||||
float t = std::clamp(1.0f - (p.life / settings.lifeMax), 0.0f, 1.0f);
|
||||
core::types::Color color = core::types::Color::Lerp(settings.startColor, settings.endColor, t);
|
||||
Renderer::DrawQuad(
|
||||
p.position,
|
||||
core::types::Vec2(p.size, p.size),
|
||||
p.rotation,
|
||||
color);
|
||||
}
|
||||
|
||||
profiler.EndSection();
|
||||
}
|
||||
}
|
||||
profiler.EndSection();
|
||||
|
||||
|
@ -9,6 +9,7 @@
|
||||
class Object;
|
||||
class ScriptComponent;
|
||||
class PhysicsComponent;
|
||||
class ParticleComponent;
|
||||
|
||||
class Engine
|
||||
{
|
||||
@ -39,5 +40,6 @@ private:
|
||||
|
||||
std::vector<std::shared_ptr<Object>> m_collectStack;
|
||||
std::vector<PhysicsComponent*> m_physicsUpdates;
|
||||
std::vector<ParticleComponent*> m_particleUpdates;
|
||||
|
||||
};
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "../Components/TilemapComponent.h"
|
||||
#include "../Components/TextComponent.h"
|
||||
#include "../Components/ScriptComponent.h"
|
||||
#include "../Components/ParticleComponent.h"
|
||||
|
||||
|
||||
#include "../core/utils/Logging.h"
|
||||
#include "../utils/UID.h"
|
||||
@ -153,6 +155,8 @@ void Object::Load(const YAML::Node &node)
|
||||
else if (type == "TilemapComponent") AddComponent<TilemapComponent>()->Load(compNode);
|
||||
else if (type == "TextComponent") AddComponent<TextComponent>()->Load(compNode);
|
||||
else if (type == "ScriptComponent") AddComponent<ScriptComponent>()->Load(compNode);
|
||||
else if (type == "ParticleComponent") AddComponent<ParticleComponent>()->Load(compNode);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,6 +40,12 @@ int Renderer::s_DrawCalls = 0;
|
||||
int Renderer::s_LightsCount = 0;
|
||||
std::unique_ptr<ColorCorrection> Renderer::s_ColorCorrection = nullptr;
|
||||
|
||||
GLuint Renderer::s_QuadVAO = 0;
|
||||
GLuint Renderer::s_QuadVBO = 0;
|
||||
GLuint Renderer::s_QuadInstanceVBO = 0;
|
||||
Shader Renderer::s_UnlitQuadShader;
|
||||
std::vector<QuadInstance> Renderer::s_QuadBatch;
|
||||
|
||||
std::vector<Light> Renderer::s_Lights;
|
||||
|
||||
std::vector<Renderer::Cluster> Renderer::s_Clusters;
|
||||
@ -118,6 +124,52 @@ void Renderer::InitQuad()
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Renderer::InitQuadBatch()
|
||||
{
|
||||
float quadVerts[] = {
|
||||
-0.5f, -0.5f,
|
||||
0.5f, -0.5f,
|
||||
0.5f, 0.5f,
|
||||
-0.5f, 0.5f};
|
||||
|
||||
glGenVertexArrays(1, &s_QuadVAO);
|
||||
glBindVertexArray(s_QuadVAO);
|
||||
|
||||
glGenBuffers(1, &s_QuadVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_QuadVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, sizeof(quadVerts), quadVerts, GL_STATIC_DRAW);
|
||||
|
||||
glEnableVertexAttribArray(0); // aPos
|
||||
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float), (void *)0);
|
||||
|
||||
glGenBuffers(1, &s_QuadInstanceVBO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_QuadInstanceVBO);
|
||||
glBufferData(GL_ARRAY_BUFFER, MAX_QUADS * sizeof(QuadInstance), nullptr, GL_DYNAMIC_DRAW);
|
||||
|
||||
std::size_t offset = 0;
|
||||
|
||||
glEnableVertexAttribArray(1); // pos
|
||||
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(QuadInstance), (void *)(offset));
|
||||
glVertexAttribDivisor(1, 1);
|
||||
offset += sizeof(glm::vec2);
|
||||
|
||||
glEnableVertexAttribArray(2); // size
|
||||
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(QuadInstance), (void *)(offset));
|
||||
glVertexAttribDivisor(2, 1);
|
||||
offset += sizeof(glm::vec2);
|
||||
|
||||
glEnableVertexAttribArray(3); // rotation
|
||||
glVertexAttribPointer(3, 1, GL_FLOAT, GL_FALSE, sizeof(QuadInstance), (void *)(offset));
|
||||
glVertexAttribDivisor(3, 1);
|
||||
offset += sizeof(float);
|
||||
|
||||
glEnableVertexAttribArray(4); // color
|
||||
glVertexAttribPointer(4, 4, GL_FLOAT, GL_FALSE, sizeof(QuadInstance), (void *)(offset));
|
||||
glVertexAttribDivisor(4, 1);
|
||||
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Renderer::Init()
|
||||
{
|
||||
glGenFramebuffers(1, &fbo);
|
||||
@ -154,6 +206,9 @@ void Renderer::Init()
|
||||
blurShader.LoadFromFile("src/assets/shaders/fullscreen.vert", "src/assets/shaders/blur.frag");
|
||||
compositeShader.LoadFromFile("src/assets/shaders/fullscreen.vert", "src/assets/shaders/composite.frag");
|
||||
|
||||
InitQuadBatch();
|
||||
s_UnlitQuadShader.LoadFromFile("src/assets/shaders/unlit_quad.vert", "src/assets/shaders/unlit_quad.frag");
|
||||
|
||||
SetColorCorrection(std::make_unique<ColorCorrection>());
|
||||
|
||||
{
|
||||
@ -366,6 +421,7 @@ void Renderer::End()
|
||||
|
||||
PROFILE_ENGINE_SCOPE("Renderer::End");
|
||||
FlushSprites();
|
||||
FlushQuads();
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
@ -443,6 +499,17 @@ void Renderer::DrawTilemap(TilemapComponent *tilemap, const glm::vec2 &worldPos,
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
void Renderer::DrawQuad(const core::types::Vec2 &pos, const core::types::Vec2 &size, float rotation, const core::types::Color &color)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Renderer::DrawQuad");
|
||||
|
||||
if (s_QuadBatch.size() >= MAX_QUADS)
|
||||
FlushQuads();
|
||||
|
||||
s_QuadBatch.push_back({pos, size, rotation, color});
|
||||
}
|
||||
|
||||
|
||||
void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float zoom, glm::vec2 &CameraPos)
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("DrawSprite");
|
||||
@ -473,6 +540,37 @@ void Renderer::DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float z
|
||||
sortedDrawList.push_back(drawEntry);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Renderer::FlushQuads()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::FlushQuads");
|
||||
|
||||
if (s_QuadBatch.empty())
|
||||
return;
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("Upload");
|
||||
|
||||
s_UnlitQuadShader.Use();
|
||||
s_UnlitQuadShader.SetVec2("uScreen", glm::vec2(width, height));
|
||||
|
||||
glBindVertexArray(s_QuadVAO);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, s_QuadInstanceVBO);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, 0, s_QuadBatch.size() * sizeof(QuadInstance), s_QuadBatch.data());
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_DEEP_SCOPE("DrawQuads");
|
||||
|
||||
glDrawArraysInstanced(GL_TRIANGLE_FAN, 0, 4, static_cast<GLsizei>(s_QuadBatch.size()));
|
||||
++s_DrawCalls;
|
||||
}
|
||||
|
||||
glBindVertexArray(0);
|
||||
s_QuadBatch.clear();
|
||||
}
|
||||
|
||||
void Renderer::FlushSprites()
|
||||
{
|
||||
PROFILE_ENGINE_SCOPE("Renderer::FlushSprites");
|
||||
|
@ -9,9 +9,9 @@
|
||||
#include "core/utils/EngineConfig.h"
|
||||
#include "utils/Shader.h"
|
||||
#include "core/utils/Profiler.h"
|
||||
#include "core/types/all.h"
|
||||
|
||||
struct ColorCorrection
|
||||
{
|
||||
struct ColorCorrection {
|
||||
float brightness = 1.0f;
|
||||
float saturation = 1.0f;
|
||||
float gamma = 1.0f;
|
||||
@ -20,41 +20,45 @@ struct ColorCorrection
|
||||
float threshold = 0.2f;
|
||||
float intensity = 1.2f;
|
||||
|
||||
|
||||
void Upload(Shader &shader) const
|
||||
{
|
||||
void Upload(Shader& shader) const {
|
||||
shader.SetFloat("uBrightness", brightness);
|
||||
shader.SetFloat("uSaturation", saturation);
|
||||
shader.SetFloat("uGamma", gamma);
|
||||
}
|
||||
};
|
||||
|
||||
struct Light
|
||||
{
|
||||
struct Light {
|
||||
glm::vec2 screenPos;
|
||||
glm::vec3 color;
|
||||
float intensity;
|
||||
float radius;
|
||||
};
|
||||
|
||||
class Renderer
|
||||
{
|
||||
struct QuadInstance {
|
||||
core::types::Vec2 pos;
|
||||
core::types::Vec2 size;
|
||||
float rotation;
|
||||
core::types::Color color;
|
||||
};
|
||||
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
static void Init();
|
||||
static void Resize(int w, int h);
|
||||
static void Begin();
|
||||
static void End();
|
||||
|
||||
static void DrawSprite(SpriteComponent *sprite, const glm::vec2 &pos, float zoom, glm::vec2 &CameraPos);
|
||||
static void DrawTilemap(TilemapComponent *tilemap, const glm::vec2 &worldPos, float zoom, const glm::vec2 &cameraPos);
|
||||
static void DrawSprite(SpriteComponent* sprite, const glm::vec2& pos, float zoom, glm::vec2& CameraPos);
|
||||
static void DrawTilemap(TilemapComponent* tilemap, const glm::vec2& worldPos, float zoom, const glm::vec2& cameraPos);
|
||||
|
||||
static void AddLight(const glm::vec2 &screenPos, const glm::vec3 &color, float intensity, float radius);
|
||||
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 void DrawGizmoLine(const glm::vec2 &worldStart, const glm::vec2 &worldEnd, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawGizmoRect(const glm::vec2 &worldPos, const glm::vec2 &size, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawGizmoCircle(const glm::vec2 &worldCenter, float radius, int segments, const glm::vec3 &color, const glm::vec2 &cameraPos, float zoom);
|
||||
static void DrawEditorGrid(const glm::vec2& cameraPos, float zoom);
|
||||
static void DrawGizmoLine(const glm::vec2& worldStart, const glm::vec2& worldEnd, const glm::vec3& color, const glm::vec2& cameraPos, float zoom);
|
||||
static void DrawGizmoRect(const glm::vec2& worldPos, const glm::vec2& size, const glm::vec3& color, const glm::vec2& cameraPos, float zoom);
|
||||
static void DrawGizmoCircle(const glm::vec2& worldCenter, float radius, int segments, const glm::vec3& color, const glm::vec2& cameraPos, float zoom);
|
||||
|
||||
static GLuint GetRenderTexture();
|
||||
static glm::ivec2 GetSize();
|
||||
@ -62,14 +66,15 @@ public:
|
||||
static int GetLightsCount();
|
||||
|
||||
static void SetColorCorrection(std::unique_ptr<ColorCorrection> correction);
|
||||
static ColorCorrection *GetColorCorrection();
|
||||
|
||||
static ColorCorrection* GetColorCorrection();
|
||||
static GLuint GetFinalTexture();
|
||||
|
||||
// Clustered lighting
|
||||
static void UpdateClusterLights(); // Call once per frame after all lights added
|
||||
static void UpdateClusterLights();
|
||||
static void FlushSprites();
|
||||
|
||||
static void InitQuadBatch();
|
||||
static void DrawQuad(const core::types::Vec2& pos, const core::types::Vec2& size, float rotation, const core::types::Color& color);
|
||||
static void FlushQuads();
|
||||
|
||||
private:
|
||||
static std::vector<Light> s_Lights;
|
||||
@ -82,16 +87,14 @@ private:
|
||||
|
||||
static GLuint shader, quadVAO, quadVBO;
|
||||
static void InitQuad();
|
||||
static GLuint LoadShader(const char *vertexSrc, const char *fragmentSrc);
|
||||
|
||||
static GLuint LoadShader(const char* vertexSrc, const char* fragmentSrc);
|
||||
static std::unique_ptr<ColorCorrection> s_ColorCorrection;
|
||||
|
||||
// --- Clustered Lighting ---
|
||||
// Clustered Lighting
|
||||
static constexpr int CLUSTER_SIZE = 16;
|
||||
static constexpr int MAX_LIGHTS_PER_CLUSTER = 32;
|
||||
|
||||
struct Cluster
|
||||
{
|
||||
struct Cluster {
|
||||
std::vector<int> lightIndices;
|
||||
};
|
||||
|
||||
@ -102,4 +105,9 @@ private:
|
||||
|
||||
static GLuint bloomFBO;
|
||||
static GLuint bloomTexture;
|
||||
|
||||
static std::vector<QuadInstance> s_QuadBatch;
|
||||
static GLuint s_QuadVAO, s_QuadVBO, s_QuadInstanceVBO;
|
||||
static Shader s_UnlitQuadShader;
|
||||
static constexpr size_t MAX_QUADS = 10000;
|
||||
};
|
||||
|
8
src/src/core/types/all.h
Normal file
8
src/src/core/types/all.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "color.h"
|
||||
#include "rect.h"
|
||||
#include "vec2.h"
|
||||
#include "vec3.h"
|
||||
#include "vec4.h"
|
||||
#include "vector.h"
|
@ -1,17 +1,130 @@
|
||||
#pragma once
|
||||
#include <algorithm>
|
||||
|
||||
namespace core {
|
||||
namespace types {
|
||||
|
||||
struct Color
|
||||
namespace core
|
||||
{
|
||||
float r{1}, g{1}, b{1}, a{1};
|
||||
namespace types
|
||||
{
|
||||
|
||||
Color() = default;
|
||||
Color(float _r, float _g, float _b, float _a = 1.0f)
|
||||
: r(_r), g(_g), b(_b), a(_a)
|
||||
{}
|
||||
};
|
||||
struct Color
|
||||
{
|
||||
float r{1}, g{1}, b{1}, a{1};
|
||||
|
||||
}
|
||||
}
|
||||
Color() = default;
|
||||
Color(float _r, float _g, float _b, float _a = 1.0f)
|
||||
: r(_r), g(_g), b(_b), a(_a) {}
|
||||
|
||||
// Add
|
||||
Color operator+(const Color &other) const
|
||||
{
|
||||
return {r + other.r, g + other.g, b + other.b, a + other.a};
|
||||
}
|
||||
|
||||
Color &operator+=(const Color &other)
|
||||
{
|
||||
r += other.r;
|
||||
g += other.g;
|
||||
b += other.b;
|
||||
a += other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Subtract
|
||||
Color operator-(const Color &other) const
|
||||
{
|
||||
return {r - other.r, g - other.g, b - other.b, a - other.a};
|
||||
}
|
||||
|
||||
Color &operator-=(const Color &other)
|
||||
{
|
||||
r -= other.r;
|
||||
g -= other.g;
|
||||
b -= other.b;
|
||||
a -= other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Multiply
|
||||
Color operator*(const Color &other) const
|
||||
{
|
||||
return {r * other.r, g * other.g, b * other.b, a * other.a};
|
||||
}
|
||||
|
||||
Color operator*(float scalar) const
|
||||
{
|
||||
return {r * scalar, g * scalar, b * scalar, a * scalar};
|
||||
}
|
||||
|
||||
Color &operator*=(const Color &other)
|
||||
{
|
||||
r *= other.r;
|
||||
g *= other.g;
|
||||
b *= other.b;
|
||||
a *= other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color &operator*=(float scalar)
|
||||
{
|
||||
r *= scalar;
|
||||
g *= scalar;
|
||||
b *= scalar;
|
||||
a *= scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Divide
|
||||
Color operator/(float scalar) const
|
||||
{
|
||||
float inv = 1.0f / scalar;
|
||||
return {r * inv, g * inv, b * inv, a * inv};
|
||||
}
|
||||
|
||||
Color &operator/=(float scalar)
|
||||
{
|
||||
float inv = 1.0f / scalar;
|
||||
r *= inv;
|
||||
g *= inv;
|
||||
b *= inv;
|
||||
a *= inv;
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Equality
|
||||
bool operator==(const Color &other) const
|
||||
{
|
||||
return r == other.r && g == other.g && b == other.b && a == other.a;
|
||||
}
|
||||
|
||||
bool operator!=(const Color &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
// Linear interpolation
|
||||
static Color Lerp(const Color &a, const Color &b, float t)
|
||||
{
|
||||
return {
|
||||
a.r + (b.r - a.r) * t,
|
||||
a.g + (b.g - a.g) * t,
|
||||
a.b + (b.b - a.b) * t,
|
||||
a.a + (b.a - a.a) * t};
|
||||
}
|
||||
|
||||
// Clamp all components between 0 and 1
|
||||
void Clamp()
|
||||
{
|
||||
r = std::clamp(r, 0.0f, 1.0f);
|
||||
g = std::clamp(g, 0.0f, 1.0f);
|
||||
b = std::clamp(b, 0.0f, 1.0f);
|
||||
a = std::clamp(a, 0.0f, 1.0f);
|
||||
}
|
||||
};
|
||||
|
||||
inline Color operator*(float scalar, const Color &c)
|
||||
{
|
||||
return c * scalar;
|
||||
}
|
||||
|
||||
} // namespace types
|
||||
} // namespace core
|
||||
|
@ -1,5 +1,6 @@
|
||||
// core/types/vec2.h
|
||||
#pragma once
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace core
|
||||
{
|
||||
@ -8,27 +9,39 @@ namespace core
|
||||
|
||||
struct Vec2
|
||||
{
|
||||
float x{0}, y{0};
|
||||
float x = 0.0f, y = 0.0f;
|
||||
|
||||
Vec2() = default;
|
||||
Vec2(float _x, float _y) : x(_x), y(_y) {}
|
||||
|
||||
Vec2 &operator+=(const Vec2 &o)
|
||||
Vec2 operator*(float s) const { return {x * s, y * s}; }
|
||||
operator glm::vec2() const { return glm::vec2(x, y); }
|
||||
|
||||
|
||||
Vec2 &operator*=(float scalar)
|
||||
{
|
||||
x += o.x;
|
||||
y += o.y;
|
||||
return *this;
|
||||
}
|
||||
Vec2 &operator-=(const Vec2 &o)
|
||||
{
|
||||
x -= o.x;
|
||||
y -= o.y;
|
||||
x *= scalar;
|
||||
y *= scalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
friend Vec2 operator+(Vec2 a, const Vec2 &b) { return a += b; }
|
||||
friend Vec2 operator-(Vec2 a, const Vec2 &b) { return a -= b; }
|
||||
friend Vec2 operator*(float scalar, const Vec2 &v)
|
||||
{
|
||||
return v * scalar;
|
||||
}
|
||||
|
||||
Vec2 operator+(const Vec2 &other) const
|
||||
{
|
||||
return {x + other.x, y + other.y};
|
||||
}
|
||||
|
||||
Vec2 &operator+=(const Vec2 &other)
|
||||
{
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
} // namespace types
|
||||
} // namespace core
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "../../components/TilemapComponent.h"
|
||||
#include "../../components/ScriptComponent.h"
|
||||
#include "../../components/PhysicsComponent.h"
|
||||
#include "../../components/ParticleComponent.h"
|
||||
|
||||
void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
{
|
||||
@ -70,7 +71,8 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
"CameraComponent",
|
||||
"LightComponent",
|
||||
"ScriptComponent",
|
||||
"TilemapComponent"};
|
||||
"TilemapComponent",
|
||||
"ParticleComponent"};
|
||||
|
||||
static int selectedIndex = -1;
|
||||
|
||||
@ -102,6 +104,8 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
selected->AddComponent<ScriptComponent>();
|
||||
else if (type == "TilemapComponent" && !selected->GetComponent<TilemapComponent>())
|
||||
selected->AddComponent<TilemapComponent>();
|
||||
else if (type == "ParticleComponent" && !selected->GetComponent<ParticleComponent>())
|
||||
selected->AddComponent<ParticleComponent>();
|
||||
}
|
||||
|
||||
if (auto sprite = selected->GetComponent<SpriteComponent>())
|
||||
@ -139,7 +143,6 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
if (!path.empty())
|
||||
sprite->SetTexture(path);
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::SeparatorText("Normal Map");
|
||||
{
|
||||
@ -161,12 +164,10 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
if (!path.empty())
|
||||
sprite->SetNormalMap(path);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ImGui::SeparatorText("Info");
|
||||
|
||||
|
||||
// — Size Display & Remove —
|
||||
glm::vec2 size = sprite->GetSize();
|
||||
ImGui::Text("Size: %.0f × %.0f", size.x, size.y);
|
||||
@ -250,6 +251,38 @@ void DrawInspectorUI(std::shared_ptr<Object> selected)
|
||||
if (ImGui::Button("Remove ScriptComponent"))
|
||||
selected->RemoveComponent<ScriptComponent>();
|
||||
}
|
||||
if (auto part = selected->GetComponent<ParticleComponent>())
|
||||
{
|
||||
ImGui::SeparatorText("Particle Component");
|
||||
|
||||
auto settings = part->GetEmitterSettings();
|
||||
|
||||
ImGui::DragInt("Max Particles", &settings.maxParticles, 10, 10, 10000);
|
||||
ImGui::DragFloat("Emission Rate", &settings.emissionRate, 1.0f, 0.0f, 1000.0f);
|
||||
ImGui::DragFloat("Life Min", &settings.lifeMin, 0.01f, 0.01f, 10.0f);
|
||||
ImGui::DragFloat("Life Max", &settings.lifeMax, 0.01f, 0.01f, 10.0f);
|
||||
ImGui::DragFloat("Size Min", &settings.sizeMin, 0.1f, 0.1f, 100.0f);
|
||||
ImGui::DragFloat("Size Max", &settings.sizeMax, 0.1f, 0.1f, 100.0f);
|
||||
ImGui::DragFloat("Speed Min", &settings.speedMin, 1.0f, 0.0f, 1000.0f);
|
||||
ImGui::DragFloat("Speed Max", &settings.speedMax, 1.0f, 0.0f, 1000.0f);
|
||||
ImGui::DragFloat2("Direction", &settings.direction.x, 0.01f);
|
||||
ImGui::DragFloat("Spread", &settings.spread, 0.01f, 0.0f, 3.14f);
|
||||
|
||||
ImGui::ColorEdit4("Start Color", &settings.startColor.r);
|
||||
ImGui::ColorEdit4("End Color", &settings.endColor.r);
|
||||
|
||||
ImGui::Checkbox("Loop", &settings.loop);
|
||||
ImGui::Checkbox("Burst", &settings.burst);
|
||||
|
||||
part->SetEmitterSettings(settings);
|
||||
|
||||
if (ImGui::Button("Emit Once"))
|
||||
part->Emit();
|
||||
|
||||
if (ImGui::Button("Remove ParticleComponent"))
|
||||
selected->RemoveComponent<ParticleComponent>();
|
||||
}
|
||||
|
||||
if (auto phys = selected->GetComponent<PhysicsComponent>())
|
||||
{
|
||||
ImGui::SeparatorText("Physics Component");
|
||||
|
Loading…
Reference in New Issue
Block a user