├── .codacy.yml ├── .gitattributes ├── .gitignore ├── Demo.meta ├── Demo ├── Demo.unitypackage ├── Demo.unitypackage.meta ├── Demo1.PNG ├── Demo1.PNG.meta ├── Demo2.PNG ├── Demo2.PNG.meta ├── Demo3.PNG └── Demo3.PNG.meta ├── Editor.meta ├── Editor ├── BindingDataContextInfoDrawer.cs ├── BindingDataContextInfoDrawer.cs.meta ├── BindingEditor.cs ├── BindingEditor.cs.meta ├── com.gameframe.bindings.Editor.asmdef └── com.gameframe.bindings.Editor.asmdef.meta ├── LICENSE.md ├── LICENSE.md.meta ├── README.md ├── README.md.meta ├── Runtime.meta ├── Runtime ├── BindableMonoBehaviour.cs ├── BindableMonoBehaviour.cs.meta ├── BindableScriptableObject.cs ├── BindableScriptableObject.cs.meta ├── Binding.cs ├── Binding.cs.meta ├── BindingBehaviour.cs ├── BindingBehaviour.cs.meta ├── BindingDataContextInfo.cs ├── BindingDataContextInfo.cs.meta ├── ComponentBinding.cs ├── ComponentBinding.cs.meta ├── GameObjectSetActiveBinding.cs ├── GameObjectSetActiveBinding.cs.meta ├── TextBinding.cs ├── TextBinding.cs.meta ├── com.gameframe.bindings.asmdef ├── com.gameframe.bindings.asmdef.meta ├── csc.rsp └── csc.rsp.meta ├── Tests.meta ├── Tests ├── Editor.meta ├── Editor │ ├── BindingsEditorTests.cs │ ├── BindingsEditorTests.cs.meta │ ├── com.gameframe.bindings.Editor.Tests.asmdef │ └── com.gameframe.bindings.Editor.Tests.asmdef.meta ├── Runtime.meta └── Runtime │ ├── BindingsRuntimeTests.cs │ ├── BindingsRuntimeTests.cs.meta │ ├── com.gameframe.bindings.Tests.asmdef │ └── com.gameframe.bindings.Tests.asmdef.meta ├── package.json └── package.json.meta /.codacy.yml: -------------------------------------------------------------------------------- 1 | exclude_paths: 2 | - '*.md' 3 | - 'Tests/Editor/*.cs' 4 | - 'Tests/Runtime/*.cs' -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # This .gitignore file should be placed at the root of your Unity project directory 2 | # 3 | # Get latest from https://github.com/github/gitignore/blob/master/Unity.gitignore 4 | # 5 | /[Ll]ibrary/ 6 | /[Tt]emp/ 7 | /[Oo]bj/ 8 | /[Bb]uild/ 9 | /[Bb]uilds/ 10 | /[Ll]ogs/ 11 | /[Mm]emoryCaptures/ 12 | 13 | # Never ignore Asset meta data 14 | !/[Aa]ssets/**/*.meta 15 | 16 | # Uncomment this line if you wish to ignore the asset store tools plugin 17 | # /[Aa]ssets/AssetStoreTools* 18 | 19 | # TextMesh Pro files 20 | [Aa]ssets/TextMesh*Pro/ 21 | 22 | # Autogenerated Jetbrains Rider plugin 23 | [Aa]ssets/Plugins/Editor/JetBrains* 24 | 25 | # Visual Studio cache directory 26 | .vs/ 27 | 28 | # Gradle cache directory 29 | .gradle/ 30 | 31 | # Autogenerated VS/MD/Consulo solution and project files 32 | ExportedObj/ 33 | .consulo/ 34 | *.csproj 35 | *.unityproj 36 | *.sln 37 | *.suo 38 | *.tmp 39 | *.user 40 | *.userprefs 41 | *.pidb 42 | *.booproj 43 | *.svd 44 | *.pdb 45 | *.mdb 46 | *.opendb 47 | *.VC.db 48 | 49 | # Unity3D generated meta files 50 | *.pidb.meta 51 | *.pdb.meta 52 | *.mdb.meta 53 | 54 | # Unity3D generated file on crash reports 55 | sysinfo.txt 56 | 57 | # Builds 58 | *.apk 59 | *.unitypackage 60 | 61 | # Crashlytics generated file 62 | crashlytics-build.properties 63 | 64 | -------------------------------------------------------------------------------- /Demo.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ab05f9ab0624b254b85b9415fd7b590d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Demo/Demo.unitypackage: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coryleach/UnityBindings/4d9e0fbc43dd520a832c0e9c53866d73e9cea4e4/Demo/Demo.unitypackage -------------------------------------------------------------------------------- /Demo/Demo.unitypackage.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2626fa5cafb410d4cab580c6f9e2ed35 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Demo/Demo1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coryleach/UnityBindings/4d9e0fbc43dd520a832c0e9c53866d73e9cea4e4/Demo/Demo1.PNG -------------------------------------------------------------------------------- /Demo/Demo1.PNG.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3994c1b487d13b948a601351708ee6c2 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Demo/Demo2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coryleach/UnityBindings/4d9e0fbc43dd520a832c0e9c53866d73e9cea4e4/Demo/Demo2.PNG -------------------------------------------------------------------------------- /Demo/Demo2.PNG.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 12541e59284eec84488c0723e60297c0 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Demo/Demo3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/coryleach/UnityBindings/4d9e0fbc43dd520a832c0e9c53866d73e9cea4e4/Demo/Demo3.PNG -------------------------------------------------------------------------------- /Demo/Demo3.PNG.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9162b13745191e1499fa4dcf273a0c09 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 11 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 1 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | isReadable: 0 24 | streamingMipmaps: 0 25 | streamingMipmapsPriority: 0 26 | grayScaleToAlpha: 0 27 | generateCubemap: 6 28 | cubemapConvolution: 0 29 | seamlessCubemap: 0 30 | textureFormat: 1 31 | maxTextureSize: 2048 32 | textureSettings: 33 | serializedVersion: 2 34 | filterMode: -1 35 | aniso: -1 36 | mipBias: -100 37 | wrapU: -1 38 | wrapV: -1 39 | wrapW: -1 40 | nPOTScale: 1 41 | lightmap: 0 42 | compressionQuality: 50 43 | spriteMode: 0 44 | spriteExtrude: 1 45 | spriteMeshType: 1 46 | alignment: 0 47 | spritePivot: {x: 0.5, y: 0.5} 48 | spritePixelsToUnits: 100 49 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 50 | spriteGenerateFallbackPhysicsShape: 1 51 | alphaUsage: 1 52 | alphaIsTransparency: 0 53 | spriteTessellationDetail: -1 54 | textureType: 0 55 | textureShape: 1 56 | singleChannelComponent: 0 57 | maxTextureSizeSet: 0 58 | compressionQualitySet: 0 59 | textureFormatSet: 0 60 | applyGammaDecoding: 0 61 | platformSettings: 62 | - serializedVersion: 3 63 | buildTarget: DefaultTexturePlatform 64 | maxTextureSize: 2048 65 | resizeAlgorithm: 0 66 | textureFormat: -1 67 | textureCompression: 1 68 | compressionQuality: 50 69 | crunchedCompression: 0 70 | allowsAlphaSplitting: 0 71 | overridden: 0 72 | androidETC2FallbackOverride: 0 73 | forceMaximumCompressionQuality_BC6H_BC7: 0 74 | spriteSheet: 75 | serializedVersion: 2 76 | sprites: [] 77 | outline: [] 78 | physicsShape: [] 79 | bones: [] 80 | spriteID: 81 | internalID: 0 82 | vertices: [] 83 | indices: 84 | edges: [] 85 | weights: [] 86 | secondaryTextures: [] 87 | spritePackingTag: 88 | pSDRemoveMatte: 0 89 | pSDShowRemoveMatteOption: 0 90 | userData: 91 | assetBundleName: 92 | assetBundleVariant: 93 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d5036d8971d589446a50ecee4e0f6c7c 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/BindingDataContextInfoDrawer.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Reflection; 4 | using UnityEngine; 5 | using UnityEditor; 6 | using UnityEditor.UIElements; 7 | using UnityEngine.UIElements; 8 | using Object = UnityEngine.Object; 9 | 10 | namespace Gameframe.Bindings.Editor 11 | { 12 | [CustomPropertyDrawer(typeof(BindingDataContextInfo))] 13 | public class BindingDataContextInfoDrawer : PropertyDrawer 14 | { 15 | private VisualElement rootContainer; 16 | private PopupField componentPopup; 17 | private PopupField propertyPopup; 18 | 19 | private SerializedProperty pDataContext; 20 | private SerializedProperty pComponent; 21 | private SerializedProperty pProperty; 22 | 23 | public override VisualElement CreatePropertyGUI(SerializedProperty property) 24 | { 25 | // Create property container element. 26 | rootContainer = new VisualElement 27 | { 28 | style = 29 | { 30 | paddingTop = 5, 31 | paddingBottom = 5, 32 | paddingLeft = 5, 33 | paddingRight = 5, 34 | marginBottom = 10, 35 | marginTop = 10, 36 | borderBottomWidth = 1, 37 | borderLeftWidth = 1, 38 | borderRightWidth = 1, 39 | borderTopWidth = 1, 40 | #if UNITY_2019_3_OR_NEWER 41 | borderBottomColor = Color.black, 42 | borderLeftColor = Color.black, 43 | borderRightColor = Color.black, 44 | borderTopColor = Color.black, 45 | #else 46 | borderColor = Color.black, 47 | #endif 48 | backgroundColor = new Color(0,0,0,0.1f) 49 | } 50 | }; 51 | 52 | rootContainer.Bind(property.serializedObject); 53 | 54 | // Create property fields. 55 | pDataContext = property.FindPropertyRelative("dataContext"); 56 | pComponent = property.FindPropertyRelative("component"); 57 | pProperty = property.FindPropertyRelative("property"); 58 | 59 | rootContainer.Add(new Label(property.displayName)); 60 | 61 | //Data Context Field is always available 62 | var dataContextField = new ObjectField("Object") 63 | { 64 | objectType = typeof(Object), 65 | bindingPath = pDataContext.propertyPath 66 | }; 67 | 68 | dataContextField.SetValueWithoutNotify(pDataContext.objectReferenceValue); 69 | 70 | rootContainer.Add(dataContextField); 71 | 72 | UpdateSelectableComponents(pDataContext.objectReferenceValue); 73 | UpdateSelectableProperties(); 74 | 75 | dataContextField.RegisterCallback>(evt => 76 | { 77 | pDataContext.objectReferenceValue = evt.newValue; 78 | 79 | //Clear component when a new data context is set 80 | pComponent.objectReferenceValue = null; 81 | pProperty.stringValue = string.Empty; 82 | //Update components and properties 83 | UpdateSelectableComponents(evt.newValue); 84 | UpdateSelectableProperties(); 85 | }); 86 | 87 | return rootContainer; 88 | } 89 | 90 | private void UpdateSelectableComponents(Object dataContext) 91 | { 92 | if (componentPopup != null) 93 | { 94 | componentPopup.RemoveFromHierarchy(); 95 | componentPopup = null; 96 | } 97 | 98 | var targetGameObject = dataContext as GameObject; 99 | if (targetGameObject == null) 100 | { 101 | return; 102 | } 103 | 104 | var components = new List(); 105 | targetGameObject.GetComponents(components); 106 | 107 | var selectableObjects = components.Cast().ToList(); 108 | selectableObjects.Insert(0, dataContext); 109 | 110 | int defaultIndex = selectableObjects.IndexOf(pComponent.objectReferenceValue); 111 | if (defaultIndex < 0) 112 | { 113 | defaultIndex = 0; 114 | } 115 | 116 | //Make sure we're currently set to the default value 117 | if (selectableObjects.Count > 0) 118 | { 119 | pComponent.objectReferenceValue = selectableObjects[defaultIndex]; 120 | pComponent.serializedObject.ApplyModifiedProperties(); 121 | } 122 | 123 | componentPopup = new PopupField("Component", selectableObjects,defaultIndex, FormatComponentType,FormatComponentTypePopup); 124 | 125 | componentPopup.RegisterCallback>(evt => 126 | { 127 | pComponent.objectReferenceValue = evt.newValue is GameObject ? null : evt.newValue; 128 | pProperty.stringValue = string.Empty; 129 | UpdateSelectableProperties(); 130 | pComponent.serializedObject.ApplyModifiedProperties(); 131 | }); 132 | 133 | rootContainer.Insert(2,componentPopup); 134 | } 135 | 136 | private void UpdateSelectableProperties() 137 | { 138 | if (propertyPopup != null) 139 | { 140 | propertyPopup.RemoveFromHierarchy(); 141 | propertyPopup = null; 142 | } 143 | 144 | Object targetObject = pComponent.objectReferenceValue; 145 | if (targetObject == null) 146 | { 147 | targetObject = pDataContext.objectReferenceValue; 148 | } 149 | 150 | if (targetObject == null) 151 | { 152 | return; 153 | } 154 | 155 | var properties = targetObject.GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.GetField); 156 | var propertyNames = properties.Select(x => x.Name).ToList(); 157 | 158 | int defaultIndex = propertyNames.IndexOf(pProperty.stringValue); 159 | if (defaultIndex < 0) 160 | { 161 | defaultIndex = 0; 162 | } 163 | 164 | //Make sure we're currently set to the default value 165 | if (propertyNames.Count > 0) 166 | { 167 | pProperty.stringValue = propertyNames[defaultIndex]; 168 | pProperty.serializedObject.ApplyModifiedProperties(); 169 | } 170 | 171 | propertyPopup = new PopupField("Property",propertyNames,defaultIndex); 172 | propertyPopup.RegisterCallback>(evt => 173 | { 174 | pProperty.stringValue = evt.newValue; 175 | pProperty.serializedObject.ApplyModifiedProperties(); 176 | }); 177 | 178 | rootContainer.Add(propertyPopup); 179 | } 180 | 181 | private static string FormatComponentType(Object obj) 182 | { 183 | return $"{obj.GetType().Name}"; 184 | } 185 | 186 | private static string FormatComponentTypePopup(Object obj) 187 | { 188 | return $"{obj.GetType().Name} - InstanceId: {obj.GetInstanceID()}"; 189 | } 190 | 191 | } 192 | } 193 | 194 | -------------------------------------------------------------------------------- /Editor/BindingDataContextInfoDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3662a14200fab4f77b5f4761a4dbc706 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/BindingEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Reflection; 5 | using UnityEngine; 6 | using UnityEditor; 7 | using UnityEditor.UIElements; 8 | using UnityEngine.UIElements; 9 | using Object = UnityEngine.Object; 10 | 11 | namespace Gameframe.Bindings.Editor 12 | { 13 | [CustomEditor(typeof(BindingBehaviour), editorForChildClasses: true)] 14 | public class BindingEditor : UnityEditor.Editor 15 | { 16 | private SerializedProperty pDataContext; 17 | private List _drawerList; 18 | 19 | private void OnEnable() 20 | { 21 | pDataContext = serializedObject.FindProperty("_sourceDataInfo"); 22 | _drawerList = new List(); 23 | } 24 | 25 | public override VisualElement CreateInspectorGUI() 26 | { 27 | var container = new VisualElement(); 28 | 29 | var drawer = new BindingDataContextInfoDrawer(); 30 | container.Add(drawer.CreatePropertyGUI(pDataContext)); 31 | _drawerList.Add(drawer); 32 | 33 | var fields = serializedObject.targetObject.GetType() 34 | .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | 35 | BindingFlags.GetField); 36 | 37 | if (fields.Length <= 0) 38 | { 39 | return container; 40 | } 41 | 42 | var fieldContainer = new VisualElement 43 | { 44 | style = 45 | { 46 | paddingTop = 5, 47 | paddingBottom = 5, 48 | paddingLeft = 5, 49 | paddingRight = 5, 50 | marginBottom = 5, 51 | marginTop = 5, 52 | borderBottomWidth = 1, 53 | borderLeftWidth = 1, 54 | borderRightWidth = 1, 55 | borderTopWidth = 1, 56 | #if UNITY_2019_3_OR_NEWER 57 | borderBottomColor = Color.black, 58 | borderLeftColor = Color.black, 59 | borderRightColor = Color.black, 60 | borderTopColor = Color.black, 61 | #else 62 | borderColor = Color.black, 63 | #endif 64 | backgroundColor = new Color(0, 0, 0, 0.1f) 65 | } 66 | }; 67 | 68 | foreach (var field in fields) 69 | { 70 | if (field.IsPublic || field.GetCustomAttribute() != null) 71 | { 72 | var property = serializedObject.FindProperty(field.Name); 73 | if (field.FieldType == typeof(BindingDataContextInfo)) 74 | { 75 | drawer = new BindingDataContextInfoDrawer(); 76 | container.Add(drawer.CreatePropertyGUI(property)); 77 | _drawerList.Add(drawer); 78 | } 79 | else 80 | { 81 | fieldContainer.Add(CreateFieldFromProperty(serializedObject.FindProperty(field.Name))); 82 | } 83 | } 84 | } 85 | 86 | container.Add(fieldContainer); 87 | 88 | return container; 89 | } 90 | 91 | 92 | private static VisualElement CreateFieldFromProperty(SerializedProperty property) 93 | { 94 | SerializedPropertyType propertyType = property.propertyType; 95 | 96 | //Ripped this from some decompiled internal unity code so it's wonky. Could fix it if there is every an actual need 97 | switch (propertyType + 1) 98 | { 99 | case SerializedPropertyType.Integer: 100 | case SerializedPropertyType.Boolean: 101 | return ConfigureField(new IntegerField(), property); 102 | case SerializedPropertyType.Float: 103 | return ConfigureField(new Toggle(), property); 104 | case SerializedPropertyType.String: 105 | return ConfigureField(new FloatField(), property); 106 | case SerializedPropertyType.Color: 107 | return ConfigureField(new TextField(), property); 108 | case SerializedPropertyType.ObjectReference: 109 | return ConfigureField(new ColorField(), property); 110 | 111 | case SerializedPropertyType.LayerMask: 112 | ObjectField field1 = new ObjectField(); 113 | GetFieldInfoFromProperty(property, out Type type); 114 | if ((object) type == null || !type.IsSubclassOf(typeof(UnityEngine.Object)) ) 115 | { 116 | type = typeof(UnityEngine.Object); 117 | } 118 | field1.objectType = type; 119 | return ConfigureField(field1, property); 120 | 121 | case SerializedPropertyType.Enum: 122 | return ConfigureField(new LayerMaskField(), property); 123 | case SerializedPropertyType.Vector2: 124 | return ConfigureField, string>( 125 | new PopupField(((IEnumerable) property.enumDisplayNames).ToList(), 126 | property.enumValueIndex, (Func) null, (Func) null) 127 | { 128 | index = property.enumValueIndex 129 | }, property); 130 | 131 | case SerializedPropertyType.Vector3: 132 | return ConfigureField(new Vector2Field(), property); 133 | case SerializedPropertyType.Vector4: 134 | return ConfigureField(new Vector3Field(), property); 135 | case SerializedPropertyType.Rect: 136 | return ConfigureField(new Vector4Field(), property); 137 | case SerializedPropertyType.ArraySize: 138 | return ConfigureField(new RectField(), property); 139 | 140 | case SerializedPropertyType.Character: 141 | IntegerField integerField = new IntegerField(); 142 | integerField.SetValueWithoutNotify(property.intValue); 143 | integerField.isDelayed = true; 144 | return ConfigureField(integerField, property); 145 | 146 | case SerializedPropertyType.AnimationCurve: 147 | TextField field2 = new TextField(); 148 | field2.maxLength = 1; 149 | return ConfigureField(field2, property); 150 | case SerializedPropertyType.Bounds: 151 | return ConfigureField(new CurveField(), property); 152 | case SerializedPropertyType.Gradient: 153 | return ConfigureField(new BoundsField(), property); 154 | case SerializedPropertyType.Quaternion: 155 | return ConfigureField(new GradientField(), property); 156 | case SerializedPropertyType.ExposedReference: 157 | return null; 158 | case SerializedPropertyType.FixedBufferSize: 159 | return null; 160 | case SerializedPropertyType.Vector2Int: 161 | return null; 162 | case SerializedPropertyType.Vector3Int: 163 | return ConfigureField(new Vector2IntField(), property); 164 | case SerializedPropertyType.RectInt: 165 | return ConfigureField(new Vector3IntField(), property); 166 | case SerializedPropertyType.BoundsInt: 167 | return ConfigureField(new RectIntField(), property); 168 | case SerializedPropertyType.Vector2 | SerializedPropertyType.Gradient: 169 | return ConfigureField(new BoundsIntField(), property); 170 | default: 171 | return null; 172 | } 173 | } 174 | 175 | private static VisualElement ConfigureField( 176 | TField field, 177 | SerializedProperty property) 178 | where TField : BaseField 179 | { 180 | string str = !string.IsNullOrEmpty(property.displayName) ? property.displayName : property.name; 181 | field.bindingPath = property.propertyPath; 182 | field.name = "unity-input-" + property.propertyPath; 183 | field.label = str; 184 | Label label = field.Q