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 67 additions and 48 deletions
Showing only changes of commit dfc03839db - Show all commits

View File

@ -153,28 +153,28 @@ namespace SHADE
bool isHovered = false; bool isHovered = false;
const bool MODIFIED_PRIMITIVE = const bool MODIFIED_PRIMITIVE =
renderFieldInInspector<int , Int16 >(field, object, SHEditorUI::InputInt , &isHovered) || renderSpecificField<int , Int16 >(field, object, SHEditorUI::InputInt , &isHovered) ||
renderFieldInInspector<int , Int32 >(field, object, SHEditorUI::InputInt , &isHovered) || renderSpecificField<int , Int32 >(field, object, SHEditorUI::InputInt , &isHovered) ||
renderFieldInInspector<int , Int64 >(field, object, SHEditorUI::InputInt , &isHovered) || renderSpecificField<int , Int64 >(field, object, SHEditorUI::InputInt , &isHovered) ||
renderFieldInInspector<int , UInt16 >(field, object, SHEditorUI::InputInt , &isHovered) || renderSpecificField<int , UInt16 >(field, object, SHEditorUI::InputInt , &isHovered) ||
renderFieldInInspector<int , UInt32 >(field, object, SHEditorUI::InputInt , &isHovered) || renderSpecificField<int , UInt32 >(field, object, SHEditorUI::InputInt , &isHovered) ||
renderFieldInInspector<int , UInt64 >(field, object, SHEditorUI::InputInt , &isHovered) || renderSpecificField<int , UInt64 >(field, object, SHEditorUI::InputInt , &isHovered) ||
renderFieldInInspector<int , Byte >(field, object, SHEditorUI::InputInt , &isHovered) || renderSpecificField<int , Byte >(field, object, SHEditorUI::InputInt , &isHovered) ||
renderFieldInInspector<bool , bool >(field, object, SHEditorUI::InputCheckbox, &isHovered) || renderSpecificField<bool , bool >(field, object, SHEditorUI::InputCheckbox, &isHovered) ||
renderFieldInInspector<float , float >(field, object, SHEditorUI::InputFloat , &isHovered) || renderSpecificField<float , float >(field, object, SHEditorUI::InputFloat , &isHovered) ||
renderFieldInInspector<double , double >(field, object, SHEditorUI::InputDouble , &isHovered) || renderSpecificField<double , double >(field, object, SHEditorUI::InputDouble , &isHovered) ||
renderFieldInInspector<SHVec2 , Vector2 >(field, object, SHEditorUI::InputVec2 , &isHovered) || renderSpecificField<SHVec2 , Vector2 >(field, object, SHEditorUI::InputVec2 , &isHovered) ||
renderFieldInInspector<SHVec3 , Vector3 >(field, object, SHEditorUI::InputVec3 , &isHovered) || renderSpecificField<SHVec3 , Vector3 >(field, object, SHEditorUI::InputVec3 , &isHovered) ||
renderFieldInInspector<uint32_t , GameObject >(field, object, nullptr , &isHovered) || renderSpecificField<uint32_t , GameObject >(field, object, nullptr , &isHovered) ||
renderFieldInInspector<std::string, System::String^>(field, object, nullptr , &isHovered) || renderSpecificField<std::string, System::String^>(field, object, nullptr , &isHovered) ||
renderFieldInInspector<int , System::Enum >(field, object, nullptr , &isHovered); renderSpecificField<int , System::Enum >(field, object, nullptr , &isHovered);
if (!MODIFIED_PRIMITIVE) if (!MODIFIED_PRIMITIVE)
{ {
// Any List // Any List
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::Type^ listType = field->FieldType->GenericTypeArguments[0];
RangeAttribute^ rangeAttrib = hasAttribute<RangeAttribute^>(field); RangeAttribute^ rangeAttrib = hasAttribute<RangeAttribute^>(field);
System::Collections::IList^ iList = safe_cast<System::Collections::IList^>(field->GetValue(object)); System::Collections::IList^ iList = safe_cast<System::Collections::IList^>(field->GetValue(object));
@ -193,7 +193,7 @@ namespace SHADE
SHEditorUI::SameLine(); SHEditorUI::SameLine();
SHEditorUI::Button("-"); SHEditorUI::Button("-");
} }
SHEditorUI::Unindent(); SHEditorUI::Unindent();*/
} }
else else
{ {
@ -277,29 +277,29 @@ namespace SHADE
} }
} }
bool Editor::renderFieldInInspector(const std::string& fieldName, System::Object^% object, RangeAttribute^ rangeAttrib) bool Editor::renderFieldEditor(const std::string& fieldName, System::Object^% object, RangeAttribute^ rangeAttrib)
{ {
const bool MODIFIED_PRIMITIVE = const bool MODIFIED_PRIMITIVE =
renderFieldInInspector<int , Int16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) || renderFieldEditor<int , Int16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , Int32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) || renderFieldEditor<int , Int32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , Int64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) || renderFieldEditor<int , Int64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , UInt16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) || renderFieldEditor<int , UInt16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , UInt32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) || renderFieldEditor<int , UInt32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , UInt64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) || renderFieldEditor<int , UInt64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , Byte >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) || renderFieldEditor<int , Byte >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<bool , bool >(fieldName, object, SHEditorUI::InputCheckbox, nullptr, rangeAttrib) || renderFieldEditor<bool , bool >(fieldName, object, SHEditorUI::InputCheckbox, nullptr, rangeAttrib) ||
renderFieldInInspector<float , float >(fieldName, object, SHEditorUI::InputFloat , nullptr, rangeAttrib) || renderFieldEditor<float , float >(fieldName, object, SHEditorUI::InputFloat , nullptr, rangeAttrib) ||
renderFieldInInspector<double , double >(fieldName, object, SHEditorUI::InputDouble , nullptr, rangeAttrib) || renderFieldEditor<double , double >(fieldName, object, SHEditorUI::InputDouble , nullptr, rangeAttrib) ||
renderFieldInInspector<SHVec2 , Vector2 >(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib) || renderFieldEditor<SHVec2 , Vector2 >(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib) ||
renderFieldInInspector<SHVec3 , Vector3 >(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib) || renderFieldEditor<SHVec3 , Vector3 >(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib) ||
renderFieldInInspector<uint32_t , GameObject >(fieldName, object, nullptr , nullptr, rangeAttrib) || renderFieldEditor<uint32_t , GameObject >(fieldName, object, nullptr , nullptr, rangeAttrib) ||
renderFieldInInspector<std::string, System::String^>(fieldName, object, nullptr , nullptr, rangeAttrib) || renderFieldEditor<std::string, System::String^>(fieldName, object, nullptr , nullptr, rangeAttrib) ||
renderFieldInInspector<int , System::Enum >(fieldName, object, nullptr , nullptr, rangeAttrib); renderFieldEditor<int , System::Enum >(fieldName, object, nullptr , nullptr, rangeAttrib);
return MODIFIED_PRIMITIVE; return MODIFIED_PRIMITIVE;
} }
bool Editor::renderEnumFieldInInspector(const std::string& fieldName, System::Object^% object, bool* isHovered) bool Editor::renderEnumEditor(const std::string& fieldName, System::Object^% object, bool* isHovered)
{ {
// Get all the names of the enums // Get all the names of the enums
const array<String^>^ ENUM_NAMES = object->GetType()->GetEnumNames(); const array<String^>^ ENUM_NAMES = object->GetType()->GetEnumNames();

View File

@ -24,7 +24,7 @@ of DigiPen Institute of Technology is prohibited.
namespace SHADE namespace SHADE
{ {
template<typename NativeType, typename ManagedType> template<typename NativeType, typename ManagedType>
bool Editor::renderFieldInInspector(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered) bool Editor::renderSpecificField(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered)
{ {
if constexpr (std::is_same_v<ManagedType, System::Enum>) if constexpr (std::is_same_v<ManagedType, System::Enum>)
{ {
@ -33,7 +33,7 @@ namespace SHADE
System::Object^ enumObj = fieldInfo->GetValue(object); System::Object^ enumObj = fieldInfo->GetValue(object);
int oldVal = safe_cast<int>(enumObj); int oldVal = safe_cast<int>(enumObj);
int val = oldVal; int val = oldVal;
if (renderEnumFieldInInspector if (renderEnumEditor
( (
Convert::ToNative(fieldInfo->Name), Convert::ToNative(fieldInfo->Name),
enumObj, enumObj,
@ -59,7 +59,7 @@ namespace SHADE
ManagedType oldVal = safe_cast<ManagedType>(fieldInfo->GetValue(object)); ManagedType oldVal = safe_cast<ManagedType>(fieldInfo->GetValue(object));
ManagedType val = oldVal; ManagedType val = oldVal;
if (renderFieldInInspector<NativeType, ManagedType> if (renderFieldEditorInternal<NativeType, ManagedType>
( (
Convert::ToNative(fieldInfo->Name), Convert::ToNative(fieldInfo->Name),
&val, &val,
@ -80,14 +80,14 @@ namespace SHADE
} }
template<typename NativeType, typename ManagedType> template<typename NativeType, typename ManagedType>
bool Editor::renderFieldInInspector(const std::string& fieldName, System::Object^% object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib) bool Editor::renderFieldEditor(const std::string& fieldName, System::Object^% object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib)
{ {
if constexpr (std::is_same_v<ManagedType, System::Enum>) if constexpr (std::is_same_v<ManagedType, System::Enum>)
{ {
if (object->GetType()->IsSubclassOf(Enum::typeid)) if (object->GetType()->IsSubclassOf(Enum::typeid))
{ {
int managedVal = safe_cast<int>(object); int managedVal = safe_cast<int>(object);
if (renderFieldInInspector<int, int>(fieldName, &managedVal, fieldEditor, isHovered, rangeAttrib)) if (renderFieldEditorInternal<int, int>(fieldName, &managedVal, fieldEditor, isHovered, rangeAttrib))
{ {
object = managedVal; object = managedVal;
} }
@ -100,7 +100,7 @@ namespace SHADE
{ {
ManagedType managedVal = safe_cast<ManagedType>(object); ManagedType managedVal = safe_cast<ManagedType>(object);
cli::interior_ptr<ManagedType> managedValPtr = &managedVal; cli::interior_ptr<ManagedType> managedValPtr = &managedVal;
if (renderFieldInInspector<NativeType, ManagedType>(fieldName, managedValPtr, fieldEditor, isHovered, rangeAttrib)) if (renderFieldEditorInternal<NativeType, ManagedType>(fieldName, managedValPtr, fieldEditor, isHovered, rangeAttrib))
{ {
object = managedVal; object = managedVal;
return true; return true;
@ -114,7 +114,7 @@ namespace SHADE
template<typename NativeType, typename ManagedType> template<typename NativeType, typename ManagedType>
bool Editor::renderFieldInInspector(const std::string& fieldName, interior_ptr<ManagedType> managedValPtr, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib) bool Editor::renderFieldEditorInternal(const std::string& fieldName, interior_ptr<ManagedType> managedValPtr, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib)
{ {
// Retrieve the native version of the object // Retrieve the native version of the object
NativeType val; NativeType val;
@ -167,7 +167,7 @@ namespace SHADE
return false; return false;
} }
template<> template<>
bool Editor::renderFieldInInspector<std::string, System::String^>(const std::string& fieldName, interior_ptr<System::String^> managedValPtr, EditorFieldFunc<std::string>, bool* isHovered, RangeAttribute^) bool Editor::renderFieldEditorInternal<std::string, System::String^>(const std::string& fieldName, interior_ptr<System::String^> managedValPtr, EditorFieldFunc<std::string>, bool* isHovered, RangeAttribute^)
{ {
// Prevent issues where String^ is null due to being empty // Prevent issues where String^ is null due to being empty
if (*managedValPtr == nullptr) if (*managedValPtr == nullptr)
@ -184,7 +184,7 @@ namespace SHADE
return false; return false;
} }
template<> template<>
bool Editor::renderFieldInInspector<uint32_t, GameObject>(const std::string& fieldName, interior_ptr<GameObject> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^) bool Editor::renderFieldEditorInternal<uint32_t, GameObject>(const std::string& fieldName, interior_ptr<GameObject> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
{ {
uint32_t entityId = managedValPtr->GetEntity(); uint32_t entityId = managedValPtr->GetEntity();
if (SHEditorUI::InputGameObjectField(fieldName, entityId, isHovered, !(*managedValPtr))) if (SHEditorUI::InputGameObjectField(fieldName, entityId, isHovered, !(*managedValPtr)))

View File

@ -90,8 +90,8 @@ namespace SHADE
/// The object that contains the data of the field to render. /// The object that contains the data of the field to render.
/// </param> /// </param>
static void renderFieldInInspector(System::Reflection::FieldInfo^ field, System::Object^ object); static void renderFieldInInspector(System::Reflection::FieldInfo^ field, System::Object^ object);
static bool renderFieldInInspector(const std::string& fieldName, System::Object^% object, RangeAttribute^ rangeAttrib); static bool renderFieldEditor(const std::string& fieldName, System::Object^% object, RangeAttribute^ rangeAttrib);
static bool renderEnumFieldInInspector(const std::string& fieldName, System::Object^% object, bool* isHovered); static bool renderEnumEditor(const std::string& fieldName, System::Object^% object, bool* isHovered);
/// <summary> /// <summary>
/// Checks if the specified field is of the specified native and managed type /// 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 /// equivalent and renders a ImGui field editor based on the specified field
@ -107,7 +107,7 @@ namespace SHADE
/// </param> /// </param>
/// <returns>True if the field is modified.</returns> /// <returns>True if the field is modified.</returns>
template<typename NativeType, typename ManagedType> template<typename NativeType, typename ManagedType>
static bool renderFieldInInspector(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered); static bool renderSpecificField(System::Reflection::FieldInfo^ fieldInfo, System::Object^ object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered);
/// <summary> /// <summary>
/// Renders a ImGui field editor based on the type of parameters specified. /// Renders a ImGui field editor based on the type of parameters specified.
/// </summary> /// </summary>
@ -127,9 +127,28 @@ namespace SHADE
/// </param> /// </param>
/// <returns>True if the field is modified.</returns> /// <returns>True if the field is modified.</returns>
template<typename NativeType, typename ManagedType> template<typename NativeType, typename ManagedType>
static bool renderFieldInInspector(const std::string& fieldName, interior_ptr<ManagedType> managedValPtr, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib); static bool renderFieldEditorInternal(const std::string& fieldName, interior_ptr<ManagedType> managedValPtr, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib);
/// <summary>
/// Renders a ImGui field editor based on the type of parameters specified.
/// </summary>
/// <typeparam name="NativeType">Native type of the field.</typeparam>
/// <typeparam name="ManagedType">Managed type of the field.</typeparam>
/// <param name="fieldName">Label to use for the field editor.</param>
/// <param name="managedVal">
/// Tracking reference for the managed variable to modify.
/// </param>
/// <param name="fieldEditor">ImGui field editor function to use.</param>
/// <param name="isHovered">
/// Pointer to a bool that stores if the field editor was hovered over.
/// </param>
/// <param name="rangeAttrib">
/// If provided and the type supports it, the field will be rendered with a
/// slider instead.
/// </param>
/// <returns>True if the field is modified.</returns>
template<typename NativeType, typename ManagedType> template<typename NativeType, typename ManagedType>
static bool renderFieldInInspector(const std::string& fieldName, System::Object^% object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib); static bool renderFieldEditor(const std::string& fieldName, System::Object^% object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib);
/// <summary> /// <summary>
/// Renders a context menu when right clicked for the scripts /// Renders a context menu when right clicked for the scripts
/// </summary> /// </summary>