Browse Source

C#: Add grouping attributes for properties.

Zae 3 years ago
parent
commit
431a28fe19

+ 3 - 0
modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs

@@ -5,6 +5,9 @@ namespace Godot.SourceGenerators
         public const string Object = "Godot.Object";
         public const string Object = "Godot.Object";
         public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
         public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
         public const string ExportAttr = "Godot.ExportAttribute";
         public const string ExportAttr = "Godot.ExportAttribute";
+        public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
+        public const string ExportGroupAttr = "Godot.ExportGroupAttribute";
+        public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute";
         public const string SignalAttr = "Godot.SignalAttribute";
         public const string SignalAttr = "Godot.SignalAttribute";
         public const string GodotClassNameAttr = "Godot.GodotClassName";
         public const string GodotClassNameAttr = "Godot.GodotClassName";
         public const string SystemFlagsAttr = "System.FlagsAttribute";
         public const string SystemFlagsAttr = "System.FlagsAttribute";

+ 49 - 0
modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs

@@ -1,3 +1,4 @@
+using System.Collections.Generic;
 using System.Linq;
 using System.Linq;
 using System.Text;
 using System.Text;
 using Microsoft.CodeAnalysis;
 using Microsoft.CodeAnalysis;
@@ -226,6 +227,9 @@ namespace Godot.SourceGenerators
 
 
                 foreach (var property in godotClassProperties)
                 foreach (var property in godotClassProperties)
                 {
                 {
+                    foreach (var groupingInfo in DetermineGroupingPropertyInfo(property.PropertySymbol))
+                        AppendGroupingPropertyInfo(source, groupingInfo);
+
                     var propertyInfo = DeterminePropertyInfo(context, typeCache,
                     var propertyInfo = DeterminePropertyInfo(context, typeCache,
                         property.PropertySymbol, property.Type);
                         property.PropertySymbol, property.Type);
 
 
@@ -237,6 +241,10 @@ namespace Godot.SourceGenerators
 
 
                 foreach (var field in godotClassFields)
                 foreach (var field in godotClassFields)
                 {
                 {
+
+                    foreach (var groupingInfo in DetermineGroupingPropertyInfo(field.FieldSymbol))
+                        AppendGroupingPropertyInfo(source, groupingInfo);
+
                     var propertyInfo = DeterminePropertyInfo(context, typeCache,
                     var propertyInfo = DeterminePropertyInfo(context, typeCache,
                         field.FieldSymbol, field.Type);
                         field.FieldSymbol, field.Type);
 
 
@@ -321,6 +329,21 @@ namespace Godot.SourceGenerators
                 .Append("        }\n");
                 .Append("        }\n");
         }
         }
 
 
+        private static void AppendGroupingPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
+        {
+            source.Append("        properties.Add(new(type: (Godot.Variant.Type)")
+                .Append((int)VariantType.Nil)
+                .Append(", name: \"")
+                .Append(propertyInfo.Name)
+                .Append("\", hint: (Godot.PropertyHint)")
+                .Append((int)PropertyHint.None)
+                .Append(", hintString: \"")
+                .Append(propertyInfo.HintString)
+                .Append("\", usage: (Godot.PropertyUsageFlags)")
+                .Append((int)propertyInfo.Usage)
+                .Append(", exported: true));\n");
+        }
+
         private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
         private static void AppendPropertyInfo(StringBuilder source, PropertyInfo propertyInfo)
         {
         {
             source.Append("        properties.Add(new(type: (Godot.Variant.Type)")
             source.Append("        properties.Add(new(type: (Godot.Variant.Type)")
@@ -338,6 +361,32 @@ namespace Godot.SourceGenerators
                 .Append("));\n");
                 .Append("));\n");
         }
         }
 
 
+        private static IEnumerable<PropertyInfo> DetermineGroupingPropertyInfo(ISymbol memberSymbol)
+        {
+            foreach (var attr in memberSymbol.GetAttributes())
+            {
+                PropertyUsageFlags? propertyUsage = attr.AttributeClass?.ToString() switch
+                {
+                    GodotClasses.ExportCategoryAttr => PropertyUsageFlags.Category,
+                    GodotClasses.ExportGroupAttr => PropertyUsageFlags.Group,
+                    GodotClasses.ExportSubgroupAttr => PropertyUsageFlags.Subgroup,
+                    _ => null
+                };
+
+                if (propertyUsage is null)
+                    continue;
+
+                if (attr.ConstructorArguments.Length > 0 && attr.ConstructorArguments[0].Value is string name)
+                {
+                    string? hintString = null;
+                    if (propertyUsage != PropertyUsageFlags.Category && attr.ConstructorArguments.Length > 1)
+                        hintString = attr.ConstructorArguments[1].Value?.ToString();
+
+                    yield return new PropertyInfo(VariantType.Nil, name, PropertyHint.None, hintString, propertyUsage.Value, true);
+                }
+            }
+        }
+
         private static PropertyInfo? DeterminePropertyInfo(
         private static PropertyInfo? DeterminePropertyInfo(
             GeneratorExecutionContext context,
             GeneratorExecutionContext context,
             MarshalUtils.TypeCache typeCache,
             MarshalUtils.TypeCache typeCache,

+ 22 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportCategoryAttribute.cs

@@ -0,0 +1,22 @@
+using System;
+
+namespace Godot
+{
+    /// <summary>
+    /// Define a new category for the following exported properties. This helps to organize properties in the Inspector dock.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
+    public sealed class ExportCategoryAttribute : Attribute
+    {
+        private string name;
+
+        /// <summary>
+        /// Define a new category for the following exported properties.
+        /// </summary>
+        /// <param name="name">The name of the category.</param>
+        public ExportCategoryAttribute(string name)
+        {
+            this.name = name;
+        }
+    }
+}

+ 25 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportGroupAttribute.cs

@@ -0,0 +1,25 @@
+using System;
+
+namespace Godot
+{
+    /// <summary>
+    /// Define a new group for the following exported properties. This helps to organize properties in the Inspector dock.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
+    public sealed class ExportGroupAttribute : Attribute
+    {
+        private string name;
+        private string prefix;
+
+        /// <summary>
+        /// Define a new group for the following exported properties.
+        /// </summary>
+        /// <param name="name">The name of the group.</param>
+        /// <param name="prefix">If provided, the group would make group to only consider properties that have this prefix.</param>
+        public ExportGroupAttribute(string name, string prefix = "")
+        {
+            this.name = name;
+            this.prefix = prefix;
+        }
+    }
+}

+ 25 - 0
modules/mono/glue/GodotSharp/GodotSharp/Core/Attributes/ExportSubgroupAttribute.cs

@@ -0,0 +1,25 @@
+using System;
+
+namespace Godot
+{
+    /// <summary>
+    /// Define a new subgroup for the following exported properties. This helps to organize properties in the Inspector dock.
+    /// </summary>
+    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
+    public sealed class ExportSubgroupAttribute : Attribute
+    {
+        private string name;
+        private string prefix;
+
+        /// <summary>
+        /// Define a new subgroup for the following exported properties. This helps to organize properties in the Inspector dock.
+        /// </summary>
+        /// <param name="name">The name of the subgroup.</param>
+        /// <param name="prefix">If provided, the subgroup would make group to only consider properties that have this prefix.</param>
+        public ExportSubgroupAttribute(string name, string prefix = "")
+        {
+            this.name = name;
+            this.prefix = prefix;
+        }
+    }
+}

+ 3 - 0
modules/mono/glue/GodotSharp/GodotSharp/GodotSharp.csproj

@@ -53,6 +53,9 @@
     <Compile Include="Core\Array.cs" />
     <Compile Include="Core\Array.cs" />
     <Compile Include="Core\Attributes\AssemblyHasScriptsAttribute.cs" />
     <Compile Include="Core\Attributes\AssemblyHasScriptsAttribute.cs" />
     <Compile Include="Core\Attributes\ExportAttribute.cs" />
     <Compile Include="Core\Attributes\ExportAttribute.cs" />
+    <Compile Include="Core\Attributes\ExportCategoryAttribute.cs" />
+    <Compile Include="Core\Attributes\ExportGroupAttribute.cs" />
+    <Compile Include="Core\Attributes\ExportSubgroupAttribute.cs" />
     <Compile Include="Core\Attributes\RPCAttribute.cs" />
     <Compile Include="Core\Attributes\RPCAttribute.cs" />
     <Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
     <Compile Include="Core\Attributes\ScriptPathAttribute.cs" />
     <Compile Include="Core\Attributes\SignalAttribute.cs" />
     <Compile Include="Core\Attributes\SignalAttribute.cs" />