diff --git a/imgui.ini b/imgui.ini index 1ce1346..a935e8a 100644 --- a/imgui.ini +++ b/imgui.ini @@ -10,24 +10,24 @@ Collapsed=1 [Window][WindowOverViewport_11111111] Pos=0,19 -Size=1920,1158 +Size=1280,701 Collapsed=0 [Window][Inspector] -Pos=1402,19 -Size=518,1158 +Pos=762,19 +Size=518,701 Collapsed=0 DockId=0x00000006,0 [Window][Scene Tree] Pos=0,19 -Size=342,575 +Size=342,348 Collapsed=0 DockId=0x00000003,0 [Window][Viewport] Pos=344,19 -Size=1056,847 +Size=416,390 Collapsed=0 DockId=0x00000007,0 @@ -36,14 +36,14 @@ Size=1280,19 Collapsed=0 [Window][Performance Info] -Pos=344,868 -Size=1056,309 +Pos=344,411 +Size=416,309 Collapsed=0 DockId=0x00000008,2 [Window][Console] -Pos=344,868 -Size=1056,309 +Pos=344,411 +Size=416,309 Collapsed=0 DockId=0x00000008,0 @@ -54,8 +54,8 @@ Collapsed=0 DockId=0x00000007,1 [Window][Profiler] -Pos=344,868 -Size=1056,309 +Pos=344,411 +Size=416,309 Collapsed=0 DockId=0x00000008,3 @@ -78,14 +78,14 @@ Collapsed=0 DockId=0x00000008,1 [Window][Color Correction] -Pos=344,868 -Size=1056,309 +Pos=344,411 +Size=416,309 Collapsed=0 DockId=0x00000008,1 [Window][Asset Browser] -Pos=0,596 -Size=342,581 +Pos=0,369 +Size=342,351 Collapsed=0 DockId=0x00000004,0 @@ -95,7 +95,7 @@ Size=325,75 Collapsed=0 [Docking][Data] -DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1920,1158 Split=X +DockSpace ID=0x11111111 Window=0x1BBC0F80 Pos=0,19 Size=1280,701 Split=X DockNode ID=0x00000005 Parent=0x11111111 SizeRef=1400,1158 Split=X DockNode ID=0x00000001 Parent=0x00000005 SizeRef=342,701 Split=Y Selected=0x12EF0F59 DockNode ID=0x00000003 Parent=0x00000001 SizeRef=342,575 HiddenTabBar=1 Selected=0x12EF0F59 diff --git a/remake/build.log b/remake/build.log index a79bae6..de46732 100644 --- a/remake/build.log +++ b/remake/build.log @@ -1,2 +1 @@ [LINK] g++ src\build\Engine.o src\build\main.o src\build\Renderer.o src\build\Components\AnimationComponent.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\AssetManager.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\LoadingWindow.o src\build\core\utils\Logging.o src\build\core\utils\Profiler.o src\build\core\utils\Texture.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 src\build\xxhash.o -o src\build\app.exe -LC:\msys64\mingw64\lib -lglfw3 -lglew32 -lopengl32 -lgdi32 -lyaml-cpp -lcomdlg32 -lssl -lcrypto -[RUN] Executed app.exe successfully. diff --git a/src/assets/scenes/Smoke.cene b/src/assets/scenes/Smoke.cene new file mode 100644 index 0000000..eb976d0 --- /dev/null +++ b/src/assets/scenes/Smoke.cene @@ -0,0 +1,110 @@ +engine_version: 0.1.0 +scene_name: Smoke +scene_hash: bb44d49b100c99a58dbbebf7385e4813ce7d55b8aa64a8e00f2fb9949af8306e +format_version: 1 +objects: + - name: Smoke and Light + uid: dc6b14507c5f4cd6be29402f26a43bed + id: 3 + position: [53, -28] + rotation: 0 + layer: 0 + visable: true + components: + - type: ParticleComponent + maxParticles: 10000 + emissionRate: 10000 + lifeMin: 0.00999999978 + lifeMax: 0.800000012 + sizeMin: 10 + sizeMax: 100 + speedMin: 100 + speedMax: 300 + direction: [0, 0] + spread: 6.27445841 + startColor: [1, 0, 1, 0.149019614] + endColor: [0.588235378, 0, 1, 0] + loop: true + burst: false + roundness: 0 + - type: LightComponent + color: + - 1 + - 0 + - 1 + intensity: 1 + radius: 300 + falloff: 1 + type: 0 + children: [] + - name: Backround + uid: d395b3d1c59140298babbce87efbabc9 + id: 4 + position: [1028, 0] + rotation: 0 + layer: 0 + visable: true + components: + - type: SpriteComponent + texture: 4 + normalMap: 5 + renderType: Lit + children: [] +color_correction: + brightness: 1 + saturation: 1 + gamma: 1 + bloom: false + intensity: 1.99000001 + threshold: 0.219999999 +Assets: + - uaid: 5 + path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_nor_gl_1k.png + filename: ganges_river_pebbles_nor_gl_1k.png + filetype: png + type: 0 + size: [1024, 1024] + hash: 6711b00700d4c94a + channels: 4 + format: GL_RGBA + lastModified: 1744565594 + - uaid: 4 + path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_diff_1k.png + filename: ganges_river_pebbles_diff_1k.png + filetype: png + type: 0 + size: [1024, 1024] + hash: 0349580fcbf62155 + channels: 4 + format: GL_RGBA + lastModified: 1744565605 + - uaid: 3 + path: C:\Users\spenc\OneDrive\Pictures\Pixel Holy Spell Effect 32x32 Pack 3\01.png + filename: 01.png + filetype: png + type: 0 + size: [704, 576] + hash: 82866fcf3324b785 + channels: 4 + format: GL_RGBA + lastModified: 1687052108 + - uaid: 2 + path: C:\Users\spenc\OneDrive\Pictures\Pixel Holy Spell Effect 32x32 Pack 3\00.png + filename: 00.png + filetype: png + type: 0 + size: [1216, 192] + hash: 2b0b3c20179d6f12 + channels: 4 + format: GL_RGBA + lastModified: 1687052065 + - uaid: 1 + path: C:\Users\spenc\OneDrive\Pictures\6656e7221e49a1774d2fb280357e56f8d25d9d95.png + filename: 6656e7221e49a1774d2fb280357e56f8d25d9d95.png + filetype: png + type: 0 + size: [1024, 1024] + hash: e8aaee6025f21557 + channels: 4 + format: GL_RGBA + lastModified: 1744577923 \ No newline at end of file diff --git a/src/assets/scenes/test.cene b/src/assets/scenes/test.cene index 008776d..0563ffe 100644 --- a/src/assets/scenes/test.cene +++ b/src/assets/scenes/test.cene @@ -1,12 +1,12 @@ engine_version: 0.1.0 scene_name: test -scene_hash: 2a85407931385c3ec75b04912f97447151603fb317700b3a5b33a0c86182db25 +scene_hash: 5176ce6547df4e17907193d5cfbbb474091eefafd718c7920a34526eaa69172f format_version: 1 objects: - name: NewObject uid: dc6b14507c5f4cd6be29402f26a43bed id: 3 - position: [48.2000008, -72] + position: [158, -28] rotation: 0 layer: 0 visable: true @@ -16,14 +16,14 @@ objects: emissionRate: 10000 lifeMin: 0.00999999978 lifeMax: 0.800000012 - sizeMin: 5 - sizeMax: 10 + sizeMin: 10 + sizeMax: 100 speedMin: 100 speedMax: 300 direction: [0, 0] - spread: 6.28318548 - startColor: [0.0588235296, 0, 1, 1] - endColor: [1, 0, 0.911765099, 0] + spread: 6.27445841 + startColor: [1, 0, 1, 0.149019614] + endColor: [0.588235378, 0, 1, 0] loop: true burst: false roundness: 0 @@ -31,7 +31,7 @@ objects: color: - 1 - 0 - - 0.941176414 + - 1 intensity: 1 radius: 300 falloff: 1 @@ -54,30 +54,30 @@ color_correction: brightness: 1 saturation: 1 gamma: 1 - bloom: true - intensity: 1.20000005 - threshold: 0.170000002 + bloom: false + intensity: 1.99000001 + threshold: 0.219999999 Assets: - - uaid: 5 - path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_nor_gl_1k.png - filename: ganges_river_pebbles_nor_gl_1k.png + - uaid: 1 + path: C:\Users\spenc\OneDrive\Pictures\6656e7221e49a1774d2fb280357e56f8d25d9d95.png + filename: 6656e7221e49a1774d2fb280357e56f8d25d9d95.png filetype: png type: 0 size: [1024, 1024] - hash: 6711b00700d4c94a + hash: e8aaee6025f21557 channels: 4 format: GL_RGBA - lastModified: 1744565594 - - uaid: 4 - path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_diff_1k.png - filename: ganges_river_pebbles_diff_1k.png + lastModified: 1744577924 + - uaid: 2 + path: C:\Users\spenc\OneDrive\Pictures\Pixel Holy Spell Effect 32x32 Pack 3\00.png + filename: 00.png filetype: png type: 0 - size: [1024, 1024] - hash: 0349580fcbf62155 + size: [1216, 192] + hash: 2b0b3c20179d6f12 channels: 4 format: GL_RGBA - lastModified: 1744565605 + lastModified: 1687052064 - uaid: 3 path: C:\Users\spenc\OneDrive\Pictures\Pixel Holy Spell Effect 32x32 Pack 3\01.png filename: 01.png @@ -88,23 +88,23 @@ Assets: channels: 4 format: GL_RGBA lastModified: 1687052107 - - uaid: 2 - path: C:\Users\spenc\OneDrive\Pictures\Pixel Holy Spell Effect 32x32 Pack 3\00.png - filename: 00.png - filetype: png - type: 0 - size: [1216, 192] - hash: 2b0b3c20179d6f12 - channels: 4 - format: GL_RGBA - lastModified: 1687052065 - - uaid: 1 - path: C:\Users\spenc\OneDrive\Pictures\6656e7221e49a1774d2fb280357e56f8d25d9d95.png - filename: 6656e7221e49a1774d2fb280357e56f8d25d9d95.png + - uaid: 4 + path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_diff_1k.png + filename: ganges_river_pebbles_diff_1k.png filetype: png type: 0 size: [1024, 1024] - hash: e8aaee6025f21557 + hash: 0349580fcbf62155 channels: 4 format: GL_RGBA - lastModified: 1744577923 \ No newline at end of file + lastModified: 1744565605 + - uaid: 5 + path: C:\Users\spenc\OneDrive\Pictures\textures\ganges_river_pebbles_nor_gl_1k.png + filename: ganges_river_pebbles_nor_gl_1k.png + filetype: png + type: 0 + size: [1024, 1024] + hash: 6711b00700d4c94a + channels: 4 + format: GL_RGBA + lastModified: 1744565594 \ No newline at end of file diff --git a/src/src/Engine.cpp b/src/src/Engine.cpp index cac6744..73f874a 100644 --- a/src/src/Engine.cpp +++ b/src/src/Engine.cpp @@ -666,7 +666,7 @@ void Engine::Run() { if (ImGui::MenuItem("Save Scene")) { - std::string file = OpenFileDialog(FileDialogType::Scenes); + std::string file = CreateFileDialog(FileDialogType::Scenes); if (!file.empty()) SaveScene(file); selected = nullptr; diff --git a/src/src/core/types/color.h b/src/src/core/types/color.h index 283fe91..b52388e 100644 --- a/src/src/core/types/color.h +++ b/src/src/core/types/color.h @@ -1,5 +1,7 @@ #pragma once #include +#include +#include namespace core { @@ -14,6 +16,17 @@ namespace core Color(float _r, float _g, float _b, float _a = 1.0f) : r(_r), g(_g), b(_b), a(_a) {} + // Conversions + Color(const glm::vec3 &v, float _a = 1.0f) + : r(v.x), g(v.y), b(v.z), a(_a) {} + + Color(const ImVec4 &v) + : r(v.x), g(v.y), b(v.z), a(v.w) {} + + operator glm::vec3() const { return {r, g, b}; } + operator glm::vec4() const { return {r, g, b, a}; } + operator ImVec4() const { return {r, g, b, a}; } + // Add Color operator+(const Color &other) const { diff --git a/src/src/core/types/vec3.h b/src/src/core/types/vec3.h index f686d5e..bc44fc6 100644 --- a/src/src/core/types/vec3.h +++ b/src/src/core/types/vec3.h @@ -1,4 +1,8 @@ #pragma once +#include +#include +#include +#include namespace core { @@ -10,42 +14,84 @@ namespace core float x{0}, y{0}, z{0}; Vec3() = default; - Vec3(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {} + Vec3(float x, float y, float z) : x(x), y(y), z(z) {} + Vec3(float v) : x(v), y(v), z(v) {} + Vec3(const glm::vec3 &v) : x(v.x), y(v.y), z(v.z) {} - Vec3 &operator+=(const Vec3 &o) + operator glm::vec3() const { return {x, y, z}; } + + Vec3 operator+(const Vec3 &rhs) const { return {x + rhs.x, y + rhs.y, z + rhs.z}; } + Vec3 operator-(const Vec3 &rhs) const { return {x - rhs.x, y - rhs.y, z - rhs.z}; } + Vec3 operator*(float scalar) const { return {x * scalar, y * scalar, z * scalar}; } + Vec3 operator/(float scalar) const { return {x / scalar, y / scalar, z / scalar}; } + + Vec3 operator*(const Vec3 &rhs) const { return {x * rhs.x, y * rhs.y, z * rhs.z}; } + + Vec3 &operator+=(const Vec3 &rhs) { x += rhs.x; y += rhs.y; z += rhs.z; return *this; } + Vec3 &operator-=(const Vec3 &rhs) { x -= rhs.x; y -= rhs.y; z -= rhs.z; return *this; } + Vec3 &operator*=(float scalar) { x *= scalar; y *= scalar; z *= scalar; return *this; } + Vec3 &operator/=(float scalar) { x /= scalar; y /= scalar; z /= scalar; return *this; } + + Vec3 operator-() const { return {-x, -y, -z}; } + + bool operator==(const Vec3 &rhs) const { return x == rhs.x && y == rhs.y && z == rhs.z; } + bool operator!=(const Vec3 &rhs) const { return !(*this == rhs); } + + float Length() const { return std::sqrt(x * x + y * y + z * z); } + float LengthSquared() const { return x * x + y * y + z * z; } + + Vec3 Normalized() const { - x += o.x; - y += o.y; - z += o.z; - return *this; - } - Vec3 &operator-=(const Vec3 &o) - { - x -= o.x; - y -= o.y; - z -= o.z; - return *this; - } - Vec3 &operator*=(float s) - { - x *= s; - y *= s; - z *= s; - return *this; - } - Vec3 &operator/=(float s) - { - x /= s; - y /= s; - z /= s; - return *this; + float len = Length(); + return len != 0 ? *this / len : Vec3(0.0f); } - friend Vec3 operator+(Vec3 a, const Vec3 &b) { return a += b; } - friend Vec3 operator-(Vec3 a, const Vec3 &b) { return a -= b; } - friend Vec3 operator*(Vec3 v, float s) { return v *= s; } - friend Vec3 operator/(Vec3 v, float s) { return v /= s; } + void Normalize() + { + float len = Length(); + if (len != 0) + { + x /= len; + y /= len; + z /= len; + } + } + + float Dot(const Vec3 &rhs) const { return x * rhs.x + y * rhs.y + z * rhs.z; } + + Vec3 Cross(const Vec3 &rhs) const + { + return Vec3( + y * rhs.z - z * rhs.y, + z * rhs.x - x * rhs.z, + x * rhs.y - y * rhs.x + ); + } + + void Clamp(const Vec3 &min, const Vec3 &max) + { + x = std::max(min.x, std::min(x, max.x)); + y = std::max(min.y, std::min(y, max.y)); + z = std::max(min.z, std::min(z, max.z)); + } + + static Vec3 Lerp(const Vec3 &a, const Vec3 &b, float t) + { + return a + (b - a) * t; + } + + static float Distance(const Vec3 &a, const Vec3 &b) + { + return (a - b).Length(); + } + + friend std::ostream &operator<<(std::ostream &os, const Vec3 &v) + { + return os << "(" << v.x << ", " << v.y << ", " << v.z << ")"; + } }; - } -} + inline Vec3 operator*(float scalar, const Vec3 &v) { return v * scalar; } + + } // namespace types +} // namespace core diff --git a/src/src/core/utils/FileDialog.cpp b/src/src/core/utils/FileDialog.cpp index 566fb2c..846e3cf 100644 --- a/src/src/core/utils/FileDialog.cpp +++ b/src/src/core/utils/FileDialog.cpp @@ -2,6 +2,7 @@ #define NOMINMAX #include #include +#include #include #include #include @@ -9,17 +10,18 @@ // Correctly null-terminated filter strings static std::unordered_map filters = { - { FileDialogType::Images, "Image Files\0*.png;*.jpg;*.jpeg;*.bmp;*.tga;*.gif;*.dds\0" }, - { FileDialogType::Scenes, "CreateScene Files\0*.cene;*.cscene;*.yaml\0" }, - { FileDialogType::Audio, "Audio Files\0*.mp3;*.wav;*.ogg;*.flac;*.aac\0" }, - { FileDialogType::Scripts, "Lua Scripts\0*.lua\0" }, - { FileDialogType::Shaders, "Shader Files\0*.glsl;*.vert;*.frag;*.hlsl\0" }, - { FileDialogType::Fonts, "Font Files\0*.ttf;*.otf;*.fnt\0" }, - { FileDialogType::Models, "3D Models\0*.obj;*.fbx;*.gltf;*.dae\0" }, + { FileDialogType::Images, "Image Files\0*.png;*.jpg;*.jpeg;*.bmp;*.tga;*.gif;*.dds\0All Files\0*.*\0" }, + { FileDialogType::Scenes, "CreateScene Files\0*.cene;*.cscene;*.yaml\0All Files\0*.*\0" }, + { FileDialogType::Audio, "Audio Files\0*.mp3;*.wav;*.ogg;*.flac;*.aac\0All Files\0*.*\0" }, + { FileDialogType::Scripts, "Lua Scripts\0*.lua\0All Files\0*.*\0" }, + { FileDialogType::Shaders, "Shader Files\0*.glsl;*.vert;*.frag;*.hlsl\0All Files\0*.*\0" }, + { FileDialogType::Fonts, "Font Files\0*.ttf;*.otf;*.fnt\0All Files\0*.*\0" }, + { FileDialogType::Models, "3D Models\0*.obj;*.fbx;*.gltf;*.dae\0All Files\0*.*\0" }, { FileDialogType::All, "All Files\0*.*\0" } }; + std::string OpenFileDialog(FileDialogType type) { char file[260] = { 0 }; OPENFILENAMEA ofn = {}; @@ -55,3 +57,47 @@ std::string SaveFileDialog(FileDialogType type) { return result ? std::string(file) : ""; } + +std::string CreateFileDialog(FileDialogType type) { + char file[260] = { 0 }; + OPENFILENAMEA ofn = {}; + ofn.lStructSize = sizeof(ofn); + + const char* filterStr = filters.count(type) ? filters[type] : filters[FileDialogType::All]; + ofn.lpstrFilter = filterStr; + ofn.lpstrFile = file; + ofn.nMaxFile = sizeof(file); + ofn.Flags = OFN_OVERWRITEPROMPT | OFN_NOCHANGEDIR; + + + const char* defaultExt = nullptr; + switch (type) { + case FileDialogType::Images: defaultExt = "png"; break; + case FileDialogType::Scenes: defaultExt = "cene"; break; + case FileDialogType::Audio: defaultExt = "mp3"; break; + case FileDialogType::Scripts: defaultExt = "lua"; break; + case FileDialogType::Shaders: defaultExt = "glsl"; break; + case FileDialogType::Fonts: defaultExt = "ttf"; break; + case FileDialogType::Models: defaultExt = "obj"; break; + default: defaultExt = "txt"; break; + } + ofn.lpstrDefExt = defaultExt; + + auto originalPath = std::filesystem::current_path(); + bool result = GetSaveFileNameA(&ofn); + std::filesystem::current_path(originalPath); + + if (result && file[0] != '\0') { + std::filesystem::path filePath(file); + + if (!std::filesystem::exists(filePath)) { + std::ofstream outFile(filePath, std::ios::out | std::ios::trunc); + outFile.close(); + } + + return filePath.string(); + } + + return ""; +} + diff --git a/src/src/core/utils/FileDialog.h b/src/src/core/utils/FileDialog.h index c8e7844..27854cf 100644 --- a/src/src/core/utils/FileDialog.h +++ b/src/src/core/utils/FileDialog.h @@ -15,3 +15,5 @@ enum class FileDialogType { std::string OpenFileDialog(FileDialogType type); std::string SaveFileDialog(FileDialogType type); +std::string CreateFileDialog(FileDialogType type); + diff --git a/src/src/editor/windows/Inspector.cpp b/src/src/editor/windows/Inspector.cpp index dff9d35..9c21a25 100644 --- a/src/src/editor/windows/Inspector.cpp +++ b/src/src/editor/windows/Inspector.cpp @@ -380,7 +380,20 @@ void DrawInspectorUI(std::shared_ptr selected) 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); + + { + float directionAngleDeg = glm::degrees(std::atan2(settings.direction.y, settings.direction.x)); + + if (directionAngleDeg < 0.0f) + directionAngleDeg += 360.0f; + + if (ImGui::DragFloat("Direction", &directionAngleDeg, 0.5f, 0.0f, 360.0f)) + { + float rad = glm::radians(directionAngleDeg); + settings.direction.x = std::cos(rad); + settings.direction.y = std::sin(rad); + } + } { float spreadDeg = glm::degrees(settings.spread);