I have a dialogue system I wrote myself, but I’m having trouble making one part of it more simple. I have a resource which contains the following 3 properties:
A SpriteFrame resource
A string resource to selecting an animation
A color resource for the text
What I’m trying to achieve here is the following:
When the SpriteFrame resource is changed, I want to dynamically update the string field to be a dropdown field, where the developers can pick one item from a list of available options. These options should be pulled from the SpriteFrame resource (as I believe it has a GetAnimationNames function).
What’s the correct way of achieving this behavior, as I found very little documentation explaining this.
Doesn’t explain what I’m trying to a achieve, as I’m not sure how to dynamically update a property. I’m aware that an enum works, but I don’t see anywhere on that page how to dynamically update said dictionary or enum every time a different property is changed.
ok i misunderstood, sorry about that. below is probably not the answer you are looking for so i am blurring it.
using Godot;
using System;
[GlobalClass]
public partial class CsharpTemp:Node {
void SpriteResourceChanged() {
GD.Print("changed");
}
public CsharpTemp() {
sprite_frame_test v_test = new sprite_frame_test();
v_test.Changed += SpriteResourceChanged;
v_test.my_number = 99;
}
}
public partial class sprite_frame_test:SpriteFrames {
int m_number = 0;
[Export]
public int my_number {
get {
GD.Print("get=", m_number);
return m_number;
}
set {
m_number = value;
EmitChanged();
GD.Print("set=", m_number);
}
}
}
using Godot;
namespace Predation.Scripts.Resources;
[Tool]
[GlobalClass]
public partial class DialogueCharacter : Resource
{
[Export]
public SpriteFrames SpriteFrames { get; set; }
[Export(PropertyHint.Enum)]
public string AnimationName { get; set; }
[Export]
public Color TextColor;
}
This is what my resource looks like at the moment, and in the editor, it looks like this:
I’m trying to get the following behavior:
When I select a Sprite Frame resource to the very first property, I want my script (which is running inside the editor as well) to update the second property called Animation Name, and make it so I see the same list of animations that the First peroperty (SpriteFrame) contains.
These:
And be able to select ONE animation that I’d like to use for that specific resource.
After many painful tries and fixing issues (Turns out the Example code shown on the official 4.3 godot docs for the C# code for _GetPropertyList was incorrect in a few places), I finally got the solution I wanted, in case anyone in the future needs something like this, this is how I achieved it:
using Godot;
using Godot.Collections;
using Array = System.Array;
namespace GameName.Scripts.Resources;
[Tool]
[GlobalClass]
public partial class DialogueCharacter : Resource
{
[Export]
public Color TextColor { get; set; }
private SpriteFrames _spriteFrames;
[Export]
public SpriteFrames SpriteFrames {
get => _spriteFrames;
set
{
_spriteFrames = value;
NotifyPropertyListChanged();
}
}
private string[] _animations;
private int _currentlySelected;
public override Array<Dictionary> _GetPropertyList()
{
Array<Dictionary> properties = new();
_animations = null;
if (SpriteFrames is null)
return base._GetPropertyList();
_animations = SpriteFrames.GetAnimationNames();
if (_animations.Length == 0)
return base._GetPropertyList();
string animationsString = _animations.Join(",");
properties.Add(new Dictionary
{
{ "name", "dialogueAnimations" },
{ "type", (int)Variant.Type.String },
{ "hint", (int)PropertyHint.Enum },
{ "hint_string", animationsString }
});
return properties;
}
public override Variant _Get(StringName property)
{
string propertyName = property.ToString();
if (propertyName != "dialogueAnimations" || _animations == null)
return default;
return _animations[_currentlySelected];
}
public override bool _Set(StringName property, Variant value)
{
string propertyName = property.ToString();
if (propertyName != "dialogueAnimations" || _animations == null)
return false;
int index = Array.IndexOf(_animations, value.ToString());
if (index == -1) return false;
_currentlySelected = index;
return true;
}
}