Publisher
roanne
Bindora : a reactive data binding library
Bindora is a reactive data binding library for Godot 4.x. Based on Godot's design philosophy, it provides a declarative and component-based approach to help you manage relationships between nodes and data.
This plugin has been mirrored from the Godot Asset Library.
The plugin author is in no way affiliated with Gadget.
If you are the author of this plugin and would like this mirror removed, please contact support@gadgetgodot.com.
Bindora
English | 简体中文
[!NOTE] Bindora is currently in the development stage and the API is subject to change, so please use it with caution.
Bindora is a reactive data binding library for Godot 4.4. Based on Godot's design philosophy, it provides a declarative and component-based approach to help you manage relationships between nodes and data.
Core Features
Reactive Data System
- Provide the
Refclass as the foundation for various data types - Supports serialization and deserialization
- Automatic type conversion and checking
- Provides
signalfor data monitoring
Comprehensive Binding Support
TextBinding、InputBinding、RadioBinding、CheckBoxBinding、PropertyBinding、VisibleBinding、ShaderBinding、ToggleBinding、ListBinding、ThemeOverrideBinding、CustomBinding
Quick Start
Installing Bindora
Copy the bindora folder into your Godot project.
Basic Usage
Create a Label node and set its text to "Text is {{value}}". Then add a script to the node with the following code:
extends Label
# Declare data
var text_ref = RefString.new("Hello World")
# Create text binding
text_ref.bind_text(self)
# Create a watcher
text_ref.value_updated.connect(func(old_value,new_value):
print("Text changed to: ", new_value)
)
# Modify data
text_ref.value = "New Text"
# Or
text_ref.set_value("New Text") # Using set_value is recommended as it includes type checking
The Ref class provides many convenient binding methods, which you can explore in the API Reference.
Using Binding
When you need more complex data binding, you can directly use Binding .
extends Label
var text_ref = RefString.new("Hello")
var text_ref2 = RefString.new("World")
func _ready():->void:
var binding = TextBinding.new(self, {"value": text_ref, "value2": text_ref2}, "Text is {{value}} {{value2}}")
Using ReactiveResource
Create a resource class that extends ReactiveResource and declare Ref variables within it.
[!NOTE]
Refvariables declared inReactiveResourcedo not need to be exported with@export. They are automatically handled and exported upon declaration. Using@exportmay cause unexpected errors.
class MyResource extends ReactiveResource
var text_ref = RefString.new("Hello World")
Using with RefArray.
var packed_scene = preload("res://path/to/your/packed_scene.tscn")
var array = RefArray.new()
array.bind_list($Container, packed_scene, func(item, data , index):
data.text_ref.bind_text(item)
)
for i in 3:
var new_item = MyResource.new()
new_item.text_ref.set_value("Item " + i)
array.append(new_item)
The ReactiveResource class provides serialization and deserialization functionality. You can use to_dictionary to convert it to a dictionary, or use from_dictionary to update values from a dictionary.
var resource = MyResource.new()
var dict = resource.to_dictionary()
dict["text_ref"] = "New Text"
resource.from_dictionary(dict)
print(resource.text_ref.value) # New Text
The ReactiveResource class also provides static serialization and deserialization methods, which can be used as follows:
var resource = MyResource.new()
resource.text_ref.set_value("Hello World")
var dict = ReactiveResource.serialize(resource)
var new_resource = ReactiveResource.reactive(dict,MyResource)
print(new_resource.text_ref.value) # Hello World
More Usage Examples
Refer to the examples in the test folder.
Best Practices
Type Selection
Choose appropriate Ref types for your data, such as RefString , RefInt , etc. Avoid directly using Ref or other base classes to create variables.
Modifying and Getting Values
Try to avoid using .value to manipulate values, as it lacks type checking in the editor and may only report errors during runtime. Instead, use set_value() and get_value() functions which perform type checking at the editor stage.
Binding Management
Binding will automatically recognize whether the node exists and recycle it. If you need to manually recycle it, you can use the destroy() method.
When to Use ReactiveResource
For most cases, using Ref will suffice. However, in some cases, using ReactiveResource can provide better performance. Here are a few examples:
- When using
@exportto export properties, numerousRefproperties can make the inspector complex and unintuitive (because exported properties are wrapped).ReactiveResource's automatic export feature can avoid this situation. - For content that needs serialization and deserialization,
ReactiveResourcecan be transformed directly using built-in functions without additional operations. - When you want to use
RefDictionary, you can useReactiveResourceinstead, as it provides better type checking and autocomplete.
# Recommended
class MyResource extends ReactiveResource
var text_ref = RefString.new("Hello World")
var number_ref = RefInt.new(1)
# Optional
class MyResource extends Resource
@export var text_ref = RefString.new("Hello World")
@export var number_ref = RefInt.new(1)
# Not recommended
extends Node
var dict_ref = RefDictionary.new({"text": "Hello World", "number": 1})
API Reference
Basic Variable Types - RefVariant
RefBool, RefInt, RefFloat, RefString, RefVector2, RefVector2i, RefVector3, RefVector3i, RefVector4, RefVector4i, RefRect2, RefRect2i, RefColor
Binding methods:
- bind_text(_node: CanvasItem, _keyword: String = "value",_template: String = "") -> TextBinding
- bind_input(_node: CanvasItem, _property: String = "") -> InputBinding
- bind_multi_input(_dict: Dictionary[CanvasItem, String]) -> Dictionary[CanvasItem, InputBinding]
- bind_property(_node: CanvasItem, _property: String, _use_node_data: bool = false) -> PropertyBinding
- bind_multi_property(_dict: Dictionary[CanvasItem, String]) -> Dictionary[CanvasItem, PropertyBinding]
- bind_radios(_nodes: Array[CanvasItem]) -> Dictionary[CanvasItem, RadioBinding]
- bind_radios_custom(_dict: Dictionary[CanvasItem, String]) -> Dictionary[CanvasItem, RadioBinding]
- bind_shader(_node: CanvasItem, _property: String) -> ShaderBinding
- bind_visible(_node: CanvasItem, _condition: Callable | Ref) -> VisibleBinding
- bind_theme_override(_node: CanvasItem, _property: String) -> ThemeOverrideBinding
- bind_toggle(_node: CanvasItem, _opposite: bool = false) -> ToggleBinding
- bind_multi_toggle(_dict: Dictionary[CanvasItem, bool]) -> Dictionary[CanvasItem, ToggleBinding]
- bind_custom(_node: CanvasItem, _callable: Callable) -> CustomBinding
Special Types
- bind_text(_node: CanvasItem, _keyword: String = "value", _template: String = "") -> TextBinding
- bind_check_boxes(_nodes: Array[CanvasItem]) -> Dictionary[CanvasItem, CheckBoxBinding]
- bind_check_boxes_custom(_dict: Dictionary[CanvasItem, String]) -> Dictionary[CanvasItem, CheckBoxBinding]
- bind_list(_parent: Node, _packed_scene: PackedScene, _callable: Callable) -> ListBinding
- bind_text(_node: CanvasItem, _template: String = "") -> TextBinding
Resource Types - RefResource
RefFont, RefLabelSettings, RefMaterial, RefStyleBox, RefTexture
Contributing
If you encounter any issues or have suggestions for improvements, feel free to open an issue or submit a pull request.
License
Bindora is an open-source project under the MIT license.