diff --git a/resources/shaders/fragment/uber.glsl b/resources/shaders/fragment/uber.glsl index d80d8e76..bda13827 100644 --- a/resources/shaders/fragment/uber.glsl +++ b/resources/shaders/fragment/uber.glsl @@ -3,20 +3,19 @@ out vec4 FragColor; // Final fragment color in vec3 FragPos; // Fragment position in world space -in vec3 Normal; // Normal in world space +in vec3 Normal; // normal in world space uniform vec3 viewPos; // Camera position struct PointLight { vec3 position; // Light position - vec3 diffuse; // Diffuse light color - vec3 specular; // Specular light color + vec3 color; // Diffuse light color + float range; // Specular light color }; struct DirectionalLight { vec3 direction; // Light position - vec3 diffuse; // Diffuse light color - vec3 specular; // Specular light color + vec3 color; // Diffuse light color }; uniform vec3 ambientLight; @@ -38,33 +37,39 @@ uniform Material material; void main() { vec3 result = ambientLight * material.diffuse; + vec3 normal = normalize(Normal); for (int i = 0; i < numPointLights; ++i) { - // Diffuse - vec3 lightDir = normalize(pointLights[i].position - FragPos); - float diff = max(dot(Normal, lightDir), 0.0); - vec3 diffuse = pointLights[i].diffuse * diff * material.diffuse; - - // Specular - vec3 viewDir = normalize(viewPos - FragPos); - vec3 reflectDir = reflect(-lightDir, Normal); - float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - vec3 specular = pointLights[i].specular * spec * material.specular; - - result += diffuse + specular; + float relativeIntensity = 1.0 - (length(pointLights[i].position - FragPos) / + pointLights[i].range); + + if (relativeIntensity > 0) { + // Diffuse + vec3 lightDir = normalize(pointLights[i].position - FragPos); + float diff = max(dot(normal, lightDir), 0.0); + vec3 diffuse = pointLights[i].color * diff * material.diffuse; + + // Specular + vec3 viewDir = normalize(viewPos - FragPos); + vec3 reflectDir = reflect(-lightDir, normal); + float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); + vec3 specular = pointLights[i].color * spec * material.specular; + + result += relativeIntensity * (diffuse + specular); + } } for (int i = 0; i < numDirectionalLights; ++i) { // Diffuse vec3 lightDir = directionalLights[i].direction; - float diff = max(dot(Normal, lightDir), 0.0); - vec3 diffuse = directionalLights[i].diffuse * diff * material.diffuse; + float diff = max(dot(normal, lightDir), 0.0); + vec3 diffuse = directionalLights[i].color * diff * material.diffuse; // Specular vec3 viewDir = normalize(viewPos - FragPos); - vec3 reflectDir = reflect(-lightDir, Normal); + vec3 reflectDir = reflect(-lightDir, normal); float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess); - vec3 specular = directionalLights[i].specular * spec * material.specular; + vec3 specular = directionalLights[i].color * spec * material.specular; result += diffuse + specular; } diff --git a/src/AssetManager/Image.cpp b/src/AssetManager/Image.cpp index 4d5e909e..e615d4e6 100644 --- a/src/AssetManager/Image.cpp +++ b/src/AssetManager/Image.cpp @@ -6,12 +6,6 @@ #include "stb_image.h" #include "stb_image_write.h" -#define GL_SILENCE_DEPRECATION -#if defined(IMGUI_IMPL_OPENGL_ES2) -#include -#endif -#include - #include namespace shkyera { diff --git a/src/AssetManager/Image.hpp b/src/AssetManager/Image.hpp index debc01bc..3945743a 100644 --- a/src/AssetManager/Image.hpp +++ b/src/AssetManager/Image.hpp @@ -19,6 +19,9 @@ class Image : public Asset { */ Image(const std::string& path); + Image(const Image& other) = delete; + Image& operator=(const Image& other) = delete; + /** * @brief Load an image from a file. * diff --git a/src/AssetManager/Mesh.cpp b/src/AssetManager/Mesh.cpp index cf6b6df5..56bdae74 100644 --- a/src/AssetManager/Mesh.cpp +++ b/src/AssetManager/Mesh.cpp @@ -332,8 +332,8 @@ Mesh* Mesh::Factory::createCylinder() { } Mesh* Mesh::Factory::createSphere() { - const int stacks = 48; - const int sectors = 96; + const int stacks = 24; + const int sectors = 48; const float radius = 1.0f; std::vector vertices; diff --git a/src/AssetManager/Mesh.hpp b/src/AssetManager/Mesh.hpp index 96a808f6..09efe90e 100644 --- a/src/AssetManager/Mesh.hpp +++ b/src/AssetManager/Mesh.hpp @@ -25,6 +25,10 @@ class Mesh : public Asset { Mesh(const std::string& filepath); Mesh(std::vector vertices, std::vector indices); + + Mesh(const Mesh& other) = delete; + Mesh& operator=(const Mesh& other) = delete; + ~Mesh(); void bind() const { glBindVertexArray(_vao); } diff --git a/src/AssetManager/Shader.hpp b/src/AssetManager/Shader.hpp index 39999305..c574d643 100644 --- a/src/AssetManager/Shader.hpp +++ b/src/AssetManager/Shader.hpp @@ -14,6 +14,8 @@ class Shader : public Asset { }; Shader(const std::string& filepath, Type type); + Shader(const Shader& other) = delete; + Shader& operator=(const Shader& other) = delete; ~Shader(); diff --git a/src/AssetManager/Wireframe.hpp b/src/AssetManager/Wireframe.hpp index 75256e32..346a7b67 100644 --- a/src/AssetManager/Wireframe.hpp +++ b/src/AssetManager/Wireframe.hpp @@ -20,6 +20,10 @@ class Wireframe : public Asset { Wireframe(const std::string& filepath); Wireframe(const std::vector& edges); + + Wireframe(const Wireframe& other) = delete; + Wireframe& operator=(const Wireframe& other) = delete; + ~Wireframe(); void bind() const { glBindVertexArray(_vao); } diff --git a/src/Components/AmbientLightComponent.hpp b/src/Components/AmbientLightComponent.hpp new file mode 100644 index 00000000..316d32dc --- /dev/null +++ b/src/Components/AmbientLightComponent.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include +#include + +#include +#include + +namespace shkyera { + +class AmbientLightComponent : public BaseComponent { +public: + float intensity = 1; + glm::vec3 color = {0.1, 0.1, 0.1}; +}; + +} // namespace shkyera diff --git a/src/Components/CMakeLists.txt b/src/Components/CMakeLists.txt index 20c28611..1f1d4a60 100644 --- a/src/Components/CMakeLists.txt +++ b/src/Components/CMakeLists.txt @@ -10,6 +10,7 @@ add_library( ${CMAKE_CURRENT_LIST_DIR}/WireframeComponent.hpp ${CMAKE_CURRENT_LIST_DIR}/PointLightComponent.hpp ${CMAKE_CURRENT_LIST_DIR}/DirectionalLightComponent.hpp + ${CMAKE_CURRENT_LIST_DIR}/AmbientLightComponent.hpp ${CMAKE_CURRENT_LIST_DIR}/BoxColliderComponent.hpp ${CMAKE_CURRENT_LIST_DIR}/SkyboxComponent.hpp ) diff --git a/src/Components/CameraComponent.hpp b/src/Components/CameraComponent.hpp index 95e443c7..80849588 100644 --- a/src/Components/CameraComponent.hpp +++ b/src/Components/CameraComponent.hpp @@ -28,9 +28,9 @@ class CameraComponent { glm::vec3 orientation = transformComponent.getOrientation(); glm::vec3 front; - front.x = cos(orientation.y) * cos(orientation.x); - front.y = sin(orientation.x); - front.z = sin(orientation.y) * cos(orientation.x); + front.x = std::cos(orientation.y) * std::cos(orientation.x); + front.y = std::sin(orientation.x); + front.z = std::sin(orientation.y) * std::cos(orientation.x); front = glm::normalize(front); glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); diff --git a/src/Components/DirectionalLightComponent.hpp b/src/Components/DirectionalLightComponent.hpp index f0e3a5ef..b2af3f80 100644 --- a/src/Components/DirectionalLightComponent.hpp +++ b/src/Components/DirectionalLightComponent.hpp @@ -10,8 +10,8 @@ namespace shkyera { class DirectionalLightComponent : public BaseComponent { public: - glm::vec3 diffuse = {0.5, 0.5, 0.5}; - glm::vec3 specular = {0.5, 0.5, 0.5}; + float intensity = 0.5; + glm::vec3 color = {1.0f, 1.0f, 1.0f}; }; } // namespace shkyera diff --git a/src/Components/PointLightComponent.hpp b/src/Components/PointLightComponent.hpp index 72323111..8e3875db 100644 --- a/src/Components/PointLightComponent.hpp +++ b/src/Components/PointLightComponent.hpp @@ -10,8 +10,9 @@ namespace shkyera { class PointLightComponent : public BaseComponent { public: - glm::vec3 diffuse = {0.5, 0.5, 0.5}; - glm::vec3 specular = {0.5, 0.5, 0.5}; + float intensity = 1; + float range = 5; + glm::vec3 color = {1, 1, 1}; }; } // namespace shkyera diff --git a/src/Components/SkyboxComponent.hpp b/src/Components/SkyboxComponent.hpp index 504f81bd..a5afaeb5 100644 --- a/src/Components/SkyboxComponent.hpp +++ b/src/Components/SkyboxComponent.hpp @@ -9,7 +9,6 @@ namespace shkyera { class SkyboxComponent : public BaseComponent { public: - glm::vec3 ambientLight = {0.1, 0.1, 0.1}; CubeMap skyboxCubeMap; }; diff --git a/src/Components/TransformComponent.hpp b/src/Components/TransformComponent.hpp index 61e1cd06..42cfc2be 100644 --- a/src/Components/TransformComponent.hpp +++ b/src/Components/TransformComponent.hpp @@ -4,6 +4,8 @@ #include #include #include + +#include #include namespace shkyera { @@ -28,9 +30,9 @@ class TransformComponent : public BaseComponent { void setScale(const glm::vec3& scale) { _scale = scale; } glm::mat4 getRotationMatrix() const { - glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0f), glm::radians(_orientation.y), glm::vec3(0.0f, 1.0f, 0.0f)); - rotationMatrix = glm::rotate(rotationMatrix, glm::radians(_orientation.x), glm::vec3(1.0f, 0.0f, 0.0f)); - rotationMatrix = glm::rotate(rotationMatrix, glm::radians(_orientation.z), glm::vec3(0.0f, 0.0f, 1.0f)); + glm::mat4 rotationMatrix = glm::rotate(glm::mat4(1.0f), _orientation.y, glm::vec3(0.0f, 1.0f, 0.0f)); + rotationMatrix = glm::rotate(rotationMatrix, _orientation.x, glm::vec3(1.0f, 0.0f, 0.0f)); + rotationMatrix = glm::rotate(rotationMatrix, _orientation.z, glm::vec3(0.0f, 0.0f, 1.0f)); return rotationMatrix; } diff --git a/src/ECS/Registry.cpp b/src/ECS/Registry.cpp index 7281ee1f..842d2119 100644 --- a/src/ECS/Registry.cpp +++ b/src/ECS/Registry.cpp @@ -6,6 +6,7 @@ static constexpr Entity INITIAL_ENTITIES = 100; Registry::Registry() : _entityProvider(INITIAL_ENTITIES) { _camera = addEntity(); + _environment = addEntity(); } Entity Registry::addEntity() { @@ -39,4 +40,8 @@ Entity Registry::getCamera() const { return _camera; } +Entity Registry::getEnvironment() const { + return _environment; +} + } // namespace shkyera diff --git a/src/ECS/Registry.hpp b/src/ECS/Registry.hpp index 17a4f885..2378032f 100644 --- a/src/ECS/Registry.hpp +++ b/src/ECS/Registry.hpp @@ -153,6 +153,8 @@ class Registry { } Entity getCamera() const; + + Entity getEnvironment() const; private: /** @@ -189,6 +191,7 @@ class Registry { EntityProvider _entityProvider; //< Manages the creation and management of entities. Entity _camera; + Entity _environment; std::unordered_set _selectedEntities; }; diff --git a/src/InputManager/InputManager.cpp b/src/InputManager/InputManager.cpp index d974c975..c37763bc 100644 --- a/src/InputManager/InputManager.cpp +++ b/src/InputManager/InputManager.cpp @@ -29,6 +29,12 @@ glm::vec2 InputManager::getMousePosition(CoordinateSystem system) { return {0, 0}; } +bool InputManager::isMouseInside(CoordinateSystem system) { + const auto& mousePosition = getRelativeMousePosition(InputManager::CoordinateSystem::SCENE); + return 0.0f < mousePosition.x && 0.0f < mousePosition.y && mousePosition.x < 1.0f && mousePosition.y < 1.0f; +} + + void InputManager::registerKeyCallback(Key key, std::function callback) { _keyCallbacks[key].push_back(callback); } diff --git a/src/InputManager/InputManager.hpp b/src/InputManager/InputManager.hpp index 9209f670..664ba236 100644 --- a/src/InputManager/InputManager.hpp +++ b/src/InputManager/InputManager.hpp @@ -23,6 +23,7 @@ class InputManager{ glm::vec2 getRelativeMousePosition(CoordinateSystem system); glm::vec2 getMousePosition(CoordinateSystem system); + bool isMouseInside(CoordinateSystem system); void registerKeyCallback(Key key, std::function callback); diff --git a/src/Math/CMakeLists.txt b/src/Math/CMakeLists.txt index ebd4587f..a0331524 100644 --- a/src/Math/CMakeLists.txt +++ b/src/Math/CMakeLists.txt @@ -3,6 +3,7 @@ add_library( STATIC ${CMAKE_CURRENT_LIST_DIR}/Box.cpp + ${CMAKE_CURRENT_LIST_DIR}/Utils.cpp ) target_include_directories( diff --git a/src/Math/Utils.cpp b/src/Math/Utils.cpp new file mode 100644 index 00000000..ec313f4f --- /dev/null +++ b/src/Math/Utils.cpp @@ -0,0 +1,16 @@ +#include +#include + +namespace shkyera { + +float toRadians(float degrees) +{ + return degrees * M_PI / 180; +} + +float toDegrees(float radians) +{ + return radians * 180 / M_PI; +} + +} // namespace shkyera diff --git a/src/Math/Utils.hpp b/src/Math/Utils.hpp new file mode 100644 index 00000000..3364ccef --- /dev/null +++ b/src/Math/Utils.hpp @@ -0,0 +1,11 @@ +#pragma once + +#include + +namespace shkyera { + +float toRadians(float degrees); + +float toDegrees(float radians); + +} // namespace shkyera diff --git a/src/Systems/CameraMovementSystem.cpp b/src/Systems/CameraMovementSystem.cpp index 15f1c284..83022d01 100644 --- a/src/Systems/CameraMovementSystem.cpp +++ b/src/Systems/CameraMovementSystem.cpp @@ -6,7 +6,7 @@ namespace shkyera { constexpr static float MOVEMENT_SPEED = 0.6; -constexpr static float MOUSE_SENSITIVITY = 0.05; +constexpr static float MOUSE_SENSITIVITY = 0.2; CameraMovementSystem::CameraMovementSystem(std::shared_ptr registry) : _registry(registry), _cameraControl(false) { @@ -18,9 +18,13 @@ void CameraMovementSystem::update() {} void CameraMovementSystem::setupCameraMovement() { auto& inputManager = InputManager::getInstance(); - inputManager.registerMouseButtonDownCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { - _cameraControl = true; + inputManager.registerMouseButtonDownCallback(GLFW_MOUSE_BUTTON_LEFT, [this, &inputManager]() { + if(inputManager.isMouseInside(InputManager::CoordinateSystem::SCENE)) + { + _cameraControl = true; + } }); + inputManager.registerMouseButtonUpCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { _cameraControl = false; }); diff --git a/src/Systems/ObjectSelectionSystem.cpp b/src/Systems/ObjectSelectionSystem.cpp index bb3da696..5a5179e5 100644 --- a/src/Systems/ObjectSelectionSystem.cpp +++ b/src/Systems/ObjectSelectionSystem.cpp @@ -13,23 +13,38 @@ namespace shkyera { ObjectSelectionSystem::ObjectSelectionSystem(std::shared_ptr registry) : _registry(registry) { InputManager::getInstance().registerMouseButtonDownCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { - tryToSelectObject(); + if(!InputManager::getInstance().isMouseInside(InputManager::CoordinateSystem::SCENE)) { + _objectSelectedOnMouseDown = std::nullopt; + return; + } + + _objectSelectedOnMouseDown = getHoveredObject(); + }); + InputManager::getInstance().registerMouseButtonUpCallback(GLFW_MOUSE_BUTTON_LEFT, [this]() { + if(!_objectSelectedOnMouseDown.has_value() && !InputManager::getInstance().isMouseInside(InputManager::CoordinateSystem::SCENE)) { + _objectSelectedOnMouseDown = std::nullopt; + return; + } + + const auto hoveredCurrently = getHoveredObject(); + if(hoveredCurrently.has_value() && _objectSelectedOnMouseDown.has_value() && *hoveredCurrently == *_objectSelectedOnMouseDown) + { + _registry->clearSelectedEntities(); + _registry->selectEntity(*hoveredCurrently); + _objectSelectedOnMouseDown = std::nullopt; + } }); } -void ObjectSelectionSystem::tryToSelectObject() { +std::optional ObjectSelectionSystem::getHoveredObject() +{ const auto& camera = _registry->getCamera(); const auto& mousePosition = InputManager::getInstance().getRelativeMousePosition(InputManager::CoordinateSystem::SCENE); - - if(mousePosition.x < 0 || mousePosition.y < 0 || mousePosition.x >= 1.0 || mousePosition.y >= 1.0) { - return; - } - const auto& cameraTransform = _registry->getComponent(camera); const auto& cameraComponent = _registry->getComponent(camera); auto ray = cameraComponent.getRayAt(cameraTransform, mousePosition.x, 1 - mousePosition.y); - float closestDistance = FLT_MAX; + float closestDistance = std::numeric_limits::max(); std::optional closestEntity; for(const auto& [entity, boxColliderComponent] : _registry->getComponentSet>()) { const auto& transform = _registry->getComponent(entity); @@ -42,11 +57,8 @@ void ObjectSelectionSystem::tryToSelectObject() { } } - if(closestEntity) - { - _registry->clearSelectedEntities(); - _registry->selectEntity(*closestEntity); - } + return closestEntity; } + } diff --git a/src/Systems/ObjectSelectionSystem.hpp b/src/Systems/ObjectSelectionSystem.hpp index 7dfec68b..dbc58f1d 100644 --- a/src/Systems/ObjectSelectionSystem.hpp +++ b/src/Systems/ObjectSelectionSystem.hpp @@ -10,8 +10,9 @@ class ObjectSelectionSystem { ObjectSelectionSystem(std::shared_ptr registry); private: - void tryToSelectObject(); + std::optional getHoveredObject(); + std::optional _objectSelectedOnMouseDown; std::shared_ptr _registry; }; diff --git a/src/Systems/RenderingSystem.cpp b/src/Systems/RenderingSystem.cpp index fa326c0e..8161b272 100644 --- a/src/Systems/RenderingSystem.cpp +++ b/src/Systems/RenderingSystem.cpp @@ -5,8 +5,9 @@ #include #include #include -#include #include +#include +#include #include namespace shkyera { @@ -158,19 +159,19 @@ void RenderingSystem::renderModels() _modelShaderProgram.setUniform("projectionMatrix", projectionMatrix); _modelShaderProgram.setUniform("viewPos", cameraTransform.getPosition()); - glm::vec3 ambientLight{0, 0, 0}; - for(const auto& skybox : _registry->getComponents()) + glm::vec3 ambientColor{0, 0, 0}; + for(const auto& ambientLightComponent : _registry->getComponents()) { - ambientLight += skybox.ambientLight; + ambientColor += ambientLightComponent.color * ambientLightComponent.intensity; } - _modelShaderProgram.setUniform("ambientLight", ambientLight); + _modelShaderProgram.setUniform("ambientLight", ambientColor); int pointLightIndex = 0; for(const auto& [entity, pointLightComponent] : _registry->getComponentSet()) { const auto& transformComponent = _registry->getComponent(entity); _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].position", transformComponent.getPosition()); - _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].diffuse", pointLightComponent.diffuse); - _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].specular", pointLightComponent.specular); + _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].color", pointLightComponent.intensity * pointLightComponent.color); + _modelShaderProgram.setUniform("pointLights[" + std::to_string(pointLightIndex) + "].range", pointLightComponent.range); ++pointLightIndex; } _modelShaderProgram.setUniform("numPointLights", pointLightIndex); @@ -180,9 +181,8 @@ void RenderingSystem::renderModels() const auto& rotationMatrix = _registry->getComponent(entity).getRotationMatrix(); auto lightDirection = rotationMatrix * glm::vec4{0, 0, 1, 1}; - _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) + "].direction", glm::vec3{lightDirection.x, lightDirection.y, lightDirection.z}); - _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) + "].diffuse", pointLightComponent.diffuse); - _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) + "].specular", pointLightComponent.specular); + _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) + "].direction", glm::vec3{lightDirection}); + _modelShaderProgram.setUniform("directionalLights[" + std::to_string(directionalLightIndex) + "].color", pointLightComponent.intensity * pointLightComponent.color); ++directionalLightIndex; } _modelShaderProgram.setUniform("numDirectionalLights", directionalLightIndex); diff --git a/src/main.cpp b/src/main.cpp index deeb7aa4..2807cb3d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -81,7 +82,7 @@ void loadScene(std::shared_ptr registry) { // Add Point Light auto pointLight = registry->addEntity(); registry->addComponent(pointLight); - registry->getComponent(pointLight).setPosition({-2, 5, 5}); + registry->getComponent(pointLight).setPosition({-2, 2, 2}); registry->addComponent(pointLight); registry->getComponent(pointLight).setName("Point Light"); registry->addComponent(pointLight); @@ -92,6 +93,7 @@ void loadScene(std::shared_ptr registry) { registry->addComponent(sky); registry->getComponent(sky).setName("Sky"); registry->addComponent(sky); + registry->addComponent(sky); const auto skyboxUp = AssetManager::getInstance().getAsset("resources/skyboxes/day/py.png"); const auto skyboxDown = AssetManager::getInstance().getAsset("resources/skyboxes/day/ny.png"); @@ -99,8 +101,8 @@ void loadScene(std::shared_ptr registry) { const auto skyboxRight = AssetManager::getInstance().getAsset("resources/skyboxes/day/px.png"); const auto skyboxFront = AssetManager::getInstance().getAsset("resources/skyboxes/day/pz.png"); const auto skyboxBack = AssetManager::getInstance().getAsset("resources/skyboxes/day/nz.png"); - registry->addComponent(sky); - registry->getComponent(sky).skyboxCubeMap.loadFaces(skyboxUp, skyboxDown, skyboxLeft, skyboxRight, skyboxFront, skyboxBack); + registry->addComponent(registry->getEnvironment()); + registry->getComponent(registry->getEnvironment()).skyboxCubeMap.loadFaces(skyboxUp, skyboxDown, skyboxLeft, skyboxRight, skyboxFront, skyboxBack); } int main() { diff --git a/src/ui/CMakeLists.txt b/src/ui/CMakeLists.txt index 2bea4cf8..38cbde1a 100644 --- a/src/ui/CMakeLists.txt +++ b/src/ui/CMakeLists.txt @@ -7,12 +7,14 @@ add_library( ${CMAKE_CURRENT_LIST_DIR}/Common/Style.cpp ${CMAKE_CURRENT_LIST_DIR}/Common/FileSelector.cpp + ${CMAKE_CURRENT_LIST_DIR}/Common/ColorSelector.cpp + ${CMAKE_CURRENT_LIST_DIR}/Common/FloatSlider.cpp ${CMAKE_CURRENT_LIST_DIR}/Components/TransformComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Components/ModelComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Components/PointLightComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Components/DirectionalLightComponentUI.cpp - ${CMAKE_CURRENT_LIST_DIR}/Components/SkyboxComponentUI.cpp + ${CMAKE_CURRENT_LIST_DIR}/Components/AmbientLightComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Components/WireframeComponentUI.cpp ${CMAKE_CURRENT_LIST_DIR}/Widgets/PreviewWidget.cpp diff --git a/src/ui/Common/ColorSelector.cpp b/src/ui/Common/ColorSelector.cpp new file mode 100644 index 00000000..f9064a85 --- /dev/null +++ b/src/ui/Common/ColorSelector.cpp @@ -0,0 +1,38 @@ +#include "imgui.h" + +#include +#include + +namespace shkyera { + +ColorSelector::ColorSelector(const std::string& title) : _title(title), _imguiIdentifier("##" + _title + "ColorSelector") {} + +ColorSelector::ColorSelector(const std::string& title, const glm::vec3& color) : _title(title), _imguiIdentifier("##" + _title + "ColorSelector"), _color(color) {} + +void ColorSelector::setUpdateCallback(std::function callback) { + _updateCallback = callback; +} + +void ColorSelector::draw() { + std::array newColor = { _color.x, _color.y, _color.z }; + + ImGui::PushItemWidth(50); + ImGui::TextUnformatted(_title.c_str()); + ImGui::PopItemWidth(); + + ImGui::SameLine(120); + ImGui::PushItemWidth(190); + ImGui::ColorEdit3(_imguiIdentifier.c_str(), newColor.data(), ImGuiColorEditFlags_PickerHueBar); + ImGui::PopItemWidth(); + + if(newColor[0] != _color.x || newColor[0] != _color.y || newColor[0] != _color.y) + { + _color = glm::vec3{newColor[0], newColor[1], newColor[2]}; + if(_updateCallback) + { + _updateCallback(_color); + } + } +} + +} diff --git a/src/ui/Common/ColorSelector.hpp b/src/ui/Common/ColorSelector.hpp new file mode 100644 index 00000000..5d9193d2 --- /dev/null +++ b/src/ui/Common/ColorSelector.hpp @@ -0,0 +1,27 @@ +#pragma once + +#include +#include + +#include +#include "imgui.h" + +namespace shkyera { + +class ColorSelector { + public: + ColorSelector(const std::string& title); + ColorSelector(const std::string& title, const glm::vec3& color); + + void setUpdateCallback(std::function callback); + + void draw(); + + private: + std::string _title; + std::string _imguiIdentifier; + glm::vec3 _color; + std::function _updateCallback; +}; + +} diff --git a/src/ui/Common/FloatSlider.cpp b/src/ui/Common/FloatSlider.cpp new file mode 100644 index 00000000..eca08d1f --- /dev/null +++ b/src/ui/Common/FloatSlider.cpp @@ -0,0 +1,37 @@ +#include "imgui.h" + +#include +#include + +namespace shkyera { + +FloatSlider::FloatSlider(const std::string& title, float min, float max) : _title(title), _imguiIdentifier("##" + _title + "Slider"), _value((min + max) / 2), _minimum(min), _maximum(max) {} + +FloatSlider::FloatSlider(const std::string& title, float value, float min, float max) : _title(title), _imguiIdentifier("##" + _title + "Slider"), _value(value), _minimum(min), _maximum(max) {} + +void FloatSlider::setUpdateCallback(std::function callback) { + _updateCallback = callback; +} + +void FloatSlider::draw() { + float oldValue = _value; + + ImGui::PushItemWidth(50); + ImGui::TextUnformatted(_title.c_str()); + ImGui::PopItemWidth(); + + ImGui::SameLine(120); + ImGui::PushItemWidth(190); + ImGui::SliderFloat(_imguiIdentifier.c_str(), &_value, _minimum, _maximum, "%.3f"); + ImGui::PopItemWidth(); + + if(oldValue != _value) + { + if(_updateCallback) + { + _updateCallback(_value); + } + } +} + +} diff --git a/src/ui/Common/FloatSlider.hpp b/src/ui/Common/FloatSlider.hpp new file mode 100644 index 00000000..23823cf6 --- /dev/null +++ b/src/ui/Common/FloatSlider.hpp @@ -0,0 +1,28 @@ +#pragma once + +#include +#include + +#include +#include "imgui.h" + +namespace shkyera { + +class FloatSlider { + public: + FloatSlider(const std::string& title, float min, float max); + FloatSlider(const std::string& title, float value, float min, float max); + + void setUpdateCallback(std::function callback); + + void draw(); + + private: + std::string _title; + std::string _imguiIdentifier; + float _value; + float _minimum, _maximum; + std::function _updateCallback; +}; + +} diff --git a/src/ui/Common/Style.cpp b/src/ui/Common/Style.cpp index 8855a374..8c8006ae 100644 --- a/src/ui/Common/Style.cpp +++ b/src/ui/Common/Style.cpp @@ -20,19 +20,14 @@ ImFont* BIG_FONT = nullptr; ImFont* HUGE_FONT = nullptr; /******** COLORS *********/ -const ImVec4 BACKGROUND_COLOR = - ImVec4(0.17f, 0.17f, 0.17f, 1.0f); ///< Background color. -const ImVec4 TEXT_COLOR = ImVec4(0.86f, 0.86f, 0.86f, 1.0f); ///< Text color. -const ImVec4 DISABLED_TEXT_COLOR = - ImVec4(0.86f, 0.93f, 0.89f, 0.28f); ///< Disabled text color. -const ImVec4 ACCENT_COLOR = ImVec4(0.4f, 0.05f, 0.7f, 1.0f); ///< Accent color. -const ImVec4 STRONG_ACCENT_COLOR = - ImVec4(0.5f, 0.06f, 0.82f, 1.0f); ///< Strong accent color. -const ImVec4 GREY = ImVec4(0.3f, 0.3f, 0.3f, 1.0f); ///< Grey color. -const ImVec4 LIGHT_GREY = - ImVec4(0.8f, 0.8f, 0.8f, 1.0f); ///< Light grey color. -const ImVec4 DARK_ACCENT = - ImVec4(0.1f, 0.1f, 0.1f, 1.0f); ///< Dark accent color. -const ImVec4 BLACK = ImVec4(0.0f, 0.0f, 0.0f, 0.0f); ///< Black color. +const ImVec4 BACKGROUND_COLOR = ImVec4(0.15f, 0.15f, 0.15f, 1.0f); +const ImVec4 TEXT_COLOR = ImVec4(0.86f, 0.86f, 0.86f, 1.0f); +const ImVec4 DISABLED_TEXT_COLOR = ImVec4(0.86f, 0.93f, 0.89f, 0.28f); +const ImVec4 ACCENT_COLOR = ImVec4(0.22f, 0.14f, 0.7f, 1.0f); +const ImVec4 STRONG_ACCENT_COLOR = ImVec4(0.46f, 0.02f, 0.9f, 1.0f); +const ImVec4 GREY = ImVec4(0.3f, 0.3f, 0.3f, 1.0f); +const ImVec4 LIGHT_GREY = ImVec4(0.8f, 0.8f, 0.8f, 1.0f); +const ImVec4 DARK_ACCENT = ImVec4(0.05f, 0.05f, 0.05f, 1.0f); +const ImVec4 BLACK = ImVec4(0.0f, 0.0f, 0.0f, 0.0f); } // namespace shkyera::style \ No newline at end of file diff --git a/src/ui/Components/AmbientLightComponentUI.cpp b/src/ui/Components/AmbientLightComponentUI.cpp new file mode 100644 index 00000000..771b34db --- /dev/null +++ b/src/ui/Components/AmbientLightComponentUI.cpp @@ -0,0 +1,33 @@ +#include "imgui.h" + +#include +#include + +namespace shkyera { + +AmbientLightComponentUI::AmbientLightComponentUI(AmbientLightComponent* ambientLightComponent) : + _colorSelector("Color", ambientLightComponent->color), + _intensitySlider("Intensity", ambientLightComponent->intensity, 0.0f, 5.0f), + _ambientLightComponent(ambientLightComponent) +{ + _colorSelector.setUpdateCallback([this](const glm::vec3& color) { + _ambientLightComponent->color = color; + }); + _intensitySlider.setUpdateCallback([this](float value) { + _ambientLightComponent->intensity = value; + }); +} + +void AmbientLightComponentUI::draw() { + ImGui::Image(_icon->getImguiTextureID(), + ImVec2(16, 16)); + ImGui::SameLine(); + if (ImGui::TreeNodeEx("Ambient Light", ImGuiTreeNodeFlags_DefaultOpen)) { + _colorSelector.draw(); + _intensitySlider.draw(); + + ImGui::TreePop(); + } +} + +} diff --git a/src/ui/Components/AmbientLightComponentUI.hpp b/src/ui/Components/AmbientLightComponentUI.hpp new file mode 100644 index 00000000..c170b446 --- /dev/null +++ b/src/ui/Components/AmbientLightComponentUI.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include +#include + +namespace shkyera { + +class AmbientLightComponentUI : public ComponentUI { + public: + AmbientLightComponentUI(AmbientLightComponent* ambientLightComponent); + + void draw() override; + + private: + ColorSelector _colorSelector; + FloatSlider _intensitySlider; + AmbientLightComponent* _ambientLightComponent; +}; + +} diff --git a/src/ui/Components/DirectionalLightComponentUI.cpp b/src/ui/Components/DirectionalLightComponentUI.cpp index cbe7a1a2..3e372960 100644 --- a/src/ui/Components/DirectionalLightComponentUI.cpp +++ b/src/ui/Components/DirectionalLightComponentUI.cpp @@ -6,35 +6,25 @@ namespace shkyera { DirectionalLightComponentUI::DirectionalLightComponentUI(DirectionalLightComponent* directionalLightComponent) : - _directionalLightComponent(directionalLightComponent) {} + _directionalLightComponent(directionalLightComponent), + _colorSelector("Color", directionalLightComponent->color), + _intensitySlider("Intensity", directionalLightComponent->intensity, 0.0f, 5.0f) +{ + _colorSelector.setUpdateCallback([this](const glm::vec3& color) { + _directionalLightComponent->color = color; + }); + _intensitySlider.setUpdateCallback([this](float value) { + _directionalLightComponent->intensity = value; + }); +} void DirectionalLightComponentUI::draw() { ImGui::Image(_icon->getImguiTextureID(), ImVec2(16, 16)); ImGui::SameLine(); if (ImGui::TreeNodeEx("Directional Light", ImGuiTreeNodeFlags_DefaultOpen)) { - glm::vec3& diffuse = _directionalLightComponent->diffuse; - glm::vec3& specular = _directionalLightComponent->specular; - - ImGui::PushItemWidth(50); - - ImGui::Text("Diffuse"); - ImGui::SameLine(120); - ImGui::DragFloat("R##Diffuse", &diffuse[0], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("G##Diffuse", &diffuse[1], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("B##Diffuse", &diffuse[2], 0.01f, 0.0f, 1.0f); - - ImGui::Text("Specular"); - ImGui::SameLine(120); - ImGui::DragFloat("R##Specular", &specular[0], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("G##Specular", &specular[1], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("B##Specular", &specular[2], 0.01f, 0.0f, 1.0f); - - ImGui::PopItemWidth(); + _colorSelector.draw(); + _intensitySlider.draw(); ImGui::TreePop(); } diff --git a/src/ui/Components/DirectionalLightComponentUI.hpp b/src/ui/Components/DirectionalLightComponentUI.hpp index 0b898eea..5642f772 100644 --- a/src/ui/Components/DirectionalLightComponentUI.hpp +++ b/src/ui/Components/DirectionalLightComponentUI.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include namespace shkyera { @@ -12,6 +14,8 @@ class DirectionalLightComponentUI : public ComponentUI { void draw() override; private: + ColorSelector _colorSelector; + FloatSlider _intensitySlider; DirectionalLightComponent* _directionalLightComponent; }; diff --git a/src/ui/Components/PointLightComponentUI.cpp b/src/ui/Components/PointLightComponentUI.cpp index 0ab25960..df098ed4 100644 --- a/src/ui/Components/PointLightComponentUI.cpp +++ b/src/ui/Components/PointLightComponentUI.cpp @@ -6,35 +6,30 @@ namespace shkyera { PointLightComponentUI::PointLightComponentUI(PointLightComponent* pointLightComponent) : - _pointLightComponent(pointLightComponent) {} + _pointLightComponent(pointLightComponent), + _colorSelector("Color", pointLightComponent->color), + _intensitySlider("Intensity", pointLightComponent->intensity, 0.0f, 5.0f), + _rangeSlider("Range", pointLightComponent->range, 0.0f, 100.0f) +{ + _colorSelector.setUpdateCallback([this](const glm::vec3& color) { + _pointLightComponent->color = color; + }); + _intensitySlider.setUpdateCallback([this](float intensity) { + _pointLightComponent->intensity = intensity; + }); + _rangeSlider.setUpdateCallback([this](float range) { + _pointLightComponent->range = range; + }); +} void PointLightComponentUI::draw() { ImGui::Image(_icon->getImguiTextureID(), ImVec2(16, 16)); ImGui::SameLine(); if (ImGui::TreeNodeEx("Point Light", ImGuiTreeNodeFlags_DefaultOpen)) { - glm::vec3& diffuse = _pointLightComponent->diffuse; - glm::vec3& specular = _pointLightComponent->specular; - - ImGui::PushItemWidth(50); - - ImGui::Text("Diffuse"); - ImGui::SameLine(120); - ImGui::DragFloat("R##Diffuse", &diffuse[0], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("G##Diffuse", &diffuse[1], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("B##Diffuse", &diffuse[2], 0.01f, 0.0f, 1.0f); - - ImGui::Text("Specular"); - ImGui::SameLine(120); - ImGui::DragFloat("R##Specular", &specular[0], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("G##Specular", &specular[1], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("B##Specular", &specular[2], 0.01f, 0.0f, 1.0f); - - ImGui::PopItemWidth(); + _colorSelector.draw(); + _intensitySlider.draw(); + _rangeSlider.draw(); ImGui::TreePop(); } diff --git a/src/ui/Components/PointLightComponentUI.hpp b/src/ui/Components/PointLightComponentUI.hpp index b20d5399..444a18bf 100644 --- a/src/ui/Components/PointLightComponentUI.hpp +++ b/src/ui/Components/PointLightComponentUI.hpp @@ -1,6 +1,8 @@ #pragma once #include +#include +#include #include namespace shkyera { @@ -12,6 +14,9 @@ class PointLightComponentUI : public ComponentUI { void draw() override; private: + ColorSelector _colorSelector; + FloatSlider _intensitySlider; + FloatSlider _rangeSlider; PointLightComponent* _pointLightComponent; }; diff --git a/src/ui/Components/SkyboxComponentUI.cpp b/src/ui/Components/SkyboxComponentUI.cpp deleted file mode 100644 index 35b2c83b..00000000 --- a/src/ui/Components/SkyboxComponentUI.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "imgui.h" - -#include -#include - -namespace shkyera { - -SkyboxComponentUI::SkyboxComponentUI(SkyboxComponent* skyboxComponent) : - _skyboxComponent(skyboxComponent) {} - -void SkyboxComponentUI::draw() { - ImGui::Image(_icon->getImguiTextureID(), - ImVec2(16, 16)); - ImGui::SameLine(); - if (ImGui::TreeNodeEx("Skybox", ImGuiTreeNodeFlags_DefaultOpen)) { - glm::vec3& ambientLight = _skyboxComponent->ambientLight; - - ImGui::PushItemWidth(50); - - ImGui::Text("Skylight Color"); - ImGui::SameLine(120); - ImGui::DragFloat("R##Skylight Color", &ambientLight[0], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("G##Skylight Color", &ambientLight[1], 0.01f, 0.0f, 1.0f); - ImGui::SameLine(); - ImGui::DragFloat("B##Skylight Color", &ambientLight[2], 0.01f, 0.0f, 1.0f); - - ImGui::PopItemWidth(); - - ImGui::TreePop(); - } -} - -} diff --git a/src/ui/Components/SkyboxComponentUI.hpp b/src/ui/Components/SkyboxComponentUI.hpp deleted file mode 100644 index 1663e900..00000000 --- a/src/ui/Components/SkyboxComponentUI.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once - -#include -#include - -namespace shkyera { - -class SkyboxComponentUI : public ComponentUI { - public: - SkyboxComponentUI(SkyboxComponent* directionalLightComponent); - - void draw() override; - - private: - SkyboxComponent* _skyboxComponent; -}; - -} diff --git a/src/ui/Components/TransformComponentUI.cpp b/src/ui/Components/TransformComponentUI.cpp index 87c0a447..7ccf948a 100644 --- a/src/ui/Components/TransformComponentUI.cpp +++ b/src/ui/Components/TransformComponentUI.cpp @@ -22,6 +22,7 @@ void TransformComponentUI::draw() { if (ImGui::TreeNodeEx("Transform", ImGuiTreeNodeFlags_DefaultOpen)) { glm::vec3& position = _positionGetter(); glm::vec3& orientation = _orientationGetter(); + glm::vec3 orientationInDegrees = { glm::degrees(orientation.x), glm::degrees(orientation.y), glm::degrees(orientation.z) }; glm::vec3& scale = _scaleGetter(); ImGui::PushItemWidth(50); @@ -36,11 +37,11 @@ void TransformComponentUI::draw() { ImGui::Text("Orientation"); ImGui::SameLine(120); - ImGui::DragFloat("X##Orientation", &orientation[0], 1.0f, -360.0f, 360.0f, "%.2f"); + ImGui::DragFloat("X##Orientation", &orientationInDegrees[0], 1.0f, -360.0f, 360.0f, "%.2f"); ImGui::SameLine(); - ImGui::DragFloat("Y##Orientation", &orientation[1], 1.0f, -360.0f, 360.0f, "%.2f"); + ImGui::DragFloat("Y##Orientation", &orientationInDegrees[1], 1.0f, -360.0f, 360.0f, "%.2f"); ImGui::SameLine(); - ImGui::DragFloat("Z##Orientation", &orientation[2], 1.0f, -360.0f, 360.0f, "%.2f"); + ImGui::DragFloat("Z##Orientation", &orientationInDegrees[2], 1.0f, -360.0f, 360.0f, "%.2f"); ImGui::Text("Scale"); ImGui::SameLine(120); @@ -53,6 +54,10 @@ void TransformComponentUI::draw() { ImGui::PopItemWidth(); ImGui::TreePop(); + + orientation.x = glm::radians(orientationInDegrees.x); + orientation.y = glm::radians(orientationInDegrees.y); + orientation.z = glm::radians(orientationInDegrees.z); } } diff --git a/src/ui/UI.cpp b/src/ui/UI.cpp index e12c6a49..70a89fb0 100644 --- a/src/ui/UI.cpp +++ b/src/ui/UI.cpp @@ -33,6 +33,7 @@ void glfw_error_callback(int error, const char* description) { void UI::initialize() { initializeImgui(); + initializeSystems(); initializeWidgets(); initializeInterpreter(); styleImgui(); @@ -86,25 +87,26 @@ void UI::initializeImgui() { ImGui_ImplOpenGL3_Init(glsl_version); } +void UI::initializeSystems() { + _objectSelectionSystem = std::make_unique(_registry); +} + void UI::initializeWidgets() { _widgets.emplace_back(std::make_unique("Console")); + + _widgets.emplace_back(std::make_unique(_registry)); + _widgets.emplace_back(std::make_unique(_registry)); + _widgets.emplace_back(std::make_unique(_registry)); - auto propertiesWidget = std::make_unique(_registry); - _objectSelectionSystem = std::make_unique(_registry); + _widgets.emplace_back(std::make_unique(_registry)); auto objectsWidget = std::make_unique("Objects"); objectsWidget->setRegistry(_registry); - _widgets.emplace_back(std::move(objectsWidget)); - _widgets.emplace_back(std::move(propertiesWidget)); auto assetsWidget = std::make_unique("Assets"); assetsWidget->setDirectory("resources"); _widgets.emplace_back(std::move(assetsWidget)); - - auto sceneWidget = std::make_unique(_registry); - - _widgets.emplace_back(std::move(sceneWidget)); } void UI::initializeInterpreter() {} @@ -144,15 +146,15 @@ void UI::styleImgui() { /******** TABS *********/ style.Colors[ImGuiCol_Tab] = ACCENT_COLOR; - style.Colors[ImGuiCol_TabHovered] = BACKGROUND_COLOR; + style.Colors[ImGuiCol_TabHovered] = STRONG_ACCENT_COLOR; style.Colors[ImGuiCol_TabUnfocused] = ACCENT_COLOR; - style.Colors[ImGuiCol_TabUnfocusedActive] = BACKGROUND_COLOR; - style.Colors[ImGuiCol_TabActive] = BACKGROUND_COLOR; + style.Colors[ImGuiCol_TabUnfocusedActive] = STRONG_ACCENT_COLOR; + style.Colors[ImGuiCol_TabActive] = STRONG_ACCENT_COLOR; /******** TITLE *********/ - style.Colors[ImGuiCol_TitleBg] = ACCENT_COLOR; - style.Colors[ImGuiCol_TitleBgActive] = ACCENT_COLOR; - style.Colors[ImGuiCol_TitleBgCollapsed] = ACCENT_COLOR; + style.Colors[ImGuiCol_TitleBg] = BACKGROUND_COLOR; + style.Colors[ImGuiCol_TitleBgActive] = BACKGROUND_COLOR; + style.Colors[ImGuiCol_TitleBgCollapsed] = BACKGROUND_COLOR; /******** HEADERS ********/ style.Colors[ImGuiCol_Header] = ACCENT_COLOR; @@ -160,7 +162,7 @@ void UI::styleImgui() { style.Colors[ImGuiCol_HeaderHovered] = STRONG_ACCENT_COLOR; /******** SLIDER *********/ - style.Colors[ImGuiCol_SliderGrab] = ACCENT_COLOR; + style.Colors[ImGuiCol_SliderGrab] = STRONG_ACCENT_COLOR; style.Colors[ImGuiCol_SliderGrabActive] = STRONG_ACCENT_COLOR; /******** SEPARATOR ********/ @@ -237,6 +239,8 @@ void UI::beginFrame() { ImGui::DockBuilderDockWindow("Objects", dock_id_left_up_left); ImGui::DockBuilderDockWindow("Scene", dock_id_left_up_right); ImGui::DockBuilderDockWindow("Properties", dock_id_right); + ImGui::DockBuilderDockWindow("Scene Camera", dock_id_right); + ImGui::DockBuilderDockWindow("Environment", dock_id_right); ImGui::DockBuilderDockWindow("Assets", dock_id_left_bottom); ImGui::DockBuilderDockWindow("Console", dock_id_left_bottom); @@ -270,6 +274,11 @@ void UI::renderFrame() { ImGui::EndMainMenuBar(); } + + static auto onlyOnce = [this]() { + ImGui::SetWindowFocus("Properties"); + return true; + } (); } void UI::endFrame() { diff --git a/src/ui/UI.hpp b/src/ui/UI.hpp index b2b659d2..3850c1e7 100644 --- a/src/ui/UI.hpp +++ b/src/ui/UI.hpp @@ -68,6 +68,11 @@ class UI { */ void initializeWidgets(); + /** + * @brief Initialize internal systems. + */ + void initializeSystems(); + /** * @brief Initialize UI assets. */ diff --git a/src/ui/widgets/ConsoleWidget.cpp b/src/ui/widgets/ConsoleWidget.cpp index f19ce8db..e2b616a0 100644 --- a/src/ui/widgets/ConsoleWidget.cpp +++ b/src/ui/widgets/ConsoleWidget.cpp @@ -48,7 +48,7 @@ ConsoleWidget::ConsoleWidget(const std::string& name) : Widget(name) _infoIcon = AssetManager::getInstance().getAsset(Image::ICON_CONSOLE_INFO); _successIcon = AssetManager::getInstance().getAsset(Image::ICON_CONSOLE_SUCCESS); _errorIcon = AssetManager::getInstance().getAsset(Image::ICON_CONSOLE_ERROR); - _totalIcon = AssetManager::getInstance().getAsset(Image::ICON_CONSOLE_ERROR); + _totalIcon = AssetManager::getInstance().getAsset(Image::ICON_CONSOLE_TOTAL); } diff --git a/src/ui/widgets/PropertiesWidget.cpp b/src/ui/widgets/PropertiesWidget.cpp index d45218d9..3c37334d 100644 --- a/src/ui/widgets/PropertiesWidget.cpp +++ b/src/ui/widgets/PropertiesWidget.cpp @@ -15,7 +15,7 @@ #include #include #include -#include +#include #include #include #include @@ -23,10 +23,10 @@ namespace shkyera { PropertiesWidget::PropertiesWidget(std::shared_ptr registry) : Widget("Properties"), _registry(registry) {} +PropertiesWidget::PropertiesWidget(std::shared_ptr registry, const std::string& title) : Widget(title), _registry(registry) {} -void PropertiesWidget::draw() { - ImGui::Begin(_name.c_str()); - +void PropertiesWidget::updateComponents() +{ if (_registry->getSelectedEntities().size() > 0) { const auto firstSelectedEntity = *(_registry->getSelectedEntities().begin()); @@ -35,17 +35,27 @@ void PropertiesWidget::draw() { _selectedEntity = firstSelectedEntity; setupComponentsUI(); } + } +} - ImGui::PushID(*_selectedEntity); +void PropertiesWidget::draw() { + updateComponents(); - ImGui::PushFont(style::HUGE_FONT); - ImGui::TextUnformatted( - _registry->getComponent(*_selectedEntity) - .getName() - .c_str()); - ImGui::PopFont(); + ImGui::Begin(_name.c_str()); + if(_selectedEntity.has_value()) + { + ImGui::PushID(*_selectedEntity); - ImGui::Separator(); + if(_registry->hasComponent(*_selectedEntity)) + { + ImGui::PushFont(style::HUGE_FONT); + ImGui::TextUnformatted( + _registry->getComponent(*_selectedEntity) + .getName() + .c_str()); + ImGui::PopFont(); + ImGui::Separator(); + } drawExistingComponents(); drawNewComponentMenu(); @@ -75,13 +85,6 @@ void PropertiesWidget::setupComponentsUI() { _componentsUi.emplace_back(std::move(componentUi)); } - if(_registry->hasComponent(*_selectedEntity)) { - auto &component = _registry->getComponent(*_selectedEntity); - auto componentUi = std::make_unique(&component); - - _componentsUi.emplace_back(std::move(componentUi)); - } - if(_registry->hasComponent(*_selectedEntity)) { auto &component = _registry->getComponent(*_selectedEntity); auto componentUi = std::make_unique(&component); @@ -104,6 +107,13 @@ void PropertiesWidget::setupComponentsUI() { _componentsUi.emplace_back(std::move(componentUi)); } + if(_registry->hasComponent(*_selectedEntity)) { + auto &component = _registry->getComponent(*_selectedEntity); + auto componentUi = std::make_unique(&component); + + _componentsUi.emplace_back(std::move(componentUi)); + } + if(_registry->hasComponent(*_selectedEntity)) { auto &component = _registry->getComponent(*_selectedEntity); auto componentUi = std::make_unique(&component); @@ -144,6 +154,12 @@ void PropertiesWidget::drawNewComponentMenu() { ImGui::CloseCurrentPopup(); } + if (ImGui::Selectable("Ambient Light")) { + _registry->addComponent(*_selectedEntity); + setupComponentsUI(); + ImGui::CloseCurrentPopup(); + } + if (ImGui::Selectable("Point Light")) { _registry->addComponent(*_selectedEntity); setupComponentsUI(); @@ -160,4 +176,30 @@ void PropertiesWidget::drawNewComponentMenu() { } } +CameraPropertiesWidget::CameraPropertiesWidget(std::shared_ptr registry) : PropertiesWidget(registry, "Scene Camera") {} + +void CameraPropertiesWidget::updateComponents() +{ + static auto onlyOnce = [this]() { + _selectedEntity = _registry->getCamera(); + setupComponentsUI(); + return true; + } (); +} + +void CameraPropertiesWidget::drawNewComponentMenu() {} + +EnvironmentPropertiesWidget::EnvironmentPropertiesWidget(std::shared_ptr registry) : PropertiesWidget(registry, "Environment") {} + +void EnvironmentPropertiesWidget::updateComponents() +{ + static auto onlyOnce = [this]() { + _selectedEntity = _registry->getEnvironment(); + setupComponentsUI(); + return true; + } (); +} + +void EnvironmentPropertiesWidget::drawNewComponentMenu() {} + } // namespace shkyera diff --git a/src/ui/widgets/PropertiesWidget.hpp b/src/ui/widgets/PropertiesWidget.hpp index 8d251e29..6f516d06 100644 --- a/src/ui/widgets/PropertiesWidget.hpp +++ b/src/ui/widgets/PropertiesWidget.hpp @@ -24,22 +24,43 @@ class PropertiesWidget : public Widget { using Widget::Widget; PropertiesWidget(std::shared_ptr registry); + PropertiesWidget(std::shared_ptr registry, const std::string& title); /** * @brief Implementation of the abstract `draw` method to render the properties widget. */ void draw() override; - private: - void drawNewComponentMenu(); - + protected: + virtual void updateComponents(); + virtual void drawNewComponentMenu(); void setupComponentsUI(); + std::shared_ptr _registry; + std::optional _selectedEntity; + + private: void drawExistingComponents(); - std::optional _selectedEntity; std::vector> _componentsUi; - std::shared_ptr _registry; +}; + +class CameraPropertiesWidget : public PropertiesWidget { + public: + CameraPropertiesWidget(std::shared_ptr registry); + + protected: + void updateComponents() override; + void drawNewComponentMenu() override; +}; + +class EnvironmentPropertiesWidget : public PropertiesWidget { + public: + EnvironmentPropertiesWidget(std::shared_ptr registry); + + protected: + void updateComponents() override; + void drawNewComponentMenu() override; }; } // namespace shkyera