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 84 additions and 24 deletions
Showing only changes of commit d98d00b916 - Show all commits

View File

@ -167,7 +167,7 @@ namespace SHADE
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<int , System::Enum> (field, object, nullptr , &isHovered);
renderFieldInInspector<int , System::Enum >(field, object, nullptr , &isHovered);
if (!MODIFIED_PRIMITIVE)
{
@ -175,22 +175,23 @@ namespace SHADE
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));
RangeAttribute^ rangeAttrib = hasAttribute<RangeAttribute^>(field);
System::Collections::IList^ iList = safe_cast<System::Collections::IList^>(field->GetValue(object));
SHEditorUI::Text(Convert::ToNative(field->Name));
SHEditorUI::SameLine();
SHEditorUI::Button("+");
SHEditorUI::Indent();
int i = 0;
for each (System::Object ^ obj in listEnummerable)
for (int i = 0; i < iList->Count; ++i)
{
int val = safe_cast<int>(obj);
SHEditorUI::InputInt(std::to_string(i), val, &isHovered);
System::Object^ obj = iList[i];
if (renderFieldInInspector(std::to_string(i), obj, rangeAttrib))
{
iList[i] = obj;
}
SHEditorUI::SameLine();
SHEditorUI::Button("-");
++i;
}
SHEditorUI::Unindent();
}
@ -276,6 +277,28 @@ namespace SHADE
}
}
bool Editor::renderFieldInInspector(const std::string& fieldName, System::Object^% object, RangeAttribute^ rangeAttrib)
{
const bool MODIFIED_PRIMITIVE =
renderFieldInInspector<int , Int16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , Int32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , Int64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , UInt16 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , UInt32 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , UInt64 >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<int , Byte >(fieldName, object, SHEditorUI::InputInt , nullptr, rangeAttrib) ||
renderFieldInInspector<bool , bool >(fieldName, object, SHEditorUI::InputCheckbox, nullptr, rangeAttrib) ||
renderFieldInInspector<float , float >(fieldName, object, SHEditorUI::InputFloat , nullptr, rangeAttrib) ||
renderFieldInInspector<double , double >(fieldName, object, SHEditorUI::InputDouble , nullptr, rangeAttrib) ||
renderFieldInInspector<SHVec2 , Vector2 >(fieldName, object, SHEditorUI::InputVec2 , nullptr, rangeAttrib) ||
renderFieldInInspector<SHVec3 , Vector3 >(fieldName, object, SHEditorUI::InputVec3 , nullptr, rangeAttrib) ||
renderFieldInInspector<uint32_t , GameObject >(fieldName, object, nullptr , nullptr, rangeAttrib) ||
renderFieldInInspector<std::string, System::String^>(fieldName, object, nullptr , nullptr, rangeAttrib) ||
renderFieldInInspector<int , System::Enum >(fieldName, object, nullptr , nullptr, rangeAttrib);
return MODIFIED_PRIMITIVE;
}
bool Editor::renderEnumFieldInInspector(const std::string& fieldName, System::Object^% object, bool* isHovered)
{
// Get all the names of the enums

View File

@ -62,7 +62,7 @@ namespace SHADE
if (renderFieldInInspector<NativeType, ManagedType>
(
Convert::ToNative(fieldInfo->Name),
val,
&val,
fieldEditor,
isHovered,
rangeAttrib
@ -78,19 +78,53 @@ namespace SHADE
return false;
}
template<typename NativeType, typename ManagedType>
bool Editor::renderFieldInInspector(const std::string& fieldName, System::Object^% object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib)
{
if constexpr (std::is_same_v<ManagedType, System::Enum>)
{
if (object->GetType()->IsSubclassOf(Enum::typeid))
{
int managedVal = safe_cast<int>(object);
if (renderFieldInInspector<int, int>(fieldName, &managedVal, fieldEditor, isHovered, rangeAttrib))
{
object = managedVal;
}
return true;
}
}
else
{
if (object->GetType() == ManagedType::typeid)
{
ManagedType managedVal = safe_cast<ManagedType>(object);
cli::interior_ptr<ManagedType> managedValPtr = &managedVal;
if (renderFieldInInspector<NativeType, ManagedType>(fieldName, managedValPtr, fieldEditor, isHovered, rangeAttrib))
{
object = managedVal;
return true;
}
return false;
}
}
return false;
}
template<typename NativeType, typename ManagedType>
bool Editor::renderFieldInInspector(const std::string& fieldName, ManagedType% managedVal, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib)
bool Editor::renderFieldInInspector(const std::string& fieldName, interior_ptr<ManagedType> managedValPtr, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib)
{
// Retrieve the native version of the object
NativeType val;
if constexpr (IsPrimitiveTypeMatches_V<NativeType>)
{
val = safe_cast<NativeType>(managedVal);
val = safe_cast<NativeType>(*managedValPtr);
}
else
{
val = Convert::ToNative(managedVal);
val = Convert::ToNative(*managedValPtr);
}
// Throw into the SHEditorUI function
@ -119,12 +153,12 @@ namespace SHADE
{
if constexpr (IsPrimitiveTypeMatches_V<NativeType>)
{
managedVal = val;
*managedValPtr = val;
}
else
{
managedVal = Convert::ToCLI(val);
*managedValPtr = Convert::ToCLI(val);
}
return true;
@ -133,27 +167,27 @@ namespace SHADE
return false;
}
template<>
bool Editor::renderFieldInInspector<std::string, System::String^>(const std::string& fieldName, System::String^% managedVal, EditorFieldFunc<std::string>, bool* isHovered, RangeAttribute^)
bool Editor::renderFieldInInspector<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
if (managedVal == nullptr)
managedVal = "";
if (*managedValPtr == nullptr)
*managedValPtr = "";
// Actual Field
std::string val = Convert::ToNative(managedVal);
std::string val = Convert::ToNative(*managedValPtr);
if (SHEditorUI::InputTextField(fieldName, val, isHovered))
{
managedVal = Convert::ToCLI(val);
*managedValPtr = Convert::ToCLI(val);
return true;
}
return false;
}
template<>
bool Editor::renderFieldInInspector<uint32_t, GameObject>(const std::string& fieldName, GameObject% managedVal, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
bool Editor::renderFieldInInspector<uint32_t, GameObject>(const std::string& fieldName, interior_ptr<GameObject> managedValPtr, EditorFieldFunc<uint32_t>, bool* isHovered, RangeAttribute^)
{
uint32_t entityId = managedVal.GetEntity();
if (SHEditorUI::InputGameObjectField(fieldName, entityId, isHovered, !managedVal))
uint32_t entityId = managedValPtr->GetEntity();
if (SHEditorUI::InputGameObjectField(fieldName, entityId, isHovered, !(*managedValPtr)))
{
GameObject newVal = GameObject(entityId);
if (entityId != MAX_EID)
@ -161,7 +195,7 @@ namespace SHADE
// Null GameObject set
newVal = GameObject(entityId);
}
managedVal = newVal;
*managedValPtr = newVal;
return true;
}

View File

@ -90,6 +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);
static bool renderFieldInInspector(const std::string& fieldName, System::Object^% object, RangeAttribute^ rangeAttrib);
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
@ -126,7 +127,9 @@ namespace SHADE
/// </param>
/// <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);
static bool renderFieldInInspector(const std::string& fieldName, interior_ptr<ManagedType> managedValPtr, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib);
template<typename NativeType, typename ManagedType>
static bool renderFieldInInspector(const std::string& fieldName, System::Object^% object, EditorFieldFunc<NativeType> fieldEditor, bool* isHovered, RangeAttribute^ rangeAttrib);
/// <summary>
/// Renders a context menu when right clicked for the scripts
/// </summary>