From 219c87f469f871f000f7301a5db8f5cc20a0b94f Mon Sep 17 00:00:00 2001 From: MinhHai Date: Fri, 9 Jan 2026 15:01:29 +0700 Subject: [PATCH 1/2] add new pack: Editor Attributes, complete GoTo cmd --- Assets/EditorAttributes.meta | 8 + Assets/EditorAttributes/CHANGELOG.md | 316 ++++ Assets/EditorAttributes/CHANGELOG.md.meta | 14 + Assets/EditorAttributes/Documentation.meta | 8 + .../EditorAttributesDocumentation.rtf | 1048 ++++++++++++++ .../EditorAttributesDocumentation.rtf.meta | 14 + .../EditorAttributes/Documentation/index.md | 1 + .../Documentation/index.md.meta | 14 + Assets/EditorAttributes/Editor.meta | 8 + Assets/EditorAttributes/Editor/Scripts.meta | 8 + .../Editor/Scripts/Drawers.meta | 8 + .../Drawers/ButtonAttributeDrawers.meta | 8 + .../ButtonAttributeDrawers/ButtonDrawer.cs | 419 ++++++ .../ButtonDrawer.cs.meta | 18 + .../ButtonFieldDrawer.cs | 76 + .../ButtonFieldDrawer.cs.meta | 18 + .../InlineButtonDrawer.cs | 81 ++ .../InlineButtonDrawer.cs.meta | 18 + .../SelectionButtonsDrawer.cs | 229 +++ .../SelectionButtonsDrawer.cs.meta | 18 + .../ValueButtonsDrawer.cs | 161 +++ .../ValueButtonsDrawer.cs.meta | 18 + .../Drawers/ConditionalAttributeDrawers.meta | 8 + .../ConditionalFieldDrawer.cs | 119 ++ .../ConditionalFieldDrawer.cs.meta | 18 + .../DisableFieldDrawer.cs | 32 + .../DisableFieldDrawer.cs.meta | 18 + .../EnableFieldDrawer.cs | 32 + .../EnableFieldDrawer.cs.meta | 18 + .../HideFieldDrawer.cs | 39 + .../HideFieldDrawer.cs.meta | 18 + .../MessageBoxDrawer.cs | 52 + .../MessageBoxDrawer.cs.meta | 18 + .../ShowFieldDrawer.cs | 39 + .../ShowFieldDrawer.cs.meta | 18 + .../Drawers/DecorativeAttributeDrawers.meta | 8 + .../AssetPreviewDrawer.cs | 79 + .../AssetPreviewDrawer.cs.meta | 18 + .../ColorFieldDrawer.cs | 36 + .../ColorFieldDrawer.cs.meta | 18 + .../GUIColorDrawer.cs | 17 + .../GUIColorDrawer.cs.meta | 18 + .../HelpBoxDrawer.cs | 36 + .../HelpBoxDrawer.cs.meta | 18 + .../HideLabelDrawer.cs | 24 + .../HideLabelDrawer.cs.meta | 18 + .../DecorativeAttributeDrawers/ImageDrawer.cs | 47 + .../ImageDrawer.cs.meta | 18 + .../IndentPropertyDrawer.cs | 23 + .../IndentPropertyDrawer.cs.meta | 18 + .../DecorativeAttributeDrawers/LineDrawer.cs | 28 + .../LineDrawer.cs.meta | 18 + .../PrefixDrawer.cs | 48 + .../PrefixDrawer.cs.meta | 18 + .../PropertyWidthDrawer.cs | 29 + .../PropertyWidthDrawer.cs.meta | 18 + .../RenameDrawer.cs | 103 ++ .../RenameDrawer.cs.meta | 18 + .../SuffixDrawer.cs | 46 + .../SuffixDrawer.cs.meta | 18 + .../DecorativeAttributeDrawers/TitleDrawer.cs | 47 + .../TitleDrawer.cs.meta | 18 + .../Drawers/DropdownAttributeDrawers.meta | 8 + .../AnimatorParamDropdownDrawer.cs | 143 ++ .../AnimatorParamDropdownDrawer.cs.meta | 18 + .../DropdownDrawer.cs | 184 +++ .../DropdownDrawer.cs.meta | 18 + .../PropertyDropdownDrawer.cs | 101 ++ .../PropertyDropdownDrawer.cs.meta | 18 + .../SceneDropdownDrawer.cs | 150 ++ .../SceneDropdownDrawer.cs.meta | 18 + .../SortingLayerDropdownDrawer.cs | 74 + .../SortingLayerDropdownDrawer.cs.meta | 18 + .../TagDropdownDrawer.cs | 83 ++ .../TagDropdownDrawer.cs.meta | 18 + .../TypeDropdownDrawer.cs | 143 ++ .../TypeDropdownDrawer.cs.meta | 18 + .../Drawers/GroupingAttributeDrawers.meta | 8 + .../DataTableDrawer.cs | 140 ++ .../DataTableDrawer.cs.meta | 18 + .../FoldoutGroupDrawer.cs | 89 ++ .../FoldoutGroupDrawer.cs.meta | 18 + .../HorizontalGroupDrawer.cs | 155 ++ .../HorizontalGroupDrawer.cs.meta | 18 + .../TabGroupDrawer.cs | 129 ++ .../TabGroupDrawer.cs.meta | 18 + .../ToggleGroupDrawer.cs | 123 ++ .../ToggleGroupDrawer.cs.meta | 18 + .../VerticalGroupDrawer.cs | 96 ++ .../VerticalGroupDrawer.cs.meta | 18 + .../MiscellaneousAttributeDrawers.meta | 8 + .../CollectionRangeDrawer.cs | 39 + .../CollectionRangeDrawer.cs.meta | 18 + .../DisableInEditModeDrawer.cs | 19 + .../DisableInEditModeDrawer.cs.meta | 18 + .../DisableInPlayModeDrawer.cs | 19 + .../DisableInPlayModeDrawer.cs.meta | 18 + .../FilePathDrawer.cs | 62 + .../FilePathDrawer.cs.meta | 18 + .../FolderPathDrawer.cs | 62 + .../FolderPathDrawer.cs.meta | 18 + .../HideInChildrenDrawer.cs | 35 + .../HideInChildrenDrawer.cs.meta | 18 + .../HideInEditModeDrawer.cs | 19 + .../HideInEditModeDrawer.cs.meta | 18 + .../HideInPlayModeDrawer.cs | 19 + .../HideInPlayModeDrawer.cs.meta | 18 + .../HidePropertyDrawer.cs | 21 + .../HidePropertyDrawer.cs.meta | 18 + .../OnValueChangedDrawer.cs | 42 + .../OnValueChangedDrawer.cs.meta | 18 + .../ReadonlyDrawer.cs | 18 + .../ReadonlyDrawer.cs.meta | 18 + .../RequiredDrawer.cs | 235 +++ .../RequiredDrawer.cs.meta | 18 + .../TypeFilterDrawer.cs | 68 + .../TypeFilterDrawer.cs.meta | 18 + .../ValidateDrawer.cs | 88 ++ .../ValidateDrawer.cs.meta | 18 + .../Drawers/NumericalAttributeDrawers.meta | 8 + .../NumericalAttributeDrawers/ClampDrawer.cs | 169 +++ .../ClampDrawer.cs.meta | 18 + .../DrawHandleDrawer.cs | 58 + .../DrawHandleDrawer.cs.meta | 18 + .../MinMaxSliderDrawer.cs | 176 +++ .../MinMaxSliderDrawer.cs.meta | 18 + .../ProgressBarDrawer.cs | 59 + .../ProgressBarDrawer.cs.meta | 18 + .../TimeFieldDrawer.cs | 226 +++ .../TimeFieldDrawer.cs.meta | 18 + .../UnitFieldDrawer.cs | 117 ++ .../UnitFieldDrawer.cs.meta | 18 + .../NumericalAttributeDrawers/WrapDrawer.cs | 179 +++ .../WrapDrawer.cs.meta | 18 + .../Scripts/Drawers/PropertyDrawerBase.cs | 1284 +++++++++++++++++ .../Drawers/PropertyDrawerBase.cs.meta | 18 + .../Editor/Scripts/Drawers/VoidDrawer.cs | 11 + .../Editor/Scripts/Drawers/VoidDrawer.cs.meta | 18 + .../Scripts/EditorAttributes.Editor.asmdef | 25 + .../EditorAttributes.Editor.asmdef.meta | 14 + .../Scripts/EditorAttributesSettings.cs | 156 ++ .../Scripts/EditorAttributesSettings.cs.meta | 18 + .../Editor/Scripts/EditorExtension.cs | 375 +++++ .../Editor/Scripts/EditorExtension.cs.meta | 18 + .../Editor/Scripts/EditorHandles.cs | 135 ++ .../Editor/Scripts/EditorHandles.cs.meta | 18 + .../Editor/Scripts/EditorValidation.cs | 325 +++++ .../Editor/Scripts/EditorValidation.cs.meta | 18 + .../Editor/Scripts/UnitConverter.cs | 375 +++++ .../Editor/Scripts/UnitConverter.cs.meta | 18 + .../Editor/Scripts/Utilities.meta | 8 + .../Editor/Scripts/Utilities/ColorUtils.cs | 229 +++ .../Scripts/Utilities/ColorUtils.cs.meta | 18 + .../Scripts/Utilities/ReflectionUtility.cs | 504 +++++++ .../Utilities/ReflectionUtility.cs.meta | 18 + .../Scripts/Utilities/UnityTypeConverter.cs | 239 +++ .../Utilities/UnityTypeConverter.cs.meta | 18 + .../Editor/Scripts/Utilities/VectorUtils.cs | 145 ++ .../Scripts/Utilities/VectorUtils.cs.meta | 18 + Assets/EditorAttributes/LICENSE | 24 + Assets/EditorAttributes/LICENSE.meta | 14 + Assets/EditorAttributes/README.md | 94 ++ Assets/EditorAttributes/README.md.meta | 14 + Assets/EditorAttributes/Runtime.meta | 8 + Assets/EditorAttributes/Runtime/Scripts.meta | 8 + .../Runtime/Scripts/Attributes.meta | 8 + .../Scripts/Attributes/ButtonAttributes.meta | 8 + .../ButtonAttributes/ButtonAttribute.cs | 122 ++ .../ButtonAttributes/ButtonAttribute.cs.meta | 18 + .../ButtonAttributes/ButtonFieldAttribute.cs | 50 + .../ButtonFieldAttribute.cs.meta | 18 + .../ButtonAttributes/IRepetableButton.cs | 9 + .../ButtonAttributes/IRepetableButton.cs.meta | 18 + .../ButtonAttributes/InlineButtonAttribute.cs | 52 + .../InlineButtonAttribute.cs.meta | 18 + .../SelectionButtonsAttribute.cs | 30 + .../SelectionButtonsAttribute.cs.meta | 18 + .../ButtonAttributes/ValueButtonsAttribute.cs | 43 + .../ValueButtonsAttribute.cs.meta | 18 + .../Attributes/ConditionalAttributes.meta | 8 + .../ConditionalFieldAttribute.cs | 96 ++ .../ConditionalFieldAttribute.cs.meta | 18 + .../DisableFieldAttribute.cs | 37 + .../DisableFieldAttribute.cs.meta | 18 + .../EnableFieldAttribute.cs | 37 + .../EnableFieldAttribute.cs.meta | 18 + .../HideFieldAttribute.cs | 37 + .../HideFieldAttribute.cs.meta | 18 + .../IConditionalAttribute.cs | 8 + .../IConditionalAttribute.cs.meta | 18 + .../MessageBoxAttribute.cs | 67 + .../MessageBoxAttribute.cs.meta | 18 + .../ShowFieldAttribute.cs | 37 + .../ShowFieldAttribute.cs.meta | 18 + .../Attributes/DecorativeAttributes.meta | 8 + .../AssetPreviewAttribute.cs | 24 + .../AssetPreviewAttribute.cs.meta | 18 + .../ColorFieldAttribute.cs | 60 + .../ColorFieldAttribute.cs.meta | 18 + .../DecorativeAttributes/GUIColorAttribute.cs | 65 + .../GUIColorAttribute.cs.meta | 18 + .../DecorativeAttributes/HelpBoxAttribute.cs | 34 + .../HelpBoxAttribute.cs.meta | 18 + .../HideLabelAttribute.cs | 9 + .../HideLabelAttribute.cs.meta | 18 + .../DecorativeAttributes/IColorAttribute.cs | 13 + .../IColorAttribute.cs.meta | 18 + .../DecorativeAttributes/ImageAttribute.cs | 33 + .../ImageAttribute.cs.meta | 18 + .../IndentPropertyAttribute.cs | 18 + .../IndentPropertyAttribute.cs.meta | 18 + .../DecorativeAttributes/LineAttribute.cs | 66 + .../LineAttribute.cs.meta | 18 + .../DecorativeAttributes/PrefixAttribute.cs | 28 + .../PrefixAttribute.cs.meta | 18 + .../PropertyOrderAttribute.cs | 19 + .../PropertyOrderAttribute.cs.meta | 18 + .../PropertyWidthAttribute.cs | 18 + .../PropertyWidthAttribute.cs.meta | 18 + .../DecorativeAttributes/RenameAttribute.cs | 42 + .../RenameAttribute.cs.meta | 18 + .../DecorativeAttributes/SuffixAttribute.cs | 27 + .../SuffixAttribute.cs.meta | 18 + .../DecorativeAttributes/TitleAttribute.cs | 43 + .../TitleAttribute.cs.meta | 18 + .../Attributes/DropdownAttributes.meta | 8 + .../AnimatorParamDropdownAttribute.cs | 18 + .../AnimatorParamDropdownAttribute.cs.meta | 18 + .../DropdownAttributes/DropdownAttribute.cs | 26 + .../DropdownAttribute.cs.meta | 18 + .../PropertyDropdownAttribute.cs | 9 + .../PropertyDropdownAttribute.cs.meta | 18 + .../SceneDropdownAttribute.cs | 9 + .../SceneDropdownAttribute.cs.meta | 18 + .../SortingLayerDropdownAttribute.cs | 9 + .../SortingLayerDropdownAttribute.cs.meta | 18 + .../TagDropdownAttribute.cs | 9 + .../TagDropdownAttribute.cs.meta | 18 + .../TypeDropdownAttribute.cs | 18 + .../TypeDropdownAttribute.cs.meta | 18 + .../Attributes/GroupingAttributes.meta | 8 + .../GroupingAttributes/DataTableAttribute.cs | 24 + .../DataTableAttribute.cs.meta | 18 + .../FoldoutGroupAttribute.cs | 40 + .../FoldoutGroupAttribute.cs.meta | 18 + .../HorizontalGroupAttribute.cs | 52 + .../HorizontalGroupAttribute.cs.meta | 18 + .../GroupingAttributes/TabGroupAttribute.cs | 18 + .../TabGroupAttribute.cs.meta | 18 + .../ToggleGroupAttribute.cs | 40 + .../ToggleGroupAttribute.cs.meta | 18 + .../VerticalGroupAttribute.cs | 34 + .../VerticalGroupAttribute.cs.meta | 18 + .../Attributes/IDynamicStringAttribute.cs | 13 + .../IDynamicStringAttribute.cs.meta | 18 + .../Attributes/MiscellaneousAttributes.meta | 8 + .../CollectionRangeAttribute.cs | 27 + .../CollectionRangeAttribute.cs.meta | 18 + .../DisableInEditModeAttribute.cs | 19 + .../DisableInEditModeAttribute.cs.meta | 18 + .../DisableInPlayModeAttribute.cs | 19 + .../DisableInPlayModeAttribute.cs.meta | 18 + .../FilePathAttribute.cs | 24 + .../FilePathAttribute.cs.meta | 18 + .../FolderPathAttribute.cs | 18 + .../FolderPathAttribute.cs.meta | 18 + .../HideInChildrenAttribute.cs | 25 + .../HideInChildrenAttribute.cs.meta | 18 + .../HideInEditModeAttribute.cs | 19 + .../HideInEditModeAttribute.cs.meta | 18 + .../HideInPlayModeAttribute.cs | 19 + .../HideInPlayModeAttribute.cs.meta | 18 + .../HidePropertyAttribute.cs | 19 + .../HidePropertyAttribute.cs.meta | 18 + .../OnValueChangedAttribute.cs | 18 + .../OnValueChangedAttribute.cs.meta | 18 + .../ReadOnlyAttribute.cs | 19 + .../ReadOnlyAttribute.cs.meta | 18 + .../RequiredAttribute.cs | 55 + .../RequiredAttribute.cs.meta | 18 + .../ShowInInspectorAttribute.cs | 9 + .../ShowInInspectorAttribute.cs.meta | 18 + .../TypeFilterAttribute.cs | 19 + .../TypeFilterAttribute.cs.meta | 18 + .../ValidateAttribute.cs | 66 + .../ValidateAttribute.cs.meta | 18 + .../Attributes/NumericalAttributes.meta | 8 + .../NumericalAttributes/ClampAttribute.cs | 114 ++ .../ClampAttribute.cs.meta | 18 + .../DrawHandleAttribute.cs | 58 + .../DrawHandleAttribute.cs.meta | 18 + .../MinMaxSliderAttribute.cs | 28 + .../MinMaxSliderAttribute.cs.meta | 18 + .../ProgressBarAttribute.cs | 24 + .../ProgressBarAttribute.cs.meta | 18 + .../NumericalAttributes/TimeFieldAttribute.cs | 35 + .../TimeFieldAttribute.cs.meta | 18 + .../NumericalAttributes/UnitFieldAttribute.cs | 57 + .../UnitFieldAttribute.cs.meta | 18 + .../NumericalAttributes/WrapAttribute.cs | 114 ++ .../NumericalAttributes/WrapAttribute.cs.meta | 18 + .../Runtime/Scripts/DataTypes.meta | 8 + .../Scripts/DataTypes/SimpleTransform.cs | 79 + .../Scripts/DataTypes/SimpleTransform.cs.meta | 18 + .../Runtime/Scripts/DataTypes/Unit.cs | 266 ++++ .../Runtime/Scripts/DataTypes/Unit.cs.meta | 18 + .../Runtime/Scripts/DataTypes/Void.cs | 10 + .../Runtime/Scripts/DataTypes/Void.cs.meta | 18 + .../Runtime/Scripts/EditorAttributes.asmdef | 14 + .../Scripts/EditorAttributes.asmdef.meta | 14 + Assets/EditorAttributes/Samples.meta | 8 + .../Samples/EditorAttributesIcon.png | Bin 0 -> 695 bytes .../Samples/EditorAttributesIcon.png.meta | 134 ++ .../Samples/ExampleAnimator.controller | 67 + .../Samples/ExampleAnimator.controller.meta | 15 + .../Samples/ExampleScriptableObject.asset | 49 + .../ExampleScriptableObject.asset.meta | 15 + .../Samples/SampleScene.unity | 3 + .../Samples/SampleScene.unity.meta | 14 + Assets/EditorAttributes/Samples/Scripts.meta | 8 + .../Samples/Scripts/AttributesSamples.asmdef | 16 + .../Scripts/AttributesSamples.asmdef.meta | 14 + .../Scripts/ButtonAttributeSamples.meta | 8 + .../ButtonFieldSample.cs | 28 + .../ButtonFieldSample.cs.meta | 18 + .../ButtonAttributeSamples/ButtonSample.cs | 27 + .../ButtonSample.cs.meta | 18 + .../InlineButtonSample.cs | 26 + .../InlineButtonSample.cs.meta | 18 + .../SelectionButtonsSample.cs | 41 + .../SelectionButtonsSample.cs.meta | 18 + .../ValueButtonsSample.cs | 17 + .../ValueButtonsSample.cs.meta | 18 + .../Scripts/ConditionalAttributeSamples.meta | 8 + .../ConditionalFieldSample.cs | 47 + .../ConditionalFieldSample.cs.meta | 18 + .../DisableFieldSample.cs | 31 + .../DisableFieldSample.cs.meta | 18 + .../EnableFieldSample.cs | 31 + .../EnableFieldSample.cs.meta | 18 + .../HideFieldSample.cs | 31 + .../HideFieldSample.cs.meta | 18 + .../MessageBoxSample.cs | 48 + .../MessageBoxSample.cs.meta | 18 + .../ShowFieldSample.cs | 31 + .../ShowFieldSample.cs.meta | 18 + .../Scripts/DecorativeAttributeSamples.meta | 8 + .../AssetPreviewSample.cs | 14 + .../AssetPreviewSample.cs.meta | 18 + .../ColorFieldSample.cs | 18 + .../ColorFieldSample.cs.meta | 18 + .../GUIColorSample.cs | 25 + .../GUIColorSample.cs.meta | 18 + .../HelpBoxSample.cs | 25 + .../HelpBoxSample.cs.meta | 18 + .../HideLabelSample.cs | 12 + .../HideLabelSample.cs.meta | 18 + .../DecorativeAttributeSamples/ImageSample.cs | 18 + .../ImageSample.cs.meta | 18 + .../IndentPropertySample.cs | 14 + .../IndentPropertySample.cs.meta | 18 + .../DecorativeAttributeSamples/LineSample.cs | 20 + .../LineSample.cs.meta | 18 + .../PrefixSample.cs | 14 + .../PrefixSample.cs.meta | 18 + .../PropertyOrderSample.cs | 16 + .../PropertyOrderSample.cs.meta | 18 + .../PropertyWidthSample.cs | 14 + .../PropertyWidthSample.cs.meta | 18 + .../RenameSample.cs | 21 + .../RenameSample.cs.meta | 18 + .../SuffixSample.cs | 14 + .../SuffixSample.cs.meta | 18 + .../DecorativeAttributeSamples/TitleSample.cs | 30 + .../TitleSample.cs.meta | 18 + .../Scripts/DropdownAttributeSamples.meta | 8 + .../AnimatorParamDropdownSample.cs | 13 + .../AnimatorParamDropdownSample.cs.meta | 18 + .../DropdownSample.cs | 36 + .../DropdownSample.cs.meta | 18 + .../PropertyDropdownSample.cs | 13 + .../PropertyDropdownSample.cs.meta | 18 + .../SceneDropdownSample.cs | 13 + .../SceneDropdownSample.cs.meta | 18 + .../SortingLayerDropdownSample.cs | 12 + .../SortingLayerDropdownSample.cs.meta | 18 + .../TagDropdownSample.cs | 12 + .../TagDropdownSample.cs.meta | 18 + .../TypeDropdownSample.cs | 13 + .../TypeDropdownSample.cs.meta | 18 + .../Scripts/ExampleScriptableObject.cs | 62 + .../Scripts/ExampleScriptableObject.cs.meta | 18 + .../Scripts/GroupingAttributeSamples.meta | 8 + .../DataTableSample.cs | 23 + .../DataTableSample.cs.meta | 18 + .../FoldoutGroupSample.cs | 24 + .../FoldoutGroupSample.cs.meta | 18 + .../HorizontalGroupSample.cs | 24 + .../HorizontalGroupSample.cs.meta | 18 + .../TabGroupSample.cs | 32 + .../TabGroupSample.cs.meta | 18 + .../ToggleGroupSample.cs | 25 + .../ToggleGroupSample.cs.meta | 18 + .../VerticalGroupSample.cs | 34 + .../VerticalGroupSample.cs.meta | 18 + .../MiscellaneousAttributeSamples.meta | 8 + .../CollectionRangeSample.cs | 15 + .../CollectionRangeSample.cs.meta | 18 + .../DisableInEditModeSample.cs | 12 + .../DisableInEditModeSample.cs.meta | 18 + .../DisableInPlayModeSample.cs | 12 + .../DisableInPlayModeSample.cs.meta | 18 + .../FilePathSample.cs | 14 + .../FilePathSample.cs.meta | 18 + .../FolderPathSample.cs | 13 + .../FolderPathSample.cs.meta | 18 + .../HideInChildrenSample.cs | 19 + .../HideInChildrenSample.cs.meta | 18 + .../HideInEditModeSample.cs | 12 + .../HideInEditModeSample.cs.meta | 18 + .../HideInPlayModeSample.cs | 12 + .../HideInPlayModeSample.cs.meta | 18 + .../HidePropertySample.cs | 14 + .../HidePropertySample.cs.meta | 18 + .../OnValueChangedSample.cs | 14 + .../OnValueChangedSample.cs.meta | 18 + .../ReadOnlySample.cs | 14 + .../ReadOnlySample.cs.meta | 18 + .../RequiredSample.cs | 16 + .../RequiredSample.cs.meta | 18 + .../ShowInInspectorSample.cs | 30 + .../ShowInInspectorSample.cs.meta | 18 + .../TypeFilterSample.cs | 15 + .../TypeFilterSample.cs.meta | 18 + .../ValidateSample.cs | 32 + .../ValidateSample.cs.meta | 18 + .../Scripts/NumericalAttributeSamples.meta | 8 + .../NumericalAttributeSamples/ClampSample.cs | 16 + .../ClampSample.cs.meta | 18 + .../DrawHandleSample.cs | 17 + .../DrawHandleSample.cs.meta | 18 + .../MinMaxSliderSample.cs | 16 + .../MinMaxSliderSample.cs.meta | 18 + .../ProgressBarSample.cs | 21 + .../ProgressBarSample.cs.meta | 18 + .../UnitFieldSample.cs | 19 + .../UnitFieldSample.cs.meta | 18 + .../NumericalAttributeSamples/WrapSample.cs | 16 + .../WrapSample.cs.meta | 18 + Assets/EditorAttributes/package.json | 36 + Assets/EditorAttributes/package.json.meta | 14 + .../PerfectWorld/Prefab/GameController.prefab | 84 +- Assets/PerfectWorld/Scripts/Debug.meta | 3 + .../PerfectWorld/Scripts/Debug/TestCmdGoto.cs | 58 + .../Scripts/Debug/TestCmdGoto.cs.meta | 3 + .../CSNetwork/C2SCommand/C2SCommand.cs | 18 + .../CSNetwork/C2SCommand/C2SCommandFactory.cs | 22 + .../Scripts/Network/CSNetwork/GameSession.cs | 14 + .../Scripts/Network/UnityGameSession.cs | 6 + .../Task/Doc/TaskSystem_Architecture.md | 1 + Packages/manifest.json | 1 + Packages/packages-lock.json | 2 +- 462 files changed, 18860 insertions(+), 2 deletions(-) create mode 100644 Assets/EditorAttributes.meta create mode 100644 Assets/EditorAttributes/CHANGELOG.md create mode 100644 Assets/EditorAttributes/CHANGELOG.md.meta create mode 100644 Assets/EditorAttributes/Documentation.meta create mode 100644 Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf create mode 100644 Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf.meta create mode 100644 Assets/EditorAttributes/Documentation/index.md create mode 100644 Assets/EditorAttributes/Documentation/index.md.meta create mode 100644 Assets/EditorAttributes/Editor.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HideLabelDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HideLabelDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ImageDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ImageDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/IndentPropertyDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/IndentPropertyDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/LineDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/LineDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/PrefixDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/PrefixDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/PropertyWidthDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/PropertyWidthDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/RenameDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/RenameDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/SuffixDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/SuffixDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/TitleDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/TitleDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/AnimatorParamDropdownDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/AnimatorParamDropdownDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/DropdownDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/DropdownDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/PropertyDropdownDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/PropertyDropdownDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/SceneDropdownDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/SceneDropdownDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/SortingLayerDropdownDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/SortingLayerDropdownDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/TagDropdownDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/TagDropdownDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/TypeDropdownDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/DropdownAttributeDrawers/TypeDropdownDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/DataTableDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/DataTableDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/FoldoutGroupDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/FoldoutGroupDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/HorizontalGroupDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/HorizontalGroupDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/TabGroupDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/TabGroupDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/ToggleGroupDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/ToggleGroupDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/VerticalGroupDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/GroupingAttributeDrawers/VerticalGroupDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/CollectionRangeDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/CollectionRangeDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/DisableInEditModeDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/DisableInEditModeDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/DisableInPlayModeDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/DisableInPlayModeDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/FilePathDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/FilePathDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/FolderPathDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/FolderPathDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HideInChildrenDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HideInChildrenDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HideInEditModeDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HideInEditModeDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HideInPlayModeDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HideInPlayModeDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HidePropertyDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/HidePropertyDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/OnValueChangedDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/OnValueChangedDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/ReadonlyDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/ReadonlyDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/RequiredDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/RequiredDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/TypeFilterDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/TypeFilterDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/ValidateDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/MiscellaneousAttributeDrawers/ValidateDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/ClampDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/ClampDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/DrawHandleDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/DrawHandleDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/MinMaxSliderDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/MinMaxSliderDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/ProgressBarDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/ProgressBarDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/TimeFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/TimeFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/UnitFieldDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/UnitFieldDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/WrapDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/NumericalAttributeDrawers/WrapDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/PropertyDrawerBase.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/PropertyDrawerBase.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/VoidDrawer.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Drawers/VoidDrawer.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorAttributes.Editor.asmdef create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorAttributes.Editor.asmdef.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorAttributesSettings.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorAttributesSettings.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorExtension.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorExtension.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorHandles.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorHandles.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorValidation.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/EditorValidation.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/UnitConverter.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/UnitConverter.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/ColorUtils.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/ColorUtils.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/ReflectionUtility.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/ReflectionUtility.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/UnityTypeConverter.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/UnityTypeConverter.cs.meta create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/VectorUtils.cs create mode 100644 Assets/EditorAttributes/Editor/Scripts/Utilities/VectorUtils.cs.meta create mode 100644 Assets/EditorAttributes/LICENSE create mode 100644 Assets/EditorAttributes/LICENSE.meta create mode 100644 Assets/EditorAttributes/README.md create mode 100644 Assets/EditorAttributes/README.md.meta create mode 100644 Assets/EditorAttributes/Runtime.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/ButtonAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/ButtonAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/ButtonFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/ButtonFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/IRepetableButton.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/IRepetableButton.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/InlineButtonAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/InlineButtonAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/SelectionButtonsAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/SelectionButtonsAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/ValueButtonsAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ButtonAttributes/ValueButtonsAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/ConditionalFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/ConditionalFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/DisableFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/DisableFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/EnableFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/EnableFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/HideFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/HideFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/IConditionalAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/IConditionalAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/MessageBoxAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/MessageBoxAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/ShowFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/ConditionalAttributes/ShowFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/AssetPreviewAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/AssetPreviewAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/ColorFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/ColorFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/GUIColorAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/GUIColorAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/HelpBoxAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/HelpBoxAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/HideLabelAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/HideLabelAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/IColorAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/IColorAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/ImageAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/ImageAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/IndentPropertyAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/IndentPropertyAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/LineAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/LineAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/PrefixAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/PrefixAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/PropertyOrderAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/PropertyOrderAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/PropertyWidthAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/PropertyWidthAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/RenameAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/RenameAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/SuffixAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/SuffixAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/TitleAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DecorativeAttributes/TitleAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/AnimatorParamDropdownAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/AnimatorParamDropdownAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/DropdownAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/DropdownAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/PropertyDropdownAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/PropertyDropdownAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/SceneDropdownAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/SceneDropdownAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/SortingLayerDropdownAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/SortingLayerDropdownAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/TagDropdownAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/TagDropdownAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/TypeDropdownAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/DropdownAttributes/TypeDropdownAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/DataTableAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/DataTableAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/FoldoutGroupAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/FoldoutGroupAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/HorizontalGroupAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/HorizontalGroupAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/TabGroupAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/TabGroupAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/ToggleGroupAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/ToggleGroupAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/VerticalGroupAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/GroupingAttributes/VerticalGroupAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/IDynamicStringAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/IDynamicStringAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/CollectionRangeAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/CollectionRangeAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/DisableInEditModeAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/DisableInEditModeAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/DisableInPlayModeAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/DisableInPlayModeAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/FilePathAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/FilePathAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/FolderPathAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/FolderPathAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HideInChildrenAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HideInChildrenAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HideInEditModeAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HideInEditModeAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HideInPlayModeAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HideInPlayModeAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HidePropertyAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/HidePropertyAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/OnValueChangedAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/OnValueChangedAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/ReadOnlyAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/ReadOnlyAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/RequiredAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/RequiredAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/ShowInInspectorAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/ShowInInspectorAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/TypeFilterAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/TypeFilterAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/ValidateAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/MiscellaneousAttributes/ValidateAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/ClampAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/ClampAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/DrawHandleAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/DrawHandleAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/MinMaxSliderAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/MinMaxSliderAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/ProgressBarAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/ProgressBarAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/TimeFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/TimeFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/UnitFieldAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/UnitFieldAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/WrapAttribute.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/Attributes/NumericalAttributes/WrapAttribute.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/DataTypes.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/DataTypes/SimpleTransform.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/DataTypes/SimpleTransform.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/DataTypes/Unit.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/DataTypes/Unit.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/DataTypes/Void.cs create mode 100644 Assets/EditorAttributes/Runtime/Scripts/DataTypes/Void.cs.meta create mode 100644 Assets/EditorAttributes/Runtime/Scripts/EditorAttributes.asmdef create mode 100644 Assets/EditorAttributes/Runtime/Scripts/EditorAttributes.asmdef.meta create mode 100644 Assets/EditorAttributes/Samples.meta create mode 100644 Assets/EditorAttributes/Samples/EditorAttributesIcon.png create mode 100644 Assets/EditorAttributes/Samples/EditorAttributesIcon.png.meta create mode 100644 Assets/EditorAttributes/Samples/ExampleAnimator.controller create mode 100644 Assets/EditorAttributes/Samples/ExampleAnimator.controller.meta create mode 100644 Assets/EditorAttributes/Samples/ExampleScriptableObject.asset create mode 100644 Assets/EditorAttributes/Samples/ExampleScriptableObject.asset.meta create mode 100644 Assets/EditorAttributes/Samples/SampleScene.unity create mode 100644 Assets/EditorAttributes/Samples/SampleScene.unity.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/AttributesSamples.asmdef create mode 100644 Assets/EditorAttributes/Samples/Scripts/AttributesSamples.asmdef.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/ButtonFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/ButtonFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/ButtonSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/ButtonSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/InlineButtonSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/InlineButtonSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/SelectionButtonsSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/SelectionButtonsSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/ValueButtonsSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ButtonAttributeSamples/ValueButtonsSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/ConditionalFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/ConditionalFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/DisableFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/DisableFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/EnableFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/EnableFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/HideFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/HideFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/MessageBoxSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/MessageBoxSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/ShowFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ConditionalAttributeSamples/ShowFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/AssetPreviewSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/AssetPreviewSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/ColorFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/ColorFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/GUIColorSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/GUIColorSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/HelpBoxSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/HelpBoxSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/HideLabelSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/HideLabelSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/ImageSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/ImageSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/IndentPropertySample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/IndentPropertySample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/LineSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/LineSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/PrefixSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/PrefixSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/PropertyOrderSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/PropertyOrderSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/PropertyWidthSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/PropertyWidthSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/RenameSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/RenameSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/SuffixSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/SuffixSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/TitleSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DecorativeAttributeSamples/TitleSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/AnimatorParamDropdownSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/AnimatorParamDropdownSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/DropdownSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/DropdownSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/PropertyDropdownSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/PropertyDropdownSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/SceneDropdownSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/SceneDropdownSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/SortingLayerDropdownSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/SortingLayerDropdownSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/TagDropdownSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/TagDropdownSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/TypeDropdownSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/DropdownAttributeSamples/TypeDropdownSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/ExampleScriptableObject.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/ExampleScriptableObject.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/DataTableSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/DataTableSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/FoldoutGroupSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/FoldoutGroupSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/HorizontalGroupSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/HorizontalGroupSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/TabGroupSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/TabGroupSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/ToggleGroupSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/ToggleGroupSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/VerticalGroupSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/GroupingAttributeSamples/VerticalGroupSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/CollectionRangeSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/CollectionRangeSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/DisableInEditModeSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/DisableInEditModeSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/DisableInPlayModeSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/DisableInPlayModeSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/FilePathSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/FilePathSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/FolderPathSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/FolderPathSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HideInChildrenSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HideInChildrenSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HideInEditModeSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HideInEditModeSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HideInPlayModeSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HideInPlayModeSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HidePropertySample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/HidePropertySample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/OnValueChangedSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/OnValueChangedSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/ReadOnlySample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/ReadOnlySample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/RequiredSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/RequiredSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/ShowInInspectorSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/ShowInInspectorSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/TypeFilterSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/TypeFilterSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/ValidateSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/MiscellaneousAttributeSamples/ValidateSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/ClampSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/ClampSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/DrawHandleSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/DrawHandleSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/MinMaxSliderSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/MinMaxSliderSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/ProgressBarSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/ProgressBarSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/UnitFieldSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/UnitFieldSample.cs.meta create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/WrapSample.cs create mode 100644 Assets/EditorAttributes/Samples/Scripts/NumericalAttributeSamples/WrapSample.cs.meta create mode 100644 Assets/EditorAttributes/package.json create mode 100644 Assets/EditorAttributes/package.json.meta create mode 100644 Assets/PerfectWorld/Scripts/Debug.meta create mode 100644 Assets/PerfectWorld/Scripts/Debug/TestCmdGoto.cs create mode 100644 Assets/PerfectWorld/Scripts/Debug/TestCmdGoto.cs.meta diff --git a/Assets/EditorAttributes.meta b/Assets/EditorAttributes.meta new file mode 100644 index 0000000000..08109af72e --- /dev/null +++ b/Assets/EditorAttributes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2927ffcd6e2c3a04daf69cb6080a3875 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/CHANGELOG.md b/Assets/EditorAttributes/CHANGELOG.md new file mode 100644 index 0000000000..856ec9fffa --- /dev/null +++ b/Assets/EditorAttributes/CHANGELOG.md @@ -0,0 +1,316 @@ +EditorAttributes v2.9.2 Changelog: +- PropertyDropdown Attribute now supports any UnityEngine.Object type +- PropertyDropdown Attribute will now draw custom editors +- Fixed conditional fields not working inside groups +- Fixed Button Attribute not supporting enums anymore +- Fixed Dropdown Attribute not updating when collection becomes invalid +- Fixed DataTable adding labels to array elements after the first one when inside a custom object + +EditorAttributes v2.9.1 Changelog: +- Added char support to Button Attribute parameters and ShowInInspector Attribute +- Added an Asset Preview Load Time setting to the project settings +- Asset previews now load asynchronously +- Required Attribute now has the option to add a button on the help box to auto reference the field +- Attributes can now find private inherited members +- Fixed HideInChildren Attribute no longer working +- Fixed PropertyDropdown not working on child types deeper in the hierarchy +- Fixed Button no longer supporting string parameters +- Fixed Button throwing a stack overflow exception when attempting to use a non supported primitive type parameter + +EditorAttributes v2.9.0 Changelog: +- Added checks for duplicate units and empty unit names when defining custom units +- Added an additional parameter to ValueButtons Attribute for displaying custom labels for items +- Added property space parameter in the HorizontalGroup Attribute +- Added support for multiple inline buttons +- Added percentage units +- Added custom serialized objects support to ShowInInspector Attribute +- Removed the widthOffset parameter from Vertical, Foldout and Toggle groups +- Deprecated TimeField Attribute in favor of UnitField +- HideProperty now will now hide nested properties as well +- MinMaxSlider handles now snap when using Vector2Int +- Fixed an issue where some attributes don't change the display value when that value is changed by script +- Fixed null reference exception in addressables validation during build +- Fixed object reference exception when using UnitField Attribute in a fresh project +- Fixed HideLabel Attribute not working in horizontal groups +- Fixed coloring issues with unit fields + +EditorAttributes v2.8.0 Changelog: +- Added UnitField Attribute +- Added TypeDropdown attribute +- Added project settings tab +- Moved the Disable Build Validation setting to the project settings tab +- Handles now rotate correctly when set to local space +- Removed the ConvertTo enum in favor of the Unit enum +- Fixed HideLabel Attribute not removing the label from an EnumButtons marked field + +EditorAttributes v2.7.2 Changelog: +- Added the ability to execute button logic from multiple selections +- Added a warning when trying to use an attribute from an ImGUI based editor +- Foldout states and button parameters are now saved by the object's instance ID instead of name +- Fixed dropdown reseting to default value when the inspector is refreshed while using dictionaries +- Fixed property dropdowns not working inside collections +- Fixed foldout states incorrectly loading + +EditorAttributes v2.7.1 Changelog: +- Unity's Space and Header attributes now work on ShowInInspector properties +- Validating all scenes should now also include addressable scenes +- Updated offline documentation + +EditorAttributes v2.7.0 Changelog: +- Added CollectionRange Attribute +- Added ShowInInspector Attribute +- Removed the drawing of static and non serialized members in favor of the ShowInInspector Attribute +- Fixed Button functions being called when selecting something + +EditorAttributes v2.6.1 Changelog: +- Added option to show all non serialized members +- Extended showing static fields to showing all static members +- Handled an error on ButtonField Attribute when it can't find the function. +- Fixed issue where Property Fields are sometimes not automatically binded + +EditorAttributes v2.6.0 Changelog: +- Added Dictionary support for Dropdown Attribute +- Added attribute search support for static and const members inside other types +- Added ValidationCheck class for more advanced validation logic +- Moved EditorValidation menu under the tools tab +- Fixed DataTable label alignment +- Fixed Wrap and Clamp Attributes not working with uint, long, ulong and double types +- Fixed Dropdown Attribute throwing error when collection value is null +- Fixed Dropdown throwing Index out of range Exception when the value collection changed is dynamically while using a custom display array + +EditorAttributes v2.5.4 Changelog: +- Added an additional parameter to Dropdown Attribute for displaying custom labels for items +- Added new CaseType.None to Rename Attribute +- Long DataTable names should now be clipped +- Updated how vectors look inside data tables +- Fixed Rename Attribute not working +- Fixed UnityEvents not displaying the property name +- Fixed UnityEvents and collections being indented inside foldout and toggle groups +- Fixed possible error when deleting an object using the Button Attribute +- Fixed attributes not applying to UnityEvents when inside a group +- Fixed message boxes not appearing back when the condition is satisfied in the editor + +EditorAttributes v2.5.3 Changelog: +- Added vector and char support to Dropdown Attribute +- Added option to disable build validation +- Added property context menus to non property fields +- Added ToLocalTransform function to the SimpleTransform +- Updated the ToTransform function inside SimpleTransform +- Realigned label on MinMaxSlider +- Fixed Hide, Show and ConditionalField attributes flickering inside arrays +- Fixed asset previews not loading when the inspector is selected + +EditorAttributes v2.5.2 Changelog: +- Added optional parameter to the HideInChildren Attribute to specify in which children to hide the field +- Added option to draw help boxes above the attached field +- Added dynamic string support to the HelpBox Attribute +- The HelpBox Attribute will now draw the helpbox under the field by default +- Fixed tooltips not being displayed on some attributes +- Fixed Rename Attribute not working on fields inside a horizontal group +- Fixed asset preivews not displaying when assigning new assets +- Removed the global update scheduler due invoked events generating a ton of garbage and tanking performance, all attributes will now use their own scheduler + +EditorAttributes v2.5.1 Changelog: +- Fixed attributes not finding properties +- Fixed overridden function mismatch warning in the UnityTypeConverter class +- Fixed Clamp and Wrap Attributes not setting their values correctly +- Fixed serialized objects not displaying in foldout and toggle groups +- Fixed properties not updating after opening the object picker +- Properties with the HideProperty Attribute should now be hidden inside a property dropdown + +EditorAttributes v2.5.0 Changelog: +- Added PropertyOrder Attribute +- Added Validate Open Scenes to the validation system +- You can now toggle the visibility of static fields in the inspector trough a component context menu +- The EditorExtension.RunUpdateLoop function is now public so you can call it from custom editor windows to make certain attributes work +- Fixed DataTable Attribute not displaying the labels in an array +- The validation system should no longer close any additive loaded scenes +- Validate Scenes will no longer validate scenes that are not part of the build + +EditorAttributes v2.4.1 Changelog: +- The validation system will no longer check for assets inside the Packages folder +- The PropertyDropdown Attribute will now save the state of the foldouts +- Fixed an issue with property dropdowns throwing "This Visual Element is not my child" errors +- Fixed an issue where visual elements don't update inside a property dropdown + +EditorAttributes v2.4.0 Changelog: +- Added Validation system +- Added Validate Attribute +- Added DrawHandle Attribute +- Added SimpleTransform struct +- Added ValueButtons Attribute (only on Unity 6 and above) +- Added lineThickness parameter to the Title and Line Attribute +- Added paramters to the Required Attribute to include it in validation or not +- Added repetable button support to the button attributes +- Added VectorUtils class +- Fixed alpha not applying on the Line Attribute when using hex colors +- Fixed vectors not drawing properly in data tables +- Fixed the PropertyDropdown Attribute not refreshing when part of a group +- Fixed obsolete error thrown from the SelectionButtons drawer in Unity 6 +- Renamed the ColorUtility class to ColorUtils to avoid conflicts with UnityEngine.ColorUtility +- Added the possibility to show static fields in the inspector but it’s experimental and must be manually enabled from code + +EditorAttributes v2.3.0 Changelog: +- Added HideProperty Attribute +- Added button parameter support for uint, long and ulong +- Added documentation for scripting API +- Improved the backend of the package to make it easier to create custom attributes or expand it +- Serialized objects and collections should now display corectly inside groups +- Fixed conditional attributes not being able to find functions and properties inside serialized objects +- Fixed an error sometimes being thrown then deleting an object using a conditional attribute +- Fixed an error thrown when a string button parameter is null +- Fixed an issue where the Dropdown Attribute error box doesn't update properly +- The SelectionButtons Attribute has been deprecated in Unity 6 in favor of the built in EnumButtons Attribute +- The Rename Attribute is now a decorative attribute + +EditorAttributes v2.2.0 Changelog: +- Added TimeField Attribute +- Added OnValueChanged Attribute +- Added AnimatorParamDropdown Attribute +- Added titleSpace parameter to the TitleAttribute +- Removed the fieldWidth parameter from all attributes having it +- Void fields will no longer be drawn in the inspector +- Removed the drawProperty parameter from the MessageBox Attribute +- The DataTable Attribute will no longer display the field labels in array elements except for the first element +- Fixed Button Attribute parameter serialization with Unity types +- Reorganized the project +- Updated samples + +• Ported the whole package from the ImGUI system to UI Toolkit which results in the following changes: +- Better layouts +- Collections will now have a scrollbar when too long +- Dynamic text will always update even if not focused on the inspector window +- The TypeFilter Attribute will now display the filtered type in the object field +- The IndentProperty Attribute will now use pixel values +- The labelWidth parameters have been changed to widthOffset and now offset the existing width instead of setting a completly new width +- The way inspectors are colored has changed and the ColorField Attribute has been deprecated for now +- You can use the UI Toolkit Debugger window with the package +- Since the inspector is now drawn with UI Toolkit any custom property drawers using ImGUI will not work, you will have to port them to UI toolkit or use the IMGUIContainer + +EditorAttributes v2.1.1 Changelog: +- Added an option to disable button parameter serialization +- The MessageBox Attribute now supports dynamic string inputs +- The PropertyDropdown properties are now indented a bit +- The PropertyDropdown Attribute will now work when placed directly on a field of type ScriptableObject or Component + +EditorAttributes v2.1.0 Changelog: +- Added IndentProperty Attribute +- Added HideInChildren Attribute +- Fixed members inside serialized objects nested in arrays or other serialized objects not being found +- Fixed an issue where serialized properties could not be found by grouping attributes +- Updated the ProgresBar Attribute with the built in look and removed color parameters +- Grouping attributes now work inside serialized objects +- The ToggleGroup Attribute will return the toggle value when placed on a bool +- The Prefix Attribute offset parameter will now increase the space between it and the field instead of decreasing it +- SelectionButtons, MinMaxSlider, FilePath and FolderPath attributes now display properly inside collections +- The File/FolderPath Attribute relative path will now include the Assets folder +- You can now dynamically change the string inputs on the Title, Image, Rename, Suffix and Prefix attributes +- Collections can now be affected by certain attributes (only available in unity 2023.3 and above) +- Updated samples + +EditorAttributes v2.0.0 Changelog: +- Added FilePath Attribute +- Added FolderPath Attribute +- Added ButtonField Attribute +- Added PropertyDropdown Attribute +- Added TabGroup Attribute +- Fixed ProgressBar label missalignment +- Handled SceneDropdown throwing an error when there are no scenes in the build settings + +EditorAttributes v1.9.0 Changelog: +- Added Title Attribute +- Added InlineButton Attribute +- Added SelectionButtons Attribute +- Changed the ProgressBar attribute label +- The attributes GUIColor and ColorField can now be attached to button functions +- When dragging a GameObject into a field using the TypeFilter Attribute will get the filtered component from it instead of nothing +- Added rich text support to HelpBox and MessageBox attributes +- Added drawInBox and showLabels parameters to the DataTable Attribute + +EditorAttributes v1.8.1 Changelog: +- Added some helpboxes when group fields cannot be found +- Fixed the dropdown attribute not finding the collection +- Added some missing null checks + +EditorAttributes v1.8.0 Changelog: +- Added DataTable Attribute +- Added ProgressBar Attribute +- Renamed the Assembly Definitions +- The name of a field using the Required Attribute inside the help box now looks nicer +- Fixed members couldn't be found by attributes if those attributes are used inside a base class +- When a member could not be found it will now display a helpbox instead of spamming errors in the console + +EditorAttributes v1.7.0 Changelog: +- You can now find values inside structs +- Fixed min or max value of a MinMaxSlider going over or under eachother when values are set by fields +- Added HideLabel Attribute +- Added Wrap Attribute +- Added Required Attribute +- Added TypeFilter Attribute +- Added SortingLayerDropdown Attribute + +EditorAttributes v1.6.1 Changelog: +- Made the Helpbox a decorator attribute +- Removed the UseRGB option from the GUIColor enum +- Added enum support to Button parameters + +EditorAttributes v1.6.0 Changelog: +- Added ColorField attribute +- Added GUIColor attribute +- Added option to draw groups inside boxes +- Fixed functions not being found +- Handled Illegal characters in path ArgumentException on the button +- Updated FoldoutGroup GUI + +EditorAttributes v1.5.0 Changelog: +- Added AssetPreview attribute +- Added FoldoutGroup attribute +- Added ToggleGroup attribute +- Added the ability to show/hide or enable/disable buttons +- Button parameters now persist after you deselect an object + +EditorAttributes v1.4.0 Changelog: +- Added Prefix/Suffix attribute +- Added DrawLine attribute +- Added TagDropdown attribute +- Added Image attribute +- Added VerticalGroup attribute +- Added SceneDropdown attribute + +EditorAttributes v1.3.0 Changelog: +- Added MinMaxSlider attribute +- Added Clamp attribute +- Added PropertyWidth attribute +- Added LayerMask support to button parameters +- Refactored the Button attribute drawing system so now the attributes can be placed directly on the function + +EditorAttributes v1.2.1 Changelog: +- Fixed public fields, properties and functions of type List not working with the dropdown attribute +- Handled an AmbiguousMatchException when creating a button that uses a function with overloads +- Buttons with parameters now show in a nice box + +EditorAttributes v1.2.0 Changelog: +- Added Rename attribute +- Added HideInEditMode attribute +- Added DisableInEditMode attribute +- Properties and functions can now be used as parameters +- The MessageBox now supports enums +- The Dropdown attribute is no longer limited to strings +- You can now have functions with parameters as buttons +- Updated the summaries for some attributes +- Internal refactoring and general optimization + +EditorAttributes v1.1.1 Changelog: +- Removed offline documentation +- Removed samples +- Updated links +- Updated Readme + +EditorAttributes v1.1.0 Changelog: +- You can now enable/disable fields using the ConditionalField attribute +- Added enum support to the Enable/DisableField attribute +- Integer casting is no longer required for enum paramters +- Fixed drawing issues with UnityEvents and Structs on certain attributes + +EditorAttributes v1.0.0 Changelog: +- Initial release diff --git a/Assets/EditorAttributes/CHANGELOG.md.meta b/Assets/EditorAttributes/CHANGELOG.md.meta new file mode 100644 index 0000000000..e6b1d31ed5 --- /dev/null +++ b/Assets/EditorAttributes/CHANGELOG.md.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 38cf2e5a105caa44592610edada4cba0 +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/CHANGELOG.md + uploadId: 806636 diff --git a/Assets/EditorAttributes/Documentation.meta b/Assets/EditorAttributes/Documentation.meta new file mode 100644 index 0000000000..543f6f26a3 --- /dev/null +++ b/Assets/EditorAttributes/Documentation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3477698a63f41f149a2c69048426971f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf b/Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf new file mode 100644 index 0000000000..ae2b858d63 --- /dev/null +++ b/Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf @@ -0,0 +1,1048 @@ +{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033\deflangfe1033{\fonttbl{\f0\fnil\fprq2\fcharset0 Roboto Slab;}{\f1\fswiss\fprq2\fcharset0 Lato;}{\f2\fswiss\fprq2 Lato;}{\f3\fmodern\fprq1\fcharset0 Consolas;}{\f4\fswiss\fprq2\fcharset0 Calibri;}{\f5\fnil\fcharset0 Calibri;}{\f6\fnil\fcharset2 Symbol;}} +{\colortbl ;\red64\green64\blue64;\red252\green252\blue252;\red0\green128\blue0;\red187\green187\blue187;\red0\green0\blue255;\red41\green128\blue185;\red61\green123\blue123;\red176\green0\blue64;\red104\green120\blue34;\red231\green76\blue60;\red255\green255\blue255;\red102\green102\blue102;} +{\stylesheet{ Normal;}{\s1 heading 1;}{\s2 heading 2;}} +{\*\generator Riched20 10.0.19041}{\*\mmathPr\mdispDef1\mwrapIndent1440 }\viewkind4\uc1 +\pard\widctlpar\sa360\cf1\kerning36\b\f0\fs42 How To Use\par + +\pard\widctlpar\sa160\sl252\slmult1\highlight2\kerning2\b0\f1\fs22 Prerequisites: Familiarity with basic C# programming in Unity and knowledge about how to use Unity\f2\rquote\f1 s built-in attributes.\par +\par + +\pard\keepn\widctlpar\s2\sa360\sl252\slmult1\highlight0\b\i\f0\fs28 Importing The Namespace\par + +\pard\widctlpar\sa160\sl252\slmult1\highlight2\b0\i0\f1\fs22 To start using the editor attributes you must add this using statement in your class:\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\highlight0\kerning0\b\f3\fs18 using\cf4\b0 \cf5\b EditorAttributes\cf1\b0 ;\par +\par +\highlight2\kerning2\f1\fs22 If you are using\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://docs.unity3d.com/2023.3/Documentation/Manual/ScriptCompilationAssemblyDefinitionFiles.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 Assembly Definitions}}}}\f1\fs22\~in your project make sure you reference the \f2\ldblquote\f1 EditorAttributes\f2\rdblquote \f1 Assembly Definition where needed.\par +\par +\cf0\highlight0\kerning0\f5\lang9{\pict{\*\picprop{\sp{\sn wzDescription}{\sv Image}}{\sp{\sn posv}{\sv 1}} +}\pngblip\picw16764\pich7620\picwgoal9504\pichgoal4320 +89504e470d0a1a0a0000000d494844520000027c0000012108020000006a77eab5000000017352 +474200aece1ce90000000467414d410000b18f0bfc6105000000097048597300000ec300000ec3 +01c76fa86400003e7049444154785eeddd07785455de06f04c7a6ff4de1248207442ef6de94de9 +2222104057691614655d77575d7775b1ecaae08a8aae0d44fd40505414a51b5a6849a8a1190821 +bd4e92ef9d3927d79b69992493c930797f0fcf70ceb965ce9dcccc7bff339389a677efde2e4444 +440e232525a559b366b2e3d82e5fbe5cb76e5dd9294f5e5e9eab6c121111513563e812119163d1 +6834c5c5c5b2e3c030494c5576acc3d0252222c7e2e3e3939696e6e0b98be9619298aaec5b87ef +e9121191c3c9c9c9c9cdcd2d2929917dc7831a1789ebebeb2bfb56c8cbcb63e8121111d9033f48 +454444643f0c5d2222223b61e8121111d90943978888c84e18ba65b8baba06050589dfbbf2f6f6 +168326995b6a792bdb52cf9688881c9f5bd3a64d65d3a28913270e1e3cb8a0a0e0c68d1b72a89a +050606de77df7db9b9b9376fde94437af5ead59b33674e6a6a6a5a5a9a1c32456cde43af7dfbf6 +08a7e4e4e4a2a222b9d89476edda2d5fbe7ce8d0a1972f5ff6f7f77ffcf1c75352527efbed37b9 +58a565cb96ca52ace9e9e9895bc6605cac693df584a3a2a2424343af5ebd6ae1d7d4d4b3c535ca +51222272545aadd6aa4a17b9d2af5fbff0f0f0fefdfbcba1ea8724c335222c65bf144a498c0704 +04c8be1962731f1f9fcccc4cac3c7efcf865cb96f9f9f9c9c5a620c0f2f2f25e79e595c4c4c4eb +d7af7ff9e59768c86565a9972229c178bca2c4843d3c3c90a06e6e6ea3478f9e3b77ae5c668a7a +b6728888881c9b55956ecf9e3d2323238f1c3982cb83070fe6e7e78b71149dbd7bf7eedab56b70 +70306a3b5196991c747777c720f6d3b8716354aea80b91a623478ecccacaead5ab57c78e1d6fdd +ba85441c3e7c78ab56ad105d858585bebebec8f83367ce346bd62c3a3adad5d55594bcd810bb3a +76ec1876d5bd7bf7b367cf6210898594425629359fd87cd7ae5ddbb66d3b74e8504242c2a04183 +7015a74e9dc252e3f9e0ac02d310bf887df1e245447b44440466857d629e486ecc010785f31414 +d9380b114b5143a32a45b46356e7cf9fc7958a711c17ae028706b88531821b4d1cb2c1aef493d5 +1113fee9a79f76ecd8819b1a1340c9bb7fff7e6c58ee6cb12b73b7308219bbc50c51e89b5bc778 +4a386aac86953179dca4e2276ebc39064dfeb88988c898b5952e9e52f17cfacd37df68349a2e5d +ba88c1c0c040d48ee86270cc9831d3a74f373788f682050b108a28e3f0e48e15900158132978cf +3df72065f1ac1d131383c2ae61c386c3860dc3a0fe1a74060f1edcb973e7962d5bce9b37af4f9f +3e72540f313c64c890e6cd9ba3ddae5d3bac69e1d5e34b972e216e1190689b9c0f320f4903288b +b182981e124534eebdf7deb66ddb22e7162d5a84930065293634b995b80a94d75e5e5ec8ce152b +5620934cee4a4ccf9888349c4c58335b93eba8af0e6709e5aea34c096bce9f3f7ff2e4c9b81644 +ecf2e5cb2d6c8e86c18f9b8888cc293f744343435bb46871f4e851543c57af5eedd6ad9b184740 +2251f6eeddbb79f3e6fffce73f7bf6ec313788440c0b0b7be79d773efef8e3575f7d15cfe0ca4e +5037af5fbffeebafbfc6b57cf1c517ebd6ad8b8d8d450c8ba5909494f4c61b6fac5dbbf6dab56b +885539aa77e2c40914c422473b74e890919161f98556514c23a84cce67e7ce9d28f2500efeef7f +ffcbcdcd95db9442e9f9d65b6ffdfbdfff46ba607339eae282c214370b602b4c468e961e328e08 +e3983fca5665f2e676254446468e1a356aead4a958ffca952bd8b335b335b98ed8e1b163c7fef5 +af7fe12762611d8329218061d3a64d1b376ec44f07b73c4a5b939b9bfc7113119139e5872eca5c +5ca2ace9d7af5f4e4e4e93264dead7af8f910b172ea07cbcfbeebbd7ac593374e85011392607f1 +d48ccb3973e63cfdf4d32b57ae44858a5a1023205eccc46e7189d4c4657676b6bbbbbb6e99deb9 +73e770595c5c7cfefcf93a75ea2032c538e4e7e79f3c7912718b1db66fdf1ec961f95b3a91b898 +0faa610bf331477c300ab18d4bc48c7ecc127115e2a5efb4b4346467a3468df44bcad9156edb88 +880814c7e9e9e96fbffd3646ac99ad8575f0e3100d0beb184c494c554cfec68d1bc8dd84840493 +9b9bfc711311913956852ee20da9d6bf7fffe0e06031824b3cc3bef6da6b2fbdf4d2f7df7f8f52 +78f1e2c548449383e21dc10f3ffc10e514fcf39fffc452ddaead808a4a6968b55a8317900f1f3e +8c948a8e8ef6f5f5455b8e9a821570082248aa321f2be5e5e5e112572aba68889172a1744659bf +7fff7e94fee2d8ad99adadd61144a12f3e7486706dd5aa556060a0c9cd4dfeb875bb20222253ca +095d143d287176eddaf5f75257ae5c11a11b1919f9d4534f356edc382e2e0e831e1e1e78823639 +78faf469e425a211974d9b369d3f7fbe95bfa704bd7bf70e0f0fc7354645459d3973468e968a8f +8f47953c76ecd8e4e4e4ab57afca5195e6cd9be37a478c18b162c50a4f4fcf1d3b7660b02af331 +565050807311f54be280a962e7a3468d4239386cd8b0808080e3c78fcb6556d8b97327f20cc785 +b635b3b5d53a02268f6b1f3d7a347efa3884071f7c1047617273933f6eb91722223252ce53a4c8 +d763c78e892ea05db76e5d84594242c2b973e766cc98b166cd9ad6ad5b7ff2c92778a636399896 +96f6c1071fb46bd7eec9279fc4a2c4c444ac2677579ea3478f6293d9b367fff6db6f5bb66c91a3 +a550f862050b652ee63f7dfaf48103075ebf7efdf5d75f17c15c95f918dbb3678fb7b737924929 +ca0157b171e346a4d1e38f3f8ec8ffe1871f626363e5322b646565eddebd1b9116161666cd6c6d +b58e909e9e8e359b3469b272e54adc743803c0cfd4e4e660fce3967b2122222355fdd37eeeeeee +c8bccccc4cf5fba92607351a0d6229373717a5921cb20e3644aa197fb849183366cc9021439e7f +fe79f5afdf58a3d2f33186f20e65b4f10bc836bc0a6b7665ab7504936b9a1c34f9e32622220388 +893bf8efe922e71e7becb1a0a0a003070e6cdab4498e121111392484aeb55f03e98010ba28b9f6 +efdfbf7bf76e39444444e4a8b45aed1d5ce9121111dd4150e9f2b3a644444476c2d0252222b213 +862e1111919d587a4f97bf7349444454151e1e1eb2c5f774898888ec89a14b444464270c5d2222 +223b61e8121111d9093f484564424646c6cd9b370dfe94a4013737b77af5ea050606ca3e119111 +830f523174894cb87dfb361e2a96ff3c3022198f91909010d9272232c24f2f1395afa4a4a4dc3f +c88f15f8879588a8422cfdc183e2e262d9d25bb060417c7cbc52fe3668d060e2c489717171a25b +51ad5ab59a3265ca8811233a74e8909b9b7bf3e64d316ee15a944568f4e9d3273a3a1adb060404 +5cbf7edd60aa445584fba4fafcd4406060607e7e3e1a5aadd6c7c7470c121119539fbee319a302 +956e585898fa6908cf35084ed9a9a0f6eddbcf9f3fffd4a9531f7cf0416c6cec8c193310a26291 +856b5116a1b16bd7aead5bb71e397224222262e9d2a5169e1f896cebde7beffdfcf3cff9562e11 +55826d5e5e46b9899a75ead4a91d3b761423c8f6be7dfb6264e0c081c68978f7dd77bffffefbfb +f7efbf76ed1a42f7dd77df9d306182ab6b0526830d9392928e1d3bb67efdfaf4f4f4c183078b71 +e39910d910121770efcdc8c89043444456b341e8225357ac5891979777e2c489d1a34777ead409 +8373e7ce6ddbb6ede9d3a71b366c18131323d6141a3468a0d16812121264dfc5e5fcf9f34f3cf1 +44a55f22debd7b775454141a2667425415f5ead5932d55e2821c2222aa081b84aebfbfbfb7b7f7 +afbffe8a887de59557e2e2e29a366d8a647defbdf7107e9f7efaa9c10bd1818181b76fdf166d6c +d8a354a5df1b4b4d4d0d0a0a42c378266205a2cac17df5a38f3e42d0a2cdc425a2aab341e82241 +f7eddbf7f4d34fa3a2edd2a50b4650dde2d96ae5ca958fe8d5d1132b032a51255f519bb6d49b36 +6d5aa5df240b0808c8cdcd45c378264455919191818845d6befcf2cb4c5c22aaba0a842ec2d2cf +cf4f765c5cd01651075f7df5d533cf3cf3f3cf3f0f183060f8f0e1f9f9f9494949ff2ef5ecb3cf +1e397244ac09d7af5f0f090911319c9999b969d3a66ddbb6b9babaa6a7a763c4c2b598d3b973e7 +73e7ce89b6c14cc42051a589a0edd4a99368c85122a24aa940e8c6c5c54d9e3cd9d7d717ede0e0 +e0b163c71e3f7e1ced060d1aa04e2d2c2c3c7dfaf4c9932743434311814d9a3441ac222f351acd +8c1933bcbdbdf5fbd0d16ab5bb76edbaefbefb44ee6287b366cd3a7af428e2165d73d76212561b +326448f7eeddbffbee3b748d67225623aa0a64edaa55ab98b844547515f8462a0f0f8fa953a776 +ebd62d2b2b0b05e89e3d7bbefcf24bf11d0273e6cc69d6ac19521305ebdb6fbf7debd6ad888888 +e9d3a763242828e8975f7ef9faebafe55ef490c423478e1c3c783002d8cbcbebf0e1c39f7ffe79 +4141011699bb162c7a412f2d2d0d97d803468a8a8ace9e3dbb75ebd61b376ea06b72261827aaa8 +d4d4546b3e6480d34a9edb1191050835d9aadcd7407a7a7a060404646464182cc5331482302727 +47f65144bbba624d8c98dc0f607db102a2570e9532772dd6309e095145f16b2089c826aa1aba44 +b501eefc59595996bfe511e776fefefeea4714119101862e1111919d1884ae0d7e6588888888ac +c1d0252222b213862e1111919d3074898888ecc4d207a9888888c856f8412a222222fb61e81211 +11d90943978888c84eca794f372727273737d7f2f7f2101111919a46a3f1f1f1117fbc4751ce37 +522171b1597070b0ab2b0b622222226b151717a7a5a5a16455e76e391fa442e886868632718988 +882a04d1890035fed33b962add94949466cd9ac90e1159e1d6ad5b59595938c9957d227276c857 +7f7f7ff117e20d5cbe7cb96eddbab253eecbcb0c5da20a41e2666767bbbbbb6bf47fef9988ee44 +414141b26585929292828282cccc4c3f3f3fe3dc350e5dbe744c6433a87199b844b50a1eef5e5e +5e01010178f8cb218b18ba4436535c5cccc425aa853c3d3dad7c5389a14b44445425d69f6dbb35 +6dda54368de4e4e454e8a56d9366cd9ad5a3478faea56edfbe9d9e9e2e97e9f5ebd7cfc7c70733 +7ef0c1077ffdf5d7a2a222d1add04751faf7ef1f191979eedc39d9777151efc4e40eebd6adab5c +2326191f1f8f865c665e25e646b5475a5a9abbbbbb68979494787979a1ab707373c338ee3cb80b +897588c801797b7bcb56a9d6ad5b4f9e3c79c2840983070f6ed3a60d520c59269795cacece0e09 +09919d52191919ea5f19d26ab5d51eba98e58e1d3bce9c398344849494145cab5ca6d7bd7bf7bc +bcbc8b172f5ebb760d4b313269d2240f0f8fdf7efb4dac502e3c974d9f3e1d07121b1b5b585828 +06d53b31b9c3fcfc7ce51a31c9fdfbf71b4ccca48ace8d6a1575e8366bd6eca5975e120f5461ec +d8b138353c7af428ee7b4aee3efae8a3c3860d1b54eae6cd9be23ea918376e9c9f9f9fababeb8b +2fbef8dd77dfe1d45074ad3947548c1f3fbe57af5ec78f1f977d1717f54e4ceeb071e3c6ca3562 +92787059738d95981b91a33108dde1c3878f1e3dfae79f7fdebe7d3b92a2a0a060ca942908820b +172ec835f41c2574070e1cf8c30f3fe07924534f041b9e98f014d0ad5b373cf5a0e2c4b46edcb8 +d1b973671c43c78e1d3b75ea84ebc5615fbd7a15818a4219b01ad6c18319878a7da28c183264c8 +f5ebd7f1fcd5ae5d3bac7fe5ca153ce07189fdab77121a1aaab4b107655b3cbb614371ab61302e +2e6ec080016ddbb6c52471dbe15a7046a3dca6b8d12f5dba1415156530379c3100ae02312cca5f +7f7fffdebd7b63352c3578f624a7a70e5d84d6fcf9f371dfc0e3302838243824a46edd3a78b821 +8c7ffdf557e5ec30262666e3c68d18c13d1070bf52160943870ecdcdcd3d79f224ee8db8c36364 +f1e2c59e9e9e384f152b940b77c5e5cb97e3f41c8f443c5f8841f54e4cee100f7fe51a31499c3a +1b4ccca48ace8dc801a94317352e12f7e5975f4e4a4a42dc001e1478c04e9b360d71a3ae77ad0c +dd8abda7dbca22b9921566ce9c89a79ec4c4449cf8e390308290430ca3217ee90297a29a9c3a75 +2a9e2c121212828383efbfff7e3c7d604da463bf7efdf0c016cf205dba74c1293ca0812ea877a2 +6eabb745f48a6b1450886005a4f2bc79f31a356aa4cc47e8d3a70fae5abd2b0ce246c7e47114f5 +ebd79f33670e46b0d5a2458bf05341658fe7caf6eddbebb7a65aad405b7cfcf22dfc43c3c7c707 +773fe4b15ca68707b3781d087007c308ee4863c68c59b870214ee9c43ac8727177eadbb72fee75 +b8fcc31ffe802eee9623468cc09aa865b1738c787979dd75d75d111111b82b8adf55e8dab52b4e +190f1e3cd8bf7f7f7441bd13755bbd6d83060dd477e0c0c0c07beeb967eedcb9cd9b3747176be2 +fe2f16011ed198a17a5718c4dc70b6ba60c1023c67e188c49a386745f58fd391e8e8683142e4c8 +507d7dfdf5d738074589884251d48ae862108be44a1551b1d0c599af0572252378802d2d85c71e +9e71ead5abb779f3e6d3a74f6fd9b2c5e0f4f9dab56be9e9e9b8c4d304c20f95c1a64d9b9061db +b66d43c48a67013c983ffbecb3a3478fa202c0130d1ee7a74e9dc204020202b067839da8db06db +eaaeafd4eeddbb8f1d3b161b1bfbf3cf3fe369518e96a5de15e6866734ec0a73fbeaabaf706684 +27239cd1e0c908fb4112bffdf6db3840b925d54a25252e8545c5b985dab8cbb7f00f8da212175f +5f3fdc09e51a663cf2c823e1e1e1b897f6ecd9b343870e1841f928920c67d9b813e212518deeb2 +65cb3a75ea74f8f061dc1b9f79e619241fd69c346912321877bfbcbc3cac3368d0a05ff4060e1c +882ea877a26eabb72d2e2e16d728a0d8c5dd1ea7f64f3ffd34ceb095f9083845c055ab778541cc +2d2a2a0a478147f1aa55ab3082ad9e7bee393cf4f0404366e3e8f45b13392ed487381b460327af +b3f5d040178395fb1e0b7b7c7af9e38f3ffe6f2914d7a80b915bcabb3e688b8631ac79f5ea55e5 +ad5694a7184103a5a412d5785467656575eedcb9478f1e78c02bc5ae39ea6dd5f04c211a78be10 +c96d1966828c5fbc78f112bd103d4ce0d75f7f5dbe7c396a0296b954e25292969dffe981b3a7ae +df3e712df5e3fd676f67e763502e2e85b05c5b0a276d38896cd2a4c9ebafbf7ee8d0a137de78c3 +e0ee8a93cb5bb76ee112b9d8b265cbb0b0b0575f7d1519b661c30644ac883184fa2bafbc82f348 +3c34fcfcfcf01841997bf2e449dc45b167839da8dbea6d45cdadf8e28b2f703efafdf7dfe31473 +dcb87172b42cf5ae10ccb82eec0a8f88f5ebd7631aeddab543b98cb364ec0749bc66cd1a1ca0dc +92a8d6b0c7cbcb78f4e2c12f94949420f6d4af71ab5f3d3780d256bc6226602be51d29054e3a10 +cc22f3d040fa2a1f51a910e58af0ec8019629eaea55f3a8d1d1a97269809ae0ecf74c2cb2fbf7c +e2c4098c7ffbedb72fbdf4d28103077af7eead1416543ba1d2cd2ed0dec8cc2dd016ddcacc3d71 +3515a15b5c6c18bab8f3207705dcaf501722b794b35271966d124eb4cf9e3daba4f2a953a7c4a9 +374a49e591d2b76fdfb4b4b40103060c1f3e3c25250555af183747bdad1aa6241af1f1f122b92d +c3510407073ffffcf32fe83568d000e7a99800621b67098f3ffeb8faed1b228775f9f2e5366dda +a071e4c8910ff5d040178358a45fa562ecf1f2b20114ac0d1b36148f5bd494385517e30a3cdda0 +884403fbc463158f5eb48382823a74e88007bc7e15293434b46eddba380747d4c1b66ddb909722 +fe959d18b4cd115f8789a0edd3a74f42428278f119350712178b9400567685a368d4a811925ef7 +5d9a1acda4499350a3e070264c988027c1c4c4444c154f3a622baab5bcdddd86b56fd6aa6e6051 +7109fe15e36c4e2ef95d4646067251c072dcf7fcfdfde532fd47f364cb08ee7b066b8ad793d590 +b20866041e20bf91be953b2bc5c9a868a05ac50c8b8b8b9533519367a59809aeee2fa5fef8c73f +eedbb70fe378ce7ae08107bef9e69b51a346e15123562672583ffef8e398316350f2e1b179580f +0d7431884572a58ab0c7cbcb0f3ffcf0ea525dba74c123163179cf3df7e0b13771e2c493274fca +f54a1d3a7408393777ee5c3c6e3ffbecb3e9d3a72f59b224262666e7ce9d376edc902be9616fd8 +5ca909e0d8b163e205776527066d73d2d3d3972e5dba62c50a5ce9fefdfb3182089f3d7bf6134f +3c81e714a598507685a3d8b469d3ac59b31e7cf0c165cb96ddbc7933272727353515853bba38b4 +c8c8c8ddbb778bada8d6cad316fd70facac5940c77575777378dab15898782b5458b16e2e41ae7 +a69d3a7512e30aad568bb33d3470e76fdebc79787838da75ead4c1f9626c6cac7e150967b78d1b +377eebadb7c419fa860d1b702f8d8a8ac2226527066d73f014834b9c7da281e79decec6c3cf574 +ecd81107347af4682574955de1285ab66c89a4c79a5867d1a2453e3e3e389c850b17a2923e7af4 +28a66acdfb384435ebfcf9f348044443b76edd50fb011ae8e224128be44a1551637ff0008f523c +08b3cc7c59251ea5eeeeee22eaf038c7293c1ebaea70b5867a27eab639980f56c3b392ecebaf1a +2306d76b3c3704b07acfc85dac8341d9a75ae3c2850bcadb251111116ffff7bfb732f3be3a72f1 +46662e6adcfa013e13bbb5aa1be0bd60fefc3367ce88d5de7df75ddc5b9402f89d77dec1b95acf +9e3d172c5870fbf6edfcfc7c9ccf21c00e1e3cb876eddaf9f3e7631da4ec238f3c929494f4b7bf +fdad73e7ce381fcdcccc0c0e0efef4d34f7ff8e18780800065cd69d3a6617cddba75fa7deb4c9e +3c1931fcef7fff5bbd13a5fdeaabaf2adbaaf783496ed9b265e8d0a11e1e1ea85fb11aeef0a8a1 +314934366fde3c63c60ca4294e588de78607546868e8b7df7efbc9279fe051ffd0430fe17c0283 +78ecfcf39fff4c4e4ed6cf8bc881205965ab54ebd6ad070f1e2c02f1f2e5cba8718d13177766e3 +b7598dffe001ffca1091cda843b769d3a6cf3efbacab9bbbb6b844abff1d6e5db1ebaa292ed2ae +59b346fc42b90538b1c3f95c5a5a9aec97859cf6f4f44424a38df44271999e9eae7ce4d04aea9d +a8dbe6f8e9bff802012ffbfaab0683eb35981b521fe7d6eaf789c52bd5061fd422721cc6a16b0d +862e91bda94317c5ab97971752070de49018c165515111aa433142440ea812a18b47f78d1b37ac +095d7bbca74b544b8888156dc42aca3b3cc650f3e152340075211397c8c9e0c18e87bfec58c4d0 +25b2197f7f7f64aa92bb44e4f4f078c7c9746666261efe72c822bebc4c644bb76eddcacacae2df +a122aa3d50e32271ebd4a923fb2a7c4f978888c84ef89e2e1111518d61e8121111d989a5d0d568 +347c6b8a8888a81210a0c6bfaa6029747d7c7cd2d2d298bb4444441582e844802a7f4a4761e983 +54909393939b9bcb5f812022227bba533ec67bd9ccdf1a428d8bc455ff493d28e7d3cb444444f6 +7707fdee8cc1e7932de3a797898888ec87a14b444464270c5d2222ba83ddab273b0e8fa14b4444 +77b0703dd971780c5d2222ba8395e8c98ec363e8121111d9097f658888881c4b4a4a4ad3a64d65 +c7947befbd372c2c4c76ca3a7bf6ecfbefbf2f3bd631b9372bf773e5ca950afdca909be50333c6 +2fca2022a26a959b9b1b1818283ba674ead4c9e49fd20304f6f1e3c765c73a26f766e57e323232 +94af9d32fed247035aadb69c4a97114b44447656a12fc7f8f39fff8ccb3ffde94fa26b6796bf1c +c32086cd7e3986fe6d691dd927222272488e9c56626e20fb2e2e862f2fab975960e56a44444415 +55eecbcb6a83070fc6e54f3ffd5423c1245e5e2ef78565a1a8a8a84ca56b61c658a42647898888 +6a544242427c7c7ccd06934846851c358245f23d5d732b59d8988888a83a94fbe965c771f5ea55 +731fe902e3f774752f2f9b4c566be296914c44443657a197976b56464686c1dfef33a644af56ab +75ad50e2625c4d8e121111d9948c1987673055317903ea71ab3e4865fd2011115115e5e5e5f9f9 +f959f9e9a41a545c5c9c9d9dadfc9eae9ac9c917151595095d831c557719b14444641f489cfcfc +7c4f4f4f47ce5d246e7a7ababb9e1cd253cfd960fe085d4daf5ebd44c764c45ace5de3112222a2 +aacbcdcd45bdebc8298340f5f6f6367843d764e22a0d1c910c5de370555faa1ba06e1311119141 +c4aa2f958689d055b256504604751b0cba444444b58a12ab8292b58232221a32740d6255c8cfcf +97434444445411e20d6991b8e21210ac9a9e3d7b8a0ec8bcd58b8d8d95a34444445411ddba7513 +a10be88a4b842eff883d1111918d89f25534944bf83d74952150b7898888a8420cb216d006137f +f0405c12111151a52961aa4e5519ba269711111151258830c5a541aaea42d760088c47888888c8 +7aea2455da263e48c5c4252222aa0a91a4c679aafb9521f5325c161717e3f2c89123fa15888888 +6aa3fd9327cb5605f5deb2a553a74eaeaeaee25786048c1bfeca10b21644438c1011115125984c +52d37f4f97888888aa484958a561e23dddf26d5f24ab65cda2ed72c800d6e8f7ca59d9a90add55 +99bb12db3039556be6fffbad00e5ac2dd6c54a675fe967615d934b2d6f629deabf198988e877ea +8256dd36fc95a1f22103c6b87c8d0d20b17d820d9ec9cd27dcd957fe7a2226e6c45fab1839d5a6 +efda4471437c1db52cdc7caa6d5f34665d0c6eb23d4bc3c296eed1fd271718fa7da9ea36b1bc89 +356c70339aff19111191794808d9d2ab78a59b786a6fdff6e1a21db674e968d1aa1667b77dea32 +edd147a7b97cbacdc19fef47bf95b8b6efba2fcc9f812837590db8736e462222e76110b742c543 +77f4a498bdcbe61a543dba974005a372cfc422f5104aa831eb5cf6a25034da541f1663c3c2c6aa +e3c26077467b371cd09768dbe5208694e5650ab744395ab69ad3adfbfba42c177b98a592ba65e6 +f0fb01eab756f6a26fbc225fa22eddb158fafb26faab573651ef599998c9fda855fd6634980f11 +11555225ded31dfd5649e2b44ff104ac7ade0fff749a78a1f56b97b22f621a2fc2d3b93254f2d6 +68ecedeb18f13aed5b65ab661916fa3c53e262fb3f9645c9d7b675ab1b744dcf64efb2bfbabca7 +1b895937463357df447befb27f940648e90a896b5dca9c4e842d7d2a46295fb77fb12ee6296b5e +e5359843b8728046af11ef5d766a927e35f564c0dc6d823d971e6ee2da1363948435b71f3d1bdc +8cbf1f42d9f91011d53abd3fffbcf7962dbac6962dba46e99fedb352a53e48a57f9b51ffbcafcf +ddb3092744190463d6ed3d9528d702e345c880bd5685971216222e649a84b7efbbeef7b431ec9a +9e49dfb5efe9af0f35ba4b5fb94b5dfb4482dcae74055dc89699be6e3599badbbf38b1f6d17212 +47ff1ab2855bc3505fb9c73293314fb7e79849620e65a66a693fb6bb198988c865ff9429b814b9 +abfb455eeb3f11a557b9d0d50b5bfadeefef63ea3e272419164316165980e26b6fe913bf267cd9 +5e17714dfab87fcf652e0675796fd0d5a9dcd509bab4296bf4a36b751f40d27d1449469719ba93 +89a8b6728daaccc1b66ae46624227266e24b332af7d519150fddedaf945644ba9cd11577616da3 +5cd699fe68acf122945b7dcdacacb6fd8b75ca478375ca7c4e091981be52d3fddeb530134bf6ca +575df555b82c254be95f94fdc73f9472d134f1c2af3e9d2a39072be8f72c6f049c05ac339caa09 +76bd1989886a05e5e565d1ad904a7c90aaed29a5708afa5aff3ea5eeb3bb2ea5e594522be9192f +c273bbfe176c9401ddaba2fa624cb5a12e2ccaa49c3eab1117dbe5278670ddbad7a80dba966662 +41dfa853ba224f7f4046655dd8d2a7a2d6ad13bb37a4d4907f6d9fa81484959b830113b789d8f3 +8931faddeade732dbf02b5ddcd68723e4444b54eefcf3fc7a528732bf19eae263a3a1affa10812 +97427171f1d1a347f52b902e92be98c4175989886a97aa7cf7726464246a165757570f0f0f51bf +80e1772f9309bab773cbfd0815111151f918ba16e87f5935fcd369e2b3cd44444455c3d0b5204c +f7a1de2a7e052311115129862e1111919d3074898888ec84a14b44446427fc95212222221be3af +0c111111d530862e1111919d3074898888ecc4ec7bba010101fa15888888a862525252347c4f97 +8888a8069557e9fa372a693ea824a48d8babbbae4b444444c68ab59adbe734493fb9645d47cf5c +a56b3174fd1b1577be3ff7c49682cb874ab4f9ba9d52592fbef8e2638f3d263b4444545b69dcbd +3c9b45fb444d763df60e72b7322f2fa3c645e2e65ff885894b4444640182127189d04474ca2153 +2c866e481bd4b8b2632388fdfaf5ebcb4ef5b3f3d51111516da67b6138a48dec9862f18354aeee +56d6b8289f3ffae8a3574aad5cb9522e28e5e7e78771345ab76ebd74e95231d8ab57af0a7d461a +d7f2dffffe77d8b061b25f760f26f7a65c1db6fdcf7ffe23062dabe8ac888888045d685afc0854 +053ebd5ca74e9de5cb97bff6da6bb8445b8e96cacdcd45bc092fbdf4921cd5d79a9e9e9eb2e3e2 +72f6ecd9d5ab578bf61ffef087e0e060d1068d46e3e5e5253ba53088c016ed1e3d7a5cbe7c79c0 +8001a20bea3d18ef0d1baaaf4e102fafcb8e29c6fbc126b2a3e7a6273b444454cbc4c4c4040505 +89361ae88ab635dc9a3469229b2a252525c8bf921683f3e277c8211797c58b17c7c7c7af5bb72e +303010e5e6fefdfbe5027d0e8d1f3ffecb2fbf94fd5223478e7cf8e187fbf5eb8769356bd66cc7 +8e1d8d1b377ee491477efcf1c769d3a6454747474545e5e4e4204a070e1cb86cd932ac09c78e1d +cbcbcbc39a8f3ffe78fffefdbb76edba77ef5eec6df6ecd95bb66ce9debd7b5c5c5c7676b67a0f +7dfaf451da454545ca86172f5e145787198e1933a661c38693264d9a3871627272f26fbffda64c +063b1f346810e23c2222423d2b8ca06ac7ae7af6ec79e4c811ad563b7ffe7c5ceff0e1c371239c +3e7d7ac488113b77eed41f2b1111d50a28e7c68d1b979494e4eded8d0682293ffff75785bd2346 +6b927e4288a06603a48f6800e2a902956eebd6ad7ff8e107c4212ed196a3a5500e22d504441746 +907098cd137ad84aaca6f8f4d34f2f5cb880ba79cf9e3df5ead59b3a75ea9a356b9e7cf2c97dfb +f6dd77df7d629d468d1abdfaeaabfff8c73fd046c8e1fc003987f545b1abde83ba6db0a1222424 +e4e8d1a34f3df5d4dffffef7850b171ad4af82c1ac264c98b06ad52acc1f898b19b668d102078e +44c7208e08b7a0dc8c88886a8df4f4f4ad5bb7deaf8706ba7281152a10bae7cf9f1f3a7428821d +97a802e5682914c7c870016d8c4446461e3e7c182529dabb77efd6af651a2acbd8d8d8cccc4cb4 +5177a22bc6af5cb992969626da28374f9e3c59b76eddc4c44494c562d01cf5860acc04d782c6b5 +6bd750e62241c5b8391d3a74c8cdcd1d356ad4942953ead7af8f3309d4c77e7e7e086c54dbdf7e +fbad384c2222222b552074df7ffffd76eddaa17c4428a294445b2ed0d36ab5df948a8f8fc7080a +c1e2e262b1b45cca9a6898ac2011b40d1a3458b468d1dd77df8d225514d35521ae45b92ee3c2d7 +d5d515e72f38bd0054d81f7cf001321865eeb163c7ba75ebf6fcf3cfabdfab2622a25a22282868 +dcb871efe8a1a1bcbf6b8d0a84eead5bb7fef5af7f3df4d0432fbef8e29b6fbe1913136390bb06 +ce9c39837042658c36ea5431a8565858e8e3e38306220db5a368f7ebd70f5dfdf2df356ddad4dd +ddfdd9679ffdabde679f7d265e6156f660d03609456ae7ce9dd14078376edcf8d2a54ba8861b36 +6c88713737b75ebd7a89d594fd60fe587afcf8f143870ea14ac66a9806b2ffe0c183ebd6adc326 +c69f26232222a7377dfa74f1aa32a081ae5c60850a7c904a0d018cd0c235fdf4d34fe82281a64d +9b86401aad171d1dbd7bf7eecccc4cd4820b172eecddbb77464606126bc78e1d0101013d7af410 +9f5d42718cca15e5635c5c1cda8b172f46f2b56ddbf68d37dec0a07a4d9c4a9c3b770e29a8bb6e +17971b376ecc9b370f25757e7ebed8c3850b1794bda5a4a4281b2a3bc10c11fc3803183366cca8 +51a350b5272525215f7d7d7d1f78e0014478424202d647c42afb411bc5ee92254b307fd8b56b17 +f63c6bd6ac61c3860d1f3efcc489137bf6ece107a988886a9bd8d858e593536888372e15963f48 +65e96b208bfbad4edffe6415bf8e0ae18de84286c97e59980d2e310f5c7a7878a0c4443ceb9758 +4bbd0775db1c14acb88d90acb2afbf5e7471d4b25f763fa8b0b10966a5ac805b068723f6c0af81 +24222285c6dd2b68f473ae7bfe5699af81d4dc3ee7d94c17c95581eb3097b88060533212756745 +1317d47b50b7cdc9cece56272ee07ad5890beafd60e5f4f474f50aa8e00df640444404084d44a7 +ec9862e9e5654dee2df74eb34a0a738ab3925d8acb09b3da89af2d131111a0c6f56ad147f7070f +12be7029c8aacccbcbbaddf04ffb11111195cb067fda8f8888882aae32efe9121111910d99ad74 +b3b2b2f42b10111151c58802b7f22f2fdfbe7d1b6b57e87b37aa437a7aba979757484888ec1311 +119977fdfaf5468d1ac98e1d55e9e56524ae9b9b5b8d272e600e9809e623fb444444770eab4217 +e1eceeee289f5ec64c301fd9212222ba735815ba252525a88b65a7a66126988fec101111dd39f8 +e965222222e9aebbee7ae18517aaef6d60862e1111d56a9e9e9eeeeeee1a8d66e2c489d1d1d1fb +f6ed4b4e4e96cb6ccdaa4f2f5fbf7e3d38385876ca1a356a545050d0279f7c22fb55e0e7e75758 +5858505020fbe6a5a5a5d5c8a7d18888a83ab46ad52a3c3cbc6eddba68a7a4a42426265eb87041 +2caa220b9f5eeed2a54bbb76ed1a376e8c80d3ea21cef6eeddfbd5575fc935f410c6fdfbf70f0b +0bdbb0618318e9d4a953cf9e3d451b3efef863e35fb235f7e9654bdfbd2c3b2e2ed89df8b3b806 +dcdcdc1e78e001dc58bb77efb6262c2d9b376f1e4e3792929264dfbcbcbc3c7e6116119173e8ae +e7efef8f8802349a376f8eac425eca35aa00f9659c1708d7458b1621479180485c94b9481fc41c +e2f3f2e5cbb367cf8e8f8f179fd8c5b6f3e7cff7f1f169dbb6ed0f3ffc2036efd5ab577a7afa9e +3d7bceeaddbe7d1ba1291629cc7df772954217a709a1a1a1e7cf9f0f0c0cc4a518447bf8f0e1bd +7bf7c661889bcc780493183468d0c08103ebd5ab872344618db3061c06f6e6ebeb8b131ce34dd4 +18ba4444ce01651b12577654900e999999696969b25f59c6a18b3daf5cb91205defaf5eb3b74e8 +80b811e3dbb66d43fae04a11c613264c387efc388213c5f7d5ab570f1e3c3860c00075e89e3e7d +fadcb973197ac6890be642b74aefe9f6eddb77bf5ebf7efdc4084e169e7efa6984e2d1a347274d +9a849bd27804ab2d59b2243232322e2e0e75fdb265cb30929c9c8c43c52532d8e4264444e47cc2 +c3c365cb88854555f1c73ffef1975f7ef9f0c30f51efa1aa16839f7df6196212618c24dab06103 +720dab61fcdab56ba87ac53a8a909090162d5acc9c3973fcf8f115fdb2a6ca87ae9f9f1f823336 +36f6cc993328d5119f18c40905caf07dfbf621509f7beeb9c3870f1b8f60ae8d1a357af3cd378f +1c39f2fefbefa3b4c569c5a54b975253537199909060bc89b8462222aa59ad6d0d75a7dcb5112c +922b5590dcde0cad568bfc126df1554ba87111c053a74e3d70e080285b7189d5f4ab9870fefc79 +9485883facf6c0030f20c5e4022b54fee5e5fefdfb63dbc2c2c2962d5ba200c7b59e3a752a3737 +1707b360c18276edda611d94ad38773018415447eb0dd6c3cd8a22fdca952ba8686fdebc8992df +7827baeb53e1cbcb444435c2e6dfc2dbac59338d99ef814012211a64a722d4df5a68fcf2f28913 +27c68e1d1b1c1c8c78eed2a5cba64d9b12131367cd9af5dd77df7df3cd37489ff9f3e7474444bc +f6da6b0823b189a7a7a7fae5651487172e5cb875eb161a281a5d5d5daf5ebd2a1629ccbdbc5cf9 +4f2faf5ebd3a3939393d3d1d6d4ca85bb76e8f3cf208b6451781ddb66ddb2953a6e04460ebd6ad +0623a8d6870c19f2c61b6fe8f6a257505080738a989818c436aa7e3168bc13053fbd4c44e41c46 +8e1cd9a04103d9290b11f3edb7dfca4e6521bf4ce6c50b2fbc80cb43870eeddab52b3434141984 +44ecd5ab17ca4264f6860d1bb2b3b3c59a80247ee289279e7aea29b411b198b0f261a3c9932723 +92b013d155d8f84ffbd5af5f1f87f1eebbef7ea6f7e1871fe28c00736ddcb8f1bdf7de8b108d8b +8b3b76ec589d3a758c47e2e3e39b376f8e02579c08cc9b374f94d1e2e3da68186fa2bf4e222272 +36a83265cb8885455581201c33660c1a3b77eefcfcf3cfa74e9d8aea6ee2c489b80c0c0c44e1fb +faebafab13d7006acbfbefbf1f3521daa8fbdbb76f7ff6ec59b1c81a95ac74274d9a84807cefbd +f764dfc505d53a6218670728585bb66c890cc681a13c4f4d4d3518b979f3665454d47df7dd87d0 +c58c718280c3c61e50e93ff4d04357ae5c59bb76adf126e25a0456ba44444ea37bf7ee882ed929 +75ead4a9d8d858d9a902e34a17dda54b97a2c6ddbc7933baeeeeeea2f043d022fef4ab185257ba +d0b469d3d9b36723287d7d7d91dc7bf7ee15e36ae62addaa7e3986499807f6ae3e53301ec15410 +db1851ff822fd6c1fcc488f1260a862e119133b1e7976320dd50f81d3e7cb82a7f3b07f1e4efef +8fd2b1a8a8480e9565d7d0ad6e0c5d2222b28671e8da878ddfd3252222a28a62e8121111d90943 +978888c84eccbea79b55f66f2638da7bbab2454444e478c45bb915f82095bbbbbb7e43222222aa +98ecec6ca42c3f48454444546318ba44444476c2d0252222b213862e1111919d3074898888ec84 +a14b444464270c5d2222223b61e8121111d90943978888c84e18ba44444476c2d0252222b21386 +2e1111919d3074898888ec847f65c8368242eadc3533a66d64e7a0e03a72a87afcdfe6f7befee2 +03d9b1af3a75eac4c4c474eedc190d39543dde7befbd0f3ea899632422b209737f65c8ad499326 +721515e42e56951d2a0f1277cdf3eb5bb68ef0f6f69543d5a65dfb2e4545dab3f12764df5e10b4 +ebd7af8f8888f0f5adf663ecd2a58b56ab3d71c2dec74844642b8585852268dddcdc44038a8a8a +18ba3630fbfe65485cd9a97e111dba6a0b0bce259c947dbb58b66c19125776aa5fd7ae5d0b0a0a +4e9eb4eb311211d98ab9d065b2da00aa4fd9b29749d3178c1c3b4d76ec02d5a76cd9cb82050ba6 +4db3eb311211553786ae0d040685ca961d4d9eb170c498a9b253fd42436be018172e5c3875aafd +8e9188a8ba3174ef605366c60c1d3545769c544c4ccc94294e7e8c44547b3074ef6c53672f1932 +7292ec38a9254b964c9ae4e4c74844b50443f78e376dce8383864f901d27f5e0830f4e98e0e4c7 +4844b50143d719cc98fbd0c061e365c7493df4d043e3c73bf9311291d363e83a8959f73ddc7fc8 +18d971520f3ffcf098314e7e8c44e4dc18ba4ea2c4c5e59efb97f71f3c5af69dd4f2e5cb478f76 +f263242227c6d0751ebadc9dbfa2efa051b2efa456ac58316a94931f2311392b86ae5341eedebb +60a5ec38af952b9dff1889c82931749d8dee2f571011914362e8d6bcf49cbc0f7f89fbcbe69ff1 +0f0d74e50227929a95f7efefe31edaf833fea181ae5c4044549b30746b1822f6e5ad078e5dbc91 +995b807f68a0eb64b98b887d72d381fd676fa4e514e01f1ae8327789a81662e8d6b0ad8713730b +b4b2a3872e0665c7297c7420313bbfcc31a28b41d92122aa3518ba35ec7c729a6ca9981cbc739d +b966e2704c0e12113937866e0dd31699f8e493c9c13b57a1a9c331394844e4dc18ba352cac6188 +6ca98437323178e76adfc4c4e17468ea54c74844640d866e0d9bd0233cd4df5b76f4d01ddf3d5c +769cc23d7dc2eb059639467467f776aa632422b20643b78605f97a2f19d95d76f4d0c5a0ec3805 +9c463c35becc31ae1edfdde0548388a83660e8d63c838875b2c4158cab79d92222aa4d18ba4444 +4476a2898e8ec67f2525ba8f92e252282e2e767777d7af40e57b63e34ed9b2283d276febe1c4f3 +c96999b90572c83a013e9ead1b048feb166e6511bc64ce08d9b29d9d3bad3ac6d4acbc8f0e249e +b996969653b1630cf6f58c681c3cb397e13bdce68c1861fb632422b295ecec6c8d46e3eaeaeae1 +e18186909f9fcf4ad74ed4df3c2587ac76a77c5395fa9ba7e490d5f84d5544541b3074edc4f89b +a72acaf1bfa9caf89ba72a8adf544544ce8da16b2736f9922907ffa62a9b7cc91476c26fcd2022 +67c5d0b5934abcaa6ccc263ba93e957855d9984d764244e49818ba44444476c2d0252222b21386 +2e1111919d3074ed2dc8d7eb9e01517f9e3ee8e9bbfacfee1f85ae5ce04442fdbdfe383ceacd79 +835e9bd3ff816151e8ca054444b51b43d7ae827c3d178fecdea945031f0ff7001fafce2d1bac18 +d7dbc97237d4cf73f5f8eebdda34f0f3740ff6f5ea13d6e0b9bb7bd761ee12113174ede6c57b86 +e1dfea2903eaf8fbc8213d1f4ff771dd9ce4efed6c5c340cff5eb96740fdc032c7e8e7e53ebd17 +ffa610111143d701b46e102c5bce2bb2b1f31f231151b918ba44444476c2d0ad790efe3d533671 +da165f56454474a763e8dac9631f7c8f7f7ffbfc975b59b97248cff1bf51d97a73defa1eff967e +f8cb8d8c32c7989daffd84dfa84c44c4d0b5b3f49cfc37bf8d8d4b4ace2dd466e6e61fbb98fcf2 +d6fd18948b9d426a56fedffe2ff6e0f9e4ec026d5a4efebeb3c94f6eda7f2bcba98e9188a87218 +baf68688ddb8fbc49f3ef9e92f9b7ff9f097134e96b80272f7b59d27166ff8e9a18dbffce7fb13 +e8ca054444b51b43978888c84e18ba44444476c2d0252222b21386ae9d04f878ca5615d86427d5 +27d8d706d3b3c94e88881c1343d74e6cf2b5530efedd5511b6f8da29ec44239b4444ce86a16b27 +e3ba85fb78bacb4ea538feb734cfec15eee755a563c4e6d889ec1011391d86ae9d04f97aaf18d7 +ab73cbfa957889189b60436c8e9dc8218714eaeffddcddbd7a87d5afc44bc4d8041b6273ec440e +1111391d4d747434fe2b29291197427171b1bb7b954a965ae58d8d3b65cb312c993342b66c67e7 +4ec73ac611236c7f8c4444b6929d9dadd1685c5d5d3d3c3cd010f2f3f359e9121111d909439788 +88c84e18ba44444476c2d0b5818cf454d97200d53499d454073a46879a0c1191f518ba36107fea +a86c39806a9accd1a30e748c0e35192222eb31746d60f347eb72b23365a746611a9b3f5a2f3b36 +b56eddba8c8c0cd9a951999999988cec1011dd51dc9a3469229b2a252525aeaecc636be5e7e51e +d8f35d50706840609097b78f1cb5af8cf4d4e347f6bdb9f699f4dbb7e4904de5e6e67efffdf7a1 +a1a14141413e3e35738ca9a9a9fbf6ed7be699676eddaa96632422b295c2c242f16b426e6e6ea2 +01454545fc3d5d2222221be3efe9121111d530862e1111919d3074898888ec84a14b44446427fc +209555b48dba1605b57071bd936f9362ad5bfa25f7eb4764978888aa0d3f485579bac40d697367 +272eb8bae328702cb24b444476c7d02d9faec67516ce742c4444779c9a0f5d94de6ddab4911d17 +171f1f1f93dfd75193cad6b85e1eeebd3bb454fe05f995f9a3ebcdea078706fa36080de8dfa9b5 +1cb21af6dc35bca9ec58a7c257645dbd8e1f4a7b153f3f3fb940af7efdfa8181812121219d3a75 +924356c39ec3c3c365c73a95bb2222220754f3a11b1414b47af56a3cb38b6ee3c68dc78e1d2bda +8ea94e90df5f168e898e6c2efe05960ddd49033bf568d7dcdfc7ab616820bacf2d1a27c6ad31b2 +67c4862767890d05f5e62677a55c916de187327ffefc885206a1dbbf7fffb66ddbe2f4087188ee +c2850bc5b835a2a3a357ad5a55a74e1dd92fbbb9c95d2957444474a7abf9af81f4f5f5edd2a54b +6464e4c183070b0b0b4343435bb76e1d1b1b8b4528a7860c19826e7272724141019e79d186ae5d +bbdebc79332f2f0feb201e860e1ddaa2458bebd7af6bb55afd2e6daca89e3c2110027cbd51e03e +f1e6ff1d3c7509ff32b275d3685c3768fab06e0deb04d609f44b49cf4e4abeede1ee16d6b4de3d +7f88d66834e7aede2a28d422adb14ea7368db134af405b3f2420aa4de33e512d11db576ea66127 +8fcc1cbafdc0a9364deb1e8ebf82ee906ee1cae6fd3ab652dac1fe3eca86c9a999b8a2cb37749b +5bc9fde629d9320f3f149c06ad5bb7eeb45e767636069194b8a971899f4b7a7afa8d1b37dcdddd +71ff19316204965ebb760d3f3e933fb20e1d3a6087f89161b5e9d3a71f387000a756090909e8e2 +47a96c1e1515a5b4fdfdfd950d6fdfbe8d2bc2d5611111d11dc1dcd7403ac47bba7806dfba75eb +9c3973645f0ff5cd638f3d8627dcacac2cd4465e5e5e75ebd69d3b772e9e7fb1fe8a152bc43a68 +a4a5a5e5e7e7a361b713058d8bc6cbc35dfc433724c067dd63d3937ebbede7ed39ae5f078c34ad +17f4875e11c84264edc90bd70bb45a7f5fafb757cdbc713bf37666ee3b4fccc29a58e7d9f9a35d +4a5caedf4ac726c8606f2ff70ddb0e8c888ed06874d7a2de5cdd566f28ae48b7b6ade1fee1510a +5da4e0ca952b11a5dedede7dfaf4c1087e1c285b9185b86f5dbc7811673c267f64f3e6cdc3399c +f8b66464b0a7a7e7f6eddbbb77efaebb0e1717f5e6eab67a437145627d22a23b9a43842ea0cc2d +2e2eeed5ab97ecbbb8e079f9d0a143a88af6eedd1b1717d7b973670c5eb87061cf9e3d3ffffc33 +ca5c3cc5639df8f8f8a4a4248ce389be79f3e662dbea16d6b4ee9b8f4e13ffbc3cdd87766ffb7f +7b4e7c7be8cc67bb8e1e3a9d24577271397be5664e7e2146f20bb4c3bab7fdf6e099aff79dc29a +7be22e0ce8ac7b1bfb70c2954d3f1ebdf4db6db491d6dbf79dcace2bb8f45b6a54ab46069babdb +061b561394b048590149d9ad5bb77dfbf6fdfaebaf3ffef8e3993367e44a2e2e57af5ec5190f46 +50d79afc91252626fef4d34f486bb491d6588a9f1df21585acc1e6eab6c1864444cec151421736 +6edc3876ec58e5dd3b9456a899441b8d80800034f0a42c4650a4a366c720b261905e4a4a0aea24 +b1b4ba255eb939efb9ff897f48c1405fef9474dd0bb090929e251a0642027c51e68a76726a6648 +a02f1a285ec5088cefdbe1aec15d3efcd3bd1d5a351adfbfa31c3543bd6135b972e5ca0ba59082 +7e7e7ee9e9ba8a1c948601933f32f50fa56fdfbef8493dfdf4d32d5bb6445b8e9a61b79f261191 +dd3850e8e6e6e67ef4d1473367ce14dd4b972e75ec28b3272a2a0a5dd156438d9b9a9afa3fbd84 +84849afa8b6fc8e0be1d5b69706b6a34d19186bf93e3e6a6bb914f5ffcad5f47f93163ac8cae68 +0bed5b36bc969271f753efccfef3fb1357adef1bd5ca5dbf1588cd05755b4da3d17d8c190d94dd +2101babfbb171ae8ebe1eea65f681b2843c58f43a3d1444418bea02d5ed8b7fc2343d0e2c468cd +9a357ff9cb5f56af5e8d3571da2416a9df1730f71e01ae579c90a1ec46baa3111818c8af7021a2 +3b8be927b89a72faf4e943870e296d544b8fe95dbe7cf9ecd9b3625cede4c993797979ab56ad7a +fcf1c7bb75eba6d4c1d5ad6db3fa2849c5bf9e912df6c49dcfcd2f7cfb89996f3e3a3d25ad4ca5 +bb63ffe98fff3cb76168e081539750e9bebd6ae67f9f98999074e368e255b986def8fe51dbf69d +14ed426dd1c13397067609435b6cde48fff9646557fab5ca68d130f48335ba77c4270de8b872e6 +50349eb97ff4f01e6df50b2ba959b366284985c8c8c8b8b838dcbcf859ac5cb9d2a0d23d78f0e0 +9ffef4a7d0d050cb3f3294b6fbf6ed136dad568b95c5ebcfcae6066d030d1a3478eaa9a7d0e8d7 +afdf8c1933d0b8efbefb94f7868988ee088efe35905e5e5eb8b49ca658076590f8307375c88f98 +64cdafb7fafb7ae5e4151417eb6e4935549fe28d58f0f5f6c4cd8b84165d6ba83757b70da0c82e +d6ff104543e91a2ad67a9df942b62bcec7c7073f0bdc3d64bf14aa4ff1462c58f32333a0de5cdd +36809f326e3da5a17489881c8db9af81acf95f19b2ac484f76ccc00ad5f4cb4292874f898f89da +cb40416191c908282afa3da250c56a555d6ba83757b70d28d72c1ae6b2c82ded826b569957b62b +04b7b3c99c53ff8cf43fb1727e64060c36972d22a23b56a123ffca908373bf7ec4edf639d488b2 +7f872ad6e228f8070f88886a10ffca101111918df1af0c111111d530862e1111919d3074898888 +ec84a14b444464270c5d2222223b61e8121111d90943978888c84e18ba44444476c2d0252222b2 +13862e1111919d3074898888ec84a14b444464270c5d2222223b61e8121111d90943978888c84e +18ba44444476c2d0252222b213862e1111919d3074898888ec84a14b444464270c5d222222bb70 +71f97fe5f456f31a37259e0000000049454e44ae426082 +}\kerning2\f4\lang1033\par +\par + +\pard\keepn\widctlpar\s2\sa360\sl252\slmult1\cf1\b\i\f0\fs28 Serialization\par + +\pard\widctlpar\sa360\sl360\slmult0\kerning0\b0\i0\f1\fs24 Every member the attribute is attached to must be serializable by Unity (with the exception of the\~{{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/ButtonAttributes/button.html"}}{\fldrslt{\ul\cf5\cf6\ul Button Attribute}}}}\f1\fs24\~and {{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/MiscellaneousAttributes/showininspector.html"}}{\fldrslt{\ul\cf5\cf6\ul ShowInInspector Attribute}}}}\f1\fs24 ), meaning those members must be either public or private with the\~{{\field{\*\fldinst{HYPERLINK "https://docs.unity3d.com/2023.3/Documentation/ScriptReference/SerializeField.html"}}{\fldrslt{\ul\cf5\cf6\ul SerializeField Attribute}}}}\f1\fs24\~and valid to the Unity serializer.\par +Here is a small example of what\f2\rquote\f1 s valid and what\f2\rquote\f1 s not:\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf7\i\f3\fs18 // Valid, public fields are serialized by default\cf1\i0\par +\cf3\b public\cf4\b0 \cf8 int\cf4 \cf1 field01;\par +\par +\cf7\i // Valid, is still a public field, we just mark it to be hidden in the inspector\cf1\i0\par +\cf9 [HideInInspector]\cf4 \cf3\b public\cf4\b0 \cf8 int\cf4 \cf1 field02;\par +\par +\cf7\i // Invalid, private fields are not serialized by default\cf1\i0\par +\cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field03;\par +\par +\cf7\i // Valid, we mark this private field to be serialized by unity\cf1\i0\par +\cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field04;\par +\par +\cf7\i // Valid, is still serialized, we just hide it in the inspector\cf1\i0\par +\cf9 [SerializeField, HideInInspector]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field05;\par +\par +\cf7\i // Invalid, static, readonly or const fields are not valid to unity's serializer\cf1\i0\par +\cf3\b public\cf4\b0 \cf3\b static\cf4\b0 \cf8 int\cf4 \cf1 field06;\par +\par +\cf7\i // Invalid, Non-Behaivour classes and structs that are not marked as serializable are not serialized by unity\cf1\i0\par +\cf3\b public\cf4\b0 \cf1 CustomRawClass\cf4 \cf1 field07;\par +\par +\highlight2\kerning2\f1\fs22 For more details about unity serialization see\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://docs.unity3d.com/Manual/script-Serialization.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 this}}}}\cf0\highlight0\f4\fs22\par +\par + +\pard\keepn\widctlpar\s2\sa360\sl252\slmult1\cf1\b\i\f0\fs28 Attribute Order\par + +\pard\widctlpar\sb100\sa360\sl360\slmult0\highlight2\b0\i0\f1\fs22 The logic of all attributes is executed in the order they are written (left to right), meaning the last attribute can override the functionality of the previous attribute if the functionality is similar. In the following example the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/NumericalAttributes/timefield.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 TimeField Attribute}}}}\f1\fs22\~will execute before the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/DecorativeAttributes/suffix.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 Suffix Attribute}}}}\f1\fs22\~meaning the suffix will fail to add because of how the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/NumericalAttributes/timefield.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 TimeField Attribute}}}}\f1\fs22\~is drawn:\highlight0\kerning0\fs24\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b\f3\fs18 using\cf4\b0 \cf5\b UnityEngine\cf1\b0 ;\par +\cf3\b using\cf4\b0 \cf5\b EditorAttributes\cf1\b0 ;\par +\par +\cf3\b public\cf4\b0 \cf3\b class\cf4\b0 \cf5\b AttributesExample\cf4\b0 \cf1 :\cf4 \cf1 MonoBehaviour\par +\{\tab\tab\par +\cf4 \cf9 [TimeField(TimeFormat.YearMonthWeek, ConvertTo.Days), Suffix("to days")]\cf1\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field;\par +\}\par +\par +\cf0\kerning2\f4\fs22\par +\kerning0\f5\lang9{\pict{\*\picprop{\sp{\sn wzDescription}{\sv Image}}{\sp{\sn posv}{\sv 1}} +}\pngblip\picw15866\pich1547\picwgoal8995\pichgoal877 +89504e470d0a1a0a0000000d49484452000002f70000004a08060000003fb47b39000000017352 +474200aece1ce90000000467414d410000b18f0bfc6105000000097048597300000ec300000ec3 +01c76fa86400001d6149444154785eed9d099055c5d9863fd6199861078161d837019545d90406 +880a6ac4e81f4d3426965163d458b1122d8958fa131331d15fb36aa2265113b724654513828811 +5134a82c8ab2ef8bc8ae20ab32c0cfd3737a381ccebd7367e6ce00f7be0fd535f7f439b7cfd674 +bffd7d5ff7ad51545474d084104208218410273c3583bf42082184104288139c1a050505b2dc0b +21841042089101282c470821841042880c416139420821841042640812f7420821841042640855 +129673e79d77dae9a79f1e6cc5f3cc33cfd8dffef6b7604b0821841042085159aac4725f96b087 +6f7ce31b76c92597045b42082184104288ca52ab7dfbf6e383cf69e3b2cb2e0b3e25e7b4d34eb3 +2fbef8c2162e5c18e49cf8d4ab57cf8a8b8b832d9129e8bd0a2184109941870e1decc20b2fb4f3 +cf3fdf860d1b669d3a75b2eddbb7dbb66ddb82232ac755575d657dfaf4b1f7df7f3fc8293fb56b +d7b6ef7ef7bbd6bf7f7f57ce810307823d65532de27ee5a69576c90397d915432fb7a2ff1d6963 +ceb8c0f272f2dcbedebd7bdb73cf3de73e5727780dce3aeb2c37b8d8b06143905b427e7ebed5ad +5bd7edf3c4e545a172dc75d75db679f366dbb56b975d77dd75b67bf76edbb469537044eaa472be +f2d2a85123774d03070e3c22d5aa55cb3efae8a3e0a863c749279d64575f7db56dddbad53efdf4 +d3203735860f1f6ed75f7fbdbdfdf6dbb66fdf3ef7fc2eb8e0021b33668c9d79e699d6bc79735b +bd7a7585047af8bd7efcf1c7416e62a2efae57af5ef6a31ffdc83ef8e003dbb973a7cb13420821 +44f53372e448fbdad7be668d1b37b6152b56d8279f7c625dbb76b5010306d8fefdfb6dd5aa55c1 +911587f29b356b66afbefa6a90537ed06ce79d779efb3b73e64cdbbb776fb0a76c62c3723a76ec +e8acea8912fb53e1e0c18356bcbfd8967cbcd40a9bb5b1e51b57586edd5c6b9cd7d8ed3b563468 +d0c08a8a8aac7bf7ee4e1446410093c2c4e54559b76e9d3dfffcf3b678f16227ee289fca531152 +395f79f1d754a74e1d27547d6220723c909b9bebaeaf61c386414e6ae4e4e43821ffeebbefba7b +a959b3a67dfffbdfb7c18307dbb265cb9ca81f3162847de73bdf09be513ec2ef3515a2ef6efefc +f9ce1af095af7c25c8114208214475837e3de79c73dc670ccb53a74eb5e9d3a7db638f3de6f246 +8d1ae5acfaa9f2c31ffed0264c987044aa51a346b0d7dcf62db7dc126c950f8c9c4f3cf1844be5 +f528c45aeef7ecd9e3461ce10bf420ca19d530ba4984b7dccf5b3bcffee7ff2eb5690b5eb7ad3b +b6da0b335fb47dc5fbecf1d79eb49e6d7a5adbe66ddd71d56db947f49d72ca29366bd62cf777c6 +8c19a52322f6e14d200c83d1d2f2e5cb9d753b9a87006544c5f7108eecc32adba3470f2798719f +90bf60c1026bd7ae9d0d1a34c8894e6fc547f4f3fdcf3efbcc76ecd8e1f65d74d145ee9933828c +9e8ff210e543860c7196e8366ddad8c68d1b4badc358bdd977c619675893264d9c8539eac2c9cb +cb73d744659e3871a2cd9b37cf25cac13acd3ebc18dc53e7ce9ddd36e57cfef9e76e40c436ee21 +cec57158c1fd7d70ef5c176e28ee9fe3478f1eedcaa10cae337c2cd749595ce3962d5bdcf571af +dcc37befbde7ca4f76bf61186df7ebd7cf5e7cf145f79fa175ebd6ced5c63d4e9a34c9896baea9 +458b16ee7ea9bb782b2897f2dbb66debf6739ffe1a13bd57be97ec1ee2ea0ffb7927d4a3b7de7a +cb9d4708218410d50ba13878f28128012238f0b6a30d30fa025a69eedcb9ee7359a01fb1ce8713 +502e8c1b37ce1d5351d0e3e8442212ca43ace51ef1819b220ef25315273d0b7bdacb774cb291bd +86dbf9fdceb3f3fa9d6b453d8b5cdec06e0382a3aa1f441982f3dffffeb713d3e109c0f5ebd777 +714e24043cfbe3f2f8cbcbbbe69a6bece4934f7662d6e7b56cd93228ade405233c11b9c44e0d1d +3ad4e5478f4534b2cda832ee7ca41b6eb8c18599207a192c8c1d3bd61d8b88bcedb6dbdc7d701c +16e26f7ef39baedc38184850864f7c87e78150c502ce7e263c2392a95458c6291f21ccb18c7a6f +bcf1465796bf8f6f7ffbdbee1e11cc37dd74935d7bedb5565050e0043efbc2c7f2cc0855e9d6ad +9b7def7bdf8b9d809dec7ea374e9d2c50d3456ae5ce9b619e132084068f7ecd9d37d7fce9c39f6 +873ffcc1e5fbb209cde23f31c71136c37ff0f035c6bdd7b2ee21eedd01567f9e2bd72a84104288 +ea075de2213c07ed3579f2643bf7dc73835c73c6c4cab264c99294bdfd89404fa0bd4871da2719 +0957cbc14a1ab5ceb34d7eaad4aa59cb1ad66f685b777e62fd3b9d6e070e1eb4b6cd0a5d1efb8e +05782410d0883d2cb16bd7ae7562dfc3a80beb3ae9c9279f7462302ecf43393ffbd9cfec8d37de +08728e042fc7af7ef52bfbf9cf7feee2dacf3efbec604f62e2ce87e51821f9c8238fd85ffef217 +bbfffefb9d18459023c20969e11af082fcf297bf4c783d70f1c517db2f7ef18bd284e0c4528de5 +1bebf2a5975eea9ed3dffffef7e01b66cf3efbac3df8e083eeefebafbfee9e21e7f730327de8a1 +87ec5ffffa57e9777ffbdbdfba5019447f98458b16d96f7ef31bf7dcfcc8394ab2fb8d82459e89 +30de53c13c075c6c88690621f7dd779f9bdce243a410ed249ed51ffff84777ddbc1b2cf89eb2de +6ba27b485457fc1c02ae5508218410c71ebce9444b8475604541679080501a34c0b122a1b8c712 +8a4009c3767926248e7d7a9c0dbd73b87db0fa43bbfbf909f6f27b2fdb336f3e67573d7c4d7044 +f5e35f206113c4db23041175616b7b79286be2c5d2a54bdd5f8427f1dfb88318299617043c30e1 +f4a73ffda973f5500e2132847e60b5befcf2cbed9e7bee7196f5642e1c2af3ef7ffffbd284d51e +10e27c66e638a296c10f205011c6dffad6b7dcb9094b012cfa1e042e10ae02886d601b2b76189e +035097f81c277893dd6f14e612e0ba0ac30a4c77df7db78b77c343432cffadb7deeaaed98fdc19 +59030356047e78d5a6b2de6b2af710867a06e1672684104288eac3eb1d0f31f65ffdea5783ad12 +98675711304892bcc7beb2a01b304e92bc864895a4ebdc1347ec2d8ffcf571c5a932eee2b1f6e7 +9b9e709f9fb9f9cfd6a87e23bbef8a7bedc12bef7779c702c227082b22d69ef82a6fcd4dc7a82d +0ec23a3c846920baf180782bb317be848724c38742311ac4624c42c8e34ea2cc071e78c0eebdf7 +5e9b32658ab3aa33a134d1208278761f6f4ff2136a1978209ed9c6b28de51b8869274cc75babff +f18f7fb8fc8a12b6f8f34ce2c2bc92dd6f14bc0ee1e7c7fd33539d7025fe23ffe73fff71029f77 +cd208ee3c17f87fbc4bbc0f1a992ca3d84f1c7fb730b218410a27a897ae38958886a9a64910f51 +fc84da3068153fb9b632136aa1b0b0d0a5f29254dc3379d62f13c9dff2ae708398dfb17787356f +d8c29ae435b1ed7b3eb37e9dfa5ad3fca6c111d50b7154586d11c03ff9c94f4ad39a356b8e10f7 +0835264086c349e2f252813875acc694cf4a434cb005e62e20f089f9620266f407bda2e7635228 +566262cff9cb245de2c6f9cb4085fbe0de580b955023e2cc13897b9e43dfbe7d4b93af380862c2 +4708eb41047fe94b5f72f90853de3df163087faeb73270cfb8c1b8179e8d7f266192dd6f143c4a +086c3f50424033b781790784f7f0dcf1d2908f959eb2191031b18667c13c831ffce007b15e8144 +24bb87b8bad2b469499d2f4f589b10420821d2075ef9575e7925d82a3106923ce8c3b23cf76108 +5726b220cc1d77dce1f27cc2f85a113048fa501f6f884e95a4e21e989c4878464517f63f70f080 +5dd47f8cedd8b3e3d0df0bad7e4ef92605a4133fe991d558c2b04d5845fbf6eddd36a336c27610 +7cdee21a97970ac46e13cec2cbc18aece3d871b1305a449033e194d00e6fcd87e8f910dd8f3ffe +b813ab3ffef18f5d99886dace98493f0fd2bafbcd28d1889a17feaa9a74abd2e5110a44c08f589 +49b04cfaa56c967c5cbf7ebd8b1d67c51944a90fd76142ebf8f1e3134eb64e15d67be7bc886fc2 +89fef9cf7f067b0e93ec7ea390c740c64f56e5fa89756bd5aa959beccab29458e71f7df45127bc +a9cb94cda0e6f6db6f7742fda5975e2a0da14a8564f7105757f084e0b1f1e13c42082184a87e5e +7bed35a707d00e18e7487c266fdab469c151e5c74fa24dd752ef843563ac25f990e754a9515454 +94f605e75f78e185e0536ab004e4f106629058ee7018455c5e2a107f85d88b8b99a24cf647272f +43dcf93896501f62cca371f558eb9951cd0a37e9aa5c61fc79b1a45704aceeccfa66122b1e8644 +cf244cb2fbf520ecf15cb074d55ffffad720b7049e0783a6b877964ad95152bd87f0bbe33c0c8a +18041066248410420851559469b9af08b367cf0e3e954d798ead4ee204612291581608ed442296 +32e3843dc49d8fb212ad794a1e1359ab42d803ebf15754d84749f64cc224bb5f0fcf0f8f036130 +d1b90b9c23d13b4ba5ec6424bb87f0bbc3fbc0738bf3500821841042a4932ab1dc0b1107567226 +e77ef8e18747adc474a29009f72084104288cc45e25e0821841042880ca14ac272841042082184 +10d54f8d3e7dfac8722f841042082144065063d0a04112f742082184104264000acb1142082184 +10224390b8174208218410224350588e1022ebe1978bf945e7aafa8d08218410229df00399fc58 +664e4e4e907318897b21445683b0e787cc6ad7ae1de408218410550bbfae5f59304891a2025f61 +394288ac068bbd84bd104288130dacf7f4615124ee8510594d341487ed9a356b9626ac2b243ed3 +902a74470821c4f1425c9f54256139f5ead5b303070e38777745a0236dd4a8917df2c927418e10 +42540d9f7df6998b5bf4e4e7e7db8811239c980f439b469b3473e64c672941e8c7413edfddbf7f +7f9053714e3ae924dbb46993fb8c77a1b8b8d87d3e16c4b9907926c77ab0c375a5e3590b214475 +12d7a64293264dac53a74ed6b06143b74d1fb562c50afbf4d34fdd76943d7bf6941eeba9555858 +383ef85c695ab46861a79f7eba356fdedcdab76fef3aa6ad5bb796bbe16dd7ae9d75eddad5d6ac +5913e424a663c78eaed3dbbd7b7790238410a9831122dcc822eefbf4e9e38c1439b9392e9691bf +f5ead7b3460d1bb94674fdfaf54ed8c63170e040ebdcb9b3ad5ab52ac82981c61aa3c5b66ddbdc +36e5721c6d6422468e1ce91a6e1a77ca656ec0ae5dbb82bda9d3ad5bb7a4e74905daf6534f3dd5 +5db34fdcc3e6cd9b83238e0dfdfbf7aff0731142886345d48004b4abb4d7f41f4b962cb1b56bd7 +3aa34eaf5ebd5c3f1527f0d95fa531f79cfc830f3eb077de79c7de78e30ddbb2658b75efde3dd8 +9b3aab57afb6e9d3a7075bc9c9cbcb4b38fa1142888a72f0d0bf9d7b76dad479d36cfda7eb6dc1 +470b5d63dcb66d5b370088a34e9d3acec8c1df060d1a04b925e01d087b0868b73082c4e1bd0213 +274e748d7b65a02c3a8b74b068d1229b3c7972699a3f7f7eb04708214465c0624ffff2d65b6f39 +03128627129fc9631fc7a442da2cf758cf3b74e8608b172f0e72cc59a8b66fdf5eea4ae6c2faf6 +edeb3ab4c68d1b3b8b0f2e5dac41749a5886e814e1e4934fb60d1b3658cb962d5db987aed37550 +050505b663c70e77c33d7af4b056ad5ab9b29a366dea8e174288f210b5dc63b1a7add9be7bbb2d +59bfc4b6eedc7a48e4efb23d5fecb146f51b5a5e6e9e2d5dbad459d4a3d056511ed6152cfc1838 +a04b972e2ed130e39944b00f1f3edc0d12d826f486b66fc89021ae4d3bedb4d3dc39080fc2e24e +1810ed27ed29c7e0d9a4ddfbf8e38f5df9948167c0b781e1ed51a346596e6eaecba3edc4c2ddac +5933e709c0f8427bbc73e7ce52ef27657bef03c7ad5bb7cee5d3f6728cf73c8419366c98b39e53 +0e7d01d7cdbd73dd943760c000571e6590cfb1dc0fd7c8fe534e39c53d2fdec3a04183ac67cf9e +a56150307af468b73d78f06077cd0c58bc27a24d9b36ee9ab82fce8d259ff2281714de2984381e +895aee319063b1a79d07da4b8c44b4dbb47ff42db4e388fd30556ab9a7703a283a051a6d3a48d8 +bb77affb8bf846a0cf9831c359f56988c3567d4278b0d62f5bb62cc8390c9630acf97c8ffd0c06 +60e1c285ee9c7482efbfffbecb134288ca82d5be460d26d4d6b29cda39f679f1e7d6a05e03ab53 +ab8edb97081ade8f3efac88977da410fed163193cb972fb7a953a7baf6f2cd37df746278ca9429 +aef106c43fc74c9a34c96d474120733c5673ca40c496c52bafbce2c434dff3f1fb88ed79f3e6d9 +cb2fbfecda4e0431d4af5fdf096e8e651f9d09db61082df2c97b2228cb5f0bc29c0101f7c4e080 +0e6adab469ae3c3aa570bbcf4066f6ecd9f6d24b2fb9f268eb39f7ebafbfeecaf130f06120c471 +dc0f65d26744c178c4e08173f19c19b8700d420871bc8381c31b2368e330f290f80cec8bc6d627 +22ad613934f0c408d1086385a703f1ee6b1a713a3cbf640f9d5dd8cabf71e3c68431ac7480fe86 +b1f6d351455dde420891360ee9f7e2fdfb9c90cfcfcd7742bf5edd7a56b74e5dab71e85f1c8408 +62d4405cd266d14e31ffa83c105b9f2c861d23879fc08a51a375ebd6ee73794014738dcc856230 +41795c2fd74afb8c05086b38d6feb973e7ba418987018bef7048780f004f05c21d8f07861cdfb6 +635d47a8f32cfcb928d7c3bde20d209fc1801f7cf01ce80fb0c47bbce1876b5cb972a5bbc63058 +f3b907fa0acec5fb60de167d8f104264136915f740c38a451dab14d61b6f7dc1f2e285bd272ce6 +7d871547f47b6c876357851022ad1cd2efdb766fb76dbbb65bf18162dbf5f92edbbb6faf13fd89 +c06a4fdb44880ac9e7a5132ce91ecee5c318cb03e2da4fe6f509818d90f61e054432f740e81022 +d98381060fab4f5e8c03e21bb732830e0f831d42740825226429593b0f7113cc3ce17e20eedeb9 +27c27ac2f785374073b2841027021835308e002197cc6125f9f04bf6714c2aa44ddce34eedddbb +77b0550271903e0e88309cb03b81cfa95a9da293d7d88e8b77154288748075be6db3426bdea099 +756ad9c9f272f2ac5bebae965327c75988e3200464ce9c39a50df2ac59b38eb22e5716c4aa87cf +e155c2c2d795ccf8e1e3e2b93e9f10e43e5e9f72b80fc25ff0a8b222592a60c9e7be099bf4829a +fbc7e04348e57befbd77c4e0a4bc84bdb5f41fe17b071f02ea9f3d891027b68510e278072f2961 +8bde7081a8f7c29e3cf6853da9c9489bb8c7bd8a85879313e3882b94184c7f61c4a1e2d2257688 +d107eedbb0cb35197408587d10f54c92a251f70d3b96265cc371f197420851516ad6a8692d1b9d +640d720fb53badbb586e9ddc84c29e368f3017c253980c4522cc846de61a01d666c245bc51836d +62dccb135a83a04730d3be624c41bc02e76170411b4b0a0b61ace558c4390f9674c436e7a67da6 +2dc6c2cd44550439d7473825e563bda75df5f3013cec0b27a05da76cae87d0213f2f0aa30ee720 +712ced7845c12bc0f5510efd07e789c220e58c33ce70d7cd35712fea1b84102702b4e37847f174 +d25e631c27f1993cf6714c2aa4759d7b2c3f5854e81468e811f65c0c20c2190060e1478ce3cef5 +ab30703c629d8e00f82e9d1ec723e8d9c62a838b9bd84d965ff3ee5d3a2abe4f671676110b2144 +2a603c08876ef01941485b53ebd03fdb7fa84daa95eb0431ed106d1522966d0f6293f8f2e85af2 +886ada27e2d1699469fb1808d036129688151df14f599c8ff62ebc1202c7fad57268e368336943 +11b9c49dfb3694fdb49f74029cd37b4db1bc03830d443fe7c4ad4bbbcc4001a1cc808549b5fefe +38960104d7ca71be0d67e5320c38b4f13ed14e730e8c3ac4d9e351259edfdf936f9311f55c0f31 +f03c5fda76ce4f8890f718503ecfd6bb9db95f3f178be78b3701e30ee7c51aef57ede17b7c87fb +e759d13720ecb936ae89730921c4f1465c1822fd046d307a9715d668b7f1c4b20cb1379647415f +fb28194f95fc426d3aa1e126c9b52a84a80a1086e13016c4210234ce4acf3e12823391155fa49f +0b2eb8c0ad94a35fa21542640a61a3526588fb85dab44fa81542881389a848671bf18e908c26f2 +11f712f64208218e07e2faa3e3de720f5c381daa1042a41bc272706be22295683f3e511f2084c8 +34d261b9f7dee4132e2c470821aa1a043e31e212904208214e043048b18a4e54d883c4bd104208 +218410198262ee851042082184c81064b91742884ac0f2642ccba8909eec827900e1df2d4817aa +4fd981ea8fa82cc4ecb3a4705c1d92b81742880ac2329aaccdce7aed716b168bcc859593f85d00 +d6fe0fff685865507dca1e547f4465610537e68bc5d521bd7d2184a82074cefcc89e3ad2ec8377 +cebb678de974a1fa943da8fe88ca82e59e1feb8bab43aa0142085141707d6bf9ccec25dd4b74aa +3e6517aa3f221dc4d5a1b48a7b96e489264faf5ebd824fc9097f274adc723f420851596877e2d6 +1cae5dbbb64b429497647d19fb645d158988ab3ba9e60901b50a0b0bc7079f2bcd6db7dd662346 +8cb061c38695a6152b56b880ffebafbfdefefbdfffbab5a413d1b46953bbeebaebecedb7df0e72 +8e64ecd8b1f6e1871f3ad7931042a48b534f3dd52ebffc729b3163469053026dce962d5b6cf3e6 +cd41ce91ecdab5eba80ef6da6bafb51b6eb8c1860c1962dbb76f7713dc44e6c20fa0e5e7e7075b +87b9f5d65bdd44b7050b16043987193f7ebcd5ad5bd7962d5b16e494a0fa947dc4d59fb3ce3acb +1944972c59e2b6313c4c9830c1e9a7d5ab57bb3cbe73e79d77dad4a953dd36a8fe6427717528ed +a683471e79c4eebefbeed2b476ed5a976ebffd76dbb97367709410421c3fcc9d3bd7757cc3870f +0f72ccce3efb6cd776c589b3445c7df5d5ce2d8e31e34f7ffa93dd78e38dd6aa55ab60afc83606 +0c18709447a877efde2e4e3615549fb293c58b175bd7ae5d832db38e1d3bdaa64d9b8ec8ebd1a3 +872d5ab428d88a47f5277ba916bf208d1b560c0f15f4965b6eb13beeb8c36ebef966ebd0a143b0 +e7481869de75d75d366edc381b33664c902b8410e9e7c5175fb4d1a347bb550758a2ee9c73ceb1 +891327067bcb864eb4a8a8c89e7efa69b78a0156b7c993273b6fa6c84e66cd9ae5047e98810307 +a654af7c7d7aeaa9a7549fb28c356bd658b366cd4a078168a63973e63891efe9d2a58b1b042442 +f527bb49bbb8c7d5882bd2278f8f9767ff15575c61cf3df79cdd73cf3d3669d224e70e8f82e0a7 +62fefad7bf76ee2846ad84ed0821445540f8cdb469d3ecfcf3cfb72f7ff9cbae2364bde85469db +b6ad2b23bc72016117898c1722f379f7dd776dd0a041c19639c1464a6512a5ea53768318f7621e +718f957ec3860dd6be7d7b97d7bd7bf7a4e25ef527bb49bbb8c7c27ef1c517bb74d1451705b987 +c195346fde3c67cd6fd7ae9d5ba39338b2c2c2c2e088127af6ec693367ce2ced5cdf79e71d77ac +1042541553a64c71ed528b162decb5d75e0b7253032b1b6b4c87851bdba9866088cc83fe0bab29 +750a060f1eecfab254f0f5298cea53f680b8efd6ad9b8ba16fdebcb98b955fb870a113fa183a89 +af27943011aa3fd94ddac5fdf3cf3f6f0f3ffcb04bbffbddef82dcc3e0f266822d21373e5169a3 +2be1f0230c54de30d16d2184483774a0f3e7cf0fb652c7af318d3bdc433ba60500b21bc43ca21e +faf5eb9770c18828be3e85517dca1e98eb43e84de7ce9d4b2df43e169fb474e952979708d59fec +a65a62eec3e0266269b9679f7db634bdfaeaabb67cf9f2e08812b66edd6a050505c156c9285461 +394288e39575ebd6390b1ba1871e3a6626e58aec0571cf24dabe7dfbdaca952b8fb2a62642f529 +bbc12a8f5622fc062b3ef0ee99108bb84f169203aa3fd94db58b7be2c6a8b04c5c23f68bd529ae +b9e69a60ef6108c96129a833cf3cd3c5985d7ae9a5495d504208712cd9b76f9f6bb7befef5afbb +6d625e69e7a64f9feeb645f642bdb8f0c20b8f5a6a3519be3e5d76d9656e5bf529fb40d4b3a478 +78551ce2e6fbf4e973d432aa51e2eacfa851a3547fb284b48a7bbffe6a1ce1caf9d0430fb98a37 +74e850cbcbcb73db1e268c00d60dc27a887d6542d29b6fbee92aaa1042542595f9c5c8471f7dd4 +4d987cecb1c7dcef7eb052c5aa55ab82bd229b085b48b1de23d4ca126451549fb21beaccecd9b3 +6dc78e1d414e49680eab30a1a1ca225a7f58c94bf5273ba8714838a7efb78f8510228bd8b871e3 +5171ad22bb603592962d5b065b9543f529fb50fd119525ae0e557b588e1042640a4c9ead8ca55f +9cd8f0eec313a82b8bea5376a1fa23d2415c1d92b81742880a82958ca50ed5a1661fbc73de7d3a +2da5aa4fd983ea8fa82cbce7e2e2e2d83aa4b01c2184a804c4c3e21655879a5d602da353cdcfcf +4fabf555f5293b50fd1195a566cd9a6e795396988f22712f84104208214486a0b01c2184104208 +213204897b2184104208213204897b2184104208213204897b2184104208213204897b21841042 +08213204897b2184104208213204897b21841042082132841a0505055ae75e082184104288131e +b3ff07da948fd13acabbe40000000049454e44ae426082 +}\kerning2\f4\lang1033\par +\par +\cf1\highlight2\f1 To fix this we can change the order by putting the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/NumericalAttributes/timefield.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 TimeField Attribute}}}}\f1\fs22\~after the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/DecorativeAttributes/suffix.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 Suffix Attribute}}}}\f1\fs22\~or use the\~\i order\i0\~parameter that every attribute has to execute the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/DecorativeAttributes/suffix.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 Suffix Attribute}}}}\f1\fs22\~first, C# will first go through the attributes with the lowest order from left to right then to the ones with the higher order the same way, the default order of all attributes is 0:\par +\par +\cf3\highlight0\kerning0\b\f3\fs18 using\cf4\b0 \cf5\b UnityEngine\cf1\b0 ;\par +\cf3\b using\cf4\b0 \cf5\b EditorAttributes\cf1\b0 ;\par +\par +\cf3\b public\cf4\b0 \cf3\b class\cf4\b0 \cf5\b AttributesExample\cf4\b0 \cf1 :\cf4 \cf1 MonoBehaviour\par +\{\par +\cf4 \cf9 [TimeField(TimeFormat.YearMonthWeek, ConvertTo.Days), Suffix("to days", order = -1)]\cf1\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field;\par +\}\par +\par + +\pard\widctlpar\sa360\sl360\slmult0\highlight2\kerning2\f1\fs22 So now the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/DecorativeAttributes/suffix.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 Suffix Attribute}}}}\f1\fs22\~will be executed first and the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/NumericalAttributes/timefield.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 TimeField Attribute}}}}\f1\fs22\~will draw the field with the suffix already on it.\highlight0\kerning0\fs24\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf0\f5\fs22\lang9{\pict{\*\picprop{\sp{\sn wzDescription}{\sv Image}}{\sp{\sn posv}{\sv 1}} +}\pngblip\picw15866\pich1589\picwgoal8995\pichgoal901 +89504e470d0a1a0a0000000d49484452000002f70000004c0806000000e9ed9824000000017352 +474200aece1ce90000000467414d410000b18f0bfc6105000000097048597300000ec300000ec3 +01c76fa86400001fa149444154785eed9d07941cc5b586af72ce799573044928239448028c303c +5b36c1e660c01830c71c1b8c8cb079323660c303676c1c08cf24db87e3872d0b218c504016a084 +84728e28271441e9e9abed5a5aad9ed9d9dd99d5cee8ff74ea68babaa7baabbbb7eaaf7b6fd594 +1b3a74e80913420821841042643de5f2f2f224ee851042082184c80164b9174208218410224728 +1ffc2f841042082184c87224ee851042082184c811321696f3fdef7fdffaf6ed1b6cc5f3d24b2f +d95ffffad7604b08218410420851123266b9efd3a74ff02931d75f7fbd7df18b5f0cb684104208 +21841025a142ebd6adc7059fd3cab5d75e6be5ca950bb61273eeb9e7daa79f7e6a4b962c0972b2 +9f6ad5aad9d1a347832d912be8b90a218410b9419b366decaaabaeb22baeb8c2860c1962eddab5 +b3bd7bf7da9e3d7b82234ac64d37dd64bd7af5b20f3ef820c8293a152b56b46f7ce31bd6af5f3f +57cef1e3c7833dc9293571bf66db1a1bfdc47576fd05d7dad0ff1e61a3fa5e6935aad470fb7af6 +ec69afbcf28afb5c9ae035b8e8a28bdce062cb962d416e3e356bd6b4ca952bbb7d9eb8bc28bc1c +0f3ef8a06ddfbedd0e1c3860b7dd769b1d3c78d0b66ddb161c913aa99cafa8d4a953c75dd38001 +034e49152a54b08d1b3706479d391a376e6c37df7cb3eddcb9d376efde1de4a6c6b061c3ecf6db +6fb777df7dd78e1c39e2eedf95575e69a3468db2f3cf3fdf1a366c68ebd6ad2b96400f3fd78f3e +fa28c84d4cf4d975efdeddbef7bdefd982050b6cfffefd2e4f08218410a5cf881123ec4b5ffa92 +d5ad5bd756af5e6dbb76edb28e1d3b5afffefdedd8b163b676eddae0c8e243f90d1a34b0b7de7a +2bc8293a68b6cb2fbfdcfd3f6bd62c3b7cf870b0273909c372dab66debacea8912fb53e1c48913 +76f4d8515bfed10a6bde20cf566d5d6d552b57b5ba35eaba7d678a5ab56ad9d0a143ad73e7ce4e +1446410093c2c4e545d9b46993bdfaeaabb66cd93227ee289f97a738a472bea2e2afa952a54a4e +a8fac440a42c50b56a55777db56bd70e7252a34a952a4ec8bffffefbae2ee5cb97b76f7deb5b36 +68d0205bb972a513f5c3870fb7af7ffdebc1378a46f8b9a642f4d92d5ab4c859033efff9cf0739 +42082184286dd0af975c7289fb8c6179f2e4c9367dfa74fbc31ffee0f22ebdf45267d54f95ef7c +e73bf6c8238f9c92c2c66db6efb9e79e60ab6860e47ceeb9e75c2a8a4721a1e5fed0a1436ec411 +175a83286754c3e82611de72bf70c342fbafff196d53164fb59dfb76daffcd7acd8e1c3d62cfbe +fdbc756bdecd5a366ce98e2f6dcb3da2af478f1e367bf66cf7ffcc99330b4644ecc39b401806a3 +a555ab5639eb76340f01ca888aef211cd98755b66bd7ae4e30e33e217ff1e2c5d6aa552b1b3870 +a0139dde8a8fe8e7fb1f7ffcb1eddbb7cfedbbfaeaabdd7d6304193d1fe521ca070f1eec2cd1cd +9b37b7ad5bb7165887b17ab38f89ccf5ead57316e6a80ba7468d1aee9a7899c78f1f6f0b172e74 +8972b04eb30f2f06756adfbebddba69c4f3ef9c40d88d8c63dc4b9380e2bb8af0775e7ba704351 +7f8e1f3972a42b8732b8cef0b15c2765718d3b76ec70d7475da9c3bc79f35cf9c9ea1b86d1f679 +e79d67afbdf69afb6368d6ac9973b551c70913263871cd35356ad4c8d59777176f05e5527ecb96 +2ddd7eeae9af31d173e57bc9ea10f7feb09f67c27b3463c60c771e21841042942e84e2e0c907a2 +0488e0c0db8e36c0e80b68a5f9f3e7bbcf85817ec43a1f4e40b93076ec58774c71418fa3138948 +489584967bc4076e8a38c84f559c746bd1cdde7860828de83eccae38ef72bbfcbccb6c68b7a12e +6f40a7fec151a50f137e119cfffad7bf9c980e4f00ae5ebdba8b732221e0d91f97c7ff3cbc5b6e +b9c5ba74e9e2c4accf6bd2a449505afe0346782272899dbae0820b5c7ef4584423db8c2ae3ce47 +bae38e3b5c9809a297c1c2983163dcb188c8fbeebbcfd583e3b0107fe52b5f71e5c6c14082327c +e23bdc0fc42a1670f633e11991cc4b85659cf211c21ccba8f7ce3bef7465f97a7ced6b5f737544 +30df75d75d76ebadb75a5e5e9e13f8ecf3c75e78e185ee9e11aad2a95327fbe637bf193b013b59 +7da374e8d0c10d34d6ac59e3b619e13208406877ebd6cd7d7feedcb9f6c73ffed1e5fbb209cde2 +8f98e3089be10fdcd727d1730def8fab43dcb303acfedc57ae5508218410a50fbac443780eda6b +e2c48976d9659705b9e68c892565f9f2e5297bfb13819e407b91e2b44f2292ae968395346a9d67 +9bfc54a950be82d5ae5edb76eedf65fddaf5b1e3274e58cb062d5c1efbce04782410d0883d2cb1 +1b366c3865d94e465d58d749cf3fffbc138371791ecaf9c94f7e62d3a64d0b724e052fc72f7ef1 +0bfbe94f7feae2da2fbef8e2604f62e2ce87e51821f9f4d34fdb9ffffc677bfcf1c79d30c5728c +0827a4856bc00bf2f39fff3ce1f5c035d75c633ffbd9cf0a1282134bf53ffef10f675d1e3d7ab4 +bb4f7ffbdbdf826f98bdfcf2cbf6e4934fbaffa74e9deaee2162d8c3c8f437bff98dfdf39fff2c +f8eeaf7ffd6b172a83e80fb374e952fbd5af7ee5ee9b1f39474956df2858e49908e33d15cc73c0 +c586986610f2d8638fb9c92d3e440ad14ee25efde94f7f72d7cdb3c182ef29ecb926aa43a277c5 +cf21e05a8510420871e6c19b4eb4445807161774060908a541039c09928a7b2ca10894306c1765 +42e29817c7da053f18660bd67d680fbdfa88bd31ef0d7be99d57eca6a76e098e287d7880585309 +9b20de1e2188a80b5bdb8b4261132f56ac58e1fe477812ff8d3b8891625141c003134e7ffce31f +3b570fd661426408fdc06a7ddd75d7d9c30f3fec2cebc95c38bcccbffbddef0a12567b4088f399 +99e3885a063f804045187ff5ab5f75e7262c05b0e87b10b840b80a20b6816dae330cf7017897f8 +1c277893d5370a7309705d856105a6871e7ac8c5bbe1a12196ffde7bef75d7ec47eefed9306045 +e087576d2aecb9c6d5c15be9e3e03d83f03d1342082144e9e1f58e8718fb2f7ce10bc1563eccb3 +2b0e182449c9b440514037609c24790d910a85ae734f1cb1b73cf2bf8f2b4e95b1d78cb1ffbdeb +39f7f9c5bb9fb73ad5ebd863373c6a4fdef8b8cb3b13103e415811b1f6c457796b6e3a466d7110 +d6e1214c03d18d07c45b99bdf0c52a9d0c1f0ac568108b3109218f3b89329f78e2097bf4d1476d +d2a449ceaace84d2448308e2d97dbc3dc94fa865e08178661bcb36966f20a69d301d6fadfefbdf +ffeef28b4bd8e2cf3d890bf34a56df28781dc2f78ffa33539d7025fe90fffdef7f3b81cfb36610 +c7f1e0dd5cd413ef02c7a74a2a7508e38ff7e71642082144e912f5c633572faa6992453e44f113 +6ac3a055fce4da924ca885162d5ab854140a15f74c9ef5cb44f27f5157b841ccef3bbccf1ad66e +64f56ad4b3bd873eb6f3daf5b6fa35eb0747942ec45161b54500ffe8473f2a48ebd7af3f45dc23 +d49800190e2789cb4b05e2d4b11a533e2b0d31c11698bb80c027e68b0998d11ff48a9e8f49a158 +89893de77f26e91237ceff0c54a80775632d54428d88334f24eeb90fbd7bf72e48fec54110133e +42580f2298f8784098f2ec891f43f873bd25813ae306a32edc1b7f4fc224ab6f143c4a086c3f50 +424033b781790784f770dff1d2908f959eb2191031b1867bc13c836f7ffbdbb15e8144c4d5c1ff +7dc4bd2bf5ebe7bff345096b1342082144fac02bffe69b6f065bf9c64092077d5898e73e0ce1ca +44168479e081075c9e4f185f8b0306491feae30dd1a950a8b8072627129e51dc85fd8f9f386e57 +f71b65fb0fed3ff9ff5556bd4aea9302d28d9ff4c86a2c61d826aca275ebd66e9b511b613b083e +6f718dcb4b0562b70967e1e16045f671ecb858182d22c899704a6887b7e643f47c88ee679f7dd6 +89d51ffef087ae4cc436d674c249f8fe8d37dee8468cc4d0bff0c20b055e972808522684fac424 +5826fd52364b3e6edebcd9c58eb3e20ca2d487eb30a175dcb87109275ba70aebbd735ec437e144 +c4fa474956df28e43190f19355b97e62dd9a366dea26bbb22c25d6f9dffffef74e78f32e533683 +9afbefbfdf09f5d75f7fbd204c271592d521fcecbce7064f081e1b1fce2384104288d2e7edb7df +767a00ed80718ec467f2a64c99121c5574fc24daa21ac213415833c65a920f794e857243870ecd +c862f388d6a2c41cb10464590331482c77388c222e2f157c8c7f5ccc1465b23f3a7919e2cec7b1 +084662cca371f558eb093561859b74bd5c61fc79b1a41707aceedffdee77ed99679e711e8644f7 +244cb2fa7a10f6782e58baea2f7ff94b909b0ff7834153dc334ba5ec28d48199eb4cc44d5687f0 +b3e33c0c8a180410662484104208910952b2dc17873973e6049f0aa728c7962671823091482c0c +847622114b9971c21ee2ce475989d63c258f89ac9910f6c07afcc515f65192dd9330c9eaebe1fe +e171200c263a778173247a66a9949d8c6475083f3bbc0fdcb7380f851042082144bac898e55e88 +38b0923339f7c30f3f3c6d25a66c2117ea2084104288dc44e25e0821841042881c216361394208 +2184104288d2a55caf5ebd64b91742082184102207283770e040897b218410420821720085e508 +2184104208912348dc0b21841042089123282c4708214ec22f17f38bce99fa8d08218410229df0 +0399fc5866952a55829c7c24ee8510673d087b7ec8ac62c58a418e1042089159f875fd9282418a +1416f80acb11429cf560b197b0174208916d60bda70f0b23712f8438eb8986e2b05dbe7cf98284 +7585c4671a5285ee082184282b44fba48c85e554ab56cd8e1f3feedcddc5818eb44e9d3ab66bd7 +ae2047082132c3c71f7fece2163d356bd6b4e1c3873b311f86368d3669d6ac59ce5282d08f837c +be7becd8b120a7f8346edcd8b66ddbe63ee35d387af4a8fb7c26887321734fcef46087eb4ac7bd +164288d224ae4d857af5ea59bb76edac76edda6e9b3e6af5ead5b67bf76eb71de5d0a14305c742 +85162d5a8c0b3ea785468d1a599f3e7dac61c386d6ba756bd731eddcb9b3c80d6fab56adac63c7 +8eb67efdfa2027316ddbb6759ddec18307831c2184481d8c10e1461671dfab572f67a4a852b58a +8b65e4ff6ad5ab599dda755c23ba79f366276ce318306080b56fdfded6ae5d1be4e443638dd162 +cf9e3d6e9b72398e36321123468c700d378d3be53237e0c08103c1ded4e9d4a953d2f3a4026dfb +39e79ce3aed927eab07dfbf6e0883343bf7efd8a7d5f8410e24c11352001ed2aed35fdc7f2e5cb +6dc3860dcea8d3bd7b77d74fc5097cf66734e69e932f58b0c0de7bef3d9b366d9aedd8b1c33a77 +ee1cec4d9d75ebd6d9f4e9d383ade4d4a85123e1e84708218acb8993fff61fda6f93174eb1cdbb +37dbe28d4b5c63dcb2654b370088a352a54acec8c1ffb56ad50a72f3c13b10f610d06e610489c3 +7b05c68f1fef1af79240597416e960e9d2a53671e2c482b468d1a2608f1042889280c59efe65c6 +8c19ce8084e189c467f2d8c731859156cb3dd6f3366ddad8b265cb821c7316aabd7bf716b892b9 +b0debd7bbb0ead6eddbacee2834b176b109d2696213a45e8d2a58b6dd9b2c59a3469e2ca3d79ad +ae83cacbcbb37dfbf6b90a77eddad59a366deacaaa5fbfbe3b5e08218a42d4728fc59eb666efc1 +bdb67cf372dbb97fe749917fc00e7d7ac8ea54af6d35aad6b0152b56388b7a14da2acac3ba8285 +1f030774e8d0c1251a663c9308f661c386b94102db84ded0f60d1e3cd8b569e79e7bae3b07e141 +58dc0903a2fda43de5183c9bb47b1f7df4912b9f32f00cf83630bc7de9a5975ad5aa555d1e6d27 +16ee060d1a384f00c617dae3fdfbf717783f29db7b1f386ed3a64d2e9fb69763bce721cc902143 +9cf59c72e80bb86eeace75535efffefd5d7994413ec7521fae91fd3d7af470f78be73070e040eb +d6ad5b4118148c1c39d26d0f1a34c85d330316ef8968debcb9bb26eac5b9b1e4531ee582c23b85 +106591a8e51e0339167bda79a0bdc44844bb4dfb47df423b8ed80f9351cb3d85d341d129d068d3 +41c2e1c387ddff886f04facc99339d559f86386cd52784076bfdca952b839ccfc01286359fefb1 +9fc1002c59b2c49d934ef0830f3e707942085152b0da972bc784da0a56a56215fbe4e82756ab5a +2dab54a192db97081ade8d1b373af14e3be8a1dd226672d5aa553679f264d75ebef3ce3b4e0c4f +9a34c935de80f8e798091326b8ed2808648ec76a4e1988d8c278f3cd379d98e67b3e7e1fb1bd70 +e1427be38d375cdb892086ead5ab3bc1cdb1eca333613b0ca1453e794f0465f96b41983320a04e +0c0ee8a0a64c99e2caa3530ab7fb0c64e6cc9963afbffeba2b8fb69e734f9d3ad595e361e0c340 +88e3a80f65d26744c178c4e08173719f19b8700d420851d6c1c0e18d11b4711879487c06f68563 +eb1391f6b01c1a7862846884b1c2d38178f7358d381d9e5fb287ce2e6ce5dfba756bc218563a40 +5f61acfd74545197b71042a48d93fafde8b1234ec8d7ac5ad309fd6a95ab59e54a95addcc97f71 +102288510371499b453bc5fca3a2406c7db218768c1c7e022b468d66cd9ab9cf450151cc353217 +8ac104e571bd5c2bed331620ace158fbe7cf9fef06251e062cbec321e13d003c1508773c1e1872 +7cdb8e751da1cebdf0e7a25c0f75c51b403e83013ff8e03ed01f6089f778c30fd7b866cd1a778d +61b0e65307fa0acec5f360de167d8f10429c2da45ddc030d2b1675ac52586fbcf505cb8b17f69e +b098f71d561cd1efb11d8e5d154288b47252bfef39b8d7f61cd86b478f1fb5039f1cb0c3470e3b +d19f08acf6b44d84a8907c5e3ac192eee15c3e8cb12820aefd645e9f10d80869ef514024530742 +8710c91e0c3478587df2621c10dfb89519747818ec10a2432811214bc9da79889b60e609f70371 +75a74e84f584eb85374073b28410d900460d8c2340c8257358493efc927d1c53186915f7b8537b +f6ec196ce5431ca48f03220c27ec4ee073aa56a7e8e435b6e3e25d8510221d609d6fd9a08535ac +d5c0da35696735aad4b04ecd3a5a954a559c85380e4240e6ce9d5bd020cf9e3dfb34eb724941ac +7af81c5e252c7c5dc98c1f3e2e9eebf30941eee3f529877a10fe82479515c952014b3ef5266cd2 +0b6aea8fc18790ca79f3e69d3238292a616f2dfd47b8eee04340fdbd2711e2c4b610429475f092 +12b6e80d17887a2fecc9635fd8939a88b48a7bdcab58783839318eb84289c1f417461c2a2e5d62 +87187de0be0dbb5c93418780d50751cf24291a75dfb06369c2351c177f298410c5a57cb9f2d6a4 +4e63ab55f564bbd3ac8355ad5435a1b0a7cd23cc85f0142643910833619bb94680b59970116fd4 +609b18f7a284d620e811ccb4af185310afc079185cd0c692c242186b391671ce83251db1cdb969 +9f698bb17033511541cef5114e49f958ef6957fd7c000ffbc20968d7299beb2174c8cf8bc2a8c3 +39481c4b3b5e5cf00a707d9443ffc179a23048e9dbb7afbb6eae89baa86f10426403b4e37847f1 +74d25e631c27f1993cf6714c61a47d9d7b2c3f5854e81468e811f65c0c20c2190060e1478ce3ce +f5ab30703c629d8e00f82e9d1ec723e8d9c62a838b9bd84d965ff3ee5d3a2abe4f671676110b21 +442a603c08876ef01941485b53e1e43f3b76b24daa50d50962da21da2a442cdb1ec426f1e5d1b5 +e411d5b44fc4a3d328d3f63110a06d242c112b3ae29fb2381fed5d7825048ef5abe5d0c6d166d2 +862272893bf76d28fb693fe90438a7f79a627907061b887ece895b97769981024299010b936a7d +fd38960104d7ca71be0d67e5320c38b4f13ed14e730e8c3ac4d9e351259edfd7c9b7c9887aae87 +1878ee2f6d3be72744c87b0c289f7bebddced4d7cfc5e2fee24dc0b8c379b1c6fb557bf81edfa1 +fedc2bfa06843dd7c635712e2184286bc48521d24fd006a37759618d761b4f2ccb107b637914f4 +b58f92818cfd426d3aa1e126c9b52a84c80408c370180be210011a67a5671f09c199c88a2fd2cf +95575ee956cad12fd10a217285b051a924447fa13623136a8510229b888a74b611ef08c968221f +712f612f8410a22c705a1f960d967be0c2e950851022dd1096835b1317a9447bd9447d801022d7 +4887e5de7b93b32e2c470821320d029f18710948218410d900062956d1090b7b90b81742082184 +10224750ccbd10420821841039822cf742085142589e8c651915d253f621c69525388bf2db02a9 +c03b90cafad3e2cca0e77e7692a9e75ed691b817428812c0329aaccdce7aed716b168bb2052b1e +31bf82f5fac33ff45512fc3bc0efb1684276d944cffdec2413cf3d1b504f24841025801f7da273 +97b0cf0eb0e4f1e356ac0b9d2e7807285302afeca2e77e769289e79e0da8371242881240288e3a +f7ec239d21540ac7ca1ef4dccf4eceb667957671cf923cd1e4e9debd7bf02939e1ef44892ef723 +8410e98076072b4f948a152bba24ce0e92f53fec938726f7887be6a9e609918cb83ea534a8d0a2 +458b71c1e7b470df7df7d9f0e1c36dc890210569f5ead56e42c3edb7df6efff9cf7fdc5ad289a8 +5fbfbedd76db6df6eebbef0639a73266cc18fbf0c30f9d3b4c0821d2c539e79c63d75d779dcd9c +3933c8c9873667c78e1db67dfbf620e7540e1c38705aa77febadb7da1d77dc6183070fb6bd7bf7 +ba4977a26cc18f96d5ac5933d8fa8c7befbdd74dbe5bbc787190f319e3c68db3ca952bdbca952b +839c7cf40e640f71cffda28b2e72c6c7e5cb97bb6d04d9238f3ce2b4caba75eb5c1edff9c10f7e +6093274f76dba0e79e3d24fa7b8fa36ddbb6ce90ccf32d29bd7bf77671ffe928ab2864c404f1f4 +d34fdb430f3d5490366cd8e0d2fdf7df6ffbf7ef0f8e124288b2c3fcf9f35d673c6cd8b020c7ec +e28b2f766d579cd04bc4cd37dfecc27430663cf3cc3376e79d775ad3a64d83bd221be8dfbfff69 +16b79e3d7bbad8dd54d03b905d2c5bb6cc3a76ec186ce58bbb6ddbb69d92d7b56b575bba7469b0 +158f9e7b6ec0e4db6cf7d095dad5d350de73cf3dc196b93f1ab61f78e001bbfbeebbad4d9b36c1 +9e5361f4fbe0830fdad8b1636dd4a85141ae1042a49fd75e7bcd468e1ce95655a857af9e5d72c9 +25367efcf8606fe1d0b10f1d3ad45e7cf14567adc1123871e244e7cd14d9c3ecd9b39dc00f3360 +c08094de05ff0ebcf0c20b7a07b284f5ebd75b83060d0a066fe893b973e73a91efe9d0a1831b04 +24427ffbb941972e5ddc808c77a04f9f3e41ae598f1e3ddcb31c31628475ead429c83d9d468d1a +b9f7002351af5ebd82dc7c1834f4ebd7cf2ebcf042574ebb76ed5c7ef3e6cd4f39179c7ffef905 +abfb74eedcd97d87f377ebd6cde5154646c43d6e4bdc9a3e797cbc3cfb6fb8e1067be59557ece1 +871fb609132638777814043f37e997bffca573913192266c4708213201e13753a64cb12baeb8c2 +3ef7b9cfb9ce99f5eb53a565cb96ae8cf0ca0c847024325e88b2c9fbefbf6f03070e0cb6cc093f +522a93f2f40e642788712fe6117658e9b76cd962ad5bb7767908ba64e25ecf3d37f0cf7dc58a15 +3667ce1c97c7b3e76f9fbe8184e86ed5aa95db1786102d043d5ee0a953a73aaf6fc3860d83bde6 +c4fcd6ad5b5d68d73befbce3b6d1c59b366d72dad68778799dbb6fdf3e676422f11dcecdf18d1b +3776fb939111718f85fd9a6bae71e9eaabaf0e723f03f7d6c2850b9d359f1bc41aa4c4b6b568d1 +2238221f4628b366cd2ae85cdf7bef3d77ac1042648a499326b976090bccdb6fbf1de4a606963f +d6bd0e8b40b6530de7106503fa1cacafbe031f346890eb7f52c1bf0361f40e947d10f788380416 +033962e5972c59e2843e628b6748d85e22f4b79fbbe4e5e5b9b9a3c0f35dbb766d6cb815ef0973 +b3fc7bb273e74ef75b081ee68be225f29e6174af377a33a0f065621447f00373057887d847a8d0 +bc79f39ca1bb303222ee5f7df5557beaa9a75cfaed6f7f1be47e061563822d21373ef187e42be9 +e14761a293104a7b528210e2ec834e7dd1a245c156eaf835ef71d17b68c7b40040f6819847d403 +2ef3448b3c44f1ef4018bd03651fe6d5107ad3be7d7b27f4c1c7e293b0e426437ffbb90baba585 +0dcb7c8efe8d03512908f630e16dde2dc271789fead6ad6b478e1c09f69813f35edcf3ffe6cd9b +dd67acf70b162cb0264d9ab84896be7dfba6b402cf19993180eb8a9bf5f2cb2f17a4b7de7acb56 +ad5a151c910fa31e464c1e462f0acb1142945568a071c3d2c87b68d071cf8aec0271cf245a56bb +c06a17b5c62742ef407682b515ab3df1cd5edcf3ccb0a222c69285e4809e7beec2df7eeddab583 +2d739fe3bc38d1e320bc420fefd18c1933dc7c0edeb1b048dfb56b978bc9e71de2b31f1460ade7 +33a13e84e530b08846b9c47146c43d314d887b26ae118fc6c4835b6eb925d8fb1984e4b03c1513 +0b887b1b3d7a7452b79810429c49b0c4d06e7df9cb5f76dbc4e1d2ce4d9f3edd6d8bec826779d5 +55579db63c6a32fc3b70edb5d7ba6dbd03d903029ee5bbc3abe260b1278e3a6a7c8ca2bffddc81 +6749d80cd672200c873071843779846f115e13058334613b8878becfe4dc70b409213a58e5895c +e198a8059e01229a38bc7c2ae764322f866d4245b1f8a7b2ea64dad7b9e7855eb366cd69e1338c +3eb829c4da037f040876c43bb18d84f278570795e7386e30ae326e1015c62d8a8b6be3c68d7275 +092132060deff1e3c70bedd081b62ebcd6353191ac6a80c1821556583800ab8b285b245af79a38 +7b2642d2c7d01913463a6dda34b78f7e88675dd83af77a07ca2ec9d63bc7e8881ef1132981d01a +26c9c63d3f3df7eca128ebdc23d211d558e199004b680ced015e1c342a7fffbb77ef0e8e3e1562 +e711f6ccdbc0028fd8e7bb58f5895a4107332196ef6391a76c6fa54703131a466cbe87778cfd9c +1bcb3e030daeaf30ca0d1c3850bf9f2c8410c584c63f2efe52946d106cde325752f40e640f7aee +6727e97cee9902e301ef1373be4aca1909cb1142885c810974e115324476109ef85852d25996c8 +2c7aee672765fd59f12bc944ada4e22d4e0559ee8510a204e056258490f84975f6651f0662845e +104ee17f24a6a4e81d28fbe8b99f9d64e2b9670312f742085142e8e471fbca825ff661fe1771d4 +e9eee889cf27b656ef40d944cffdec2453cfbdac23712f8410420821448ea0987b218410420821 +7204897b2184104208217204897b2184104208217204897b2184104208217204897b2184104208 +217204897b2184104208217204897b2184104208217284727979795ae75e0821841042881c403f +62258410420821448ea0b01c2184104208217204897b2184104208217202b3ff079279c4fe6a62 +64130000000049454e44ae426082 +}\kerning2\f4\lang1033\par +\par + +\pard\widctlpar\s1\sa360\cf1\kerning36\b\f0\fs42 Good Practices\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\highlight2\kerning2\b0\f1\fs22 Here are a few good practices to follow when using this package.\par +\par + +\pard\widctlpar\li-180\ri-180\sa180\cf0\highlight0\kerning0\b\fs24 Note:\par +\b0 These are just some general recommendations to follow when using this package, you don\f2\rquote\f1 t have to abide by them like laws, if you already have a workflow that fits better for you, feel free to use it.\par +\par + +\pard\keepn\widctlpar\s2\sa360\sl252\slmult1\cf1\kerning2\b\i\f0\fs28 Using the void struct\par + +\pard\widctlpar\sa360\sl360\slmult0\kerning0\b0\i0\f1\fs24 The\~{{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/GettingStarted/voidstruct.html"}}{\fldrslt{\ul\cf5\cf6\ul Void Struct}}}}\f1\fs24\~is made to act as a holder for attributes that redraw the property is attached to. While it\f2\rquote\f1 s not necessary to use the struct for those attributes (any serialized data type can be used), using the struct as a holder makes the code more readable for you and others.\par +When you use the\~{{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/GettingStarted/voidstruct.html"}}{\fldrslt{\ul\cf5\cf6\ul Void Struct}}}}\f1\fs24\~as a variable it makes it obvious that is a holder and it will be redrawn, it also keeps some consistency in your code rather than using\~\cf10\highlight11\f3\fs18 int\cf1\highlight0\f1\fs24\~or\~\cf10\highlight11\f3\fs18 float\cf1\highlight0\f1\fs24\~randomly in your code as holders.\par +Is also a good idea to add a\~\i holder\i0\~suffix or other naming convention to the void fields so when it comes up in something like\~\i IntelliSense\i0\~you know what it is.\par + +\pard\keepn\widctlpar\s2\sa360\sl252\slmult1\kerning2\b\i\f0\fs28 Managing multiple attributes\par + +\pard\widctlpar\sa360\sl360\slmult0\kerning0\b0\i0\f1\fs24 When an attribute has a lot of parameters or you use multiple attributes on one field, that line of code can become pretty long which is generally a bad thing. Here is an example:\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b\f3\fs18 using\cf4\b0 \cf5\b UnityEngine\cf1\b0 ;\par +\cf3\b using\cf4\b0 \cf5\b EditorAttributes\cf1\b0 ;\par +\par +\cf3\b public\cf4\b0 \cf3\b class\cf4\b0 \cf5\b AttributesExample\cf4\b0 \cf1 :\cf4 \cf1 MonoBehaviour\par +\{\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 bool\cf4 \cf1 condition01;\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 bool\cf4 \cf1 condition02;\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 bool\cf4 \cf1 condition03;\par +\par +\cf4 \cf9 [SerializeField, ReadOnly, ConditionalField(ConditionType.AND, new bool[]\cf4 \cf1\{\cf4 \cf3\b false\cf1\b0 ,\cf4 \cf3\b true\cf1\b0 ,\cf4 \cf3\b false\cf4\b0 \cf1\},\cf4 \cf1 nameof(condition01),\cf4 \cf1 nameof(condition02),\cf4 \cf1 nameof(condition03))]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field;\par +\}\par + +\pard\widctlpar\sa360\sl360\slmult0\highlight2\f1\fs24 Our\~\cf10\highlight11\f3\fs18 int\cf1\highlight2\f1\fs24\~field got pretty long, let\f2\rquote\f1 s see what can we do to organize this better.\highlight0\par + +\pard{\pntext\f6\'B7\tab}{\*\pn\pnlvlblt\pnf6\pnindent0{\pntxtb\'B7}}\fi-360\li1080\sa180\sl360\slmult0 We can put the variable on a separate line with all attributes above it:\par + +\pard\widctlpar\li1080\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf9\f3\fs18 [SerializeField, ReadOnly, ConditionalField(ConditionType.AND, new bool[]\cf4 \cf1\{\cf4 \cf3\b false\cf1\b0 ,\cf4 \cf3\b true\cf1\b0 ,\cf4 \cf3\b false\cf4\b0 \cf1\},\cf4 \cf1 nameof(condition01),\cf4 \cf1 nameof(condition02),\cf4 \cf1 nameof(condition03))]\par + +\pard\widctlpar\li1080\sa160\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field;\par + +\pard{\pntext\f6\'B7\tab}{\*\pn\pnlvlblt\pnf6\pnindent0{\pntxtb\'B7}}\fi-360\li1080\sa180\sl360\slmult0\f1\fs24 Keep the attributes from the package and the built-in Unity ones separate:\par + +\pard\widctlpar\li1080\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf9\f3\fs18 [ReadOnly, ConditionalField(ConditionType.AND, new bool[]\cf4 \cf1\{\cf4 \cf3\b false\cf1\b0 ,\cf4 \cf3\b true\cf1\b0 ,\cf4 \cf3\b false\cf4\b0 \cf1\},\cf4 \cf1 nameof(condition01),\cf4 \cf1 nameof(condition02),\cf4 \cf1 nameof(condition03))]\par + +\pard\widctlpar\li1080\sa160\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field;\par + +\pard{\pntext\f6\'B7\tab}{\*\pn\pnlvlblt\pnf6\pnindent0{\pntxtb\'B7}}\fi-360\li1080\sa180\sl360\slmult0\f1\fs24 Put the attribute with a lot of parameters on a separate line:\par + +\pard\widctlpar\li1080\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf9\f3\fs18 [ConditionalField(ConditionType.AND, new bool[]\cf4 \cf1\{\cf4 \cf3\b false\cf1\b0 ,\cf4 \cf3\b true\cf1\b0 ,\cf4 \cf3\b false\cf4\b0 \cf1\},\cf4 \cf1 nameof(condition01),\cf4 \cf1 nameof(condition02),\cf4 \cf1 nameof(condition03))]\par + +\pard\widctlpar\li1080\sa160\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf9 [SerializeField, ReadOnly]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field;\par + +\pard\widctlpar\sa360\sl360\slmult0\f1\fs24 Any of these methods are valid ways of shortening the line of code, is up to you which one you prefer.\par + +\pard\keepn\widctlpar\s2\sa360\sl252\slmult1\kerning2\b\i\f0\fs28 Using the nameof expression\par + +\pard\widctlpar\sa360\sl360\slmult0\kerning0\b0\i0\f1\fs24 Some attributes need to look for a member in your script and it will ask you to give the name of that member as a\~\cf10\highlight11\f3\fs18 string\cf1\highlight0\f1\fs24\~parameter, but strings are error prone and you might encounter issues saying,\~\i that field cannot be found\i0\~and spend hours scratching you head when you realize you just made a typo or had a character in the wrong case. Thats why you should use the\~{{\field{\*\fldinst{HYPERLINK "https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/nameof"}}{\fldrslt{\ul\cf5\cf6\ul nameof}}}}\f1\fs24\~expression, that allows you to add your variable like a parameter and converts its name to a\~\cf10\highlight11\f3\fs18 string\cf1\highlight0\f1\fs24\~for the attribute:\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b\f3\fs18 using\cf4\b0 \cf5\b UnityEngine\cf1\b0 ;\par +\cf3\b using\cf4\b0 \cf5\b EditorAttributes\cf1\b0 ;\par +\par +\cf3\b public\cf4\b0 \cf3\b class\cf4\b0 \cf5\b AttributesExample\cf4\b0 \cf1 :\cf4 \cf1 MonoBehaviour\par +\{\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf8 bool\cf4 \cf1 condition01;\par +\par +\cf4 \cf7\i // Passing the variable as a string (error prone)\cf1\i0\par +\cf4 \cf9 [SerializeField, EnableField("condition01")]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field01;\par +\par +\cf4 \cf7\i // Using the nameof condition\cf1\i0\par +\cf4 \cf9 [SerializeField, EnableField(nameof(condition01))]\cf4 \cf3\b private\cf4\b0 \cf8 int\cf4 \cf1 field02;\par +\}\par +\par + +\pard\widctlpar\sa360\sl360\slmult0\cf0\b\f1\fs24 Note:\cf1\b0\par +The only exception to using the nameof expression is when you need to input the entire path to a member inside another type, for more details see How To Use.\par + +\pard\widctlpar\s1\sa360\kerning36\b\f0\fs42 Void Struct\par + +\pard\widctlpar\sa360\sl360\slmult0\highlight2\kerning2\b0\f1\fs22 The\~\b Void\b0\~struct is an empty serialized struct to use as a holder property for attributes like the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/GroupingAttributes/verticalgroup.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 VerticalGroup Attribute}}}}\f1\fs22 ,\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/en/latest/Attributes/GroupingAttributes/horizontalgroup.html"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 HorizontalGroup Attribute}}}}\f1\fs22 , etc. that completely redraw the property in the inspector.\par +By itself the Void struct will not be drawn in the inspector but attributes attached to it will still execute.\par +If you are using the\~\i System\i0\~namespace and\~\i EditorAttributes\i0\~namespace in your script then use the\~\b Void\b0\~struct you will notice a naming conflict between\~\cf10\highlight11\f3\fs18 System.Void\cf1\highlight2\f1\fs22\~and\~\cf10\highlight11\f3\fs18 EditorAttributes.Void\cf1\highlight2\f1\fs22 , to fix that you will just have to specify which version you want to use, and there are 2 ways to do that.\par + +\pard +{\pntext\f1 1.\tab}{\*\pn\pnlvlbody\pnf1\pnindent0\pnstart1\pndec{\pntxta.}} +\fi-360\li1080\sa180\sl360\slmult0\highlight0\kerning0\fs24 Specify the namespace of the version you want to use on that line:\par + +\pard\widctlpar\li1080\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b\f3\fs18 private\cf4\b0 \cf1 System.Void\cf4 \cf1 systemVoidField;\par +\cf7\i // Or\cf1\i0\par + +\pard\widctlpar\li1080\sa160\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b private\cf4\b0 \cf1 EditorAttributes.Void\cf4 \cf1 attributesVoidField;\par + +\pard\widctlpar\fi-360\li1080\sa180\sl360\slmult0\f1 2.\tab\fs24 Specify which version you want to use for the whole script under your other usings:\par + +\pard\widctlpar\li1080\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b\f3\fs18 using\cf4\b0 \cf5\b Void\cf4\b0 \cf12 =\cf4 \cf1 System.Void;\par +\cf7\i // Or\cf1\i0\par + +\pard\widctlpar\li1080\sa160\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\b using\cf4\b0 \cf5\b Void\cf4\b0 \cf12 =\cf4 \cf1 EditorAttributes.Void;\par + +\pard\widctlpar\sa360\sl360\slmult0\highlight2\kerning2\f1\fs22 A common way this conflict can happen is when you use the editor attributes and serialize structs:\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf3\highlight0\kerning0\b\f3\fs18 using\cf4\b0 \cf5\b System\cf1\b0 ;\par +\cf3\b using\cf4\b0 \cf5\b UnityEngine\cf1\b0 ;\par +\cf3\b using\cf4\b0 \cf5\b EditorAttributes\cf1\b0 ;\par +\par +\cf3\b public\cf4\b0 \cf3\b class\cf4\b0 \cf5\b AttributesExample\cf4\b0 \cf1 :\cf4 \cf1 MonoBehaviour\par +\{\par +\cf4 \cf9 [Serializable]\cf1\par +\cf4 \cf3\b private\cf4\b0 \cf3\b struct\cf4\b0 \cf5\b ExampleStruct\cf1\b0\par +\cf4 \cf1\{\par +\cf4 \cf3\b public\cf4\b0 \cf8 int\cf4 \cf1 data01;\par +\cf4 \cf3\b public\cf4\b0 \cf8 int\cf4 \cf1 data02;\par +\cf4 \cf1\}\par +\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf1 ExampleStruct\cf4 \cf1 exampleStruct;\par +\par +\cf4 \cf9 [HelpBox("This is a help box")]\cf1\par +\cf4 \cf9 [SerializeField]\cf4 \cf3\b private\cf4\b0 \cf1 Void\cf4 \cf1 helpBoxHolder;\cf4 \cf7\i // This line will throw an error\cf1\i0\par +\}\par + +\pard\widctlpar\sa360\sl360\slmult0\f1\fs24\par +\highlight2\kerning2\fs22 We can fix the error either by adding\~\cf10\highlight11\f3\fs18 using\~Void\~=\~EditorAttributes.Void;\cf1\highlight2\f1\fs22\~between the usings and class declaration or by removing the\~\cf10\highlight11\f3\fs18 using\~System;\cf1\highlight2\f1\fs22\~at the top of the file, then to use the\~{\cf0\highlight0\f4{\field{\*\fldinst{HYPERLINK "https://learn.microsoft.com/en-us/dotnet/api/system.serializableattribute?view=net-7.0"}}{\fldrslt{\ul\cf5\cf6\highlight2\ul\f1 Serializable Attribute}}}}\f1\fs22\~we just call the namespace directly:\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf9\highlight0\kerning0\f3\fs18 [System.Serializable]\cf1\par +\cf3\b private\cf4\b0 \cf3\b struct\cf4\b0 \cf5\b ExampleStruct\cf1\b0\par +\{\par +\cf4 \cf3\b public\cf4\b0 \cf8 int\cf4 \cf1 data01;\par +\cf4 \cf3\b public\cf4\b0 \cf8 int\cf4 \cf1 data02;\par +\}\par + +\pard\widctlpar\sa360\sl360\slmult0\highlight2\kerning2\f1\fs22 Now which version you want to use if up to personal preferece.\par +\par + +\pard\widctlpar\s1\sa360\highlight0\kerning36\b\f0\fs42 Attributes\par + +\pard\widctlpar\sa360\sl360\slmult0\kerning0\b0\f1\fs24 To see how each attribute works import the package sample or check out the {{\field{\*\fldinst{HYPERLINK "https://editorattributesdocs.readthedocs.io/"}}{\fldrslt{\ul\cf5\cf5\ul online documentation}}}}\f1\fs24\par + +\pard\widctlpar\li-180\ri-180\sa180\cf0\par + +\pard\widctlpar\tx916\tx1832\tx2748\tx3664\tx4580\tx5496\tx6412\tx7328\tx8244\tx9160\tx10076\tx10992\tx11908\tx12824\tx13740\tx14656\cf1\f3\fs18\par +} + \ No newline at end of file diff --git a/Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf.meta b/Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf.meta new file mode 100644 index 0000000000..ff31e30942 --- /dev/null +++ b/Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 3d521f6a5c53f4c4d95c81206cfc5e78 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Documentation/EditorAttributesDocumentation.rtf + uploadId: 806636 diff --git a/Assets/EditorAttributes/Documentation/index.md b/Assets/EditorAttributes/Documentation/index.md new file mode 100644 index 0000000000..b92fcd7819 --- /dev/null +++ b/Assets/EditorAttributes/Documentation/index.md @@ -0,0 +1 @@ +This is a filler file so unity can detect the offline documentation, because it only looks for .md files which is bullshit because their page says .rtf files are supported, anyways go to the other file to read the documentation. \ No newline at end of file diff --git a/Assets/EditorAttributes/Documentation/index.md.meta b/Assets/EditorAttributes/Documentation/index.md.meta new file mode 100644 index 0000000000..6252b2604e --- /dev/null +++ b/Assets/EditorAttributes/Documentation/index.md.meta @@ -0,0 +1,14 @@ +fileFormatVersion: 2 +guid: 35a1a618300bf2a46a115a2e0ae5540d +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Documentation/index.md + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor.meta b/Assets/EditorAttributes/Editor.meta new file mode 100644 index 0000000000..9a85cf905c --- /dev/null +++ b/Assets/EditorAttributes/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 8bb6aaeb8c583394db1d20a84ffebf74 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/Editor/Scripts.meta b/Assets/EditorAttributes/Editor/Scripts.meta new file mode 100644 index 0000000000..fa6cf41f4e --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f4687e18dc1a3024aaaa4567bbabb62d +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers.meta new file mode 100644 index 0000000000..f27e838f62 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 39991b2a9623a10439dd199798549d6c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers.meta new file mode 100644 index 0000000000..601a520610 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 66d670bcd98fdb742b29addf8c9fd7fc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs new file mode 100644 index 0000000000..1c44f4ecf1 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs @@ -0,0 +1,419 @@ +using System; +using System.IO; +using System.Linq; +using UnityEditor; +using UnityEngine; +using Newtonsoft.Json; +using System.Reflection; +using UnityEngine.UIElements; +using System.Collections.Generic; +using EditorAttributes.Editor.Utility; +using Object = UnityEngine.Object; + +namespace EditorAttributes.Editor +{ + public class ButtonDrawer + { + [Serializable] + private class FunctionParamData + { + public Dictionary foldouts = new(); + public Dictionary parameterValues = new(); + } + + internal const string PARAMS_DATA_LOCATION = "ProjectSettings/EditorAttributes"; + + internal static VisualElement DrawButton(MethodInfo function, ButtonAttribute buttonAttribute, Dictionary foldouts, Dictionary parameterValues, Object[] targets) + { + var root = new VisualElement(); + + var functionParameters = function.GetParameters(); + + if (functionParameters.Length > 0) + { + // Parameter default setup + if (!parameterValues.ContainsKey(function)) + { + parameterValues[function] = new object[functionParameters.Length]; + + for (int i = 0; i < functionParameters.Length; i++) + parameterValues[function][i] = functionParameters[i].DefaultValue; + } + + if (!foldouts.ContainsKey(function)) + foldouts[function] = true; + + // Create the button + var button = MakeButton(function, buttonAttribute, () => + { + var paramValueList = new object[functionParameters.Length]; + + for (int i = 0; i < functionParameters.Length; i++) + paramValueList[i] = ConvertParameterValue(functionParameters[i].ParameterType, parameterValues[function][i]); + + InvokeFunctionOnAllTargets(targets, function.Name, parameterValues[function]); + }); + + // Styling + var foldout = new Foldout + { + text = "Parameters", + value = foldouts[function] + }; + + PropertyDrawerBase.ApplyBoxStyle(root); + PropertyDrawerBase.ApplyBoxStyle(foldout); + + foldout.style.unityFontStyleAndWeight = FontStyle.Bold; + foldout.style.paddingLeft = 15f; + + if (EditorExtension.GLOBAL_COLOR != EditorExtension.DEFAULT_GLOBAL_COLOR) + { + button.style.color = EditorExtension.GLOBAL_COLOR; + foldout.style.color = EditorExtension.GLOBAL_COLOR; + } + + foldout.RegisterValueChangedCallback((callback) => foldouts[function] = callback.newValue); + + // Create parameter fields + for (int i = 0; i < functionParameters.Length; i++) + { + var parameter = functionParameters[i]; + + if (!parameter.ParameterType.IsPrimitive && parameter.ParameterType != typeof(string) && !parameter.ParameterType.IsEnum) + { + foldout.Add(new HelpBox($"Parameter type {parameter.ParameterType} is not supported. Only Unity supported primitive types, strings and enums are supported.", HelpBoxMessageType.Error)); + continue; + } + + var field = PropertyDrawerBase.CreateFieldForType(parameter.ParameterType, parameter.Name, ConvertParameterValue(parameter.ParameterType, parameterValues[function][i])); + + if (EditorExtension.GLOBAL_COLOR != EditorExtension.DEFAULT_GLOBAL_COLOR) + ColorUtils.ApplyColor(field, EditorExtension.GLOBAL_COLOR); + + int index = i; // Local copy for the lambda + + PropertyDrawerBase.RegisterValueChangedCallbackByType(parameter.ParameterType, field, (valueCallback) => parameterValues[function][index] = valueCallback); + + field.SetEnabled(targets.Length <= 1); + field.style.unityFontStyleAndWeight = FontStyle.Normal; + + foldout.Add(field); + } + + root.Add(button); + root.Add(foldout); + } + else + { + var button = MakeButton(function, buttonAttribute, () => InvokeFunctionOnAllTargets(targets, function.Name, null)); + + if (EditorExtension.GLOBAL_COLOR != EditorExtension.DEFAULT_GLOBAL_COLOR) + button.style.color = EditorExtension.GLOBAL_COLOR; + + root.Add(button); + } + + return root; + } + + private static VisualElement MakeButton(MethodInfo function, ButtonAttribute buttonAttribute, Action buttonLogic) + { + var buttonLabel = string.IsNullOrWhiteSpace(buttonAttribute.ButtonLabel) ? function.Name : buttonAttribute.ButtonLabel; + var tooltipAttribute = function?.GetCustomAttribute(); + string buttonTooltip = string.Empty; + + if (tooltipAttribute != null) + buttonTooltip = tooltipAttribute.tooltip; + + if (buttonAttribute.IsRepetable) + { + var repeatButton = new RepeatButton(buttonLogic, buttonAttribute.PressDelay, buttonAttribute.RepetitionInterval) + { + text = buttonLabel, + tooltip = buttonTooltip + }; + + repeatButton.style.height = buttonAttribute.ButtonHeight; + repeatButton.AddToClassList(Button.ussClassName); + + return repeatButton; + } + else + { + var button = new Button(buttonLogic) + { + text = buttonLabel, + tooltip = buttonTooltip + }; + + button.style.height = buttonAttribute.ButtonHeight; + + return button; + } + } + + private static void InvokeFunctionOnAllTargets(Object[] targets, string functionName, object[] parameterValues) + { + foreach (var target in targets) + { + var methodInfo = ReflectionUtility.FindFunction(functionName, target); + var functionParameters = methodInfo.GetParameters(); + + object[] paramValueList = null; + + if (functionParameters.Length > 0) + { + paramValueList = new object[functionParameters.Length]; + + for (int i = 0; i < functionParameters.Length; i++) + paramValueList[i] = ConvertParameterValue(functionParameters[i].ParameterType, parameterValues[i]); + } + + Undo.RecordObject(target, $"Invoke {functionName}"); + + methodInfo.Invoke(target, paramValueList); + + EditorUtility.SetDirty(target); + } + } + + internal static void SaveParamsData(MethodInfo[] functions, object target, Dictionary foldouts, Dictionary parameterValues) + { + var data = new FunctionParamData(); + var keyToMethod = new Dictionary(); + + foreach (var function in functions) + { + if (!IsButtonFunction(function, out bool serializeParameters) || !serializeParameters) + continue; + + string id = GetFunctionID(function, target); + keyToMethod[id] = function; + + if (foldouts.TryGetValue(function, out bool foldoutValue)) + data.foldouts[id] = foldoutValue; + + if (parameterValues.TryGetValue(function, out object[] parameterValue)) + data.parameterValues[id] = parameterValue; + } + + if (data.foldouts.Count == 0 && data.parameterValues.Count == 0) + return; + + JsonConvert.DefaultSettings = () => new JsonSerializerSettings { Converters = { new UnityTypeConverter() } }; + + string jsonData = JsonConvert.SerializeObject(data, Formatting.Indented); + + File.WriteAllTextAsync(Path.Combine(PARAMS_DATA_LOCATION, GetFileName(target)), jsonData); + } + + internal static void LoadParamsData(MethodInfo[] functions, object target, ref Dictionary foldouts, ref Dictionary parameterValues) + { + if (!Directory.Exists(PARAMS_DATA_LOCATION)) + Directory.CreateDirectory(PARAMS_DATA_LOCATION); + + try + { + var filePath = Path.Combine(PARAMS_DATA_LOCATION, GetFileName(target)); + + if (File.Exists(filePath)) + { + string jsonData = File.ReadAllText(filePath); + + var data = JsonConvert.DeserializeObject(jsonData); + var keyToMethod = new Dictionary(); + + foreach (var function in functions) + { + if (!IsButtonFunction(function, out bool serializeParameters) || !serializeParameters) + continue; + + string id = GetFunctionID(function, target); + + keyToMethod[id] = function; + } + + foreach (var key in data.foldouts.Keys) + { + if (keyToMethod.TryGetValue(key, out var method)) + { + foldouts[method] = data.foldouts[key]; + parameterValues[method] = data.parameterValues[key]; + } + } + } + } + catch (ArgumentException) + { + return; + } + } + + internal static void DeleteParamsData(string filePath) + { + if (File.Exists(filePath)) + File.Delete(filePath); + } + + internal static void ClearAllParamsData() + { + if (Directory.Exists(PARAMS_DATA_LOCATION)) + { + int fileCount = 0; + + foreach (var file in Directory.GetFiles(PARAMS_DATA_LOCATION, "*_ButtonParameterData.json")) + { + File.Delete(file); + fileCount++; + } + + Debug.Log($"{fileCount} files were deleted"); + } + } + + internal static string GetFileName(object target) => $"{(target as Object).GetInstanceID()}_{target}_ButtonParameterData.json"; + + internal static string GetFunctionID(MethodInfo function, object target) => $"{(target as Object).GetInstanceID()}_{target}_{function.Name}_{string.Join("_", function.GetParameters().Select(param => param.ParameterType.Name))}"; + + internal static bool IsButtonFunction(MethodInfo function, out bool serializeParameters) + { + var buttonAttribute = function.GetCustomAttribute(); + + if (buttonAttribute != null) + { + serializeParameters = buttonAttribute.SerializeParameters; + return true; + } + + serializeParameters = false; + return false; + } + + private static T ParseFromJson(object value) + { + if (value == null) + return default; + + try // Try to see if we can cast the value directly + { + return (T)value; + } + catch (InvalidCastException) + { + string jsonString = value.ToString(); + + try + { + return string.IsNullOrEmpty(jsonString) ? default : JsonConvert.DeserializeObject(jsonString); + } + catch (JsonReaderException) + { + return default; + } + } + } + + private static object ConvertParameterValue(Type parameterType, object parameterValue) + { + bool isDBNull = Convert.IsDBNull(parameterValue); + + if (parameterType == typeof(string)) + { + return parameterValue?.ToString(); + } + else if (parameterType == typeof(char)) + { + string stringParamValue = parameterValue.ToString(); + + return isDBNull || stringParamValue.Length != 1 ? '\0' : Convert.ToChar(parameterValue); + } + else if (parameterType == typeof(int)) + { + return isDBNull ? 0 : Convert.ToInt32(parameterValue); + } + else if (parameterType == typeof(uint)) + { + return isDBNull ? 0 : Convert.ToUInt32(parameterValue); + } + else if (parameterType == typeof(long)) + { + return isDBNull ? 0 : Convert.ToInt64(parameterValue); + } + else if (parameterType == typeof(ulong)) + { + return isDBNull ? 0 : Convert.ToUInt64(parameterValue); + } + else if (parameterType == typeof(float)) + { + return isDBNull ? 0.0f : Convert.ToSingle(parameterValue); + } + else if (parameterType == typeof(double)) + { + return isDBNull ? 0.0 : (double)parameterValue; + } + else if (parameterType == typeof(bool)) + { + return !isDBNull && (bool)parameterValue; + } + else if (parameterType.IsEnum) + { + return isDBNull ? Enum.ToObject(parameterType, 0) as Enum : Enum.ToObject(parameterType, parameterValue) as Enum; + } + else if (parameterType == typeof(Vector2)) + { + return isDBNull ? Vector2.zero : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(Vector2Int)) + { + return isDBNull ? Vector2Int.zero : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(Vector3)) + { + return isDBNull ? Vector3.zero : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(Vector3Int)) + { + return isDBNull ? Vector3Int.zero : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(Vector4)) + { + return isDBNull ? Vector4.zero : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(Color)) + { + return isDBNull ? Color.black : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(Gradient)) + { + return isDBNull ? new Gradient() : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(AnimationCurve)) + { + return isDBNull ? AnimationCurve.Linear(0f, 0f, 1f, 1f) : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(LayerMask)) + { + return isDBNull ? (LayerMask)0 : (LayerMask)Convert.ToInt32(parameterValue); + } + else if (parameterType == typeof(Rect)) + { + return isDBNull ? new Rect(0f, 0f, 0f, 0f) : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(RectInt)) + { + return isDBNull ? new RectInt(0, 0, 0, 0) : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(Bounds)) + { + return isDBNull ? new Bounds(new(0, 0), new(0, 0)) : ParseFromJson(parameterValue); + } + else if (parameterType == typeof(BoundsInt)) + { + return isDBNull ? new BoundsInt(new(0, 0), new(0, 0)) : ParseFromJson(parameterValue); + } + + return null; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs.meta new file mode 100644 index 0000000000..d3c5ab4c63 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: f647d1a4a3d6019488b6e5f638f04ca7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs new file mode 100644 index 0000000000..ccde6fa99d --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs @@ -0,0 +1,76 @@ +using UnityEditor; +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(ButtonFieldAttribute))] + public class ButtonFieldDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var buttonFieldAttribute = attribute as ButtonFieldAttribute; + + var path = property.propertyPath.Split('.'); + object ownerObject = null; + + if (path.Length == 1) + { + ownerObject = property.serializedObject.targetObject; + } + else + { + // Get the object that the property is a member of + var type = ReflectionUtility.GetNestedObjectType(property, out ownerObject); + + if (type == null) + return new HelpBox("Field must be a member of a class", HelpBoxMessageType.Error); + } + + var function = ReflectionUtility.FindFunction(buttonFieldAttribute.FunctionName, ownerObject); + + if (function == null) + return new HelpBox($"Could not find function {buttonFieldAttribute.FunctionName}. If this function is inherited make sure is marked at protected.", HelpBoxMessageType.Error); + + var functionParameters = function.GetParameters(); + var buttonLabel = string.IsNullOrWhiteSpace(buttonFieldAttribute.ButtonLabel) ? function.Name : buttonFieldAttribute.ButtonLabel; + + var root = new VisualElement(); + + if (functionParameters.Length == 0) + { + if (buttonFieldAttribute.IsRepetable) + { + var repeatButton = new RepeatButton(() => InvokeFunctionOnAllTargets(property.serializedObject.targetObjects, function.Name), buttonFieldAttribute.PressDelay, buttonFieldAttribute.RepetitionInterval) + { + text = buttonLabel, + tooltip = property.tooltip + }; + + repeatButton.style.height = buttonFieldAttribute.ButtonHeight; + repeatButton.AddToClassList(Button.ussClassName); + + root.Add(repeatButton); + } + else + { + var button = new Button(() => InvokeFunctionOnAllTargets(property.serializedObject.targetObjects, function.Name)) + { + text = buttonLabel, + tooltip = property.tooltip + }; + + button.style.height = buttonFieldAttribute.ButtonHeight; + + root.Add(button); + } + } + else + { + root.Add(new HelpBox("The function cannot have parameters", HelpBoxMessageType.Error)); + } + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs.meta new file mode 100644 index 0000000000..30259cc4fd --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 86f1ba3c924576045a515a222b393c9d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ButtonFieldDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs new file mode 100644 index 0000000000..9df73a81c8 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs @@ -0,0 +1,81 @@ +using System.Linq; +using UnityEditor; +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(InlineButtonAttribute))] + public class InlineButtonDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var root = new VisualElement() { style = { flexDirection = FlexDirection.Row } }; + + var propertyField = CreatePropertyField(property); + + propertyField.name = "CustomPropertyField"; // This is used to identify the our property field from the one automatically created by unity for the drawer + propertyField.style.flexGrow = 1f; + + root.Add(propertyField); + + root.RegisterCallback(OnGeometryChanged); + + void OnGeometryChanged(GeometryChangedEvent changeEvent) + { + root.UnregisterCallback(OnGeometryChanged); + + // Adding multiple InlineButton attributes on the same property causes a root and propertyField to be continously added to the hierarchy with each property drawer call + // So we move children recursively from the bottom of the hierarchy to the root and remove their original parents so there is only one root and property field no matter how many times this attribute is used + MoveChildren(root, propertyField.name); + MoveChildren(propertyField, propertyField.name); + + var propertyInfo = ReflectionUtility.GetValidMemberInfo(property.name, property); + var inlineButtonAttributes = propertyInfo.GetCustomAttributes(typeof(InlineButtonAttribute), true) as InlineButtonAttribute[]; + + foreach (var inlineButtonAttribute in inlineButtonAttributes) + root.Add(CreateInlineButton(inlineButtonAttribute, property)); + } + + return root; + } + + private VisualElement CreateInlineButton(InlineButtonAttribute inlineButtonAttribute, SerializedProperty property) + { + var methodInfo = ReflectionUtility.FindFunction(inlineButtonAttribute.FunctionName, property.serializedObject.targetObject); + string buttonLabel = inlineButtonAttribute.ButtonLabel == string.Empty ? inlineButtonAttribute.FunctionName : inlineButtonAttribute.ButtonLabel; + + if (methodInfo.GetParameters().Length > 0) + return new HelpBox("The function cannot have parameters", HelpBoxMessageType.Error); + + if (inlineButtonAttribute.IsRepetable) + { + var repeatButton = new RepeatButton(() => InvokeFunctionOnAllTargets(property.serializedObject.targetObjects, methodInfo.Name), inlineButtonAttribute.PressDelay, inlineButtonAttribute.RepetitionInterval) { text = buttonLabel }; + + repeatButton.style.width = inlineButtonAttribute.ButtonWidth; + repeatButton.AddToClassList(Button.ussClassName); + + return repeatButton; + } + else + { + var button = new Button(() => InvokeFunctionOnAllTargets(property.serializedObject.targetObjects, methodInfo.Name)) { text = buttonLabel }; + + button.style.width = inlineButtonAttribute.ButtonWidth; + + return button; + } + } + + private void MoveChildren(VisualElement element, string parentName) + { + if (element.parent.name == parentName) + { + foreach (var child in element.Children().ToList()) + element.parent.Add(child); + + element.RemoveFromHierarchy(); + } + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs.meta new file mode 100644 index 0000000000..bfde67368f --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e8b453b4c2f4a5e4e883b956ac06b125 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/InlineButtonDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs new file mode 100644 index 0000000000..538eff34ed --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs @@ -0,0 +1,229 @@ +using System; +using System.Linq; +using UnityEditor; +using UnityEditor.Overlays; +using UnityEngine.UIElements; +using UnityEditor.UIElements; +using System.Collections.Generic; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ +#if UNITY_6000_0_OR_NEWER + [Obsolete] +#endif + [CustomPropertyDrawer(typeof(SelectionButtonsAttribute))] + public class SelectionButtonsDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var selectionButtonsAttribute = attribute as SelectionButtonsAttribute; + + var errorBox = new HelpBox(); + var root = new VisualElement() + { + style = { + paddingTop = 3f, + paddingBottom = 3f + } + }; + + if (property.propertyType == SerializedPropertyType.Enum) + { + var enumType = fieldInfo.FieldType; + bool isFlagsEnum = enumType.IsDefined(typeof(FlagsAttribute), false); + + if (isFlagsEnum) + { + var flagValue = property.enumValueFlag; + + root.Add(DrawEnumFlagButtons(flagValue, property.enumDisplayNames, property, selectionButtonsAttribute, (value) => + { + property.enumValueFlag = value; + property.serializedObject.ApplyModifiedProperties(); + })); + } + else + { + var buttonsValue = property.enumValueIndex; + + root.Add(DrawButtons(buttonsValue, property.enumDisplayNames, property, selectionButtonsAttribute, (value) => + { + property.enumValueIndex = value; + property.serializedObject.ApplyModifiedProperties(); + })); + } + } + else if (property.propertyType != SerializedPropertyType.Enum && !string.IsNullOrEmpty(selectionButtonsAttribute.CollectionName)) + { + var memberInfo = ReflectionUtility.GetValidMemberInfo(selectionButtonsAttribute.CollectionName, property); + var displayNames = ConvertCollectionValuesToStrings(selectionButtonsAttribute.CollectionName, property, memberInfo, errorBox).ToArray(); + + var buttonsValue = Array.IndexOf(displayNames, GetPropertyValueAsString(property)); + + root.Add(DrawButtons(buttonsValue, displayNames, property, selectionButtonsAttribute, (value) => + { + if (value >= 0 && value < displayNames.Length) + SetPropertyValueFromString(displayNames[value], property); + })); + } + else + { + errorBox.text = "If the attached field is not an enum, a collection name must be provided"; + } + + DisplayErrorBox(root, errorBox); + + return root; + } + + private VisualElement DrawButtons(int buttonsValue, string[] valueLabels, SerializedProperty property, SelectionButtonsAttribute selectionButtonsAttribute, Action onValueChanged) + { + if (valueLabels == null || valueLabels.Length == 0) + return new HelpBox("The provided collection is empty", HelpBoxMessageType.Error); + + var toolbarToggles = new Dictionary(); + var toolbar = new OverlayToolbar(); + + toolbar.style.flexDirection = FlexDirection.Row; + + if (selectionButtonsAttribute.ShowLabel) + { + var label = new Label(preferredLabel); + + label.AddToClassList(BaseField.labelUssClassName); + + label.style.flexGrow = 1f; + label.style.paddingLeft = 4f; + label.style.minWidth = 100f; + label.tooltip = property.tooltip; + + toolbar.Add(label); + } + + for (int i = 0; i < valueLabels.Length; i++) + { + string label = valueLabels[i]; + var toggle = new ToolbarToggle + { + text = label, + value = buttonsValue == i, + style = { + flexGrow = 1f, + height = selectionButtonsAttribute.ButtonsHeight, + } + }; + + if (i == 0) + { + toggle.AddToClassList("unity-editor-toolbar__button-strip-element--left"); + } + else if (i == valueLabels.Length - 1) + { + toggle.AddToClassList("unity-editor-toolbar__button-strip-element--right"); + } + else + { + toggle.AddToClassList("unity-editor-toolbar__button-strip-element--middle"); + } + + // Set default value + if (i == 0 && buttonsValue == -1) + { + toggle.value = true; + buttonsValue = i; + onValueChanged.Invoke(buttonsValue); + } + + toolbar.Add(toggle); + toolbarToggles.Add(toggle, i); + } + + foreach (var toggle in toolbarToggles) + { + toggle.Key.RegisterValueChangedCallback((callback) => + { + buttonsValue = toggle.Value; + + foreach (var toolbarToggle in toolbarToggles.Where((source) => toggle.Key != source.Key)) + { + toolbarToggle.Key.SetValueWithoutNotify(false); + } + + if (buttonsValue == toggle.Value && !toggle.Key.value) + { + toggle.Key.SetValueWithoutNotify(true); + } + + onValueChanged.Invoke(buttonsValue); + }); + } + + return toolbar; + } + + private VisualElement DrawEnumFlagButtons(int flagValue, string[] valueLabels, SerializedProperty property, SelectionButtonsAttribute selectionButtonsAttribute, Action onValueChanged) + { + var toolbar = new OverlayToolbar(); + toolbar.style.flexDirection = FlexDirection.Row; + + if (selectionButtonsAttribute.ShowLabel) + { + var label = new Label(preferredLabel); + + label.style.flexGrow = 1f; + label.style.minWidth = 100f; + label.tooltip = property.tooltip; + + toolbar.Add(label); + } + + for (int i = 1; i < valueLabels.Length; i++) + { + int enumValue = 1 << i - 1; + bool isSelected = (flagValue & enumValue) != 0; + + var toggle = new ToolbarToggle() + { + text = valueLabels[i], + value = isSelected, + style = { + flexGrow = 1f, + height = selectionButtonsAttribute.ButtonsHeight + } + }; + + if (i == 1) + { + toggle.AddToClassList("unity-editor-toolbar__button-strip-element--left"); + } + else if (i == valueLabels.Length - 1) + { + toggle.AddToClassList("unity-editor-toolbar__button-strip-element--right"); + } + else + { + toggle.AddToClassList("unity-editor-toolbar__button-strip-element--middle"); + } + + toggle.RegisterValueChangedCallback((callback) => + { + if (callback.newValue) + { + flagValue |= enumValue; + } + else + { + flagValue &= ~enumValue; + } + + onValueChanged.Invoke(flagValue); + }); + + toolbar.Add(toggle); + } + + return toolbar; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs.meta new file mode 100644 index 0000000000..6c02b2b7a3 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 581d6089839f1f842aee0b8a9f2ef498 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/SelectionButtonsDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs new file mode 100644 index 0000000000..8758408db1 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs @@ -0,0 +1,161 @@ +using UnityEditor; +using UnityEngine.UIElements; + +#if UNITY_6000_0_OR_NEWER +using System; +using System.Linq; +using UnityEngine; +using System.Reflection; +using System.Collections; +using UnityEditor.UIElements; +using System.Collections.Generic; +using EditorAttributes.Editor.Utility; +#endif + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(ValueButtonsAttribute))] + public class ValueButtonsDrawer : PropertyDrawerBase + { +#if !UNITY_6000_0_OR_NEWER + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var root = new VisualElement(); + + root.Add(new HelpBox("The ValueButtons Attribute is only available in Unity 6 and above, use the SelectionButtons Attribute for the same functionality", HelpBoxMessageType.Warning)); + + return root; + } +#else + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var valueButtonsAttribute = attribute as ValueButtonsAttribute; + + var root = new VisualElement(); + var errorBox = new HelpBox(); + + var collectionInfo = ReflectionUtility.GetValidMemberInfo(valueButtonsAttribute.CollectionName, property); + + string[] propertyValues = ConvertCollectionValuesToStrings(valueButtonsAttribute.CollectionName, property, collectionInfo, errorBox).ToArray(); + string[] displayValues = GetDisplayValues(collectionInfo, valueButtonsAttribute, property, propertyValues.ToList()); + + if (!IsCollectionValid(displayValues)) + { + errorBox.text = "The provided collection is empty"; + DisplayErrorBox(root, errorBox); + + return root; + } + + int buttonsValueIndex = Array.IndexOf(propertyValues, GetPropertyValueAsString(property)); + + var valueButtons = DrawButtons(buttonsValueIndex, displayValues, valueButtonsAttribute, (value) => + { + if (valueButtonsAttribute.DisplayNames != null || IsDictionary(collectionInfo, property, out _)) + { + if (value >= 0 && value < propertyValues.Length) + SetPropertyValueFromString(propertyValues[value], property); + } + else + { + if (value >= 0 && value < propertyValues.Length) + SetPropertyValueFromString(propertyValues[value], property); + } + }); + + valueButtons.TrackPropertyValue(property, (trackedProperty) => + { + if (propertyValues.Contains(trackedProperty.boxedValue.ToString())) + { + int propertyValueIndex = Array.IndexOf(propertyValues, GetPropertyValueAsString(trackedProperty)); + bool[] selectionValues = new bool[propertyValues.Length]; + + selectionValues[propertyValueIndex] = true; + + valueButtons.SetValueWithoutNotify(ToggleButtonGroupState.CreateFromOptions(selectionValues)); + } + else + { + Debug.LogWarning($"The value {trackedProperty.boxedValue} set to the {trackedProperty.name} variable is not a value available in the button selection", trackedProperty.serializedObject.targetObject); + } + }); + + AddPropertyContextMenu(valueButtons, property); + + root.Add(valueButtons); + + DisplayErrorBox(root, errorBox); + + return root; + } + + private ToggleButtonGroup DrawButtons(int buttonsValue, string[] valueLabels, ValueButtonsAttribute selectionButtonsAttribute, Action onValueChanged) + { + var activeButtonList = new List(); + var buttonGroup = new ToggleButtonGroup(selectionButtonsAttribute.ShowLabel ? preferredLabel : string.Empty); + + foreach (string label in valueLabels) + { + var toggle = new Button + { + text = label, + style = { height = selectionButtonsAttribute.ButtonsHeight } + }; + + activeButtonList.Add(false); + buttonGroup.Add(toggle); + } + + activeButtonList[buttonsValue == -1 ? 0 : buttonsValue] = true; + + buttonGroup.SetValueWithoutNotify(ToggleButtonGroupState.CreateFromOptions(activeButtonList)); + buttonGroup.RegisterValueChangedCallback((value) => onValueChanged.Invoke(value.newValue.GetActiveOptions(ConvertBoolsToSpan(activeButtonList))[0])); + + return buttonGroup; + } + + private static Span ConvertBoolsToSpan(List boolList) + { + var intArray = new int[boolList.Count]; + + for (int i = 0; i < boolList.Count; i++) + intArray[i] = boolList[i] ? 1 : 0; + + return new Span(intArray); + } + + private string[] GetDisplayValues(MemberInfo collectionInfo, ValueButtonsAttribute valueButtonsAttribute, SerializedProperty serializedProperty, List propertyValues) + { + var displayStrings = new List(); + + if (valueButtonsAttribute.DisplayNames == null) + { + if (IsDictionary(collectionInfo, serializedProperty, out IDictionary dictionary)) + { + foreach (DictionaryEntry item in dictionary) + displayStrings.Add(item.Key == null ? "NULL" : item.Key.ToString()); + } + else + { + displayStrings = propertyValues; + } + } + else + { + displayStrings = valueButtonsAttribute.DisplayNames.ToList(); + } + + return displayStrings.ToArray(); + } + + private bool IsDictionary(MemberInfo collectionInfo, SerializedProperty serializedProperty, out IDictionary dictionary) + { + var collectionValue = ReflectionUtility.GetMemberInfoValue(collectionInfo, serializedProperty); + + dictionary = collectionValue as IDictionary; + + return collectionValue is IDictionary; + } +#endif + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs.meta new file mode 100644 index 0000000000..8d6f743dc1 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d1c3a6dcb0a06cd4aad7d63daa91604a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ButtonAttributeDrawers/ValueButtonsDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers.meta new file mode 100644 index 0000000000..9ae223eda5 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0134189b383584345b37b3dd229927fc +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs new file mode 100644 index 0000000000..a331468b5f --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs @@ -0,0 +1,119 @@ +using UnityEditor; +using UnityEngine.UIElements; +using System.Collections.Generic; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(ConditionalFieldAttribute))] + public class ConditionalFieldDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var conditionalAttribute = attribute as ConditionalFieldAttribute; + + var root = new VisualElement(); + var propertyField = CreatePropertyField(property); + + var errorBox = new HelpBox(); + + root.Add(propertyField); + + UpdateVisualElement(root, () => + { + var canDrawProperty = CanDrawProperty(conditionalAttribute, conditionalAttribute.BooleanNames, property, errorBox); + + switch (conditionalAttribute.ConditionResult) + { + case ConditionResult.ShowHide: + if (canDrawProperty) + { + AddElement(root, propertyField); + } + else + { + RemoveElement(root, propertyField); + } + break; + + case ConditionResult.EnableDisable: + propertyField.SetEnabled(canDrawProperty); + break; + } + + DisplayErrorBox(root, errorBox); + }); + + return root; + } + + private bool CanDrawProperty(ConditionalFieldAttribute attribute, string[] conditionNames, SerializedProperty property, HelpBox errorBox) + { + var booleanList = new List(); + + foreach (var conditionName in conditionNames) + { + var memberInfo = ReflectionUtility.GetValidMemberInfo(conditionName, property); + var serializedProperty = property.serializedObject.FindProperty(conditionName); + + if (memberInfo == null) + { + errorBox.text = $"The provided condition \"{conditionName}\" could not be found"; + continue; + } + + if (ReflectionUtility.GetMemberInfoType(memberInfo) == typeof(bool)) + { + var propertyValue = (bool)ReflectionUtility.GetMemberInfoValue(memberInfo, property); + + booleanList.Add(propertyValue); + } + else if (serializedProperty != null && serializedProperty.propertyType == SerializedPropertyType.Boolean) + { + var propertyValue = serializedProperty.boolValue; + + booleanList.Add(propertyValue); + } + else + { + errorBox.text = $"The provided condition \"{conditionName}\" is not a valid boolean"; + } + } + + for (int i = 0; i < booleanList.Count; i++) + { + if (!(attribute.NegatedValues == null || attribute.NegatedValues.Length == 0)) + { + if (attribute.NegatedValues[i]) + booleanList[i] = !booleanList[i]; + } + + switch (attribute.ConditionType) + { + case ConditionType.AND: + if (!booleanList[i]) return false; + continue; + + case ConditionType.OR: + if (booleanList[i]) return true; + continue; + + case ConditionType.NAND: + if (!booleanList[i]) return true; + continue; + + case ConditionType.NOR: + if (booleanList[i]) return false; + continue; + } + } + + return attribute.ConditionType switch + { + ConditionType.AND => true, + ConditionType.NOR => true, + _ => false, + }; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs.meta new file mode 100644 index 0000000000..3b5893a9c6 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: d062566b347cae942af514d0f6ab2e33 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ConditionalFieldDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs new file mode 100644 index 0000000000..5b45f1ca10 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs @@ -0,0 +1,32 @@ +using UnityEditor; +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(DisableFieldAttribute))] + public class DisableFieldDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var disableAttribute = attribute as DisableFieldAttribute; + var conditionalProperty = ReflectionUtility.GetValidMemberInfo(disableAttribute.ConditionName, property); + + var root = new VisualElement(); + var errorBox = new HelpBox(); + + var propertyField = CreatePropertyField(property); + + root.Add(propertyField); + + UpdateVisualElement(root, () => + { + propertyField.SetEnabled(!GetConditionValue(conditionalProperty, disableAttribute, property, errorBox)); + + DisplayErrorBox(root, errorBox); + }); + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs.meta new file mode 100644 index 0000000000..cc73299845 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 5458bc359dce3bb4eacee8ebf6ab74a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/DisableFieldDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs new file mode 100644 index 0000000000..227ee0a1f4 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs @@ -0,0 +1,32 @@ +using UnityEditor; +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(EnableFieldAttribute))] + public class EnableFieldDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var enableAttribute = attribute as EnableFieldAttribute; + var conditionalProperty = ReflectionUtility.GetValidMemberInfo(enableAttribute.ConditionName, property); + + var root = new VisualElement(); + var errorBox = new HelpBox(); + + var propertyField = CreatePropertyField(property); + + root.Add(propertyField); + + UpdateVisualElement(root, () => + { + propertyField.SetEnabled(GetConditionValue(conditionalProperty, enableAttribute, property, errorBox)); + + DisplayErrorBox(root, errorBox); + }); + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs.meta new file mode 100644 index 0000000000..cf7e97a479 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: abf530b593355344bb291599d633a329 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/EnableFieldDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs new file mode 100644 index 0000000000..5d09e28ab4 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs @@ -0,0 +1,39 @@ +using UnityEditor; +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(HideFieldAttribute))] + public class HideFieldDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var hideAttribute = attribute as HideFieldAttribute; + var conditionalProperty = ReflectionUtility.GetValidMemberInfo(hideAttribute.ConditionName, property); + + var root = new VisualElement(); + var errorBox = new HelpBox(); + + var propertyField = CreatePropertyField(property); + + root.Add(propertyField); + + UpdateVisualElement(root, () => + { + if (!GetConditionValue(conditionalProperty, hideAttribute, property, errorBox)) + { + AddElement(root, propertyField); + } + else + { + RemoveElement(root, propertyField); + } + + DisplayErrorBox(root, errorBox); + }); + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs.meta new file mode 100644 index 0000000000..568c6e0ff0 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9f0329d2b01fbd84eb75c495073b388e +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/HideFieldDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs new file mode 100644 index 0000000000..fe6fe2fb90 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs @@ -0,0 +1,52 @@ +using UnityEditor; +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(MessageBoxAttribute))] + public class MessageBoxDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var messageBoxAttribute = attribute as MessageBoxAttribute; + + var conditionalProperty = ReflectionUtility.GetValidMemberInfo(messageBoxAttribute.ConditionName, property); + + var root = new VisualElement(); + var messageBox = new HelpBox(string.Empty, (HelpBoxMessageType)messageBoxAttribute.MessageType); + var errorBox = new HelpBox(); + + var propertyField = CreatePropertyField(property); + + if (CanApplyGlobalColor) + { + messageBox.style.color = EditorExtension.GLOBAL_COLOR; + messageBox.style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f; + } + + root.Add(propertyField); + + UpdateVisualElement(propertyField, () => + { + if (GetConditionValue(conditionalProperty, messageBoxAttribute, property, errorBox)) + { + messageBox.text = GetDynamicString(messageBoxAttribute.Message, property, messageBoxAttribute, errorBox); + + AddElement(root, messageBox); + + if (messageBoxAttribute.DrawAbove) + messageBox.PlaceBehind(propertyField); + } + else + { + RemoveElement(root, messageBox); + } + + DisplayErrorBox(root, errorBox); + }); + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs.meta new file mode 100644 index 0000000000..f953c3c61d --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 524d7cbc09e4c004aa17e28deede4edd +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/MessageBoxDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs new file mode 100644 index 0000000000..d0aff1d06a --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs @@ -0,0 +1,39 @@ +using UnityEditor; +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(ShowFieldAttribute))] + public class ShowFieldDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var showAttribute = attribute as ShowFieldAttribute; + var conditionalProperty = ReflectionUtility.GetValidMemberInfo(showAttribute.ConditionName, property); + + var root = new VisualElement(); + var errorBox = new HelpBox(); + + var propertyField = CreatePropertyField(property); + + root.Add(propertyField); + + UpdateVisualElement(root, () => + { + if (GetConditionValue(conditionalProperty, showAttribute, property, errorBox)) + { + AddElement(root, propertyField); + } + else + { + RemoveElement(root, propertyField); + } + + DisplayErrorBox(root, errorBox); + }); + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs.meta new file mode 100644 index 0000000000..7e61dfeeb6 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 44436e22c103bc24d82c535844bfb12a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/ConditionalAttributeDrawers/ShowFieldDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers.meta new file mode 100644 index 0000000000..c2ef9036d0 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6c7faf9c714943c46b58573da3760e4f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs new file mode 100644 index 0000000000..c527fefd4c --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs @@ -0,0 +1,79 @@ +using UnityEngine; +using UnityEditor; +using UnityEngine.UIElements; +using System.Threading.Tasks; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(AssetPreviewAttribute))] + public class AssetPreviewDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var assetPreviewAttribute = attribute as AssetPreviewAttribute; + var root = new VisualElement(); + + var propertyField = CreatePropertyField(property); + + root.Add(propertyField); + + if (property.propertyType == SerializedPropertyType.ObjectReference) + { + var image = new Image(); + + root.Add(image); + + // Register the callback later else arrays have a stroke + ExecuteLater(root, () => + { + GetAssetPreview(property, assetPreviewAttribute, root, image); + + propertyField.RegisterValueChangeCallback((changeEvent) => GetAssetPreview(property, assetPreviewAttribute, root, image)); + }); + } + else + { + root.Add(new HelpBox("The attached field is not a valid asset", HelpBoxMessageType.Error)); + } + + return root; + } + + private async void GetAssetPreview(SerializedProperty property, AssetPreviewAttribute assetPreviewAttribute, VisualElement root, Image image) + { + if (property.objectReferenceValue == null) + { + RemoveElement(root, image); + return; + } + + Texture2D texture = null; + + // When reassigning the object reference and the preview is not cached yet the texture will return null the first time, so we request it a second time after the first call cached it + for (int i = 0; i < 2; i++) + { + if (texture != null) + break; + + texture = AssetPreview.GetAssetPreview(property.objectReferenceValue); + + await Task.Delay(EditorAttributesSettings.instance.assetPreviewLoadTime); // Give time for the asset preview to load since is doing it asynchronously under the hood + } + + if (texture == null) + { + RemoveElement(root, image); + return; + } + + var imageWidth = assetPreviewAttribute.PreviewWidth == 0f ? GetTextureSize(texture).x : assetPreviewAttribute.PreviewWidth; + var imageHeight = assetPreviewAttribute.PreviewHeight == 0f ? GetTextureSize(texture).y : assetPreviewAttribute.PreviewHeight; + + image.image = texture; + image.style.width = imageWidth; + image.style.height = imageHeight; + + root.Add(image); + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs.meta new file mode 100644 index 0000000000..8280367c27 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 9898033101c5a7c479d0090411577e47 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/AssetPreviewDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs new file mode 100644 index 0000000000..91a94a35c5 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs @@ -0,0 +1,36 @@ +using UnityEditor; +using UnityEngine.UIElements; +//using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ +#pragma warning disable CS0618 + [CustomPropertyDrawer(typeof(ColorFieldAttribute))] + public class ColorFieldDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + //var colorFieldAttribute = attribute as ColorFieldAttribute; + + var root = new VisualElement(); + var propertyField = CreatePropertyField(property); + + /* + var errorBox = new HelpBox(); + + ColorUtility.ApplyColor(root, colorFieldAttribute, errorBox); + + DisplayErrorBox(root, errorBox); + */ + + root.Add(propertyField); + + // Because UI toolkit makes tinting elements very difficult, it's not possible to properly tint properties with ColorField, this attribute will stay deprecated until Unity adds an easyer way of tinting elements + // Which I estimate it will be in about 234287346598175492164 years + // If you think this attribute would work well enough for you, feel free to uncomment all the code + root.Add(new HelpBox("This attribute has been deprecated, use GUIColor instead. See ColorFieldDrawer.cs for more details", HelpBoxMessageType.Warning)); + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs.meta new file mode 100644 index 0000000000..0fa9a9bd27 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: e8c4eb6d4007b9d47942289ee3d43765 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/ColorFieldDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs new file mode 100644 index 0000000000..f43921f6f6 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs @@ -0,0 +1,17 @@ +using UnityEngine.UIElements; +using EditorAttributes.Editor.Utility; + +namespace EditorAttributes.Editor +{ + public class GUIColorDrawer + { + public static void ColorField(VisualElement root, IColorAttribute colorAttribute) + { + var errorBox = new HelpBox(); + + EditorExtension.GLOBAL_COLOR = ColorUtils.GetColorFromAttribute(colorAttribute, errorBox); + ColorUtils.ApplyColor(root, colorAttribute, errorBox); + PropertyDrawerBase.DisplayErrorBox(root, errorBox); + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs.meta new file mode 100644 index 0000000000..d1931b5315 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: 6baeb086a87b9324cba2f368179b7d96 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/GUIColorDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs new file mode 100644 index 0000000000..a90913f849 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs @@ -0,0 +1,36 @@ +using UnityEditor; +using UnityEngine.UIElements; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(HelpBoxAttribute))] + public class HelpBoxDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var helpBoxAttribute = attribute as HelpBoxAttribute; + var propertyField = CreatePropertyField(property); + + var root = new VisualElement(); + var errorBox = new HelpBox(); + var helpBox = new HelpBox(string.Empty, (HelpBoxMessageType)helpBoxAttribute.MessageType); + + if (EditorExtension.GLOBAL_COLOR != EditorExtension.DEFAULT_GLOBAL_COLOR) + helpBox.style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f; + + root.Add(propertyField); + root.Add(helpBox); + + if (helpBoxAttribute.DrawAbove) + helpBox.PlaceBehind(propertyField); + + UpdateVisualElement(helpBox, () => + { + helpBox.text = GetDynamicString(helpBoxAttribute.Message, property, helpBoxAttribute, errorBox); + DisplayErrorBox(root, errorBox); + }); + + return root; + } + } +} diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs.meta b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs.meta new file mode 100644 index 0000000000..c619927e0d --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs.meta @@ -0,0 +1,18 @@ +fileFormatVersion: 2 +guid: b4c0ea4a3cf31754dbc5df0f427bfb8a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: +AssetOrigin: + serializedVersion: 1 + productId: 269285 + packageName: EditorAttributes + packageVersion: 2.9.2 + assetPath: Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HelpBoxDrawer.cs + uploadId: 806636 diff --git a/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HideLabelDrawer.cs b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HideLabelDrawer.cs new file mode 100644 index 0000000000..be24a478f0 --- /dev/null +++ b/Assets/EditorAttributes/Editor/Scripts/Drawers/DecorativeAttributeDrawers/HideLabelDrawer.cs @@ -0,0 +1,24 @@ +using UnityEditor; +using UnityEngine.UIElements; + +namespace EditorAttributes.Editor +{ + [CustomPropertyDrawer(typeof(HideLabelAttribute))] + public class HideLabelDrawer : PropertyDrawerBase + { + public override VisualElement CreatePropertyGUI(SerializedProperty property) + { + var propertyField = CreatePropertyField(property); + + ExecuteLater(propertyField, () => + { + var label = propertyField.Q