Merge remote-tracking branch 'origin/main' into SP3-1-Rendering
This commit is contained in:
commit
09911cc50c
|
@ -364,3 +364,7 @@ MigrationBackup/
|
||||||
*.filters
|
*.filters
|
||||||
|
|
||||||
Assets/Editor/Layouts/UserLayout.ini
|
Assets/Editor/Layouts/UserLayout.ini
|
||||||
|
|
||||||
|
JSON/Schemas/Catalog/
|
||||||
|
|
||||||
|
Assets/Editor/Editor.SHConfig
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
Start in Fullscreen: false
|
Start in Fullscreen: false
|
||||||
Starting Scene ID: 86098106
|
Starting Scene ID: 87244611
|
||||||
Window Size: {x: 1920, y: 1080}
|
Window Size: {x: 1920, y: 1080}
|
||||||
Window Title: SHADE Engine
|
Window Title: SHADE Engine
|
|
@ -0,0 +1 @@
|
||||||
|
0
|
|
@ -0,0 +1,4 @@
|
||||||
|
Start Maximized: true
|
||||||
|
Working Scene ID: 97161771
|
||||||
|
Window Size: {x: 1920, y: 1080}
|
||||||
|
Style: 0
|
|
@ -1,7 +1,7 @@
|
||||||
- EID: 0
|
- EID: 0
|
||||||
Name: Canvas
|
Name: Canvas
|
||||||
IsActive: true
|
IsActive: true
|
||||||
NumberOfChildren: 1
|
NumberOfChildren: 2
|
||||||
Components:
|
Components:
|
||||||
Canvas Component:
|
Canvas Component:
|
||||||
Canvas Width: 10
|
Canvas Width: 10
|
||||||
|
@ -28,6 +28,26 @@
|
||||||
Clicked Texture: 0
|
Clicked Texture: 0
|
||||||
IsActive: true
|
IsActive: true
|
||||||
Scripts: ~
|
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
|
- EID: 1
|
||||||
Name: Camera
|
Name: Camera
|
||||||
IsActive: true
|
IsActive: true
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
Name: UI_Test
|
Name: UI_Test
|
||||||
ID: 87707373
|
ID: 87244611
|
||||||
Type: 5
|
Type: 5
|
||||||
|
|
|
@ -20,10 +20,11 @@ echo "M - SDL"
|
||||||
echo "N - dotnet"
|
echo "N - dotnet"
|
||||||
echo "O - tinyddsloader"
|
echo "O - tinyddsloader"
|
||||||
echo "P - fmod"
|
echo "P - fmod"
|
||||||
|
echo "Q - vswhere"
|
||||||
echo ---------------------------------------------------
|
echo ---------------------------------------------------
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
choice /C ABCDEFGHIJKLMNOP /T 10 /D A
|
choice /C ABCDEFGHIJKLMNOPQ /T 10 /D A
|
||||||
set _e=%ERRORLEVEL%
|
set _e=%ERRORLEVEL%
|
||||||
|
|
||||||
if %_e%==1 goto VMA
|
if %_e%==1 goto VMA
|
||||||
|
@ -42,6 +43,7 @@ if %_e%==13 goto SDL
|
||||||
if %_e%==14 goto dotnet
|
if %_e%==14 goto dotnet
|
||||||
if %_e%==15 goto tinyddsloader
|
if %_e%==15 goto tinyddsloader
|
||||||
if %_e%==16 goto fmod
|
if %_e%==16 goto fmod
|
||||||
|
if %_e%==17 goto vswhere
|
||||||
|
|
||||||
:VMA
|
:VMA
|
||||||
echo -----------------------VMA----------------------------
|
echo -----------------------VMA----------------------------
|
||||||
|
@ -155,6 +157,13 @@ if %_e%==15 (goto :done) else (goto :fmod)
|
||||||
echo --------------------fmod-------------------------
|
echo --------------------fmod-------------------------
|
||||||
rmdir "Dependencies/fmod" /S /Q
|
rmdir "Dependencies/fmod" /S /Q
|
||||||
git clone https://github.com/SHADE-DP/FMOD.git "Dependencies/fmod"
|
git clone https://github.com/SHADE-DP/FMOD.git "Dependencies/fmod"
|
||||||
|
if %_e%==16 (goto :done) else (goto :vswhere)
|
||||||
|
|
||||||
|
:vswhere
|
||||||
|
echo -----------------------vswhere----------------------------
|
||||||
|
rmdir "Dependencies/vswhere" /S /Q
|
||||||
|
mkdir "Dependencies/vswhere"
|
||||||
|
powershell -Command "& {wget https://github.com/microsoft/vswhere/releases/download/3.1.1/vswhere.exe -OutFile "Dependencies/vswhere/vswhere.exe"}"
|
||||||
|
|
||||||
:done
|
:done
|
||||||
echo DONE!
|
echo DONE!
|
||||||
|
|
|
@ -17,3 +17,4 @@ IncludeDir["VULKAN"] = "$(VULKAN_SDK)"
|
||||||
IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet"
|
IncludeDir["dotnet"] = "%{wks.location}\\Dependencies\\dotnet"
|
||||||
IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader"
|
IncludeDir["tinyddsloader"] = "%{wks.location}\\Dependencies\\tinyddsloader"
|
||||||
IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod"
|
IncludeDir["fmod"] = "%{wks.location}\\Dependencies\\fmod"
|
||||||
|
IncludeDir["vswhere"] = "%{wks.location}\\Dependencies\\vswhere"
|
|
@ -67,6 +67,9 @@ namespace Sandbox
|
||||||
SHFileUtilities::SetWorkDirToExecDir();
|
SHFileUtilities::SetWorkDirToExecDir();
|
||||||
WindowData wndData{};
|
WindowData wndData{};
|
||||||
auto& appConfig = SHConfigurationManager::LoadApplicationConfig(&wndData);
|
auto& appConfig = SHConfigurationManager::LoadApplicationConfig(&wndData);
|
||||||
|
#if SHEDITOR
|
||||||
|
auto& editorConfig = SHConfigurationManager::LoadEditorConfig(&wndData);
|
||||||
|
#endif
|
||||||
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
|
window.Create(hInstance, hPrevInstance, lpCmdLine, nCmdShow, wndData);
|
||||||
|
|
||||||
// Create Systems
|
// Create Systems
|
||||||
|
@ -158,8 +161,11 @@ namespace Sandbox
|
||||||
|
|
||||||
SHSystemManager::Init();
|
SHSystemManager::Init();
|
||||||
|
|
||||||
|
#if SHEDITOR
|
||||||
|
SHSceneManager::InitSceneManager<SBMainScene>(editorConfig.workingSceneID);
|
||||||
|
#else
|
||||||
SHSceneManager::InitSceneManager<SBMainScene>(appConfig.startingSceneID);
|
SHSceneManager::InitSceneManager<SBMainScene>(appConfig.startingSceneID);
|
||||||
|
#endif
|
||||||
SHFrameRateController::UpdateFRC();
|
SHFrameRateController::UpdateFRC();
|
||||||
|
|
||||||
// Link up SHDebugDraw
|
// Link up SHDebugDraw
|
||||||
|
|
|
@ -124,7 +124,8 @@ project "SHADE_Engine"
|
||||||
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\ModelCompiler.exe\" \"$(OutDir)\"",
|
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Debug\\ModelCompiler.exe\" \"$(OutDir)\"",
|
||||||
"xcopy /r /y /q \"%{IncludeDir.FontCompiler}\\bin\\Debug\\FontCompiler.exe\" \"$(OutDir)\"",
|
"xcopy /r /y /q \"%{IncludeDir.FontCompiler}\\bin\\Debug\\FontCompiler.exe\" \"$(OutDir)\"",
|
||||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"",
|
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodL.dll\" \"$(OutDir)\"",
|
||||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\""
|
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudioL.dll\" \"$(OutDir)\"",
|
||||||
|
"xcopy /r /y /q \"%{IncludeDir.vswhere}\\vswhere.exe\" \"$(OutDir)\""
|
||||||
}
|
}
|
||||||
|
|
||||||
filter "configurations:Release"
|
filter "configurations:Release"
|
||||||
|
@ -134,7 +135,8 @@ project "SHADE_Engine"
|
||||||
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\ModelCompiler.exe\" \"$(OutDir)\"",
|
"xcopy /r /y /q \"%{IncludeDir.ModelCompiler}\\bin\\Release\\ModelCompiler.exe\" \"$(OutDir)\"",
|
||||||
"xcopy /r /y /q \"%{IncludeDir.FontCompiler}\\bin\\Release\\FontCompiler.exe\" \"$(OutDir)\"",
|
"xcopy /r /y /q \"%{IncludeDir.FontCompiler}\\bin\\Release\\FontCompiler.exe\" \"$(OutDir)\"",
|
||||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmod.dll\" \"$(OutDir)\"",
|
||||||
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\""
|
"xcopy /r /y /q \"%{IncludeDir.fmod}\\lib\\fmodstudio.dll\" \"$(OutDir)\"",
|
||||||
|
"xcopy /r /y /q \"%{IncludeDir.vswhere}\\vswhere.exe\" \"$(OutDir)\""
|
||||||
}
|
}
|
||||||
|
|
||||||
filter "configurations:Publish"
|
filter "configurations:Publish"
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#include "Events/SHEventManager.hpp"
|
#include "Events/SHEventManager.hpp"
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
|
@ -151,6 +151,32 @@ namespace SHADE
|
||||||
return (componentSet.GetSparseSet<T>()->GetElement_s(EntityHandleGenerator::GetIndex(entityID)));
|
return (componentSet.GetSparseSet<T>()->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<typename ...T>
|
||||||
|
static std::enable_if_t<(... && std::is_base_of_v<SHComponent, T>), std::tuple<T*...>> GetComponents(EntityID entityID) noexcept
|
||||||
|
{
|
||||||
|
return std::make_tuple<T*...>(GetComponent_s<T>(entityID)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*!*************************************************************************
|
/*!*************************************************************************
|
||||||
* \brief
|
* \brief
|
||||||
* Gets the Component of the entity with the specified entityID
|
* Gets the Component of the entity with the specified entityID
|
||||||
|
|
|
@ -18,11 +18,17 @@ namespace SHADE
|
||||||
|
|
||||||
SHCommandManager::CommandStackPtr SHCommandManager::pCurrUndoStack(&undoStack);
|
SHCommandManager::CommandStackPtr SHCommandManager::pCurrUndoStack(&undoStack);
|
||||||
SHCommandManager::CommandStackPtr SHCommandManager::pCurrRedoStack(&redoStack);
|
SHCommandManager::CommandStackPtr SHCommandManager::pCurrRedoStack(&redoStack);
|
||||||
|
bool SHCommandManager::failedExecution(false);
|
||||||
|
|
||||||
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
|
void SHCommandManager::PerformCommand(BaseCommandPtr commandPtr, bool const& overrideValue)
|
||||||
{
|
{
|
||||||
*pCurrRedoStack = CommandStack(defaultStackSize);
|
|
||||||
commandPtr->Execute();
|
commandPtr->Execute();
|
||||||
|
if(failedExecution)
|
||||||
|
{
|
||||||
|
failedExecution = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
*pCurrRedoStack = CommandStack(defaultStackSize);
|
||||||
if (overrideValue && !pCurrUndoStack->Empty())
|
if (overrideValue && !pCurrUndoStack->Empty())
|
||||||
{
|
{
|
||||||
pCurrUndoStack->Top()->Merge(commandPtr);
|
pCurrUndoStack->Top()->Merge(commandPtr);
|
||||||
|
@ -68,12 +74,14 @@ namespace SHADE
|
||||||
|
|
||||||
void SHCommandManager::PopLatestCommandFromRedoStack()
|
void SHCommandManager::PopLatestCommandFromRedoStack()
|
||||||
{
|
{
|
||||||
pCurrRedoStack->Pop();
|
if(!pCurrRedoStack->Empty())
|
||||||
|
pCurrRedoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::PopLatestCommandFromUndoStack()
|
void SHCommandManager::PopLatestCommandFromUndoStack()
|
||||||
{
|
{
|
||||||
pCurrUndoStack->Pop();
|
if(!pCurrUndoStack->Empty())
|
||||||
|
pCurrUndoStack->Pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHCommandManager::SwapStacks()
|
void SHCommandManager::SwapStacks()
|
||||||
|
|
|
@ -39,6 +39,7 @@ namespace SHADE
|
||||||
static void SwapStacks();
|
static void SwapStacks();
|
||||||
static void ClearAll();
|
static void ClearAll();
|
||||||
|
|
||||||
|
static bool failedExecution;
|
||||||
static constexpr CommandStack::SizeType defaultStackSize = 100;
|
static constexpr CommandStack::SizeType defaultStackSize = 100;
|
||||||
private:
|
private:
|
||||||
static CommandStackPtr pCurrUndoStack;
|
static CommandStackPtr pCurrUndoStack;
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
#include "Editor/DragDrop/SHDragDrop.hpp"
|
#include "Editor/DragDrop/SHDragDrop.hpp"
|
||||||
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
|
#include "Editor/EditorWindow/MaterialInspector/SHMaterialInspector.h"
|
||||||
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
#include "Editor/EditorWindow/SHEditorWindowManager.h"
|
||||||
|
#include "Scripting/SHVSUtilities.h"
|
||||||
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -249,6 +251,12 @@ namespace SHADE
|
||||||
matInspector->OpenMaterial(asset->id);
|
matInspector->OpenMaterial(asset->id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case AssetType::SCRIPT:
|
||||||
|
if(auto scriptEngine = SHSystemManager::GetSystem<SHScriptEngine>())
|
||||||
|
{
|
||||||
|
scriptEngine->OpenFile(asset->path);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case AssetType::MAX_COUNT: break;
|
case AssetType::MAX_COUNT: break;
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,33 +84,31 @@ namespace SHADE
|
||||||
editor->selectedEntities.clear();
|
editor->selectedEntities.clear();
|
||||||
}
|
}
|
||||||
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
|
ImGui::SeparatorEx(ImGuiSeparatorFlags_Horizontal);
|
||||||
if (ImGui::IsWindowFocused())
|
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A))
|
||||||
{
|
{
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_A))
|
SelectAllEntities();
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_C))
|
||||||
|
{
|
||||||
|
CopySelectedEntities();
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
|
||||||
|
{
|
||||||
|
PasteEntities();
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
|
||||||
|
{
|
||||||
|
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
||||||
|
if (editor->selectedEntities.size() == 1)
|
||||||
{
|
{
|
||||||
SelectAllEntities();
|
PasteEntities(editor->selectedEntities.back());
|
||||||
}
|
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_C))
|
|
||||||
{
|
|
||||||
CopySelectedEntities();
|
|
||||||
}
|
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && !ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
|
|
||||||
{
|
|
||||||
PasteEntities();
|
|
||||||
}
|
|
||||||
if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyReleased(ImGuiKey_V))
|
|
||||||
{
|
|
||||||
const auto editor = SHSystemManager::GetSystem<SHEditor>();
|
|
||||||
if (editor->selectedEntities.size() == 1)
|
|
||||||
{
|
|
||||||
PasteEntities(editor->selectedEntities.back());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(ImGui::IsKeyReleased(ImGuiKey_Delete))
|
|
||||||
{
|
|
||||||
DeleteSelectedEntities();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsKeyReleased(ImGuiKey_Delete))
|
||||||
|
{
|
||||||
|
DeleteSelectedEntities();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
if(ImGui::IsWindowHovered() && !ImGui::IsAnyItemHovered() && ImGui::IsMouseReleased(ImGuiMouseButton_Left))
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
#include "Reflection/SHReflectionMetadata.h"
|
#include "Reflection/SHReflectionMetadata.h"
|
||||||
#include "Resource/SHResourceManager.h"
|
#include "Resource/SHResourceManager.h"
|
||||||
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
#include "Physics/Collision/SHCollisionTagMatrix.h"
|
||||||
|
#include "Serialization/SHSerializationHelper.hpp"
|
||||||
|
#include "Tools/Utilities/SHClipboardUtilities.h"
|
||||||
|
#include "SHInspectorCommands.h"
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -46,11 +49,12 @@ namespace SHADE
|
||||||
|
|
||||||
if (ImGui::Selectable(std::format("{} Copy {}", ICON_MD_CONTENT_COPY, componentName.data()).data()))
|
if (ImGui::Selectable(std::format("{} Copy {}", ICON_MD_CONTENT_COPY, componentName.data()).data()))
|
||||||
{
|
{
|
||||||
//SHClipboardUtil::WriteStringToClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT, SHComponentToString(component));
|
SHClipboardUtilities::WriteToClipboard(SHSerializationHelper::SerializeComponentToString<T>(component->GetEID()));
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable(std::format("{} Paste {}", ICON_MD_CONTENT_PASTE, componentName.data()).data()))
|
if (ImGui::Selectable(std::format("{} Paste {}", ICON_MD_CONTENT_PASTE, componentName.data()).data()))
|
||||||
{
|
{
|
||||||
//SHStringToComponent(component, SHClipboardUtil::ReadStringFromClipboard(SHClipboardUtil::CFNAME::CFCOMPONENT));
|
//SHSerializationHelper::DeserializeComponentFromString<T>(SHClipboardUtilities::GetDataFromClipboard(), component->GetEID());
|
||||||
|
SHCommandManager::PerformCommand(std::reinterpret_pointer_cast<SHBaseCommand>( std::make_shared<SHPasteComponentCommand<T>>(component->GetEID(), SHClipboardUtilities::GetDataFromClipboard())));
|
||||||
}
|
}
|
||||||
if (ImGui::Selectable(std::format("{} Delete {}", ICON_MD_DELETE, componentName.data()).data()))
|
if (ImGui::Selectable(std::format("{} Delete {}", ICON_MD_DELETE, componentName.data()).data()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#include "UI/SHUIComponent.h"
|
#include "UI/SHUIComponent.h"
|
||||||
#include "UI/SHCanvasComponent.h"
|
#include "UI/SHCanvasComponent.h"
|
||||||
#include "UI/SHButtonComponent.h"
|
#include "UI/SHButtonComponent.h"
|
||||||
|
#include "UI/SHToggleButtonComponent.h"
|
||||||
#include "SHEditorComponentView.h"
|
#include "SHEditorComponentView.h"
|
||||||
#include "AudioSystem/SHAudioListenerComponent.h"
|
#include "AudioSystem/SHAudioListenerComponent.h"
|
||||||
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
#include "Graphics/MiddleEnd/TextRendering/SHTextRenderableComponent.h"
|
||||||
|
@ -154,6 +155,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
DrawComponent(buttonComponent);
|
DrawComponent(buttonComponent);
|
||||||
}
|
}
|
||||||
|
if (auto toggleButton = SHComponentManager::GetComponent_s<SHToggleButtonComponent>(eid))
|
||||||
|
{
|
||||||
|
DrawComponent(toggleButton);
|
||||||
|
}
|
||||||
ImGui::Separator();
|
ImGui::Separator();
|
||||||
// Render Scripts
|
// Render Scripts
|
||||||
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
|
@ -167,6 +172,7 @@ namespace SHADE
|
||||||
DrawAddComponentButton<SHLightComponent>(eid);
|
DrawAddComponentButton<SHLightComponent>(eid);
|
||||||
DrawAddComponentButton<SHCanvasComponent>(eid);
|
DrawAddComponentButton<SHCanvasComponent>(eid);
|
||||||
DrawAddComponentButton<SHButtonComponent>(eid);
|
DrawAddComponentButton<SHButtonComponent>(eid);
|
||||||
|
DrawAddComponentButton<SHToggleButtonComponent>(eid);
|
||||||
|
|
||||||
// Components that require Transforms
|
// Components that require Transforms
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
#include "Editor/Command/SHCommand.hpp"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
class SHPasteComponentCommand final : SHBaseCommand
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Data
|
||||||
|
{
|
||||||
|
EntityID eid;
|
||||||
|
std::string oldComponentData;
|
||||||
|
std::string newComponentData;
|
||||||
|
};
|
||||||
|
|
||||||
|
SHPasteComponentCommand(EntityID eid, std::string const& newComponentData);
|
||||||
|
|
||||||
|
void Execute() override;
|
||||||
|
void Undo() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
Data data;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "SHInspectorCommands.hpp"
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
#include "SHInspectorCommands.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
template<typename T>
|
||||||
|
SHPasteComponentCommand<T>::SHPasteComponentCommand(EntityID eid, std::string const& newComponentData)
|
||||||
|
:data(eid, {}, newComponentData)
|
||||||
|
{
|
||||||
|
data.oldComponentData = SHSerializationHelper::SerializeComponentToString<T>(eid);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SHPasteComponentCommand<T>::Execute()
|
||||||
|
{
|
||||||
|
bool result = SHSerializationHelper::DeserializeComponentFromString<T>(data.newComponentData, data.eid);
|
||||||
|
if(!result)
|
||||||
|
SHCommandManager::failedExecution = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void SHPasteComponentCommand<T>::Undo()
|
||||||
|
{
|
||||||
|
SHSerializationHelper::DeserializeComponentFromString<T>(data.oldComponentData, data.eid);
|
||||||
|
}
|
||||||
|
}
|
|
@ -81,126 +81,18 @@ namespace SHADE
|
||||||
|
|
||||||
if (ImGui::BeginMainMenuBar())
|
if (ImGui::BeginMainMenuBar())
|
||||||
{
|
{
|
||||||
if (ImGui::BeginMenu("File"))
|
DrawFileMenu();
|
||||||
{
|
DrawEditMenu();
|
||||||
if(ImGui::Selectable("New Scene"))
|
DrawScriptsMenu();
|
||||||
{
|
DrawWindowMenu();
|
||||||
SHSystemManager::GetSystem<SHEditor>()->NewScene();
|
DrawThemeMenu();
|
||||||
}
|
DrawLayoutMenu();
|
||||||
if(ImGui::Selectable("Save"))
|
DrawApplicationConfig();
|
||||||
{
|
|
||||||
SHSystemManager::GetSystem<SHEditor>()->SaveScene();
|
|
||||||
}
|
|
||||||
if(ImGui::Selectable("Load"))
|
|
||||||
{
|
|
||||||
//SHSystemManager::GetSystem<SHEditor>()->LoadScene()
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
if(ImGui::BeginMenu("Edit"))
|
|
||||||
{
|
|
||||||
ImGui::BeginDisabled(!SHCommandManager::GetUndoStackSize());
|
|
||||||
if(ImGui::Button(std::format("{} Undo", ICON_MD_UNDO).data()))
|
|
||||||
{
|
|
||||||
SHCommandManager::UndoCommand();
|
|
||||||
}
|
|
||||||
ImGui::EndDisabled();
|
|
||||||
ImGui::BeginDisabled(!SHCommandManager::GetRedoStackSize());
|
|
||||||
if(ImGui::Button(std::format("{} Redo", ICON_MD_REDO).data()))
|
|
||||||
{
|
|
||||||
SHCommandManager::RedoCommand();
|
|
||||||
}
|
|
||||||
ImGui::EndDisabled();
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginMenu("Scripts"))
|
|
||||||
{
|
|
||||||
if (ImGui::Selectable("Generate Visual Studio Project"))
|
|
||||||
{
|
|
||||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
|
||||||
scriptEngine->GenerateScriptsCsProjFile();
|
|
||||||
}
|
|
||||||
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
|
|
||||||
if (ImGui::Selectable("Build Scripts - Debug"))
|
|
||||||
{
|
|
||||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
|
||||||
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
|
|
||||||
scriptEngine->BuildScriptAssembly(true, true);
|
|
||||||
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
|
|
||||||
}
|
|
||||||
if (ImGui::Selectable("Build Scripts - Release"))
|
|
||||||
{
|
|
||||||
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
|
||||||
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
|
|
||||||
scriptEngine->BuildScriptAssembly(false, true);
|
|
||||||
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
|
|
||||||
}
|
|
||||||
ImGui::EndDisabled();
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Window"))
|
std::string const sceneName{std::format("Current Scene: {}",SHSceneManager::GetSceneName().data())};
|
||||||
{
|
auto const size = ImGui::CalcTextSize(sceneName.data());
|
||||||
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
ImGui::SetCursorPosX(ImGui::GetWindowWidth() - size.x - ImGui::GetStyle().FramePadding.x);
|
||||||
{
|
ImGui::Text("%s", sceneName.data());
|
||||||
if (window.get() != this)
|
|
||||||
ImGui::Checkbox(window->windowName.data(), &window->isOpen);
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
if (ImGui::BeginMenu("Theme"))
|
|
||||||
{
|
|
||||||
const auto styles = rttr::type::get<SHEditor::Style>().get_enumeration();
|
|
||||||
auto values = styles.get_values();
|
|
||||||
for (auto style : values)
|
|
||||||
{
|
|
||||||
if (ImGui::Selectable(style.to_string().c_str()))
|
|
||||||
{
|
|
||||||
if (auto editor = SHSystemManager::GetSystem<SHEditor>())
|
|
||||||
editor->SetStyle(style.convert<SHEditor::Style>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
if(ImGui::BeginMenu("Layout"))
|
|
||||||
{
|
|
||||||
for(auto const& entry : layoutPaths)
|
|
||||||
{
|
|
||||||
if(ImGui::Selectable(entry.stem().string().c_str()))
|
|
||||||
{
|
|
||||||
ImGui::LoadIniSettingsFromDisk(entry.string().c_str());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ImGui::BeginMenu("Application Config"))
|
|
||||||
{
|
|
||||||
auto& appConfig = SHConfigurationManager::applicationConfig;
|
|
||||||
ImGui::InputText("Window Title", &appConfig.windowTitle);
|
|
||||||
ImGui::Checkbox("Start in Fullscreen", &appConfig.startInFullScreen);
|
|
||||||
SHEditorWidgets::DragN<float, 2>("Window Size", { "Width", "Height" }, { &appConfig.windowSize.x, &appConfig.windowSize.y });
|
|
||||||
//ImGui::InputScalar("Starting Scene", ImGuiDataType_U32, &appConfig.startingSceneID);
|
|
||||||
auto sceneAsset = SHAssetManager::GetData<SHSceneAsset>(appConfig.startingSceneID);
|
|
||||||
|
|
||||||
if(ImGui::BeginCombo("Starting Scne", sceneAsset ? sceneAsset->name.data() : ""))
|
|
||||||
{
|
|
||||||
auto scenes = SHAssetManager::GetAllRecordOfType(AssetType::SCENE);
|
|
||||||
for(auto const& scene : scenes)
|
|
||||||
{
|
|
||||||
if(ImGui::Selectable(scene.name.data()))
|
|
||||||
{
|
|
||||||
appConfig.startingSceneID = scene.id;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ImGui::EndCombo();
|
|
||||||
}
|
|
||||||
if (ImGui::Button("Save"))
|
|
||||||
{
|
|
||||||
SHConfigurationManager::SaveApplicationConfig();
|
|
||||||
}
|
|
||||||
ImGui::EndMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
ImGui::EndMainMenuBar();
|
ImGui::EndMainMenuBar();
|
||||||
}
|
}
|
||||||
|
@ -267,4 +159,148 @@ namespace SHADE
|
||||||
ImGui::PopStyleVar(3);
|
ImGui::PopStyleVar(3);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
void SHEditorMenuBar::DrawFileMenu() noexcept
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("File"))
|
||||||
|
{
|
||||||
|
if (ImGui::Selectable("New Scene"))
|
||||||
|
{
|
||||||
|
SHSystemManager::GetSystem<SHEditor>()->NewScene();
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable("Save"))
|
||||||
|
{
|
||||||
|
SHSystemManager::GetSystem<SHEditor>()->SaveScene();
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable("Load"))
|
||||||
|
{
|
||||||
|
//SHSystemManager::GetSystem<SHEditor>()->LoadScene()
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SHEditorMenuBar::DrawEditMenu() noexcept
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("Edit"))
|
||||||
|
{
|
||||||
|
ImGui::BeginDisabled(!SHCommandManager::GetUndoStackSize());
|
||||||
|
if (ImGui::Button(std::format("{} Undo", ICON_MD_UNDO).data()))
|
||||||
|
{
|
||||||
|
SHCommandManager::UndoCommand();
|
||||||
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
ImGui::BeginDisabled(!SHCommandManager::GetRedoStackSize());
|
||||||
|
if (ImGui::Button(std::format("{} Redo", ICON_MD_REDO).data()))
|
||||||
|
{
|
||||||
|
SHCommandManager::RedoCommand();
|
||||||
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SHEditorMenuBar::DrawScriptsMenu() noexcept
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("Scripts"))
|
||||||
|
{
|
||||||
|
if (ImGui::Selectable("Generate Visual Studio Project"))
|
||||||
|
{
|
||||||
|
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
|
scriptEngine->GenerateScriptsCsProjFile();
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable("Open Visual Studio Project"))
|
||||||
|
{
|
||||||
|
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
|
scriptEngine->OpenSolution();
|
||||||
|
}
|
||||||
|
ImGui::BeginDisabled(SHSystemManager::GetSystem<SHEditor>()->editorState != SHEditor::State::STOP);
|
||||||
|
if (ImGui::Selectable("Build Scripts - Debug"))
|
||||||
|
{
|
||||||
|
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
|
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
|
||||||
|
scriptEngine->BuildScriptAssembly(true, true);
|
||||||
|
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||||
|
}
|
||||||
|
if (ImGui::Selectable("Build Scripts - Release"))
|
||||||
|
{
|
||||||
|
auto* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
|
||||||
|
SHSerialization::SerializeSceneToFile(SHSceneManager::GetCurrentSceneAssetID());
|
||||||
|
scriptEngine->BuildScriptAssembly(false, true);
|
||||||
|
SHSceneManager::RestartScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||||
|
}
|
||||||
|
ImGui::EndDisabled();
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SHEditorMenuBar::DrawWindowMenu() noexcept
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("Window"))
|
||||||
|
{
|
||||||
|
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
||||||
|
{
|
||||||
|
if (window.get() != this)
|
||||||
|
ImGui::Checkbox(window->windowName.data(), &window->isOpen);
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SHEditorMenuBar::DrawThemeMenu() noexcept
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("Theme"))
|
||||||
|
{
|
||||||
|
const auto styles = rttr::type::get<SHEditor::Style>().get_enumeration();
|
||||||
|
auto values = styles.get_values();
|
||||||
|
for (auto style : values)
|
||||||
|
{
|
||||||
|
if (ImGui::Selectable(style.to_string().c_str()))
|
||||||
|
{
|
||||||
|
if (auto editor = SHSystemManager::GetSystem<SHEditor>())
|
||||||
|
editor->SetStyle(style.convert<SHEditor::Style>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SHEditorMenuBar::DrawLayoutMenu() noexcept
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("Layout"))
|
||||||
|
{
|
||||||
|
for (auto const& entry : layoutPaths)
|
||||||
|
{
|
||||||
|
if (ImGui::Selectable(entry.stem().string().c_str()))
|
||||||
|
{
|
||||||
|
ImGui::LoadIniSettingsFromDisk(entry.string().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void SHEditorMenuBar::DrawApplicationConfig() noexcept
|
||||||
|
{
|
||||||
|
if (ImGui::BeginMenu("Application Config"))
|
||||||
|
{
|
||||||
|
auto& appConfig = SHConfigurationManager::applicationConfig;
|
||||||
|
ImGui::InputText("Window Title", &appConfig.windowTitle);
|
||||||
|
ImGui::Checkbox("Start in Fullscreen", &appConfig.startInFullScreen);
|
||||||
|
SHEditorWidgets::DragN<float, 2>("Window Size", { "Width", "Height" }, { &appConfig.windowSize.x, &appConfig.windowSize.y });
|
||||||
|
//ImGui::InputScalar("Starting Scene", ImGuiDataType_U32, &appConfig.startingSceneID);
|
||||||
|
auto sceneAsset = SHAssetManager::GetData<SHSceneAsset>(appConfig.startingSceneID);
|
||||||
|
|
||||||
|
if (ImGui::BeginCombo("Starting Scene", sceneAsset ? sceneAsset->name.data() : ""))
|
||||||
|
{
|
||||||
|
auto scenes = SHAssetManager::GetAllRecordOfType(AssetType::SCENE);
|
||||||
|
for (auto const& scene : scenes)
|
||||||
|
{
|
||||||
|
if (ImGui::Selectable(scene.name.data()))
|
||||||
|
{
|
||||||
|
appConfig.startingSceneID = scene.id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ImGui::EndCombo();
|
||||||
|
}
|
||||||
|
if (ImGui::Button("Save"))
|
||||||
|
{
|
||||||
|
SHConfigurationManager::SaveApplicationConfig();
|
||||||
|
}
|
||||||
|
ImGui::EndMenu();
|
||||||
|
}
|
||||||
|
}
|
||||||
}//namespace SHADE
|
}//namespace SHADE
|
||||||
|
|
|
@ -17,6 +17,15 @@ namespace SHADE
|
||||||
void DrawMainMenuBar() noexcept;
|
void DrawMainMenuBar() noexcept;
|
||||||
void DrawSecondaryBar() const noexcept;
|
void DrawSecondaryBar() const noexcept;
|
||||||
void DrawStatusBar() const noexcept;
|
void DrawStatusBar() const noexcept;
|
||||||
|
|
||||||
|
void DrawFileMenu() noexcept;
|
||||||
|
void DrawEditMenu() noexcept;
|
||||||
|
void DrawScriptsMenu() noexcept;
|
||||||
|
void DrawWindowMenu() noexcept;
|
||||||
|
void DrawThemeMenu() noexcept;
|
||||||
|
void DrawLayoutMenu() noexcept;
|
||||||
|
void DrawApplicationConfig() noexcept;
|
||||||
|
|
||||||
float menuBarHeight = 20.0f;
|
float menuBarHeight = 20.0f;
|
||||||
std::vector<std::filesystem::path> layoutPaths;
|
std::vector<std::filesystem::path> layoutPaths;
|
||||||
};//class SHEditorMenuBar
|
};//class SHEditorMenuBar
|
||||||
|
|
|
@ -94,6 +94,8 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
editorConfig = &SHConfigurationManager::LoadEditorConfig();
|
||||||
|
|
||||||
//Add editor windows
|
//Add editor windows
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
|
SHEditorWindowManager::CreateEditorWindow<SHEditorMenuBar>();
|
||||||
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
SHEditorWindowManager::CreateEditorWindow<SHHierarchyPanel>();
|
||||||
|
@ -122,7 +124,7 @@ namespace SHADE
|
||||||
|
|
||||||
InitBackend();
|
InitBackend();
|
||||||
|
|
||||||
SetStyle(Style::SHADE);
|
SetStyle(static_cast<Style>(editorConfig->style));
|
||||||
|
|
||||||
|
|
||||||
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
for (const auto& window : SHEditorWindowManager::editorWindows | std::views::values)
|
||||||
|
@ -160,26 +162,7 @@ namespace SHADE
|
||||||
RenderUnsavedChangesPrompt();
|
RenderUnsavedChangesPrompt();
|
||||||
//PollPicking();
|
//PollPicking();
|
||||||
|
|
||||||
if(ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
ProcessShortcuts();
|
||||||
{
|
|
||||||
SHCommandManager::RedoCommand();
|
|
||||||
}
|
|
||||||
else if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
|
||||||
{
|
|
||||||
SHCommandManager::UndoCommand();
|
|
||||||
}
|
|
||||||
if(ImGui::IsKeyReleased(ImGuiKey_F5))
|
|
||||||
{
|
|
||||||
Play();
|
|
||||||
}
|
|
||||||
else if (ImGui::IsKeyReleased(ImGuiKey_F6))
|
|
||||||
{
|
|
||||||
Pause();
|
|
||||||
}
|
|
||||||
else if (ImGui::IsKeyReleased(ImGuiKey_F7))
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
Render();
|
Render();
|
||||||
}
|
}
|
||||||
|
@ -376,10 +359,14 @@ namespace SHADE
|
||||||
ImGui_ImplVulkan_Shutdown();
|
ImGui_ImplVulkan_Shutdown();
|
||||||
ImGui_ImplSDL2_Shutdown();
|
ImGui_ImplSDL2_Shutdown();
|
||||||
ImGui::DestroyContext();
|
ImGui::DestroyContext();
|
||||||
|
|
||||||
|
editorConfig->startMaximized = shWindow->GetWindowData().isMaximised;
|
||||||
|
SHConfigurationManager::SaveEditorConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHEditor::SetStyle(Style style)
|
void SHEditor::SetStyle(Style style)
|
||||||
{
|
{
|
||||||
|
editorConfig->style = static_cast<uint32_t>(style);
|
||||||
switch (style)
|
switch (style)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
|
@ -583,6 +570,7 @@ namespace SHADE
|
||||||
|
|
||||||
SHSceneManager::SetCurrentSceneName(newSceneName);
|
SHSceneManager::SetCurrentSceneName(newSceneName);
|
||||||
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
|
SHSceneManager::SetCurrentSceneAssetID(SHAssetManager::CreateNewAsset(AssetType::SCENE, newSceneName));
|
||||||
|
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
|
||||||
}
|
}
|
||||||
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
|
//Get data, if data is null, asset doesn't exist, prompt for a name and create a new asset with the name
|
||||||
|
|
||||||
|
@ -591,7 +579,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
if(shWindow->IsUnsavedChanges())
|
if(shWindow->IsUnsavedChanges())
|
||||||
shWindow->ToggleUnsavedChanges();
|
shWindow->ToggleUnsavedChanges();
|
||||||
|
editorConfig->workingSceneID = SHSceneManager::GetCurrentSceneAssetID();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -659,6 +647,37 @@ namespace SHADE
|
||||||
LoadScene(SHSceneManager::GetCurrentSceneAssetID());
|
LoadScene(SHSceneManager::GetCurrentSceneAssetID());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHEditor::ProcessShortcuts()
|
||||||
|
{
|
||||||
|
if(ImGui::IsKeyDown(ImGuiKey_LeftCtrl))
|
||||||
|
{
|
||||||
|
if(ImGui::IsKeyReleased(ImGuiKey_S))
|
||||||
|
{
|
||||||
|
SaveScene();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyDown(ImGuiKey_LeftShift) && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||||
|
{
|
||||||
|
SHCommandManager::RedoCommand();
|
||||||
|
}
|
||||||
|
else if (ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyReleased(ImGuiKey_Z))
|
||||||
|
{
|
||||||
|
SHCommandManager::UndoCommand();
|
||||||
|
}
|
||||||
|
if (ImGui::IsKeyReleased(ImGuiKey_F5))
|
||||||
|
{
|
||||||
|
Play();
|
||||||
|
}
|
||||||
|
else if (ImGui::IsKeyReleased(ImGuiKey_F6))
|
||||||
|
{
|
||||||
|
Pause();
|
||||||
|
}
|
||||||
|
else if (ImGui::IsKeyReleased(ImGuiKey_F7))
|
||||||
|
{
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SHEditor::NewFrame()
|
void SHEditor::NewFrame()
|
||||||
{
|
{
|
||||||
SDL_Event event;
|
SDL_Event event;
|
||||||
|
@ -672,6 +691,18 @@ namespace SHADE
|
||||||
ImGuizmo::BeginFrame();
|
ImGuizmo::BeginFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHEditor::SetSHWindow(SHWindow* inWindow)
|
||||||
|
{
|
||||||
|
shWindow = inWindow;
|
||||||
|
shWindow->RegisterWindowSizeCallback([&](uint32_t width, uint32_t height)
|
||||||
|
{
|
||||||
|
if(width > 0 && height > 0)
|
||||||
|
{
|
||||||
|
auto [width, height] = shWindow->GetWindowSize();
|
||||||
|
editorConfig->windowSize = { static_cast<float>(width), static_cast<float>(height) };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
void SHEditor::EditorRoutine::Execute(double dt) noexcept
|
void SHEditor::EditorRoutine::Execute(double dt) noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Events/SHEventDefines.h"
|
#include "Events/SHEventDefines.h"
|
||||||
#include "Events/SHEvent.h"
|
#include "Events/SHEvent.h"
|
||||||
#include "Graphics/Windowing/SHWindow.h"
|
#include "Graphics/Windowing/SHWindow.h"
|
||||||
|
#include "Serialization/Configurations/SHConfigurationManager.h"
|
||||||
|
|
||||||
//#==============================================================#
|
//#==============================================================#
|
||||||
//|| Library Includes ||
|
//|| Library Includes ||
|
||||||
|
@ -108,7 +109,7 @@ namespace SHADE
|
||||||
void InitBackend();
|
void InitBackend();
|
||||||
|
|
||||||
void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;};
|
void SetSDLWindow(SDL_Window* inSDLWindow){sdlWindow = inSDLWindow;};
|
||||||
void SetSHWindow(SHWindow* inWindow){shWindow = inWindow;}
|
void SetSHWindow(SHWindow* inWindow);
|
||||||
|
|
||||||
void PollPicking();
|
void PollPicking();
|
||||||
|
|
||||||
|
@ -122,11 +123,15 @@ namespace SHADE
|
||||||
void Pause();
|
void Pause();
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
|
void ProcessShortcuts();
|
||||||
|
|
||||||
// List of selected entities
|
// List of selected entities
|
||||||
std::vector<EntityID> selectedEntities;
|
std::vector<EntityID> selectedEntities;
|
||||||
|
|
||||||
State editorState = State::STOP;
|
State editorState = State::STOP;
|
||||||
|
|
||||||
|
SHEditorConfig* editorConfig;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Start new frame for editor
|
* @brief Start new frame for editor
|
||||||
|
|
|
@ -160,7 +160,7 @@ namespace SHADE
|
||||||
|
|
||||||
template <typename T, std::size_t N>
|
template <typename T, std::size_t N>
|
||||||
static bool DragN(const std::string& label, std::vector<std::string>const& componentLabels,
|
static bool DragN(const std::string& label, std::vector<std::string>const& componentLabels,
|
||||||
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "", T valueMin = T(), T valueMax = T(),
|
std::vector<T*> values, float speed = 0.1f, const char* displayFormat = "%.3f", T valueMin = T(), T valueMax = T(),
|
||||||
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
ImGuiSliderFlags flags = 0, bool* isHovered = nullptr)
|
||||||
{
|
{
|
||||||
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
|
const ImGuiWindow* const window = ImGui::GetCurrentWindow();
|
||||||
|
|
|
@ -23,4 +23,5 @@ constexpr SHEventIdentifier SH_SCENE_INIT_POST { 14 };
|
||||||
constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 };
|
constexpr SHEventIdentifier SH_SCENE_EXIT_PRE { 15 };
|
||||||
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 };
|
constexpr SHEventIdentifier SH_SCENE_EXIT_POST { 16 };
|
||||||
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 };
|
constexpr SHEventIdentifier SH_GRAPHICS_LIGHT_ENABLE_SHADOW_EVENT { 17 };
|
||||||
|
constexpr SHEventIdentifier SH_BUTTON_CLICK_EVENT { 18 };
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,10 @@ namespace SHADE
|
||||||
auto subPass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data())->GetSubpass("Debug Draw");
|
auto subPass = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW.data())->GetSubpass("Debug Draw");
|
||||||
subPass->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
subPass->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
|
// Set line width first
|
||||||
|
cmdBuffer->SetLineWidth(LineWidth);
|
||||||
|
|
||||||
|
// Draw
|
||||||
const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex();
|
const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex();
|
||||||
cmdBuffer->BeginLabeledSegment("SHDebugDraw (No Depth Test)");
|
cmdBuffer->BeginLabeledSegment("SHDebugDraw (No Depth Test)");
|
||||||
{
|
{
|
||||||
|
@ -128,6 +132,10 @@ namespace SHADE
|
||||||
auto subPassWithDepth = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data())->GetSubpass("Debug Draw with Depth");
|
auto subPassWithDepth = renderGraph->GetNode(SHGraphicsConstants::RenderGraphEntityNames::DEBUG_DRAW_DEPTH_PASS.data())->GetSubpass("Debug Draw with Depth");
|
||||||
subPassWithDepth->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
subPassWithDepth->AddExteriorDrawCalls([this](Handle<SHVkCommandBuffer> cmdBuffer, Handle<SHRenderer> renderer, uint32_t frameIndex)
|
||||||
{
|
{
|
||||||
|
// Set line width first
|
||||||
|
cmdBuffer->SetLineWidth(LineWidth);
|
||||||
|
|
||||||
|
// Draw
|
||||||
const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex();
|
const uint32_t FRAME_IDX = gfxSystem->GetCurrentFrameIndex();
|
||||||
cmdBuffer->BeginLabeledSegment("SHDebugDraw (Depth Tested)");
|
cmdBuffer->BeginLabeledSegment("SHDebugDraw (Depth Tested)");
|
||||||
{
|
{
|
||||||
|
@ -207,6 +215,11 @@ namespace SHADE
|
||||||
drawSphere(getMeshBatch(true, depthTested), matrix, color);
|
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 */
|
/* Persistent Draw Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -264,6 +277,12 @@ namespace SHADE
|
||||||
markPersistentDrawsDirty();
|
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()
|
void SHDebugDrawSystem::ClearPersistentDraws()
|
||||||
{
|
{
|
||||||
for (auto& batch : persistentLineBatches)
|
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 */
|
/* Helper Batch Functions - Lines */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -448,7 +514,6 @@ namespace SHADE
|
||||||
if (batch.NumPoints[frameIndex] > 0)
|
if (batch.NumPoints[frameIndex] > 0)
|
||||||
{
|
{
|
||||||
cmdBuffer->BindPipeline(batch.Pipeline);
|
cmdBuffer->BindPipeline(batch.Pipeline);
|
||||||
cmdBuffer->SetLineWidth(LineWidth);
|
|
||||||
cmdBuffer->BindVertexBuffer(0, batch.VertexBuffers[frameIndex], 0);
|
cmdBuffer->BindVertexBuffer(0, batch.VertexBuffers[frameIndex], 0);
|
||||||
cmdBuffer->DrawArrays(batch.NumPoints[frameIndex], 1, 0, 0);
|
cmdBuffer->DrawArrays(batch.NumPoints[frameIndex], 1, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,6 +163,17 @@ namespace SHADE
|
||||||
/// <param name="color">Colour to draw with.</param>
|
/// <param name="color">Colour to draw with.</param>
|
||||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
void DrawSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
void DrawSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the outline of a capsule.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Position of the wireframe capsule.</param>
|
||||||
|
/// <param name="rotation">Rotation of the capsule.</param>
|
||||||
|
/// <param name="height">Height of the overall capsule.</param>
|
||||||
|
/// <param name="radius">Radius of the capsule.</param>
|
||||||
|
/// <param name="color"></param>
|
||||||
|
/// <param name="color">Colour to draw with.</param>
|
||||||
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
|
void DrawWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
/* Persistent Draw Functions */
|
/* Persistent Draw Functions */
|
||||||
|
@ -269,6 +280,17 @@ namespace SHADE
|
||||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
void DrawPersistentSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
void DrawPersistentSphere(const SHMatrix& matrix, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Draws a persistent outline of a capsule.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Position of the wireframe capsule.</param>
|
||||||
|
/// <param name="rotation">Rotation of the capsule.</param>
|
||||||
|
/// <param name="height">Height of the overall capsule.</param>
|
||||||
|
/// <param name="radius">Radius of the capsule.</param>
|
||||||
|
/// <param name="color"></param>
|
||||||
|
/// <param name="color">Colour to draw with.</param>
|
||||||
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
|
void DrawPersistentWireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||||
|
/// <summary>
|
||||||
/// Clears any persistent drawn debug primitives.
|
/// Clears any persistent drawn debug primitives.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ClearPersistentDraws();
|
void ClearPersistentDraws();
|
||||||
|
@ -386,6 +408,7 @@ namespace SHADE
|
||||||
void drawCube(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
|
void drawCube(MeshBatch& batch, const SHMatrix& transformMatrix, const SHColour& color);
|
||||||
void drawSphere(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 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 */
|
/* Helper Batch Functions - Lines */
|
||||||
|
|
|
@ -440,6 +440,7 @@ namespace SHADE
|
||||||
primitiveMeshes[static_cast<int>(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary);
|
primitiveMeshes[static_cast<int>(PrimitiveType::Sphere)] = SHPrimitiveGenerator::Sphere(meshLibrary);
|
||||||
primitiveMeshes[static_cast<int>(PrimitiveType::LineCube)] = SHPrimitiveGenerator::LineCube(meshLibrary);
|
primitiveMeshes[static_cast<int>(PrimitiveType::LineCube)] = SHPrimitiveGenerator::LineCube(meshLibrary);
|
||||||
primitiveMeshes[static_cast<int>(PrimitiveType::LineCircle)] = SHPrimitiveGenerator::LineCircle(meshLibrary);
|
primitiveMeshes[static_cast<int>(PrimitiveType::LineCircle)] = SHPrimitiveGenerator::LineCircle(meshLibrary);
|
||||||
|
primitiveMeshes[static_cast<int>(PrimitiveType::LineCapsuleCap)] = SHPrimitiveGenerator::LineCapsuleCap(meshLibrary);
|
||||||
BuildMeshBuffers();
|
BuildMeshBuffers();
|
||||||
|
|
||||||
// Create default materials
|
// Create default materials
|
||||||
|
@ -895,6 +896,7 @@ namespace SHADE
|
||||||
case PrimitiveType::Sphere:
|
case PrimitiveType::Sphere:
|
||||||
case PrimitiveType::LineCube:
|
case PrimitiveType::LineCube:
|
||||||
case PrimitiveType::LineCircle:
|
case PrimitiveType::LineCircle:
|
||||||
|
case PrimitiveType::LineCapsuleCap:
|
||||||
return primitiveMeshes[static_cast<int>(type)];
|
return primitiveMeshes[static_cast<int>(type)];
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -72,9 +72,10 @@ namespace SHADE
|
||||||
Cube,
|
Cube,
|
||||||
Sphere,
|
Sphere,
|
||||||
LineCube,
|
LineCube,
|
||||||
LineCircle
|
LineCircle,
|
||||||
|
LineCapsuleCap
|
||||||
};
|
};
|
||||||
static constexpr int MAX_PRIMITIVE_TYPES = 4;
|
static constexpr int MAX_PRIMITIVE_TYPES = 5;
|
||||||
enum class DebugDrawPipelineType
|
enum class DebugDrawPipelineType
|
||||||
{
|
{
|
||||||
LineNoDepthTest,
|
LineNoDepthTest,
|
||||||
|
|
|
@ -29,6 +29,7 @@ namespace SHADE
|
||||||
SHMeshData SHPrimitiveGenerator::sphereMesh;
|
SHMeshData SHPrimitiveGenerator::sphereMesh;
|
||||||
SHMeshData SHPrimitiveGenerator::lineCubeMesh;
|
SHMeshData SHPrimitiveGenerator::lineCubeMesh;
|
||||||
SHMeshData SHPrimitiveGenerator::lineCircleMesh;
|
SHMeshData SHPrimitiveGenerator::lineCircleMesh;
|
||||||
|
SHMeshData SHPrimitiveGenerator::lineCapsuleCapMesh;
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Primitive Generation Functions */
|
/* Primitive Generation Functions */
|
||||||
|
@ -392,6 +393,64 @@ namespace SHADE
|
||||||
return addMeshDataTo(lineCircleMesh, gfxSystem);
|
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<float> * 2.0f) / static_cast<float>(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<uint32_t>(i - 1));
|
||||||
|
mesh.Indices.emplace_back(static_cast<uint32_t>(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<uint32_t>(i - 1));
|
||||||
|
mesh.Indices.emplace_back(static_cast<uint32_t>(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
mesh.VertexNormals.resize(mesh.VertexPositions.size());
|
||||||
|
mesh.VertexTangents.resize(mesh.VertexPositions.size());
|
||||||
|
mesh.VertexTexCoords.resize(mesh.VertexPositions.size());
|
||||||
|
|
||||||
|
return mesh;
|
||||||
|
}
|
||||||
|
Handle<SHADE::SHMesh> SHPrimitiveGenerator::LineCapsuleCap(SHMeshLibrary& meshLibrary) noexcept
|
||||||
|
{
|
||||||
|
if (lineCapsuleCapMesh.VertexPositions.empty())
|
||||||
|
lineCapsuleCapMesh = LineCapsuleCap();
|
||||||
|
|
||||||
|
return addMeshDataTo(lineCapsuleCapMesh, meshLibrary);
|
||||||
|
}
|
||||||
|
Handle<SHADE::SHMesh> SHPrimitiveGenerator::LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept
|
||||||
|
{
|
||||||
|
if (lineCapsuleCapMesh.VertexPositions.empty())
|
||||||
|
lineCapsuleCapMesh = LineCapsuleCap();
|
||||||
|
|
||||||
|
return addMeshDataTo(lineCapsuleCapMesh, gfxSystem);
|
||||||
|
}
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Helper Functions */
|
/* Helper Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -194,6 +194,46 @@ namespace SHADE
|
||||||
*/
|
*/
|
||||||
/***********************************************************************************/
|
/***********************************************************************************/
|
||||||
[[nodiscard]] static Handle<SHMesh> LineCircle(SHGraphicsSystem& gfxSystem) noexcept;
|
[[nodiscard]] static Handle<SHMesh> 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<SHMesh> 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<SHMesh> LineCapsuleCap(SHGraphicsSystem& gfxSystem) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
@ -209,5 +249,6 @@ namespace SHADE
|
||||||
static SHMeshData sphereMesh;
|
static SHMeshData sphereMesh;
|
||||||
static SHMeshData lineCubeMesh;
|
static SHMeshData lineCubeMesh;
|
||||||
static SHMeshData lineCircleMesh;
|
static SHMeshData lineCircleMesh;
|
||||||
|
static SHMeshData lineCapsuleCapMesh;
|
||||||
};
|
};
|
||||||
}
|
}
|
|
@ -115,6 +115,11 @@ namespace SHADE
|
||||||
SetFocus(wndHWND);
|
SetFocus(wndHWND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(!wndData.isFullscreen && wndData.isMaximised)
|
||||||
|
{
|
||||||
|
Maximize();
|
||||||
|
}
|
||||||
|
|
||||||
if (!wndData.icoPath.empty())
|
if (!wndData.icoPath.empty())
|
||||||
{
|
{
|
||||||
//HICON hIcon = ::LoadIcon(nullptr, MAKEINTRESOURCE(wndData.icoPath.c_str()));
|
//HICON hIcon = ::LoadIcon(nullptr, MAKEINTRESOURCE(wndData.icoPath.c_str()));
|
||||||
|
@ -208,10 +213,12 @@ namespace SHADE
|
||||||
if (!IsZoomed(wndHWND))
|
if (!IsZoomed(wndHWND))
|
||||||
{
|
{
|
||||||
ShowWindow(wndHWND, SW_MAXIMIZE);
|
ShowWindow(wndHWND, SW_MAXIMIZE);
|
||||||
|
wndData.isMaximised = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ShowWindow(wndHWND, SW_RESTORE);
|
ShowWindow(wndHWND, SW_RESTORE);
|
||||||
|
wndData.isMaximised = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +435,9 @@ namespace SHADE
|
||||||
wndData.isMinimised = true;
|
wndData.isMinimised = true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
wndData.isMinimised = false;
|
wndData.isMinimised = false;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto const& entry : windowResizeCallbacks)
|
for (auto const& entry : windowResizeCallbacks)
|
||||||
{
|
{
|
||||||
|
|
|
@ -64,6 +64,8 @@ namespace SHADE
|
||||||
|
|
||||||
bool isMinimised = false;
|
bool isMinimised = false;
|
||||||
|
|
||||||
|
bool isMaximised = true;
|
||||||
|
|
||||||
std::wstring title = L"SHADE ENGINE";
|
std::wstring title = L"SHADE ENGINE";
|
||||||
|
|
||||||
std::wstring name = L"SHADEEngineApp";
|
std::wstring name = L"SHADEEngineApp";
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <SHpch.h>
|
#include <SHpch.h>
|
||||||
|
#include <fstream>
|
||||||
#include "SHInputManager.h"
|
#include "SHInputManager.h"
|
||||||
#include "../Tools/SHException.h"
|
#include "../Tools/SHException.h"
|
||||||
|
|
||||||
|
@ -99,18 +100,173 @@ 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<int>(lbd.bindingType) << std::endl;
|
||||||
|
file << static_cast<int>(lbd.inverted) << std::endl;
|
||||||
|
file << lbd.gravity << std::endl;
|
||||||
|
file << lbd.dead << std::endl;
|
||||||
|
file << lbd.sensitivity << std::endl;
|
||||||
|
file << static_cast<int>(lbd.snap) << std::endl;
|
||||||
|
|
||||||
|
//Bindings
|
||||||
|
file << lbd.positiveKeyCodes.size() << std::endl;
|
||||||
|
for (auto kc : lbd.positiveKeyCodes)
|
||||||
|
file << static_cast<int>(kc) << std::endl;
|
||||||
|
file << lbd.negativeKeyCodes.size() << std::endl;
|
||||||
|
for (auto kc : lbd.negativeKeyCodes)
|
||||||
|
file << static_cast<int>(kc) << std::endl;
|
||||||
|
file << lbd.positiveControllerCodes.size() << std::endl;
|
||||||
|
for (auto cc : lbd.positiveControllerCodes)
|
||||||
|
file << static_cast<int>(cc) << std::endl;
|
||||||
|
file << lbd.negativeControllerCodes.size() << std::endl;
|
||||||
|
for (auto cc : lbd.negativeControllerCodes)
|
||||||
|
file << static_cast<int>(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<SH_BINDINGTYPE>(std::stoi(read)));
|
||||||
|
|
||||||
|
//Inversion
|
||||||
|
std::getline(file, read);
|
||||||
|
SetBindingInverted(bindingName, static_cast<bool>(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<bool>(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<SH_KEYCODE>(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<SH_KEYCODE>(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<SH_CONTROLLERCODE>(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<SH_CONTROLLERCODE>(std::stoi(read)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
file.close();
|
||||||
|
}
|
||||||
|
|
||||||
void SHInputManager::UpdateInput(double dt) noexcept
|
void SHInputManager::UpdateInput(double dt) noexcept
|
||||||
{
|
{
|
||||||
//Keyboard and Mouse Buttons////////////////////////////////////////////////
|
//Keyboard and Mouse Buttons////////////////////////////////////////////////
|
||||||
//Write to lastKeys
|
//Write to lastKeys
|
||||||
memcpy(keysLast, keys, sizeof(keys));
|
memcpy(keysLast, keys, sizeof(keys));
|
||||||
|
|
||||||
//Poll
|
//Poll KB/M
|
||||||
unsigned char keyboardState[MAX_KEYS] = {};
|
unsigned char keyboardState[MAX_KEYS] = {};
|
||||||
SecureZeroMemory(keyboardState, sizeof(keyboardState));
|
SecureZeroMemory(keyboardState, sizeof(keyboardState));
|
||||||
//if (GetKeyboardState(keyboardState) == false) return;
|
//if (GetKeyboardState(keyboardState) == false) return;
|
||||||
bool keyboardStateGot = GetKeyboardState(keyboardState);
|
bool keyboardStateGot = GetKeyboardState(keyboardState);
|
||||||
SHASSERT(keyboardStateGot, "SHInputManager:GetKeyboardState() failed ({})", GetLastError());
|
SHASSERT(keyboardStateGot, "SHInputManager::GetKeyboardState() failed ({})", GetLastError());
|
||||||
keyCount = 0;
|
keyCount = 0;
|
||||||
keyToggleCount = 0;
|
keyToggleCount = 0;
|
||||||
for (size_t i = 0; i < MAX_KEYS; ++i)
|
for (size_t i = 0; i < MAX_KEYS; ++i)
|
||||||
|
@ -159,7 +315,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Mouse Positioning/////////////////////////////////////
|
//Mouse Positioning/////////////////////////////////////////////////////////
|
||||||
//https://stackoverflow.com/a/6423739
|
//https://stackoverflow.com/a/6423739
|
||||||
|
|
||||||
//Set last positioning
|
//Set last positioning
|
||||||
|
@ -181,7 +337,7 @@ namespace SHADE
|
||||||
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
|
mouseWheelVerticalDelta = mouseWheelVerticalDeltaPoll;
|
||||||
mouseWheelVerticalDeltaPoll = 0;
|
mouseWheelVerticalDeltaPoll = 0;
|
||||||
|
|
||||||
//Controllers//////////////////////////////////////////////////////////////
|
//Controllers///////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
controllersConnectedCount = 0;
|
controllersConnectedCount = 0;
|
||||||
|
|
||||||
|
@ -447,6 +603,200 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Bindings//////////////////////////////////////////////////////////////////
|
||||||
|
for (auto& binding : bindings)
|
||||||
|
{
|
||||||
|
SHLogicalBindingData& data = binding.second;
|
||||||
|
|
||||||
|
//Set last value
|
||||||
|
data.positiveInputHeldLast = data.positiveInputHeld;
|
||||||
|
data.negativeInputHeldLast = data.negativeInputHeld;
|
||||||
|
|
||||||
|
//Reset held values
|
||||||
|
data.positiveInputHeld = false;
|
||||||
|
data.negativeInputHeld = false;
|
||||||
|
|
||||||
|
if (data.bindingType == SHInputManager::SH_BINDINGTYPE::MOUSE_X)
|
||||||
|
{
|
||||||
|
double velX = 0.0;
|
||||||
|
GetMouseVelocity(&velX, nullptr);
|
||||||
|
if (data.value > 0.0) data.positiveInputHeld = true;
|
||||||
|
else if (data.value < 0.0) data.negativeInputHeld = true;
|
||||||
|
data.value = velX * data.sensitivity * (data.inverted ? -1.0 : 1.0);
|
||||||
|
}
|
||||||
|
else if (data.bindingType == SHInputManager::SH_BINDINGTYPE::MOUSE_Y)
|
||||||
|
{
|
||||||
|
double velY = 0.0;
|
||||||
|
GetMouseVelocity(nullptr, &velY);
|
||||||
|
if (data.value > 0.0) data.positiveInputHeld = true;
|
||||||
|
else if (data.value < 0.0) data.negativeInputHeld = true;
|
||||||
|
data.value = velY * data.sensitivity * (data.inverted ? -1.0 : 1.0);
|
||||||
|
}
|
||||||
|
else if (data.bindingType == SHInputManager::SH_BINDINGTYPE::MOUSE_SCROLL)
|
||||||
|
{
|
||||||
|
if (mouseWheelVerticalDelta > 0.0) data.positiveInputHeld = true;
|
||||||
|
else if (mouseWheelVerticalDelta < 0.0) data.negativeInputHeld = true;
|
||||||
|
data.value = mouseWheelVerticalDelta * data.sensitivity * (data.inverted ? -1.0 : 1.0);
|
||||||
|
}
|
||||||
|
else if (data.bindingType == SHInputManager::SH_BINDINGTYPE::KB_MB_CONTROLLER)
|
||||||
|
{
|
||||||
|
//Prioritise the largest magnitude
|
||||||
|
double largestMagnitude = 0.0;
|
||||||
|
|
||||||
|
//If digital input was in, use sensitivity
|
||||||
|
bool digitalInput = false;
|
||||||
|
|
||||||
|
//Over keycodes
|
||||||
|
for (SH_KEYCODE k : data.positiveKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKey(k))
|
||||||
|
{
|
||||||
|
if (std::abs(1.0) > std::abs(largestMagnitude)) largestMagnitude = 1.0 * (data.inverted ? -1.0 : 1.0);
|
||||||
|
digitalInput = true;
|
||||||
|
data.positiveInputHeld = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (SH_KEYCODE k : data.negativeKeyCodes)
|
||||||
|
{
|
||||||
|
if (GetKey(k))
|
||||||
|
{
|
||||||
|
if (std::abs(-1.0) > std::abs(largestMagnitude)) largestMagnitude = -1.0 * (data.inverted ? -1.0 : 1.0);
|
||||||
|
digitalInput = true;
|
||||||
|
data.negativeInputHeld = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Over controllerCodes
|
||||||
|
for (SH_CONTROLLERCODE c : data.positiveControllerCodes)
|
||||||
|
{
|
||||||
|
double newValue = 0.0;
|
||||||
|
GetControllerInput(c, &newValue);
|
||||||
|
if (std::abs(newValue) > std::abs(data.dead))
|
||||||
|
{
|
||||||
|
data.positiveInputHeld = true;
|
||||||
|
if (static_cast<size_t>(c) < NUM_CONTROLLER_BUTTON)
|
||||||
|
{
|
||||||
|
digitalInput = true;
|
||||||
|
}
|
||||||
|
if (std::abs(newValue) > std::abs(largestMagnitude))
|
||||||
|
largestMagnitude = newValue * data.sensitivity * (data.inverted ? -1.0 : 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (SH_CONTROLLERCODE c : data.negativeControllerCodes)
|
||||||
|
{
|
||||||
|
double newValue = 0.0;
|
||||||
|
GetControllerInput(c, &newValue);
|
||||||
|
if (std::abs(newValue) > std::abs(data.dead))
|
||||||
|
{
|
||||||
|
data.negativeInputHeld = true;
|
||||||
|
if (static_cast<size_t>(c) < NUM_CONTROLLER_BUTTON)
|
||||||
|
{
|
||||||
|
digitalInput = true;
|
||||||
|
}
|
||||||
|
if (std::abs(newValue) > std::abs(largestMagnitude))
|
||||||
|
largestMagnitude = -newValue * data.sensitivity * (data.inverted ? -1.0 : 1.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//If both positive and negative inputs read, do not modify value
|
||||||
|
if (data.positiveInputHeld && data.negativeInputHeld)
|
||||||
|
{
|
||||||
|
data.value = data.value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//If no data received, use gravity
|
||||||
|
if (!data.positiveInputHeld && !data.negativeInputHeld)
|
||||||
|
{
|
||||||
|
if (data.value > 0.0)
|
||||||
|
{
|
||||||
|
data.value -= data.gravity * dt;
|
||||||
|
if (data.value < 0.0) data.value = 0.0;
|
||||||
|
}
|
||||||
|
if (data.value < 0.0)
|
||||||
|
{
|
||||||
|
data.value += data.gravity * dt;
|
||||||
|
if (data.value > 0.0) data.value = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else //Either positive OR negative input was read
|
||||||
|
{
|
||||||
|
//If digital input was in,
|
||||||
|
//sensitivity is used as a rate at which the axis value is changed
|
||||||
|
if (digitalInput)
|
||||||
|
{
|
||||||
|
//If the input is opposite the current value, gravity works
|
||||||
|
//with the sensitivity
|
||||||
|
if (data.value > 0.0 && largestMagnitude < 0.0)
|
||||||
|
data.value -= data.gravity * dt;
|
||||||
|
if (data.value < 0.0 && largestMagnitude > 0.0)
|
||||||
|
data.value += data.gravity * dt;
|
||||||
|
|
||||||
|
//Moved by sensitivity
|
||||||
|
data.value += data.sensitivity * largestMagnitude * dt;
|
||||||
|
|
||||||
|
if (data.value > 1.0) data.value = 1.0;
|
||||||
|
else if (data.value < -1.0) data.value = -1.0;
|
||||||
|
}
|
||||||
|
//If analog input was in,
|
||||||
|
//sensitivity is instead used as a multiplier
|
||||||
|
else
|
||||||
|
{
|
||||||
|
data.value = largestMagnitude * data.sensitivity;
|
||||||
|
if (data.value > 1.0) data.value = 1.0;
|
||||||
|
else if (data.value < -1.0) data.value = -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.snap) //Snapping
|
||||||
|
{
|
||||||
|
if (data.value > 0.0 && data.negativeInputHeld)
|
||||||
|
data.value = 0.0;
|
||||||
|
if (data.value < 0.0 && data.positiveInputHeld)
|
||||||
|
data.value = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Binding timings
|
||||||
|
|
||||||
|
//Positivie bindings
|
||||||
|
if (data.positiveInputHeld) //Input is down
|
||||||
|
{
|
||||||
|
if (!data.positiveInputHeldLast) //Input was just pressed
|
||||||
|
{
|
||||||
|
data.positiveHeldTime = 0.0; //Reset timer
|
||||||
|
}
|
||||||
|
data.positiveHeldTime += dt; //Tick up
|
||||||
|
}
|
||||||
|
else //Input is up
|
||||||
|
{
|
||||||
|
if (data.positiveInputHeldLast) //Input was just released
|
||||||
|
{
|
||||||
|
data.positiveReleasedTime = 0.0; //Reset timer
|
||||||
|
}
|
||||||
|
data.positiveReleasedTime += dt; //Tick up
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.negativeInputHeld) //Input is down
|
||||||
|
{
|
||||||
|
if (!data.negativeInputHeldLast) //Input was just pressed
|
||||||
|
{
|
||||||
|
data.negativeHeldTime = 0.0; //Reset timer
|
||||||
|
}
|
||||||
|
data.negativeHeldTime += dt; //Tick up
|
||||||
|
}
|
||||||
|
else //Input is up
|
||||||
|
{
|
||||||
|
if (data.negativeInputHeldLast) //Input was just released
|
||||||
|
{
|
||||||
|
data.negativeReleasedTime = 0.0; //Reset timer
|
||||||
|
}
|
||||||
|
data.negativeReleasedTime += dt; //Tick up
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
|
bool SHInputManager::AnyKeyDown(SH_KEYCODE* firstDetected) noexcept
|
||||||
|
@ -574,40 +924,34 @@ namespace SHADE
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Only get of largest magnitude
|
double SHInputManager::GetBindingAxis(std::string const& bindingName, size_t cNum) noexcept
|
||||||
double SHInputManager::GetBindingAxis(std::string bindingName, size_t cNum) noexcept
|
|
||||||
{
|
{
|
||||||
//Over keycodes, prioritise positive
|
return bindings[bindingName].value;
|
||||||
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
|
|
||||||
{
|
|
||||||
if (GetKey(k)) return 1.0;
|
|
||||||
}
|
|
||||||
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
|
|
||||||
{
|
|
||||||
if (GetKey(k)) return -1.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
double largestMagnitude = 0.0;
|
|
||||||
|
|
||||||
//Over controllerCodes
|
|
||||||
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
|
|
||||||
{
|
|
||||||
double newValue = 0.0;
|
|
||||||
if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum))
|
|
||||||
if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = newValue;
|
|
||||||
}
|
|
||||||
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
|
|
||||||
{
|
|
||||||
double newValue = 0.0;
|
|
||||||
if (GetControllerInput(c, &newValue, nullptr, nullptr, cNum))
|
|
||||||
if (std::abs(newValue) > std::abs(largestMagnitude)) largestMagnitude = -newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
return largestMagnitude;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::GetBindingPositiveButton(std::string bindingName, size_t cNum) noexcept
|
double SHInputManager::GetBindingAxisRaw(std::string const& bindingName, size_t cNum) noexcept
|
||||||
{
|
{
|
||||||
|
//Neutral if both positive and negative held
|
||||||
|
if (bindings[bindingName].positiveInputHeld && bindings[bindingName].negativeInputHeld)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
else if (bindings[bindingName].positiveInputHeld)
|
||||||
|
{
|
||||||
|
return 1.0;
|
||||||
|
}
|
||||||
|
else if (bindings[bindingName].negativeInputHeld)
|
||||||
|
{
|
||||||
|
return -1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//No input means neutral
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SHInputManager::GetBindingPositiveButton(std::string const& bindingName, size_t cNum) noexcept
|
||||||
|
{
|
||||||
|
/*
|
||||||
if (cNum >= XUSER_MAX_COUNT) return false;
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
//Over keycodes
|
//Over keycodes
|
||||||
|
@ -622,11 +966,13 @@ namespace SHADE
|
||||||
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
|
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;*/
|
||||||
|
return bindings[bindingName].positiveInputHeld;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::GetBindingNegativeButton(std::string bindingName, size_t cNum) noexcept
|
bool SHInputManager::GetBindingNegativeButton(std::string const& bindingName, size_t cNum) noexcept
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (cNum >= XUSER_MAX_COUNT) return false;
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
//Over keycodes
|
//Over keycodes
|
||||||
|
@ -641,11 +987,13 @@ namespace SHADE
|
||||||
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
|
if (GetControllerInput(c, nullptr, nullptr, nullptr, cNum)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;*/
|
||||||
|
return bindings[bindingName].negativeInputHeld;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::GetBindingPositiveButtonDown(std::string bindingName, size_t cNum) noexcept
|
bool SHInputManager::GetBindingPositiveButtonDown(std::string const& bindingName, size_t cNum) noexcept
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (cNum >= XUSER_MAX_COUNT) return false;
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
//Over keycodes
|
//Over keycodes
|
||||||
|
@ -660,11 +1008,13 @@ namespace SHADE
|
||||||
if (GetControllerInputDown(c, nullptr, cNum)) return true;
|
if (GetControllerInputDown(c, nullptr, cNum)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;*/
|
||||||
|
return (bindings[bindingName].positiveInputHeld && !bindings[bindingName].positiveInputHeldLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::GetBindingNegativeButtonDown(std::string bindingName, size_t cNum) noexcept
|
bool SHInputManager::GetBindingNegativeButtonDown(std::string const& bindingName, size_t cNum) noexcept
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (cNum >= XUSER_MAX_COUNT) return false;
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
//Over keycodes
|
//Over keycodes
|
||||||
|
@ -679,11 +1029,13 @@ namespace SHADE
|
||||||
if (GetControllerInputDown(c, nullptr, cNum)) return true;
|
if (GetControllerInputDown(c, nullptr, cNum)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;*/
|
||||||
|
return (bindings[bindingName].negativeInputHeld && !bindings[bindingName].negativeInputHeldLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::GetBindingPositiveButtonUp(std::string bindingName, size_t cNum) noexcept
|
bool SHInputManager::GetBindingPositiveButtonUp(std::string const& bindingName, size_t cNum) noexcept
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (cNum >= XUSER_MAX_COUNT) return false;
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
//Over keycodes
|
//Over keycodes
|
||||||
|
@ -698,11 +1050,13 @@ namespace SHADE
|
||||||
if (GetControllerInputUp(c, nullptr, cNum)) return true;
|
if (GetControllerInputUp(c, nullptr, cNum)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;*/
|
||||||
|
return (!bindings[bindingName].positiveInputHeld && bindings[bindingName].positiveInputHeldLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SHInputManager::GetBindingNegativeButtonUp(std::string bindingName, size_t cNum) noexcept
|
bool SHInputManager::GetBindingNegativeButtonUp(std::string const& bindingName, size_t cNum) noexcept
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
if (cNum >= XUSER_MAX_COUNT) return false;
|
if (cNum >= XUSER_MAX_COUNT) return false;
|
||||||
|
|
||||||
//Over keycodes
|
//Over keycodes
|
||||||
|
@ -717,107 +1071,7 @@ namespace SHADE
|
||||||
if (GetControllerInputUp(c, nullptr, cNum)) return true;
|
if (GetControllerInputUp(c, nullptr, cNum)) return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;*/
|
||||||
|
return (!bindings[bindingName].positiveInputHeld && bindings[bindingName].positiveInputHeldLast);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Fetches longest hold time
|
|
||||||
double SHInputManager::GetBindingPositiveHeldTime(std::string bindingName, size_t cNum) noexcept
|
|
||||||
{
|
|
||||||
if (cNum >= XUSER_MAX_COUNT) return 0.0;
|
|
||||||
|
|
||||||
double maxHeldTime = 0.0;
|
|
||||||
|
|
||||||
//Over keycodes
|
|
||||||
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
|
|
||||||
{
|
|
||||||
if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Over controller buttons
|
|
||||||
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
|
|
||||||
{
|
|
||||||
if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxHeldTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
double SHInputManager::GetBindingNegativeHeldTime(std::string bindingName, size_t cNum) noexcept
|
|
||||||
{
|
|
||||||
if (cNum >= XUSER_MAX_COUNT) return 0.0;
|
|
||||||
|
|
||||||
double maxHeldTime = 0.0;
|
|
||||||
|
|
||||||
//Over keycodes
|
|
||||||
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
|
|
||||||
{
|
|
||||||
if (GetKeyHeldTime(k) > maxHeldTime) maxHeldTime = GetKeyHeldTime(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Over controller buttons
|
|
||||||
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
|
|
||||||
{
|
|
||||||
if (GetControllerInputHeldTime(c, cNum) > maxHeldTime) maxHeldTime = GetControllerInputHeldTime(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return maxHeldTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Fetches shortest release time
|
|
||||||
double SHInputManager::GetBindingPositiveReleasedTime(std::string bindingName, size_t cNum) noexcept
|
|
||||||
{
|
|
||||||
if (cNum >= XUSER_MAX_COUNT) return 0.0;
|
|
||||||
|
|
||||||
double minReleaseTime = _HUGE_ENUF;
|
|
||||||
|
|
||||||
//Over keycodes
|
|
||||||
for (SH_KEYCODE k : bindings[bindingName].positiveKeyCodes)
|
|
||||||
{
|
|
||||||
if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Over controller buttons
|
|
||||||
for (SH_CONTROLLERCODE c : bindings[bindingName].positiveControllerCodes)
|
|
||||||
{
|
|
||||||
if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return minReleaseTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
double SHInputManager::GetBindingNegativeReleasedTime(std::string bindingName, size_t cNum) noexcept
|
|
||||||
{
|
|
||||||
if (cNum >= XUSER_MAX_COUNT) return 0.0;
|
|
||||||
|
|
||||||
double minReleaseTime = _HUGE_ENUF;
|
|
||||||
|
|
||||||
//Over keycodes
|
|
||||||
for (SH_KEYCODE k : bindings[bindingName].negativeKeyCodes)
|
|
||||||
{
|
|
||||||
if (GetKeyReleasedTime(k) < minReleaseTime) minReleaseTime = GetKeyReleasedTime(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Over controller buttons
|
|
||||||
for (SH_CONTROLLERCODE c : bindings[bindingName].negativeControllerCodes)
|
|
||||||
{
|
|
||||||
if (GetControllerInputReleasedTime(c, cNum) < minReleaseTime) minReleaseTime = GetControllerInputReleasedTime(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
return minReleaseTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Only for mouse movement
|
|
||||||
//Get largest delta
|
|
||||||
double SHInputManager::GetBindingMouseVelocity(std::string bindingName, size_t cNum) noexcept
|
|
||||||
{
|
|
||||||
if (cNum >= XUSER_MAX_COUNT) return 0.0;
|
|
||||||
|
|
||||||
//Mouse velocity
|
|
||||||
double velX = 0.0;
|
|
||||||
double velY = 0.0;
|
|
||||||
GetMouseVelocity(&velX, &velY);
|
|
||||||
|
|
||||||
return bindings[bindingName].mouseXPositiveMultiplier * velX + bindings[bindingName].mouseYPositiveMultiplier * velY;
|
|
||||||
}
|
|
||||||
|
|
||||||
} //namespace SHADE
|
} //namespace SHADE
|
|
@ -14,6 +14,7 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include "../../SHADE_Managed/src/SHpch.h"
|
#include "../../SHADE_Managed/src/SHpch.h"
|
||||||
|
#include "../../SHADE_Engine/src/Assets/SHAssetMacros.h"
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#pragma comment(lib, "xinput.lib")
|
#pragma comment(lib, "xinput.lib")
|
||||||
|
|
||||||
|
@ -300,12 +301,28 @@ namespace SHADE
|
||||||
RIGHT_THUMBSTICK_Y
|
RIGHT_THUMBSTICK_Y
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//BINDING TYPES///////////////////////////////////////////////////////////
|
||||||
|
enum class SH_BINDINGTYPE
|
||||||
|
{
|
||||||
|
KB_MB_CONTROLLER,
|
||||||
|
MOUSE_X,
|
||||||
|
MOUSE_Y,
|
||||||
|
MOUSE_SCROLL
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Struct for logical bindings */
|
/* Struct for logical bindings */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
struct SH_API SHLogicalBindingData
|
struct SH_API SHLogicalBindingData
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
//BINDINGS////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//The type of the binding
|
||||||
|
SH_BINDINGTYPE bindingType = SH_BINDINGTYPE::KB_MB_CONTROLLER;
|
||||||
|
|
||||||
//Key codes mapped to positive
|
//Key codes mapped to positive
|
||||||
std::set<SH_KEYCODE> positiveKeyCodes;
|
std::set<SH_KEYCODE> positiveKeyCodes;
|
||||||
|
|
||||||
|
@ -318,9 +335,51 @@ namespace SHADE
|
||||||
//Controller Codes mapped to negative
|
//Controller Codes mapped to negative
|
||||||
std::set<SH_CONTROLLERCODE> negativeControllerCodes;
|
std::set<SH_CONTROLLERCODE> negativeControllerCodes;
|
||||||
|
|
||||||
//Mouse movement mapped to axes?
|
//VALUES//////////////////////////////////////////////////////////////////
|
||||||
double mouseXPositiveMultiplier;
|
|
||||||
double mouseYPositiveMultiplier;
|
//The current value of the axis binding
|
||||||
|
double value = 0.0;
|
||||||
|
|
||||||
|
bool positiveInputHeld = false;
|
||||||
|
bool negativeInputHeld = false;
|
||||||
|
|
||||||
|
bool positiveInputHeldLast = false;
|
||||||
|
bool negativeInputHeldLast = false;
|
||||||
|
|
||||||
|
//Whether the input is inverted,
|
||||||
|
//If so, positive bindings will make the value negative,
|
||||||
|
// negative bindings will make the value positive,
|
||||||
|
// moving the mouse up will make the value negative,
|
||||||
|
// scrolling the mousewheel up will make the value negative,
|
||||||
|
bool inverted = false;
|
||||||
|
|
||||||
|
//When no input is present, how fast does the value fall back to neutral?
|
||||||
|
//Best to be non-negative
|
||||||
|
double gravity = 1.0;
|
||||||
|
|
||||||
|
//How far the user needs to move an analog stick before application
|
||||||
|
//registers the movement
|
||||||
|
double dead = 0.2;
|
||||||
|
|
||||||
|
//Speed in units per second that the axis will move toward target value for digital
|
||||||
|
//For mouse movement / scrolling, serves as multiplier
|
||||||
|
double sensitivity = 1.0;
|
||||||
|
|
||||||
|
//If enabled, axis value will reset to zero when pressing a button
|
||||||
|
//that corresponds in the opposite direction
|
||||||
|
bool snap = false;
|
||||||
|
|
||||||
|
//How long the positive binding has been held for
|
||||||
|
double positiveHeldTime = 0.0;
|
||||||
|
|
||||||
|
//How long the positive binding has been released for
|
||||||
|
double positiveReleasedTime = 0.0;
|
||||||
|
|
||||||
|
//How long the negative binding has been held for
|
||||||
|
double negativeHeldTime = 0.0;
|
||||||
|
|
||||||
|
//How long the negative binding has been released for
|
||||||
|
double negativeReleasedTime = 0.0;
|
||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -350,6 +409,12 @@ namespace SHADE
|
||||||
mouseWheelVerticalDeltaPoll += GET_WHEEL_DELTA_WPARAM(wParam);
|
mouseWheelVerticalDeltaPoll += GET_WHEEL_DELTA_WPARAM(wParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Get if controller or KB/M is presently being used
|
||||||
|
static inline bool GetControllerInUse() noexcept
|
||||||
|
{
|
||||||
|
return controllerInUse;
|
||||||
|
}
|
||||||
|
|
||||||
//For testing purposes
|
//For testing purposes
|
||||||
//static void PrintCurrentState() noexcept;
|
//static void PrintCurrentState() noexcept;
|
||||||
|
|
||||||
|
@ -484,7 +549,7 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Input state accessors (KB & M) */
|
/* Input state accessors (Controller) */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
//How many controller inputs of any kind are being used now
|
//How many controller inputs of any kind are being used now
|
||||||
|
@ -617,172 +682,362 @@ namespace SHADE
|
||||||
return controllersReleasedTime[controllerNum][static_cast<size_t>(code)];
|
return controllersReleasedTime[controllerNum][static_cast<size_t>(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 */
|
/* Binding Functions */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
//Add a new binding to the map
|
//Get a read-only map of the bindings
|
||||||
static inline void BindingsAdd(std::string newBindingName) noexcept
|
static inline std::map<std::string, SHLogicalBindingData> const& GetBindings() noexcept
|
||||||
{
|
{
|
||||||
bindings.insert({ newBindingName, SHLogicalBindingData() });
|
return bindings;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove a binding from the map
|
//Add a new binding to the map with settings
|
||||||
//Returns 1 if found and removed, 0 if not found
|
//Binding type is between four different types,
|
||||||
static inline size_t BindingsRemove(std::string targetBindingName) noexcept
|
//KB_MB_CONTROLLER Binding is connected to the keyboard, mouse and controller buttons and its analog inputs
|
||||||
|
//MOUSE_X Binding is connected to horizontal movement of the mouse
|
||||||
|
//MOUSE_Y Binding is connected to the vertical movement of the mouse
|
||||||
|
//MOUSE_SCROLL Binding is connected to the scrolling of the mouse wheel
|
||||||
|
//Inverted is whether positive inputs result in a negative value and vice-versa
|
||||||
|
//Snap is if inputting in the opposite direction results in the value snapping to 0 before continuing in the direction
|
||||||
|
//Sensitivity is how fast the value moves with input
|
||||||
|
//Dead is how much analogue input magnitude on a scale of 0 to 1 is required before being registered
|
||||||
|
//Gravity is how fast the value moves to neutral without input
|
||||||
|
static inline void AddBinding(std::string const& newBindingName,
|
||||||
|
SH_BINDINGTYPE const bindingType = SH_BINDINGTYPE::KB_MB_CONTROLLER,
|
||||||
|
bool const inverted = false,
|
||||||
|
bool const snap = false,
|
||||||
|
double const sensitivity = 1.0,
|
||||||
|
double const dead = 0.2,
|
||||||
|
double const gravity = 1.0) noexcept
|
||||||
{
|
{
|
||||||
return bindings.erase(targetBindingName);
|
bindings.insert({ newBindingName, SHLogicalBindingData() });
|
||||||
|
bindings[newBindingName].bindingType = bindingType;
|
||||||
|
bindings[newBindingName].inverted = inverted;
|
||||||
|
bindings[newBindingName].snap = snap;
|
||||||
|
bindings[newBindingName].sensitivity = sensitivity;
|
||||||
|
bindings[newBindingName].dead = dead;
|
||||||
|
bindings[newBindingName].gravity = gravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Remove a binding and all its associated inputs from the list
|
||||||
|
//Returns 1 if found and removed, 0 if not found
|
||||||
|
static inline size_t RemoveBinding(std::string const& bindingName) noexcept
|
||||||
|
{
|
||||||
|
return bindings.erase(bindingName);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clears all bindings from the list
|
//Clears all bindings from the list
|
||||||
static inline void BindingsClear() noexcept
|
static inline void ClearBindings() noexcept
|
||||||
{
|
{
|
||||||
bindings.clear();
|
bindings.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Get the number of bindings present
|
//Get the number of bindings present
|
||||||
static inline size_t BindingsCount() noexcept
|
static inline size_t CountBindings() noexcept
|
||||||
{
|
{
|
||||||
return bindings.size();
|
return bindings.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//BINDING VALUES////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//Get whether the binding is inverted or not
|
||||||
|
//If inverted, positive inputs subtract the value of the binding
|
||||||
|
// negative inputs add to the value of the binding
|
||||||
|
// Moving mouse up / right will be negative
|
||||||
|
// Scrolling the mouse wheel up will be negative
|
||||||
|
static inline bool GetBindingInverted(std::string const& bindingName)
|
||||||
|
{
|
||||||
|
return bindings[bindingName].inverted;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set whether the binding is inverted or not
|
||||||
|
//If inverted, positive inputs subtract the value of the binding
|
||||||
|
// negative inputs add to the value of the binding
|
||||||
|
// Moving mouse up / right will be negative
|
||||||
|
// Scrolling the mouse wheel up will be negative
|
||||||
|
static inline void SetBindingInverted(std::string const& bindingName, bool const newValue)
|
||||||
|
{
|
||||||
|
bindings[bindingName].inverted = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Gets the gravity of the binding
|
||||||
|
//The rate at which the value moves to neutral if no input in the direction is read
|
||||||
|
//Should be non-negative
|
||||||
|
//Irrelevant for mouse movement and scrolling
|
||||||
|
static inline double GetBindingGravity(std::string const& bindingName)
|
||||||
|
{
|
||||||
|
return bindings[bindingName].gravity;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sets the gravity of the binding
|
||||||
|
//The rate at which the value moves to neutral if no input in the direction is read
|
||||||
|
//Should be non-negative
|
||||||
|
//Irrelevant for mouse movement and scrolling
|
||||||
|
static inline void SetBindingGravity(std::string const& bindingName, double const newValue)
|
||||||
|
{
|
||||||
|
bindings[bindingName].gravity = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the dead zone of the binding on a scale of 0 to 1,
|
||||||
|
//Any positive or negative analog input with magnitude less than this will be registered as neutral
|
||||||
|
//Irrelvant for digital inputs, mouse movement and scrolling
|
||||||
|
static inline double GetBindingDead(std::string const& bindingName)
|
||||||
|
{
|
||||||
|
return bindings[bindingName].dead;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the dead zone of the binding on a scale of 0 to 1,
|
||||||
|
//Any positive or negative analog input with magnitude less than this will be registered as neutral
|
||||||
|
//Irrelvant for digital inputs, mouse movement and scrolling
|
||||||
|
static inline void SetBindingDead(std::string const& bindingName, double const newValue)
|
||||||
|
{
|
||||||
|
bindings[bindingName].dead = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get the sensitivity of the binding
|
||||||
|
//Serves as a multiplier for mouse movement/scrolling
|
||||||
|
//For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative
|
||||||
|
//For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1
|
||||||
|
static inline double GetBindingSensitivity(std::string const& bindingName)
|
||||||
|
{
|
||||||
|
return bindings[bindingName].sensitivity;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the sensitivity of the binding
|
||||||
|
//Serves as a multiplier for mouse movement/scrolling
|
||||||
|
//For other digital inputs, serves as a rate of how fast axis value goes to maximum positive/negative
|
||||||
|
//For other analog inputs, serves as a multiplier, but axis value magnitude will still be capped at 1
|
||||||
|
static inline void SetBindingSensitivity(std::string const& bindingName, double const newValue)
|
||||||
|
{
|
||||||
|
bindings[bindingName].sensitivity = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Gets the snap of the binding
|
||||||
|
//If no other input on the axis is present and a input is made in the opposite direction of the current value,
|
||||||
|
//the binding's value will jump to neutral 0 before resuming in the input direction
|
||||||
|
//Irrelevant for mouse movement and scrolling
|
||||||
|
static inline bool GetBindingSnap(std::string const& bindingName)
|
||||||
|
{
|
||||||
|
return bindings[bindingName].snap;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Sets the snap of the binding
|
||||||
|
//If no other input on the axis is present and a input is made in the opposite direction of the current value,
|
||||||
|
//the binding's value will jump to neutral 0 before resuming in the input direction
|
||||||
|
//Irrelevant for mouse movement and scrolling
|
||||||
|
static inline void SetBindingSnap(std::string const& bindingName, bool const newValue)
|
||||||
|
{
|
||||||
|
bindings[bindingName].snap = newValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//BINDING TYPE//////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
//Get the type of the binding
|
||||||
|
//There are four types:
|
||||||
|
//KB_MB_CONTROLLER Binding is connected to the keyboard, mouse and controller buttons and its analog inputs
|
||||||
|
//MOUSE_X Binding is connected to horizontal movement of the mouse
|
||||||
|
//MOUSE_Y Binding is connected to the vertical movement of the mouse
|
||||||
|
//MOUSE_SCROLL Binding is connected to the scrolling of the mouse wheel
|
||||||
|
static inline SH_BINDINGTYPE GetBindingType(std::string const& bindingName)
|
||||||
|
{
|
||||||
|
return bindings[bindingName].bindingType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Set the type of the binding
|
||||||
|
//There are four types:
|
||||||
|
//KB_MB_CONTROLLER Binding is connected to the keyboard, mouse and controller buttons and its analog inputs
|
||||||
|
//MOUSE_X Binding is connected to horizontal movement of the mouse
|
||||||
|
//MOUSE_Y Binding is connected to the vertical movement of the mouse
|
||||||
|
//MOUSE_SCROLL Binding is connected to the scrolling of the mouse wheel
|
||||||
|
static inline void SetBindingType(std::string const& bindingName, SH_BINDINGTYPE const newType)
|
||||||
|
{
|
||||||
|
bindings[bindingName].bindingType = newType;
|
||||||
|
}
|
||||||
|
|
||||||
|
//POSITIVE KEYCODES/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//Check positive keycodes to binding
|
//Check positive keycodes to binding
|
||||||
static inline std::set<SH_KEYCODE> const& BindingsGetPositiveKeyCodes(std::string bindingName) noexcept
|
static inline std::set<SH_KEYCODE> const& GetBindingPositiveKeyCodes(std::string const& bindingName) noexcept
|
||||||
{
|
{
|
||||||
return bindings[bindingName].positiveKeyCodes;
|
return bindings[bindingName].positiveKeyCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add positive SH_KEYCODE to binding
|
//Add positive SH_KEYCODE to binding
|
||||||
static inline void BindingsAddPositiveKeyCode(std::string targetBindingName,
|
static inline void AddBindingPositiveKeyCode(std::string const& bindingName,
|
||||||
SH_KEYCODE toAdd) noexcept
|
SH_KEYCODE toAdd) noexcept
|
||||||
{
|
{
|
||||||
bindings[targetBindingName].positiveKeyCodes.insert(toAdd);
|
bindings[bindingName].positiveKeyCodes.insert(toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove positive SH_KEYCODE from binding
|
//Remove positive SH_KEYCODE from binding
|
||||||
//If toRemove found and removed, returns 1. Otherwise, 0.
|
//If toRemove found and removed, returns 1. Otherwise, 0.
|
||||||
static inline size_t BindingsRemovePositiveKeyCode(std::string targetBindingName,
|
static inline size_t RemoveBindingPositiveKeyCode(std::string const& bindingName,
|
||||||
SH_KEYCODE toRemove) noexcept
|
SH_KEYCODE toRemove) noexcept
|
||||||
{
|
{
|
||||||
return bindings[targetBindingName].positiveKeyCodes.erase(toRemove);
|
return bindings[bindingName].positiveKeyCodes.erase(toRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Clear all positive SH_KEYCODEs from binding
|
||||||
|
static inline void ClearBindingPositiveKeyCodes(std::string const& bindingName) noexcept
|
||||||
|
{
|
||||||
|
bindings[bindingName].positiveKeyCodes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//NEGATIVE KEYCODES/////////////////////////////////////////////////////////
|
||||||
|
|
||||||
//Check negative keycodes to binding
|
//Check negative keycodes to binding
|
||||||
static inline std::set<SH_KEYCODE> const& BindingsGetNegativeKeyCodes(std::string bindingName) noexcept
|
static inline std::set<SH_KEYCODE> const& GetBindingNegativeKeyCodes(std::string const& bindingName) noexcept
|
||||||
{
|
{
|
||||||
return bindings[bindingName].negativeKeyCodes;
|
return bindings[bindingName].negativeKeyCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add negative SH_KEYCODE to binding
|
//Add negative SH_KEYCODE to binding
|
||||||
static inline void BindingsAddNegativeKeyCode(std::string targetBindingName,
|
static inline void AddBindingNegativeKeyCode(std::string const& bindingName,
|
||||||
SH_KEYCODE toAdd) noexcept
|
SH_KEYCODE toAdd) noexcept
|
||||||
{
|
{
|
||||||
bindings[targetBindingName].negativeKeyCodes.insert(toAdd);
|
bindings[bindingName].negativeKeyCodes.insert(toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove negative SH_KEYCODE from binding
|
//Remove negative SH_KEYCODE from binding
|
||||||
//If toRemove found and removed, returns 1. Otherwise, 0.
|
//If toRemove found and removed, returns 1. Otherwise, 0.
|
||||||
static inline size_t BindingsRemoveNegativeKeyCode(std::string targetBindingName,
|
static inline size_t RemoveBindingNegativeKeyCode(std::string const& bindingName,
|
||||||
SH_KEYCODE toRemove) noexcept
|
SH_KEYCODE toRemove) noexcept
|
||||||
{
|
{
|
||||||
return bindings[targetBindingName].negativeKeyCodes.erase(toRemove);
|
return bindings[bindingName].negativeKeyCodes.erase(toRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Clear all negative SH_KEYCODEs from binding
|
||||||
|
static inline void ClearBindingNegativeKeyCodes(std::string const& bindingName) noexcept
|
||||||
|
{
|
||||||
|
bindings[bindingName].negativeKeyCodes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//POSITIVE CONTROLLERCODES//////////////////////////////////////////////////
|
||||||
|
|
||||||
//Check positive controllercodes to binding
|
//Check positive controllercodes to binding
|
||||||
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetPositiveControllerCodes(std::string bindingName) noexcept
|
static inline std::set<SH_CONTROLLERCODE> const& GetBindingPositiveControllerCodes(std::string const& bindingName) noexcept
|
||||||
{
|
{
|
||||||
return bindings[bindingName].positiveControllerCodes;
|
return bindings[bindingName].positiveControllerCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add positive SH_CONTROLLERCODE to binding
|
//Add positive SH_CONTROLLERCODE to binding
|
||||||
static inline void BindingsAddPositiveControllerCode(std::string targetBindingName,
|
static inline void AddBindingPositiveControllerCode(std::string const& bindingName,
|
||||||
SH_CONTROLLERCODE toAdd) noexcept
|
SH_CONTROLLERCODE toAdd) noexcept
|
||||||
{
|
{
|
||||||
bindings[targetBindingName].positiveControllerCodes.insert(toAdd);
|
bindings[bindingName].positiveControllerCodes.insert(toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove positive SH_CONTROLLERCODE from binding
|
//Remove positive SH_CONTROLLERCODE from binding
|
||||||
//If toRemove found and removed, returns 1. Otherwise, 0.
|
//If toRemove found and removed, returns 1. Otherwise, 0.
|
||||||
static inline size_t BindingsRemovePositiveControllerCode(std::string targetBindingName,
|
static inline size_t RemoveBindingPositiveControllerCode(std::string const& bindingName,
|
||||||
SH_CONTROLLERCODE toRemove) noexcept
|
SH_CONTROLLERCODE toRemove) noexcept
|
||||||
{
|
{
|
||||||
return bindings[targetBindingName].positiveControllerCodes.erase(toRemove);
|
return bindings[bindingName].positiveControllerCodes.erase(toRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Clear all positive SH_CONTROLLERCODEs from binding
|
||||||
|
static inline void ClearBindingPositiveControllerCodes(std::string const& bindingName) noexcept
|
||||||
|
{
|
||||||
|
bindings[bindingName].positiveControllerCodes.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
//NEGATIVE CONTROLLERCODES//////////////////////////////////////////////////
|
||||||
|
|
||||||
//Check negative controllercodes to binding
|
//Check negative controllercodes to binding
|
||||||
static inline std::set<SH_CONTROLLERCODE> const& BindingsGetNegativeControllerCodes(std::string bindingName) noexcept
|
static inline std::set<SH_CONTROLLERCODE> const& GetBindingNegativeControllerCodes(std::string const& bindingName) noexcept
|
||||||
{
|
{
|
||||||
return bindings[bindingName].negativeControllerCodes;
|
return bindings[bindingName].negativeControllerCodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Add negative SH_CONTROLLERCODE to binding
|
//Add negative SH_CONTROLLERCODE to binding
|
||||||
static inline void BindingsAddNegativeControllerCode(std::string targetBindingName,
|
static inline void AddBindingNegativeControllerCode(std::string const& bindingName,
|
||||||
SH_CONTROLLERCODE toAdd) noexcept
|
SH_CONTROLLERCODE toAdd) noexcept
|
||||||
{
|
{
|
||||||
bindings[targetBindingName].negativeControllerCodes.insert(toAdd);
|
bindings[bindingName].negativeControllerCodes.insert(toAdd);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Remove negative SH_CONTROLLERCODE from binding
|
//Remove negative SH_CONTROLLERCODE from binding
|
||||||
//If toRemove found and removed, returns 1. Otherwise, 0.
|
//If toRemove found and removed, returns 1. Otherwise, 0.
|
||||||
static inline size_t BindingsRemoveNegativeControllerCode(std::string targetBindingName,
|
static inline size_t RemoveBindingNegativeControllerCode(std::string const& bindingName,
|
||||||
SH_CONTROLLERCODE toRemove) noexcept
|
SH_CONTROLLERCODE toRemove) noexcept
|
||||||
{
|
{
|
||||||
return bindings[targetBindingName].negativeControllerCodes.erase(toRemove);
|
return bindings[bindingName].negativeControllerCodes.erase(toRemove);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Mouse movement bindings
|
//Clear all negative SH_CONTROLLERCODEs from binding
|
||||||
|
static inline void ClearBindingNegativeControllerCodes(std::string const& bindingName) noexcept
|
||||||
static inline double const BindingsGetMouseXPositiveMultiplier(std::string bindingName) noexcept
|
|
||||||
{
|
{
|
||||||
return bindings[bindingName].mouseXPositiveMultiplier;
|
bindings[bindingName].negativeControllerCodes.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void BindingsSetMouseXPositiveMultiplier(std::string bindingName, double newValue) noexcept
|
//Get the axis value of binding, between -1 and 1 for non-mouse movement/wheel
|
||||||
{
|
//For mouse movement/wheel, it won't be between -1 and 1. It will also be multiplied by sensitivity
|
||||||
bindings[bindingName].mouseXPositiveMultiplier = newValue;
|
//To avoid interference between mouse movement/wheel and keyboard/mouse/controller input,
|
||||||
}
|
//Set mouseXBound, mouseYBound and mouseScrollBound to false
|
||||||
|
//controllerNumber is not used
|
||||||
|
static double GetBindingAxis(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
|
|
||||||
static inline double const BindingsGetMouseYPositiveMultiplier(std::string bindingName) noexcept
|
//Get the axis value of binding, which will be fixed among -1, 0 and 1 for non-mouse movement/wheel
|
||||||
{
|
//No difference between this and GetBindingAxis for mouse movement/wheel
|
||||||
return bindings[bindingName].mouseXPositiveMultiplier;
|
//But for other inputs, does not consider smoothing options such as gravity and sensitivity
|
||||||
}
|
//If both positive and negative input is detected, returns neutral 0
|
||||||
|
//controllerNumber is not used
|
||||||
static inline void BindingsSetMouseYPositiveMultiplier(std::string bindingName, double newValue) noexcept
|
static double GetBindingAxisRaw(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
{
|
|
||||||
bindings[bindingName].mouseXPositiveMultiplier = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Get the axis value of binding, between -1 and 1
|
|
||||||
static double GetBindingAxis(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
|
||||||
|
|
||||||
//Whether binding is being held or not
|
//Whether binding is being held or not
|
||||||
//Does not work for mouse movement
|
//Does not work for mouse movement or wheel
|
||||||
static bool GetBindingPositiveButton(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static bool GetBindingPositiveButton(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
static bool GetBindingNegativeButton(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static bool GetBindingNegativeButton(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
|
|
||||||
//Whether binding is pressed down IN THIS FRAME ONLY
|
//Whether binding is pressed down IN THIS FRAME ONLY
|
||||||
//Does not work for mouse movement
|
//Does not work for mouse movement or wheel
|
||||||
static bool GetBindingPositiveButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static bool GetBindingPositiveButtonDown(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
static bool GetBindingNegativeButtonDown(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static bool GetBindingNegativeButtonDown(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
|
|
||||||
//Whether binding is released IN THIS FRAME ONLY
|
//Whether binding is released IN THIS FRAME ONLY
|
||||||
//Does not work for mouse movement
|
//Does not work for mouse movement or wheel
|
||||||
static bool GetBindingPositiveButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static bool GetBindingPositiveButtonUp(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
static bool GetBindingNegativeButtonUp(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static bool GetBindingNegativeButtonUp(std::string const& bindingName, size_t controllerNumber = 0) noexcept;
|
||||||
|
|
||||||
//Binding times
|
//Binding times
|
||||||
|
|
||||||
//Does not work for mouse movement
|
//Gets how long the binding has been considered positive
|
||||||
static double GetBindingPositiveHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
//Does not work for mouse movement or wheel
|
||||||
static double GetBindingNegativeHeldTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static inline double GetBindingPositiveHeldTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].positiveHeldTime;
|
||||||
|
}
|
||||||
|
//Gets how long the binding has been considered negative
|
||||||
|
//Does not work for mouse movement or wheel
|
||||||
|
static inline double GetBindingNegativeHeldTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].negativeHeldTime;
|
||||||
|
}
|
||||||
|
|
||||||
//Does not work for mouse movement
|
//Gets how long the binding has been not considered positive
|
||||||
static double GetBindingPositiveReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
//Does not work for mouse movement or wheel
|
||||||
static double GetBindingNegativeReleasedTime(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
static inline double GetBindingPositiveReleasedTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept
|
||||||
|
{
|
||||||
//Binding mouse velocity
|
return bindings[bindingName].positiveReleasedTime;
|
||||||
//Only for mouse movement
|
}
|
||||||
static double GetBindingMouseVelocity(std::string bindingName, size_t controllerNumber = 0) noexcept;
|
//Gets how long the binding has been not considered negative
|
||||||
|
//Does not work for mouse movement or wheel
|
||||||
|
static inline double GetBindingNegativeReleasedTime(std::string const& bindingName, size_t controllerNumber = 0) noexcept
|
||||||
|
{
|
||||||
|
return bindings[bindingName].negativeReleasedTime;
|
||||||
|
}
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Other Functions */
|
/* Other Functions */
|
||||||
|
|
|
@ -35,7 +35,17 @@ namespace SHADE
|
||||||
: position { pos }
|
: position { pos }
|
||||||
, orientation { SHQuaternion::FromEuler(rot) }
|
, orientation { SHQuaternion::FromEuler(rot) }
|
||||||
, scale { scl }
|
, 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 */
|
/* Operator Overload Definitions */
|
||||||
|
|
|
@ -28,8 +28,9 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
#include "Physics/System/SHPhysicsSystem.h"
|
#include "Physics/System/SHPhysicsSystem.h"
|
||||||
#include "Physics/SHPhysicsEvents.h"
|
#include "Physics/SHPhysicsEvents.h"
|
||||||
#include "Scene/SHSceneEvents.h"
|
#include "Scene/SHSceneEvents.h"
|
||||||
|
|
||||||
#include "Assets/SHAssetMacros.h"
|
#include "Assets/SHAssetMacros.h"
|
||||||
|
#include "Tools/Utilities/SHExecUtilities.h"
|
||||||
|
#include "SHVSUtilities.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -189,12 +190,9 @@ namespace SHADE
|
||||||
oss << "[ScriptEngine] Building " << (debug ? " debug " : "") << "Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!";
|
oss << "[ScriptEngine] Building " << (debug ? " debug " : "") << "Managed Script Assembly (" << MANAGED_SCRIPT_LIB_NAME << ")!";
|
||||||
SHLOG_INFO(oss.str());
|
SHLOG_INFO(oss.str());
|
||||||
oss.str("");
|
oss.str("");
|
||||||
const bool BUILD_SUCCESS = execProcess
|
const auto BUILD_SUCCESS = SHExecUtilties::ExecBlockingProcess(L"C:\\Program Files\\dotnet\\dotnet.exe", generateBuildCommand(debug), false, false);
|
||||||
(
|
SHLOG_WARNING("Build Output: {}", SHStringUtilities::WstrToStr(BUILD_SUCCESS.StdOutput));
|
||||||
L"C:\\Windows\\system32\\cmd.exe",
|
if (BUILD_SUCCESS.Code == 0)
|
||||||
L"/K \"" + generateBuildCommand(debug) + L" & exit\""
|
|
||||||
) == 0;
|
|
||||||
if (BUILD_SUCCESS)
|
|
||||||
{
|
{
|
||||||
// Copy to built dll to the working directory and replace
|
// Copy to built dll to the working directory and replace
|
||||||
if (!copyFile("./tmp/SHADE_Scripting.dll", "SHADE_Scripting.dll", std::filesystem::copy_options::overwrite_existing))
|
if (!copyFile("./tmp/SHADE_Scripting.dll", "SHADE_Scripting.dll", std::filesystem::copy_options::overwrite_existing))
|
||||||
|
@ -238,7 +236,7 @@ namespace SHADE
|
||||||
LoadScriptAssembly();
|
LoadScriptAssembly();
|
||||||
}
|
}
|
||||||
|
|
||||||
return BUILD_SUCCESS;
|
return BUILD_SUCCESS.Code == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path) const
|
void SHScriptEngine::GenerateScriptsCsProjFile(const std::filesystem::path& path) const
|
||||||
|
@ -306,6 +304,16 @@ namespace SHADE
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SHScriptEngine::OpenSolution()
|
||||||
|
{
|
||||||
|
SHVSUtilties::OpenProject(CSPROJ_PATH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHScriptEngine::OpenFile(const std::filesystem::path& path)
|
||||||
|
{
|
||||||
|
SHVSUtilties::OpenFile(CSPROJ_PATH, path);
|
||||||
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
/* Event Handler Functions */
|
/* Event Handler Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -610,64 +618,12 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD SHScriptEngine::execProcess(const std::wstring& path, const std::wstring& args)
|
|
||||||
{
|
|
||||||
STARTUPINFOW startInfo;
|
|
||||||
PROCESS_INFORMATION procInfo;
|
|
||||||
ZeroMemory(&startInfo, sizeof(startInfo));
|
|
||||||
ZeroMemory(&procInfo, sizeof(procInfo));
|
|
||||||
startInfo.cb = sizeof(startInfo);
|
|
||||||
|
|
||||||
std::wstring argsWstr = args;
|
|
||||||
|
|
||||||
// Start Process
|
|
||||||
const auto SUCCESS = CreateProcess
|
|
||||||
(
|
|
||||||
path.data(), argsWstr.data(),
|
|
||||||
nullptr, nullptr, false, NULL, nullptr, nullptr,
|
|
||||||
&startInfo, &procInfo
|
|
||||||
);
|
|
||||||
|
|
||||||
// Error Check
|
|
||||||
if (!SUCCESS)
|
|
||||||
{
|
|
||||||
auto err = GetLastError();
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "[ScriptEngine] Failed to launch process. Error code: " << std::hex << err
|
|
||||||
<< " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")";
|
|
||||||
throw std::runtime_error(oss.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for execution to end
|
|
||||||
DWORD status;
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
const auto EXEC_SUCCESS = GetExitCodeProcess(procInfo.hProcess, &status);
|
|
||||||
if (!EXEC_SUCCESS)
|
|
||||||
{
|
|
||||||
auto err = GetLastError();
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << "[ScriptEngine] Failed to query process. Error code: " << std::hex << err
|
|
||||||
<< " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")";
|
|
||||||
throw std::runtime_error(oss.str());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Break only if process ends
|
|
||||||
if (status != STILL_ACTIVE)
|
|
||||||
{
|
|
||||||
CloseHandle(procInfo.hProcess);
|
|
||||||
CloseHandle(procInfo.hThread);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::wstring SHScriptEngine::generateBuildCommand(bool debug)
|
std::wstring SHScriptEngine::generateBuildCommand(bool debug)
|
||||||
{
|
{
|
||||||
std::wostringstream oss;
|
std::wostringstream oss;
|
||||||
oss << "dotnet build \"" << SHStringUtilities::StrToWstr(CSPROJ_PATH) << "\" -c ";
|
oss << " build \"" << SHStringUtilities::StrToWstr(std::filesystem::absolute(CSPROJ_PATH).string()) << "\" -c ";
|
||||||
oss << debug ? "Debug" : "Release";
|
oss << debug ? "Debug" : "Release";
|
||||||
oss << " -o \"./tmp/\" -fl -flp:LogFile=build.log;Verbosity=quiet -r \"win-x64\"";
|
oss << " -o \"./tmp/\" -r \"win-x64\"";
|
||||||
return oss.str();
|
return oss.str();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/************************************************************************************//*!
|
/************************************************************************************//*!
|
||||||
\file ScriptEngine.h
|
\file SHScriptEngine.h
|
||||||
\author Tng Kah Wei, kahwei.tng, 390009620
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
\par email: kahwei.tng\@digipen.edu
|
\par email: kahwei.tng\@digipen.edu
|
||||||
\date Sep 17, 2021
|
\date Sep 17, 2021
|
||||||
|
@ -217,6 +217,15 @@ namespace SHADE
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">File path to the generated file.</param>
|
/// <param name="path">File path to the generated file.</param>
|
||||||
void GenerateScriptsCsProjFile(const std::filesystem::path& path = CSPROJ_PATH) const;
|
void GenerateScriptsCsProjFile(const std::filesystem::path& path = CSPROJ_PATH) const;
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the script solution in Visual Studio.
|
||||||
|
/// </summary>
|
||||||
|
void OpenSolution();
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the file in Visual Studio.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path"></param>
|
||||||
|
void OpenFile(const std::filesystem::path& path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
|
@ -320,7 +329,6 @@ namespace SHADE
|
||||||
/// <returns> True if the file exists </returns>
|
/// <returns> True if the file exists </returns>
|
||||||
static bool fileExists(const std::filesystem::path& filePath);
|
static bool fileExists(const std::filesystem::path& filePath);
|
||||||
static bool copyFile(const std::filesystem::path& from, const std::filesystem::path& to, const std::filesystem::copy_options options) noexcept;
|
static bool copyFile(const std::filesystem::path& from, const std::filesystem::path& to, const std::filesystem::copy_options options) noexcept;
|
||||||
static DWORD execProcess(const std::wstring& path, const std::wstring& args);
|
|
||||||
static std::wstring generateBuildCommand(bool debug);
|
static std::wstring generateBuildCommand(bool debug);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,127 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHVSUtilities.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Dec 21, 2022
|
||||||
|
\brief Contains the implementation for SHVSUtilities static class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include <SHpch.h>
|
||||||
|
// Primary Header
|
||||||
|
#include "SHVSUtilities.h"
|
||||||
|
// Project Headers
|
||||||
|
#include "Tools/Utilities/SHExecUtilities.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Static Data Members */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
std::filesystem::path SHVSUtilties::devEnvPath;
|
||||||
|
HANDLE SHVSUtilties::devEnvInst = nullptr;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
void SHVSUtilties::OpenProject(const std::filesystem::path& projPath)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check if there is an instance
|
||||||
|
bool devEnvActive = false;
|
||||||
|
if (devEnvInst)
|
||||||
|
{
|
||||||
|
|
||||||
|
DWORD status;
|
||||||
|
const auto GET_CODE_STATUS = GetExitCodeProcess(devEnvInst, &status);
|
||||||
|
devEnvActive = GET_CODE_STATUS && status == STILL_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reuse the existing instance if there is one
|
||||||
|
if (devEnvActive)
|
||||||
|
{
|
||||||
|
// No need to reopen one
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (devEnvPath.empty())
|
||||||
|
{
|
||||||
|
devEnvPath = SHVSUtilties::getDevEnvPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto absProjPath = std::filesystem::canonical(projPath);
|
||||||
|
auto pi = SHExecUtilties::ExecProcess(devEnvPath.generic_wstring(), L" " + absProjPath.generic_wstring());
|
||||||
|
// Cache the process handle
|
||||||
|
devEnvInst = pi.hProcess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("{}", e.what());
|
||||||
|
SHLOG_ERROR("[SHVSUtilities] Failed to launch Visual Studio.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHVSUtilties::OpenFile(const std::filesystem::path& projPath, const std::filesystem::path& path)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check if there is an instance
|
||||||
|
bool devEnvActive = false;
|
||||||
|
if (devEnvInst)
|
||||||
|
{
|
||||||
|
|
||||||
|
DWORD status;
|
||||||
|
const auto GET_CODE_STATUS = GetExitCodeProcess(devEnvInst, &status);
|
||||||
|
devEnvActive = GET_CODE_STATUS && status == STILL_ACTIVE;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto absPath = std::filesystem::canonical(path);
|
||||||
|
|
||||||
|
// Reuse the existing instance if there is one
|
||||||
|
if (devEnvActive)
|
||||||
|
{
|
||||||
|
// Edit the file only
|
||||||
|
SHExecUtilties::ExecProcess(devEnvPath.generic_wstring(), L" /Edit " + absPath.generic_wstring());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (devEnvPath.empty())
|
||||||
|
{
|
||||||
|
devEnvPath = SHVSUtilties::getDevEnvPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto absProjPath = std::filesystem::canonical(projPath);
|
||||||
|
auto pi = SHExecUtilties::ExecProcess(devEnvPath.generic_wstring(), absProjPath.generic_wstring() + L" " + absPath.generic_wstring());
|
||||||
|
// Cache the process handle
|
||||||
|
devEnvInst = pi.hProcess;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("{}", e.what());
|
||||||
|
SHLOG_ERROR("[SHVSUtilities] Failed to launch Visual Studio.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
std::filesystem::path SHVSUtilties::getDevEnvPath()
|
||||||
|
{
|
||||||
|
#ifdef _PUBLISH
|
||||||
|
return {}; // Don't do anything if it's a published build
|
||||||
|
#else
|
||||||
|
static constexpr int EXCESS_CHARS_COUNT = 2;
|
||||||
|
|
||||||
|
const auto RESULT = SHExecUtilties::ExecBlockingPowerShellCommand(L"./vswhere -version \"[15.0,19.0]\" -requires Microsoft.NetCore.Component.DevelopmentTools -find Common7\\\\IDE\\\\devenv.exe | Select-Object -first 1", true, true);
|
||||||
|
if (RESULT.StdOutput.size() < EXCESS_CHARS_COUNT)
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[SHVSUtilities] Unable to get path to Visual Studio installation. SHVSUtilities will not work.");
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return RESULT.StdOutput.substr(0, RESULT.StdOutput.size() - EXCESS_CHARS_COUNT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHVSUtilties.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Dec 21, 2022
|
||||||
|
\brief Contains the interface for SHVSUtilties class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
|
||||||
|
// STL Includes
|
||||||
|
#include <filesystem>
|
||||||
|
// External Dependencies
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static class containing functions for working with Visual Studio installation and
|
||||||
|
/// running instances.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHVSUtilties final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Usage Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the project at the specified path with a new or existing instance of Visual
|
||||||
|
/// Studio if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="projPath">Path to the project file to open.</param>
|
||||||
|
static void OpenProject(const std::filesystem::path& projPath);
|
||||||
|
/// <summary>
|
||||||
|
/// Opens the file at the specified path with a new or existing instance of Visual
|
||||||
|
/// Studio if it exists.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="projPath">Path to the project file to open.</param>
|
||||||
|
/// <param name="path">Path to the file to open.</param>
|
||||||
|
static void OpenFile(const std::filesystem::path& projPath, const std::filesystem::path& path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors/Destructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHVSUtilties() = delete;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Static Data Members */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static std::filesystem::path devEnvPath;
|
||||||
|
static HANDLE devEnvInst;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static std::filesystem::path getDevEnvPath();
|
||||||
|
};
|
||||||
|
}
|
|
@ -52,15 +52,27 @@ namespace SHADE
|
||||||
SHFileIO::WriteStringToFile(editorConfigPath, out.c_str());
|
SHFileIO::WriteStringToFile(editorConfigPath, out.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
SHEditorConfig& SHConfigurationManager::LoadEditorConfig()
|
SHEditorConfig& SHConfigurationManager::LoadEditorConfig(WindowData* windowData)
|
||||||
{
|
{
|
||||||
|
if (!std::filesystem::exists(editorConfigPath))
|
||||||
|
{
|
||||||
|
SaveApplicationConfig();
|
||||||
|
return editorConfig;
|
||||||
|
}
|
||||||
|
|
||||||
auto const node = YAML::Load(SHFileIO::GetStringFromFile(editorConfigPath));
|
auto const node = YAML::Load(SHFileIO::GetStringFromFile(editorConfigPath));
|
||||||
auto properties = rttr::type::get<SHApplicationConfig>().get_properties();
|
auto properties = rttr::type::get<SHEditorConfig>().get_properties();
|
||||||
for(auto const& property : properties)
|
for(auto const& property : properties)
|
||||||
{
|
{
|
||||||
if(node[property.get_name().data()].IsDefined())
|
if(node[property.get_name().data()].IsDefined())
|
||||||
SHSerializationHelper::InitializeProperty(&editorConfig, property, node[property.get_name().data()]);
|
SHSerializationHelper::InitializeProperty(&editorConfig, property, node[property.get_name().data()]);
|
||||||
}
|
}
|
||||||
|
if(windowData)
|
||||||
|
{
|
||||||
|
windowData->isMaximised = editorConfig.startMaximized;
|
||||||
|
windowData->width = static_cast<uint32_t>(editorConfig.windowSize.x);
|
||||||
|
windowData->height = static_cast<uint32_t>(editorConfig.windowSize.y);
|
||||||
|
}
|
||||||
return editorConfig;
|
return editorConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,4 +98,10 @@ RTTR_REGISTRATION
|
||||||
.property("Starting Scene ID", &SHApplicationConfig::startingSceneID)
|
.property("Starting Scene ID", &SHApplicationConfig::startingSceneID)
|
||||||
.property("Window Size", &SHApplicationConfig::windowSize)
|
.property("Window Size", &SHApplicationConfig::windowSize)
|
||||||
.property("Window Title", &SHApplicationConfig::windowTitle);
|
.property("Window Title", &SHApplicationConfig::windowTitle);
|
||||||
|
|
||||||
|
registration::class_<SHEditorConfig>("Editor Config")
|
||||||
|
.property("Start Maximized", &SHEditorConfig::startMaximized)
|
||||||
|
.property("Working Scene ID", &SHEditorConfig::workingSceneID)
|
||||||
|
.property("Window Size", &SHEditorConfig::windowSize)
|
||||||
|
.property("Style", &SHEditorConfig::style);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
||||||
struct SHApplicationConfig
|
struct SHApplicationConfig
|
||||||
{
|
{
|
||||||
bool startInFullScreen{ false };
|
bool startInFullScreen{ false };
|
||||||
|
@ -19,7 +18,11 @@ namespace SHADE
|
||||||
|
|
||||||
struct SHEditorConfig
|
struct SHEditorConfig
|
||||||
{
|
{
|
||||||
|
bool startMaximized{true};
|
||||||
|
AssetID workingSceneID{};
|
||||||
|
SHVec2 windowSize {1920, 1080};
|
||||||
|
uint32_t style = 0;
|
||||||
|
RTTR_ENABLE()
|
||||||
};
|
};
|
||||||
|
|
||||||
class SH_API SHConfigurationManager
|
class SH_API SHConfigurationManager
|
||||||
|
@ -33,7 +36,7 @@ namespace SHADE
|
||||||
static SHApplicationConfig applicationConfig;
|
static SHApplicationConfig applicationConfig;
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
static void SaveEditorConfig();
|
static void SaveEditorConfig();
|
||||||
static SHEditorConfig& LoadEditorConfig();
|
static SHEditorConfig& LoadEditorConfig(WindowData* windowData = nullptr);
|
||||||
static SHEditorConfig editorConfig;
|
static SHEditorConfig editorConfig;
|
||||||
private:
|
private:
|
||||||
static void FetchEditorCameraData();
|
static void FetchEditorCameraData();
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "Physics/Interface/SHRigidBodyComponent.h"
|
#include "Physics/Interface/SHRigidBodyComponent.h"
|
||||||
#include "UI/SHCanvasComponent.h"
|
#include "UI/SHCanvasComponent.h"
|
||||||
#include "UI/SHButtonComponent.h"
|
#include "UI/SHButtonComponent.h"
|
||||||
|
#include "UI/SHToggleButtonComponent.h"
|
||||||
#include "ECS_Base/Managers/SHSystemManager.h"
|
#include "ECS_Base/Managers/SHSystemManager.h"
|
||||||
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
#include "Graphics/MiddleEnd/Lights/SHLightComponent.h"
|
||||||
#include "Scripting/SHScriptEngine.h"
|
#include "Scripting/SHScriptEngine.h"
|
||||||
|
@ -169,25 +170,15 @@ namespace SHADE
|
||||||
//}
|
//}
|
||||||
|
|
||||||
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
|
static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
|
||||||
{
|
{
|
||||||
if (const ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
|
YAML::Node node{};
|
||||||
{
|
if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
|
||||||
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(component);
|
{
|
||||||
}
|
node = SHSerializationHelper::SerializeComponentToNode(component);
|
||||||
}
|
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = node;
|
||||||
|
}
|
||||||
template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
}
|
||||||
static void AddConvComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
|
|
||||||
{
|
|
||||||
if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
|
|
||||||
{
|
|
||||||
auto componentNode = YAML::convert<ComponentType>::encode(*component);
|
|
||||||
componentNode[IsActive.data()] = component->isActive;
|
|
||||||
componentsNode[rttr::type::get<ComponentType>().get_name().data()] = componentNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode)
|
YAML::Node SHSerialization::SerializeEntityToNode(SHSceneNode* sceneNode)
|
||||||
{
|
{
|
||||||
|
@ -211,15 +202,16 @@ namespace SHADE
|
||||||
AddComponentToComponentNode<SHTransformComponent>(components, eid);
|
AddComponentToComponentNode<SHTransformComponent>(components, eid);
|
||||||
AddComponentToComponentNode<SHCameraComponent>(components, eid);
|
AddComponentToComponentNode<SHCameraComponent>(components, eid);
|
||||||
AddComponentToComponentNode<SHCameraArmComponent>(components, eid);
|
AddComponentToComponentNode<SHCameraArmComponent>(components, eid);
|
||||||
AddConvComponentToComponentNode<SHRenderable>(components, eid);
|
AddComponentToComponentNode<SHRenderable>(components, eid);
|
||||||
AddComponentToComponentNode<SHLightComponent>(components, eid);
|
AddComponentToComponentNode<SHLightComponent>(components, eid);
|
||||||
AddComponentToComponentNode<SHRigidBodyComponent>(components, eid);
|
AddComponentToComponentNode<SHRigidBodyComponent>(components, eid);
|
||||||
AddConvComponentToComponentNode<SHColliderComponent>(components, eid);
|
AddComponentToComponentNode<SHColliderComponent>(components, eid);
|
||||||
|
|
||||||
AddComponentToComponentNode<SHCanvasComponent>(components, eid);
|
AddComponentToComponentNode<SHCanvasComponent>(components, eid);
|
||||||
AddComponentToComponentNode<SHButtonComponent>(components, eid);
|
AddComponentToComponentNode<SHButtonComponent>(components, eid);
|
||||||
|
AddComponentToComponentNode<SHToggleButtonComponent>(components, eid);
|
||||||
|
|
||||||
AddConvComponentToComponentNode<SHTextRenderableComponent>(components, eid);
|
AddComponentToComponentNode<SHTextRenderableComponent>(components, eid);
|
||||||
|
|
||||||
node[ComponentsNode] = components;
|
node[ComponentsNode] = components;
|
||||||
|
|
||||||
|
@ -275,6 +267,7 @@ namespace SHADE
|
||||||
|
|
||||||
AddComponentID<SHCanvasComponent>(componentIDList, componentsNode);
|
AddComponentID<SHCanvasComponent>(componentIDList, componentsNode);
|
||||||
AddComponentID<SHButtonComponent>(componentIDList, componentsNode);
|
AddComponentID<SHButtonComponent>(componentIDList, componentsNode);
|
||||||
|
AddComponentID<SHToggleButtonComponent>(componentIDList, componentsNode);
|
||||||
AddComponentID<SHTextRenderableComponent>(componentIDList, componentsNode);
|
AddComponentID<SHTextRenderableComponent>(componentIDList, componentsNode);
|
||||||
|
|
||||||
return componentIDList;
|
return componentIDList;
|
||||||
|
@ -351,12 +344,13 @@ namespace SHADE
|
||||||
SHSerializationHelper::InitializeComponentFromNode<SHCameraComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHCameraComponent>(componentsNode, eid);
|
||||||
SHSerializationHelper::InitializeComponentFromNode<SHCameraArmComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHCameraArmComponent>(componentsNode, eid);
|
||||||
SHSerializationHelper::InitializeComponentFromNode<SHRigidBodyComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHRigidBodyComponent>(componentsNode, eid);
|
||||||
SHSerializationHelper::ConvertNodeToComponent<SHRenderable>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHRenderable>(componentsNode, eid);
|
||||||
SHSerializationHelper::ConvertNodeToComponent<SHColliderComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHColliderComponent>(componentsNode, eid);
|
||||||
|
|
||||||
SHSerializationHelper::InitializeComponentFromNode<SHCanvasComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHCanvasComponent>(componentsNode, eid);
|
||||||
SHSerializationHelper::InitializeComponentFromNode<SHButtonComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHButtonComponent>(componentsNode, eid);
|
||||||
SHSerializationHelper::ConvertNodeToComponent<SHTextRenderableComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHToggleButtonComponent>(componentsNode, eid);
|
||||||
|
SHSerializationHelper::InitializeComponentFromNode<SHTextRenderableComponent>(componentsNode, eid);
|
||||||
SHSerializationHelper::InitializeComponentFromNode<SHLightComponent>(componentsNode, eid);
|
SHSerializationHelper::InitializeComponentFromNode<SHLightComponent>(componentsNode, eid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,12 +104,6 @@ namespace SHADE
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
|
||||||
static std::string SerializeComponentToString(ComponentType* component)
|
|
||||||
{
|
|
||||||
return std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
|
static void SerializeComponentToFile(ComponentType* component, std::filesystem::path const& path)
|
||||||
{
|
{
|
||||||
|
@ -118,14 +112,29 @@ namespace SHADE
|
||||||
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
static YAML::Node SerializeComponentToNode(ComponentType* component)
|
static YAML::Node SerializeComponentToNode(ComponentType* component)
|
||||||
{
|
{
|
||||||
YAML::Node node{};
|
if constexpr (YAML::HasYAMLConv<ComponentType>())
|
||||||
if (!component)
|
{
|
||||||
return node;
|
if (component)
|
||||||
auto componentType = rttr::type::get<ComponentType>();
|
{
|
||||||
node = RTTRToNode(*component);
|
auto componentNode = YAML::convert<ComponentType>::encode(*component);
|
||||||
node[IsActive.data()] = component->isActive;
|
componentNode[IsActive.data()] = component->isActive;
|
||||||
|
return componentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (component)
|
||||||
|
{
|
||||||
|
YAML::Node compNode{};
|
||||||
|
if (!component)
|
||||||
|
return compNode;
|
||||||
|
auto componentType = rttr::type::get<ComponentType>();
|
||||||
|
compNode = RTTRToNode(*component);
|
||||||
|
compNode[IsActive.data()] = component->isActive;
|
||||||
|
return compNode;
|
||||||
|
|
||||||
return node;
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Type>
|
template <typename Type>
|
||||||
|
@ -192,26 +201,43 @@ namespace SHADE
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
static void InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
|
static bool InitializeComponentFromNode(YAML::Node const& componentsNode, EntityID const& eid)
|
||||||
{
|
{
|
||||||
ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid);
|
if constexpr (YAML::HasYAMLConv<ComponentType>())
|
||||||
if (componentsNode.IsNull() && !component)
|
|
||||||
return;
|
|
||||||
auto rttrType = rttr::type::get<ComponentType>();
|
|
||||||
auto componentNode = componentsNode[rttrType.get_name().data()];
|
|
||||||
if (!componentNode.IsDefined())
|
|
||||||
return;
|
|
||||||
if(componentNode[IsActive.data()].IsDefined())
|
|
||||||
component->isActive = componentNode[IsActive.data()].as<bool>();
|
|
||||||
|
|
||||||
auto properties = rttrType.get_properties();
|
|
||||||
for (auto const& prop : properties)
|
|
||||||
{
|
{
|
||||||
if (componentNode[prop.get_name().data()].IsDefined())
|
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
|
||||||
|
if (componentsNode.IsNull() || !component)
|
||||||
|
return false;
|
||||||
|
auto componentNode = GetComponentNode<ComponentType>(componentsNode, eid);
|
||||||
|
if (componentNode.IsNull() || !componentNode.IsDefined())
|
||||||
|
return false;
|
||||||
|
if (componentNode[IsActive.data()].IsDefined())
|
||||||
|
component->isActive = componentNode[IsActive.data()].as<bool>();
|
||||||
|
YAML::convert<ComponentType>::decode(componentNode, *component);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid);
|
||||||
|
if (componentsNode.IsNull() && !component)
|
||||||
|
return false;
|
||||||
|
auto rttrType = rttr::type::get<ComponentType>();
|
||||||
|
auto componentNode = componentsNode[rttrType.get_name().data()];
|
||||||
|
if (!componentNode.IsDefined())
|
||||||
|
return false;
|
||||||
|
if (componentNode[IsActive.data()].IsDefined())
|
||||||
|
component->isActive = componentNode[IsActive.data()].as<bool>();
|
||||||
|
|
||||||
|
auto properties = rttrType.get_properties();
|
||||||
|
for (auto const& prop : properties)
|
||||||
{
|
{
|
||||||
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
|
if (componentNode[prop.get_name().data()].IsDefined())
|
||||||
|
{
|
||||||
|
InitializeProperty<ComponentType>(component, prop, componentNode[prop.get_name().data()]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
|
@ -227,16 +253,49 @@ namespace SHADE
|
||||||
return componentNode;
|
return componentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//template<typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
|
//static void AddComponentToComponentNode(YAML::Node& componentsNode, EntityID const& eid)
|
||||||
|
//{
|
||||||
|
// if constexpr (YAML::HasYAMLConv<ComponentType>())
|
||||||
|
// {
|
||||||
|
// if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
|
||||||
|
// {
|
||||||
|
// auto componentNode = YAML::convert<ComponentType>::encode(*component);
|
||||||
|
// componentNode[IsActive.data()] = component->isActive;
|
||||||
|
// componentsNode[rttr::type::get<ComponentType>().get_name().data()] = componentNode;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// if (const ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
|
||||||
|
// {
|
||||||
|
// componentsNode[rttr::type::get<ComponentType>().get_name().data()] = SHSerializationHelper::SerializeComponentToNode(component);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
static void ConvertNodeToComponent(YAML::Node const& componentsNode, EntityID const& eid)
|
static std::string SerializeComponentToString(EntityID const& eid)
|
||||||
{
|
{
|
||||||
auto component = SHComponentManager::GetComponent_s<ComponentType>(eid);
|
if (ComponentType* component = SHComponentManager::GetComponent_s<ComponentType>(eid))
|
||||||
if (componentsNode.IsNull() && !component)
|
{
|
||||||
return;
|
YAML::Emitter out;
|
||||||
auto componentNode = GetComponentNode<ComponentType>(componentsNode, eid);
|
YAML::Node node{};
|
||||||
if (componentNode[IsActive.data()].IsDefined())
|
|
||||||
component->isActive = componentNode[IsActive.data()].as<bool>();
|
node[rttr::type::get<ComponentType>().get_name().data()] = SerializeComponentToNode(component);
|
||||||
YAML::convert<ComponentType>::decode(componentNode, *component);
|
out << node;
|
||||||
|
|
||||||
|
return out.c_str();
|
||||||
|
}
|
||||||
|
return std::string();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
|
static bool DeserializeComponentFromString(std::string data, EntityID const& eid)
|
||||||
|
{
|
||||||
|
YAML::Node node = YAML::Load(data);
|
||||||
|
return InitializeComponentFromNode<ComponentType>(node, eid);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
template <typename ComponentType, std::enable_if_t<std::is_base_of_v<SHComponent, ComponentType>, bool> = true>
|
||||||
|
|
|
@ -20,6 +20,16 @@ namespace YAML
|
||||||
{
|
{
|
||||||
using namespace SHADE;
|
using namespace SHADE;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct HasYAMLConv : std::false_type{};
|
||||||
|
|
||||||
|
template<>
|
||||||
|
struct HasYAMLConv<SHColliderComponent> : std::true_type {};
|
||||||
|
template<>
|
||||||
|
struct HasYAMLConv<SHRenderable> : std::true_type {};
|
||||||
|
template<>
|
||||||
|
struct HasYAMLConv<SHTextRenderableComponent> : std::true_type {};
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
struct convert<SHVec4>
|
struct convert<SHVec4>
|
||||||
{
|
{
|
||||||
|
|
|
@ -128,6 +128,10 @@ namespace SHADE
|
||||||
dbgDrawSys->DrawWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested);
|
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 */
|
/* Persistent Draw Functions */
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
@ -216,6 +220,10 @@ namespace SHADE
|
||||||
dbgDrawSys->DrawPersistentWireSphere(SHMatrix::Transform(center, SHQuaternion(), scale), color, depthTested);
|
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()
|
void SHDebugDraw::Persistent::ClearDraws()
|
||||||
{
|
{
|
||||||
dbgDrawSys->ClearPersistentDraws();
|
dbgDrawSys->ClearPersistentDraws();
|
||||||
|
|
|
@ -194,6 +194,18 @@ namespace SHADE
|
||||||
/// <param name="color">Colour to draw with.</param>
|
/// <param name="color">Colour to draw with.</param>
|
||||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
|
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
|
||||||
|
/// <summary>
|
||||||
|
/// Draws the outline of a capsule.
|
||||||
|
/// This will remain drawn until ClearDraws() is called.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Position of the wireframe capsule.</param>
|
||||||
|
/// <param name="rotation">Rotation of the capsule.</param>
|
||||||
|
/// <param name="height">Height of the overall capsule.</param>
|
||||||
|
/// <param name="radius">Radius of the capsule.</param>
|
||||||
|
/// <param name="color"></param>
|
||||||
|
/// <param name="color">Colour to draw with.</param>
|
||||||
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
|
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" */
|
/* Persistent Draw Function Class "Folder" */
|
||||||
|
@ -366,6 +378,18 @@ namespace SHADE
|
||||||
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
|
static void WireSphere(const SHVec3& center, const SHVec3& scale, const SHVec4& color = SHColour::WHITE, bool depthTested = false);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Draws the outline of a capsule.
|
||||||
|
/// This will remain drawn until ClearDraws() is called.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="position">Position of the wireframe capsule.</param>
|
||||||
|
/// <param name="rotation">Rotation of the capsule.</param>
|
||||||
|
/// <param name="height">Height of the overall capsule.</param>
|
||||||
|
/// <param name="radius">Radius of the capsule.</param>
|
||||||
|
/// <param name="color"></param>
|
||||||
|
/// <param name="color">Colour to draw with.</param>
|
||||||
|
/// <param name="depthTested">Whether or not drawn object will be occluded.</param>
|
||||||
|
static void WireCapsule(const SHVec3& position, const SHQuaternion& rotation, float height, float radius, const SHColour& color = SHColour::WHITE, bool depthTested = false);
|
||||||
|
/// <summary>
|
||||||
/// Clears any persistent drawn debug primitives.
|
/// Clears any persistent drawn debug primitives.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static void ClearDraws();
|
static void ClearDraws();
|
||||||
|
|
|
@ -0,0 +1,215 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHExecUtilities.cpp
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Dec 21, 2022
|
||||||
|
\brief Contains the implementation for SHExecUtilities static class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
// Precompiled Headers
|
||||||
|
#include <SHpch.h>
|
||||||
|
// Primary Header
|
||||||
|
#include "SHExecUtilities.h"
|
||||||
|
// Project Includes
|
||||||
|
#include "SHStringUtilities.h"
|
||||||
|
#include "SHFileUtilties.h"
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Process Execution Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
PROCESS_INFORMATION SHExecUtilties::ExecProcess(const std::wstring& path, const std::wstring& args)
|
||||||
|
{
|
||||||
|
return execProcess(path, args, nullptr, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecResult SHExecUtilties::ExecBlockingProcess(const std::wstring& path, const std::wstring& args, bool output, bool errorOutput)
|
||||||
|
{
|
||||||
|
// Create pipes for stdout and stderr if specified
|
||||||
|
HANDLE stdoutReadPipe = nullptr;
|
||||||
|
HANDLE stdoutWritePipe = nullptr;
|
||||||
|
HANDLE stderrReadPipe = nullptr;
|
||||||
|
HANDLE stderrWritePipe = nullptr;
|
||||||
|
if (output)
|
||||||
|
{
|
||||||
|
std::tie(stdoutReadPipe, stdoutWritePipe) = createIoPipes();
|
||||||
|
}
|
||||||
|
if (errorOutput)
|
||||||
|
{
|
||||||
|
std::tie(stderrReadPipe, stderrWritePipe) = createIoPipes();
|
||||||
|
}
|
||||||
|
|
||||||
|
PROCESS_INFORMATION procInfo = execProcess(path, args, stdoutWritePipe, stderrWritePipe);
|
||||||
|
|
||||||
|
// Wait for execution to end
|
||||||
|
ExecResult result;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const auto EXEC_SUCCESS = GetExitCodeProcess(procInfo.hProcess, &result.Code);
|
||||||
|
if (!EXEC_SUCCESS)
|
||||||
|
{
|
||||||
|
auto err = GetLastError();
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[SHExecUtilties] Failed to query process. Error code: " << std::hex << err
|
||||||
|
<< " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break only if process ends
|
||||||
|
if (result.Code != STILL_ACTIVE)
|
||||||
|
{
|
||||||
|
// Get stdout/stderror output
|
||||||
|
if (stdoutReadPipe)
|
||||||
|
{
|
||||||
|
readPipeData(stdoutReadPipe, stdoutWritePipe, result.StdOutput);
|
||||||
|
}
|
||||||
|
if (stderrReadPipe)
|
||||||
|
{
|
||||||
|
readPipeData(stderrReadPipe, stderrWritePipe, result.StdErrOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the process and threads for that process
|
||||||
|
CloseHandle(procInfo.hProcess);
|
||||||
|
CloseHandle(procInfo.hThread);
|
||||||
|
|
||||||
|
// Return results
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
/* Command Execution Functions */
|
||||||
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
PROCESS_INFORMATION SHExecUtilties::ExecCommand(const std::wstring& command)
|
||||||
|
{
|
||||||
|
return ExecProcess
|
||||||
|
(
|
||||||
|
L"C:\\Windows\\system32\\cmd.exe",
|
||||||
|
L"/K \"" + command + L" & exit\""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecResult SHExecUtilties::ExecBlockingCommand(const std::wstring& command, bool output, bool errorOutput)
|
||||||
|
{
|
||||||
|
return ExecBlockingProcess
|
||||||
|
(
|
||||||
|
L"C:\\Windows\\system32\\cmd.exe",
|
||||||
|
L"/K \"" + command + L" & exit\"",
|
||||||
|
output,
|
||||||
|
errorOutput
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROCESS_INFORMATION SHExecUtilties::ExecPowerShellCommand(const std::wstring& command)
|
||||||
|
{
|
||||||
|
return ExecProcess
|
||||||
|
(
|
||||||
|
L"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
||||||
|
L"-Command \"& {" + command + L"} \""
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecResult SHExecUtilties::ExecBlockingPowerShellCommand(const std::wstring& command, bool output, bool errorOutput)
|
||||||
|
{
|
||||||
|
return ExecBlockingProcess
|
||||||
|
(
|
||||||
|
L"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
|
||||||
|
L"-Command \"& { cd \"" + SHFileUtilities::GetExecDir().generic_wstring() + L"\";" + command + L"} \"",
|
||||||
|
output,
|
||||||
|
errorOutput
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
PROCESS_INFORMATION SHExecUtilties::execProcess(const std::wstring& path, const std::wstring& args, HANDLE outputWritePipe, HANDLE errorOutputWritePipe)
|
||||||
|
{
|
||||||
|
STARTUPINFOW startInfo;
|
||||||
|
PROCESS_INFORMATION procInfo;
|
||||||
|
ZeroMemory(&startInfo, sizeof(startInfo));
|
||||||
|
ZeroMemory(&procInfo, sizeof(procInfo));
|
||||||
|
startInfo.cb = sizeof(startInfo);
|
||||||
|
if (outputWritePipe)
|
||||||
|
{
|
||||||
|
startInfo.hStdOutput = outputWritePipe;
|
||||||
|
startInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
startInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
}
|
||||||
|
if (errorOutputWritePipe)
|
||||||
|
{
|
||||||
|
startInfo.hStdError = errorOutputWritePipe;
|
||||||
|
startInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
|
startInfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::wstring argsWstr = args;
|
||||||
|
|
||||||
|
// Start Process
|
||||||
|
const auto SUCCESS = CreateProcess
|
||||||
|
(
|
||||||
|
path.data(), argsWstr.data(),
|
||||||
|
nullptr, nullptr, true, NULL, nullptr, nullptr,
|
||||||
|
&startInfo, &procInfo
|
||||||
|
);
|
||||||
|
|
||||||
|
// Error Check
|
||||||
|
if (!SUCCESS)
|
||||||
|
{
|
||||||
|
auto err = GetLastError();
|
||||||
|
std::ostringstream oss;
|
||||||
|
oss << "[SHExecUtilties] Failed to launch process. Error code: " << std::hex << err
|
||||||
|
<< " (" << SHStringUtilities::GetWin32ErrorMessage(err) << ")";
|
||||||
|
throw std::runtime_error(oss.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return procInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::pair<HANDLE, HANDLE> SHExecUtilties::createIoPipes()
|
||||||
|
{
|
||||||
|
SECURITY_ATTRIBUTES saAttr;
|
||||||
|
saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||||
|
saAttr.bInheritHandle = true;
|
||||||
|
saAttr.lpSecurityDescriptor = nullptr;
|
||||||
|
|
||||||
|
// First: Read | Second: Write
|
||||||
|
std::pair<HANDLE, HANDLE> output = { nullptr, nullptr };
|
||||||
|
if (CreatePipe(&output.first, &output.second, &saAttr, 0))
|
||||||
|
{
|
||||||
|
if (!SetHandleInformation(output.first, HANDLE_FLAG_INHERIT, 0))
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[SHExecUtilities] Failed to initialize pipe for process IO.");
|
||||||
|
CloseHandle(output.first);
|
||||||
|
CloseHandle(output.second);
|
||||||
|
output = { nullptr, nullptr };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SHLOG_ERROR("[SHExecUtilities] Failed to create pipe for process IO.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SHExecUtilties::readPipeData(HANDLE readPipe, HANDLE writePipe, std::wstring& output)
|
||||||
|
{
|
||||||
|
CloseHandle(writePipe);
|
||||||
|
|
||||||
|
LARGE_INTEGER stdoutSize = {};
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
std::array<char, 256> buffer{};
|
||||||
|
DWORD bytesRead = 0;
|
||||||
|
const auto RESULT = ReadFile(readPipe, buffer.data(), buffer.size(), &bytesRead, nullptr);
|
||||||
|
if (!RESULT || bytesRead <= 0)
|
||||||
|
break;
|
||||||
|
output.insert(output.end(), buffer.data(), buffer.data() + bytesRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(readPipe);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,142 @@
|
||||||
|
/************************************************************************************//*!
|
||||||
|
\file SHExecUtilties.h
|
||||||
|
\author Tng Kah Wei, kahwei.tng, 390009620
|
||||||
|
\par email: kahwei.tng\@digipen.edu
|
||||||
|
\date Dec 21, 2022
|
||||||
|
\brief Contains the interface for SHExecUtilities class.
|
||||||
|
|
||||||
|
Copyright (C) 2022 DigiPen Institute of Technology.
|
||||||
|
Reproduction or disclosure of this file or its contents without the prior written consent
|
||||||
|
of DigiPen Institute of Technology is prohibited.
|
||||||
|
*//*************************************************************************************/
|
||||||
|
|
||||||
|
// STL Includes
|
||||||
|
#include <string>
|
||||||
|
// External Dependencies
|
||||||
|
#include <Windows.h>
|
||||||
|
|
||||||
|
namespace SHADE
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Stores the result of an execution of a process.
|
||||||
|
/// </summary>
|
||||||
|
struct SH_API ExecResult final
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exit code of the process.
|
||||||
|
/// </summary>
|
||||||
|
DWORD Code;
|
||||||
|
/// <summary>
|
||||||
|
/// Stored text output from the process.
|
||||||
|
/// </summary>
|
||||||
|
std::wstring StdOutput;
|
||||||
|
/// <summary>
|
||||||
|
/// Stored error text output from the process.
|
||||||
|
/// </summary>
|
||||||
|
std::wstring StdErrOutput;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Static class containing functions for executing external processes or commands.
|
||||||
|
/// </summary>
|
||||||
|
class SH_API SHExecUtilties final
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Process Execution Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a process at the specified path with the specified arguments. This call
|
||||||
|
/// does not wait for the process to finish executing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">Path to the processs to start.</param>
|
||||||
|
/// <param name="args">Arguments to pass to the process.</param>
|
||||||
|
/// <returns>Information about the started process.</returns>
|
||||||
|
/// <exception cref="std::runtime_error">
|
||||||
|
/// Thrown if failed to start the process.
|
||||||
|
/// </exception>
|
||||||
|
static PROCESS_INFORMATION ExecProcess(const std::wstring& path, const std::wstring& args);
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a process at the specified path with the specified arguments and waits
|
||||||
|
/// for that process to finish executing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">Path to the processs to start.</param>
|
||||||
|
/// <param name="args">Arguments to pass to the process.</param>
|
||||||
|
/// <param name="output">If true, stdout will be routed to return.</param>
|
||||||
|
/// <param name="errorOutput">If true, outstderr will be routed to return.</param>
|
||||||
|
/// <returns>Information about the process's execution.</returns>
|
||||||
|
/// <exception cref="std::runtime_error">
|
||||||
|
/// Thrown if failed to start the process.
|
||||||
|
/// </exception>
|
||||||
|
static ExecResult ExecBlockingProcess(const std::wstring& path, const std::wstring& args, bool output = false, bool errorOutput = false);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Command Execution Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a specified command in cmd.
|
||||||
|
/// This call does not wait for the command to finish executing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">Command to execute.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Information about the started cmd process that executes the command.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="std::runtime_error">
|
||||||
|
/// Thrown if failed to start the process.
|
||||||
|
/// </exception>
|
||||||
|
static PROCESS_INFORMATION ExecCommand(const std::wstring& command);
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a specified command in cmd and waits for that process to finish
|
||||||
|
/// executing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">Command to execute.</param>
|
||||||
|
/// <param name="output">If true, stdout will be routed to return.</param>
|
||||||
|
/// <param name="errorOutput">If true, outstderr will be routed to return.</param>
|
||||||
|
/// <returns>Information about the process's execution.</returns>
|
||||||
|
/// <exception cref="std::runtime_error">
|
||||||
|
/// Thrown if failed to start the process.
|
||||||
|
/// </exception>
|
||||||
|
static ExecResult ExecBlockingCommand(const std::wstring& command, bool output = false, bool errorOutput = false);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* PowerShell Execution Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a specified command in PowerShell.
|
||||||
|
/// This call does not wait for the command to finish executing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">Command to execute.</param>
|
||||||
|
/// <returns>
|
||||||
|
/// Information about the started cmd process that executes the command.
|
||||||
|
/// </returns>
|
||||||
|
/// <exception cref="std::runtime_error">
|
||||||
|
/// Thrown if failed to start the process.
|
||||||
|
/// </exception>
|
||||||
|
static PROCESS_INFORMATION ExecPowerShellCommand(const std::wstring& command);
|
||||||
|
/// <summary>
|
||||||
|
/// Executes a specified command in PowerShell and waits for that process to finish
|
||||||
|
/// executing.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="command">Command to execute.</param>
|
||||||
|
/// <param name="output">If true, stdout will be routed to return.</param>
|
||||||
|
/// <param name="errorOutput">If true, outstderr will be routed to return.</param>
|
||||||
|
/// <returns>Information about the process's execution.</returns>
|
||||||
|
/// <exception cref="std::runtime_error">
|
||||||
|
/// Thrown if failed to start the process.
|
||||||
|
/// </exception>
|
||||||
|
static ExecResult ExecBlockingPowerShellCommand(const std::wstring& command, bool output, bool errorOutput);
|
||||||
|
|
||||||
|
private:
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Constructors/Destructors */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
SHExecUtilties() = delete;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Helper Functions */
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
static PROCESS_INFORMATION execProcess(const std::wstring& path, const std::wstring& args, HANDLE outputWritePipe, HANDLE errorOutputWritePipe);
|
||||||
|
static std::pair<HANDLE, HANDLE> createIoPipes();
|
||||||
|
static void readPipeData(HANDLE readPipe, HANDLE writePipe, std::wstring& output);
|
||||||
|
};
|
||||||
|
}
|
|
@ -22,9 +22,21 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
void SHFileUtilities::SetWorkDirToExecDir()
|
void SHFileUtilities::SetWorkDirToExecDir()
|
||||||
{
|
{
|
||||||
TCHAR currentExecFilePath[MAX_PATH] = { '\0' };
|
std::filesystem::current_path(GetExecDir());
|
||||||
GetModuleFileName(nullptr, currentExecFilePath, MAX_PATH);
|
}
|
||||||
PathRemoveFileSpec(currentExecFilePath);
|
|
||||||
std::filesystem::current_path(currentExecFilePath);
|
std::filesystem::path SHFileUtilities::GetExecDir()
|
||||||
|
{
|
||||||
|
TCHAR currentExecFilePath[MAX_PATH] = { '\0' };
|
||||||
|
GetModuleFileName(nullptr, currentExecFilePath, MAX_PATH);
|
||||||
|
PathRemoveFileSpec(currentExecFilePath);
|
||||||
|
return std::filesystem::path(currentExecFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::filesystem::path SHFileUtilities::GetExecPath()
|
||||||
|
{
|
||||||
|
TCHAR currentExecFilePath[MAX_PATH] = { '\0' };
|
||||||
|
GetModuleFileName(nullptr, currentExecFilePath, MAX_PATH);
|
||||||
|
return std::filesystem::path(currentExecFilePath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,24 +15,29 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
/*!************************************************************************************
|
/// <summary>
|
||||||
|
/// Static class that contains functions for working with files and directories.
|
||||||
\class SHFileUtilities
|
/// </summary>
|
||||||
|
|
||||||
\brief
|
|
||||||
Static class that contains functions for working with files and directories.
|
|
||||||
|
|
||||||
**************************************************************************************/
|
|
||||||
class SH_API SHFileUtilities
|
class SH_API SHFileUtilities
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!**********************************************************************************
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Executable Directory Functions */
|
||||||
\brief
|
/*---------------------------------------------------------------------------------*/
|
||||||
Sets the application's current working directory to the application executable's
|
/// <summary>
|
||||||
directory.
|
/// Sets the application's current working directory to the application executable's
|
||||||
|
/// directory.
|
||||||
************************************************************************************/
|
/// </summary>
|
||||||
static void SetWorkDirToExecDir();
|
static void SetWorkDirToExecDir();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the file path to the executable's directory.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>File path to the executable's directory.</returns>
|
||||||
|
static std::filesystem::path GetExecDir();
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the file path to the executable.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>File path to the executable.</returns>
|
||||||
|
static std::filesystem::path GetExecPath();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,27 +26,29 @@ namespace SHADE
|
||||||
std::vector<std::wstring> SHStringUtilities::Split(const std::wstring& str, const wchar_t& delim)
|
std::vector<std::wstring> SHStringUtilities::Split(const std::wstring& str, const wchar_t& delim)
|
||||||
{
|
{
|
||||||
return Split<wchar_t>(str, delim);
|
return Split<wchar_t>(str, delim);
|
||||||
}
|
}
|
||||||
std::string SHStringUtilities::WstrToStr(const std::wstring& wstr)
|
std::string SHStringUtilities::WstrToStr(const std::wstring& wstr)
|
||||||
{
|
{
|
||||||
static std::vector<char> buffer;
|
static std::vector<char> buffer;
|
||||||
const int STR_SIZE = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), nullptr, 0, nullptr, nullptr) + 1 /* Null Terminator */;
|
buffer.clear();
|
||||||
buffer.resize(STR_SIZE);
|
const int STR_SIZE = WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), nullptr, 0, nullptr, nullptr) + 1 /* Null Terminator */;
|
||||||
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), buffer.data(), MAX_PATH, nullptr, nullptr);
|
buffer.resize(STR_SIZE, '\0');
|
||||||
return std::string(buffer.data());
|
WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast<int>(wstr.size()), buffer.data(), MAX_PATH, nullptr, nullptr);
|
||||||
}
|
return std::string(buffer.data());
|
||||||
std::wstring SHStringUtilities::StrToWstr(const std::string& str)
|
}
|
||||||
{
|
std::wstring SHStringUtilities::StrToWstr(const std::string& str)
|
||||||
static std::vector<wchar_t> buffer;
|
{
|
||||||
const int WSTR_SIZE = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()), nullptr, 0) + 1 /* Null Terminator */;
|
static std::vector<wchar_t> buffer;
|
||||||
buffer.resize(WSTR_SIZE);
|
buffer.clear();
|
||||||
MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()), buffer.data(), WSTR_SIZE);
|
const int WSTR_SIZE = MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()), nullptr, 0) + 1 /* Null Terminator */;
|
||||||
return std::wstring(buffer.data());
|
buffer.resize(WSTR_SIZE, '\0');
|
||||||
}
|
MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast<int>(str.size()), buffer.data(), WSTR_SIZE);
|
||||||
|
return std::wstring(buffer.data());
|
||||||
|
}
|
||||||
|
|
||||||
std::string SHStringUtilities::GetWin32ErrorMessage(unsigned long errorCode)
|
std::string SHStringUtilities::GetWin32ErrorMessage(unsigned long errorCode)
|
||||||
{
|
{
|
||||||
return std::system_category().message(errorCode);
|
return std::system_category().message(errorCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -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};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -5,7 +5,7 @@
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
SHButtonComponent::SHButtonComponent()
|
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)
|
defaultTexture(0), hoveredTexture(0), clickedTexture(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ namespace SHADE
|
||||||
virtual ~SHButtonComponent() = default;
|
virtual ~SHButtonComponent() = default;
|
||||||
|
|
||||||
SHVec2 size;
|
SHVec2 size;
|
||||||
SHVec2 offset;
|
|
||||||
|
|
||||||
AssetID GetClickedTexture() const noexcept;
|
AssetID GetClickedTexture() const noexcept;
|
||||||
AssetID GetDefaultTexture() const noexcept;
|
AssetID GetDefaultTexture() const noexcept;
|
||||||
|
@ -33,8 +32,10 @@ namespace SHADE
|
||||||
|
|
||||||
friend class SHUISystem;
|
friend class SHUISystem;
|
||||||
private:
|
private:
|
||||||
|
//Set to true when mouse is hovering over the button.
|
||||||
bool isHovered;
|
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 isClicked;
|
||||||
AssetID defaultTexture;
|
AssetID defaultTexture;
|
||||||
AssetID hoveredTexture;
|
AssetID hoveredTexture;
|
||||||
|
|
|
@ -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_<SHSliderComponent>("Slider Component")
|
||||||
|
.property("Slider Value", &SHSliderComponent::GetValue, &SHSliderComponent::SetValue)
|
||||||
|
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <rttr/registration>
|
||||||
|
|
||||||
|
#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()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -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_<SHToggleButtonComponent>("Toggle Button Component")
|
||||||
|
.property("Non Toggled Texture", &SHToggleButtonComponent::GetDefaultTexture, &SHToggleButtonComponent::SetDefaultTexture)
|
||||||
|
.property("Toggled Texture", &SHToggleButtonComponent::GetToggledTexture, &SHToggleButtonComponent::SetToggledTexture)
|
||||||
|
.property("Value", &SHToggleButtonComponent::GetValue, &SHToggleButtonComponent::SetValue)
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <rttr/registration>
|
||||||
|
|
||||||
|
#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()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -9,7 +9,15 @@
|
||||||
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
#include "Editor/EditorWindow/ViewportWindow/SHEditorViewport.h"
|
||||||
#include "Editor/SHEditor.h"
|
#include "Editor/SHEditor.h"
|
||||||
#include "Resource/SHResourceManager.h"
|
#include "Resource/SHResourceManager.h"
|
||||||
|
#include "Assets/SHAssetManager.h"
|
||||||
#include "Input/SHInputManager.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
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
@ -103,7 +111,7 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(comp.GetEID());
|
auto transform = SHComponentManager::GetComponent<SHTransformComponent>(comp.GetEID());
|
||||||
if (canvasComp != nullptr)
|
if (canvasComp != nullptr)
|
||||||
comp.localToCanvasMatrix = canvasComp->GetMatrix()* transform->GetTRS();
|
comp.localToCanvasMatrix = transform->GetTRS() * canvasComp->GetMatrix();
|
||||||
else
|
else
|
||||||
comp.localToCanvasMatrix = transform->GetTRS();
|
comp.localToCanvasMatrix = transform->GetTRS();
|
||||||
}
|
}
|
||||||
|
@ -139,77 +147,235 @@ namespace SHADE
|
||||||
|
|
||||||
void SHUISystem::UpdateButtonComponent(SHButtonComponent& comp) noexcept
|
void SHUISystem::UpdateButtonComponent(SHButtonComponent& comp) noexcept
|
||||||
{
|
{
|
||||||
if (!SHComponentManager::HasComponent<SHTransformComponent>(comp.GetEID()) || !SHComponentManager::HasComponent<SHUIComponent>(comp.GetEID()))
|
if (!SHComponentManager::HasComponent<SHUIComponent>(comp.GetEID()))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
|
auto uiComp = SHComponentManager::GetComponent<SHUIComponent>(comp.GetEID());
|
||||||
|
//auto canvasComp = SHComponentManager::GetComponent_s<SHCanvasComponent>(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<SHEditorViewport>()->beginContentRegionAvailable;
|
||||||
|
mousePos = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->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<SHGraphicsSystem>()->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<SHEditor>()->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<SHRenderable>(comp.GetEID()))
|
||||||
|
{
|
||||||
|
auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(comp.GetEID());
|
||||||
|
//auto texture = SHResourceManager::Get<SHTexture>(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<SHUIComponent>(comp.GetEID()))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
auto uiComp = SHComponentManager::GetComponent<SHUIComponent>(comp.GetEID());
|
auto uiComp = SHComponentManager::GetComponent<SHUIComponent>(comp.GetEID());
|
||||||
|
|
||||||
SHVec4 topExtent4 = 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 = uiComp->GetMatrix() * SHVec4(comp.size.x * 0.5f , -comp.size.y * 0.5f , 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 mousePos;
|
||||||
|
SHVec2 windowSize;
|
||||||
|
|
||||||
#ifdef SHEDITOR
|
#ifdef SHEDITOR
|
||||||
|
windowSize = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->beginContentRegionAvailable;
|
||||||
windowSize = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->windowSize;
|
|
||||||
mousePos = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->viewportMousePos;
|
mousePos = SHEditorWindowManager::GetEditorWindow<SHEditorViewport>()->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<SHGraphicsSystem>()->GetWindow()->GetWindowSize();
|
||||||
|
windowSize = { ws.first,ws.second };
|
||||||
|
mousePos /= windowSize;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0) };
|
||||||
|
|
||||||
|
|
||||||
SHVec2 camSize{ cameraSystem->GetCameraWidthHeight(0).x , cameraSystem->GetCameraWidthHeight(0).y };
|
|
||||||
|
|
||||||
topExtent += camSize * 0.5f;
|
topExtent = CanvasToScreenPoint(topExtent,true);
|
||||||
btmExtent += camSize * 0.5f;
|
btmExtent = CanvasToScreenPoint(btmExtent, true);
|
||||||
|
|
||||||
//Convert everything to using ratios
|
|
||||||
topExtent /= camSize;
|
|
||||||
btmExtent /= camSize;
|
|
||||||
|
|
||||||
mousePos /= windowSize;
|
|
||||||
|
|
||||||
//SHLOG_INFO("mousePos: {} , {}", mousePos.x, mousePos.y);
|
|
||||||
comp.isClicked = false;
|
comp.isClicked = false;
|
||||||
if (mousePos.x >= topExtent.x && mousePos.x <= btmExtent.x
|
if (mousePos.x >= topExtent.x && mousePos.x <= btmExtent.x
|
||||||
&& mousePos.y >= topExtent.y && mousePos.y <= btmExtent.y)
|
&& mousePos.y >= topExtent.y && mousePos.y <= btmExtent.y)
|
||||||
{
|
{
|
||||||
comp.isHovered = true;
|
comp.isHovered = true;
|
||||||
if (SHInputManager::GetKeyUp(SHInputManager::SH_KEYCODE::LMB))
|
#ifdef SHEDITOR
|
||||||
|
if (SHSystemManager::GetSystem<SHEditor>()->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;
|
comp.isClicked = true;
|
||||||
}
|
}
|
||||||
//SHLOG_INFO("BUTTON HOVERED");
|
#endif
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
comp.isHovered = false;
|
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<SHRenderable>(comp.GetEID()))
|
if (SHComponentManager::HasComponent<SHRenderable>(comp.GetEID()))
|
||||||
{
|
{
|
||||||
//auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(comp.GetEID());
|
auto renderable = SHComponentManager::GetComponent_s<SHRenderable>(comp.GetEID());
|
||||||
//auto texture = SHResourceManager::Get<SHTexture>(comp.GetDefaultTexture());
|
//auto texture = SHResourceManager::Get<SHTexture>(comp.GetDefaultTexture());
|
||||||
|
|
||||||
//auto material = renderable->GetModifiableMaterial();
|
auto material = renderable->GetModifiableMaterial();
|
||||||
//material->SetProperty("texture", comp.GetDefaultTexture());
|
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
|
void SHUISystem::UpdateButtonsRoutine::Execute(double dt) noexcept
|
||||||
{
|
{
|
||||||
SHUISystem* system = (SHUISystem*)GetSystem();
|
SHUISystem* system = (SHUISystem*)GetSystem();
|
||||||
|
@ -219,6 +385,34 @@ namespace SHADE
|
||||||
if (SHSceneManager::CheckNodeAndComponentsActive<SHButtonComponent>(comp.GetEID()))
|
if (SHSceneManager::CheckNodeAndComponentsActive<SHButtonComponent>(comp.GetEID()))
|
||||||
system->UpdateButtonComponent(comp);
|
system->UpdateButtonComponent(comp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto& toggleButtonDense = SHComponentManager::GetDense<SHToggleButtonComponent>();
|
||||||
|
for (auto& comp : toggleButtonDense)
|
||||||
|
{
|
||||||
|
if (SHSceneManager::CheckNodeAndComponentsActive<SHToggleButtonComponent>(comp.GetEID()))
|
||||||
|
system->UpdateToggleButtonComponent(comp);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SHVec2 SHUISystem::CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept
|
||||||
|
{
|
||||||
|
SHVec2 result{canvasPoint};
|
||||||
|
|
||||||
|
auto cameraSystem = SHSystemManager::GetSystem<SHCameraSystem>();
|
||||||
|
|
||||||
|
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
|
}//end namespace
|
||||||
|
|
|
@ -3,14 +3,20 @@
|
||||||
#include "SH_API.h"
|
#include "SH_API.h"
|
||||||
#include "ECS_Base/System/SHSystem.h"
|
#include "ECS_Base/System/SHSystem.h"
|
||||||
#include "ECS_Base/System/SHSystemRoutine.h"
|
#include "ECS_Base/System/SHSystemRoutine.h"
|
||||||
#include "SHUIComponent.h"
|
|
||||||
#include "SHButtonComponent.h"
|
|
||||||
#include "SHCanvasComponent.h"
|
|
||||||
#include "Scene/SHSceneGraph.h"
|
#include "Scene/SHSceneGraph.h"
|
||||||
#include "Scene/SHSceneManager.h"
|
#include "Scene/SHSceneManager.h"
|
||||||
|
#include "Math/Vector/SHVec2.h"
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class SHButtonComponent;
|
||||||
|
class SHUIComponent;
|
||||||
|
class SHToggleButtonComponent;
|
||||||
|
class SHSliderComponent;
|
||||||
|
class SHCanvasComponent;
|
||||||
|
|
||||||
class SH_API SHUISystem final: public SHSystem
|
class SH_API SHUISystem final: public SHSystem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -64,8 +70,12 @@ namespace SHADE
|
||||||
private:
|
private:
|
||||||
void UpdateUIComponent(SHUIComponent& comp) noexcept;
|
void UpdateUIComponent(SHUIComponent& comp) noexcept;
|
||||||
void UpdateButtonComponent(SHButtonComponent& comp) noexcept;
|
void UpdateButtonComponent(SHButtonComponent& comp) noexcept;
|
||||||
|
void UpdateToggleButtonComponent(SHToggleButtonComponent& comp) noexcept;
|
||||||
void UpdateCanvasComponent(SHCanvasComponent& comp) noexcept;
|
void UpdateCanvasComponent(SHCanvasComponent& comp) noexcept;
|
||||||
|
|
||||||
|
SHVec2 CanvasToScreenPoint(SHVec2& const canvasPoint, bool normalized) noexcept;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -107,8 +107,7 @@ namespace SHADE
|
||||||
|
|
||||||
Vector3 Transform::Forward::get()
|
Vector3 Transform::Forward::get()
|
||||||
{
|
{
|
||||||
const SHVec3 DIRECTION = SHVec3::Rotate(-SHVec3::UnitZ, Convert::ToNative(GlobalRotation));
|
return Vector3::Rotate(Vector3::Forward, GlobalRotation);
|
||||||
return Convert::ToCLI(DIRECTION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*-----------------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------------*/
|
||||||
|
|
|
@ -44,6 +44,10 @@ namespace SHADE
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
bool Application::IsEditor::get()
|
||||||
|
{
|
||||||
|
return SHSystemManager::GetSystem<SHEditor>() != nullptr;
|
||||||
|
}
|
||||||
int Application::WindowWidth::get()
|
int Application::WindowWidth::get()
|
||||||
{
|
{
|
||||||
return SHGraphicsSystemInterface::GetWindowWidth();
|
return SHGraphicsSystemInterface::GetWindowWidth();
|
||||||
|
@ -66,6 +70,9 @@ namespace SHADE
|
||||||
/*---------------------------------------------------------------------------------*/
|
/*---------------------------------------------------------------------------------*/
|
||||||
void Application::Quit()
|
void Application::Quit()
|
||||||
{
|
{
|
||||||
SHGraphicsSystemInterface::CloseWindow();
|
if (!IsEditor)
|
||||||
|
{
|
||||||
|
SHGraphicsSystemInterface::CloseWindow();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,13 @@ namespace SHADE
|
||||||
bool get();
|
bool get();
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// True if the engine is running in the editor.
|
||||||
|
/// </summary>
|
||||||
|
static property bool IsEditor
|
||||||
|
{
|
||||||
|
bool get();
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
/// Retrieves the designated width of the current window.
|
/// Retrieves the designated width of the current window.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static property int WindowWidth
|
static property int WindowWidth
|
||||||
|
@ -71,6 +78,7 @@ namespace SHADE
|
||||||
/*-----------------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------------*/
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Marks the application to stop at the end of the current frame.
|
/// Marks the application to stop at the end of the current frame.
|
||||||
|
/// If running in the editor, this function does nothing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
static void Quit();
|
static void Quit();
|
||||||
};
|
};
|
||||||
|
|
|
@ -167,6 +167,10 @@ namespace SHADE
|
||||||
{
|
{
|
||||||
return Convert::ToCLI(SHVec3::Rotate(Convert::ToNative(vec), Convert::ToNative(axis), radians));
|
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)
|
Vector3 Vector3::Min(Vector3 lhs, Vector3 rhs)
|
||||||
{
|
{
|
||||||
float lx = lhs.x, rx = rhs.x;
|
float lx = lhs.x, rx = rhs.x;
|
||||||
|
|
|
@ -19,10 +19,17 @@ of DigiPen Institute of Technology is prohibited.
|
||||||
// Project Includes
|
// Project Includes
|
||||||
#include "Vector2.hxx"
|
#include "Vector2.hxx"
|
||||||
|
|
||||||
value struct Quaternion;
|
|
||||||
|
|
||||||
namespace SHADE
|
namespace SHADE
|
||||||
{
|
{
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Forward Declarations */
|
||||||
|
/*-------------------------------------------------------------------------- --- */
|
||||||
|
value struct Quaternion;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------------*/
|
||||||
|
/* Type Definitions */
|
||||||
|
/*-------------------------------------------------------------------------- --- */
|
||||||
|
|
||||||
///<summary>
|
///<summary>
|
||||||
/// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector.
|
/// CLR version of SHADE Engine's Vector3 class that represents a 3-Dimensional Vector.
|
||||||
/// Designed to closely match Unity's Vector3 struct.
|
/// Designed to closely match Unity's Vector3 struct.
|
||||||
|
@ -308,6 +315,12 @@ namespace SHADE
|
||||||
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
/// <returns>The Vector3 that represents the rotated vector.</returns>
|
||||||
static Vector3 Rotate(Vector3 vec, Vector3 axis, float radians);
|
static Vector3 Rotate(Vector3 vec, Vector3 axis, float radians);
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// Rotates a Vector3 using a Quaternion.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="vec">A Vector3 to rotate.</param>
|
||||||
|
/// <param name="quat">A Quaternion to rotate the vector with.</param>
|
||||||
|
static Vector3 Rotate(Vector3 vec, Quaternion quat);
|
||||||
|
/// <summary>
|
||||||
/// Computes and returns a Vector3 that is made from the smallest components of
|
/// Computes and returns a Vector3 that is made from the smallest components of
|
||||||
/// the two specified Vector3s.
|
/// the two specified Vector3s.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in New Issue