// // /*=============================================================================== // // Copyright (C) 2023 PhantomsXR Ltd. All Rights Reserved. // // // // This file is part of the Phantom.XRMOD.UnityFusion.Runtime.CodeHook.Editor. // // // // The PicoPlatform cannot be copied, distributed, or made available to // // third-parties for commercial purposes without written permission of PhantomsXR Ltd. // // // // Contact info@phantomsxr.com for licensing requests. // // ===============================================================================*/ using System; using System.Collections.Generic; using System.Linq; using Phantom.XRMOD.UnityFusion.Runtime.CodeHook; using UnityEditor; using UnityEditorInternal; using UnityEngine; namespace Phantom.XRMOD.Runtime.Editor { public class MonoBinderFieldEditor : UnityEditor.Editor { private Dictionary fieldsReorderableList = new(); private const string _CONST_COMPONENTS_NAME = "Components"; public void EnsureReorderableList(Rect _rect, int _idx, SerializedProperty _fieldsProperty) { var tmp_FieldsReorderList = new ReorderableList(serializedObject, _fieldsProperty, true, true, true, true); fieldsReorderableList.TryAdd(_idx, tmp_FieldsReorderList); tmp_FieldsReorderList.drawElementCallback += (_rect, _index, _active, _focused) => { if (_fieldsProperty.arraySize <= 0) return; var tmp_FieldProperty = _fieldsProperty.GetArrayElementAtIndex(_index); var tmp_ColRect = new Rect(_rect.x, _rect.y, _rect.width, EditorGUIUtility.singleLineHeight); EditorGUI.PropertyField(tmp_ColRect, tmp_FieldProperty.FindPropertyRelative("FieldName")); tmp_ColRect.y += Utilities.MakeSureHeight; EditorGUI.PropertyField(tmp_ColRect, tmp_FieldProperty.FindPropertyRelative("FieldType")); tmp_ColRect.y += Utilities.MakeSureHeight; DrawField(tmp_FieldProperty.FindPropertyRelative("FieldType"), tmp_FieldProperty, tmp_ColRect); }; tmp_FieldsReorderList.drawHeaderCallback += _rect => { }; tmp_FieldsReorderList.elementHeightCallback += _index => { float offsetHeight = 0; SerializedProperty element = _fieldsProperty.GetArrayElementAtIndex(_index); var tmp_EnumIndex = (MonoField.FieldTypeEnum) element.FindPropertyRelative("FieldType").enumValueIndex; switch (tmp_EnumIndex) { case MonoField.FieldTypeEnum.TextureArray: case MonoField.FieldTypeEnum.AudioClipArray: case MonoField.FieldTypeEnum.ShaderArray: case MonoField.FieldTypeEnum.SpriteArray: case MonoField.FieldTypeEnum.MaterialArray: case MonoField.FieldTypeEnum.AnimationClipArray: case MonoField.FieldTypeEnum.VideoClipArray: case MonoField.FieldTypeEnum.MeshArray: case MonoField.FieldTypeEnum.ColorArray: case MonoField.FieldTypeEnum.ScriptableObjectArray: case MonoField.FieldTypeEnum.QuaternionArray: case MonoField.FieldTypeEnum.Vector2Array: case MonoField.FieldTypeEnum.Vector3Array: case MonoField.FieldTypeEnum.Vector4Array: case MonoField.FieldTypeEnum.ScriptableObject: case MonoField.FieldTypeEnum.AnimationCurveArray: case MonoField.FieldTypeEnum.Components: case MonoField.FieldTypeEnum.GameObjectArray: var tmp_Property = element.FindPropertyRelative($"{tmp_EnumIndex}"); if (tmp_Property.isExpanded) { offsetHeight += EditorGUI.GetPropertyHeight(tmp_Property) + tmp_FieldsReorderList.footerHeight; } else { offsetHeight = Utilities.MakeSureHeight * 2; } break; default: offsetHeight = Utilities.MakeSureHeight * 2; break; } return EditorGUI.GetPropertyHeight(element) + offsetHeight; }; tmp_FieldsReorderList.onChangedCallback += _list => { if (_list.count == 0) { fieldsReorderableList.Clear(); _list.serializedProperty.ClearArray(); } }; tmp_FieldsReorderList.onAddCallback += _list => { var tmp_SerializedProperty = _list.serializedProperty; var tmp_InsertIdx = tmp_SerializedProperty.arraySize; tmp_SerializedProperty.InsertArrayElementAtIndex(tmp_InsertIdx); }; tmp_FieldsReorderList.drawHeaderCallback += _rect => { EditorGUI.LabelField(_rect, $"Binding Fields(Count:{_fieldsProperty.arraySize})"); }; } public void DrawLayout(Rect _rect, int _index) { if (fieldsReorderableList.TryGetValue(_index, out var tmp_FieldsReorderList)) tmp_FieldsReorderList.DoList(_rect); } public void RemoveElement(int _index) { if (fieldsReorderableList.ContainsKey(_index)) { fieldsReorderableList[_index] = null; fieldsReorderableList.Remove(_index); } } // internal void Cleanup() // { // fieldsReorderableList.Clear(); // } private void DrawField(SerializedProperty _fieldType, SerializedProperty _property, Rect _fieldRect) { var tmp_FieldType = (MonoField.FieldTypeEnum) _fieldType.enumValueIndex; switch (tmp_FieldType) { case MonoField.FieldTypeEnum.Number: var numberProperty = _property.FindPropertyRelative("Value"); EditorGUI.PropertyField(_fieldRect, numberProperty, new GUIContent("Number Value")); break; case MonoField.FieldTypeEnum.String: var stringProperty = _property.FindPropertyRelative("Value"); EditorGUI.PropertyField(_fieldRect, stringProperty, new GUIContent("String Value")); break; case MonoField.FieldTypeEnum.Bool: var boolProperty = _property.FindPropertyRelative("Value"); Boolean.TryParse(boolProperty.stringValue, out var tmp_BoolValue); boolProperty.stringValue = EditorGUI.Toggle(_fieldRect, "Boolean Value", tmp_BoolValue) .ToString(); break; case MonoField.FieldTypeEnum.Enum: var tmp_EnumProperty = _property.FindPropertyRelative("Value"); EditorGUI.PropertyField(_fieldRect, tmp_EnumProperty, new GUIContent("Enum Value")); break; case MonoField.FieldTypeEnum.LayerMask: var tmp_LayerMaskProperty = _property.FindPropertyRelative("Value"); if (!string.IsNullOrEmpty(tmp_LayerMaskProperty.stringValue)) { var tmp_LayerMaskNames = tmp_LayerMaskProperty.stringValue.Split(","); tmp_LayerMaskNames = tmp_LayerMaskNames.Where(_e => !string.IsNullOrEmpty(_e)).ToArray(); // string[] tmp_Layers = Enumerable.Range(0, 31).Select(LayerMask.LayerToName).ToArray(); var tmp_SelectedIdx = EditorGUI.MaskField(_fieldRect, new GUIContent("LayerMask Value"), InternalEditorUtility.LayerMaskToConcatenatedLayersMask( LayerMask.GetMask(tmp_LayerMaskNames)), InternalEditorUtility.layers); var tmp_AllLayerOfSelected = Utilities.GetLayerNamesFromMask(tmp_SelectedIdx); if (tmp_AllLayerOfSelected.Length != tmp_LayerMaskNames.Length) _property.FindPropertyRelative("Value").stringValue = string.Join(",", tmp_AllLayerOfSelected); } else { var tmp_SelectedIdx = EditorGUI.MaskField(_fieldRect, new GUIContent("LayerMask Value"), 0, InternalEditorUtility.layers); if (tmp_SelectedIdx != 0) { var tmp_AllLayerOfSelected = Utilities.GetLayerNamesFromMask(tmp_SelectedIdx); _property.FindPropertyRelative("Value").stringValue = string.Join(",", tmp_AllLayerOfSelected); } } break; case MonoField.FieldTypeEnum.GameObject: var gameObjectProperty = _property.FindPropertyRelative("GameObject"); EditorGUI.PropertyField(_fieldRect, gameObjectProperty, new GUIContent("GameObject")); break; case MonoField.FieldTypeEnum.UnityComponent: var componentProperty = _property.FindPropertyRelative("GameObject"); // 或者另一个合适的属性 EditorGUI.PropertyField(_fieldRect, componentProperty, new GUIContent("Unity Component")); break; // Components case MonoField.FieldTypeEnum.Components: var tmp_GameObjectsProperty = _property.FindPropertyRelative(_CONST_COMPONENTS_NAME); MakeSureUnityObjectField(_fieldRect, ref tmp_GameObjectsProperty); break; case MonoField.FieldTypeEnum.GameObjectArray: var tmp_GameObjectArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_GameObjectArrayProperty); break; case MonoField.FieldTypeEnum.AssetReferenceArray: var tmp_AssetReferenceArrayProperty = _property.FindPropertyRelative("Value"); EditorGUI.PropertyField(_fieldRect, tmp_AssetReferenceArrayProperty, new GUIContent("Asset Reference Array")); break; case MonoField.FieldTypeEnum.AssetReference: var tmp_AssetReferenceProperty = _property.FindPropertyRelative("Value"); EditorGUI.PropertyField(_fieldRect, tmp_AssetReferenceProperty, new GUIContent("Asset Reference")); break; case MonoField.FieldTypeEnum.Vector2: var tmp_VectorProperty = _property.FindPropertyRelative("Value"); try { if (string.IsNullOrEmpty(tmp_VectorProperty.stringValue)) { tmp_VectorProperty.stringValue = new Vector2(0, 0).Serializer(); } var tmp_CurVec2 = JsonUtility.FromJson(tmp_VectorProperty.stringValue) .ToVector2(); tmp_VectorProperty.stringValue = JsonUtility.ToJson( new SerializableVector2(EditorGUI.Vector2Field(_fieldRect, "Vector2", tmp_CurVec2))); } catch (Exception) { tmp_VectorProperty.stringValue = new Vector2(0, 0).Serializer(); } break; case MonoField.FieldTypeEnum.Vector3: var vector3Property = _property.FindPropertyRelative("Value"); try { if (string.IsNullOrEmpty(vector3Property.stringValue) || vector3Property.stringValue.Split(",").Length != 3) { vector3Property.stringValue = new Vector3(0, 0, 0).Serializer(); } var tmp_CurVec3 = JsonUtility.FromJson(vector3Property.stringValue) .ToVector3(); vector3Property.stringValue = JsonUtility.ToJson( new SerializableVector3(EditorGUI.Vector3Field(_fieldRect, "Vector3", tmp_CurVec3))); } catch (Exception) { vector3Property.stringValue = new Vector3(0, 0, 0).Serializer(); } break; case MonoField.FieldTypeEnum.Vector4: var vector4Property = _property.FindPropertyRelative("Value"); try { if (string.IsNullOrEmpty(vector4Property.stringValue) || vector4Property.stringValue.Split(",").Length != 4) { vector4Property.stringValue = new Vector4(0, 0, 0).Serializer(); } var tmp_CurVec4 = JsonUtility.FromJson(vector4Property.stringValue) .ToVector4(); vector4Property.stringValue = JsonUtility.ToJson( new SerializableVector4(EditorGUI.Vector4Field(_fieldRect, "Vector4", tmp_CurVec4))); } catch (Exception) { vector4Property.stringValue = new Vector4(0, 0, 0).Serializer(); } break; case MonoField.FieldTypeEnum.Quaternion: var q4Property = _property.FindPropertyRelative("Value"); try { if (string.IsNullOrEmpty(q4Property.stringValue) || q4Property.stringValue.Split(",").Length != 4) { q4Property.stringValue = new Quaternion(0, 0, 0, 0).Serializer(); } var tmp_CurQ4 = JsonUtility.FromJson(q4Property.stringValue).ToVector4(); q4Property.stringValue = JsonUtility.ToJson( new SerializableVector4(EditorGUI.Vector4Field(_fieldRect, "Vector4", tmp_CurQ4))); } catch (Exception) { q4Property.stringValue = new Quaternion(0, 0, 0, 0).Serializer(); } break; case MonoField.FieldTypeEnum.Primitives: var primitivesProperty = _property.FindPropertyRelative("Value"); EditorGUI.PropertyField(_fieldRect, primitivesProperty, new GUIContent("Primitive Value")); break; case MonoField.FieldTypeEnum.Color: var colorProperty = _property.FindPropertyRelative("Value"); if (ColorUtility.TryParseHtmlString($"#{colorProperty.stringValue}", out var tmp_Color)) { Color tmp_CachedColor = Color.white; tmp_CachedColor = EditorGUI.ColorField(_fieldRect, tmp_Color); colorProperty.stringValue = ColorUtility.ToHtmlStringRGBA(tmp_CachedColor); } else { EditorGUI.PropertyField(_fieldRect, colorProperty, new GUIContent("Color Value")); } break; case MonoField.FieldTypeEnum.AnimationCurve: try { var tmp_AnimationCurveProperty = _property.FindPropertyRelative("Value"); AnimationCurve tmp_AnimationCurveData = string.IsNullOrEmpty(tmp_AnimationCurveProperty.stringValue) ? new AnimationCurve() : tmp_AnimationCurveProperty.stringValue.DeserializeAnimationCurve(); tmp_AnimationCurveData = EditorGUI.CurveField(_fieldRect, tmp_AnimationCurveData); tmp_AnimationCurveProperty.stringValue = tmp_AnimationCurveData.SerializeAnimationCurve(); } catch (Exception tmp_E) { Debug.LogError(tmp_E); } break; case MonoField.FieldTypeEnum.AnimationCurveArray: var tmp_AnimationCurvesProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_AnimationCurvesProperty); break; case MonoField.FieldTypeEnum.TextureArray: var tmp_TextureArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_TextureArrayProperty); break; case MonoField.FieldTypeEnum.AudioClipArray: var tmp_AudioClipArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_AudioClipArrayProperty); break; case MonoField.FieldTypeEnum.ShaderArray: var tmp_ShaderArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_ShaderArrayProperty); break; case MonoField.FieldTypeEnum.SpriteArray: var tmp_SpriteArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_SpriteArrayProperty); break; case MonoField.FieldTypeEnum.MaterialArray: var tmp_MaterialArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_MaterialArrayProperty); break; case MonoField.FieldTypeEnum.AnimationClipArray: var tmp_AnimationClipArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_AnimationClipArrayProperty); break; case MonoField.FieldTypeEnum.VideoClipArray: var tmp_VideoClipArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_VideoClipArrayProperty); break; case MonoField.FieldTypeEnum.MeshArray: var tmp_MeshArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_MeshArrayProperty); break; case MonoField.FieldTypeEnum.ColorArray: var tmp_ColorArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_ColorArrayProperty); break; case MonoField.FieldTypeEnum.ScriptableObjectArray: var tmp_ScriptableObjectArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_ScriptableObjectArrayProperty); break; case MonoField.FieldTypeEnum.Vector2Array: var tmp_Vector2ArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_Vector2ArrayProperty); break; case MonoField.FieldTypeEnum.Vector3Array: var tmp_Vector3ArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_Vector3ArrayProperty); break; case MonoField.FieldTypeEnum.Vector4Array: var tmp_Vector4ArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_Vector4ArrayProperty); break; case MonoField.FieldTypeEnum.QuaternionArray: var tmp_QuaternionArrayProperty = _property.FindPropertyRelative(tmp_FieldType.ToString()); MakeSureUnityObjectField(_fieldRect, ref tmp_QuaternionArrayProperty); break; default: EditorGUI.HelpBox(_fieldRect, "Type is not supported yet.", MessageType.Warning); break; } } private void MakeSureUnityObjectField(Rect _rect, ref SerializedProperty _unityObjectsProperty) { EditorGUI.indentLevel = 1; EditorGUI.PropertyField(new Rect(_rect.x, _rect.y, _rect.width, EditorGUIUtility.singleLineHeight), _unityObjectsProperty); EditorGUI.indentLevel = 0; } } }