Last active
July 24, 2024 10:03
-
-
Save SolarianZ/deb6f95d59cbcd9ccb0858eed65c9af6 to your computer and use it in GitHub Desktop.
{"category": "Unity Engine/Editor/Extensions", "keywords": "Unity, Editor, UI, Odin, Primary, Key, List, Element"} Odin extension to verify the primary key of the list element.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| using System; | |
| using System.Collections; | |
| using System.Diagnostics; | |
| using Sirenix.OdinInspector.Editor; | |
| using Sirenix.Utilities.Editor; | |
| using UnityEngine; | |
| // Put the following class to the Runtime folder | |
| // Used on primary key field | |
| [Conditional("UNITY_EDITOR")] | |
| public class PrimaryKeyAttribute : Attribute { } | |
| // Put the following class to the Editor folder | |
| public class PrimaryKeyListElementDrawer : OdinAttributeDrawer<PrimaryKeyAttribute> | |
| { | |
| /// <inheritdoc /> | |
| protected override void DrawPropertyLayout(GUIContent label) | |
| { | |
| if (IsParentObjectInList()) | |
| { | |
| if (Property.ValueEntry.WeakSmartValue == null | |
| || (Property.ValueEntry.WeakSmartValue is string str && string.IsNullOrEmpty(str))) | |
| { | |
| SirenixEditorGUI.ErrorMessageBox("Primary key cannot be null or empty."); | |
| } | |
| else if (HasDuplicateKeys()) | |
| { | |
| SirenixEditorGUI.ErrorMessageBox("Duplicate primary keys are not allowed."); | |
| } | |
| } | |
| CallNextDrawer(label); | |
| } | |
| private bool IsParentObjectInList() | |
| { | |
| return Property.Parent.Parent?.ValueEntry?.WeakSmartValue is IList; | |
| } | |
| private bool HasDuplicateKeys() | |
| { | |
| InspectorProperty listProperty = Property.Parent.Parent; | |
| foreach (InspectorProperty listElementProperty in listProperty.Children) | |
| { | |
| if (listElementProperty == Property.Parent) | |
| { | |
| continue; | |
| } | |
| foreach (InspectorProperty siblingProperty in listElementProperty.Children) | |
| { | |
| if (!Property.Name.Equals(siblingProperty.Name)) | |
| { | |
| continue; | |
| } | |
| // Do not use == operator here, because it does not support polymorphic comparison | |
| if (Property.ValueEntry.WeakSmartValue.Equals(siblingProperty.ValueEntry.WeakSmartValue)) | |
| { | |
| return true; | |
| } | |
| } | |
| } | |
| return false; | |
| } | |
| } | |
| // If you can add the PrimaryKeyAttribute to the field of the list element type, | |
| // you can use the following code to validate the primary key: | |
| // | |
| // // Usage: [ListDrawerSettings(OnBeginListElementGUI = nameof(OdinValidatePrimaryKey))] | |
| // // Replace "LIST" and "PRIMARY_KEY" with your list name and primary key name. | |
| // private void OdinValidatePrimaryKey(int index) | |
| // { | |
| // var value = LIST[index].PRIMARY_KEY; | |
| // if (value == null || (value is string str && string.IsNullOrEmpty(str))) // Not suitable for all types | |
| // { | |
| // SirenixEditorGUI.ErrorMessageBox("Primary key cannot be null or empty."); | |
| // return; | |
| // } | |
| // | |
| // for (int i = 0; i < LIST.Length; i++) | |
| // { | |
| // if (i == index) | |
| // { | |
| // continue; | |
| // } | |
| // | |
| // var otherValue = LIST[i].PRIMARY_KEY; | |
| // if (value.Equals(otherValue)) | |
| // { | |
| // SirenixEditorGUI.ErrorMessageBox("Duplicate primary keys are not allowed."); | |
| // return; | |
| // } | |
| // } | |
| // } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment