diff --git a/src/Godot.Bindings/Core/Attributes/BindPropertyAttribute.cs b/src/Godot.Bindings/Core/Attributes/BindPropertyAttribute.cs
index 851dcc9e..701f4f62 100644
--- a/src/Godot.Bindings/Core/Attributes/BindPropertyAttribute.cs
+++ b/src/Godot.Bindings/Core/Attributes/BindPropertyAttribute.cs
@@ -15,6 +15,18 @@ public sealed class BindPropertyAttribute : Attribute
///
public string? Name { get; init; }
+ ///
+ /// Specifies the hint that will be used to register the property.
+ /// If unspecified it will use the hint calculated from the property type.
+ ///
+ public PropertyHint Hint { get; init; } = PropertyHint.None;
+
+ ///
+ /// Specifies the hint string that will be used to register the property.
+ /// If unspecified it will use the hint string calculated from the property type.
+ ///
+ public string? HintString { get; init; }
+
///
/// Specifies the marshaller type that will be used to marshal this property.
/// If unspecified the default marshaller for the annotated property's type
diff --git a/src/Godot.SourceGenerators/BindMethodsWriter.cs b/src/Godot.SourceGenerators/BindMethodsWriter.cs
index 24d4e587..fcb7bc2f 100644
--- a/src/Godot.SourceGenerators/BindMethodsWriter.cs
+++ b/src/Godot.SourceGenerators/BindMethodsWriter.cs
@@ -524,13 +524,13 @@ private static void AppendPropertyInfoObjectInitializer(IndentedStringBuilder sb
List lines = [];
- if (marshalInfo.Hint != PropertyHint.None)
+ if (property.HintOverride != PropertyHint.None || marshalInfo.Hint != PropertyHint.None)
{
- lines.Add($"Hint = {marshalInfo.Hint.FullNameWithGlobal()},");
+ lines.Add($"Hint = {(property.HintOverride == PropertyHint.None ? marshalInfo.Hint : property.HintOverride).FullNameWithGlobal()},");
}
- if (!string.IsNullOrEmpty(marshalInfo.HintString))
+ if (!string.IsNullOrEmpty(property.HintStringOverride) || !string.IsNullOrEmpty(marshalInfo.HintString))
{
- lines.Add($"""HintString = "{marshalInfo.HintString}",""");
+ lines.Add($"""HintString = "{property.HintStringOverride ?? marshalInfo.HintString}",""");
}
if (marshalInfo.Usage != PropertyUsageFlags.None)
{
diff --git a/src/Godot.SourceGenerators/SpecCollectors/PropertySpecCollector.cs b/src/Godot.SourceGenerators/SpecCollectors/PropertySpecCollector.cs
index a250ac60..43b05226 100644
--- a/src/Godot.SourceGenerators/SpecCollectors/PropertySpecCollector.cs
+++ b/src/Godot.SourceGenerators/SpecCollectors/PropertySpecCollector.cs
@@ -88,6 +88,8 @@ public static GodotPropertySpec Collect(Compilation compilation, ITypeSymbol ret
private static GodotPropertySpec CollectCore(Compilation compilation, string symbolName, ITypeSymbol typeSymbol, AttributeData? attribute, CancellationToken cancellationToken = default)
{
string? nameOverride = null;
+ PropertyHint hintOverride = PropertyHint.None;
+ string? hintStringOverride = null;
if (attribute is not null)
{
@@ -98,6 +100,15 @@ private static GodotPropertySpec CollectCore(Compilation compilation, string sym
case "Name":
nameOverride = constant.Value as string;
break;
+ case "Hint":
+ if (constant.Value is long longValue)
+ {
+ hintOverride = (PropertyHint)longValue;
+ }
+ break;
+ case "HintString":
+ hintStringOverride = constant.Value as string;
+ break;
}
}
}
@@ -110,6 +121,8 @@ private static GodotPropertySpec CollectCore(Compilation compilation, string sym
FullyQualifiedTypeName = typeSymbol.FullNameWithGlobal(),
MarshalInfo = marshalInfo,
NameOverride = nameOverride,
+ HintOverride = hintOverride,
+ HintStringOverride = hintStringOverride
};
}
}
diff --git a/src/Godot.SourceGenerators/Specs/GodotPropertySpec.cs b/src/Godot.SourceGenerators/Specs/GodotPropertySpec.cs
index 28f12a09..8609e03e 100644
--- a/src/Godot.SourceGenerators/Specs/GodotPropertySpec.cs
+++ b/src/Godot.SourceGenerators/Specs/GodotPropertySpec.cs
@@ -45,6 +45,20 @@ namespace Godot.SourceGenerators;
///
public string? NameOverride { get; init; }
+ ///
+ /// Hint specified in the [BindProperty] attribute for this property,
+ /// or PropertyType.None if a hint was not specified.
+ /// If unspecified the hint of the property will be calculated from the .
+ ///
+ public PropertyHint HintOverride { get; init; }
+
+ ///
+ /// Hint string specified in the [BindProperty] attribute for this property,
+ /// or if a hint string was not specified.
+ /// If unspecified the hint string of the property will be calculated from the .
+ ///
+ public string? HintStringOverride { get; init; }
+
///
/// Group information specified in the [PropertyGroup] attribute,
/// if the property is annotated to define a group from this property.
diff --git a/tests/Godot.SourceGenerators.Tests/TestData/GeneratedSources/NS.NodeWithProperties.generated.cs b/tests/Godot.SourceGenerators.Tests/TestData/GeneratedSources/NS.NodeWithProperties.generated.cs
index 4ab5ab9f..1b4888f1 100644
--- a/tests/Godot.SourceGenerators.Tests/TestData/GeneratedSources/NS.NodeWithProperties.generated.cs
+++ b/tests/Godot.SourceGenerators.Tests/TestData/GeneratedSources/NS.NodeWithProperties.generated.cs
@@ -18,6 +18,8 @@ partial class NodeWithProperties
public static global::Godot.StringName @myField { get; } = global::Godot.StringName.CreateStaticFromAscii("myField"u8);
public static global::Godot.StringName @myNamedField { get; } = global::Godot.StringName.CreateStaticFromAscii("my_named_field"u8);
public static global::Godot.StringName @myFieldWithDefaultValue { get; } = global::Godot.StringName.CreateStaticFromAscii("myFieldWithDefaultValue"u8);
+ public static global::Godot.StringName @myFieldWithHintOverride { get; } = global::Godot.StringName.CreateStaticFromAscii("myFieldWithHintOverride"u8);
+ public static global::Godot.StringName @myFieldWithHintStringOverride { get; } = global::Godot.StringName.CreateStaticFromAscii("myFieldWithHintStringOverride"u8);
}
public new partial class SignalName : global::Godot.Node.SignalName
{
@@ -99,5 +101,31 @@ internal static void BindMethods(global::Godot.Bridge.ClassRegistrationContext c
{
__instance.@myFieldWithDefaultValue = value;
});
+ context.BindProperty(new global::Godot.Bridge.PropertyInfo(PropertyName.@myFieldWithHintOverride, global::Godot.VariantType.Int, global::Godot.Bridge.VariantTypeMetadata.Int32)
+ {
+ Hint = global::Godot.PropertyHint.Layers3DPhysics,
+ Usage = global::Godot.PropertyUsageFlags.Default,
+ },
+ static (NodeWithProperties __instance) =>
+ {
+ return __instance.@myFieldWithHintOverride;
+ },
+ static (NodeWithProperties __instance, int value) =>
+ {
+ __instance.@myFieldWithHintOverride = value;
+ });
+ context.BindProperty(new global::Godot.Bridge.PropertyInfo(PropertyName.@myFieldWithHintStringOverride, global::Godot.VariantType.Int, global::Godot.Bridge.VariantTypeMetadata.Int32)
+ {
+ HintString = "my_hint_string",
+ Usage = global::Godot.PropertyUsageFlags.Default,
+ },
+ static (NodeWithProperties __instance) =>
+ {
+ return __instance.@myFieldWithHintStringOverride;
+ },
+ static (NodeWithProperties __instance, int value) =>
+ {
+ __instance.@myFieldWithHintStringOverride = value;
+ });
}
}
diff --git a/tests/Godot.SourceGenerators.Tests/TestData/Sources/NodeWithProperties.cs b/tests/Godot.SourceGenerators.Tests/TestData/Sources/NodeWithProperties.cs
index 3ac4ba92..067b99bd 100644
--- a/tests/Godot.SourceGenerators.Tests/TestData/Sources/NodeWithProperties.cs
+++ b/tests/Godot.SourceGenerators.Tests/TestData/Sources/NodeWithProperties.cs
@@ -26,4 +26,10 @@ public partial class NodeWithProperties : Node
[BindProperty]
public int myFieldWithDefaultValue = 42;
+
+ [BindProperty(Hint = PropertyHint.Layers3DPhysics)]
+ public int myFieldWithHintOverride;
+
+ [BindProperty(HintString = "my_hint_string")]
+ public int myFieldWithHintStringOverride;
}