mirror of
https://github.com/godotengine/godot.git
synced 2024-11-21 19:42:43 +00:00
Implement [ExportToolButton]
This commit is contained in:
parent
db66bd35af
commit
4f52c2bb1f
@ -74,4 +74,31 @@ public class ExportDiagnosticsTests
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ExportToolButtonInNonToolClass()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||||
|
new string[] { "ExportDiagnostics_GD0108.cs" },
|
||||||
|
new string[] { "ExportDiagnostics_GD0108_ScriptProperties.generated.cs" }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ExportAndExportToolButtonOnSameMember()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||||
|
new string[] { "ExportDiagnostics_GD0109.cs" },
|
||||||
|
new string[] { "ExportDiagnostics_GD0109_ScriptProperties.generated.cs" }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ExportToolButtonOnNonCallable()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||||
|
new string[] { "ExportDiagnostics_GD0110.cs" },
|
||||||
|
new string[] { "ExportDiagnostics_GD0110_ScriptProperties.generated.cs" }
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,4 +66,13 @@ public class ScriptPropertiesGeneratorTests
|
|||||||
"AbstractGenericNode(Of T)_ScriptProperties.generated.cs"
|
"AbstractGenericNode(Of T)_ScriptProperties.generated.cs"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ExportedButtons()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertiesGenerator>.Verify(
|
||||||
|
"ExportedToolButtons.cs",
|
||||||
|
"ExportedToolButtons_ScriptProperties.generated.cs"
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
partial class ExportDiagnostics_GD0108
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||||
|
/// <summary>
|
||||||
|
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||||
|
/// </summary>
|
||||||
|
public new class PropertyName : global::Godot.Node.PropertyName {
|
||||||
|
/// <summary>
|
||||||
|
/// Cached name for the 'MyButton' field.
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly global::Godot.StringName @MyButton = "MyButton";
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
|
||||||
|
{
|
||||||
|
if (name == PropertyName.@MyButton) {
|
||||||
|
this.@MyButton = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.SetGodotClassPropertyValue(name, value);
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||||
|
{
|
||||||
|
if (name == PropertyName.@MyButton) {
|
||||||
|
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.GetGodotClassPropertyValue(name, out value);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Get the property information for all the properties declared in this class.
|
||||||
|
/// This method is used by Godot to register the available properties in the editor.
|
||||||
|
/// Do not call this method.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||||
|
{
|
||||||
|
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
#pragma warning restore CS0109
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
partial class ExportDiagnostics_GD0109
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||||
|
/// <summary>
|
||||||
|
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||||
|
/// </summary>
|
||||||
|
public new class PropertyName : global::Godot.Node.PropertyName {
|
||||||
|
/// <summary>
|
||||||
|
/// Cached name for the 'MyButton' field.
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly global::Godot.StringName @MyButton = "MyButton";
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
|
||||||
|
{
|
||||||
|
if (name == PropertyName.@MyButton) {
|
||||||
|
this.@MyButton = global::Godot.NativeInterop.VariantUtils.ConvertTo<global::Godot.Callable>(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.SetGodotClassPropertyValue(name, value);
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||||
|
{
|
||||||
|
if (name == PropertyName.@MyButton) {
|
||||||
|
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.GetGodotClassPropertyValue(name, out value);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Get the property information for all the properties declared in this class.
|
||||||
|
/// This method is used by Godot to register the available properties in the editor.
|
||||||
|
/// Do not call this method.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||||
|
{
|
||||||
|
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
#pragma warning restore CS0109
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
partial class ExportDiagnostics_GD0110
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||||
|
/// <summary>
|
||||||
|
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||||
|
/// </summary>
|
||||||
|
public new class PropertyName : global::Godot.Node.PropertyName {
|
||||||
|
/// <summary>
|
||||||
|
/// Cached name for the 'MyButton' field.
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly global::Godot.StringName @MyButton = "MyButton";
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
protected override bool SetGodotClassPropertyValue(in godot_string_name name, in godot_variant value)
|
||||||
|
{
|
||||||
|
if (name == PropertyName.@MyButton) {
|
||||||
|
this.@MyButton = global::Godot.NativeInterop.VariantUtils.ConvertTo<string>(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.SetGodotClassPropertyValue(name, value);
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||||
|
{
|
||||||
|
if (name == PropertyName.@MyButton) {
|
||||||
|
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<string>(this.@MyButton);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.GetGodotClassPropertyValue(name, out value);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Get the property information for all the properties declared in this class.
|
||||||
|
/// This method is used by Godot to register the available properties in the editor.
|
||||||
|
/// Do not call this method.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||||
|
{
|
||||||
|
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
#pragma warning restore CS0109
|
||||||
|
}
|
@ -0,0 +1,48 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.NativeInterop;
|
||||||
|
|
||||||
|
partial class ExportedToolButtons
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||||
|
/// <summary>
|
||||||
|
/// Cached StringNames for the properties and fields contained in this class, for fast lookup.
|
||||||
|
/// </summary>
|
||||||
|
public new class PropertyName : global::Godot.GodotObject.PropertyName {
|
||||||
|
/// <summary>
|
||||||
|
/// Cached name for the 'MyButton1' property.
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly global::Godot.StringName @MyButton1 = "MyButton1";
|
||||||
|
/// <summary>
|
||||||
|
/// Cached name for the 'MyButton2' property.
|
||||||
|
/// </summary>
|
||||||
|
public new static readonly global::Godot.StringName @MyButton2 = "MyButton2";
|
||||||
|
}
|
||||||
|
/// <inheritdoc/>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
protected override bool GetGodotClassPropertyValue(in godot_string_name name, out godot_variant value)
|
||||||
|
{
|
||||||
|
if (name == PropertyName.@MyButton1) {
|
||||||
|
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (name == PropertyName.@MyButton2) {
|
||||||
|
value = global::Godot.NativeInterop.VariantUtils.CreateFrom<global::Godot.Callable>(this.@MyButton2);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return base.GetGodotClassPropertyValue(name, out value);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Get the property information for all the properties declared in this class.
|
||||||
|
/// This method is used by Godot to register the available properties in the editor.
|
||||||
|
/// Do not call this method.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
internal new static global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo> GetGodotPropertyList()
|
||||||
|
{
|
||||||
|
var properties = new global::System.Collections.Generic.List<global::Godot.Bridge.PropertyInfo>();
|
||||||
|
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButton1, hint: (global::Godot.PropertyHint)39, hintString: "Click me!", usage: (global::Godot.PropertyUsageFlags)4, exported: true));
|
||||||
|
properties.Add(new(type: (global::Godot.Variant.Type)25, name: PropertyName.@MyButton2, hint: (global::Godot.PropertyHint)39, hintString: "Click me!,ColorRect", usage: (global::Godot.PropertyUsageFlags)4, exported: true));
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
#pragma warning restore CS0109
|
||||||
|
}
|
@ -0,0 +1,8 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.Collections;
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0108 : Node
|
||||||
|
{
|
||||||
|
[ExportToolButton("")]
|
||||||
|
public Callable {|GD0108:MyButton|};
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.Collections;
|
||||||
|
|
||||||
|
[Tool]
|
||||||
|
public partial class ExportDiagnostics_GD0109 : Node
|
||||||
|
{
|
||||||
|
[Export, ExportToolButton("")]
|
||||||
|
public Callable {|GD0109:MyButton|};
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
using Godot;
|
||||||
|
using Godot.Collections;
|
||||||
|
|
||||||
|
[Tool]
|
||||||
|
public partial class ExportDiagnostics_GD0110 : Node
|
||||||
|
{
|
||||||
|
[ExportToolButton("")]
|
||||||
|
public string {|GD0110:MyButton|};
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
using Godot;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
[Tool]
|
||||||
|
public partial class ExportedToolButtons : GodotObject
|
||||||
|
{
|
||||||
|
[ExportToolButton("Click me!")]
|
||||||
|
public Callable MyButton1 => Callable.From(() => { GD.Print("Clicked MyButton1!"); });
|
||||||
|
|
||||||
|
[ExportToolButton("Click me!", Icon = "ColorRect")]
|
||||||
|
public Callable MyButton2 => Callable.From(() => { GD.Print("Clicked MyButton2!"); });
|
||||||
|
}
|
@ -3,3 +3,6 @@
|
|||||||
Rule ID | Category | Severity | Notes
|
Rule ID | Category | Severity | Notes
|
||||||
--------|----------|----------|--------------------
|
--------|----------|----------|--------------------
|
||||||
GD0003 | Usage | Error | ScriptPathAttributeGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0003.html)
|
GD0003 | Usage | Error | ScriptPathAttributeGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0003.html)
|
||||||
|
GD0108 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0108.html)
|
||||||
|
GD0109 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0109.html)
|
||||||
|
GD0110 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0110.html)
|
||||||
|
@ -107,6 +107,36 @@ namespace Godot.SourceGenerators
|
|||||||
"Types not derived from Node should not export Node members. Node export is only supported in Node-derived classes.",
|
"Types not derived from Node should not export Node members. Node export is only supported in Node-derived classes.",
|
||||||
helpLinkUri: string.Format(_helpLinkFormat, "GD0107"));
|
helpLinkUri: string.Format(_helpLinkFormat, "GD0107"));
|
||||||
|
|
||||||
|
public static readonly DiagnosticDescriptor OnlyToolClassesShouldUseExportToolButtonRule =
|
||||||
|
new DiagnosticDescriptor(id: "GD0108",
|
||||||
|
title: "The exported tool button is not in a tool class",
|
||||||
|
messageFormat: "The exported tool button '{0}' is not in a tool class",
|
||||||
|
category: "Usage",
|
||||||
|
DiagnosticSeverity.Error,
|
||||||
|
isEnabledByDefault: true,
|
||||||
|
"The exported tool button is not in a tool class. Annotate the class with the '[Tool]' attribute, or remove the '[ExportToolButton]' attribute.",
|
||||||
|
helpLinkUri: string.Format(_helpLinkFormat, "GD0108"));
|
||||||
|
|
||||||
|
public static readonly DiagnosticDescriptor ExportToolButtonShouldNotBeUsedWithExportRule =
|
||||||
|
new DiagnosticDescriptor(id: "GD0109",
|
||||||
|
title: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute",
|
||||||
|
messageFormat: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute on '{0}'",
|
||||||
|
category: "Usage",
|
||||||
|
DiagnosticSeverity.Error,
|
||||||
|
isEnabledByDefault: true,
|
||||||
|
"The '[ExportToolButton]' attribute cannot be used with the '[Export]' attribute. Remove one of the attributes.",
|
||||||
|
helpLinkUri: string.Format(_helpLinkFormat, "GD0109"));
|
||||||
|
|
||||||
|
public static readonly DiagnosticDescriptor ExportToolButtonIsNotCallableRule =
|
||||||
|
new DiagnosticDescriptor(id: "GD0110",
|
||||||
|
title: "The exported tool button is not a Callable",
|
||||||
|
messageFormat: "The exported tool button '{0}' is not a Callable",
|
||||||
|
category: "Usage",
|
||||||
|
DiagnosticSeverity.Error,
|
||||||
|
isEnabledByDefault: true,
|
||||||
|
"The exported tool button is not a Callable. The '[ExportToolButton]' attribute is only supported on members of type Callable.",
|
||||||
|
helpLinkUri: string.Format(_helpLinkFormat, "GD0110"));
|
||||||
|
|
||||||
public static readonly DiagnosticDescriptor SignalDelegateMissingSuffixRule =
|
public static readonly DiagnosticDescriptor SignalDelegateMissingSuffixRule =
|
||||||
new DiagnosticDescriptor(id: "GD0201",
|
new DiagnosticDescriptor(id: "GD0201",
|
||||||
title: "The name of the delegate must end with 'EventHandler'",
|
title: "The name of the delegate must end with 'EventHandler'",
|
||||||
|
@ -287,6 +287,12 @@ namespace Godot.SourceGenerators
|
|||||||
public static bool IsGodotGlobalClassAttribute(this INamedTypeSymbol symbol)
|
public static bool IsGodotGlobalClassAttribute(this INamedTypeSymbol symbol)
|
||||||
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.GlobalClassAttr;
|
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.GlobalClassAttr;
|
||||||
|
|
||||||
|
public static bool IsGodotExportToolButtonAttribute(this INamedTypeSymbol symbol)
|
||||||
|
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ExportToolButtonAttr;
|
||||||
|
|
||||||
|
public static bool IsGodotToolAttribute(this INamedTypeSymbol symbol)
|
||||||
|
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ToolAttr;
|
||||||
|
|
||||||
public static bool IsSystemFlagsAttribute(this INamedTypeSymbol symbol)
|
public static bool IsSystemFlagsAttribute(this INamedTypeSymbol symbol)
|
||||||
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.SystemFlagsAttr;
|
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.SystemFlagsAttr;
|
||||||
|
|
||||||
|
@ -9,10 +9,12 @@ namespace Godot.SourceGenerators
|
|||||||
public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
|
public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
|
||||||
public const string ExportGroupAttr = "Godot.ExportGroupAttribute";
|
public const string ExportGroupAttr = "Godot.ExportGroupAttribute";
|
||||||
public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute";
|
public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute";
|
||||||
|
public const string ExportToolButtonAttr = "Godot.ExportToolButtonAttribute";
|
||||||
public const string SignalAttr = "Godot.SignalAttribute";
|
public const string SignalAttr = "Godot.SignalAttribute";
|
||||||
public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute";
|
public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute";
|
||||||
public const string GodotClassNameAttr = "Godot.GodotClassNameAttribute";
|
public const string GodotClassNameAttr = "Godot.GodotClassNameAttribute";
|
||||||
public const string GlobalClassAttr = "Godot.GlobalClassAttribute";
|
public const string GlobalClassAttr = "Godot.GlobalClassAttribute";
|
||||||
|
public const string ToolAttr = "Godot.ToolAttribute";
|
||||||
public const string SystemFlagsAttr = "System.FlagsAttribute";
|
public const string SystemFlagsAttr = "System.FlagsAttribute";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,8 @@ namespace Godot.SourceGenerators
|
|||||||
Password = 36,
|
Password = 36,
|
||||||
LayersAvoidance = 37,
|
LayersAvoidance = 37,
|
||||||
DictionaryType = 38,
|
DictionaryType = 38,
|
||||||
Max = 39
|
ToolButton = 39,
|
||||||
|
Max = 40
|
||||||
}
|
}
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
|
@ -69,6 +69,7 @@ namespace Godot.SourceGenerators
|
|||||||
bool hasNamespace = classNs.Length != 0;
|
bool hasNamespace = classNs.Length != 0;
|
||||||
|
|
||||||
bool isInnerClass = symbol.ContainingType != null;
|
bool isInnerClass = symbol.ContainingType != null;
|
||||||
|
bool isToolClass = symbol.GetAttributes().Any(a => a.AttributeClass?.IsGodotToolAttribute() ?? false);
|
||||||
|
|
||||||
string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
|
string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
|
||||||
+ "_ScriptProperties.generated";
|
+ "_ScriptProperties.generated";
|
||||||
@ -277,6 +278,16 @@ namespace Godot.SourceGenerators
|
|||||||
if (propertyInfo == null)
|
if (propertyInfo == null)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
if (propertyInfo.Value.Hint == PropertyHint.ToolButton && !isToolClass)
|
||||||
|
{
|
||||||
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
|
Common.OnlyToolClassesShouldUseExportToolButtonRule,
|
||||||
|
member.Symbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||||
|
member.Symbol.ToDisplayString()
|
||||||
|
));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
AppendPropertyInfo(source, propertyInfo.Value);
|
AppendPropertyInfo(source, propertyInfo.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -418,6 +429,19 @@ namespace Godot.SourceGenerators
|
|||||||
var exportAttr = memberSymbol.GetAttributes()
|
var exportAttr = memberSymbol.GetAttributes()
|
||||||
.FirstOrDefault(a => a.AttributeClass?.IsGodotExportAttribute() ?? false);
|
.FirstOrDefault(a => a.AttributeClass?.IsGodotExportAttribute() ?? false);
|
||||||
|
|
||||||
|
var exportToolButtonAttr = memberSymbol.GetAttributes()
|
||||||
|
.FirstOrDefault(a => a.AttributeClass?.IsGodotExportToolButtonAttribute() ?? false);
|
||||||
|
|
||||||
|
if (exportAttr != null && exportToolButtonAttr != null)
|
||||||
|
{
|
||||||
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
|
Common.ExportToolButtonShouldNotBeUsedWithExportRule,
|
||||||
|
memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||||
|
memberSymbol.ToDisplayString()
|
||||||
|
));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var propertySymbol = memberSymbol as IPropertySymbol;
|
var propertySymbol = memberSymbol as IPropertySymbol;
|
||||||
var fieldSymbol = memberSymbol as IFieldSymbol;
|
var fieldSymbol = memberSymbol as IFieldSymbol;
|
||||||
|
|
||||||
@ -446,19 +470,56 @@ namespace Godot.SourceGenerators
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (exportToolButtonAttr != null && propertySymbol != null && propertySymbol.GetMethod == null)
|
||||||
|
{
|
||||||
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
|
Common.ExportedPropertyIsWriteOnlyRule,
|
||||||
|
propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||||
|
propertySymbol.ToDisplayString()
|
||||||
|
));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
var memberType = propertySymbol?.Type ?? fieldSymbol!.Type;
|
var memberType = propertySymbol?.Type ?? fieldSymbol!.Type;
|
||||||
|
|
||||||
var memberVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(marshalType)!.Value;
|
var memberVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(marshalType)!.Value;
|
||||||
string memberName = memberSymbol.Name;
|
string memberName = memberSymbol.Name;
|
||||||
|
|
||||||
|
string? hintString = null;
|
||||||
|
|
||||||
|
if (exportToolButtonAttr != null)
|
||||||
|
{
|
||||||
|
if (memberVariantType != VariantType.Callable)
|
||||||
|
{
|
||||||
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
|
Common.ExportToolButtonIsNotCallableRule,
|
||||||
|
memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
|
||||||
|
memberSymbol.ToDisplayString()
|
||||||
|
));
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
hintString = exportToolButtonAttr.ConstructorArguments[0].Value?.ToString() ?? "";
|
||||||
|
foreach (var namedArgument in exportToolButtonAttr.NamedArguments)
|
||||||
|
{
|
||||||
|
if (namedArgument is { Key: "Icon", Value.Value: string { Length: > 0 } })
|
||||||
|
{
|
||||||
|
hintString += $",{namedArgument.Value.Value}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new PropertyInfo(memberVariantType, memberName, PropertyHint.ToolButton,
|
||||||
|
hintString: hintString, PropertyUsageFlags.Editor, exported: true);
|
||||||
|
}
|
||||||
|
|
||||||
if (exportAttr == null)
|
if (exportAttr == null)
|
||||||
{
|
{
|
||||||
return new PropertyInfo(memberVariantType, memberName, PropertyHint.None,
|
return new PropertyInfo(memberVariantType, memberName, PropertyHint.None,
|
||||||
hintString: null, PropertyUsageFlags.ScriptVariable, exported: false);
|
hintString: hintString, PropertyUsageFlags.ScriptVariable, exported: false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!TryGetMemberExportHint(typeCache, memberType, exportAttr, memberVariantType,
|
if (!TryGetMemberExportHint(typeCache, memberType, exportAttr, memberVariantType,
|
||||||
isTypeArgument: false, out var hint, out var hintString))
|
isTypeArgument: false, out var hint, out hintString))
|
||||||
{
|
{
|
||||||
var constructorArguments = exportAttr.ConstructorArguments;
|
var constructorArguments = exportAttr.ConstructorArguments;
|
||||||
|
|
||||||
|
@ -0,0 +1,33 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
|
namespace Godot
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Exports the annotated <see cref="Callable"/> as a clickable button.
|
||||||
|
/// </summary>
|
||||||
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||||
|
public sealed class ExportToolButtonAttribute : Attribute
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The label of the button.
|
||||||
|
/// </summary>
|
||||||
|
public string Text { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If defined, used to fetch an icon for the button via <see cref="Control.GetThemeIcon"/>,
|
||||||
|
/// from the <code>EditorIcons</code> theme type.
|
||||||
|
/// </summary>
|
||||||
|
public string? Icon { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Exports the annotated <see cref="Callable"/> as a clickable button.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The label of the button.</param>
|
||||||
|
public ExportToolButtonAttribute(string text)
|
||||||
|
{
|
||||||
|
Text = text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -48,6 +48,7 @@
|
|||||||
<!-- Sources -->
|
<!-- Sources -->
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="Core\Aabb.cs" />
|
<Compile Include="Core\Aabb.cs" />
|
||||||
|
<Compile Include="Core\Attributes\ExportToolButtonAttribute.cs" />
|
||||||
<Compile Include="Core\Bridge\GodotSerializationInfo.cs" />
|
<Compile Include="Core\Bridge\GodotSerializationInfo.cs" />
|
||||||
<Compile Include="Core\Bridge\MethodInfo.cs" />
|
<Compile Include="Core\Bridge\MethodInfo.cs" />
|
||||||
<Compile Include="Core\Callable.generics.cs" />
|
<Compile Include="Core\Callable.generics.cs" />
|
||||||
|
Loading…
Reference in New Issue
Block a user