List Serialization and Editor for Scripts #193

Merged
Pycorax merged 21 commits from SP3-6-ArraySerialization into main 2022-11-13 11:58:06 +08:00
3 changed files with 94 additions and 63 deletions
Showing only changes of commit 5d2aae3561 - Show all commits

View File

@ -30,6 +30,7 @@ of DigiPen Institute of Technology is prohibited.
#include "RangeAttribute.hxx"
#include "Math/Vector2.hxx"
#include "Math/Vector3.hxx"
#include <string>
// Using Directives
using namespace System;
@ -146,6 +147,7 @@ namespace SHADE
}
SHEditorUI::PopID();
}
void Editor::renderFieldInInspector(Reflection::FieldInfo^ field, System::Object^ object)
{
bool isHovered = false;
@ -164,30 +166,13 @@ namespace SHADE
renderFieldInInspector<SHVec2 , Vector2 >(field, object, SHEditorUI::InputVec2 , &isHovered) ||
renderFieldInInspector<SHVec3 , Vector3 >(field, object, SHEditorUI::InputVec3 , &isHovered) ||
renderFieldInInspector<uint32_t , GameObject >(field, object, nullptr , &isHovered) ||
renderFieldInInspector<std::string, System::String^>(field, object, nullptr , &isHovered);
renderFieldInInspector<std::string, System::String^>(field, object, nullptr , &isHovered) ||
renderFieldInInspector<int , System::Enum> (field, object, nullptr , &isHovered);
if (!MODIFIED_PRIMITIVE)
{
if (field->FieldType->IsSubclassOf(Enum::typeid))
{
// Get all the names of the enums
const array<String^>^ ENUM_NAMES = field->FieldType->GetEnumNames();
std::vector<std::string> nativeEnumNames;
for each (String ^ str in ENUM_NAMES)
{
nativeEnumNames.emplace_back(Convert::ToNative(str));
}
int val = safe_cast<int>(field->GetValue(object));
int oldVal = val;
if (SHEditorUI::InputEnumCombo(Convert::ToNative(field->Name), val, nativeEnumNames, &isHovered))
{
field->SetValue(object, val);
registerUndoAction(object, field, val, oldVal);
}
}
// Any List
else if (field->FieldType->IsGenericType && field->FieldType->GetGenericTypeDefinition() == System::Collections::Generic::List<int>::typeid->GetGenericTypeDefinition())
if (field->FieldType->IsGenericType && field->FieldType->GetGenericTypeDefinition() == System::Collections::Generic::List<int>::typeid->GetGenericTypeDefinition())
{
System::Type^ listType = field->FieldType->GenericTypeArguments[0];
System::Collections::IEnumerable^ listEnummerable = safe_cast<System::Collections::IEnumerable^>(field->GetValue(object));
@ -291,6 +276,27 @@ namespace SHADE
}
}
bool Editor::renderEnumFieldInInspector(const std::string& fieldName, System::Object^% object, bool* isHovered)
{
// Get all the names of the enums
const array<String^>^ ENUM_NAMES = object->GetType()->GetEnumNames();
std::vector<std::string> nativeEnumNames;
for each (String ^ str in ENUM_NAMES)
{
nativeEnumNames.emplace_back(Convert::ToNative(str));
}
int val = safe_cast<int>(object);
int oldVal = val;
if (SHEditorUI::InputEnumCombo(fieldName, val, nativeEnumNames, isHovered))
{
object = val;
return true;
}
return false;
}
void Editor::renderScriptContextMenu(Entity entity, Script^ script)
{
// Right Click Menu

View File

@ -26,30 +26,54 @@ namespace SHADE
template<typename NativeType, typename ManagedType>
bool Editor::renderFieldInInspector(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered)
{
if (fieldInfo->FieldType == ManagedType::typeid)
if constexpr (std::is_same_v<ManagedType, System::Enum>)
{
RangeAttribute^ rangeAttrib;
if constexpr (std::is_arithmetic_v<NativeType> && !std::is_same_v<NativeType, bool>)
if (fieldInfo->FieldType->IsSubclassOf(Enum::typeid))
{
rangeAttrib = hasAttribute<RangeAttribute^>(fieldInfo);
}
System::Object^ enumObj = fieldInfo->GetValue(object);
int oldVal = safe_cast<int>(enumObj);
int val = oldVal;
if (renderEnumFieldInInspector
(
Convert::ToNative(fieldInfo->Name),
enumObj,
isHovered
))
{
fieldInfo->SetValue(object, safe_cast<int>(enumObj));
registerUndoAction(object, fieldInfo, fieldInfo->GetValue(object), oldVal);
}
ManagedType oldVal = safe_cast<ManagedType>(fieldInfo->GetValue(object));
ManagedType val = oldVal;
if (renderFieldInInspector<NativeType, ManagedType>
(
Convert::ToNative(fieldInfo->Name),
val,
fieldEditor,
isHovered,
rangeAttrib
))
{
fieldInfo->SetValue(object, val);
registerUndoAction(object, fieldInfo, fieldInfo->GetValue(object), oldVal);
return true;
}
}
else
{
if (fieldInfo->FieldType == ManagedType::typeid)
{
RangeAttribute^ rangeAttrib;
if constexpr (std::is_arithmetic_v<NativeType> && !std::is_same_v<NativeType, bool>)
{
rangeAttrib = hasAttribute<RangeAttribute^>(fieldInfo);
}
ManagedType oldVal = safe_cast<ManagedType>(fieldInfo->GetValue(object));
ManagedType val = oldVal;
if (renderFieldInInspector<NativeType, ManagedType>
(
Convert::ToNative(fieldInfo->Name),
val,
fieldEditor,
isHovered,
rangeAttrib
))
{
fieldInfo->SetValue(object, val);
registerUndoAction(object, fieldInfo, fieldInfo->GetValue(object), oldVal);
}
return true;
}
return true;
}
return false;

View File

@ -90,29 +90,7 @@ namespace SHADE
/// The object that contains the data of the field to render.
/// </param>
static void renderFieldInInspector(System::Reflection::FieldInfo^ field, System::Object^ object);
/// <summary>
/// Renders a context menu when right clicked for the scripts
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
/// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script);
/// <summary>
/// Adds changes to a variable as an undo-able/redo-able action on the Undo-Redo
/// stack.
/// </summary>
/// <param name="object">The object that changes are applied to.</param>
/// <param name="field">The field that was changed.</param>
/// <param name="newData">New data to set.</param>
/// <param name="oldData">Data that was overriden.</param>
static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
/// <summary>
/// Checks if a specific field has the specified attribute
/// </summary>
/// <typeparam name="Attribute">Type of Attribute to check for.</typeparam>
/// <param name="field">The field to check.</param>
/// <returns>The attribute to check for if it exists. Null otherwise.</returns>
generic<typename Attribute> where Attribute : System::Attribute
static Attribute hasAttribute(System::Reflection::FieldInfo^ field);
static bool renderEnumFieldInInspector(const std::string& fieldName, System::Object^% object, bool* isHovered);
/// <summary>
/// Checks if the specified field is of the specified native and managed type
/// equivalent and renders a ImGui field editor based on the specified field
@ -149,6 +127,29 @@ namespace SHADE
/// <returns>True if the field is modified.</returns>
template<typename NativeType, typename ManagedType>
static bool renderFieldInInspector(const std::string& fieldName, ManagedType% managedVal, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib);
/// <summary>
/// Renders a context menu when right clicked for the scripts
/// </summary>
/// <param name="entity">The Entity to render the Scripts of.</param>
/// <param name="script">The Script to render the inspector for.</param>
static void renderScriptContextMenu(Entity entity, Script^ script);
/// <summary>
/// Adds changes to a variable as an undo-able/redo-able action on the Undo-Redo
/// stack.
/// </summary>
/// <param name="object">The object that changes are applied to.</param>
/// <param name="field">The field that was changed.</param>
/// <param name="newData">New data to set.</param>
/// <param name="oldData">Data that was overriden.</param>
static void registerUndoAction(System::Object^ object, System::Reflection::FieldInfo^ field, System::Object^ newData, System::Object^ oldData);
/// <summary>
/// Checks if a specific field has the specified attribute
/// </summary>
/// <typeparam name="Attribute">Type of Attribute to check for.</typeparam>
/// <param name="field">The field to check.</param>
/// <returns>The attribute to check for if it exists. Null otherwise.</returns>
generic<typename Attribute> where Attribute : System::Attribute
static Attribute hasAttribute(System::Reflection::FieldInfo^ field);
};
}
#include "Editor.h++"