Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for setting bindings in editor #15

Open
MechWarrior99 opened this issue Jun 22, 2023 · 4 comments
Open

Support for setting bindings in editor #15

MechWarrior99 opened this issue Jun 22, 2023 · 4 comments

Comments

@MechWarrior99
Copy link

Hey, I just found this library, and it is pretty nice!
Though a major downside currently is not being able to set bindings in editor in my opinion.

I did see that it was in the possible future plans. I was wondering what the status of that would be. And what your plan for going about it would be? I could possibly see about taking a swing at implementing it. Though I am new to Godot, but not to programming.

Thanks :)

@Dangles91
Copy link
Owner

Hey there,

Thanks for trying out the library!

I haven't thought too much about how this would be implemented, I'm also pretty new to Godot plugins.

But I'm thinking there would possibly need to be an autoload that would read in the config created in the editor and create a binding context for the scene to then create the bindings against - maybe as a static list on the BindingContext so they can be retrieved at runtime.

I think there would be some limitations, such as not being able to create validations from the editor, but that might be worked around by using resources or by changing validations so they're implemented as a type instead of just lambdas (similar to ValueFormatters) .

Absolutely feel free to have a crack at an implementation. I don't have any concrete time frame planned to start looking at it at the moment, but happy to help with any questions

@MechWarrior99
Copy link
Author

But I'm thinking there would possibly need to be an autoload that would read in the config created in the editor and create a binding context for the scene to then create the bindings against - maybe as a static list on the BindingContext so they can be retrieved at runtime.

Hmm, so you are thinking having a object (node?) that holds the bindings for all of the nodes, that you then load in?

When I was looking at doing my own system, one big issue I was running in to was running in to was how to actually set the bindings in editor. There was two parts to it, one was that there was no way to add the binding info to the control nodes. So needed to resort to inheriting from a node and implementing a IBindableControl interface to hold the info. The other issue was that Godot doesn't support structs in the inspector. So there was no good way to create a pair of property paths (controlProperty, viewModelProperty). Not sure if there is a way around this point using a GDExtension or something.

Another option I had thought of was having a BindingNode that you would add as a child to any node you wanted to bind to, and it would hold the binding data. It would keep the bindings local, but also be a pain.

Anyway, just some thoughts let me know your thinking :)

@Dangles91
Copy link
Owner

Dangles91 commented Jul 16, 2023

Hey @MechWarrior99, apologies for the super late reply!

I was doing a bit of digging and it could be possible to use the node metadata attributes to store data about the bindings on each node. Another method might be to use a node that gets placed in the scene that can be used to hold references to other nodes in the tree and the binding info for those nodes.

The first option of using metadata might make the user experience better as the only thing to interact with would be editor panels that are included as part of the plugin. However I think the method of using a custom node for the binding context would be a bit easier to implement.

I'll probable spend some time in the coming weeks fleshing out these ideas a bit further and testing them, but if you're still interested, these ideas might be some additonal starting off points.

https://docs.godotengine.org/en/stable/classes/class_object.html#class-object-method-set-meta

@MechWarrior99
Copy link
Author

Hey @Dangles91 no problem. I had taken a break and came back to this anyway.

Metadata was exactly the sort of thing I was looking for, I think it would be a great use for it. It lets us have a sort of structure like XAML has.

I did some experimenting and got it working. My thinking was this. We use strings for the metadata, the name of the metadata would use a Binding_ prefix, followed by the name of the property to bind to Binding_Value. And the value would effectively be like tags in XAML. Path= for the data source binding path, and Mode= for the binding mode. So Path=TestValue, Mode=TwoWay. This pattern lets it be similar to XAML, and we could expand on it to add more functions. I did try to use a single dictionary instead, but they can't be typed, so you have to specify the type of the key and value each time which is a pain.
kc8tHtc
NQKlISK

For doing the actual binding, I was thinking to have a ControlBinding node which would be at the root of the UI nodes tree. You would give it a BindingContext and it would iterate over every descendent and try to bind it using the metadata if the node had any.
It can also subscribe to the GetTree().NodeAdded event, so it can automatically bind to any node that gets added.

I think this seems like a decent approach, and would be fully codeless binding. Let me know what your thoughts though.

There is two thing still tripping me up on how and where to go about implementing. I was thinking it would be good to be able to specify a BindingContext for subtrees of nodes, you probably don't want the whole UI binding to the same context. But not sure what the API for that should look like. Maybe a extension method for Control nodes like void Bind(this Control control, BindingContext ctx)?
We have to store the actual binding in a static(?) dictionary so that we can find it from child nodes so we know what to bind to.

The other thing that I am not sure about is only sort of related. And that is how and if we should do bindings that are relative to the parent path. So if you have a Vector3 control for example. Have the X, Y, and Z fields have a data binding path of Path=X for the X control field, and Y for Y, and Z for Z. That way you bind a position to the Vector3 control and the X, Y, Z are automatically handled. But maybe I am not thinking of this right. And maybe this is more of a separate issue really...

Anyway, let me know what you think!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants