Skip to content

C# Bindings: Setting AnchorsPreset property on Control has no effect and fails silently #111186

@EvarDion

Description

@EvarDion

Tested versions

v4.5.stable.mono.Official

System information

Windows 10 - Godot 4.5.Stable.Mono

Issue description

When using the C# bindings, setting the AnchorsPreset property on any Control-derived node has no effect and fails silently. The property's value remains at 0 (PRESET_NONE), and the control's anchors are not updated. To correctly change the anchors preset, one must call the SetAnchorsPreset() method.
This represents a significant API "paper cut" as it violates the Principle of Least Astonishment. Code that appears correct and compiles without error (myControl.AnchorsPreset = (int)LayoutPreset.FullRect;) does not perform the expected action. This leads to frustrating bugs that are difficult to diagnose, as the failure is completely silent.

Potential solutions:
(Ideal Fix) Modify the C# source generator to ensure that the generated set accessor for properties like this correctly calls the corresponding Set...() method (e.g., set { SetAnchorsPreset((LayoutPreset)value); }).

(Minimum Fix) If the ideal fix is not feasible, the property should be made read-only ({ get; }) in the C# bindings. This would prevent this error by forcing developers to use the SetAnchorsPreset() method, resulting in a compile-time error instead of a silent runtime failure.
This would significantly improve the developer experience and prevent future confusion for C# users.

Steps to reproduce

Create a new C# script.

  1. In the _Ready() method, instantiate a Control node.
  2. Attempt to set its anchors using the AnchorsPreset property.
  3. Print the value of the property and the control's AnchorRight after setting.
public override void _Ready()
{
    var myControl = new Panel();
    AddChild(myControl);

    GD.Print($"Before setting: AnchorsPreset = {myControl.AnchorsPreset}, AnchorRight = {myControl.AnchorRight}");

    // This line compiles but does nothing at runtime.
    myControl.AnchorsPreset = (int)LayoutPreset.FullRect;

    GD.Print($"After setting: AnchorsPreset = {myControl.AnchorsPreset}, AnchorRight = {myControl.AnchorRight}");

    // The correct way, which works as expected.
    // myControl.SetAnchorsPreset(LayoutPreset.FullRect);
    // GD.Print($"After SetAnchorsPreset(): AnchorRight = {myControl.AnchorRight}");
}

Actual Behavior:
The console shows that AnchorsPreset remains 0 and AnchorRight remains 0.0. The property assignment failed silently.
Analysis and Suggested Fix:

This issue appears to stem from the C# source generator. The property is defined in scene/gui/control.cpp using ADD_PROPERTY with set_anchors_preset as the setter method. The generated C# property AnchorsPreset does not seem to call this method in its setter.

Minimal reproduction project (MRP)

this isnt really necessary for this bug report as it is a simple bindings issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions