Merge branch 'develop' into update-in-game
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: df9253c4d2102ee46b74a2aabe7ebc1c
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,9 @@
|
||||
// taskID,bezierID,speed,angle,dir,model file path
|
||||
|
||||
"32220,-1001,30,30.0,1,Models\NPCs\³èÎï\Æï³è\·ï»Ë\·ï»Ë.ecm"
|
||||
"32221,-1003,30,30.0,1,Models\NPCs\³èÎï\Æï³è\·ï»Ë\·ï»Ë.ecm"
|
||||
"32222,-1002,30,30.0,1,Models\NPCs\³èÎï\Æï³è\·ï»Ë\·ï»Ë.ecm"
|
||||
"32223,-1004,30,30.0,1,Models\NPCs\³èÎï\Æï³è\·ï»Ë\·ï»Ë.ecm"
|
||||
"32224,-1005,30,30.0,1,Models\NPCs\³èÎï\Æï³è\·ï»Ë\·ï»Ë.ecm"
|
||||
"32428,-1006,30,30.0,1,Models\NPCs\³èÎï\Æï³è\·ï»Ë\·ï»Ë.ecm"
|
||||
"32225,-1007,30,30.0,1,Models\NPCs\³èÎï\Æï³è\·ï»Ë\·ï»Ë.ecm"
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7adf1899d4b87594b88254868366424a
|
||||
TextScriptImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3217576b92552584cbfea13094acd727
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -85,6 +85,11 @@ MonoBehaviour:
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: df9253c4d2102ee46b74a2aabe7ebc1c
|
||||
m_Address: Assets/Addressable/coord_data.txt
|
||||
m_ReadOnly: 0
|
||||
m_SerializedLabels: []
|
||||
FlaggedDuringContentUpdateRestriction: 0
|
||||
- m_GUID: ef28dc36280e16643b8d27fd5839ffa0
|
||||
m_Address: Assets/Addressable/ingame.txt
|
||||
m_ReadOnly: 0
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2927ffcd6e2c3a04daf69cb6080a3875
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3477698a63f41f149a2c69048426971f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
@@ -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.
|
||||
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8bb6aaeb8c583394db1d20a84ffebf74
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f4687e18dc1a3024aaaa4567bbabb62d
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39991b2a9623a10439dd199798549d6c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 66d670bcd98fdb742b29addf8c9fd7fc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+419
@@ -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<string, bool> foldouts = new();
|
||||
public Dictionary<string, object[]> parameterValues = new();
|
||||
}
|
||||
|
||||
internal const string PARAMS_DATA_LOCATION = "ProjectSettings/EditorAttributes";
|
||||
|
||||
internal static VisualElement DrawButton(MethodInfo function, ButtonAttribute buttonAttribute, Dictionary<MethodInfo, bool> foldouts, Dictionary<MethodInfo, object[]> 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<TooltipAttribute>();
|
||||
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<MethodInfo, bool> foldouts, Dictionary<MethodInfo, object[]> parameterValues)
|
||||
{
|
||||
var data = new FunctionParamData();
|
||||
var keyToMethod = new Dictionary<string, MethodInfo>();
|
||||
|
||||
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<MethodInfo, bool> foldouts, ref Dictionary<MethodInfo, object[]> 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<FunctionParamData>(jsonData);
|
||||
var keyToMethod = new Dictionary<string, MethodInfo>();
|
||||
|
||||
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($"<b>{fileCount}</b> 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<ButtonAttribute>();
|
||||
|
||||
if (buttonAttribute != null)
|
||||
{
|
||||
serializeParameters = buttonAttribute.SerializeParameters;
|
||||
return true;
|
||||
}
|
||||
|
||||
serializeParameters = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static T ParseFromJson<T>(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<T>(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<Vector2>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(Vector2Int))
|
||||
{
|
||||
return isDBNull ? Vector2Int.zero : ParseFromJson<Vector2Int>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(Vector3))
|
||||
{
|
||||
return isDBNull ? Vector3.zero : ParseFromJson<Vector3>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(Vector3Int))
|
||||
{
|
||||
return isDBNull ? Vector3Int.zero : ParseFromJson<Vector3Int>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(Vector4))
|
||||
{
|
||||
return isDBNull ? Vector4.zero : ParseFromJson<Vector4>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(Color))
|
||||
{
|
||||
return isDBNull ? Color.black : ParseFromJson<Color>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(Gradient))
|
||||
{
|
||||
return isDBNull ? new Gradient() : ParseFromJson<Gradient>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(AnimationCurve))
|
||||
{
|
||||
return isDBNull ? AnimationCurve.Linear(0f, 0f, 1f, 1f) : ParseFromJson<AnimationCurve>(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<Rect>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(RectInt))
|
||||
{
|
||||
return isDBNull ? new RectInt(0, 0, 0, 0) : ParseFromJson<RectInt>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(Bounds))
|
||||
{
|
||||
return isDBNull ? new Bounds(new(0, 0), new(0, 0)) : ParseFromJson<Bounds>(parameterValue);
|
||||
}
|
||||
else if (parameterType == typeof(BoundsInt))
|
||||
{
|
||||
return isDBNull ? new BoundsInt(new(0, 0), new(0, 0)) : ParseFromJson<BoundsInt>(parameterValue);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+76
@@ -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 <b>{buttonFieldAttribute.FunctionName}</b>. 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+81
@@ -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<GeometryChangedEvent>(OnGeometryChanged);
|
||||
|
||||
void OnGeometryChanged(GeometryChangedEvent changeEvent)
|
||||
{
|
||||
root.UnregisterCallback<GeometryChangedEvent>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+229
@@ -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<int> onValueChanged)
|
||||
{
|
||||
if (valueLabels == null || valueLabels.Length == 0)
|
||||
return new HelpBox("The provided collection is empty", HelpBoxMessageType.Error);
|
||||
|
||||
var toolbarToggles = new Dictionary<ToolbarToggle, int>();
|
||||
var toolbar = new OverlayToolbar();
|
||||
|
||||
toolbar.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
if (selectionButtonsAttribute.ShowLabel)
|
||||
{
|
||||
var label = new Label(preferredLabel);
|
||||
|
||||
label.AddToClassList(BaseField<Void>.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<int> 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+161
@@ -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 <b>ValueButtons Attribute</b> is only available in <b>Unity 6 and above</b>, use the <b>SelectionButtons Attribute</b> 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 <b>{trackedProperty.boxedValue}</b> set to the <b>{trackedProperty.name}</b> 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<int> onValueChanged)
|
||||
{
|
||||
var activeButtonList = new List<bool>();
|
||||
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<int> ConvertBoolsToSpan(List<bool> boolList)
|
||||
{
|
||||
var intArray = new int[boolList.Count];
|
||||
|
||||
for (int i = 0; i < boolList.Count; i++)
|
||||
intArray[i] = boolList[i] ? 1 : 0;
|
||||
|
||||
return new Span<int>(intArray);
|
||||
}
|
||||
|
||||
private string[] GetDisplayValues(MemberInfo collectionInfo, ValueButtonsAttribute valueButtonsAttribute, SerializedProperty serializedProperty, List<string> propertyValues)
|
||||
{
|
||||
var displayStrings = new List<string>();
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0134189b383584345b37b3dd229927fc
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+119
@@ -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<bool>();
|
||||
|
||||
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,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+32
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+32
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+39
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+52
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+39
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c7faf9c714943c46b58573da3760e4f
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+79
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+36
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+17
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+36
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -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
|
||||
+24
@@ -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<Label>(className: "unity-label");
|
||||
|
||||
if (label != null)
|
||||
label.style.display = DisplayStyle.None;
|
||||
});
|
||||
|
||||
return propertyField;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a5956c5defb72f44284e751f54e6fbbc
|
||||
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/HideLabelDrawer.cs
|
||||
uploadId: 806636
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ImageAttribute))]
|
||||
public class ImageDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var imageAttribute = attribute as ImageAttribute;
|
||||
var root = new VisualElement();
|
||||
|
||||
var image = new Image();
|
||||
var errorBox = new HelpBox();
|
||||
|
||||
root.Add(image);
|
||||
root.Add(CreatePropertyField(property));
|
||||
|
||||
UpdateVisualElement(image, () =>
|
||||
{
|
||||
var imagePath = GetDynamicString(imageAttribute.ImagePath, property, imageAttribute, errorBox);
|
||||
var texture = AssetDatabase.LoadAssetAtPath<Texture2D>(imagePath);
|
||||
|
||||
if (texture == null)
|
||||
{
|
||||
errorBox.text = "The image asset could not be found make sure you inputted the correct filepath to a image asset";
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveElement(root, errorBox);
|
||||
|
||||
var imageWidth = imageAttribute.ImageWidth == 0f ? GetTextureSize(texture).x : imageAttribute.ImageWidth;
|
||||
var imageHeight = imageAttribute.ImageHeight == 0f ? GetTextureSize(texture).y : imageAttribute.ImageHeight;
|
||||
|
||||
image.image = texture;
|
||||
image.style.width = imageWidth;
|
||||
image.style.height = imageHeight;
|
||||
|
||||
DisplayErrorBox(root, errorBox);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 48fc15695614a2740a763d86aee3bccb
|
||||
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/ImageDrawer.cs
|
||||
uploadId: 806636
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(IndentPropertyAttribute))]
|
||||
public class IndentPropertyDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var indentPropertyAttribute = attribute as IndentPropertyAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var propertyField = CreatePropertyField(property);
|
||||
|
||||
propertyField.style.marginLeft = indentPropertyAttribute.IndentLevel;
|
||||
|
||||
root.Add(propertyField);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d54058b313e6fec4fbb2e942d925af80
|
||||
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/IndentPropertyDrawer.cs
|
||||
uploadId: 806636
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using EditorAttributes.Editor.Utility;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(LineAttribute))]
|
||||
public class LineDrawer : DecoratorDrawer
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI()
|
||||
{
|
||||
var lineAttribute = attribute as LineAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var line = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
|
||||
line.style.marginBottom = 5f;
|
||||
line.style.marginTop = 5f;
|
||||
line.style.height = lineAttribute.LineThickness;
|
||||
line.style.backgroundColor = ColorUtils.GetColorFromAttribute(lineAttribute, lineAttribute.A, errorBox);
|
||||
|
||||
root.Add(line);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 243c4cf6f076627488014f74ec45b952
|
||||
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/LineDrawer.cs
|
||||
uploadId: 806636
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(PrefixAttribute))]
|
||||
public class PrefixDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var prefixAttribute = attribute as PrefixAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
var propertyField = CreatePropertyField(property);
|
||||
|
||||
var prefixLabel = new Label()
|
||||
{
|
||||
style = {
|
||||
fontSize = 12,
|
||||
maxWidth = 200f,
|
||||
marginRight = prefixAttribute.Offset,
|
||||
unityTextAlign = TextAnchor.MiddleRight,
|
||||
alignSelf = Align.FlexEnd,
|
||||
overflow = Overflow.Hidden
|
||||
}
|
||||
};
|
||||
|
||||
prefixLabel.style.color = CanApplyGlobalColor ? EditorExtension.GLOBAL_COLOR : Color.gray;
|
||||
root.Add(propertyField);
|
||||
|
||||
ExecuteLater(root, () =>
|
||||
{
|
||||
var field = propertyField.Q<Label>();
|
||||
field.Add(prefixLabel);
|
||||
});
|
||||
|
||||
UpdateVisualElement(prefixLabel, () =>
|
||||
{
|
||||
prefixLabel.text = GetDynamicString(prefixAttribute.Prefix, property, prefixAttribute, errorBox);
|
||||
DisplayErrorBox(root, errorBox);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ac1d6fec74592d42a48a51e577de5ba
|
||||
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/PrefixDrawer.cs
|
||||
uploadId: 806636
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(PropertyWidthAttribute))]
|
||||
public class PropertyWidthDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var propertyWidthAttribute = attribute as PropertyWidthAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var propertyField = CreatePropertyField(property);
|
||||
|
||||
root.Add(propertyField);
|
||||
|
||||
ExecuteLater(propertyField, () =>
|
||||
{
|
||||
var fieldLabel = propertyField.Q<Label>();
|
||||
|
||||
if (fieldLabel != null)
|
||||
fieldLabel.style.marginRight = propertyWidthAttribute.WidthOffset;
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 107ec70bc1e734547ba6daf54daaec7b
|
||||
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/PropertyWidthDrawer.cs
|
||||
uploadId: 806636
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
using UnityEditor;
|
||||
using System.Text;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(RenameAttribute))]
|
||||
public class RenameDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var renameAttribute = attribute as RenameAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
var propertyField = new PropertyField(property, GetNewName(renameAttribute, property, errorBox));
|
||||
|
||||
root.Add(propertyField);
|
||||
|
||||
if (renameAttribute.StringInputMode == StringInputMode.Dynamic)
|
||||
{
|
||||
Label propertyLabel = null;
|
||||
|
||||
ExecuteLater(propertyField, () => propertyLabel = propertyField.Q<Label>());
|
||||
|
||||
UpdateVisualElement(propertyField, () =>
|
||||
{
|
||||
if (propertyLabel != null)
|
||||
propertyLabel.text = GetNewName(renameAttribute, property, errorBox);
|
||||
});
|
||||
|
||||
DisplayErrorBox(root, errorBox);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
internal static string GetNewName(RenameAttribute renameAttribute, SerializedProperty property, HelpBox errorBox)
|
||||
{
|
||||
var newName = GetDynamicString(renameAttribute.Name, property, renameAttribute, errorBox);
|
||||
|
||||
switch (renameAttribute.CaseType)
|
||||
{
|
||||
case CaseType.None:
|
||||
return newName;
|
||||
|
||||
case CaseType.Unity:
|
||||
newName = ObjectNames.NicifyVariableName(newName);
|
||||
break;
|
||||
|
||||
case CaseType.Pascal:
|
||||
var pascalName = char.ToUpper(newName[0]) + newName[1..];
|
||||
|
||||
FormatString(ref pascalName);
|
||||
|
||||
newName = pascalName;
|
||||
break;
|
||||
|
||||
case CaseType.Camel:
|
||||
var camelName = char.ToLower(newName[0]) + newName[1..];
|
||||
|
||||
FormatString(ref camelName);
|
||||
|
||||
newName = camelName;
|
||||
break;
|
||||
|
||||
case CaseType.Snake:
|
||||
newName = newName.Replace(" ", "_");
|
||||
break;
|
||||
|
||||
case CaseType.Kebab:
|
||||
newName = newName.Replace(" ", "-");
|
||||
break;
|
||||
|
||||
case CaseType.Upper:
|
||||
newName = newName.ToUpper();
|
||||
break;
|
||||
|
||||
case CaseType.Lower:
|
||||
newName = newName.ToLower();
|
||||
break;
|
||||
}
|
||||
|
||||
return newName;
|
||||
}
|
||||
|
||||
private static void FormatString(ref string stringToFormat)
|
||||
{
|
||||
while (stringToFormat.Contains(" "))
|
||||
{
|
||||
var spaceIndex = stringToFormat.IndexOf(" ");
|
||||
var charAfterSpace = stringToFormat[spaceIndex + 1];
|
||||
var stringBuilder = new StringBuilder(stringToFormat);
|
||||
|
||||
stringBuilder.Replace(charAfterSpace, char.ToUpper(charAfterSpace), spaceIndex + 1, 1);
|
||||
|
||||
stringToFormat = stringBuilder.ToString();
|
||||
stringToFormat = stringToFormat.Remove(spaceIndex, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3f0655f057eada94faf09137890abe74
|
||||
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/RenameDrawer.cs
|
||||
uploadId: 806636
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(SuffixAttribute))]
|
||||
public class SuffixDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var suffixAttribute = attribute as SuffixAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
var propertyField = CreatePropertyField(property);
|
||||
|
||||
var suffixLabel = new Label()
|
||||
{
|
||||
style = {
|
||||
fontSize = 12,
|
||||
maxWidth = 200f,
|
||||
marginLeft = suffixAttribute.Offset,
|
||||
unityTextAlign = TextAnchor.MiddleRight,
|
||||
alignSelf = Align.Center,
|
||||
overflow = Overflow.Hidden
|
||||
}
|
||||
};
|
||||
|
||||
root.style.flexDirection = FlexDirection.Row;
|
||||
propertyField.style.flexGrow = 1f;
|
||||
suffixLabel.style.color = suffixLabel.style.color = CanApplyGlobalColor ? EditorExtension.GLOBAL_COLOR : Color.gray;
|
||||
|
||||
root.Add(propertyField);
|
||||
root.Add(suffixLabel);
|
||||
|
||||
UpdateVisualElement(suffixLabel, () =>
|
||||
{
|
||||
suffixLabel.text = GetDynamicString(suffixAttribute.Suffix, property, suffixAttribute, errorBox);
|
||||
DisplayErrorBox(root, errorBox);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2890c38b9084cc34aa30f377a4da0f5b
|
||||
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/SuffixDrawer.cs
|
||||
uploadId: 806636
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
using EditorAttributes.Editor.Utility;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TitleAttribute))]
|
||||
public class TitleDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var titleAttribute = attribute as TitleAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
var title = new Label();
|
||||
|
||||
title.style.fontSize = titleAttribute.TitleSize;
|
||||
title.style.unityTextAlign = titleAttribute.Alignment;
|
||||
title.style.marginBottom = titleAttribute.TitleSpace;
|
||||
|
||||
if (titleAttribute.DrawLine)
|
||||
{
|
||||
var colorWithAlpha = ColorUtils.GetPropertyColor(property, 0.5f);
|
||||
var color = ColorUtils.GetPropertyColor(property);
|
||||
|
||||
if (color.HasValue)
|
||||
title.style.color = color.Value;
|
||||
|
||||
title.style.borderBottomColor = colorWithAlpha ?? Color.gray;
|
||||
title.style.borderBottomWidth = titleAttribute.LineThickness;
|
||||
}
|
||||
|
||||
root.Add(title);
|
||||
root.Add(CreatePropertyField(property));
|
||||
|
||||
UpdateVisualElement(title, () =>
|
||||
{
|
||||
title.text = GetDynamicString(titleAttribute.Title, property, titleAttribute, errorBox);
|
||||
DisplayErrorBox(root, errorBox);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad9b9fbfd88a2544e9dfad3d20685d4d
|
||||
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/TitleDrawer.cs
|
||||
uploadId: 806636
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1bc2968beb8e38489610e11106ed839
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
using EditorAttributes.Editor.Utility;
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.Animations;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(AnimatorParamDropdownAttribute))]
|
||||
public class AnimatorParamDropdownDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var animatorParamAttribute = attribute as AnimatorParamDropdownAttribute;
|
||||
|
||||
var root = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
var animatorParameters = GetAnimatorParams(animatorParamAttribute, property, errorBox);
|
||||
|
||||
var dropdownField = IsCollectionValid(animatorParameters) ? new DropdownField(property.displayName, animatorParameters, GetDropdownDefaultValue(animatorParameters, property))
|
||||
: new DropdownField(property.displayName, new List<string>() { "NULL" }, 0);
|
||||
|
||||
dropdownField.tooltip = property.tooltip;
|
||||
dropdownField.AddToClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
|
||||
AddPropertyContextMenu(dropdownField, property);
|
||||
|
||||
dropdownField.RegisterValueChangedCallback(callback =>
|
||||
{
|
||||
if (!property.hasMultipleDifferentValues)
|
||||
{
|
||||
property.stringValue = callback.newValue;
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
});
|
||||
|
||||
dropdownField.TrackPropertyValue(property, (trackedProperty) =>
|
||||
{
|
||||
if (dropdownField.choices.Contains(trackedProperty.stringValue))
|
||||
{
|
||||
dropdownField.SetValueWithoutNotify(trackedProperty.stringValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"The value <b>{trackedProperty.stringValue}</b> set to the <b>{trackedProperty.name}</b> variable is not a valid animator parameter.", trackedProperty.serializedObject.targetObject);
|
||||
}
|
||||
});
|
||||
|
||||
if (dropdownField.value != "NULL")
|
||||
{
|
||||
dropdownField.showMixedValue = property.hasMultipleDifferentValues;
|
||||
|
||||
if (!property.hasMultipleDifferentValues)
|
||||
{
|
||||
property.stringValue = dropdownField.value;
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
|
||||
root.Add(dropdownField);
|
||||
|
||||
ExecuteLater(dropdownField, () => dropdownField.Q(className: DropdownField.inputUssClassName).style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f);
|
||||
|
||||
UpdateVisualElement(dropdownField, () =>
|
||||
{
|
||||
var animatorParams = GetAnimatorParams(animatorParamAttribute, property, errorBox);
|
||||
|
||||
if (IsCollectionValid(animatorParams))
|
||||
dropdownField.choices = animatorParams;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
errorBox.text = "The AnimatorParamDropdown attribute can only be attached to string fields";
|
||||
}
|
||||
|
||||
DisplayErrorBox(root, errorBox);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private List<string> GetAnimatorParams(AnimatorParamDropdownAttribute animatorParamAttribute, SerializedProperty property, HelpBox errorBox)
|
||||
{
|
||||
var paramList = new List<string>();
|
||||
|
||||
var memberInfo = ReflectionUtility.GetValidMemberInfo(animatorParamAttribute.AnimatorFieldName, property);
|
||||
var memberInfoType = ReflectionUtility.GetMemberInfoType(memberInfo);
|
||||
|
||||
if (memberInfoType == typeof(Animator))
|
||||
{
|
||||
var memberInfoValue = ReflectionUtility.GetMemberInfoValue(memberInfo, property) as Animator;
|
||||
|
||||
if (memberInfoValue != null && memberInfoValue.runtimeAnimatorController != null)
|
||||
{
|
||||
// Hack for having the animator refesh its parameters when editing them in edit mode otherwise the parameters array will be empty
|
||||
var editorController = AssetDatabase.LoadAssetAtPath<AnimatorController>(AssetDatabase.GetAssetPath(memberInfoValue.runtimeAnimatorController));
|
||||
|
||||
foreach (var parameter in editorController.parameters)
|
||||
paramList.Add(parameter.name);
|
||||
}
|
||||
else
|
||||
{
|
||||
errorBox.text = $"The Animator or Animator Controller is null, make sure they are assigned";
|
||||
return null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
errorBox.text = $"The provided field \"{animatorParamAttribute.AnimatorFieldName}\" is not of type Animator";
|
||||
return null;
|
||||
}
|
||||
|
||||
return paramList;
|
||||
}
|
||||
|
||||
protected override void PasteValue(VisualElement element, SerializedProperty property, string clipboardValue)
|
||||
{
|
||||
var dropdown = element as DropdownField;
|
||||
|
||||
if (dropdown.choices.Contains(clipboardValue))
|
||||
{
|
||||
base.PasteValue(element, property, clipboardValue);
|
||||
dropdown.SetValueWithoutNotify(clipboardValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Could not paste value \"{clipboardValue}\" since is not availiable as an option in the dropdown");
|
||||
}
|
||||
}
|
||||
|
||||
private string GetDropdownDefaultValue(List<string> collectionValues, SerializedProperty property)
|
||||
{
|
||||
var propertyStringValue = property.stringValue;
|
||||
|
||||
return collectionValues.Contains(propertyStringValue) ? propertyStringValue : collectionValues[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e8a56d90de6ddf44c951aecf49c3c1ff
|
||||
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/DropdownAttributeDrawers/AnimatorParamDropdownDrawer.cs
|
||||
uploadId: 806636
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
using System.Collections;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using System.Collections.Generic;
|
||||
using EditorAttributes.Editor.Utility;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(DropdownAttribute))]
|
||||
public class DropdownDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var dropdownAttribute = attribute as DropdownAttribute;
|
||||
var root = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
|
||||
var collectionInfo = ReflectionUtility.GetValidMemberInfo(dropdownAttribute.CollectionName, property);
|
||||
var propertyValues = ConvertCollectionValuesToStrings(dropdownAttribute.CollectionName, property, collectionInfo, errorBox);
|
||||
|
||||
var displayValues = GetDisplayValues(collectionInfo, dropdownAttribute, property, propertyValues);
|
||||
|
||||
List<string> nullList = new() { "NULL" };
|
||||
|
||||
DropdownField dropdownField = IsCollectionValid(displayValues) ? new(property.displayName, displayValues, GetDropdownDefaultValueIndex(propertyValues, property)) : new(property.displayName, nullList, 0);
|
||||
|
||||
dropdownField.tooltip = property.tooltip;
|
||||
dropdownField.AddToClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
|
||||
AddPropertyContextMenu(dropdownField, property);
|
||||
|
||||
dropdownField.RegisterValueChangedCallback((callback) =>
|
||||
{
|
||||
if (!property.hasMultipleDifferentValues)
|
||||
SetPropertyValue(property, callback.newValue, dropdownAttribute, propertyValues, dropdownField, collectionInfo);
|
||||
});
|
||||
|
||||
dropdownField.TrackPropertyValue(property, (trackedProperty) =>
|
||||
{
|
||||
if (propertyValues.Contains(trackedProperty.boxedValue.ToString()))
|
||||
{
|
||||
dropdownField.SetValueWithoutNotify(displayValues[propertyValues.IndexOf(trackedProperty.boxedValue.ToString())]);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"The value <b>{trackedProperty.boxedValue}</b> set to the <b>{trackedProperty.name}</b> variable is not a value available in the dropdown", trackedProperty.serializedObject.targetObject);
|
||||
}
|
||||
});
|
||||
|
||||
if (dropdownField.value != "NULL" && !HasMismatchedDisplayCollectionCounts(dropdownAttribute, propertyValues, displayValues))
|
||||
{
|
||||
dropdownField.showMixedValue = property.hasMultipleDifferentValues;
|
||||
|
||||
if (!property.hasMultipleDifferentValues)
|
||||
SetPropertyValue(property, dropdownField.value, dropdownAttribute, propertyValues, dropdownField, collectionInfo);
|
||||
}
|
||||
|
||||
root.Add(dropdownField);
|
||||
|
||||
ExecuteLater(dropdownField, () => dropdownField.Q(className: DropdownField.inputUssClassName).style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f);
|
||||
|
||||
UpdateVisualElement(dropdownField, () =>
|
||||
{
|
||||
var currentPropertyValues = ConvertCollectionValuesToStrings(dropdownAttribute.CollectionName, property, collectionInfo, errorBox);
|
||||
var currentDisplayValues = GetDisplayValues(collectionInfo, dropdownAttribute, property, currentPropertyValues);
|
||||
|
||||
if (IsCollectionValid(currentPropertyValues))
|
||||
{
|
||||
errorBox.text = string.Empty;
|
||||
dropdownField.choices = currentDisplayValues;
|
||||
|
||||
propertyValues = currentPropertyValues;
|
||||
}
|
||||
else
|
||||
{
|
||||
dropdownField.choices = nullList;
|
||||
propertyValues = nullList;
|
||||
displayValues = nullList;
|
||||
}
|
||||
|
||||
if (HasMismatchedDisplayCollectionCounts(dropdownAttribute, propertyValues, displayValues))
|
||||
{
|
||||
errorBox.text = "The value collection item count and display names count do not match";
|
||||
DisplayErrorBox(root, errorBox);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
DisplayErrorBox(root, errorBox);
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override string CopyValue(VisualElement element, SerializedProperty property)
|
||||
{
|
||||
var dropdown = element as DropdownField;
|
||||
var dropdownAttribute = attribute as DropdownAttribute;
|
||||
|
||||
return dropdownAttribute.DisplayNames != null ? dropdown.value : base.CopyValue(element, property);
|
||||
}
|
||||
|
||||
protected override void PasteValue(VisualElement element, SerializedProperty property, string clipboardValue)
|
||||
{
|
||||
var dropdown = element as DropdownField;
|
||||
var dropdownAttribute = attribute as DropdownAttribute;
|
||||
|
||||
if (dropdown.choices.Contains(clipboardValue))
|
||||
{
|
||||
if (dropdownAttribute.DisplayNames != null)
|
||||
{
|
||||
dropdown.value = clipboardValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
base.PasteValue(element, property, clipboardValue);
|
||||
dropdown.SetValueWithoutNotify(clipboardValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Could not paste value \"{clipboardValue}\" since is not availiable as an option in the dropdown");
|
||||
}
|
||||
}
|
||||
|
||||
private bool HasMismatchedDisplayCollectionCounts(DropdownAttribute dropdownAttribute, List<string> propertyValues, List<string> collectionValues) => dropdownAttribute.DisplayNames != null && propertyValues.Count != collectionValues.Count;
|
||||
|
||||
private void SetPropertyValue(SerializedProperty property, string value, DropdownAttribute dropdownAttribute, List<string> propertyValues, DropdownField dropdownField, MemberInfo collectionInfo)
|
||||
{
|
||||
if (dropdownAttribute.DisplayNames != null || IsDictionary(collectionInfo, property, out _))
|
||||
{
|
||||
SetPropertyValueFromString(propertyValues[dropdownField.index], property);
|
||||
}
|
||||
else
|
||||
{
|
||||
SetPropertyValueFromString(value, property);
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetDisplayValues(MemberInfo collectionInfo, DropdownAttribute dropdownAttribute, SerializedProperty serializedProperty, List<string> propertyValues)
|
||||
{
|
||||
var displayStrings = new List<string>();
|
||||
|
||||
if (dropdownAttribute.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 = dropdownAttribute.DisplayNames.ToList();
|
||||
}
|
||||
|
||||
return displayStrings;
|
||||
}
|
||||
|
||||
private int GetDropdownDefaultValueIndex(List<string> collectionValues, SerializedProperty property)
|
||||
{
|
||||
var propertyStringValue = GetPropertyValueAsString(property);
|
||||
|
||||
return collectionValues.Contains(propertyStringValue) ? collectionValues.IndexOf(propertyStringValue) : 0;
|
||||
}
|
||||
|
||||
private bool IsDictionary(MemberInfo collectionInfo, SerializedProperty serializedProperty, out IDictionary dictionary)
|
||||
{
|
||||
var collectionValue = ReflectionUtility.GetMemberInfoValue(collectionInfo, serializedProperty);
|
||||
|
||||
dictionary = collectionValue as IDictionary;
|
||||
|
||||
return collectionValue is IDictionary;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 08af5fd491c7fa945b245936d43670b2
|
||||
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/DropdownAttributeDrawers/DropdownDrawer.cs
|
||||
uploadId: 806636
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using EditorAttributes.Editor.Utility;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(PropertyDropdownAttribute))]
|
||||
public class PropertyDropdownDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var fieldType = GetValidPropertyType(property);
|
||||
|
||||
var root = new VisualElement();
|
||||
var propertyField = CreatePropertyField(property);
|
||||
var errorBox = new HelpBox("The PropertyDropdown Attribute can only be attached on to <b>UnityEngine.Object</b> types", HelpBoxMessageType.Error);
|
||||
|
||||
ApplyBoxStyle(root);
|
||||
|
||||
root.Add(propertyField);
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.ObjectReference)
|
||||
{
|
||||
InitializeFoldoutDrawer(root, property, fieldType, errorBox);
|
||||
|
||||
// Register the callback later to skip any initialization calls
|
||||
ExecuteLater(propertyField, () =>
|
||||
{
|
||||
propertyField.RegisterCallback<SerializedPropertyChangeEvent>((callback) =>
|
||||
{
|
||||
if (root.childCount > 1 && root.ElementAt(1) != null)
|
||||
root.RemoveAt(1);
|
||||
|
||||
InitializeFoldoutDrawer(root, property, fieldType, errorBox);
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
root.Add(errorBox);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void InitializeFoldoutDrawer(VisualElement root, SerializedProperty property, Type fieldType, HelpBox errorBox)
|
||||
{
|
||||
if (property.objectReferenceValue == null)
|
||||
{
|
||||
var foldout = root.Q<Foldout>();
|
||||
|
||||
if (foldout != null)
|
||||
root.Remove(foldout);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
root.Add(CreatePropertyFoldout(new SerializedObject(property.objectReferenceValue), property));
|
||||
}
|
||||
|
||||
private Foldout CreatePropertyFoldout(SerializedObject serializedObject, SerializedProperty serializedProperty)
|
||||
{
|
||||
var foldoutSaveKey = CreatePropertySaveKey(serializedProperty, "IsPropertyDropdownFolded");
|
||||
|
||||
var foldout = new Foldout
|
||||
{
|
||||
text = "Properties",
|
||||
value = EditorPrefs.GetBool(foldoutSaveKey)
|
||||
};
|
||||
|
||||
ApplyBoxStyle(foldout);
|
||||
|
||||
foldout.style.paddingLeft = 15f;
|
||||
|
||||
foldout.Add(new InspectorElement(serializedObject));
|
||||
|
||||
serializedObject.ApplyModifiedProperties();
|
||||
|
||||
foldout.RegisterValueChangedCallback((callback) => EditorPrefs.SetBool(foldoutSaveKey, callback.newValue));
|
||||
|
||||
ExecuteLater(foldout, () =>
|
||||
{
|
||||
foldout.Q<Label>(className: Foldout.textUssClassName).style.unityFontStyleAndWeight = FontStyle.Bold;
|
||||
foldout.Q<ObjectField>("unity-input-m_Script")?.parent.RemoveFromHierarchy();
|
||||
});
|
||||
|
||||
return foldout;
|
||||
}
|
||||
|
||||
private Type GetValidPropertyType(SerializedProperty property)
|
||||
{
|
||||
var validProperty = IsPropertyCollection(property) ? GetCollectionProperty(property) : property;
|
||||
var memberInfo = ReflectionUtility.GetValidMemberInfo(validProperty.name, validProperty);
|
||||
|
||||
return ReflectionUtility.GetMemberInfoType(memberInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f71b94d54e68a849a3d5fce711ae434
|
||||
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/DropdownAttributeDrawers/PropertyDropdownDrawer.cs
|
||||
uploadId: 806636
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(SceneDropdownAttribute))]
|
||||
public class SceneDropdownDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var root = new VisualElement();
|
||||
var errorBox = new HelpBox();
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String || property.propertyType == SerializedPropertyType.Integer)
|
||||
{
|
||||
var sceneNames = GetSceneNames(errorBox);
|
||||
|
||||
var dropdownField = IsCollectionValid(sceneNames) ? new DropdownField(property.displayName, sceneNames, GetDropdownDefaultValue(sceneNames, property))
|
||||
: new DropdownField(property.displayName, new List<string>() { "NULL" }, 0);
|
||||
|
||||
dropdownField.tooltip = property.tooltip;
|
||||
dropdownField.AddToClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
dropdownField.RegisterValueChangedCallback(callback => ApplyPropertyValue(property, dropdownField));
|
||||
|
||||
AddPropertyContextMenu(dropdownField, property);
|
||||
|
||||
if (dropdownField.value != "NULL")
|
||||
{
|
||||
dropdownField.showMixedValue = property.hasMultipleDifferentValues;
|
||||
ApplyPropertyValue(property, dropdownField);
|
||||
}
|
||||
|
||||
root.Add(dropdownField);
|
||||
DisplayErrorBox(root, errorBox);
|
||||
|
||||
dropdownField.TrackPropertyValue(property, (trackedProperty) =>
|
||||
{
|
||||
string sceneName = trackedProperty.propertyType == SerializedPropertyType.Integer ? SceneNameFromIndex(trackedProperty.intValue) : trackedProperty.stringValue;
|
||||
|
||||
if (dropdownField.choices.Contains(sceneName))
|
||||
{
|
||||
dropdownField.SetValueWithoutNotify(sceneName);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"The value <b>{trackedProperty.boxedValue}</b> set to the <b>{trackedProperty.name}</b> variable is not a valid scene identifier.", trackedProperty.serializedObject.targetObject);
|
||||
}
|
||||
});
|
||||
|
||||
ExecuteLater(dropdownField, () => dropdownField.Q(className: DropdownField.inputUssClassName).style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f);
|
||||
|
||||
UpdateVisualElement(dropdownField, () =>
|
||||
{
|
||||
var sceneNames = GetSceneNames(errorBox);
|
||||
|
||||
if (IsCollectionValid(sceneNames))
|
||||
dropdownField.choices = sceneNames;
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
else
|
||||
{
|
||||
errorBox.text = "The SceneDropdown attribute can only be attached to a string or int";
|
||||
DisplayErrorBox(root, errorBox);
|
||||
|
||||
return root;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void PasteValue(VisualElement element, SerializedProperty property, string clipboardValue)
|
||||
{
|
||||
var dropdown = element as DropdownField;
|
||||
|
||||
string sceneName = int.TryParse(clipboardValue, out int sceneIndex) ? SceneNameFromIndex(sceneIndex) : clipboardValue;
|
||||
|
||||
if (dropdown.choices.Contains(sceneName))
|
||||
{
|
||||
dropdown.value = sceneName;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Could not paste value \"{clipboardValue}\" since is not availiable as an option in the dropdown");
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetSceneNames(HelpBox errorBox)
|
||||
{
|
||||
var sceneList = new List<string>();
|
||||
var activeSceneList = EditorBuildSettingsScene.GetActiveSceneList(EditorBuildSettings.scenes);
|
||||
|
||||
if (activeSceneList == null || activeSceneList.Length == 0)
|
||||
{
|
||||
errorBox.text = "There are no scenes in the active build settings";
|
||||
return sceneList;
|
||||
}
|
||||
|
||||
foreach (var scene in activeSceneList)
|
||||
{
|
||||
var sceneName = scene.Split('/')[^1].Split('.')[0]; // Remove the asset paths and file extension from the name
|
||||
|
||||
sceneList.Add(sceneName);
|
||||
}
|
||||
|
||||
return sceneList;
|
||||
}
|
||||
|
||||
private string SceneNameFromIndex(int BuildIndex)
|
||||
{
|
||||
var path = SceneUtility.GetScenePathByBuildIndex(BuildIndex);
|
||||
|
||||
if (path == string.Empty)
|
||||
return "";
|
||||
|
||||
var slashIndex = path.LastIndexOf('/');
|
||||
var name = path[(slashIndex + 1)..];
|
||||
var dotIndex = name.LastIndexOf('.');
|
||||
|
||||
return name[..dotIndex];
|
||||
}
|
||||
|
||||
private string GetDropdownDefaultValue(List<string> collectionValues, SerializedProperty property)
|
||||
{
|
||||
var propertyStringValue = property.propertyType == SerializedPropertyType.String ? property.stringValue : SceneNameFromIndex(property.intValue);
|
||||
|
||||
return collectionValues.Contains(propertyStringValue) ? propertyStringValue : collectionValues[0];
|
||||
}
|
||||
|
||||
private void ApplyPropertyValue(SerializedProperty property, DropdownField dropdown)
|
||||
{
|
||||
if (property.hasMultipleDifferentValues)
|
||||
return;
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
property.stringValue = dropdown.value;
|
||||
}
|
||||
else
|
||||
{
|
||||
property.intValue = dropdown.index;
|
||||
}
|
||||
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1862b63729c73e04a986f040c67f58cf
|
||||
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/DropdownAttributeDrawers/SceneDropdownDrawer.cs
|
||||
uploadId: 806636
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(SortingLayerDropdownAttribute))]
|
||||
public class SortingLayerDropdownDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var root = new VisualElement();
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.Integer)
|
||||
{
|
||||
var maskField = new MaskField(property.displayName, GetSortingLayerNames(), property.intValue)
|
||||
{
|
||||
showMixedValue = property.hasMultipleDifferentValues,
|
||||
tooltip = property.tooltip
|
||||
};
|
||||
|
||||
maskField.AddToClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
AddPropertyContextMenu(maskField, property);
|
||||
|
||||
maskField.RegisterValueChangedCallback(callback =>
|
||||
{
|
||||
property.intValue = maskField.value;
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
|
||||
maskField.TrackPropertyValue(property, (trackedProperty) => maskField.SetValueWithoutNotify(trackedProperty.intValue));
|
||||
|
||||
root.Add(maskField);
|
||||
|
||||
ExecuteLater(maskField, () => maskField.Q(className: MaskField.inputUssClassName).style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
root.Add(new HelpBox("The SortingLayerDropdown attribute can only be attached to int fields", HelpBoxMessageType.Error));
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override void PasteValue(VisualElement element, SerializedProperty property, string clipboardValue)
|
||||
{
|
||||
var dropdown = element as MaskField;
|
||||
|
||||
base.PasteValue(element, property, clipboardValue);
|
||||
|
||||
try
|
||||
{
|
||||
dropdown.SetValueWithoutNotify(int.Parse(clipboardValue));
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
// Ignore, error will already be thrown by the base function
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetSortingLayerNames()
|
||||
{
|
||||
var layerList = new List<string>();
|
||||
|
||||
foreach (var layer in SortingLayer.layers)
|
||||
layerList.Add(layer.name);
|
||||
|
||||
return layerList;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3c51a50b251f4ec468514ecf0e6c9f0f
|
||||
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/DropdownAttributeDrawers/SortingLayerDropdownDrawer.cs
|
||||
uploadId: 806636
|
||||
+83
@@ -0,0 +1,83 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditorInternal;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TagDropdownAttribute))]
|
||||
public class TagDropdownDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var root = new VisualElement();
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
var tagField = new TagField(property.displayName, DoesStringValueContainTag(property.stringValue) ? property.stringValue : "Untagged")
|
||||
{
|
||||
showMixedValue = property.hasMultipleDifferentValues,
|
||||
tooltip = property.tooltip
|
||||
};
|
||||
|
||||
tagField.AddToClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
AddPropertyContextMenu(tagField, property);
|
||||
|
||||
tagField.RegisterValueChangedCallback(callback =>
|
||||
{
|
||||
property.stringValue = tagField.value;
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
|
||||
tagField.TrackPropertyValue(property, (trackedProperty) =>
|
||||
{
|
||||
if (DoesStringValueContainTag(trackedProperty.stringValue))
|
||||
{
|
||||
tagField.SetValueWithoutNotify(trackedProperty.stringValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"The value <b>{trackedProperty.stringValue}</b> set to the <b>{trackedProperty.name}</b> variable is not a valid tag.", trackedProperty.serializedObject.targetObject);
|
||||
}
|
||||
});
|
||||
|
||||
root.Add(tagField);
|
||||
|
||||
ExecuteLater(tagField, () => tagField.Q(className: TagField.inputUssClassName).style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
root.Add(new HelpBox("The TagDropdown attribute can only be attached to string fields", HelpBoxMessageType.Error));
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override void PasteValue(VisualElement element, SerializedProperty property, string clipboardValue)
|
||||
{
|
||||
var dropdown = element as TagField;
|
||||
|
||||
if (dropdown.choices.Contains(clipboardValue))
|
||||
{
|
||||
base.PasteValue(element, property, clipboardValue);
|
||||
dropdown.SetValueWithoutNotify(clipboardValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Could not paste value \"{clipboardValue}\" since is not availiable as an option in the dropdown");
|
||||
}
|
||||
}
|
||||
|
||||
private bool DoesStringValueContainTag(string stringValue)
|
||||
{
|
||||
foreach (var tag in InternalEditorUtility.tags)
|
||||
{
|
||||
if (stringValue == tag)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7acdcb2a08bc4846ac4d279b384c5fe
|
||||
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/DropdownAttributeDrawers/TagDropdownDrawer.cs
|
||||
uploadId: 806636
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TypeDropdownAttribute))]
|
||||
public class TypeDropdownDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var root = new VisualElement();
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
var dropdownValues = GetAvailableTypes();
|
||||
|
||||
var typeDropdown = new DropdownField(property.displayName, dropdownValues, GetDropdownDefaultValue(dropdownValues, property))
|
||||
{
|
||||
showMixedValue = property.hasMultipleDifferentValues,
|
||||
tooltip = property.tooltip
|
||||
};
|
||||
|
||||
typeDropdown.AddToClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
AddPropertyContextMenu(typeDropdown, property);
|
||||
|
||||
typeDropdown.RegisterValueChangedCallback(callback =>
|
||||
{
|
||||
if (callback.newValue == "Null")
|
||||
{
|
||||
property.stringValue = string.Empty;
|
||||
}
|
||||
else if (callback.newValue.StartsWith("Global/"))
|
||||
{
|
||||
property.stringValue = callback.newValue[7..].Replace('/', '.');
|
||||
}
|
||||
else
|
||||
{
|
||||
property.stringValue = callback.newValue.Replace('/', '.');
|
||||
}
|
||||
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
|
||||
typeDropdown.TrackPropertyValue(property, (trackedProperty) =>
|
||||
{
|
||||
string dropdownValue = ConvertPropertyValueToDropdownValue(trackedProperty.stringValue);
|
||||
|
||||
if (typeDropdown.choices.Contains(dropdownValue))
|
||||
{
|
||||
typeDropdown.SetValueWithoutNotify(dropdownValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"The value <b>{trackedProperty.stringValue}</b> set to the <b>{trackedProperty.name}</b> variable is not a valid type string.", trackedProperty.serializedObject.targetObject);
|
||||
}
|
||||
});
|
||||
|
||||
root.Add(typeDropdown);
|
||||
|
||||
ExecuteLater(typeDropdown, () => typeDropdown.Q(className: DropdownField.inputUssClassName).style.backgroundColor = EditorExtension.GLOBAL_COLOR / 2f);
|
||||
}
|
||||
else
|
||||
{
|
||||
root.Add(new HelpBox("The TypeDropdown attribute can only be attached to string fields", HelpBoxMessageType.Error));
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
protected override void PasteValue(VisualElement element, SerializedProperty property, string clipboardValue)
|
||||
{
|
||||
var dropdown = element as DropdownField;
|
||||
|
||||
string dropdownValue = ConvertPropertyValueToDropdownValue(clipboardValue);
|
||||
|
||||
if (dropdown.choices.Contains(dropdownValue))
|
||||
{
|
||||
base.PasteValue(element, property, clipboardValue);
|
||||
dropdown.SetValueWithoutNotify(dropdownValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning($"Could not paste value \"{dropdownValue}\" since is not availiable as an option in the dropdown");
|
||||
}
|
||||
}
|
||||
|
||||
private List<string> GetAvailableTypes()
|
||||
{
|
||||
var typeDropdownAttribute = attribute as TypeDropdownAttribute;
|
||||
|
||||
var typeNameList = new List<string>();
|
||||
var typeCollection = typeDropdownAttribute.AssemblyName == string.Empty ? TypeCache.GetTypesDerivedFrom<object>() : TypeCache.GetTypesDerivedFrom<object>(typeDropdownAttribute.AssemblyName);
|
||||
|
||||
foreach (var item in typeCollection)
|
||||
{
|
||||
if (typeDropdownAttribute.AssemblyName == string.Empty && !item.IsVisible)
|
||||
continue;
|
||||
|
||||
string assemblyName = item.Assembly.ToString().Split(',')[0];
|
||||
|
||||
if (!item.FullName.Contains('.'))
|
||||
{
|
||||
typeNameList.Add($"Global/{item.FullName}, {assemblyName}");
|
||||
}
|
||||
else
|
||||
{
|
||||
typeNameList.Add($"{item.FullName.Replace('.', '/')}, {assemblyName}");
|
||||
}
|
||||
}
|
||||
|
||||
typeNameList.Sort();
|
||||
typeNameList.Insert(0, "Null");
|
||||
|
||||
return typeNameList;
|
||||
}
|
||||
|
||||
private string GetDropdownDefaultValue(List<string> collectionValues, SerializedProperty property)
|
||||
{
|
||||
string propertyStringValue = ConvertPropertyValueToDropdownValue(property.stringValue);
|
||||
|
||||
return collectionValues.Contains(propertyStringValue) ? propertyStringValue : collectionValues[0];
|
||||
}
|
||||
|
||||
private string ConvertPropertyValueToDropdownValue(string propertyValue)
|
||||
{
|
||||
if (propertyValue == string.Empty)
|
||||
return "Null";
|
||||
|
||||
int commaIndex = propertyValue.IndexOf(',');
|
||||
|
||||
if (commaIndex == -1)
|
||||
return propertyValue;
|
||||
|
||||
string typeName = propertyValue[..commaIndex].Replace('.', '/');
|
||||
string assemblyName = propertyValue[(commaIndex + 1)..];
|
||||
|
||||
return !typeName.Contains("/") ? $"Global/{propertyValue}" : $"{typeName},{assemblyName}";
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: abf1f80377b4f144d9b4c20c65067b67
|
||||
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/DropdownAttributeDrawers/TypeDropdownDrawer.cs
|
||||
uploadId: 806636
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0fb763bd14063414aa95714f68b6bd83
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+140
@@ -0,0 +1,140 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
using UnityEditor.UIElements;
|
||||
using EditorAttributes.Editor.Utility;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(DataTableAttribute))]
|
||||
public class DataTableDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var dataTableAttribute = attribute as DataTableAttribute;
|
||||
var root = new VisualElement();
|
||||
|
||||
if (property.propertyType != SerializedPropertyType.Generic)
|
||||
{
|
||||
var errorBox = new HelpBox("The DataTableAttribute can only be attached to serialized structs or classes and collections containing them", HelpBoxMessageType.Error);
|
||||
root.Add(errorBox);
|
||||
return root;
|
||||
}
|
||||
|
||||
property.isExpanded = true;
|
||||
|
||||
root.style.flexDirection = FlexDirection.Row;
|
||||
|
||||
if (dataTableAttribute.DrawInBox)
|
||||
ApplyBoxStyle(root);
|
||||
|
||||
var label = new Label(property.displayName)
|
||||
{
|
||||
tooltip = property.tooltip,
|
||||
style = {
|
||||
overflow = Overflow.Hidden,
|
||||
unityFontStyleAndWeight = FontStyle.Bold,
|
||||
marginRight = 50f,
|
||||
maxWidth = 100f,
|
||||
width = 100f,
|
||||
alignSelf = Align.Center,
|
||||
color = EditorExtension.GLOBAL_COLOR
|
||||
}
|
||||
};
|
||||
|
||||
root.Add(label);
|
||||
|
||||
var serializedProperty = property.Copy();
|
||||
int initialDepth = serializedProperty.depth;
|
||||
|
||||
while (serializedProperty.NextVisible(true) && serializedProperty.depth > initialDepth)
|
||||
{
|
||||
if (serializedProperty.propertyType is SerializedPropertyType.Generic or SerializedPropertyType.Vector4 or SerializedPropertyType.ArraySize)
|
||||
{
|
||||
var errorBox = new HelpBox("Collection, UnityEvent and Serialized Object types are not supported", HelpBoxMessageType.Error);
|
||||
root.Add(errorBox);
|
||||
break;
|
||||
}
|
||||
|
||||
if (serializedProperty.depth >= initialDepth + 2) // Skip the X Y Z properties that are inside Vectors since we draw the vector field ourself
|
||||
continue;
|
||||
|
||||
var tableColumn = new VisualElement();
|
||||
tableColumn.style.flexGrow = 1f;
|
||||
tableColumn.style.flexBasis = 0.1f;
|
||||
|
||||
if (dataTableAttribute.ShowLabels && IsNotFirstArrayElement(property))
|
||||
{
|
||||
var propertyLabel = new Label(serializedProperty.displayName);
|
||||
|
||||
propertyLabel.style.color = EditorExtension.GLOBAL_COLOR;
|
||||
propertyLabel.style.overflow = Overflow.Hidden;
|
||||
propertyLabel.tooltip = serializedProperty.tooltip;
|
||||
|
||||
tableColumn.Add(propertyLabel);
|
||||
}
|
||||
|
||||
var propertyField = new PropertyField(serializedProperty, string.Empty);
|
||||
|
||||
propertyField.style.flexGrow = 1f;
|
||||
propertyField.style.marginRight = 10f;
|
||||
|
||||
// Add X Y Z labels to Vector fields
|
||||
if (serializedProperty.propertyType is SerializedPropertyType.Vector2 or SerializedPropertyType.Vector3 or SerializedPropertyType.Vector2Int or SerializedPropertyType.Vector3Int)
|
||||
{
|
||||
ExecuteLater(propertyField, () =>
|
||||
{
|
||||
var floatFields = propertyField.Query<FloatField>().ToList();
|
||||
|
||||
for (int i = 0; i < floatFields.Count; i++)
|
||||
{
|
||||
var label = new Label(i == 0 ? "X" : i == 1 ? "Y" : "Z")
|
||||
{
|
||||
style = {
|
||||
alignSelf = Align.Center,
|
||||
marginRight = 3f,
|
||||
color = EditorExtension.GLOBAL_COLOR
|
||||
}
|
||||
};
|
||||
|
||||
floatFields[i].style.marginRight = 3f;
|
||||
|
||||
floatFields[i].parent.Add(label);
|
||||
|
||||
floatFields[i].PlaceInFront(label);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (EditorExtension.GLOBAL_COLOR != EditorExtension.DEFAULT_GLOBAL_COLOR)
|
||||
ColorUtils.ApplyColor(propertyField, EditorExtension.GLOBAL_COLOR, 100);
|
||||
|
||||
tableColumn.Add(propertyField);
|
||||
root.Add(tableColumn);
|
||||
}
|
||||
|
||||
// When there are other attributes on the dataTable field they would recreate the label of the property field so we make sure it will never be there
|
||||
UpdateVisualElement(root, () =>
|
||||
{
|
||||
var labels = root.Query<Label>(className: "unity-base-field__label").ToList();
|
||||
|
||||
foreach (var label in labels)
|
||||
label.RemoveFromHierarchy();
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private bool IsNotFirstArrayElement(SerializedProperty property)
|
||||
{
|
||||
if (IsPropertyCollection(property))
|
||||
{
|
||||
var splitName = property.propertyPath.Split(".");
|
||||
|
||||
return splitName[^1] == "data[0]";
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8e33ad44453b54e409ee404502eb0a2f
|
||||
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/GroupingAttributeDrawers/DataTableDrawer.cs
|
||||
uploadId: 806636
|
||||
+89
@@ -0,0 +1,89 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(FoldoutGroupAttribute))]
|
||||
public class FoldoutGroupDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var foldoutGroup = attribute as FoldoutGroupAttribute;
|
||||
var foldoutSaveKey = CreatePropertySaveKey(property, "IsFoldoutGroupFolded");
|
||||
|
||||
var root = new VisualElement();
|
||||
|
||||
var foldout = new Foldout
|
||||
{
|
||||
style = { unityFontStyleAndWeight = FontStyle.Bold },
|
||||
text = foldoutGroup.GroupName,
|
||||
tooltip = property.tooltip,
|
||||
value = EditorPrefs.GetBool(foldoutSaveKey)
|
||||
};
|
||||
|
||||
if (foldoutGroup.DrawInBox)
|
||||
ApplyBoxStyle(foldout.contentContainer);
|
||||
|
||||
foreach (string variableName in foldoutGroup.FieldsToGroup)
|
||||
{
|
||||
var propertyField = CreateField(variableName, property, root);
|
||||
|
||||
foldout.Add(propertyField);
|
||||
}
|
||||
|
||||
root.Add(foldout);
|
||||
|
||||
ExecuteLater(foldout, () =>
|
||||
{
|
||||
var toggle = foldout.Q<Toggle>();
|
||||
|
||||
toggle.style.backgroundColor = CanApplyGlobalColor ? EditorExtension.GLOBAL_COLOR / 3f : new Color(0.1f, 0.1f, 0.1f, 0.2f);
|
||||
|
||||
// Register this callback later since value changed callbacks are called on inspector initalization and we don't want to save values on initalization
|
||||
foldout.RegisterValueChangedCallback((callback) => EditorPrefs.SetBool(foldoutSaveKey, callback.newValue));
|
||||
});
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private VisualElement CreateField(string variableName, SerializedProperty property, VisualElement root)
|
||||
{
|
||||
VisualElement field;
|
||||
|
||||
var variableProperty = FindNestedProperty(property, GetSerializedPropertyName(variableName, property));
|
||||
|
||||
if (variableProperty == null)
|
||||
return new HelpBox($"<b>{variableName}</b> is not a valid field or property", HelpBoxMessageType.Error);
|
||||
|
||||
field = CreatePropertyField(variableProperty);
|
||||
|
||||
field.style.unityFontStyleAndWeight = FontStyle.Normal;
|
||||
|
||||
// Slightly move foldouts for serialized objects
|
||||
if (variableProperty.propertyType == SerializedPropertyType.Generic && variableProperty.type != "UnityEvent" && !IsPropertyCollection(variableProperty))
|
||||
field.style.marginLeft = 10f;
|
||||
|
||||
root.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
|
||||
void OnGeometryChanged(GeometryChangedEvent changeEvent)
|
||||
{
|
||||
// Force update this logic to make sure fields are visible
|
||||
UpdateVisualElement(field, () =>
|
||||
{
|
||||
var hiddenField = field.Q<VisualElement>(HidePropertyDrawer.HIDDEN_PROPERTY_ID);
|
||||
|
||||
if (hiddenField != null)
|
||||
{
|
||||
hiddenField.name = GROUPED_PROPERTY_ID;
|
||||
hiddenField.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
}, 100L);
|
||||
|
||||
root.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ecc183ddb62745459826228e6803d7e
|
||||
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/GroupingAttributeDrawers/FoldoutGroupDrawer.cs
|
||||
uploadId: 806636
|
||||
+155
@@ -0,0 +1,155 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using System.Reflection;
|
||||
using UnityEngine.UIElements;
|
||||
using EditorAttributes.Editor.Utility;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(HorizontalGroupAttribute))]
|
||||
public class HorizontalGroupDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var horizontalGroup = attribute as HorizontalGroupAttribute;
|
||||
var root = new VisualElement();
|
||||
|
||||
if (horizontalGroup.DrawInBox)
|
||||
ApplyBoxStyle(root);
|
||||
|
||||
root.style.flexDirection = FlexDirection.Row;
|
||||
root.style.alignItems = Align.FlexStart;
|
||||
|
||||
foreach (string variableName in horizontalGroup.FieldsToGroup)
|
||||
{
|
||||
var errorBox = new HelpBox();
|
||||
var groupBox = new VisualElement()
|
||||
{
|
||||
style = {
|
||||
flexDirection = FlexDirection.Row,
|
||||
flexGrow = 1f,
|
||||
flexBasis = 0.1f,
|
||||
alignItems = Align.Center
|
||||
}
|
||||
};
|
||||
|
||||
// Add space between properties excluding the last property
|
||||
if (ArrayUtility.LastIndexOf(horizontalGroup.FieldsToGroup, variableName) != horizontalGroup.FieldsToGroup.Length - 1)
|
||||
groupBox.style.marginRight = horizontalGroup.PropertySpace;
|
||||
|
||||
var variableProperty = FindNestedProperty(property, GetSerializedPropertyName(variableName, property));
|
||||
var memberInfo = ReflectionUtility.GetValidMemberInfo(variableName, property);
|
||||
|
||||
var propertyField = CreateField(variableName, variableProperty);
|
||||
|
||||
if (variableProperty == null)
|
||||
{
|
||||
groupBox.Add(propertyField);
|
||||
root.Add(groupBox);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var hideLabelAttribute = memberInfo?.GetCustomAttribute<HideLabelAttribute>();
|
||||
|
||||
propertyField.style.flexGrow = 1f;
|
||||
propertyField.style.flexBasis = 0.1f;
|
||||
groupBox.style.paddingLeft = 20f;
|
||||
|
||||
if (hideLabelAttribute == null)
|
||||
{
|
||||
var renameAttribute = memberInfo?.GetCustomAttribute<RenameAttribute>();
|
||||
var tooltipAttribute = memberInfo?.GetCustomAttribute<TooltipAttribute>();
|
||||
|
||||
string labelText = renameAttribute == null ? ObjectNames.NicifyVariableName(variableName) : RenameDrawer.GetNewName(renameAttribute, property, errorBox);
|
||||
|
||||
var label = new Label(labelText)
|
||||
{
|
||||
tooltip = tooltipAttribute?.tooltip,
|
||||
style = {
|
||||
flexGrow = 1f,
|
||||
flexBasis = 0.1f,
|
||||
marginRight = horizontalGroup.WidthOffset
|
||||
}
|
||||
};
|
||||
|
||||
// Serialized objects and Vector 4 are displayed with foldouts and don't need the custom label
|
||||
if (variableProperty.propertyType is not SerializedPropertyType.Generic and not SerializedPropertyType.Vector4)
|
||||
groupBox.Add(label);
|
||||
|
||||
if (renameAttribute != null)
|
||||
{
|
||||
UpdateVisualElement(label, () =>
|
||||
{
|
||||
label.text = RenameDrawer.GetNewName(renameAttribute, property, errorBox);
|
||||
DisplayErrorBox(propertyField, errorBox);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
groupBox.Add(propertyField);
|
||||
root.Add(groupBox);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private VisualElement CreateField(string variableName, SerializedProperty variableProperty)
|
||||
{
|
||||
VisualElement field;
|
||||
|
||||
if (variableProperty == null)
|
||||
return new HelpBox($"<b>{variableName}</b> is not a valid field or property", HelpBoxMessageType.Error);
|
||||
|
||||
field = CreatePropertyField(variableProperty);
|
||||
|
||||
field.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
|
||||
void OnGeometryChanged(GeometryChangedEvent changeEvent)
|
||||
{
|
||||
// Force update this logic to make sure fields are visible
|
||||
UpdateVisualElement(field, () =>
|
||||
{
|
||||
var hiddenField = field.Q<VisualElement>(HidePropertyDrawer.HIDDEN_PROPERTY_ID);
|
||||
|
||||
if (hiddenField != null)
|
||||
{
|
||||
hiddenField.name = GROUPED_PROPERTY_ID;
|
||||
hiddenField.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
if (variableProperty.propertyType is not SerializedPropertyType.Generic and not SerializedPropertyType.Vector4)
|
||||
{
|
||||
var propertyLabel = field.Q<Label>();
|
||||
|
||||
if (propertyLabel != null)
|
||||
{
|
||||
if (!propertyLabel.parent.ClassListContains(BaseCompositeField<Void, IntegerField, int>.fieldUssClassName)) // Do not remove the label from composite fields
|
||||
propertyLabel.RemoveFromHierarchy();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var alignedFields = field.Query<VisualElement>(className: BaseField<Void>.alignedFieldUssClassName).ToList();
|
||||
|
||||
// Fix alignment issues with fields inside foldouts
|
||||
foreach (var alignedField in alignedFields)
|
||||
{
|
||||
alignedField.RemoveFromClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
|
||||
var alignedFieldLabel = alignedField.Q<Label>();
|
||||
|
||||
alignedFieldLabel.style.width = 0f;
|
||||
alignedFieldLabel.style.minWidth = 80f;
|
||||
alignedFieldLabel.style.marginRight = (attribute as HorizontalGroupAttribute).WidthOffset;
|
||||
}
|
||||
}
|
||||
}, 100L);
|
||||
|
||||
field.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a183350440f575a489b2076705f49295
|
||||
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/GroupingAttributeDrawers/HorizontalGroupDrawer.cs
|
||||
uploadId: 806636
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEditor.UIElements;
|
||||
using UnityEngine.UIElements;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(TabGroupAttribute))]
|
||||
public class TabGroupDrawer : PropertyDrawerBase
|
||||
{
|
||||
private int selectedTab = 0;
|
||||
private Dictionary<ToolbarToggle, int> toolbarToggles = new();
|
||||
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var tabGroupAttribute = attribute as TabGroupAttribute;
|
||||
var root = new VisualElement();
|
||||
|
||||
var selectedTabSaveKey = CreatePropertySaveKey(property, "SelectedTab");
|
||||
|
||||
selectedTab = EditorPrefs.GetInt(selectedTabSaveKey);
|
||||
|
||||
ApplyBoxStyle(root);
|
||||
|
||||
var toolbar = new Toolbar();
|
||||
|
||||
var propertyNames = GetPropertyNames(property, tabGroupAttribute);
|
||||
|
||||
for (int i = 0; i < propertyNames.Length; i++)
|
||||
{
|
||||
string propertyName = propertyNames[i];
|
||||
var toolbarToggle = new ToolbarToggle()
|
||||
{
|
||||
text = propertyName,
|
||||
value = selectedTab == i,
|
||||
style = {
|
||||
flexGrow = 1f,
|
||||
unityFontStyleAndWeight = FontStyle.Bold,
|
||||
}
|
||||
};
|
||||
|
||||
toolbarToggles.Add(toolbarToggle, i);
|
||||
toolbar.Add(toolbarToggle);
|
||||
}
|
||||
|
||||
var propertyField = CreateField(tabGroupAttribute.FieldsToGroup[selectedTab], property);
|
||||
|
||||
propertyField.style.marginLeft = 10f;
|
||||
|
||||
foreach (var toggle in toolbarToggles)
|
||||
{
|
||||
toggle.Key.RegisterValueChangedCallback((callback) =>
|
||||
{
|
||||
selectedTab = toggle.Value;
|
||||
|
||||
EditorPrefs.SetInt(selectedTabSaveKey, selectedTab);
|
||||
|
||||
foreach (var toolbarToggle in toolbarToggles.Where((source) => toggle.Key != source.Key))
|
||||
toolbarToggle.Key.SetValueWithoutNotify(false);
|
||||
|
||||
if (selectedTab == toggle.Value && !toggle.Key.value)
|
||||
toggle.Key.SetValueWithoutNotify(true);
|
||||
|
||||
root.Remove(propertyField);
|
||||
|
||||
propertyField = CreateField(tabGroupAttribute.FieldsToGroup[selectedTab], property);
|
||||
propertyField.style.marginLeft = 10f;
|
||||
|
||||
root.Add(propertyField);
|
||||
});
|
||||
}
|
||||
|
||||
root.Add(toolbar);
|
||||
root.Add(propertyField);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private VisualElement CreateField(string variableName, SerializedProperty property)
|
||||
{
|
||||
VisualElement field;
|
||||
|
||||
var variableProperty = FindNestedProperty(property, GetSerializedPropertyName(variableName, property));
|
||||
|
||||
if (variableProperty == null)
|
||||
return new HelpBox($"<b>{variableName}</b> is not a valid field or property", HelpBoxMessageType.Error);
|
||||
|
||||
field = CreatePropertyField(variableProperty);
|
||||
|
||||
// Replace the hidden field ID with the grouped field ID so the EditorExtension class doesn't remove it when drawing the editor
|
||||
field.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
|
||||
void OnGeometryChanged(GeometryChangedEvent changeEvent)
|
||||
{
|
||||
// Force update this logic to make sure fields are visible
|
||||
UpdateVisualElement(field, () =>
|
||||
{
|
||||
var hiddenField = field.Q<VisualElement>(HidePropertyDrawer.HIDDEN_PROPERTY_ID);
|
||||
|
||||
if (hiddenField != null)
|
||||
{
|
||||
hiddenField.name = GROUPED_PROPERTY_ID;
|
||||
hiddenField.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
}, 100L);
|
||||
|
||||
field.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
private string[] GetPropertyNames(SerializedProperty property, TabGroupAttribute tabGroupAttribute)
|
||||
{
|
||||
var stringList = new List<string>();
|
||||
|
||||
foreach (var field in tabGroupAttribute.FieldsToGroup)
|
||||
{
|
||||
var fieldProperty = FindNestedProperty(property, GetSerializedPropertyName(field, property));
|
||||
|
||||
stringList.Add(fieldProperty == null ? field : fieldProperty.displayName);
|
||||
}
|
||||
|
||||
return stringList.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 214f2376a2e884f4c8577e45e79b2855
|
||||
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/GroupingAttributeDrawers/TabGroupDrawer.cs
|
||||
uploadId: 806636
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
using UnityEngine;
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(ToggleGroupAttribute))]
|
||||
public class ToggleGroupDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var toggleGroup = attribute as ToggleGroupAttribute;
|
||||
var foldoutSaveKey = CreatePropertySaveKey(property, "IsToggleGroupFolded");
|
||||
var toggleSaveKey = CreatePropertySaveKey(property, "IsToggleGroupToggled");
|
||||
|
||||
var root = new VisualElement();
|
||||
|
||||
var foldout = new Foldout
|
||||
{
|
||||
text = toggleGroup.GroupName,
|
||||
tooltip = property.tooltip,
|
||||
style = { unityFontStyleAndWeight = FontStyle.Bold },
|
||||
value = EditorPrefs.GetBool(foldoutSaveKey)
|
||||
};
|
||||
|
||||
var toggleBox = new Toggle()
|
||||
{
|
||||
text = "",
|
||||
style = { marginRight = 10f },
|
||||
value = property.propertyType == SerializedPropertyType.Boolean ? property.boolValue : EditorPrefs.GetBool(toggleSaveKey)
|
||||
};
|
||||
|
||||
foldout.contentContainer.SetEnabled(toggleBox.value);
|
||||
|
||||
if (toggleGroup.DrawInBox)
|
||||
ApplyBoxStyle(foldout.contentContainer);
|
||||
|
||||
root.Add(toggleBox);
|
||||
|
||||
foreach (string variableName in toggleGroup.FieldsToGroup)
|
||||
{
|
||||
var propertyField = CreateField(variableName, property, root);
|
||||
|
||||
foldout.Add(propertyField);
|
||||
}
|
||||
|
||||
toggleBox.RegisterValueChangedCallback((callback) =>
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.Boolean)
|
||||
{
|
||||
property.boolValue = callback.newValue;
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorPrefs.SetBool(toggleSaveKey, callback.newValue); // The value is already serialized via the property, there is no point in saving it.
|
||||
}
|
||||
|
||||
foldout.contentContainer.SetEnabled(callback.newValue);
|
||||
});
|
||||
|
||||
root.Add(foldout);
|
||||
|
||||
ExecuteLater(foldout, () =>
|
||||
{
|
||||
var toggle = foldout.Q<Toggle>();
|
||||
|
||||
toggle.style.backgroundColor = CanApplyGlobalColor ? EditorExtension.GLOBAL_COLOR / 3f : new Color(0.1f, 0.1f, 0.1f, 0.2f);
|
||||
|
||||
var parentElement = foldout.Q<Label>().parent;
|
||||
|
||||
parentElement.Insert(1, toggleBox);
|
||||
|
||||
// Register this callback later since value changed callbacks are called on inspector initalization and we don't want to save values on initalization
|
||||
foldout.RegisterValueChangedCallback((callback) => EditorPrefs.SetBool(foldoutSaveKey, callback.newValue));
|
||||
});
|
||||
|
||||
if (property.propertyType == SerializedPropertyType.Boolean)
|
||||
UpdateVisualElement(toggleBox, () => toggleBox.value = property.boolValue);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private VisualElement CreateField(string variableName, SerializedProperty property, VisualElement root)
|
||||
{
|
||||
VisualElement field;
|
||||
|
||||
var variableProperty = FindNestedProperty(property, GetSerializedPropertyName(variableName, property));
|
||||
|
||||
if (variableProperty == null)
|
||||
return new HelpBox($"<b>{variableName}</b> is not a valid field or property", HelpBoxMessageType.Error);
|
||||
|
||||
field = CreatePropertyField(variableProperty);
|
||||
|
||||
field.style.unityFontStyleAndWeight = FontStyle.Normal;
|
||||
|
||||
// Slightly move foldouts for serialized objects
|
||||
if (variableProperty.propertyType == SerializedPropertyType.Generic && variableProperty.type != "UnityEvent" && !IsPropertyCollection(variableProperty))
|
||||
field.style.marginLeft = 10f;
|
||||
|
||||
root.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
|
||||
void OnGeometryChanged(GeometryChangedEvent changeEvent)
|
||||
{
|
||||
// Force update this logic to make sure fields are visible
|
||||
UpdateVisualElement(field, () =>
|
||||
{
|
||||
var hiddenField = field.Q<VisualElement>(HidePropertyDrawer.HIDDEN_PROPERTY_ID);
|
||||
|
||||
if (hiddenField != null)
|
||||
{
|
||||
hiddenField.name = GROUPED_PROPERTY_ID;
|
||||
hiddenField.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
}, 100L);
|
||||
|
||||
root.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afa75f6fff6fe2d479a1562d42c98217
|
||||
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/GroupingAttributeDrawers/ToggleGroupDrawer.cs
|
||||
uploadId: 806636
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(VerticalGroupAttribute))]
|
||||
public class VerticalGroupDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var verticalGroup = attribute as VerticalGroupAttribute;
|
||||
var root = new VisualElement();
|
||||
|
||||
if (verticalGroup.DrawInBox)
|
||||
ApplyBoxStyle(root);
|
||||
|
||||
foreach (string variableName in verticalGroup.FieldsToGroup)
|
||||
{
|
||||
var groupBox = new VisualElement()
|
||||
{
|
||||
style = {
|
||||
flexDirection = FlexDirection.Row,
|
||||
alignItems = Align.Center
|
||||
}
|
||||
};
|
||||
|
||||
var variableProperty = FindNestedProperty(property, GetSerializedPropertyName(variableName, property));
|
||||
|
||||
var propertyField = CreateField(variableName, variableProperty);
|
||||
|
||||
propertyField.style.flexGrow = 1f;
|
||||
propertyField.style.flexBasis = 0.1f;
|
||||
|
||||
if (variableProperty == null)
|
||||
{
|
||||
groupBox.Add(propertyField);
|
||||
root.Add(groupBox);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (variableProperty.propertyType == SerializedPropertyType.Generic && verticalGroup.DrawInBox) // Add an offset to serialized objects drawn in a box
|
||||
propertyField.style.marginLeft = 10f;
|
||||
|
||||
groupBox.Add(propertyField);
|
||||
root.Add(groupBox);
|
||||
}
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private VisualElement CreateField(string variableName, SerializedProperty variableProperty)
|
||||
{
|
||||
VisualElement field;
|
||||
|
||||
if (variableProperty == null)
|
||||
return new HelpBox($"<b>{variableName}</b> is not a valid field or property", HelpBoxMessageType.Error);
|
||||
|
||||
field = CreatePropertyField(variableProperty);
|
||||
|
||||
field.RegisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
|
||||
void OnGeometryChanged(GeometryChangedEvent changeEvent)
|
||||
{
|
||||
// Force update this logic to make sure fields are visible
|
||||
UpdateVisualElement(field, () =>
|
||||
{
|
||||
var hiddenField = field.Q<VisualElement>(HidePropertyDrawer.HIDDEN_PROPERTY_ID);
|
||||
|
||||
if (hiddenField != null)
|
||||
{
|
||||
hiddenField.name = GROUPED_PROPERTY_ID;
|
||||
hiddenField.style.display = DisplayStyle.Flex;
|
||||
}
|
||||
|
||||
var alignedFields = field.Query<VisualElement>(className: BaseField<Void>.alignedFieldUssClassName).ToList();
|
||||
|
||||
// Fix alignment issues with fields
|
||||
foreach (var alignedField in alignedFields)
|
||||
{
|
||||
alignedField.RemoveFromClassList(BaseField<Void>.alignedFieldUssClassName);
|
||||
|
||||
var alignedFieldLabel = alignedField.Q<Label>();
|
||||
|
||||
alignedFieldLabel.style.width = 0f;
|
||||
alignedFieldLabel.style.minWidth = 100f;
|
||||
}
|
||||
}, 100L);
|
||||
|
||||
field.UnregisterCallback<GeometryChangedEvent>(OnGeometryChanged);
|
||||
}
|
||||
|
||||
return field;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af30d525ade167e41942a69e3737b066
|
||||
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/GroupingAttributeDrawers/VerticalGroupDrawer.cs
|
||||
uploadId: 806636
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: efdc82d5ab9506547ad98cbf90d443ea
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UIElements;
|
||||
|
||||
namespace EditorAttributes.Editor
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(CollectionRangeAttribute))]
|
||||
public class CollectionRangeDrawer : PropertyDrawerBase
|
||||
{
|
||||
public override VisualElement CreatePropertyGUI(SerializedProperty property)
|
||||
{
|
||||
var collectionRangeAttribute = attribute as CollectionRangeAttribute;
|
||||
var root = new VisualElement();
|
||||
|
||||
if (!IsPropertyCollection(property))
|
||||
return new HelpBox("The CollectionRange Attribute can only be used on collections", HelpBoxMessageType.Error);
|
||||
|
||||
var propertyField = CreatePropertyField(property);
|
||||
|
||||
#if UNITY_2023_3_OR_NEWER
|
||||
ClampCollectionSize(property, collectionRangeAttribute);
|
||||
|
||||
propertyField.RegisterValueChangeCallback((evt) => ClampCollectionSize(property, collectionRangeAttribute));
|
||||
#else
|
||||
root.Add(new HelpBox("The CollectionRange Attribute is only available in <b>Unity 6 and above</b>", HelpBoxMessageType.Warning));
|
||||
#endif
|
||||
|
||||
root.Add(propertyField);
|
||||
|
||||
return root;
|
||||
}
|
||||
|
||||
private void ClampCollectionSize(SerializedProperty property, CollectionRangeAttribute collectionRangeAttribute)
|
||||
{
|
||||
property.arraySize = Mathf.Clamp(property.arraySize, collectionRangeAttribute.MinRange, collectionRangeAttribute.MaxRange);
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: eb83e98318feb2f48b068566b921dcdf
|
||||
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/MiscellaneousAttributeDrawers/CollectionRangeDrawer.cs
|
||||
uploadId: 806636
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user