diff --git a/Assets/Bindings.SHConfig b/Assets/Bindings.SHConfig new file mode 100644 index 00000000..573541ac --- /dev/null +++ b/Assets/Bindings.SHConfig @@ -0,0 +1 @@ +0 diff --git a/Assets/Editor/Editor.SHConfig b/Assets/Editor/Editor.SHConfig new file mode 100644 index 00000000..51425027 --- /dev/null +++ b/Assets/Editor/Editor.SHConfig @@ -0,0 +1,4 @@ +Start Maximized: true +Working Scene ID: 97161771 +Window Size: {x: 1920, y: 1080} +Style: 0 \ No newline at end of file diff --git a/Assets/Scenes/UI_Test.shade b/Assets/Scenes/UI_Test.shade index e8ee4df2..0026a48b 100644 --- a/Assets/Scenes/UI_Test.shade +++ b/Assets/Scenes/UI_Test.shade @@ -1,7 +1,7 @@ - EID: 0 Name: Canvas IsActive: true - NumberOfChildren: 1 + NumberOfChildren: 2 Components: Canvas Component: Canvas Width: 10 @@ -28,6 +28,26 @@ Clicked Texture: 0 IsActive: true Scripts: ~ +- EID: 5 + Name: Default + IsActive: true + NumberOfChildren: 0 + Components: + Transform Component: + Translate: {x: 0, y: -3.9000001, z: 0} + Rotate: {x: 0, y: 0, z: 0} + Scale: {x: 1, y: 1, z: 1} + IsActive: true + Renderable Component: + Mesh: 141771688 + Material: 129340704 + IsActive: true + Toggle Button Component: + Non Toggled Texture: 0 + Toggled Texture: 0 + Value: true + IsActive: true + Scripts: ~ - EID: 1 Name: Camera IsActive: true diff --git a/Assets/Scenes/UI_Test.shade.shmeta b/Assets/Scenes/UI_Test.shade.shmeta index 8b8d6f22..77355480 100644 --- a/Assets/Scenes/UI_Test.shade.shmeta +++ b/Assets/Scenes/UI_Test.shade.shmeta @@ -1,3 +1,3 @@ Name: UI_Test -ID: 87707373 +ID: 87244611 Type: 5 diff --git a/SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.h b/SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.h index 8921fbce..9fcbf6f8 100644 --- a/SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.h +++ b/SHADE_Engine/src/ECS_Base/Managers/SHComponentManager.h @@ -23,7 +23,7 @@ #include "SH_API.h" #include "Events/SHEventManager.hpp" - +#include #include namespace SHADE @@ -151,6 +151,32 @@ namespace SHADE return (componentSet.GetSparseSet()->GetElement_s(EntityHandleGenerator::GetIndex(entityID))); } + /*!************************************************************************* + * \brief + * Gets the Component of the entity with the specified entityID + * + * This is the safe version of GetComponent_s which does a HasComponent to make + * sure that the entity has such a component and returns nullptr if it doesn't + * + * This safe version also checks if the sparse set of this component type + * has been created in SHComponentManager and creates one if it doesn't + * + * @tparam T... + * Pack of Types for all the Components to get. + * \param entityID + * EntityID of the entity that we are trying to get the component of. + * \return + * A tuple of pointers to all the components specified. + * Returns nullptr if the entity does not contain such a component. + ***************************************************************************/ + + template + static std::enable_if_t<(... && std::is_base_of_v), std::tuple> GetComponents(EntityID entityID) noexcept + { + return std::make_tuple(GetComponent_s(entityID)...); + } + + /*!************************************************************************* * \brief * Gets the Component of the entity with the specified entityID diff --git a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp index 83647da7..ed6ea6bb 100644 --- a/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp +++ b/SHADE_Engine/src/Editor/EditorWindow/Inspector/SHEditorInspector.cpp @@ -21,6 +21,7 @@ #include "UI/SHUIComponent.h" #include "UI/SHCanvasComponent.h" #include "UI/SHButtonComponent.h" +#include "UI/SHToggleButtonComponent.h" #include "SHEditorComponentView.h" #include "AudioSystem/SHAudioListenerComponent.h" #include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h" @@ -154,6 +155,10 @@ namespace SHADE { DrawComponent(buttonComponent); } + if (auto toggleButton = SHComponentManager::GetComponent_s(eid)) + { + DrawComponent(toggleButton); + } ImGui::Separator(); // Render Scripts SHScriptEngine* scriptEngine = static_cast(SHSystemManager::GetSystem()); @@ -167,6 +172,7 @@ namespace SHADE DrawAddComponentButton(eid); DrawAddComponentButton(eid); DrawAddComponentButton(eid); + DrawAddComponentButton(eid); // Components that require Transforms diff --git a/SHADE_Engine/src/Events/SHEventDefines.h b/SHADE_Engine/src/Events/SHEventDefines.h index f8e452c1..ca29d416 100644 --- a/SHADE_Engine/src/Events/SHEventDefines.h +++ b/SHADE_Engine/src/Events/SHEventDefines.h @@ -23,6 +23,7 @@ constexpr SHEventIdentifier SH_SCENE_INIT_POST { 14 }; constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 }; constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 }; constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 }; -constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_DRAW_EVENT { 18 }; +constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 }; +constexpr SHEventIdentifier SH_PHYSICS_COLLIDER_DRAW_EVENT { 19 }; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp index b57249de..5a694516 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.cpp @@ -104,6 +104,10 @@ namespace SHADE auto subPass = renderGraph->GetNode("Debug Draw")->GetSubpass("Debug Draw"); subPass->AddExteriorDrawCalls([this](Handle cmdBuffer, Handle renderer, uint32_t frameIndex) { + // Set line width first + cmdBuffer->SetLineWidth(LineWidth); + + // Draw const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex(); cmdBuffer->BeginLabeledSegment("SHDebugDraw (No Depth Test)"); { @@ -128,6 +132,10 @@ namespace SHADE auto subPassWithDepth = renderGraph->GetNode("Debug Draw with Depth")->GetSubpass("Debug Draw with Depth"); subPassWithDepth->AddExteriorDrawCalls([this](Handle cmdBuffer, Handle renderer, uint32_t frameIndex) { + // Set line width first + cmdBuffer->SetLineWidth(LineWidth); + + // Draw const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex(); cmdBuffer->BeginLabeledSegment("SHDebugDraw (Depth Tested)"); { @@ -207,6 +215,11 @@ namespace SHADE drawSphere(getMeshBatch(true, depthTested), matrix, color); } + void SHDebugDrawSystem::DrawWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested) + { + drawWireCapsule(getLineBatch(depthTested), getMeshBatch(false, depthTested), position, rotation, height, radius, color); + } + /*-----------------------------------------------------------------------------------*/ /* Persistent Draw Functions */ /*-----------------------------------------------------------------------------------*/ @@ -264,6 +277,12 @@ namespace SHADE markPersistentDrawsDirty(); } + void SHDebugDrawSystem::DrawPersistentWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested) + { + drawWireCapsule(getPersistentLineBatch(depthTested), getPersistentMeshBatch(false, depthTested), position, rotation, height, radius, color); + markPersistentDrawsDirty(); + } + void SHDebugDrawSystem::ClearPersistentDraws() { for (auto& batch : persistentLineBatches) @@ -348,6 +367,53 @@ namespace SHADE ); } + void SHDebugDrawSystem::drawWireCapsule(LinesBatch& lineBatch, MeshBatch& meshBatch, const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color) + { + // Get local axis vectors + const SHVec3 LOCAL_UP = SHVec3::Rotate(SHVec3::Up, rotation); + const SHVec3 LOCAL_RIGHT = SHVec3::Rotate(SHVec3::Right, rotation); + const SHVec3 LOCAL_FORWARD = SHVec3::Rotate(SHVec3::Forward, rotation); + + // Rotate the circle + SHQuaternion circleOrientation = SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(90.0), 0.0f, 0.0f)) * rotation; + + // Compute top and bottom of the cylinder + const SHVec3 HALF_UP = LOCAL_UP * (height * 0.5f - radius); + const SHVec3 TOP_POS = position + HALF_UP; + const SHVec3 BOT_POS = position - HALF_UP; + + // Render circles + const SHVec3 CIRCLE_SCALE = SHVec3(radius * 2.0f, radius * 2.0, radius * 2.0); + drawCircle(meshBatch, SHMatrix::Transform(TOP_POS, circleOrientation, CIRCLE_SCALE), color); + drawCircle(meshBatch, SHMatrix::Transform(BOT_POS, circleOrientation, CIRCLE_SCALE), color); + + // Render connecting lines + drawLine(lineBatch, TOP_POS + LOCAL_RIGHT * radius, BOT_POS + LOCAL_RIGHT * radius, color); + drawLine(lineBatch, TOP_POS - LOCAL_RIGHT * radius, BOT_POS - LOCAL_RIGHT * radius, color); + drawLine(lineBatch, TOP_POS + LOCAL_FORWARD * radius, BOT_POS + LOCAL_FORWARD * radius, color); + drawLine(lineBatch, TOP_POS - LOCAL_FORWARD * radius, BOT_POS - LOCAL_FORWARD * radius, color); + + // Render caps + const SHVec3 RADIUS_SCALE = SHVec3(radius * 2.0, radius * 2.0f, radius * 2.0); + const SHMatrix TOP_CAP_MAT = SHMatrix::Transform(TOP_POS, rotation, RADIUS_SCALE); + drawMesh + ( + gfxSystem->GetMeshPrimitive(PrimitiveType::LineCapsuleCap), + meshBatch, TOP_CAP_MAT, color + ); + const SHMatrix BOT_CAP_MAT = SHMatrix::Transform + ( + BOT_POS, + SHQuaternion::FromEuler(SHVec3(SHMath::DegreesToRadians(180.0), 0.0f, 0.0f)) * rotation, + RADIUS_SCALE + ); + drawMesh + ( + gfxSystem->GetMeshPrimitive(PrimitiveType::LineCapsuleCap), + meshBatch, BOT_CAP_MAT, color + ); + } + /*-----------------------------------------------------------------------------------*/ /* Helper Batch Functions - Lines */ /*-----------------------------------------------------------------------------------*/ @@ -448,7 +514,6 @@ namespace SHADE if (batch.NumPoints[frameIndex] > 0) { cmdBuffer->BindPipeline(batch.Pipeline); - cmdBuffer->SetLineWidth(LineWidth); cmdBuffer->BindVertexBuffer(0, batch.VertexBuffers[frameIndex], 0); cmdBuffer->DrawArrays(batch.NumPoints[frameIndex], 1, 0, 0); } diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h index 2978d68e..3997b6df 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHDebugDrawSystem.h @@ -163,6 +163,17 @@ namespace SHADE /// Colour to draw with. /// Whether or not drawn object will be occluded. void DrawSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false); + /// + /// Draws the outline of a capsule. + /// + /// Position of the wireframe capsule. + /// Rotation of the capsule. + /// Height of the overall capsule. + /// Radius of the capsule. + /// + /// Colour to draw with. + /// Whether or not drawn object will be occluded. + void DrawWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false); /*---------------------------------------------------------------------------------*/ /* Persistent Draw Functions */ @@ -269,6 +280,17 @@ namespace SHADE /// Whether or not drawn object will be occluded. void DrawPersistentSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false); /// + /// Draws a persistent outline of a capsule. + /// + /// Position of the wireframe capsule. + /// Rotation of the capsule. + /// Height of the overall capsule. + /// Radius of the capsule. + /// + /// Colour to draw with. + /// Whether or not drawn object will be occluded. + void DrawPersistentWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false); + /// /// Clears any persistent drawn debug primitives. /// void ClearPersistentDraws(); @@ -386,6 +408,7 @@ namespace SHADE void drawCube(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color); void drawSphere(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color); void drawCircle(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color); + void drawWireCapsule(LinesBatch& lineBatch, MeshBatch& meshBatch, const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color); /*---------------------------------------------------------------------------------*/ /* Helper Batch Functions - Lines */ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp index b1256921..f3bcc8f7 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.cpp @@ -419,6 +419,7 @@ namespace SHADE primitiveMeshes[static_cast(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary); primitiveMeshes[static_cast(PrimitiveType::LineCube)] = SHPrimitiveGenerator::LineCube(meshLibrary); primitiveMeshes[static_cast(PrimitiveType::LineCircle)] = SHPrimitiveGenerator::LineCircle(meshLibrary); + primitiveMeshes[static_cast(PrimitiveType::LineCapsuleCap)] = SHPrimitiveGenerator::LineCapsuleCap(meshLibrary); BuildMeshBuffers(); // Create default materials @@ -819,6 +820,7 @@ namespace SHADE case PrimitiveType::Sphere: case PrimitiveType::LineCube: case PrimitiveType::LineCircle: + case PrimitiveType::LineCapsuleCap: return primitiveMeshes[static_cast(type)]; default: return {}; diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h index 40148e05..707862f9 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Interface/SHGraphicsSystem.h @@ -72,9 +72,10 @@ namespace SHADE Cube, Sphere, LineCube, - LineCircle + LineCircle, + LineCapsuleCap }; - static constexpr int MAX_PRIMITIVE_TYPES = 4; + static constexpr int MAX_PRIMITIVE_TYPES = 5; enum class DebugDrawPipelineType { LineNoDepthTest, diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp index 444a6630..d5a0073f 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.cpp @@ -29,6 +29,7 @@ namespace SHADE SHMeshData SHPrimitiveGenerator::sphereMesh; SHMeshData SHPrimitiveGenerator::lineCubeMesh; SHMeshData SHPrimitiveGenerator::lineCircleMesh; + SHMeshData SHPrimitiveGenerator::lineCapsuleCapMesh; /*-----------------------------------------------------------------------------------*/ /* Primitive Generation Functions */ @@ -392,6 +393,64 @@ namespace SHADE return addMeshDataTo(lineCircleMesh, gfxSystem); } + SHADE::SHMeshData SHPrimitiveGenerator::LineCapsuleCap() noexcept + { + SHMeshData mesh; + + // Have multiple semi-circles for the cap + static constexpr int SPLITS = 36; + static constexpr float ANGLE_INCREMENTS = (std::numbers::pi_v * 2.0f) / static_cast(SPLITS); + + /* X-Axis */ + // Generate points of the circle + for (int i = 0; i <= SPLITS / 2; ++i) + { + const float ANGLE = ANGLE_INCREMENTS * i; + mesh.VertexPositions.emplace_back(cos(ANGLE) * 0.5f, sin(ANGLE) * 0.5f, 0.0f); + } + + // Generate lines of the circle + for (int i = 1; i <= SPLITS / 2; ++i) + { + mesh.Indices.emplace_back(static_cast(i - 1)); + mesh.Indices.emplace_back(static_cast(i)); + } + + /* Z-Axis */ + // Generate points of the circle + for (int i = 0; i <= SPLITS / 2; ++i) + { + const float ANGLE = ANGLE_INCREMENTS * i; + mesh.VertexPositions.emplace_back(0.0f, sin(ANGLE) * 0.5f, cos(ANGLE) * 0.5f); + } + + // Generate lines of the circle + for (int i = 2 + SPLITS / 2; i <= SPLITS + 1; ++i) + { + mesh.Indices.emplace_back(static_cast(i - 1)); + mesh.Indices.emplace_back(static_cast(i)); + } + + mesh.VertexNormals.resize(mesh.VertexPositions.size()); + mesh.VertexTangents.resize(mesh.VertexPositions.size()); + mesh.VertexTexCoords.resize(mesh.VertexPositions.size()); + + return mesh; + } + Handle SHPrimitiveGenerator::LineCapsuleCap(SHMeshLibrary& meshLibrary) noexcept + { + if (lineCapsuleCapMesh.VertexPositions.empty()) + lineCapsuleCapMesh = LineCapsuleCap(); + + return addMeshDataTo(lineCapsuleCapMesh, meshLibrary); + } + Handle SHPrimitiveGenerator::LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept + { + if (lineCapsuleCapMesh.VertexPositions.empty()) + lineCapsuleCapMesh = LineCapsuleCap(); + + return addMeshDataTo(lineCapsuleCapMesh, gfxSystem); + } /*-----------------------------------------------------------------------------------*/ /* Helper Functions */ /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h index 9bcd2f3c..839d0ef6 100644 --- a/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h +++ b/SHADE_Engine/src/Graphics/MiddleEnd/Meshes/SHPrimitiveGenerator.h @@ -194,6 +194,46 @@ namespace SHADE */ /***********************************************************************************/ [[nodiscard]] static Handle LineCircle(SHGraphicsSystem& gfxSystem) noexcept; + /***********************************************************************************/ + /*! + \brief + Produces a cap of a wireframe capsule that is comprised only of lines and + store the data in a SHMeshData object. + + \return + SHMeshData object containing vertex data for the line circle. + */ + /***********************************************************************************/ + [[nodiscard]] static SHMeshData LineCapsuleCap() noexcept; + /***********************************************************************************/ + /*! + \brief + Produces a cap of a wireframe capsule that is comprised only of lines and + constructs a SHMesh using the SHGraphicsSystem provided. + + \param meshLibrary + Reference to the SHMeshLibrary to produce and store a line circle mesh in. + + \return + SHMesh object that points to the generated line circle mesh in the SHMeshLibrary. + */ + /***********************************************************************************/ + [[nodiscard]] static Handle LineCapsuleCap(SHMeshLibrary& meshLibrary) noexcept; + /***********************************************************************************/ + /*! + \brief + Produces a cap of a wireframe capsule that is comprised only of lines and + constructs a SHMesh using the SHGraphicsSystem provided. + + \param gfxSystem + Reference to the SHGraphicsSystem to produce and store a line circle mesh in. + + \return + SHMesh object that points to the generated line circle mesh in the + SHGraphicsSystem. + */ + /***********************************************************************************/ + [[nodiscard]] static Handle LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept; private: /*---------------------------------------------------------------------------------*/ @@ -209,5 +249,6 @@ namespace SHADE static SHMeshData sphereMesh; static SHMeshData lineCubeMesh; static SHMeshData lineCircleMesh; + static SHMeshData lineCapsuleCapMesh; }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Input/SHInputManager.cpp b/SHADE_Engine/src/Input/SHInputManager.cpp index cec78648..b8f329b9 100644 --- a/SHADE_Engine/src/Input/SHInputManager.cpp +++ b/SHADE_Engine/src/Input/SHInputManager.cpp @@ -11,6 +11,7 @@ #pragma once #include +#include #include "SHInputManager.h" #include "../Tools/SHException.h" @@ -99,6 +100,161 @@ namespace SHADE } } + //The Binding File format presently goes as such: + /* + * Binding count + * (For each binding:) + * Name + Binding Type Enum + Inverted Bool + Gravity Double + Dead Double + Sensitivity Double + Snap Bool + PositiveKeyCode count + PositiveKeyCodes + NegativeKeyCode count + NegativeKeyCodes + PositiveControllerCode Count + PositiveControllerCodes + NegativeControllerCode Count + NegativeControllerCodes + */ + void SHInputManager::SaveBindings(std::string const& targetFile) noexcept + { + std::ofstream file; + file.open(targetFile); + + //File cannot be written to + if (!file) return; + + //First write the number of bindings + file << bindings.size() << std::endl; + + for (auto& b : bindings) + { + //Name + file << b.first << std::endl; + + //Data + auto& lbd = b.second; + + file << static_cast(lbd.bindingType) << std::endl; + file << static_cast(lbd.inverted) << std::endl; + file << lbd.gravity << std::endl; + file << lbd.dead << std::endl; + file << lbd.sensitivity << std::endl; + file << static_cast(lbd.snap) << std::endl; + + //Bindings + file << lbd.positiveKeyCodes.size() << std::endl; + for (auto kc : lbd.positiveKeyCodes) + file << static_cast(kc) << std::endl; + file << lbd.negativeKeyCodes.size() << std::endl; + for (auto kc : lbd.negativeKeyCodes) + file << static_cast(kc) << std::endl; + file << lbd.positiveControllerCodes.size() << std::endl; + for (auto cc : lbd.positiveControllerCodes) + file << static_cast(cc) << std::endl; + file << lbd.negativeControllerCodes.size() << std::endl; + for (auto cc : lbd.negativeControllerCodes) + file << static_cast(cc) << std::endl; + } + + file.close(); + } + + void SHInputManager::LoadBindings(std::string const& sourceFile) noexcept + { + std::ifstream file; + file.open(sourceFile); + + //Check + if (!file) return; + + //Erase + ClearBindings(); + + //Read + std::string read; + + int count = 0; + std::getline(file, read); + count = std::stoi(read); + + std::string bindingName; + for (int b = 0; b < count; ++b) + { + //Name + std::getline(file, read); + bindingName = read; + AddBinding(bindingName); + + //Type + std::getline(file, read); + SetBindingType(bindingName, static_cast(std::stoi(read))); + + //Inversion + std::getline(file, read); + SetBindingInverted(bindingName, static_cast(std::stoi(read))); + + //Gravity + std::getline(file, read); + SetBindingGravity(bindingName, std::stod(read)); + + //Dead + std::getline(file, read); + SetBindingDead(bindingName, std::stod(read)); + + //Sensitivity + std::getline(file, read); + SetBindingSensitivity(bindingName, std::stod(read)); + + //Snap + std::getline(file, read); + SetBindingSnap(bindingName, static_cast(std::stoi(read))); + + int count = 0; + //Positive Key Codes + std::getline(file, read); + count = std::stoi(read); + for (int i = 0; i < count; ++i) + { + std::getline(file, read); + AddBindingPositiveKeyCode(bindingName, static_cast(std::stoi(read))); + } + + //Negative Key Codes + std::getline(file, read); + count = std::stoi(read); + for (int i = 0; i < count; ++i) + { + std::getline(file, read); + AddBindingNegativeKeyCode(bindingName, static_cast(std::stoi(read))); + } + + //Positive Controller Codes + std::getline(file, read); + count = std::stoi(read); + for (int i = 0; i < count; ++i) + { + std::getline(file, read); + AddBindingPositiveControllerCode(bindingName, static_cast(std::stoi(read))); + } + + //Negative Controller Codes + std::getline(file, read); + count = std::stoi(read); + for (int i = 0; i < count; ++i) + { + std::getline(file, read); + AddBindingNegativeControllerCode(bindingName, static_cast(std::stoi(read))); + } + } + + file.close(); + } + void SHInputManager::UpdateInput(double dt) noexcept { //Keyboard and Mouse Buttons//////////////////////////////////////////////// diff --git a/SHADE_Engine/src/Input/SHInputManager.h b/SHADE_Engine/src/Input/SHInputManager.h index 3f708124..680035c3 100644 --- a/SHADE_Engine/src/Input/SHInputManager.h +++ b/SHADE_Engine/src/Input/SHInputManager.h @@ -14,6 +14,7 @@ #include #include #include "../../SHADE_Managed/src/SHpch.h" +#include "../../SHADE_Engine/src/Assets/SHAssetMacros.h" #include "SH_API.h" #pragma comment(lib, "xinput.lib") @@ -681,6 +682,17 @@ namespace SHADE return controllersReleasedTime[controllerNum][static_cast(code)]; } + /*------------------------------------------------------------------------*/ + /* Binding I/O */ + /*------------------------------------------------------------------------*/ + + //Save bindings registered into a file + static void SaveBindings(std::string const& targetFile = std::string(ASSET_ROOT) + "/Bindings.SHConfig") noexcept; + + //Load and register bindings from a file + //If specified file exists, the current list of bindings will be overwritten, so save them somewhere else before loading + static void LoadBindings(std::string const& sourceFile = std::string(ASSET_ROOT) + "/Bindings.SHConfig") noexcept; + /*------------------------------------------------------------------------*/ /* Binding Functions */ /*------------------------------------------------------------------------*/ diff --git a/SHADE_Engine/src/Math/Transform/SHTransform.cpp b/SHADE_Engine/src/Math/Transform/SHTransform.cpp index ef7c5fda..7be2a60c 100644 --- a/SHADE_Engine/src/Math/Transform/SHTransform.cpp +++ b/SHADE_Engine/src/Math/Transform/SHTransform.cpp @@ -35,7 +35,17 @@ namespace SHADE : position { pos } , orientation { SHQuaternion::FromEuler(rot) } , scale { scl } - {} + { + ComputeTRS(); + } + + SHTransform::SHTransform(const SHVec3& pos, const SHQuaternion& quat, const SHVec3& scl) noexcept + : position { pos } + , orientation { quat } + , scale { scl } + { + ComputeTRS(); + } /*-----------------------------------------------------------------------------------*/ /* Operator Overload Definitions */ diff --git a/SHADE_Engine/src/Serialization/SHSerialization.cpp b/SHADE_Engine/src/Serialization/SHSerialization.cpp index a0b961a3..cc081413 100644 --- a/SHADE_Engine/src/Serialization/SHSerialization.cpp +++ b/SHADE_Engine/src/Serialization/SHSerialization.cpp @@ -18,6 +18,7 @@ #include "Physics/Interface/SHRigidBodyComponent.h" #include "UI/SHCanvasComponent.h" #include "UI/SHButtonComponent.h" +#include "UI/SHToggleButtonComponent.h" #include "ECS_Base/Managers/SHSystemManager.h" #include "Graphics/MiddleEnd/Lights/SHLightComponent.h" #include "Scripting/SHScriptEngine.h" @@ -208,6 +209,7 @@ namespace SHADE AddComponentToComponentNode(components, eid); AddComponentToComponentNode(components, eid); + AddComponentToComponentNode(components, eid); AddComponentToComponentNode(components, eid); @@ -265,6 +267,7 @@ namespace SHADE AddComponentID(componentIDList, componentsNode); AddComponentID(componentIDList, componentsNode); + AddComponentID(componentIDList, componentsNode); AddComponentID(componentIDList, componentsNode); return componentIDList; @@ -346,6 +349,7 @@ namespace SHADE SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); + SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); SHSerializationHelper::InitializeComponentFromNode(componentsNode, eid); } diff --git a/SHADE_Engine/src/Tools/SHDebugDraw.cpp b/SHADE_Engine/src/Tools/SHDebugDraw.cpp index 02eca592..ee040d8b 100644 --- a/SHADE_Engine/src/Tools/SHDebugDraw.cpp +++ b/SHADE_Engine/src/Tools/SHDebugDraw.cpp @@ -128,6 +128,10 @@ namespace SHADE dbgDrawSys->DrawWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested); } + void SHDebugDraw::WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested) + { + dbgDrawSys->DrawWireCapsule(position, rotation, height, radius, color, depthTested); + } /*-----------------------------------------------------------------------------------*/ /* Persistent Draw Functions */ /*-----------------------------------------------------------------------------------*/ @@ -216,6 +220,10 @@ namespace SHADE dbgDrawSys->DrawPersistentWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested); } + void SHDebugDraw::Persistent::WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color, bool depthTested) + { + dbgDrawSys->DrawPersistentWireCapsule(position, rotation, height, radius, color, depthTested); + } void SHDebugDraw::Persistent::ClearDraws() { dbgDrawSys->ClearPersistentDraws(); diff --git a/SHADE_Engine/src/Tools/SHDebugDraw.h b/SHADE_Engine/src/Tools/SHDebugDraw.h index c28b93e6..c775a514 100644 --- a/SHADE_Engine/src/Tools/SHDebugDraw.h +++ b/SHADE_Engine/src/Tools/SHDebugDraw.h @@ -194,6 +194,18 @@ namespace SHADE /// Colour to draw with. /// Whether or not drawn object will be occluded. static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false); + /// + /// Draws the outline of a capsule. + /// This will remain drawn until ClearDraws() is called. + /// + /// Position of the wireframe capsule. + /// Rotation of the capsule. + /// Height of the overall capsule. + /// Radius of the capsule. + /// + /// Colour to draw with. + /// Whether or not drawn object will be occluded. + static void WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false); /*---------------------------------------------------------------------------------*/ /* Persistent Draw Function Class "Folder" */ @@ -366,6 +378,18 @@ namespace SHADE /// Whether or not drawn object will be occluded. static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false); /// + /// Draws the outline of a capsule. + /// This will remain drawn until ClearDraws() is called. + /// + /// Position of the wireframe capsule. + /// Rotation of the capsule. + /// Height of the overall capsule. + /// Radius of the capsule. + /// + /// Colour to draw with. + /// Whether or not drawn object will be occluded. + static void WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false); + /// /// Clears any persistent drawn debug primitives. /// static void ClearDraws(); diff --git a/SHADE_Engine/src/UI/Events/SHButtonClickEvent.h b/SHADE_Engine/src/UI/Events/SHButtonClickEvent.h new file mode 100644 index 00000000..35bcdc61 --- /dev/null +++ b/SHADE_Engine/src/UI/Events/SHButtonClickEvent.h @@ -0,0 +1,16 @@ +#pragma once + + +#include "ECS_Base/SHECSMacros.h" + +namespace SHADE +{ + struct SHButtonClickEvent + { + EntityID EID; + // value of the toggle button, default to false if its a button and not a toggle button + bool value{false}; + }; + + +} diff --git a/SHADE_Engine/src/UI/SHButtonComponent.cpp b/SHADE_Engine/src/UI/SHButtonComponent.cpp index 7b275128..8e87b10e 100644 --- a/SHADE_Engine/src/UI/SHButtonComponent.cpp +++ b/SHADE_Engine/src/UI/SHButtonComponent.cpp @@ -5,7 +5,7 @@ namespace SHADE { SHButtonComponent::SHButtonComponent() - :size(1.0f), offset(0.0f), isHovered(false), isClicked(false), + :size(1.0f), isHovered(false), isClicked(false), defaultTexture(0), hoveredTexture(0), clickedTexture(0) { } diff --git a/SHADE_Engine/src/UI/SHButtonComponent.h b/SHADE_Engine/src/UI/SHButtonComponent.h index 39790b6a..3aac09e6 100644 --- a/SHADE_Engine/src/UI/SHButtonComponent.h +++ b/SHADE_Engine/src/UI/SHButtonComponent.h @@ -18,7 +18,6 @@ namespace SHADE virtual ~SHButtonComponent() = default; SHVec2 size; - SHVec2 offset; AssetID GetClickedTexture() const noexcept; AssetID GetDefaultTexture() const noexcept; @@ -33,8 +32,10 @@ namespace SHADE friend class SHUISystem; private: - + //Set to true when mouse is hovering over the button. bool isHovered; + //This is set to true when the mouse clicks down, and set back to false when mouse releases. + //The event for the button click will be broadcasted when mouse release. bool isClicked; AssetID defaultTexture; AssetID hoveredTexture; diff --git a/SHADE_Engine/src/UI/SHSliderComponent.cpp b/SHADE_Engine/src/UI/SHSliderComponent.cpp new file mode 100644 index 00000000..56d1d89b --- /dev/null +++ b/SHADE_Engine/src/UI/SHSliderComponent.cpp @@ -0,0 +1,39 @@ +#include "SHpch.h" +#include "SHSliderComponent.h" + +namespace SHADE +{ + SHSliderComponent::SHSliderComponent() + :size(1.0f), isHovered(false), isClicked(false), value(0.0f) + { + + } + + + float SHSliderComponent::GetValue() const noexcept + { + return value; + } + + void SHSliderComponent::SetValue(float value) noexcept + { + this->value = value; + } + + + +} + + +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; + + registration::class_("Slider Component") + .property("Slider Value", &SHSliderComponent::GetValue, &SHSliderComponent::SetValue) + + ; + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/UI/SHSliderComponent.h b/SHADE_Engine/src/UI/SHSliderComponent.h new file mode 100644 index 00000000..bdc57c7e --- /dev/null +++ b/SHADE_Engine/src/UI/SHSliderComponent.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include "SH_API.h" +#include "ECS_Base/Components/SHComponent.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec2.h" +#include "Assets/SHAssetMacros.h" + +namespace SHADE +{ + + class SH_API SHSliderComponent final: public SHComponent + { + public: + SHSliderComponent(); + virtual ~SHSliderComponent() = default; + + SHVec2 size; + + + float GetValue() const noexcept; + + + void SetValue(float value) noexcept; + + + friend class SHUISystem; + private: + + bool isHovered; + bool isClicked; + + float value; + + RTTR_ENABLE() + }; + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/UI/SHToggleButtonComponent.cpp b/SHADE_Engine/src/UI/SHToggleButtonComponent.cpp new file mode 100644 index 00000000..527323ea --- /dev/null +++ b/SHADE_Engine/src/UI/SHToggleButtonComponent.cpp @@ -0,0 +1,59 @@ +#include "SHpch.h" +#include "SHToggleButtonComponent.h" + + +namespace SHADE +{ + SHToggleButtonComponent::SHToggleButtonComponent() + :size(1.0f), isHovered(false), isClicked(false), value(false), + defaultTexture(0), toggledTexture(0) + { + } + + AssetID SHToggleButtonComponent::GetDefaultTexture() const noexcept + { + return defaultTexture; + } + + AssetID SHToggleButtonComponent::GetToggledTexture() const noexcept + { + return toggledTexture; + } + + bool SHToggleButtonComponent::GetValue() const noexcept + { + return value; + } + + + void SHToggleButtonComponent::SetDefaultTexture(AssetID texture) noexcept + { + defaultTexture = texture; + } + + void SHToggleButtonComponent::SetToggledTexture(AssetID texture) noexcept + { + toggledTexture = texture; + } + + void SHToggleButtonComponent::SetValue(bool value) noexcept + { + this->value = value; + } + +} + + +RTTR_REGISTRATION +{ + using namespace SHADE; + using namespace rttr; + + registration::class_("Toggle Button Component") + .property("Non Toggled Texture", &SHToggleButtonComponent::GetDefaultTexture, &SHToggleButtonComponent::SetDefaultTexture) + .property("Toggled Texture", &SHToggleButtonComponent::GetToggledTexture, &SHToggleButtonComponent::SetToggledTexture) + .property("Value", &SHToggleButtonComponent::GetValue, &SHToggleButtonComponent::SetValue) + ; + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/UI/SHToggleButtonComponent.h b/SHADE_Engine/src/UI/SHToggleButtonComponent.h new file mode 100644 index 00000000..2c77f3ba --- /dev/null +++ b/SHADE_Engine/src/UI/SHToggleButtonComponent.h @@ -0,0 +1,51 @@ +#pragma once + +#include + +#include "SH_API.h" +#include "ECS_Base/Components/SHComponent.h" +#include "Math/Vector/SHVec3.h" +#include "Math/Vector/SHVec2.h" +#include "Assets/SHAssetMacros.h" + +namespace SHADE +{ + + class SH_API SHToggleButtonComponent final: public SHComponent + { + public: + SHToggleButtonComponent(); + virtual ~SHToggleButtonComponent() = default; + + SHVec2 size; + + AssetID GetToggledTexture() const noexcept; + AssetID GetDefaultTexture() const noexcept; + bool GetValue() const noexcept; + + + void SetDefaultTexture(AssetID texture) noexcept; + void SetToggledTexture(AssetID texture) noexcept; + void SetValue(bool value) noexcept; + + + + friend class SHUISystem; + private: + + //Set to true when mouse is hovering over the button. + bool isHovered; + //This is set to true when the mouse clicks down, and set back to false when mouse releases. + //The event for the button click will be broadcasted when mouse release. + bool isClicked; + bool value; + AssetID defaultTexture; + AssetID toggledTexture; + + + + RTTR_ENABLE() + }; + + +} \ No newline at end of file diff --git a/SHADE_Engine/src/UI/SHUISystem.cpp b/SHADE_Engine/src/UI/SHUISystem.cpp index 1387bc6b..c75af66f 100644 --- a/SHADE_Engine/src/UI/SHUISystem.cpp +++ b/SHADE_Engine/src/UI/SHUISystem.cpp @@ -9,7 +9,15 @@ #include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h" #include "Editor/SHEditor.h" #include "Resource/SHResourceManager.h" +#include "Assets/SHAssetManager.h" #include "Input/SHInputManager.h" +#include "SHUIComponent.h" +#include "SHButtonComponent.h" +#include "SHToggleButtonComponent.h" +#include "SHSliderComponent.h" +#include "SHCanvasComponent.h" +#include "Events/SHEventManager.hpp" +#include "Events/SHButtonClickEvent.h" namespace SHADE { @@ -103,7 +111,7 @@ namespace SHADE { auto transform = SHComponentManager::GetComponent(comp.GetEID()); if (canvasComp != nullptr) - comp.localToCanvasMatrix = canvasComp->GetMatrix()* transform->GetTRS(); + comp.localToCanvasMatrix = transform->GetTRS() * canvasComp->GetMatrix(); else comp.localToCanvasMatrix = transform->GetTRS(); } @@ -139,77 +147,235 @@ namespace SHADE void SHUISystem::UpdateButtonComponent(SHButtonComponent& comp) noexcept { - if (!SHComponentManager::HasComponent(comp.GetEID()) || !SHComponentManager::HasComponent(comp.GetEID())) + if (!SHComponentManager::HasComponent(comp.GetEID())) + { + return; + } + auto cameraSystem = SHSystemManager::GetSystem(); + auto uiComp = SHComponentManager::GetComponent(comp.GetEID()); + //auto canvasComp = SHComponentManager::GetComponent_s(uiComp->canvasID); + + SHVec4 topExtent4 = SHMatrix::Translate(-comp.size.x * 0.5f, comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f, 0.0f, 0.0f, 1.0f); + SHVec4 btmExtent4 = SHMatrix::Translate(comp.size.x * 0.5f, -comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f,0.0f, 0.0f,1.0f); + + + SHVec2 topExtent{ topExtent4.x,topExtent4.y }; + SHVec2 btmExtent{ btmExtent4.x,btmExtent4.y }; + + + SHVec2 mousePos; + SHVec2 windowSize; +#ifdef SHEDITOR + windowSize = SHEditorWindowManager::GetEditorWindow()->beginContentRegionAvailable; + mousePos = SHEditorWindowManager::GetEditorWindow()->viewportMousePos; + //mousePos.y = windowSize.y - mousePos.y; + //SHLOG_INFO("mouse pos: {}, {}", mousePos.x, mousePos.y) + mousePos /= windowSize; + //SHLOG_INFO("mouse pos normalized: {}, {}", mousePos.x, mousePos.y) + + + +#else + + int x, y; + SHInputManager::GetMouseScreenPosition(&x, &y); + mousePos.x = x; + mousePos.y = y; + auto ws = SHSystemManager::GetSystem()->GetWindow()->GetWindowSize(); + windowSize = { ws.first,ws.second }; + mousePos /= windowSize; +#endif + + SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0)}; + //SHLOG_INFO("TopExtent: {}, {}", topExtent.x, topExtent.y) + + topExtent = CanvasToScreenPoint(topExtent,true); + btmExtent = CanvasToScreenPoint(btmExtent,true); + //SHLOG_INFO("TopExtent: {}, {} Btm Extent: {}, {}", topExtent.x, topExtent.y, btmExtent.x, btmExtent.y) + + + //comp.isClicked = false; + if (mousePos.x >= topExtent.x && mousePos.x <= btmExtent.x + && mousePos.y >= topExtent.y && mousePos.y <= btmExtent.y) + { + comp.isHovered = true; + #ifdef SHEDITOR + //if (SHSystemManager::GetSystem()->editorState == SHEditor::State::PLAY) + { + if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB)) + { + comp.isClicked = true; + } + } + #else + if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB)) + { + comp.isClicked = true; + } + #endif + + //SHLOG_INFO("HOVERED") + } + else + { + comp.isHovered = false; + //SHLOG_INFO("NOT HOVERED") + } + if (comp.isClicked && SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB)) + { + comp.isClicked = false; + SHButtonClickEvent clickEvent; + clickEvent.EID = comp.GetEID(); + SHEventManager::BroadcastEvent(clickEvent, SH_BUTTON_CLICK_EVENT); + } + + if (SHComponentManager::HasComponent(comp.GetEID())) + { + auto renderable = SHComponentManager::GetComponent_s(comp.GetEID()); + //auto texture = SHResourceManager::Get(comp.GetDefaultTexture()); + + auto material = renderable->GetModifiableMaterial(); + if(!comp.isHovered && !comp.isClicked) + if (comp.GetDefaultTexture() != 0 && SHAssetManager::GetType(comp.GetDefaultTexture()) == AssetType::TEXTURE) + { + material->SetProperty("data.textureIndex", comp.GetDefaultTexture()); + //SHLOG_INFO("SETTING DEFAULT TEXTURE") + } + else if (comp.isClicked) + { + if (comp.GetClickedTexture() != 0 && SHAssetManager::GetType(comp.GetClickedTexture()) == AssetType::TEXTURE) + { + material->SetProperty("data.textureIndex", comp.GetClickedTexture()); + //SHLOG_INFO("SETTING CLICKED TEXTURE") + } + } + else + { + if (comp.GetHoveredTexture() != 0 && SHAssetManager::GetType(comp.GetHoveredTexture()) == AssetType::TEXTURE) + { + material->SetProperty("data.textureIndex", comp.GetHoveredTexture()); + //SHLOG_INFO("SETTING HOVERED TEXTURE") + } + } + + + + } + } + + + void SHUISystem::UpdateToggleButtonComponent(SHToggleButtonComponent& comp) noexcept + { + if (!SHComponentManager::HasComponent(comp.GetEID())) { return; } auto cameraSystem = SHSystemManager::GetSystem(); auto uiComp = SHComponentManager::GetComponent(comp.GetEID()); - SHVec4 topExtent4 = uiComp->GetMatrix() * SHVec4(-comp.size.x * 0.5f, comp.size.y * 0.5f , 0.0f,1.0f); - SHVec4 btmExtent4 = uiComp->GetMatrix() * SHVec4(comp.size.x * 0.5f , -comp.size.y * 0.5f , 0.0f, 1.0f); + SHVec4 topExtent4 = SHMatrix::Translate(-comp.size.x * 0.5f, comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f, 0.0f, 0.0f, 1.0f); + SHVec4 btmExtent4 = SHMatrix::Translate(comp.size.x * 0.5f, -comp.size.y * 0.5f, 0.0f) * uiComp->GetMatrix() * SHVec4(0.0f, 0.0f, 0.0f, 1.0f); - SHVec2 topExtent{ topExtent4.x,-topExtent4.y }; - SHVec2 btmExtent{ btmExtent4.x,-btmExtent4.y }; - + SHVec2 topExtent{ topExtent4.x,topExtent4.y }; + SHVec2 btmExtent{ btmExtent4.x,btmExtent4.y }; - SHVec2 windowSize; SHVec2 mousePos; + SHVec2 windowSize; + #ifdef SHEDITOR - - windowSize = SHEditorWindowManager::GetEditorWindow()->windowSize; + windowSize = SHEditorWindowManager::GetEditorWindow()->beginContentRegionAvailable; mousePos = SHEditorWindowManager::GetEditorWindow()->viewportMousePos; + //mousePos.y = windowSize.y - mousePos.y; + //SHLOG_INFO("mouse pos: {}, {}", mousePos.x, mousePos.y) + mousePos /= windowSize; + //SHLOG_INFO("mouse pos normalized: {}, {}", mousePos.x, mousePos.y) -#endif - - - - SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0).x , cameraSystem->GetCameraWidthHeight(0).y }; - - topExtent += camSize * 0.5f; - btmExtent += camSize * 0.5f; - - //Convert everything to using ratios - topExtent /= camSize; - btmExtent /= camSize; +#else + int x, y; + SHInputManager::GetMouseScreenPosition(&x, &y); + mousePos.x = x; + mousePos.y = y; + auto ws = SHSystemManager::GetSystem()->GetWindow()->GetWindowSize(); + windowSize = { ws.first,ws.second }; mousePos /= windowSize; +#endif + + SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0) }; + + + + topExtent = CanvasToScreenPoint(topExtent,true); + btmExtent = CanvasToScreenPoint(btmExtent, true); + + - //SHLOG_INFO("mousePos: {} , {}", mousePos.x, mousePos.y); comp.isClicked = false; if (mousePos.x >= topExtent.x && mousePos.x <= btmExtent.x && mousePos.y >= topExtent.y && mousePos.y <= btmExtent.y) { comp.isHovered = true; - if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB)) +#ifdef SHEDITOR + if (SHSystemManager::GetSystem()->editorState == SHEditor::State::PLAY) + { + if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB)) + { + comp.isClicked = true; + } + } +#else + if (SHInputManager::GetKeyDown(SHInputManager::SH_KEYCODE::LMB)) { comp.isClicked = true; } - //SHLOG_INFO("BUTTON HOVERED"); - - +#endif } else { comp.isHovered = false; - - //SHLOG_INFO("BUTTON NOT HOVERED") } - - + + + if (comp.isClicked && SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB)) + { + comp.isClicked = false; + comp.value = !comp.value; + SHButtonClickEvent clickEvent; + clickEvent.EID = comp.GetEID(); + clickEvent.value = comp.value; + SHEventManager::BroadcastEvent(clickEvent, SH_BUTTON_CLICK_EVENT); + } + if (SHComponentManager::HasComponent(comp.GetEID())) { - //auto renderable = SHComponentManager::GetComponent_s(comp.GetEID()); + auto renderable = SHComponentManager::GetComponent_s(comp.GetEID()); //auto texture = SHResourceManager::Get(comp.GetDefaultTexture()); - //auto material = renderable->GetModifiableMaterial(); - //material->SetProperty("texture", comp.GetDefaultTexture()); + auto material = renderable->GetModifiableMaterial(); + if (comp.GetValue() == false) + { + if (comp.GetDefaultTexture()!= 0 && SHAssetManager::GetType(comp.GetDefaultTexture()) == AssetType::TEXTURE) + { + material->SetProperty("data.textureIndex", comp.GetDefaultTexture()); + //SHLOG_INFO("SETTING DEFAULT TEXTURE") + } + } + else + { + if (comp.GetToggledTexture() != 0 && SHAssetManager::GetType(comp.GetToggledTexture()) == AssetType::TEXTURE) + { + material->SetProperty("data.textureIndex", comp.GetToggledTexture()); + //SHLOG_INFO("SETTING DEFAULT TEXTURE") + } + } + } } + void SHUISystem::UpdateButtonsRoutine::Execute(double dt) noexcept { SHUISystem* system = (SHUISystem*)GetSystem(); @@ -219,6 +385,34 @@ namespace SHADE if (SHSceneManager::CheckNodeAndComponentsActive(comp.GetEID())) system->UpdateButtonComponent(comp); } + + auto& toggleButtonDense = SHComponentManager::GetDense(); + for (auto& comp : toggleButtonDense) + { + if (SHSceneManager::CheckNodeAndComponentsActive(comp.GetEID())) + system->UpdateToggleButtonComponent(comp); + } } + SHVec2 SHUISystem::CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept + { + SHVec2 result{canvasPoint}; + + auto cameraSystem = SHSystemManager::GetSystem(); + + SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0) }; + //camSize.y *= -1.0f; + + result.y *= -1.0f; + result += camSize * 0.5f; + + if (normalized) + return result / camSize; + else + return result; + } + + + + }//end namespace diff --git a/SHADE_Engine/src/UI/SHUISystem.h b/SHADE_Engine/src/UI/SHUISystem.h index 04e057ad..ae1091ec 100644 --- a/SHADE_Engine/src/UI/SHUISystem.h +++ b/SHADE_Engine/src/UI/SHUISystem.h @@ -3,14 +3,20 @@ #include "SH_API.h" #include "ECS_Base/System/SHSystem.h" #include "ECS_Base/System/SHSystemRoutine.h" -#include "SHUIComponent.h" -#include "SHButtonComponent.h" -#include "SHCanvasComponent.h" + #include "Scene/SHSceneGraph.h" #include "Scene/SHSceneManager.h" +#include "Math/Vector/SHVec2.h" namespace SHADE { + + class SHButtonComponent; + class SHUIComponent; + class SHToggleButtonComponent; + class SHSliderComponent; + class SHCanvasComponent; + class SH_API SHUISystem final: public SHSystem { public: @@ -64,7 +70,11 @@ namespace SHADE private: void UpdateUIComponent(SHUIComponent& comp) noexcept; void UpdateButtonComponent(SHButtonComponent& comp) noexcept; + void UpdateToggleButtonComponent(SHToggleButtonComponent& comp) noexcept; void UpdateCanvasComponent(SHCanvasComponent& comp) noexcept; + + SHVec2 CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept; + }; diff --git a/SHADE_Managed/src/Components/Transform.cxx b/SHADE_Managed/src/Components/Transform.cxx index bc61eff3..d5b38967 100644 --- a/SHADE_Managed/src/Components/Transform.cxx +++ b/SHADE_Managed/src/Components/Transform.cxx @@ -107,8 +107,7 @@ namespace SHADE Vector3 Transform::Forward::get() { - const SHVec3 DIRECTION = SHVec3::Rotate(-SHVec3::UnitZ, Convert::ToNative(GlobalRotation)); - return Convert::ToCLI(DIRECTION); + return Vector3::Rotate(Vector3::Forward, GlobalRotation); } /*-----------------------------------------------------------------------------------*/ diff --git a/SHADE_Managed/src/Math/Vector3.cxx b/SHADE_Managed/src/Math/Vector3.cxx index d2862ac7..647174a2 100644 --- a/SHADE_Managed/src/Math/Vector3.cxx +++ b/SHADE_Managed/src/Math/Vector3.cxx @@ -167,6 +167,10 @@ namespace SHADE { return Convert::ToCLI(SHVec3::Rotate(Convert::ToNative(vec), Convert::ToNative(axis), radians)); } + Vector3 Vector3::Rotate(Vector3 vec, Quaternion quat) + { + return Convert::ToCLI(SHVec3::Rotate(Convert::ToNative(vec), Convert::ToNative(quat))); + } Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs) { float lx = lhs.x, rx = rhs.x; diff --git a/SHADE_Managed/src/Math/Vector3.hxx b/SHADE_Managed/src/Math/Vector3.hxx index 76b11420..31a373ba 100644 --- a/SHADE_Managed/src/Math/Vector3.hxx +++ b/SHADE_Managed/src/Math/Vector3.hxx @@ -19,10 +19,17 @@ of DigiPen Institute of Technology is prohibited. // Project Includes #include "Vector2.hxx" -value struct Quaternion; - namespace SHADE { + /*---------------------------------------------------------------------------------*/ + /* Forward Declarations */ + /*-------------------------------------------------------------------------- --- */ + value struct Quaternion; + + /*---------------------------------------------------------------------------------*/ + /* Type Definitions */ + /*-------------------------------------------------------------------------- --- */ + /// /// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector. /// Designed to closely match Unity's Vector3 struct. @@ -308,6 +315,12 @@ namespace SHADE /// The Vector3 that represents the rotated vector. static Vector3 Rotate(Vector3 vec, Vector3 axis, float radians); /// + /// Rotates a Vector3 using a Quaternion. + /// + /// A Vector3 to rotate. + /// A Quaternion to rotate the vector with. + static Vector3 Rotate(Vector3 vec, Quaternion quat); + /// /// Computes and returns a Vector3 that is made from the smallest components of /// the two specified Vector3s. ///