From c8cf42d35f401a258c949eff88ca5bc981625307 Mon Sep 17 00:00:00 2001 From: ls9512 <598914653@qq.com> Date: Mon, 7 Jun 2021 11:42:05 +0800 Subject: [PATCH] v0.9.0 preview release --- .github/README.md | 170 ++++++------ .github/README_CN.md | 387 +++++++++++++++++++++++++++ .github/images/UBind_OpenUpmLogo.png | Bin 0 -> 21922 bytes package.json | 4 +- 4 files changed, 474 insertions(+), 87 deletions(-) create mode 100644 .github/README_CN.md create mode 100644 .github/images/UBind_OpenUpmLogo.png diff --git a/.github/README.md b/.github/README.md index b28236f..0cbc197 100644 --- a/.github/README.md +++ b/.github/README.md @@ -3,7 +3,7 @@ # UBind ***[Preview]*** -**UBind** 是一个适用于 Unity 的数值绑定组件,用于快速实现UI和逻辑数据的关联绑定。 +**UBind** is a value binding component for Unity, which is used to quickly realize the association binding between UI and logical data. ![license](https://img.shields.io/github/license/ls9512/UBind) [![openupm](https://img.shields.io/npm/v/com.ls9512.ubind?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/com.ls9512.ubind/) @@ -21,20 +21,20 @@ [[中文文档]](README_CN.md) -* 1. [特性](#) -* 2. [使用方法](#-1) - * 2.1. [组件方式](#-1) - * 2.1.1. [常用组件绑定器](#-1) - * 2.1.2. [属性绑定器](#-1) - * 2.1.3. [类型绑定器](#-1) - * 2.2. [代码方式](#-1) - * 2.2.1. [MonoBehaviour 自动绑定](#MonoBehaviour) - * 2.2.2. [MonoBehaviour 手动绑定](#MonoBehaviour-1) - * 2.2.3. [手动绑定任意对象](#-1) -* 3. [工作模式](#-1) - * 3.1. [被动回调模式](#-1) - * 3.2. [主动更新模式](#-1) -* 4. [内建类型](#-1) +* 1. [ Features](#Features) +* 2. [How to use](#Howtouse) + * 2.1. [ Component](#Component) + * 2.1.1. [Common Component Binder](#CommonComponentBinder) + * 2.1.2. [Property Binder](#PropertyBinder) + * 2.1.3. [Type Binder](#TypeBinder) + * 2.2. [Programming](#Programming) + * 2.2.1. [MonoBehaviour automatic binding](#MonoBehaviourautomaticbinding) + * 2.2.2. [MonoBehaviour manual binding](#MonoBehaviourmanualbinding) + * 2.2.3. [Manually bind any objects](#Manuallybindanyobjects) +* 3. [ Work mode](#Workmode) + * 3.1. [ Passive callback mode](#Passivecallbackmode) + * 3.2. [Active update mode](#Activeupdatemode) +* 4. [Built-in type](#Built-intype) * 4.1. [Attribute](#Attribute) * 4.1.1. [Bind Value Attribute](#BindValueAttribute) * 4.1.2. [Bind Type Attribute](#BindTypeAttribute) @@ -44,14 +44,14 @@ * 4.5. [Component Binder](#ComponentBinder) * 4.6. [Bind Updater](#BindUpdater) * 4.7. [Bind Map](#BindMap) -* 5. [内建组件](#-1) -* 6. [自定义扩展](#-1) +* 5. [Built-in components](#Built-incomponents) +* 6. [Custom extension](#Customextension) * 6.1. [Custom Data Binder](#CustomDataBinder) * 6.2. [Custom Component Binder](#CustomComponentBinder) * 6.3. [Custom Binder Editor](#CustomBinderEditor) * 6.4. [Custom Data Converter](#CustomDataConverter) -* 7. [注意事项](#-1) -* 8. [扩展 -- TextMeshPro](#--TextMeshPro) +* 7. [Notes](#Notes) +* 8. [Extension -- TextMeshPro](#Extension--TextMeshPro) **DataConverter** --> **DataBinder**(Target) -默认推荐使用的模式,此时 **DataBinder** 的 **NeedUpdate** 属性为 **false**,数据由数据源提供的数值变化回调触发刷新,通知到数据源绑定器,广播给所有的数据目标绑定器,再经由数据转换器转换成目标数据类熊。 +The default recommended mode, at this time the **NeedUpdate** property of **DataBinder** is **false**, the data is refreshed by the value change callback provided by the data source, notified to the data source binder, and broadcast to all The data target binder is then converted into target data bears through the data converter. -### 3.2. 主动更新模式 +### 3.2. Active update mode > **BindUpdater** -> **DataBinder**(Source) --> **DataConverter** --> **DataBinder**(Target) -当数据源不具备主动触发数据变化的能力时,框架提供统一的更新周期来主动检测数值变化,但这个模式无法避免的会造成性能损耗,应尽量减少使用,比较适合快速原型阶段。在这个模式下,**DataBinder** 的 **NeedUpdate** 属性为 **true**,且需要实现 **AddListener()** 和 **RemoveListener()** 方法实现具体的回调注册和注销。框架在 **BindUpdater** 组件中统一按周期触发所有数据源的 **UpdateSource()** 方法以实现数据变化检测和数据更新广播。 +When the data source does not have the ability to actively trigger data changes, the framework provides a unified update cycle to actively detect the value changes, but this mode will inevitably cause performance loss. It should be used as little as possible, which is more suitable for rapid prototyping. In this mode, the **NeedUpdate** property of **DataBinder** is **true**, and the **AddListener()** and **RemoveListener()** methods need to be implemented to achieve specific callback registration and cancellation . The framework triggers the **UpdateSource()** method of all data sources in the **BindUpdater** component on a periodic basis to achieve data change detection and data update broadcasting. *** -## 4. 内建类型 +## 4. Built-in type ### 4.1. Attribute #### 4.1.1. Bind Value Attribute -用于在拥有处理绑定关系能力的类中标记需要绑定的属性和字段,只推荐绑定常见基础数据类型。被标记对象会动态创建 **RuntimeValueBinder** 进行处理。 +It is used to mark attributes and fields that need to be bound in a class that has the ability to handle binding relationships. It is only recommended to bind common basic data types. The marked object will dynamically create a **RuntimeValueBinder** for processing. #### 4.1.2. Bind Type Attribute -与 **BindValueAttribute** 的不同,用于标记自定义类和结构体类型对象,会动态创建 **RuntimeTypeBinder** 进行处理。 +Unlike **BindValueAttribute**, it is used to mark custom class and structure type objects, and **RuntimeTypeBinder** is dynamically created for processing. ### 4.2. Data Context -数据容器,用于维护一组 Data Binder,可以包含多个数据源和数据目标点。每个数据容器相互独立。 +The data container is used to maintain a set of Data Binder, which can contain multiple data sources and data destinations. Each data container is independent of each other. ### 4.3. Data Binder -数据绑定器,用于将数据与具体的对象和其属性进行绑定,可以用于接收和广播数据。 -|属性|描述| +The data binder is used to bind data to specific objects and its properties, and can be used to receive and broadcast data. +|Property|Description| |-|-| -|Target|数据目标对象。| -|Context|数据容器的 Key 值,默认为 Default,无特殊需求可保持默认不设置。| -|Key|目标数据的 Key 值,是单个数据容器内数据的唯一标识。| -|Direction|数据的传递方向,Source 标识当前绑定器是数据源,作为数据广播发送者,Destination 标识当前绑定器作为数据接收者。| -|UpdateType|对于未提供数据变化回调的目标对象,数据采用 Update 模式检测变化是否发生,此时需要指定 Update 的时机。| +|Target|Data target object.| +|Context|The Key value of the data container, the default is **Default**, if there is no special requirement, you can keep the default setting.| +|Key|The Key value of the target data is the unique identification of the data in a single data container.| +|Direction|Data transfer direction, Source identifies the current binder as the data source, as the data broadcast sender, and Target identifies the current binder as the data receiver.| +|UpdateType|For target objects that do not provide data change callbacks, the data adopts the Update mode to detect whether changes have occurred. At this time, the update timing needs to be specified.| ### 4.4. Data Converter -当数据源和数据目标的数据类型不同时,会使用与 **(sourceType, targetType)** 对应的数据转换器尝试转换。 +When the data types of the data source and the data target are different, the data converter corresponding to **(sourceType, targetType)** will be used to try the conversion. -默认的转换器 **CommonConverter** 的实现如下,可以通过修改 **DataConverter.Default** 来替换: +The implementation of the default converter **CommonConverter** is as follows, which can be replaced by modifying **DataConverter.Default**: ``` cs Convert.ChangeType(object data, Type type); ``` -可以按需要使用以下接口提前注册特定类型的自定义转换器: +You can register specific types of custom converters in advance using the following interfaces as needed: ``` cs DataConvert.Register(Type sourceType, Type targetType, DataConverter dataConverter); ``` ### 4.5. Component Binder -数据绑定器的 Unity Component 版本,需要与一个具体的绑定器实现泛型绑定,用于实现组件数据的绑定。 +The Unity Component version of the data binder needs to realize generic binding with a specific binder to realize the binding of component data. ### 4.6. Bind Updater -基于 **MonoBehaviour** 生命周期实现,用于统一维护需要主动更新数据的 **DataBinder** 的更新周期。 +Based on the **MonoBehaviour** life cycle implementation, it is used to uniformly maintain the update cycle of **DataBinder** that needs to actively update data. ### 4.7. Bind Map - +Used to cache all the binding structure information of the objects marked by **BindAttribute**. *** - -## 5. 内建组件 -|组件|绑定对象类型|默认绑定属性|绑定属性类型| +## 5. Built-in components +|Component|Binding object type|Default binding property|Binding property type| |-|-|-|-| |Text Binder|Text|text|string| |Text FontSize Binder|Text|fontSize|int| @@ -308,9 +308,9 @@ DataConvert.Register(Type sourceType, Type targetType, DataConverter dataConvert *** -## 6. 自定义扩展 +## 6. Custom extension ### 6.1. Custom Data Binder -通过继承 **DataBinder** 实现一个特定对象和属性的运行时数据绑定器: +Implement a runtime data binder for a specific object and property by inheriting **DataBinder**: ``` cs public class RuntimeImageFillAmountBinder : DataBinder { @@ -327,7 +327,7 @@ public class RuntimeImageFillAmountBinder : DataBinder ``` ### 6.2. Custom Component Binder -如果需要用作组件,则需要额外实现对应的 **ComponentBinder**: +If you need to use it as a component, you need to additionally implement the corresponding **ComponentBinder**: ``` cs [AddComponentMenu("Data Binding/Image FillAmount Binder")] public class ImageFillAmountBinder : ComponentUpdateBinder @@ -336,7 +336,7 @@ public class ImageFillAmountBinder : ComponentUpdateBinderCustom Binder Editor -如果组件需要保持基础组件样式并且扩展自定义属性和样式,则需要实现对应的 **ComponentBinderEditor**,与绑定器组件和运行时绑定器泛型关联: +If the component needs to maintain the basic component style and extend custom properties and styles, it needs to implement the corresponding **ComponentBinderEditor**, which is generically associated with the binder component and the runtime binder: ``` cs #if UNITY_EDITOR using UnityEditor; @@ -349,7 +349,7 @@ public class ImageFillAmountBinderEditor : ComponentBinderEditorCustom Data Converter -如果需要在传递不同数据类型,并且数据不是 **Convert.ChangeType()** 可以处理的,则需要实现该类型转换的自定义数据转换器: +If you need to transfer different data types and the data is not what **Convert.ChangeType()** can handle, you need a custom data converter that implements this type conversion: ``` cs public class CustomDataConverter : DataConverter { @@ -361,7 +361,7 @@ public class CustomDataConverter : DataConverter } } ``` -需要使用这些绑定器之前,比如游戏初始化时,注册自定的绑定器: +Before you need to use these binders, such as when the game is initialized, register a custom binder: ``` cs var sourcetType = sourceData.GetType(); var targetType = targetData.GetType(); @@ -370,17 +370,17 @@ DataConverter.Register((sourceType, targetType), new CustomDataConverter()); *** -## 7. 注意事项 -* OnValueChanged 仅数据源可用。 -* 所有参数必须在编辑器模式配置,运行时修改参数无效。 -* TypeBinder 暂时仅支持单一层级属性的简单数据类。 -* 尽管组件支持不同数据类型的自动转换,但任然建议直接传递相同的数据类型以优化性能。 -* 多个数据源之间的数据不会被同步,如果数据源之间也需要同步需要将 Direction 设置成 Both。 -* PropertyBinder 和 TypeBinder 依赖反射实现,但由于某些原生组件的属性封装,直接反射修改字段并不能刷新显示,可能需要操作对应的属性,或者定制专用绑定器。 +## 7. Notes +* OnValueChanged is only available for data sources. +* All parameters must be configured in the editor mode. Modifying the parameters during operation is invalid. +* TypeBinder temporarily only supports simple data classes with single-level property. +* Although the component supports automatic conversion of different data types, it is still recommended to pass the same data type directly to optimize performance. +* The data between multiple data sources will not be synchronized. If the data sources also need to be synchronized, the Direction must be set to Both. +* PropertyBinder and TypeBinder rely on reflection to achieve, but due to the property encapsulation of some native components, direct reflection to modify the field does not refresh the display. It may be necessary to manipulate the corresponding properties or customize a dedicated binder. *** -## 8. 扩展 -- TextMeshPro +## 8. Extension -- TextMeshPro * TMP Text Binder * TMP Text UI Binder * TMP Input Field Binder \ No newline at end of file diff --git a/.github/README_CN.md b/.github/README_CN.md new file mode 100644 index 0000000..6acec44 --- /dev/null +++ b/.github/README_CN.md @@ -0,0 +1,387 @@ +
+ +
+ +# UBind ***[Preview]*** +**UBind** 是一个适用于 Unity 的数值绑定组件,用于快速实现UI和逻辑数据的关联绑定。 + +![license](https://img.shields.io/github/license/ls9512/UBind) +[![openupm](https://img.shields.io/npm/v/com.ls9512.ubind?label=openupm®istry_uri=https://package.openupm.com)](https://openupm.com/packages/com.ls9512.ubind/) +![Unity: 2019.4.3f1](https://img.shields.io/badge/Unity-2019.4.3f1-blue) +![.NET 4.x](https://img.shields.io/badge/.NET-4.x-blue) +![topLanguage](https://img.shields.io/github/languages/top/ls9512/UBind) +![size](https://img.shields.io/github/languages/code-size/ls9512/UBind) +![last](https://img.shields.io/github/last-commit/ls9512/UBind) +[![996.icu](https://img.shields.io/badge/link-996.icu-red.svg)](https://996.icu) + +[![issue](https://img.shields.io/github/issues/ls9512/UTween)](https://github.com/ls9512/UBind/issues) +[![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/ls9512/UBind/pulls) +[![Updates](https://img.shields.io/badge/Platform-%20iOS%20%7C%20OS%20X%20%7C%20Android%20%7C%20Windows%20%7C%20Linux%20-brightgreen.svg)](https://github.com/ls9512/UBind) + +[[English Documents Available]](README.md) + + +* 1. [特性](#) +* 2. [使用方法](#-1) + * 2.1. [组件方式](#-1) + * 2.1.1. [常用组件绑定器](#-1) + * 2.1.2. [属性绑定器](#-1) + * 2.1.3. [类型绑定器](#-1) + * 2.2. [代码方式](#-1) + * 2.2.1. [MonoBehaviour 自动绑定](#MonoBehaviour) + * 2.2.2. [MonoBehaviour 手动绑定](#MonoBehaviour-1) + * 2.2.3. [手动绑定任意对象](#-1) +* 3. [工作模式](#-1) + * 3.1. [被动回调模式](#-1) + * 3.2. [主动更新模式](#-1) +* 4. [内建类型](#-1) + * 4.1. [Attribute](#Attribute) + * 4.1.1. [Bind Value Attribute](#BindValueAttribute) + * 4.1.2. [Bind Type Attribute](#BindTypeAttribute) + * 4.2. [Data Context](#DataContext) + * 4.3. [Data Binder](#DataBinder) + * 4.4. [Data Converter](#DataConverter) + * 4.5. [Component Binder](#ComponentBinder) + * 4.6. [Bind Updater](#BindUpdater) + * 4.7. [Bind Map](#BindMap) +* 5. [内建组件](#-1) +* 6. [自定义扩展](#-1) + * 6.1. [Custom Data Binder](#CustomDataBinder) + * 6.2. [Custom Component Binder](#CustomComponentBinder) + * 6.3. [Custom Binder Editor](#CustomBinderEditor) + * 6.4. [Custom Data Converter](#CustomDataConverter) +* 7. [注意事项](#-1) +* 8. [扩展 -- TextMeshPro](#--TextMeshPro) + + + + +*** + +## 1. 特性 +* 支持双向绑定 +* 支持多数据源和多目标对象 +* 支持任意组件的任意属性和字段绑定 +* 支持数据源和目标数据类型不同时的自动类型转换 +* 提供大量内置组件的常用属性绑定器 +* 任意运行时对象的属性和字段绑定 +* 提供数据容器以按组划分数据使用域 +* 可扩展自定义数据绑定器、自定义类型转换器 + +*** + +## 2. 使用方法 +### 2.1. 组件方式 +#### 2.1.1. 常用组件绑定器 +可以使用内置的绑定器组件直接将常见UI组件的属性设置成数据源或者数据目标: + +![Text Binder](images/UBind_Sample_TextBinder.png) + +#### 2.1.2. 属性绑定器 +如果需要操作自定义组件,或者未内置提供专用绑定器的组件,则可以使用更为通用的 **PropertyBinder**,简单设置即可绑定任意组件的任意属性字段: + +![Property Binder](images/UBind_Sample_PropertyBinder.png) + +#### 2.1.3. 类型绑定器 +如果需要将一个数据类绑定到对应的UI,则只需要使用 **TypeBinder**,指定数据类的程序集和类名,然后将对应属性字段与UI依次绑定,然后在提供数据的逻辑代码中,编码绑定数据源即可: + +``` cs +public class UBindSamplePlayerData +{ + public string Name; + public int Exp; + public float Stat; + public float PlayTime; +} +``` + +![Type Binder](images/UBind_Sample_TypeBinder.png) + +``` cs +public class UBindSampleGameManager +{ + public UBindSamplePlayerData Player; + + public void Awake() + { + Player = new UBindSamplePlayerData() {Name = "Player",}; + UBind.BindSource("PlayerData", Player); + } +} +``` +### 2.2. 代码方式 +#### 2.2.1. MonoBehaviour 自动绑定 +通过继承 **BindableMonoBehaviour** 获得自动处理属性和字段绑定、解绑的能力。 + +使用 **BindValue** Attribute 来标记需要绑定基础类型数据: +``` cs +public class ExampleMonoBehaviour : BindableMonoBehaviour +{ + [BindValueSource("ValueKey")] + public string ValueSource; + + [BindValueTarget("ValueKey")] + public string ValueTarget; +} +``` +使用 **BindType** Attribute 来标记需要绑定类和结构体数据: +``` cs +public class ExampleData +{ + public string Value; +} + +public class ExanokeMonoBehaviour : BindableMonoBehaviour +{ + [BindTypeSource("TypeKey")] + public ExampleData DataSource; + + [BindTypeTarget("TypeKey")] + public ExampleData DataTarget; +} +``` +#### 2.2.2. MonoBehaviour 手动绑定 +对于无法使用继承的自定义 **Monobehaviour** 对象,可以在 **OnEnable / OnDisable**方法中添加如下代码,手动调用 **BindMap** 的绑定和解绑接口,可以获得和自动绑定一样的效果: +``` cs +public class ExanokeMonoBehaviour : MonoBehaviour +{ + [BindValueSource("ValueKey")] + public string ValueSource; + + [BindValueTarget("ValueKey")] + public string ValueTarget; + + public void OnEnable() + { + BindMap.Bind(this); + } + + public void OnDisable() + { + BindMap.UnBind(this); + } +} +``` +#### 2.2.3. 手动绑定任意对象 +通过调用 **UBind** 的多种重载接口,可以实现对运行时的数值、属性、字段、类对象、结构体对象进行绑定,如果需要在特定时间进行绑定和解绑操作,则需要自行缓存返回的 **DataBinder** 对象: +``` cs +public class ExampleData +{ + public string Value; +} + +public class ExampleClass +{ + public string ValueSource; + public string ValueTarget; + + public ExampleData TypeSource; + public ExampleData TypeTarget; + + private DataBinder _runtimeValueSourceBinder; + private DataBinder _runtimeValueTargetBinder; + + private DataBinder _runtimeTypeSourceBinder; + private DataBinder _runtimeTypeTargetBinder; + + public void BindTest() + { + _runtimeValueSourceBinder = UBind.BindSource("ValueKey", () => ValueSource); + _runtimeValueTargetBinder = UBind.BindTarget("ValueKey", value => ValueTarget = value); + + _runtimeTypeSourceBinder = UBind.BindSource("TypeKey", TypeSource); + _runtimeTypeTargetBinder = UBind.BindTarget("TypeKey", TypeTarget); + } + + public void UnBindTest() + { + _runtimeValueSourceBinder.UnBind(); + _runtimeValueTargetBinder.UnBind(); + + _runtimeTypeSourceBinder.UnBind(); + _runtimeTypeTargetBinder.UnBind(); + } +} +``` +需要注意的是,在以上的例子中,数据源和数据目标各生成了一个绑定器,这是默认并且推荐的使用方式,以便于支持多数据源、多数据目标。但是数值类的绑定 (**RuntimeValueBinder\**) 也可以使用下面的方式简化调用,会同时返回数据源绑定器和数据目标绑定器: +``` cs +public class ExampleClass +{ + public string Source; + public string Target; + + private DataBinder _sourceBinder; + private DataBinder _targetBinder; + + public void BindTest() + { + (_sourceBinder, _targetBinder) = UBind.Bind("Key", () => Source, value => Target = value); + } + + public void UnBindTest() + { + _sourceBinder.UnBind(); + _targetBinder.UnBind(); + } +} +``` + +*** + + +## 3. 工作模式 +### 3.1. 被动回调模式 +> **OnValueChangedTrigger** -> **DataBinder**(Source) --> **DataConverter** --> **DataBinder**(Target) + +默认推荐使用的模式,此时 **DataBinder** 的 **NeedUpdate** 属性为 **false**,数据由数据源提供的数值变化回调触发刷新,通知到数据源绑定器,广播给所有的数据目标绑定器,再经由数据转换器转换成目标数据类熊。 + +### 3.2. 主动更新模式 +> **BindUpdater** -> **DataBinder**(Source) --> **DataConverter** --> **DataBinder**(Target) + +当数据源不具备主动触发数据变化的能力时,框架提供统一的更新周期来主动检测数值变化,但这个模式无法避免的会造成性能损耗,应尽量减少使用,比较适合快速原型阶段。在这个模式下,**DataBinder** 的 **NeedUpdate** 属性为 **true**,且需要实现 **AddListener()** 和 **RemoveListener()** 方法实现具体的回调注册和注销。框架在 **BindUpdater** 组件中统一按周期触发所有数据源的 **UpdateSource()** 方法以实现数据变化检测和数据更新广播。 + +*** + +## 4. 内建类型 +### 4.1. Attribute +#### 4.1.1. Bind Value Attribute +用于在拥有处理绑定关系能力的类中标记需要绑定的属性和字段,只推荐绑定常见基础数据类型。被标记对象会动态创建 **RuntimeValueBinder** 进行处理。 +#### 4.1.2. Bind Type Attribute +与 **BindValueAttribute** 的不同,用于标记自定义类和结构体类型对象,会动态创建 **RuntimeTypeBinder** 进行处理。 +### 4.2. Data Context +数据容器,用于维护一组 Data Binder,可以包含多个数据源和数据目标点。每个数据容器相互独立。 + +### 4.3. Data Binder +数据绑定器,用于将数据与具体的对象和其属性进行绑定,可以用于接收和广播数据。 +|属性|描述| +|-|-| +|Target|数据目标对象。| +|Context|数据容器的 Key 值,默认为 Default,无特殊需求可保持默认不设置。| +|Key|目标数据的 Key 值,是单个数据容器内数据的唯一标识。| +|Direction|数据的传递方向,Source Target 标识当前绑定器作为数据接收者。| +|UpdateType|对于未提供数据变化回调的目标对象,数据采用 Update 模式检测变化是否发生,此时需要指定 Update 的时机。| + +### 4.4. Data Converter +当数据源和数据目标的数据类型不同时,会使用与 **(sourceType, targetType)** 对应的数据转换器尝试转换。 + +默认的转换器 **CommonConverter** 的实现如下,可以通过修改 **DataConverter.Default** 来替换: +``` cs +Convert.ChangeType(object data, Type type); +``` +可以按需要使用以下接口提前注册特定类型的自定义转换器: +``` cs +DataConvert.Register(Type sourceType, Type targetType, DataConverter dataConverter); +``` + +### 4.5. Component Binder +数据绑定器的 Unity Component 版本,需要与一个具体的绑定器实现泛型绑定,用于实现组件数据的绑定。 + +### 4.6. Bind Updater +基于 **MonoBehaviour** 生命周期实现,用于统一维护需要主动更新数据的 **DataBinder** 的更新周期。 + +### 4.7. Bind Map + + +*** + + +## 5. 内建组件 +|组件|绑定对象类型|默认绑定属性|绑定属性类型| +|-|-|-|-| +|Text Binder|Text|text|string| +|Text FontSize Binder|Text|fontSize|int| +|InputField Binder|InputField|text|string| +|Slider Binder|Slider|value|float| +|Scrollbar Binder|Scrollbar|value|float| +|Dropdown Binder|Dropdown|value|int| +|Dropdown List Binder|Dropdown|options|List| +|CanvasGroup Binder|CanvasGroup|alpha|float| +|Toggle Binder|Toggle|value|bool| +|Color Binder|Graphic|color|Color| +|Image Binder|Image|sprite|Sprite| +|Image FillAmount Binder|Image|fillAmount|float| +|RawImage Binder|RawImage|texture|Texture| +|Property Binder|Component||| +|Type Binder|Component|| + +*** + +## 6. 自定义扩展 +### 6.1. Custom Data Binder +通过继承 **DataBinder** 实现一个特定对象和属性的运行时数据绑定器: +``` cs +public class RuntimeImageFillAmountBinder : DataBinder +{ + public override void SetData(float data) + { + Target.fillAmount = data; + } + + public override float GetData() + { + return Target.fillAmount; + } +} +``` + +### 6.2. Custom Component Binder +如果需要用作组件,则需要额外实现对应的 **ComponentBinder**: +``` cs +[AddComponentMenu("Data Binding/Image FillAmount Binder")] +public class ImageFillAmountBinder : ComponentUpdateBinder +{ +} +``` + +### 6.3. Custom Binder Editor +如果组件需要保持基础组件样式并且扩展自定义属性和样式,则需要实现对应的 **ComponentBinderEditor**,与绑定器组件和运行时绑定器泛型关联: +``` cs +#if UNITY_EDITOR +using UnityEditor; + +[CustomEditor(typeof(ImageFillAmountBinder)), UnityEditor.CanEditMultipleObjects] +public class ImageFillAmountBinderEditor : ComponentBinderEditor +{ +} +#endif +``` + +### 6.4. Custom Data Converter +如果需要在传递不同数据类型,并且数据不是 **Convert.ChangeType()** 可以处理的,则需要实现该类型转换的自定义数据转换器: +``` cs +public class CustomDataConverter : DataConverter +{ + public object To(object data, Type targetType) + { + object result; + // To do something... + return result; + } +} +``` +需要使用这些绑定器之前,比如游戏初始化时,注册自定的绑定器: +``` cs +var sourcetType = sourceData.GetType(); +var targetType = targetData.GetType(); +DataConverter.Register((sourceType, targetType), new CustomDataConverter()); +``` + +*** + +## 7. 注意事项 +* OnValueChanged 仅数据源可用。 +* 所有参数必须在编辑器模式配置,运行时修改参数无效。 +* TypeBinder 暂时仅支持单一层级属性的简单数据类。 +* 尽管组件支持不同数据类型的自动转换,但任然建议直接传递相同的数据类型以优化性能。 +* 多个数据源之间的数据不会被同步,如果数据源之间也需要同步需要将 Direction 设置成 Both。 +* PropertyBinder 和 TypeBinder 依赖反射实现,但由于某些原生组件的属性封装,直接反射修改字段并不能刷新显示,可能需要操作对应的属性,或者定制专用绑定器。 + +*** + +## 8. 扩展 -- TextMeshPro +* TMP Text Binder +* TMP Text UI Binder +* TMP Input Field Binder \ No newline at end of file diff --git a/.github/images/UBind_OpenUpmLogo.png b/.github/images/UBind_OpenUpmLogo.png new file mode 100644 index 0000000000000000000000000000000000000000..9e08d45049d0a19ee62235166557c25d45c00b55 GIT binary patch literal 21922 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 WyEtXcmW%(gt5Ygxlrt5rF8wd3VcWF; literal 0 HcmV?d00001 diff --git a/package.json b/package.json index 7b9856f..0c6040c 100644 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "com.ls9512.ubind", "displayName": "UBind", - "description": "UBind һ Unity ֵڿʵUI߼ݵĹ󶨡", - "version": "1.0.0", + "description": "UBind is a value binding component for Unity, which is used to quickly realize the association binding between UI and logical data.", + "version": "0.9.0", "unity": "2019.4.3f1", "license": "MIT", "repository": {