Merge remote-tracking branch 'origin/main' into SP3-1-Rendering

This commit is contained in:
Brandon Mak 2022-10-02 03:09:25 +08:00
commit 3f334da934
10 changed files with 290 additions and 33 deletions

View File

@ -5,9 +5,13 @@
//#==============================================================# //#==============================================================#
#include <functional> #include <functional>
#include "SH_API.h"
#include "Scripting/SHScriptEngine.h"
#include "ECS_Base/Managers/SHSystemManager.h"
namespace SHADE namespace SHADE
{ {
class SHBaseCommand class SH_API SHBaseCommand
{ {
public: public:
virtual ~SHBaseCommand() = default; virtual ~SHBaseCommand() = default;
@ -48,4 +52,20 @@ namespace SHADE
T newValue; T newValue;
SetterFunction set; SetterFunction set;
}; };
class SH_API SHCLICommand : SHBaseCommand
{
public:
SHCLICommand() = default;
void Execute() override
{
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->RedoScriptInspectorChanges();
}
void Undo() override
{
SHScriptEngine* scriptEngine = static_cast<SHScriptEngine*>(SHSystemManager::GetSystem<SHScriptEngine>());
scriptEngine->UndoScriptInspectorChanges();
}
};
}//namespace SHADE }//namespace SHADE

View File

@ -27,6 +27,11 @@ namespace SHADE
} }
} }
void SHCommandManager::RegisterCommand(CommandPtr commandPtr)
{
undoStack.push(commandPtr);
}
void SHCommandManager::UndoCommand() void SHCommandManager::UndoCommand()
{ {
if (undoStack.empty()) if (undoStack.empty())

View File

@ -9,10 +9,11 @@
//|| SHADE Includes || //|| SHADE Includes ||
//#==============================================================# //#==============================================================#
#include "SHCommand.hpp" #include "SHCommand.hpp"
#include "SH_API.h"
namespace SHADE namespace SHADE
{ {
class SHCommandManager class SH_API SHCommandManager
{ {
public: public:
//#==============================================================# //#==============================================================#
@ -22,6 +23,7 @@ namespace SHADE
using CommandStack = std::stack<CommandPtr>; using CommandStack = std::stack<CommandPtr>;
static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false); static void PerformCommand(CommandPtr commandPtr, bool const& overrideValue = false);
static void RegisterCommand(CommandPtr commandPtr);
static void UndoCommand(); static void UndoCommand();
static void RedoCommand(); static void RedoCommand();
static std::size_t GetUndoStackSize(); static std::size_t GetUndoStackSize();

View File

@ -153,6 +153,16 @@ namespace SHADE
csEditorRenderScripts(entity); csEditorRenderScripts(entity);
} }
void SHScriptEngine::UndoScriptInspectorChanges() const
{
csEditorUndo();
}
void SHScriptEngine::RedoScriptInspectorChanges() const
{
csEditorRedo();
}
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
/* Static Utility Functions */ /* Static Utility Functions */
/*-----------------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------------*/
@ -400,6 +410,18 @@ namespace SHADE
DEFAULT_CSHARP_NAMESPACE + ".Editor", DEFAULT_CSHARP_NAMESPACE + ".Editor",
"RenderScriptsInInspector" "RenderScriptsInInspector"
); );
csEditorUndo = dotNet.GetFunctionPtr<CsFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".Editor",
"Undo"
);
csEditorRedo = dotNet.GetFunctionPtr<CsFuncPtr>
(
DEFAULT_CSHARP_LIB_NAME,
DEFAULT_CSHARP_NAMESPACE + ".Editor",
"Redo"
);
} }
void SHScriptEngine::registerEvents() void SHScriptEngine::registerEvents()

View File

@ -171,6 +171,14 @@ namespace SHADE
/// </summary> /// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param> /// <param name="entity">The Entity to render the Scripts of.</param>
void RenderScriptsInInspector(EntityID entity) const; void RenderScriptsInInspector(EntityID entity) const;
/// <summary>
/// Performs an undo for script inspector changes if it exists.
/// </summary>
void UndoScriptInspectorChanges() const;
/// <summary>
/// Performs a redo for script inspector changes if it exists.
/// </summary>
void RedoScriptInspectorChanges() const;
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Static Utility Functions */ /* Static Utility Functions */
@ -243,9 +251,8 @@ namespace SHADE
CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr; CsScriptSerialiseYamlFuncPtr csScriptDeserialiseYaml = nullptr;
// - Editor // - Editor
CsScriptEditorFuncPtr csEditorRenderScripts = nullptr; CsScriptEditorFuncPtr csEditorRenderScripts = nullptr;
// Delegates CsFuncPtr csEditorUndo = nullptr;
/*ECS::EntityEvent::Delegate onEntityCreate; CsFuncPtr csEditorRedo = nullptr;
ECS::EntityEvent::Delegate onEntityDestroy;*/
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Event Handler Functions */ /* Event Handler Functions */

View File

@ -31,6 +31,7 @@ project "SHADE_Managed"
"%{IncludeDir.imnodes}", "%{IncludeDir.imnodes}",
"%{IncludeDir.yamlcpp}", "%{IncludeDir.yamlcpp}",
"%{IncludeDir.RTTR}/include", "%{IncludeDir.RTTR}/include",
"%{IncludeDir.dotnet}\\include",
"%{wks.location}/SHADE_Engine/src" "%{wks.location}/SHADE_Engine/src"
} }

View File

@ -3,7 +3,7 @@
\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 27, 2022 \date Sep 27, 2022
\brief Contains the definition of the functions for the ScriptStore managed \brief Contains the definition of the functions for the Editor managed
static class. static class.
Note: This file is written in C++17/CLI. Note: This file is written in C++17/CLI.
@ -16,6 +16,8 @@ of DigiPen Institute of Technology is prohibited.
#include "SHpch.h" #include "SHpch.h"
// Primary Header // Primary Header
#include "Editor/Editor.hxx" #include "Editor/Editor.hxx"
// STL Includes
#include <memory>
// External Dependencies // External Dependencies
#include "Editor/SHEditorUI.h" #include "Editor/SHEditorUI.h"
// Project Headers // Project Headers
@ -25,6 +27,8 @@ of DigiPen Institute of Technology is prohibited.
#include "Utility/Debug.hxx" #include "Utility/Debug.hxx"
#include "Serialisation/ReflectionUtilities.hxx" #include "Serialisation/ReflectionUtilities.hxx"
#include "Editor/IconsMaterialDesign.h" #include "Editor/IconsMaterialDesign.h"
#include "Editor/Command/SHCommandManager.h"
#include "Editor/Command/SHCommand.hpp"
// Using Directives // Using Directives
using namespace System; using namespace System;
@ -48,9 +52,11 @@ using namespace System::Collections::Generic;
(field->FieldType == MANAGED_TYPE::typeid) \ (field->FieldType == MANAGED_TYPE::typeid) \
{ \ { \
NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \ NATIVE_TYPE val = safe_cast<NATIVE_TYPE>(field->GetValue(object)); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \ if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \ { \
field->SetValue(object, val); \ field->SetValue(object, val); \
registerUndoAction(object, field, val, oldVal); \
} \ } \
} \ } \
/// <summary> /// <summary>
@ -69,9 +75,11 @@ using namespace System::Collections::Generic;
(field->FieldType == MANAGED_TYPE::typeid) \ (field->FieldType == MANAGED_TYPE::typeid) \
{ \ { \
NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \ NATIVE_TYPE val = Convert::ToNative(safe_cast<MANAGED_TYPE>(field->GetValue(object))); \
NATIVE_TYPE oldVal = val; \
if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \ if (SHEditorUI::FUNC(Convert::ToNative(field->Name), val)) \
{ \ { \
field->SetValue(object, Convert::ToCLI(val)); \ field->SetValue(object, Convert::ToCLI(val)); \
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal)); \
} \ } \
} \ } \
@ -105,26 +113,43 @@ namespace SHADE
SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.RenderScriptsInInspector") SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.RenderScriptsInInspector")
} }
void Editor::RenderScriptAddButton(Entity entity) void Editor::RenderScriptAddButton(Entity entity)
{ {
// Get list of Scripts // Get list of Scripts
auto scriptTypes = ScriptStore::GetAvailableScriptList(); auto scriptTypes = ScriptStore::GetAvailableScriptList();
// Define pop up // Define pop up
if (SHEditorUI::BeginMenu("Add Script", ICON_MD_LIBRARY_ADD)) if (SHEditorUI::BeginMenu("Add Script", ICON_MD_LIBRARY_ADD))
{ {
for each (Type ^ type in scriptTypes) for each (Type ^ type in scriptTypes)
{ {
if (SHEditorUI::Selectable(Convert::ToNative(type->Name))) if (SHEditorUI::Selectable(Convert::ToNative(type->Name)))
{ {
// Add the script // Add the script
ScriptStore::AddScriptViaName(entity, type->Name); ScriptStore::AddScriptViaName(entity, type->Name);
} }
} }
SHEditorUI::EndMenu(); SHEditorUI::EndMenu();
} }
} }
/*---------------------------------------------------------------------------------*/
/* UndoRedoStack Functions */
/*---------------------------------------------------------------------------------*/
void Editor::Undo()
{
SAFE_NATIVE_CALL_BEGIN
actionStack.Undo();
SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.Undo")
}
void Editor::Redo()
{
SAFE_NATIVE_CALL_BEGIN
actionStack.Redo();
SAFE_NATIVE_CALL_END_N("SHADE_Managed.Editor.Redo")
}
/*---------------------------------------------------------------------------------*/ /*---------------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
@ -192,9 +217,11 @@ namespace SHADE
} }
int val = safe_cast<int>(field->GetValue(object)); int val = safe_cast<int>(field->GetValue(object));
int oldVal = val;
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames)) if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames))
{ {
field->SetValue(object, val); field->SetValue(object, val);
registerUndoAction(object, field, val, oldVal);
} }
} }
else if RENDER_FIELD_CASTED(Vector2, SHVec2, InputVec2) else if RENDER_FIELD_CASTED(Vector2, SHVec2, InputVec2)
@ -210,9 +237,11 @@ namespace SHADE
// Actual Field // Actual Field
std::string val = Convert::ToNative(stringVal); std::string val = Convert::ToNative(stringVal);
std::string oldVal = val;
if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val)) if (SHEditorUI::InputTextField(Convert::ToNative(field->Name), val))
{ {
field->SetValue(object, Convert::ToCLI(val)); field->SetValue(object, Convert::ToCLI(val));
registerUndoAction(object, field, Convert::ToCLI(val), Convert::ToCLI(oldVal));
} }
} }
} }
@ -231,4 +260,18 @@ namespace SHADE
} }
} }
void Editor::registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData)
{
// Create command and add it into the undo stack
UndoRedoStack::Command cmd;
cmd.Field = field;
cmd.Object = object;
cmd.NewData = newData;
cmd.OldData = oldData;
actionStack.Add(cmd);
// Inform the C++ Undo-Redo stack
SHCommandManager::RegisterCommand(std::reinterpret_pointer_cast<SHBaseCommand>(std::make_shared<SHCLICommand>()));
}
} }

View File

@ -16,6 +16,7 @@ of DigiPen Institute of Technology is prohibited.
// Project Includes // Project Includes
#include "Engine/Entity.hxx" #include "Engine/Entity.hxx"
#include "Scripts/Script.hxx" #include "Scripts/Script.hxx"
#include "UndoRedoStack.hxx"
namespace SHADE namespace SHADE
{ {
@ -36,15 +37,26 @@ namespace SHADE
/// rendering code. /// rendering code.
/// </summary> /// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param> /// <param name="entity">The Entity to render the Scripts of.</param>
static void RenderScriptsInInspector(Entity entity); static void RenderScriptsInInspector(Entity entity);
/// <summary> /// <summary>
/// Renders a dropdown button that allows for the addition of PlushieScripts /// Renders a dropdown button that allows for the addition of PlushieScripts
/// onto the specified Entity. /// onto the specified Entity.
/// </summary> /// </summary>
/// <param name="entity">The Entity to add PlushieScripts to.</param> /// <param name="entity">The Entity to add PlushieScripts to.</param>
static void RenderScriptAddButton(Entity entity); static void RenderScriptAddButton(Entity entity);
/*-----------------------------------------------------------------------------*/
/* UndoRedoStack Functions */
/*-----------------------------------------------------------------------------*/
static void Undo();
static void Redo();
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
static UndoRedoStack actionStack;
private:
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
/* Helper Functions */ /* Helper Functions */
/*-----------------------------------------------------------------------------*/ /*-----------------------------------------------------------------------------*/
@ -73,5 +85,6 @@ namespace SHADE
/// <param name="entity">The Entity to render the Scripts of.</param> /// <param name="entity">The Entity to render the Scripts of.</param>
/// <param name="script">The Script to render the inspector for.</param> /// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script); static void renderScriptContextMenu(Entity entity, Script^ script);
static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
}; };
} }

View File

@ -0,0 +1,69 @@
/************************************************************************************//*!
\file UndoRedoStack.cxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 29, 2022
\brief Contains the definition of the functions for the UndoRedoStack managed
class.
Note: This file is written in C++17/CLI.
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 "UndoRedoStack.hxx"
// External Dependencies
#include "Editor/SHEditorUI.h"
// Project Headers
namespace SHADE
{
bool UndoRedoStack::UndoActionPresent::get()
{
return commandStack->Count > 0 && latestActionIndex >= 0;
}
bool UndoRedoStack::RedoActionPresent::get()
{
return latestActionIndex >= 0 && latestActionIndex < commandStack->Count - 1;
}
void UndoRedoStack::Add(Command command)
{
// Erase any other actions ahead of the current action
if (latestActionIndex >= 0 && latestActionIndex < commandStack->Count - 1)
{
commandStack->RemoveRange(latestActionIndex, commandStack->Count - latestActionIndex);
}
// Add the command
commandStack->Add(command);
// Set the latest command
latestActionIndex = commandStack->Count - 1;
}
void UndoRedoStack::Undo()
{
if (!UndoActionPresent)
return;
Command cmd = commandStack[latestActionIndex];
cmd.Field->SetValue(cmd.Object, cmd.OldData);
--latestActionIndex;
}
void UndoRedoStack::Redo()
{
if (!RedoActionPresent)
return;
Command cmd = commandStack[latestActionIndex];
cmd.Field->SetValue(cmd.Object, cmd.NewData);
++latestActionIndex;
}
}

View File

@ -0,0 +1,75 @@
/************************************************************************************//*!
\file UndoRedoStack.hxx
\author Tng Kah Wei, kahwei.tng, 390009620
\par email: kahwei.tng\@digipen.edu
\date Sep 29, 2022
\brief Contains the definition of the managed UndoRedoStack class.
Note: This file is written in C++17/CLI.
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.
*//*************************************************************************************/
#pragma once
namespace SHADE
{
/// <summary>
/// Class that is able to store a stack of actions that can be done and redone.
/// </summary>
private ref class UndoRedoStack sealed
{
public:
/*-----------------------------------------------------------------------------*/
/* Type Definitions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Command for the stack that represents a data modification.
/// </summary>
value struct Command
{
public:
System::Object^ Object;
System::Reflection::FieldInfo^ Field;
System::Object^ NewData;
System::Object^ OldData;
};
/*-----------------------------------------------------------------------------*/
/* Properties */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// True if there is an undoable action in the stack.
/// </summary>
property bool UndoActionPresent { bool get(); }
/// <summary>
/// True if there is a redoable action in the stack.
/// </summary>
property bool RedoActionPresent { bool get(); }
/*-----------------------------------------------------------------------------*/
/* Usage Functions */
/*-----------------------------------------------------------------------------*/
/// <summary>
/// Adds a command onto the stack.
/// </summary>
/// <param name="command"></param>
void Add(Command command);
/// <summary>
/// Undos the last added command if it exists.
/// </summary>
void Undo();
/// <summary>
/// Redoes the last undo-ed command if it exists.
/// </summary>
void Redo();
private:
/*-----------------------------------------------------------------------------*/
/* Data Members */
/*-----------------------------------------------------------------------------*/
int latestActionIndex = -1;
System::Collections::Generic::List<Command>^ commandStack = gcnew System::Collections::Generic::List<Command>();
};
}