Skip to content
This repository was archived by the owner on Nov 25, 2025. It is now read-only.

Commit 4cfef93

Browse files
Merge remote-tracking branch 'origin/main' into dev/upm-readiness
2 parents 042d562 + 82dc6e5 commit 4cfef93

File tree

4 files changed

+374
-38
lines changed

4 files changed

+374
-38
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2024 Virtual Maker Corporation
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.
Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
# VirtualMaker Bindings
2+
3+
The VirtualMaker Bindings library provides a robust system for creating and managing properties in Unity. It allows for easy data binding between properties and UI elements, supports derived properties, and integrates seamlessly with both UGUI and UI Toolkit.
4+
5+
## Installation
6+
7+
To install the VirtualMaker Bindings library, add the following line to your `Packages/manifest.json` file in the `dependencies` section:
8+
9+
```json
10+
"dependencies": {
11+
"com.virtualmaker.bindings": "https://github.com/virtual-maker-net/com.virtualmaker.bindings.git?path=/Bindings/Packages/com.virtualmaker.bindings#main"
12+
}
13+
```
14+
15+
## Creating a `Property<T>`
16+
17+
To create a property, simply instantiate the `Property<T>` class with the desired type. Properties can be serialized to appear in the editor.
18+
19+
```cs
20+
using VirtualMaker.Bindings;
21+
22+
public class Ex ampleComponent : MonoBehaviour
23+
{
24+
[SerializeField]
25+
private Property<int> _intProperty = new();
26+
27+
[SerializeField]
28+
private Property<string> _stringProperty = new();
29+
}
30+
```
31+
32+
## Binding to a Property with the `Bindings` Class
33+
34+
The `Bindings` class allows you to bind properties to callbacks or directly to UI elements. Here's an example of how to bind an `IntegerField` and a `TextField` to properties:
35+
36+
```cs
37+
using UnityEngine.UIElements;
38+
using VirtualMaker.Bindings;
39+
40+
public class Example
41+
{
42+
private Bindings _bindings;
43+
private Property<int> _intProperty = new();
44+
private Property<string> _stringProperty = new();
45+
46+
public void SetupBindings(VisualElement root)
47+
{
48+
_bindings = new Bindings(root);
49+
50+
// Invoke a callback now and whenever the property changes
51+
_bindings.Bind(_stringProperty, (value) => Debug.Log(value));
52+
53+
// Invoke a callback only when the property changes
54+
_bindings.BindDeferred(_intProperty, (value) => Debug.Log(value));
55+
56+
// Two-way bind to fields in the UI
57+
_bindings.BindField("my-integer-field", _intProperty, true);
58+
_bindings.BindField("my-text-field", _stringProperty, true);
59+
}
60+
}
61+
```
62+
63+
## Creating a Derived Property
64+
65+
Derived properties allow you to create properties based on other properties. Here's an example of how to create a derived property:
66+
67+
```cs
68+
using VirtualMaker.Bindings;
69+
70+
public class Example
71+
{
72+
private Property<int> _intProperty1 = new();
73+
private Property<int> _intProperty2 = new();
74+
private Derived<int> _sumProperty;
75+
76+
public Example()
77+
{
78+
_sumProperty = Derived.From(_intProperty1, _intProperty2, (val1, val2) => val1 + val2);
79+
}
80+
}
81+
```
82+
83+
## Using UGUI and UI Toolkit Extensions
84+
85+
The library provides extensions for both UGUI and UI Toolkit to facilitate binding properties to UI elements.
86+
87+
### UGUI Example
88+
89+
To use UGUI extensions, add the **BINDINGS_UGUI** define symbol to your project settings.
90+
91+
```cs
92+
using UnityEngine;
93+
using TMPro;
94+
using VirtualMaker.Bindings;
95+
96+
public class UGUIExample : MonoBehaviour
97+
{
98+
[SerializeField]
99+
private TMP_Text text;
100+
101+
[SerializeField]
102+
private Property<string> _textProperty = new();
103+
104+
private Bindings _bindings = new();
105+
106+
void Start()
107+
{
108+
bindings.BindText(text, _textProperty);
109+
}
110+
}
111+
```
112+
113+
### UI Toolkit Example
114+
115+
To use UI Toolkit extensions, add the **BINDINGS_UI_ELEMENTS** define symbol to your project settings.
116+
117+
```cs
118+
using UnityEngine.UIElements;
119+
using VirtualMaker.Bindings;
120+
121+
public class UIToolkitExample
122+
{
123+
[SerializeField]
124+
private Property<string> _textProperty = new Property<string>();
125+
126+
public void SetupBindings(VisualElement root)
127+
{
128+
var bindings = new Bindings(root);
129+
130+
// Search for a text element with the name "my-label" and bind to the text property.
131+
bindings.BindText("my-label", _textProperty);
132+
133+
// Bind to the click event of the button. You can also use On<T> to bind to any event.
134+
bindings.OnClick("my-button", () => Debug.Log("Button clicked!"));
135+
}
136+
}
137+
```
138+
139+
## Bindings at Edit Time
140+
141+
You can have bindings work at edit time by adding the `[ExecuteAlways]` attribute to your MonoBehaviour class, declaring your bindings in `OnEnable`, and resetting them in `OnDisable`.
142+
143+
### Example of Edit-Time Bindings
144+
145+
Here's an example of a `MonoBehaviour` with edit-time bindings:
146+
147+
```cs
148+
using UnityEngine;
149+
using UnityEngine.UIElements;
150+
using VirtualMaker.Bindings;
151+
152+
[ExecuteAlways]
153+
public class EditTimeBindingsExample : MonoBehaviour
154+
{
155+
[SerializeField]
156+
private Property<string> _textProperty = new Property<string>();
157+
158+
[SerializeField]
159+
private UIDocument _uiDocument;
160+
161+
private Bindings _bindings;
162+
163+
void OnEnable()
164+
{
165+
var root = _uiDocument_.rootVisualElement;
166+
_bindings = new Bindings(root);
167+
_bindings.BindText("my-label", _textProperty);
168+
}
169+
170+
void OnDisable()
171+
{
172+
_bindings.Reset();
173+
}
174+
}
175+
```
176+
177+
Now, changing the value of `_textProperty` in the editor will automatically update the bound UI element.

Bindings/Packages/com.virtualmaker.bindings/Runtime/Bindings.UIElements.cs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Linq;
66
using System.Threading.Tasks;
77
using UnityEngine;
8+
using UnityEngine.Events;
89
using UnityEngine.UIElements;
910

1011
namespace VirtualMaker.Bindings
@@ -44,7 +45,7 @@ public void BindText<T, W>(TextElement element, IProperty<T> prop, Func<T, W> tr
4445

4546
public void SetText<T>(string name, T value)
4647
{
47-
if (TryGetElement<Label>(name, out var element))
48+
if (TryGetElement<TextElement>(name, out var element))
4849
{
4950
SetText(element, value);
5051
}
@@ -63,14 +64,6 @@ public void SetLineHeight(string name, int lineHeight)
6364
}
6465
}
6566

66-
public void SetButtonText<T>(string name, T value)
67-
{
68-
if (TryGetElement<Button>(name, out var element))
69-
{
70-
element.text = value?.ToString();
71-
}
72-
}
73-
7467
public void BindWidth(string name, IProperty<StyleLength> prop)
7568
{
7669
Bind<VisualElement, StyleLength>(name, prop, (element, value) => element.style.width = value);
@@ -314,6 +307,15 @@ public void BindField<T>(BaseField<T> baseField, Property<T> property, bool twoW
314307
On<ChangeEvent<T>>(baseField, e => property.Value = e.newValue);
315308
}
316309
}
310+
311+
public void BindField<T>(string name, T value, Action<T> onChange)
312+
{
313+
if (TryGetElement<BaseField<T>>(name, out var baseField))
314+
{
315+
baseField.value = value;
316+
On<ChangeEvent<T>>(baseField, e => onChange(e.newValue));
317+
}
318+
}
317319
#endif
318320

319321
public void SetClass(VisualElement element, string className, bool value)

0 commit comments

Comments
 (0)