diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..82adb59 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,282 @@ +# 上位ディレクトリから .editorconfig 設定を継承する場合は、以下の行を削除します +root = true + +# C# ファイル +[*.cs] + +#### コア EditorConfig オプション #### + +# インデントと間隔 +indent_size = 4 +indent_style = space +tab_width = 4 + +# 改行設定 +end_of_line = crlf +insert_final_newline = false + +#### .NET コード アクション #### + +# 型メンバー +dotnet_hide_advanced_members = false +dotnet_member_insertion_location = with_other_members_of_the_same_kind +dotnet_property_generation_behavior = prefer_throwing_properties + +# シンボルの検索 +dotnet_search_reference_assemblies = true + +#### .NET コーディング規則 #### + +# using の整理 +dotnet_separate_import_directive_groups = false +dotnet_sort_system_directives_first = true +file_header_template = unset + +# this. と Me. の設定 +dotnet_style_qualification_for_event = false +dotnet_style_qualification_for_field = false +dotnet_style_qualification_for_method = false +dotnet_style_qualification_for_property = false + +# 言語キーワードと BCL の種類の設定 +dotnet_style_predefined_type_for_locals_parameters_members = true +dotnet_style_predefined_type_for_member_access = true + +# かっこの設定 +dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_binary_operators = always_for_clarity +dotnet_style_parentheses_in_other_operators = never_if_unnecessary +dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity + +# 修飾子設定 +dotnet_style_require_accessibility_modifiers = for_non_interface_members + +# 式レベルの設定 +dotnet_prefer_system_hash_code = true +dotnet_style_coalesce_expression = true +dotnet_style_collection_initializer = true +dotnet_style_explicit_tuple_names = true +dotnet_style_namespace_match_folder = true +dotnet_style_null_propagation = true +dotnet_style_object_initializer = true +dotnet_style_operator_placement_when_wrapping = beginning_of_line +dotnet_style_prefer_auto_properties = true +dotnet_style_prefer_collection_expression = when_types_loosely_match +dotnet_style_prefer_compound_assignment = true +dotnet_style_prefer_conditional_expression_over_assignment = true +dotnet_style_prefer_conditional_expression_over_return = true +dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed +dotnet_style_prefer_inferred_anonymous_type_member_names = true +dotnet_style_prefer_inferred_tuple_names = true +dotnet_style_prefer_is_null_check_over_reference_equality_method = true +dotnet_style_prefer_simplified_boolean_expressions = true +dotnet_style_prefer_simplified_interpolation = true + +# フィールド設定 +dotnet_style_readonly_field = true + +# パラメーターの設定 +dotnet_code_quality_unused_parameters = all + +# 抑制の設定 +dotnet_remove_unnecessary_suppression_exclusions = none + +# 改行設定 +dotnet_style_allow_multiple_blank_lines_experimental = false +dotnet_style_allow_statement_immediately_after_block_experimental = true + +#### C# コーディング規則 #### + +# var を優先 +csharp_style_var_elsewhere = false +csharp_style_var_for_built_in_types = false +csharp_style_var_when_type_is_apparent = false + +# 式のようなメンバー +csharp_style_expression_bodied_accessors = true +csharp_style_expression_bodied_constructors = false +csharp_style_expression_bodied_indexers = true +csharp_style_expression_bodied_lambdas = true +csharp_style_expression_bodied_local_functions = false +csharp_style_expression_bodied_methods = false +csharp_style_expression_bodied_operators = false +csharp_style_expression_bodied_properties = true + +# パターン マッチング設定 +csharp_style_pattern_matching_over_as_with_null_check = true +csharp_style_pattern_matching_over_is_with_cast_check = true +csharp_style_prefer_extended_property_pattern = true +csharp_style_prefer_not_pattern = true +csharp_style_prefer_pattern_matching = true +csharp_style_prefer_switch_expression = true + +# Null チェック設定 +csharp_style_conditional_delegate_call = true + +# 修飾子設定 +csharp_prefer_static_anonymous_function = true +csharp_prefer_static_local_function = true +csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async +csharp_style_prefer_readonly_struct = true +csharp_style_prefer_readonly_struct_member = true + +# コード ブロックの設定 +csharp_prefer_braces = true +csharp_prefer_simple_using_statement = true +csharp_prefer_system_threading_lock = true +csharp_style_namespace_declarations = block_scoped +csharp_style_prefer_method_group_conversion = true +csharp_style_prefer_primary_constructors = true +csharp_style_prefer_top_level_statements = true + +# 式レベルの設定 +csharp_prefer_simple_default_expression = true +csharp_style_deconstructed_variable_declaration = true +csharp_style_implicit_object_creation_when_type_is_apparent = true +csharp_style_inlined_variable_declaration = true +csharp_style_prefer_index_operator = true +csharp_style_prefer_local_over_anonymous_function = true +csharp_style_prefer_null_check_over_type_check = true +csharp_style_prefer_range_operator = true +csharp_style_prefer_tuple_swap = true +csharp_style_prefer_unbound_generic_type_in_nameof = true +csharp_style_prefer_utf8_string_literals = true +csharp_style_throw_expression = true +csharp_style_unused_value_assignment_preference = discard_variable +csharp_style_unused_value_expression_statement_preference = discard_variable + +# 'using' ディレクティブの基本設定 +csharp_using_directive_placement = outside_namespace + +# 改行設定 +csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true +csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true +csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true +csharp_style_allow_blank_lines_between_consecutive_braces_experimental = false +csharp_style_allow_embedded_statements_on_same_line_experimental = true + +#### C# 書式ルール #### + +# 改行設定 +csharp_new_line_before_catch = true +csharp_new_line_before_else = true +csharp_new_line_before_finally = true +csharp_new_line_before_members_in_anonymous_types = true +csharp_new_line_before_members_in_object_initializers = true +csharp_new_line_before_open_brace = all +csharp_new_line_between_query_expression_clauses = true + +# インデント設定 +csharp_indent_block_contents = true +csharp_indent_braces = false +csharp_indent_case_contents = true +csharp_indent_case_contents_when_block = false +csharp_indent_labels = one_less_than_current +csharp_indent_switch_labels = true + +# スペース設定 +csharp_space_after_cast = false +csharp_space_after_colon_in_inheritance_clause = true +csharp_space_after_comma = true +csharp_space_after_dot = false +csharp_space_after_keywords_in_control_flow_statements = true +csharp_space_after_semicolon_in_for_statement = true +csharp_space_around_binary_operators = before_and_after +csharp_space_around_declaration_statements = false +csharp_space_before_colon_in_inheritance_clause = true +csharp_space_before_comma = false +csharp_space_before_dot = false +csharp_space_before_open_square_brackets = false +csharp_space_before_semicolon_in_for_statement = false +csharp_space_between_empty_square_brackets = false +csharp_space_between_method_call_empty_parameter_list_parentheses = false +csharp_space_between_method_call_name_and_opening_parenthesis = false +csharp_space_between_method_call_parameter_list_parentheses = false +csharp_space_between_method_declaration_empty_parameter_list_parentheses = false +csharp_space_between_method_declaration_name_and_open_parenthesis = true +csharp_space_between_method_declaration_parameter_list_parentheses = false +csharp_space_between_parentheses = false +csharp_space_between_square_brackets = false + +# 折り返しの設定 +csharp_preserve_single_line_blocks = true +csharp_preserve_single_line_statements = false + +#### 命名スタイル #### + +# 名前付けルール + +dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion +dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface +dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i + +dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.types_should_be_pascal_case.symbols = types +dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.const_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.const_should_be_pascal_case.symbols = const +dotnet_naming_rule.const_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.static_readonly_field_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.static_readonly_field_should_be_pascal_case.symbols = static_readonly_field +dotnet_naming_rule.static_readonly_field_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion +dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members +dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case + +dotnet_naming_rule.private_or_internal_field_should_be_camel_case.severity = suggestion +dotnet_naming_rule.private_or_internal_field_should_be_camel_case.symbols = private_or_internal_field +dotnet_naming_rule.private_or_internal_field_should_be_camel_case.style = camel_case + +dotnet_naming_rule.public_or_protected_field_should_be_camel_case.severity = suggestion +dotnet_naming_rule.public_or_protected_field_should_be_camel_case.symbols = public_or_protected_field +dotnet_naming_rule.public_or_protected_field_should_be_camel_case.style = camel_case + +# 記号の仕様 + +dotnet_naming_symbols.interface.applicable_kinds = interface +dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.interface.required_modifiers = + +dotnet_naming_symbols.public_or_protected_field.applicable_kinds = field +dotnet_naming_symbols.public_or_protected_field.applicable_accessibilities = public, protected +dotnet_naming_symbols.public_or_protected_field.required_modifiers = + +dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field +dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected +dotnet_naming_symbols.private_or_internal_field.required_modifiers = + +dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum +dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.types.required_modifiers = + +dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method +dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected +dotnet_naming_symbols.non_field_members.required_modifiers = + +dotnet_naming_symbols.const.applicable_kinds = field +dotnet_naming_symbols.const.applicable_accessibilities = * +dotnet_naming_symbols.const.required_modifiers = const + +dotnet_naming_symbols.static_readonly_field.applicable_kinds = field +dotnet_naming_symbols.static_readonly_field.applicable_accessibilities = * +dotnet_naming_symbols.static_readonly_field.required_modifiers = readonly, static + +# 命名スタイル + +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.capitalization = pascal_case + +dotnet_naming_style.begins_with_i.required_prefix = I +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.capitalization = pascal_case + +dotnet_naming_style.camel_case.required_prefix = +dotnet_naming_style.camel_case.required_suffix = +dotnet_naming_style.camel_case.word_separator = +dotnet_naming_style.camel_case.capitalization = camel_case diff --git a/Assets/Example/Example.cs b/Assets/Example/Example.cs index 94a7acc..f043780 100644 --- a/Assets/Example/Example.cs +++ b/Assets/Example/Example.cs @@ -1,94 +1,94 @@ -using System.Collections.Generic; using System; +using System.Collections.Generic; using UnityEditor; using UnityEngine; [Serializable] public abstract class Food { - public string name; + public string name; - public float kcal; + public float kcal; } [Serializable] public class Apple : Food { - public Apple () - { - name = "Apple"; - kcal = 100f; - } + public Apple () + { + name = "Apple"; + kcal = 100f; + } } [Serializable] public class Peach : Food { - public Peach () - { - name = "Peach"; - kcal = 100f; - } + public Peach () + { + name = "Peach"; + kcal = 100f; + } } [Serializable] public class Grape : Food { - public Grape () - { - name = "Grape"; - kcal = 100f; - } + public Grape () + { + name = "Grape"; + kcal = 100f; + } } [Serializable] [HideInTypeMenu] public class Banana : Food { - public Banana () - { - name = "Banana"; - kcal = 100f; - } + public Banana () + { + name = "Banana"; + kcal = 100f; + } } public class Example : MonoBehaviour { - [SerializeReference] - public Food food1 = new Apple(); + [SerializeReference] + public Food food1 = new Apple(); - [SerializeReference] - public Food food2 = new Peach(); + [SerializeReference] + public Food food2 = new Peach(); - [SerializeReference] - public Food food3 = new Grape(); + [SerializeReference] + public Food food3 = new Grape(); - [SerializeReference, SubclassSelector] - public Food foodOne = new Apple(); + [SerializeReference, SubclassSelector] + public Food foodOne = new Apple(); - [SerializeReference, SubclassSelector] - public Food foodTwo = new Peach(); + [SerializeReference, SubclassSelector] + public Food foodTwo = new Peach(); - // UseToStringAsLabel support on UNITY_2021_3_OR_NEWER - [SerializeReference, SubclassSelector(UseToStringAsLabel = true)] - public Food foodThree = new Grape(); + // UseToStringAsLabel support on UNITY_2021_3_OR_NEWER + [SerializeReference, SubclassSelector(UseToStringAsLabel = true)] + public Food foodThree = new Grape(); - [SerializeReference] - public List foodsOne = new List - { - new Apple(), - new Peach(), - new Grape() - }; + [SerializeReference] + public List foodsOne = new List + { + new Apple(), + new Peach(), + new Grape() + }; - [SerializeReference, SubclassSelector] - public List foodsTwo = new List - { - new Apple(), - new Peach(), - new Grape() - }; + [SerializeReference, SubclassSelector] + public List foodsTwo = new List + { + new Apple(), + new Peach(), + new Grape() + }; } #if UNITY_EDITOR @@ -98,32 +98,32 @@ public class Example : MonoBehaviour [CustomPropertyDrawer(typeof(Peach), true)] public class PeachDrawer : PropertyDrawer { - public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) - { - position.height = EditorGUIUtility.singleLineHeight; - EditorGUI.PropertyField(position, property.FindPropertyRelative("name")); - - position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - EditorGUI.PropertyField(position, property.FindPropertyRelative("kcal")); - } - - public override float GetPropertyHeight (SerializedProperty property, GUIContent label) - { - return EditorGUIUtility.singleLineHeight * 2 + EditorGUIUtility.standardVerticalSpacing * 1; - } + public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) + { + position.height = EditorGUIUtility.singleLineHeight; + EditorGUI.PropertyField(position, property.FindPropertyRelative("name")); + + position.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + EditorGUI.PropertyField(position, property.FindPropertyRelative("kcal")); + } + + public override float GetPropertyHeight (SerializedProperty property, GUIContent label) + { + return EditorGUIUtility.singleLineHeight * 2 + EditorGUIUtility.standardVerticalSpacing * 1; + } } [CustomPropertyDrawer(typeof(Apple), true)] public class AppleDrawer : PropertyDrawer { - public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) - { - EditorGUI.LabelField(position, "I'm an apple!"); - } - - public override float GetPropertyHeight (SerializedProperty property, GUIContent label) - { - return EditorGUIUtility.singleLineHeight; - } + public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) + { + EditorGUI.LabelField(position, "I'm an apple!"); + } + + public override float GetPropertyHeight (SerializedProperty property, GUIContent label) + { + return EditorGUIUtility.singleLineHeight; + } } #endif \ No newline at end of file diff --git a/Assets/Example/Example_Generics.cs b/Assets/Example/Example_Generics.cs index f94145e..450eb66 100644 --- a/Assets/Example/Example_Generics.cs +++ b/Assets/Example/Example_Generics.cs @@ -6,13 +6,14 @@ public interface IActor { } public interface IStandardActor : IActor { } public interface INetworkActor : IActor { } -public interface IContravarianceAction where T : IActor { - void DoAction (T actor); +public interface IContravarianceAction where T : IActor +{ + void DoAction (T actor); } public interface ICovarianceAction where T : IActor { - T Actor { get; } + T Actor { get; } } public interface IActorAction : IContravarianceAction, ICovarianceAction { } @@ -22,27 +23,28 @@ public interface INetworkActorAction : IContravarianceAction, ICo [Serializable] public sealed class StandardActorAction : IContravarianceAction, ICovarianceAction { - public void DoAction (IStandardActor actor) - { - } - public IStandardActor Actor => null; + public void DoAction (IStandardActor actor) + { + } + public IStandardActor Actor => null; } [Serializable] public sealed class ActorAction : IContravarianceAction, ICovarianceAction { - public void DoAction (IActor actor) - { - } - public IActor Actor => null; + public void DoAction (IActor actor) + { + } + public IActor Actor => null; } [Serializable] public abstract class BaseAction : IContravarianceAction, ICovarianceAction where T : IActor { - public void DoAction (T actor) { - } - public T Actor => default; + public void DoAction (T actor) + { + } + public T Actor => default; } [Serializable] @@ -57,43 +59,43 @@ public sealed class DerivedAction3 : BaseAction { } [Serializable] public sealed class NetworkActorAction1 : INetworkActorAction { - public void DoAction (INetworkActor actor) - { - } - public INetworkActor Actor => null; + public void DoAction (INetworkActor actor) + { + } + public INetworkActor Actor => null; } [Serializable] public sealed class NetworkActorAction2 : IContravarianceAction, ICovarianceAction { - public void DoAction (INetworkActor actor) - { - } - public INetworkActor Actor => null; + public void DoAction (INetworkActor actor) + { + } + public INetworkActor Actor => null; } [Serializable] public sealed class NetworkActorAction3 : IContravarianceAction, ICovarianceAction { - public void DoAction (IActor actor) - { - } - public IActor Actor => null; + public void DoAction (IActor actor) + { + } + public IActor Actor => null; } public class Example_Generics : MonoBehaviour { - [SerializeReference, SubclassSelector] - public IContravarianceAction contravarianceAction = null; + [SerializeReference, SubclassSelector] + public IContravarianceAction contravarianceAction = null; [SerializeReference, SubclassSelector] - public BaseAction baseAction = null; + public BaseAction baseAction = null; [SerializeReference, SubclassSelector] - public List> contravarianceActions = new List>(); + public List> contravarianceActions = new List>(); - [SerializeReference, SubclassSelector] - public List> covarianceActions = new List>(); + [SerializeReference, SubclassSelector] + public List> covarianceActions = new List>(); } diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/AdvancedTypePopup.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/AdvancedTypePopup.cs index 04f769e..49ed756 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/AdvancedTypePopup.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/AdvancedTypePopup.cs @@ -1,139 +1,168 @@ using System; -using System.Linq; using System.Collections.Generic; -using UnityEngine; +using System.Linq; using UnityEditor; using UnityEditor.IMGUI.Controls; +using UnityEngine; -namespace MackySoft.SerializeReferenceExtensions.Editor { - - public class AdvancedTypePopupItem : AdvancedDropdownItem { - - public Type Type { get; } - - public AdvancedTypePopupItem (Type type,string name) : base(name) { - Type = type; - } - - } - - /// - /// A type popup with a fuzzy finder. - /// - public class AdvancedTypePopup : AdvancedDropdown { - - const int kMaxNamespaceNestCount = 16; - - public static void AddTo (AdvancedDropdownItem root,IEnumerable types) { - int itemCount = 0; - - // Add null item. - var nullItem = new AdvancedTypePopupItem(null,TypeMenuUtility.k_NullDisplayName) { - id = itemCount++ - }; - root.AddChild(nullItem); - - Type[] typeArray = types.OrderByType().ToArray(); - - // Single namespace if the root has one namespace and the nest is unbranched. - bool isSingleNamespace = true; - string[] namespaces = new string[kMaxNamespaceNestCount]; - foreach (Type type in typeArray) { - string[] splittedTypePath = TypeMenuUtility.GetSplittedTypePath(type); - if (splittedTypePath.Length <= 1) { - continue; - } - // If they explicitly want sub category, let them do. - if (TypeMenuUtility.GetAttribute(type) != null) { - isSingleNamespace = false; - break; - } - for (int k = 0;(splittedTypePath.Length - 1) > k;k++) { - string ns = namespaces[k]; - if (ns == null) { - namespaces[k] = splittedTypePath[k]; - } - else if (ns != splittedTypePath[k]) { - isSingleNamespace = false; - break; - } - } - - if (!isSingleNamespace) { - break; - } - } - - // Add type items. - foreach (Type type in typeArray) { - string[] splittedTypePath = TypeMenuUtility.GetSplittedTypePath(type); - if (splittedTypePath.Length == 0) { - continue; - } - - AdvancedDropdownItem parent = root; - - // Add namespace items. - if (!isSingleNamespace) { - for (int k = 0;(splittedTypePath.Length - 1) > k;k++) { - AdvancedDropdownItem foundItem = GetItem(parent,splittedTypePath[k]); - if (foundItem != null) { - parent = foundItem; - } - else { - var newItem = new AdvancedDropdownItem(splittedTypePath[k]) { - id = itemCount++, - }; - parent.AddChild(newItem); - parent = newItem; - } - } - } - - // Add type item. - var item = new AdvancedTypePopupItem(type,ObjectNames.NicifyVariableName(splittedTypePath[splittedTypePath.Length - 1])) { - id = itemCount++ - }; - parent.AddChild(item); - } - } - - static AdvancedDropdownItem GetItem (AdvancedDropdownItem parent,string name) { - foreach (AdvancedDropdownItem item in parent.children) { - if (item.name == name) { - return item; - } - } - return null; - } - - static readonly float k_HeaderHeight = EditorGUIUtility.singleLineHeight * 2f; - - Type[] m_Types; - - public event Action OnItemSelected; - - public AdvancedTypePopup (IEnumerable types,int maxLineCount,AdvancedDropdownState state) : base(state) { - SetTypes(types); - minimumSize = new Vector2(minimumSize.x,EditorGUIUtility.singleLineHeight * maxLineCount + k_HeaderHeight); - } - - public void SetTypes (IEnumerable types) { - m_Types = types.ToArray(); - } - - protected override AdvancedDropdownItem BuildRoot () { - var root = new AdvancedDropdownItem("Select Type"); - AddTo(root,m_Types); - return root; - } - - protected override void ItemSelected (AdvancedDropdownItem item) { - base.ItemSelected(item); - if (item is AdvancedTypePopupItem typePopupItem) { - OnItemSelected?.Invoke(typePopupItem); - } - } - - } +namespace MackySoft.SerializeReferenceExtensions.Editor +{ + + public class AdvancedTypePopupItem : AdvancedDropdownItem + { + + public Type Type { get; } + + public AdvancedTypePopupItem (Type type, string name) : base(name) + { + Type = type; + } + + } + + /// + /// A type popup with a fuzzy finder. + /// + public class AdvancedTypePopup : AdvancedDropdown + { + + private const int MaxNamespaceNestCount = 16; + + public static void AddTo (AdvancedDropdownItem root, IEnumerable types) + { + int itemCount = 0; + + // Add null item. + var nullItem = new AdvancedTypePopupItem(null, TypeMenuUtility.NullDisplayName) + { + id = itemCount++ + }; + root.AddChild(nullItem); + + Type[] typeArray = types.OrderByType().ToArray(); + + // Single namespace if the root has one namespace and the nest is unbranched. + bool isSingleNamespace = true; + string[] namespaces = new string[MaxNamespaceNestCount]; + foreach (Type type in typeArray) + { + string[] splittedTypePath = TypeMenuUtility.GetSplittedTypePath(type); + if (splittedTypePath.Length <= 1) + { + continue; + } + // If they explicitly want sub category, let them do. + if (TypeMenuUtility.GetAttribute(type) != null) + { + isSingleNamespace = false; + break; + } + for (int k = 0; (splittedTypePath.Length - 1) > k; k++) + { + string ns = namespaces[k]; + if (ns == null) + { + namespaces[k] = splittedTypePath[k]; + } + else if (ns != splittedTypePath[k]) + { + isSingleNamespace = false; + break; + } + } + + if (!isSingleNamespace) + { + break; + } + } + + // Add type items. + foreach (Type type in typeArray) + { + string[] splittedTypePath = TypeMenuUtility.GetSplittedTypePath(type); + if (splittedTypePath.Length == 0) + { + continue; + } + + AdvancedDropdownItem parent = root; + + // Add namespace items. + if (!isSingleNamespace) + { + for (int k = 0; (splittedTypePath.Length - 1) > k; k++) + { + AdvancedDropdownItem foundItem = GetItem(parent, splittedTypePath[k]); + if (foundItem != null) + { + parent = foundItem; + } + else + { + var newItem = new AdvancedDropdownItem(splittedTypePath[k]) + { + id = itemCount++, + }; + parent.AddChild(newItem); + parent = newItem; + } + } + } + + // Add type item. + var item = new AdvancedTypePopupItem(type, ObjectNames.NicifyVariableName(splittedTypePath[splittedTypePath.Length - 1])) + { + id = itemCount++ + }; + parent.AddChild(item); + } + } + + private static AdvancedDropdownItem GetItem (AdvancedDropdownItem parent, string name) + { + foreach (AdvancedDropdownItem item in parent.children) + { + if (item.name == name) + { + return item; + } + } + return null; + } + + private static readonly float HeaderHeight = EditorGUIUtility.singleLineHeight * 2f; + + private Type[] types; + + public event Action OnItemSelected; + + public AdvancedTypePopup (IEnumerable types, int maxLineCount, AdvancedDropdownState state) : base(state) + { + SetTypes(types); + minimumSize = new Vector2(minimumSize.x, EditorGUIUtility.singleLineHeight * maxLineCount + HeaderHeight); + } + + public void SetTypes (IEnumerable types) + { + this.types = types.ToArray(); + } + + protected override AdvancedDropdownItem BuildRoot () + { + var root = new AdvancedDropdownItem("Select Type"); + AddTo(root, types); + return root; + } + + protected override void ItemSelected (AdvancedDropdownItem item) + { + base.ItemSelected(item); + if (item is AdvancedTypePopupItem typePopupItem) + { + OnItemSelected?.Invoke(typePopupItem); + } + } + + } } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceContextualPropertyMenu.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceContextualPropertyMenu.cs index 837f1c3..d7547f8 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceContextualPropertyMenu.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceContextualPropertyMenu.cs @@ -6,102 +6,102 @@ namespace MackySoft.SerializeReferenceExtensions.Editor { - public static class ManagedReferenceContextualPropertyMenu - { - - const string kCopiedPropertyPathKey = "SerializeReferenceExtensions.CopiedPropertyPath"; - const string kClipboardKey = "SerializeReferenceExtensions.CopyAndPasteProperty"; - - static readonly GUIContent kPasteContent = new GUIContent("Paste Property"); - static readonly GUIContent kNewInstanceContent = new GUIContent("New Instance"); - static readonly GUIContent kResetAndNewInstanceContent = new GUIContent("Reset and New Instance"); - - [InitializeOnLoadMethod] - static void Initialize () - { - EditorApplication.contextualPropertyMenu += OnContextualPropertyMenu; - } - - static void OnContextualPropertyMenu (GenericMenu menu, SerializedProperty property) - { - if (property.propertyType == SerializedPropertyType.ManagedReference) - { - // NOTE: When the callback function is called, the SerializedProperty is rewritten to the property that was being moused over at the time, - // so a new SerializedProperty instance must be created. - SerializedProperty clonedProperty = property.Copy(); - - menu.AddItem(new GUIContent($"Copy \"{property.propertyPath}\" property"), false, Copy, clonedProperty); - - string copiedPropertyPath = SessionState.GetString(kCopiedPropertyPathKey, string.Empty); - if (!string.IsNullOrEmpty(copiedPropertyPath)) - { - menu.AddItem(new GUIContent($"Paste \"{copiedPropertyPath}\" property"), false, Paste, clonedProperty); - } - else - { - menu.AddDisabledItem(kPasteContent); - } - - menu.AddSeparator(""); - - bool hasInstance = clonedProperty.managedReferenceValue != null; - if (hasInstance) - { - menu.AddItem(kNewInstanceContent, false, NewInstance, clonedProperty); - menu.AddItem(kResetAndNewInstanceContent, false, ResetAndNewInstance, clonedProperty); - } - else - { - menu.AddDisabledItem(kNewInstanceContent); - menu.AddDisabledItem(kResetAndNewInstanceContent); - } - } - } - - static void Copy (object customData) - { - SerializedProperty property = (SerializedProperty)customData; - string json = JsonUtility.ToJson(property.managedReferenceValue); - SessionState.SetString(kCopiedPropertyPathKey, property.propertyPath); - SessionState.SetString(kClipboardKey, json); - } - - static void Paste (object customData) - { - SerializedProperty property = (SerializedProperty)customData; - string json = SessionState.GetString(kClipboardKey, string.Empty); - if (string.IsNullOrEmpty(json)) - { - return; - } - - Undo.RecordObject(property.serializedObject.targetObject, "Paste Property"); - JsonUtility.FromJsonOverwrite(json, property.managedReferenceValue); - property.serializedObject.ApplyModifiedProperties(); - } - - static void NewInstance (object customData) - { - SerializedProperty property = (SerializedProperty)customData; - string json = JsonUtility.ToJson(property.managedReferenceValue); - - Undo.RecordObject(property.serializedObject.targetObject, "New Instance"); - property.managedReferenceValue = JsonUtility.FromJson(json, property.managedReferenceValue.GetType()); - property.serializedObject.ApplyModifiedProperties(); - - Debug.Log($"Create new instance of \"{property.propertyPath}\"."); - } - - static void ResetAndNewInstance (object customData) - { - SerializedProperty property = (SerializedProperty)customData; - - Undo.RecordObject(property.serializedObject.targetObject, "Reset and New Instance"); - property.managedReferenceValue = Activator.CreateInstance(property.managedReferenceValue.GetType()); - property.serializedObject.ApplyModifiedProperties(); - - Debug.Log($"Reset property and created new instance of \"{property.propertyPath}\"."); - } - } + public static class ManagedReferenceContextualPropertyMenu + { + + private const string CopiedPropertyPathKey = "SerializeReferenceExtensions.CopiedPropertyPath"; + private const string ClipboardKey = "SerializeReferenceExtensions.CopyAndPasteProperty"; + + private static readonly GUIContent PasteContent = new GUIContent("Paste Property"); + private static readonly GUIContent NewInstanceContent = new GUIContent("New Instance"); + private static readonly GUIContent ResetAndNewInstanceContent = new GUIContent("Reset and New Instance"); + + [InitializeOnLoadMethod] + private static void Initialize () + { + EditorApplication.contextualPropertyMenu += OnContextualPropertyMenu; + } + + private static void OnContextualPropertyMenu (GenericMenu menu, SerializedProperty property) + { + if (property.propertyType == SerializedPropertyType.ManagedReference) + { + // NOTE: When the callback function is called, the SerializedProperty is rewritten to the property that was being moused over at the time, + // so a new SerializedProperty instance must be created. + SerializedProperty clonedProperty = property.Copy(); + + menu.AddItem(new GUIContent($"Copy \"{property.propertyPath}\" property"), false, Copy, clonedProperty); + + string copiedPropertyPath = SessionState.GetString(CopiedPropertyPathKey, string.Empty); + if (!string.IsNullOrEmpty(copiedPropertyPath)) + { + menu.AddItem(new GUIContent($"Paste \"{copiedPropertyPath}\" property"), false, Paste, clonedProperty); + } + else + { + menu.AddDisabledItem(PasteContent); + } + + menu.AddSeparator(""); + + bool hasInstance = clonedProperty.managedReferenceValue != null; + if (hasInstance) + { + menu.AddItem(NewInstanceContent, false, NewInstance, clonedProperty); + menu.AddItem(ResetAndNewInstanceContent, false, ResetAndNewInstance, clonedProperty); + } + else + { + menu.AddDisabledItem(NewInstanceContent); + menu.AddDisabledItem(ResetAndNewInstanceContent); + } + } + } + + private static void Copy (object customData) + { + SerializedProperty property = (SerializedProperty)customData; + string json = JsonUtility.ToJson(property.managedReferenceValue); + SessionState.SetString(CopiedPropertyPathKey, property.propertyPath); + SessionState.SetString(ClipboardKey, json); + } + + private static void Paste (object customData) + { + SerializedProperty property = (SerializedProperty)customData; + string json = SessionState.GetString(ClipboardKey, string.Empty); + if (string.IsNullOrEmpty(json)) + { + return; + } + + Undo.RecordObject(property.serializedObject.targetObject, "Paste Property"); + JsonUtility.FromJsonOverwrite(json, property.managedReferenceValue); + property.serializedObject.ApplyModifiedProperties(); + } + + private static void NewInstance (object customData) + { + SerializedProperty property = (SerializedProperty)customData; + string json = JsonUtility.ToJson(property.managedReferenceValue); + + Undo.RecordObject(property.serializedObject.targetObject, "New Instance"); + property.managedReferenceValue = JsonUtility.FromJson(json, property.managedReferenceValue.GetType()); + property.serializedObject.ApplyModifiedProperties(); + + Debug.Log($"Create new instance of \"{property.propertyPath}\"."); + } + + private static void ResetAndNewInstance (object customData) + { + SerializedProperty property = (SerializedProperty)customData; + + Undo.RecordObject(property.serializedObject.targetObject, "Reset and New Instance"); + property.managedReferenceValue = Activator.CreateInstance(property.managedReferenceValue.GetType()); + property.serializedObject.ApplyModifiedProperties(); + + Debug.Log($"Reset property and created new instance of \"{property.propertyPath}\"."); + } + } } #endif \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceUtility.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceUtility.cs index 646b9f2..dda4bd1 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceUtility.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/ManagedReferenceUtility.cs @@ -6,41 +6,44 @@ namespace MackySoft.SerializeReferenceExtensions.Editor { - public static class ManagedReferenceUtility { + public static class ManagedReferenceUtility + { - public static object SetManagedReference (this SerializedProperty property,Type type) { - object result = null; + public static object SetManagedReference (this SerializedProperty property, Type type) + { + object result = null; #if UNITY_2021_3_OR_NEWER - // NOTE: managedReferenceValue getter is available only in Unity 2021.3 or later. - if ((type != null) && (property.managedReferenceValue != null)) - { - // Restore an previous values from json. - string json = JsonUtility.ToJson(property.managedReferenceValue); - result = JsonUtility.FromJson(json, type); - } + // NOTE: managedReferenceValue getter is available only in Unity 2021.3 or later. + if ((type != null) && (property.managedReferenceValue != null)) + { + // Restore an previous values from json. + string json = JsonUtility.ToJson(property.managedReferenceValue); + result = JsonUtility.FromJson(json, type); + } #endif - if (result == null) - { - result = (type != null) ? Activator.CreateInstance(type) : null; - } - - property.managedReferenceValue = result; - return result; + if (result == null) + { + result = (type != null) ? Activator.CreateInstance(type) : null; + } - } + property.managedReferenceValue = result; + return result; - public static Type GetType (string typeName) { - if (string.IsNullOrEmpty(typeName)) - { - return null; - } + } - int splitIndex = typeName.IndexOf(' '); - var assembly = Assembly.Load(typeName.Substring(0,splitIndex)); - return assembly.GetType(typeName.Substring(splitIndex + 1)); - } + public static Type GetType (string typeName) + { + if (string.IsNullOrEmpty(typeName)) + { + return null; + } - } + int splitIndex = typeName.IndexOf(' '); + var assembly = Assembly.Load(typeName.Substring(0, splitIndex)); + return assembly.GetType(typeName.Substring(splitIndex + 1)); + } + + } } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/PropertyDrawerCache.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/PropertyDrawerCache.cs index 9a1cbe2..868413f 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/PropertyDrawerCache.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/PropertyDrawerCache.cs @@ -1,80 +1,80 @@ using System; using System.Collections.Generic; -using UnityEditor; using System.Reflection; +using UnityEditor; namespace MackySoft.SerializeReferenceExtensions.Editor { - public static class PropertyDrawerCache - { + public static class PropertyDrawerCache + { + + private static readonly Dictionary Caches = new Dictionary(); - static readonly Dictionary s_Caches = new Dictionary(); + public static bool TryGetPropertyDrawer (Type type, out PropertyDrawer drawer) + { + if (!Caches.TryGetValue(type, out drawer)) + { + Type drawerType = GetCustomPropertyDrawerType(type); + drawer = (drawerType != null) ? (PropertyDrawer)Activator.CreateInstance(drawerType) : null; - public static bool TryGetPropertyDrawer (Type type,out PropertyDrawer drawer) - { - if (!s_Caches.TryGetValue(type,out drawer)) - { - Type drawerType = GetCustomPropertyDrawerType(type); - drawer = (drawerType != null) ? (PropertyDrawer)Activator.CreateInstance(drawerType) : null; + Caches.Add(type, drawer); + } + return (drawer != null); + } - s_Caches.Add(type, drawer); - } - return (drawer != null); - } + private static Type GetCustomPropertyDrawerType (Type type) + { + Type[] interfaceTypes = type.GetInterfaces(); - static Type GetCustomPropertyDrawerType (Type type) - { - Type[] interfaceTypes = type.GetInterfaces(); + var types = TypeCache.GetTypesWithAttribute(); + foreach (Type drawerType in types) + { + var customPropertyDrawerAttributes = drawerType.GetCustomAttributes(typeof(CustomPropertyDrawer), true); + foreach (CustomPropertyDrawer customPropertyDrawer in customPropertyDrawerAttributes) + { + var field = customPropertyDrawer.GetType().GetField("m_Type", BindingFlags.NonPublic | BindingFlags.Instance); + if (field != null) + { + var fieldType = field.GetValue(customPropertyDrawer) as Type; + if (fieldType != null) + { + if (fieldType == type) + { + return drawerType; + } - var types = TypeCache.GetTypesWithAttribute(); - foreach (Type drawerType in types) - { - var customPropertyDrawerAttributes = drawerType.GetCustomAttributes(typeof(CustomPropertyDrawer), true); - foreach (CustomPropertyDrawer customPropertyDrawer in customPropertyDrawerAttributes) - { - var field = customPropertyDrawer.GetType().GetField("m_Type", BindingFlags.NonPublic | BindingFlags.Instance); - if (field != null) - { - var fieldType = field.GetValue(customPropertyDrawer) as Type; - if (fieldType != null) - { - if (fieldType == type) - { - return drawerType; - } - - // If the property drawer also allows for being applied to child classes, check if they match - var useForChildrenField = customPropertyDrawer.GetType().GetField("m_UseForChildren", BindingFlags.NonPublic | BindingFlags.Instance); - if (useForChildrenField != null) - { - object useForChildrenValue = useForChildrenField.GetValue(customPropertyDrawer); - if (useForChildrenValue is bool && (bool)useForChildrenValue) - { - // Check interfaces - if (Array.Exists(interfaceTypes, interfaceType => interfaceType == fieldType)) - { - return drawerType; - } + // If the property drawer also allows for being applied to child classes, check if they match + var useForChildrenField = customPropertyDrawer.GetType().GetField("m_UseForChildren", BindingFlags.NonPublic | BindingFlags.Instance); + if (useForChildrenField != null) + { + object useForChildrenValue = useForChildrenField.GetValue(customPropertyDrawer); + if (useForChildrenValue is bool && (bool)useForChildrenValue) + { + // Check interfaces + if (Array.Exists(interfaceTypes, interfaceType => interfaceType == fieldType)) + { + return drawerType; + } - // Check derived types - Type baseType = type.BaseType; - while (baseType != null) - { - if (baseType == fieldType) - { - return drawerType; - } + // Check derived types + Type baseType = type.BaseType; + while (baseType != null) + { + if (baseType == fieldType) + { + return drawerType; + } - baseType = baseType.BaseType; - } - } - } - } - } - } - } - return null; - } + baseType = baseType.BaseType; + } + } + } + } + } + } + } + return null; + } - } + } } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SerializedPropertyExtensions.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SerializedPropertyExtensions.cs index b26177e..75316bc 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SerializedPropertyExtensions.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SerializedPropertyExtensions.cs @@ -3,27 +3,27 @@ namespace MackySoft.SerializeReferenceExtensions.Editor { - public static class SerializedPropertyExtensions - { - public static IEnumerable GetChildProperties (this SerializedProperty parent, int depth = 1) - { - parent = parent.Copy(); + public static class SerializedPropertyExtensions + { + public static IEnumerable GetChildProperties (this SerializedProperty parent, int depth = 1) + { + parent = parent.Copy(); - int depthOfParent = parent.depth; - var enumerator = parent.GetEnumerator(); + int depthOfParent = parent.depth; + var enumerator = parent.GetEnumerator(); - while (enumerator.MoveNext()) - { - if (enumerator.Current is not SerializedProperty childProperty) - { - continue; - } - if (childProperty.depth > (depthOfParent + depth)) - { - continue; - } - yield return childProperty.Copy(); - } - } - } + while (enumerator.MoveNext()) + { + if (enumerator.Current is not SerializedProperty childProperty) + { + continue; + } + if (childProperty.depth > (depthOfParent + depth)) + { + continue; + } + yield return childProperty.Copy(); + } + } + } } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SubclassSelectorDrawer.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SubclassSelectorDrawer.cs index 2bc890d..1d711b2 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SubclassSelectorDrawer.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/SubclassSelectorDrawer.cs @@ -1,224 +1,237 @@ using System; -using System.Linq; using System.Collections.Generic; -using UnityEngine; using UnityEditor; using UnityEditor.IMGUI.Controls; +using UnityEngine; namespace MackySoft.SerializeReferenceExtensions.Editor { - [CustomPropertyDrawer(typeof(SubclassSelectorAttribute))] - public class SubclassSelectorDrawer : PropertyDrawer { + [CustomPropertyDrawer(typeof(SubclassSelectorAttribute))] + public class SubclassSelectorDrawer : PropertyDrawer + { + + private struct TypePopupCache + { + public AdvancedTypePopup TypePopup { get; } + public AdvancedDropdownState State { get; } + public TypePopupCache (AdvancedTypePopup typePopup, AdvancedDropdownState state) + { + TypePopup = typePopup; + State = state; + } + } - struct TypePopupCache { - public AdvancedTypePopup TypePopup { get; } - public AdvancedDropdownState State { get; } - public TypePopupCache (AdvancedTypePopup typePopup,AdvancedDropdownState state) { - TypePopup = typePopup; - State = state; - } - } + private const int MaxTypePopupLineCount = 13; - const int k_MaxTypePopupLineCount = 13; - - static readonly GUIContent k_NullDisplayName = new GUIContent(TypeMenuUtility.k_NullDisplayName); - static readonly GUIContent k_IsNotManagedReferenceLabel = new GUIContent("The property type is not manage reference."); + private static readonly GUIContent NullDisplayName = new GUIContent(TypeMenuUtility.NullDisplayName); + private static readonly GUIContent IsNotManagedReferenceLabel = new GUIContent("The property type is not manage reference."); - readonly Dictionary m_TypePopups = new Dictionary(); - readonly Dictionary m_TypeNameCaches = new Dictionary(); + private readonly Dictionary typePopups = new Dictionary(); + private readonly Dictionary typeNameCaches = new Dictionary(); - SerializedProperty m_TargetProperty; + private SerializedProperty targetProperty; - public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) - { - EditorGUI.BeginProperty(position, label, property); + public override void OnGUI (Rect position, SerializedProperty property, GUIContent label) + { + EditorGUI.BeginProperty(position, label, property); - if (property.propertyType == SerializedPropertyType.ManagedReference) - { - // Render label first to avoid label overlap for lists - Rect foldoutLabelRect = new Rect(position); - foldoutLabelRect.height = EditorGUIUtility.singleLineHeight; + if (property.propertyType == SerializedPropertyType.ManagedReference) + { + // Render label first to avoid label overlap for lists + Rect foldoutLabelRect = new Rect(position); + foldoutLabelRect.height = EditorGUIUtility.singleLineHeight; - // NOTE: IndentedRect should be disabled as it causes extra indentation. - //foldoutLabelRect = EditorGUI.IndentedRect(foldoutLabelRect); - Rect popupPosition = EditorGUI.PrefixLabel(foldoutLabelRect, label); + // NOTE: IndentedRect should be disabled as it causes extra indentation. + //foldoutLabelRect = EditorGUI.IndentedRect(foldoutLabelRect); + Rect popupPosition = EditorGUI.PrefixLabel(foldoutLabelRect, label); #if UNITY_2021_3_OR_NEWER - // Override the label text with the ToString() of the managed reference. - var subclassSelectorAttribute = (SubclassSelectorAttribute)attribute; - if (subclassSelectorAttribute.UseToStringAsLabel && !property.hasMultipleDifferentValues) - { - object managedReferenceValue = property.managedReferenceValue; - if (managedReferenceValue != null) - { - label.text = managedReferenceValue.ToString(); - } - } + // Override the label text with the ToString() of the managed reference. + var subclassSelectorAttribute = (SubclassSelectorAttribute)attribute; + if (subclassSelectorAttribute.UseToStringAsLabel && !property.hasMultipleDifferentValues) + { + object managedReferenceValue = property.managedReferenceValue; + if (managedReferenceValue != null) + { + label.text = managedReferenceValue.ToString(); + } + } #endif - // Draw the subclass selector popup. - if (EditorGUI.DropdownButton(popupPosition, GetTypeName(property), FocusType.Keyboard)) - { - TypePopupCache popup = GetTypePopup(property); - m_TargetProperty = property; - popup.TypePopup.Show(popupPosition); - } + // Draw the subclass selector popup. + if (EditorGUI.DropdownButton(popupPosition, GetTypeName(property), FocusType.Keyboard)) + { + TypePopupCache popup = GetTypePopup(property); + targetProperty = property; + popup.TypePopup.Show(popupPosition); + } - // Draw the foldout. - if (!string.IsNullOrEmpty(property.managedReferenceFullTypename)) - { - Rect foldoutRect = new Rect(position); - foldoutRect.height = EditorGUIUtility.singleLineHeight; + // Draw the foldout. + if (!string.IsNullOrEmpty(property.managedReferenceFullTypename)) + { + Rect foldoutRect = new Rect(position); + foldoutRect.height = EditorGUIUtility.singleLineHeight; #if UNITY_2022_2_OR_NEWER && !UNITY_6000_0_OR_NEWER && !UNITY_2022_3 - // NOTE: Position x must be adjusted. - // FIXME: Is there a more essential solution...? - // The most promising is UI Toolkit, but it is currently unable to reproduce all of SubclassSelector features. (Complete provision of contextual menu, e.g.) - // 2021.3: No adjustment - // 2022.1: No adjustment - // 2022.2: Adjustment required - // 2022.3: Adjustment required - // 2023.1: Adjustment required - // 2023.2: Adjustment required - // 6000.0: No adjustment - foldoutRect.x -= 12; + // NOTE: Position x must be adjusted. + // FIXME: Is there a more essential solution...? + // The most promising is UI Toolkit, but it is currently unable to reproduce all of SubclassSelector features. (Complete provision of contextual menu, e.g.) + // 2021.3: No adjustment + // 2022.1: No adjustment + // 2022.2: Adjustment required + // 2022.3: Adjustment required + // 2023.1: Adjustment required + // 2023.2: Adjustment required + // 6000.0: No adjustment + foldoutRect.x -= 12; #endif property.isExpanded = EditorGUI.Foldout(foldoutRect, property.isExpanded, GUIContent.none, true); - } - - // Draw property if expanded. - if (property.isExpanded) - { - using (new EditorGUI.IndentLevelScope()) - { - // Check if a custom property drawer exists for this type. - PropertyDrawer customDrawer = GetCustomPropertyDrawer(property); - if (customDrawer != null) - { - // Draw the property with custom property drawer. - Rect indentedRect = position; - float foldoutDifference = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - indentedRect.height = customDrawer.GetPropertyHeight(property, label); - indentedRect.y += foldoutDifference; - customDrawer.OnGUI(indentedRect, property, label); - } - else - { - // Draw the properties of the child elements. - // NOTE: In the following code, since the foldout layout isn't working properly, I'll iterate through the properties of the child elements myself. - // EditorGUI.PropertyField(position, property, GUIContent.none, true); - - Rect childPosition = position; - childPosition.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; - foreach (SerializedProperty childProperty in property.GetChildProperties()) - { - float height = EditorGUI.GetPropertyHeight(childProperty, new GUIContent(childProperty.displayName, childProperty.tooltip), true); - childPosition.height = height; - EditorGUI.PropertyField(childPosition, childProperty, true); - - childPosition.y += height + EditorGUIUtility.standardVerticalSpacing; - } - } - } - } - } - else - { - EditorGUI.LabelField(position, label, k_IsNotManagedReferenceLabel); - } - - EditorGUI.EndProperty(); - } - - PropertyDrawer GetCustomPropertyDrawer (SerializedProperty property) - { - Type propertyType = ManagedReferenceUtility.GetType(property.managedReferenceFullTypename); - if (propertyType != null && PropertyDrawerCache.TryGetPropertyDrawer(propertyType, out PropertyDrawer drawer)) - { - return drawer; - } - return null; - } - - TypePopupCache GetTypePopup (SerializedProperty property) { - // Cache this string. This property internally call Assembly.GetName, which result in a large allocation. - string managedReferenceFieldTypename = property.managedReferenceFieldTypename; - - if (!m_TypePopups.TryGetValue(managedReferenceFieldTypename,out TypePopupCache result)) { - var state = new AdvancedDropdownState(); - - Type baseType = ManagedReferenceUtility.GetType(managedReferenceFieldTypename); - var types = TypeSearchService.TypeCandiateService.GetDisplayableTypes(baseType); + } + + // Draw property if expanded. + if (property.isExpanded) + { + using (new EditorGUI.IndentLevelScope()) + { + // Check if a custom property drawer exists for this type. + PropertyDrawer customDrawer = GetCustomPropertyDrawer(property); + if (customDrawer != null) + { + // Draw the property with custom property drawer. + Rect indentedRect = position; + float foldoutDifference = EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + indentedRect.height = customDrawer.GetPropertyHeight(property, label); + indentedRect.y += foldoutDifference; + customDrawer.OnGUI(indentedRect, property, label); + } + else + { + // Draw the properties of the child elements. + // NOTE: In the following code, since the foldout layout isn't working properly, I'll iterate through the properties of the child elements myself. + // EditorGUI.PropertyField(position, property, GUIContent.none, true); + + Rect childPosition = position; + childPosition.y += EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing; + foreach (SerializedProperty childProperty in property.GetChildProperties()) + { + float height = EditorGUI.GetPropertyHeight(childProperty, new GUIContent(childProperty.displayName, childProperty.tooltip), true); + childPosition.height = height; + EditorGUI.PropertyField(childPosition, childProperty, true); + + childPosition.y += height + EditorGUIUtility.standardVerticalSpacing; + } + } + } + } + } + else + { + EditorGUI.LabelField(position, label, IsNotManagedReferenceLabel); + } + + EditorGUI.EndProperty(); + } + + private PropertyDrawer GetCustomPropertyDrawer (SerializedProperty property) + { + Type propertyType = ManagedReferenceUtility.GetType(property.managedReferenceFullTypename); + if (propertyType != null && PropertyDrawerCache.TryGetPropertyDrawer(propertyType, out PropertyDrawer drawer)) + { + return drawer; + } + return null; + } + + private TypePopupCache GetTypePopup (SerializedProperty property) + { + // Cache this string. This property internally call Assembly.GetName, which result in a large allocation. + string managedReferenceFieldTypename = property.managedReferenceFieldTypename; + + if (!typePopups.TryGetValue(managedReferenceFieldTypename, out TypePopupCache result)) + { + var state = new AdvancedDropdownState(); + + Type baseType = ManagedReferenceUtility.GetType(managedReferenceFieldTypename); + var types = TypeSearchService.TypeCandiateService.GetDisplayableTypes(baseType); var popup = new AdvancedTypePopup( types, - k_MaxTypePopupLineCount, - state - ); - popup.OnItemSelected += item => { - Type type = item.Type; - - // Apply changes to individual serialized objects. - foreach (var targetObject in m_TargetProperty.serializedObject.targetObjects) { - SerializedObject individualObject = new SerializedObject(targetObject); - SerializedProperty individualProperty = individualObject.FindProperty(m_TargetProperty.propertyPath); - object obj = individualProperty.SetManagedReference(type); - individualProperty.isExpanded = (obj != null); - - individualObject.ApplyModifiedProperties(); - individualObject.Update(); - } - }; - - result = new TypePopupCache(popup, state); - m_TypePopups.Add(managedReferenceFieldTypename, result); - } - return result; - } - - GUIContent GetTypeName (SerializedProperty property) { - // Cache this string. - string managedReferenceFullTypename = property.managedReferenceFullTypename; - - if (string.IsNullOrEmpty(managedReferenceFullTypename)) { - return k_NullDisplayName; - } - if (m_TypeNameCaches.TryGetValue(managedReferenceFullTypename,out GUIContent cachedTypeName)) { - return cachedTypeName; - } - - Type type = ManagedReferenceUtility.GetType(managedReferenceFullTypename); - string typeName = null; - - AddTypeMenuAttribute typeMenu = TypeMenuUtility.GetAttribute(type); - if (typeMenu != null) { - typeName = typeMenu.GetTypeNameWithoutPath(); - if (!string.IsNullOrWhiteSpace(typeName)) { - typeName = ObjectNames.NicifyVariableName(typeName); - } - } - - if (string.IsNullOrWhiteSpace(typeName)) { - typeName = ObjectNames.NicifyVariableName(type.Name); - } - - GUIContent result = new GUIContent(typeName); - m_TypeNameCaches.Add(managedReferenceFullTypename,result); - return result; - } - - public override float GetPropertyHeight (SerializedProperty property,GUIContent label) { - PropertyDrawer customDrawer = GetCustomPropertyDrawer(property); - if (customDrawer != null) - { - return property.isExpanded ? EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing + customDrawer.GetPropertyHeight(property,label):EditorGUIUtility.singleLineHeight; - } - else - { - return property.isExpanded ? EditorGUI.GetPropertyHeight(property,true) : EditorGUIUtility.singleLineHeight; - } - } - - } + MaxTypePopupLineCount, + state + ); + popup.OnItemSelected += item => + { + Type type = item.Type; + + // Apply changes to individual serialized objects. + foreach (var targetObject in targetProperty.serializedObject.targetObjects) + { + SerializedObject individualObject = new SerializedObject(targetObject); + SerializedProperty individualProperty = individualObject.FindProperty(targetProperty.propertyPath); + object obj = individualProperty.SetManagedReference(type); + individualProperty.isExpanded = (obj != null); + + individualObject.ApplyModifiedProperties(); + individualObject.Update(); + } + }; + + result = new TypePopupCache(popup, state); + typePopups.Add(managedReferenceFieldTypename, result); + } + return result; + } + + private GUIContent GetTypeName (SerializedProperty property) + { + // Cache this string. + string managedReferenceFullTypename = property.managedReferenceFullTypename; + + if (string.IsNullOrEmpty(managedReferenceFullTypename)) + { + return NullDisplayName; + } + if (typeNameCaches.TryGetValue(managedReferenceFullTypename, out GUIContent cachedTypeName)) + { + return cachedTypeName; + } + + Type type = ManagedReferenceUtility.GetType(managedReferenceFullTypename); + string typeName = null; + + AddTypeMenuAttribute typeMenu = TypeMenuUtility.GetAttribute(type); + if (typeMenu != null) + { + typeName = typeMenu.GetTypeNameWithoutPath(); + if (!string.IsNullOrWhiteSpace(typeName)) + { + typeName = ObjectNames.NicifyVariableName(typeName); + } + } + + if (string.IsNullOrWhiteSpace(typeName)) + { + typeName = ObjectNames.NicifyVariableName(type.Name); + } + + GUIContent result = new GUIContent(typeName); + typeNameCaches.Add(managedReferenceFullTypename, result); + return result; + } + + public override float GetPropertyHeight (SerializedProperty property, GUIContent label) + { + PropertyDrawer customDrawer = GetCustomPropertyDrawer(property); + if (customDrawer != null) + { + return property.isExpanded ? EditorGUIUtility.singleLineHeight + EditorGUIUtility.standardVerticalSpacing + customDrawer.GetPropertyHeight(property, label) : EditorGUIUtility.singleLineHeight; + } + else + { + return property.isExpanded ? EditorGUI.GetPropertyHeight(property, true) : EditorGUIUtility.singleLineHeight; + } + } + + } } diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeMenuUtility.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeMenuUtility.cs index 354d9d4..497ca62 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeMenuUtility.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeMenuUtility.cs @@ -1,45 +1,59 @@ using System; -using System.Linq; using System.Collections.Generic; +using System.Linq; using UnityEditor; namespace MackySoft.SerializeReferenceExtensions.Editor { - public static class TypeMenuUtility { + public static class TypeMenuUtility + { - public const string k_NullDisplayName = ""; + public const string NullDisplayName = ""; - public static AddTypeMenuAttribute GetAttribute (Type type) { - return Attribute.GetCustomAttribute(type,typeof(AddTypeMenuAttribute)) as AddTypeMenuAttribute; - } + public static AddTypeMenuAttribute GetAttribute (Type type) + { + return Attribute.GetCustomAttribute(type, typeof(AddTypeMenuAttribute)) as AddTypeMenuAttribute; + } - public static string[] GetSplittedTypePath (Type type) { - AddTypeMenuAttribute typeMenu = GetAttribute(type); - if (typeMenu != null) { - return typeMenu.GetSplittedMenuName(); - } else { - int splitIndex = type.FullName.LastIndexOf('.'); - if (splitIndex >= 0) { - return new string[] { type.FullName.Substring(0,splitIndex),type.FullName.Substring(splitIndex + 1) }; - } else { - return new string[] { type.Name }; - } - } - } + public static string[] GetSplittedTypePath (Type type) + { + AddTypeMenuAttribute typeMenu = GetAttribute(type); + if (typeMenu != null) + { + return typeMenu.GetSplittedMenuName(); + } + else + { + int splitIndex = type.FullName.LastIndexOf('.'); + if (splitIndex >= 0) + { + return new string[] { type.FullName.Substring(0, splitIndex), type.FullName.Substring(splitIndex + 1) }; + } + else + { + return new string[] { type.Name }; + } + } + } - public static IEnumerable OrderByType (this IEnumerable source) { - return source.OrderBy(type => { - if (type == null) { - return -999; - } - return GetAttribute(type)?.Order ?? 0; - }).ThenBy(type => { - if (type == null) { - return null; - } - return GetAttribute(type)?.MenuName ?? type.Name; - }); - } + public static IEnumerable OrderByType (this IEnumerable source) + { + return source.OrderBy(type => + { + if (type == null) + { + return -999; + } + return GetAttribute(type)?.Order ?? 0; + }).ThenBy(type => + { + if (type == null) + { + return null; + } + return GetAttribute(type)?.MenuName ?? type.Name; + }); + } - } + } } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/ITypeCandiateProvider.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/ITypeCandiateProvider.cs index ea65b44..8c340f3 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/ITypeCandiateProvider.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/ITypeCandiateProvider.cs @@ -4,7 +4,7 @@ namespace MackySoft.SerializeReferenceExtensions.Editor { public interface ITypeCandiateProvider - { - IEnumerable GetTypeCandidates (Type baseType); + { + IEnumerable GetTypeCandidates (Type baseType); } } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCandiateProvider/Unity_2023_2_OrNewer_TypeCandiateProvider.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCandiateProvider/Unity_2023_2_OrNewer_TypeCandiateProvider.cs index 07831e6..4ed3c3c 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCandiateProvider/Unity_2023_2_OrNewer_TypeCandiateProvider.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCandiateProvider/Unity_2023_2_OrNewer_TypeCandiateProvider.cs @@ -13,18 +13,18 @@ public sealed class Unity_2023_2_OrNewer_TypeCandiateProvider : ITypeCandiatePro Unity_2023_2_OrNewer_GenericVarianceTypeCompatibilityPolicy.Instance ); - private Dictionary> m_TypeCache = new Dictionary>(); + private readonly Dictionary> typeCache = new Dictionary>(); - private readonly IIntrinsicTypePolicy m_IntrinsicTypePolicy; - private readonly ITypeCompatibilityPolicy m_TypeCompatibilityPolicy; + private readonly IIntrinsicTypePolicy intrinsicTypePolicy; + private readonly ITypeCompatibilityPolicy typeCompatibilityPolicy; private Unity_2023_2_OrNewer_TypeCandiateProvider ( IIntrinsicTypePolicy intrinsicTypePolicy, ITypeCompatibilityPolicy typeCompatibilityPolicy ) { - m_IntrinsicTypePolicy = intrinsicTypePolicy ?? throw new ArgumentNullException(nameof(intrinsicTypePolicy)); - m_TypeCompatibilityPolicy = typeCompatibilityPolicy ?? throw new ArgumentNullException(nameof(typeCompatibilityPolicy)); + this.intrinsicTypePolicy = intrinsicTypePolicy ?? throw new ArgumentNullException(nameof(intrinsicTypePolicy)); + this.typeCompatibilityPolicy = typeCompatibilityPolicy ?? throw new ArgumentNullException(nameof(typeCompatibilityPolicy)); } public IEnumerable GetTypeCandidates (Type baseType) @@ -39,7 +39,7 @@ public IEnumerable GetTypeCandidates (Type baseType) private IEnumerable GetTypesWithGeneric (Type baseType) { - if (m_TypeCache.TryGetValue(baseType, out List result)) + if (typeCache.TryGetValue(baseType, out List result)) { return result; } @@ -49,11 +49,11 @@ private IEnumerable GetTypesWithGeneric (Type baseType) IEnumerable types = EnumerateAllTypesSafely(); foreach (Type type in types) { - if (!m_IntrinsicTypePolicy.IsAllowed(type)) + if (!intrinsicTypePolicy.IsAllowed(type)) { continue; } - if (!m_TypeCompatibilityPolicy.IsCompatible(baseType, type)) + if (!typeCompatibilityPolicy.IsCompatible(baseType, type)) { continue; } @@ -62,12 +62,12 @@ private IEnumerable GetTypesWithGeneric (Type baseType) } // Include the base type itself if allowed - if (m_IntrinsicTypePolicy.IsAllowed(baseType) && m_TypeCompatibilityPolicy.IsCompatible(baseType, baseType)) + if (intrinsicTypePolicy.IsAllowed(baseType) && typeCompatibilityPolicy.IsCompatible(baseType, baseType)) { result.Add(baseType); } - m_TypeCache.Add(baseType, result); + typeCache.Add(baseType, result); return result; } diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCompatibilityPolicy/DefaultTypeCompatibilityPolicy.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCompatibilityPolicy/DefaultTypeCompatibilityPolicy.cs index 8b80dac..28eb044 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCompatibilityPolicy/DefaultTypeCompatibilityPolicy.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Editor/TypeSearch/TypeCompatibilityPolicy/DefaultTypeCompatibilityPolicy.cs @@ -6,7 +6,7 @@ public sealed class DefaultTypeCompatibilityPolicy : ITypeCompatibilityPolicy { public static readonly DefaultTypeCompatibilityPolicy Instance = new DefaultTypeCompatibilityPolicy(); - + public bool IsCompatible (Type baseType, Type candiateType) { if (baseType == null) diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/AddTypeMenuAttribute.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/AddTypeMenuAttribute.cs index 9f36c1e..19b33eb 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/AddTypeMenuAttribute.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/AddTypeMenuAttribute.cs @@ -1,35 +1,39 @@ using System; - + /// /// An attribute that overrides the name of the type displayed in the SubclassSelector popup. /// -[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface,AllowMultiple = false,Inherited = false)] -public sealed class AddTypeMenuAttribute : Attribute { - - public string MenuName { get; } - - public int Order { get; } - - public AddTypeMenuAttribute (string menuName,int order = 0) { - MenuName = menuName; - Order = order; - } - - static readonly char[] k_Separeters = new char[] { '/' }; - - /// - /// Returns the menu name split by the '/' separator. - /// - public string[] GetSplittedMenuName () { - return !string.IsNullOrWhiteSpace(MenuName) ? MenuName.Split(k_Separeters,StringSplitOptions.RemoveEmptyEntries) : Array.Empty(); - } - - /// - /// Returns the display name without the path. - /// - public string GetTypeNameWithoutPath () { - string[] splittedDisplayName = GetSplittedMenuName(); - return (splittedDisplayName.Length != 0) ? splittedDisplayName[splittedDisplayName.Length - 1] : null; - } +[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)] +public sealed class AddTypeMenuAttribute : Attribute +{ + + public string MenuName { get; } + + public int Order { get; } + + public AddTypeMenuAttribute (string menuName, int order = 0) + { + MenuName = menuName; + Order = order; + } + + private static readonly char[] k_Separeters = new char[] { '/' }; + + /// + /// Returns the menu name split by the '/' separator. + /// + public string[] GetSplittedMenuName () + { + return !string.IsNullOrWhiteSpace(MenuName) ? MenuName.Split(k_Separeters, StringSplitOptions.RemoveEmptyEntries) : Array.Empty(); + } + + /// + /// Returns the display name without the path. + /// + public string GetTypeNameWithoutPath () + { + string[] splittedDisplayName = GetSplittedMenuName(); + return (splittedDisplayName.Length != 0) ? splittedDisplayName[splittedDisplayName.Length - 1] : null; + } } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/HideInTypeMenuAttribute.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/HideInTypeMenuAttribute.cs index 0809014..589feb0 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/HideInTypeMenuAttribute.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/HideInTypeMenuAttribute.cs @@ -4,6 +4,7 @@ /// An attribute that hides the type in the SubclassSelector. /// [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Interface, AllowMultiple = false, Inherited = false)] -public sealed class HideInTypeMenuAttribute : Attribute { +public sealed class HideInTypeMenuAttribute : Attribute +{ } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/SubclassSelectorAttribute.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/SubclassSelectorAttribute.cs index ad78e8f..7c14288 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/SubclassSelectorAttribute.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Runtime/SubclassSelectorAttribute.cs @@ -9,8 +9,8 @@ public sealed class SubclassSelectorAttribute : PropertyAttribute { #if UNITY_2021_3_OR_NEWER - // NOTE: Use managedReferenceValue getter to invoke instance method in SubclassSelectorDrawer. - public bool UseToStringAsLabel { get; set; } + // NOTE: Use managedReferenceValue getter to invoke instance method in SubclassSelectorDrawer. + public bool UseToStringAsLabel { get; set; } #endif } \ No newline at end of file diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateService_NonGenericTests.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateService_NonGenericTests.cs index d677fbb..ea28b68 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateService_NonGenericTests.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateService_NonGenericTests.cs @@ -1,5 +1,4 @@ using System; -using System.CodeDom; using System.Collections.Generic; using System.Linq; using MackySoft.SerializeReferenceExtensions.Editor; diff --git a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateTestTypes.cs b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateTestTypes.cs index b3e1ce3..f73c113 100644 --- a/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateTestTypes.cs +++ b/Assets/MackySoft/MackySoft.SerializeReferenceExtensions/Tests/Editor/TypeCandidateTestTypes.cs @@ -1,5 +1,4 @@ using System; -using System.Collections; using System.Reflection; using UnityEngine; @@ -72,17 +71,20 @@ public sealed class Contravariant_NetworkActor : IContravariant { public sealed class Contravariant_DerivedNetworkActor : IContravariant { } [Serializable] - public sealed class Covariant_Actor : ICovariant { + public sealed class Covariant_Actor : ICovariant + { public IActor Create () => null; } [Serializable] - public sealed class Covariant_NetworkActor : ICovariant { + public sealed class Covariant_NetworkActor : ICovariant + { public INetworkActor Create () => null; } - + [Serializable] - public sealed class Covariant_Object : ICovariant { + public sealed class Covariant_Object : ICovariant + { public object Create () => null; }