How to use setget with [Tool] to update mesh material

Godot Version

4.2.2.stable.mono

Question

Hello,

I’m trying to make it so when I add a custom resource to a scene, the scene will automatically update itself with the texture from the resource in the editor. I tried achieving this using a setget for an exported variable of the custom resource. However, every time I build the code Godot will crash. I’ve tried following tutorials and similar steps from others having similar issues, but reached the same outcome.

using Godot;
using System;

[Tool]
public partial class pickupable_object : Node3D
{
    [Export] private Item _itemResource
    {
        get { return _itemResource; }
        set { 
            _itemResource = value;
            InitializeResource();
        }
    }
    [Export] private MeshInstance3D _meshInstance;
    private StandardMaterial3D _objectsMaterial;

    private void InitializeResource()
    {
        _objectsMaterial = _meshInstance.Mesh.SurfaceGetMaterial(0) as StandardMaterial3D;
        _objectsMaterial.AlbedoTexture = _itemResource.sprite;
    }
}

Thanks in advance!

Found the solution - For those who run into this in the future, I was accidentally causing an infinite recursion by have the getsetter reference itself in the “set” process. To resolve this all I did was create a new private variable and have the getsetter reference that new private variable and then poof, no more crashes. It’s amazing how looking away from your code and coming back can make you see the way. This is also my first time playing with [Tool] in godot on Csharp, so I felt out of my element and overcomplicated things in my head.

Updated code is below.

I’ve also updated the initialization method to make unique instances of the mesh.

using Godot;
using System;

[Tool]
public partial class pickupable_object : Node3D
{
    
    [Export] public Item ItemResource
    {
        get { 
            if( _itemResource == null)
                return null;
            else
                return _itemResource; 
            }
        set { 
            _itemResource = value;
            InitializeResource();
            }
    }
    [Export] private float _objectSize = 0.5f;
    private Item _itemResource;
    
    private void InitializeResource()
    {
        MeshInstance3D _meshInstance = this.GetNode<MeshInstance3D>("MeshInstance3D");

        QuadMesh newQuadMesh = new QuadMesh();
        newQuadMesh.Size = new Vector2(_objectSize, _objectSize);

        StandardMaterial3D _objectsMaterial = new StandardMaterial3D
        {
            Transparency = BaseMaterial3D.TransparencyEnum.Alpha,
            BillboardMode = BaseMaterial3D.BillboardModeEnum.Enabled,
            TextureFilter = BaseMaterial3D.TextureFilterEnum.Nearest
        };  

        Texture2D newTexture = new Texture2D();
        newTexture = _itemResource == null? null : _itemResource.sprite;

        if (_itemResource != null)
            _objectsMaterial.AlbedoTexture = newTexture;
        else
            _objectsMaterial.AlbedoTexture = null;
        
        newQuadMesh.Material = _objectsMaterial;
        _meshInstance.Mesh = newQuadMesh;

        NotifyPropertyListChanged();
    }
}

1 Like