├── .npmignore ├── UnityVue.SG.dll ├── DynamicExpresso.Core.dll ├── Runtime ├── Unity.MonoBehaviours │ ├── res │ │ ├── imgDelete.png │ │ └── imgDelete.png.meta │ ├── res.meta │ ├── RTime.cs.meta │ ├── DataProvider.cs.meta │ ├── ComponentBinder.cs.meta │ ├── DataFlowGroup.cs.meta │ ├── DestroyTrigger.cs.meta │ ├── ReactiveBehaviour.cs.meta │ ├── UnityObject_GetLifeKeeper.cs.meta │ ├── DataBinderUI.uxml.meta │ ├── DataBinderExpressionUI.uxml.meta │ ├── RTime.cs │ ├── ComponentBinderEditor.cs.meta │ ├── DestroyTrigger.cs │ ├── DataBinderUI.uxml │ ├── DataProvider.cs │ ├── DataBinderExpressionUI.uxml │ ├── DataFlowGroup.cs │ ├── ReactiveBehaviour.cs │ ├── ComponentBinder.cs │ ├── UnityObject_GetLifeKeeper.cs │ └── ComponentBinderEditor.cs ├── DataSource │ ├── IValuedData.cs │ ├── IgnoreProxyAttribute.cs │ ├── RList.cs.meta │ ├── RSet.cs.meta │ ├── RefData.cs.meta │ ├── Signal.cs.meta │ ├── Computed.cs.meta │ ├── EventChannel.cs.meta │ ├── IDataProxy.cs.meta │ ├── IValuedData.cs.meta │ ├── RDictionary.cs.meta │ ├── RSortedSet.cs.meta │ ├── CollectionBase.cs.meta │ ├── ReactiveAttribute.cs.meta │ ├── IgnoreProxyAttribute.cs.meta │ ├── AtomicCollectionOperation.cs.meta │ ├── Signal.cs │ ├── CollectionBase.cs │ ├── AtomicCollectionOperation.cs │ ├── EventChannel.cs │ ├── Computed.cs │ ├── RefData.cs │ ├── RSet.cs │ ├── RSortedSet.cs │ └── ReactiveAttribute.cs ├── AssemblyInfo.cs ├── Core.meta ├── Utils.meta ├── DataSource.meta ├── Extends.meta ├── Extensions.meta ├── BBBirder.UnityVue.asmdef.meta ├── Extends │ ├── UGUIEx.meta │ ├── FairyGUIEx.meta │ └── UIToolkitEx.meta ├── RuntimeObjects.meta ├── Unity.MonoBehaviours.meta ├── AssemblyInfo.cs.meta ├── Core │ ├── Logger.cs.meta │ ├── IWatchable.cs.meta │ ├── WatchScope.cs.meta │ ├── CSReactive.Update.cs.meta │ ├── CSReactive.Watch.cs.meta │ ├── DataFlowRegistry.cs.meta │ ├── GlobalTrackerData.cs.meta │ ├── IScopeLifeKeeper.cs.meta │ ├── ScopeCollection.cs.meta │ ├── IScopeLifeKeeper.cs │ ├── GlobalTrackerData.cs │ ├── ScopeCollection.cs │ ├── Logger.cs │ ├── WatchScope.cs │ ├── IWatchable.cs │ └── CSReactive.Watch.cs ├── UnityVueDriver.cs.meta ├── Utils │ ├── CastUtils.cs.meta │ └── CastUtils.cs ├── Extensions │ ├── JsonExtensions.cs.meta │ ├── WatchedExtension.cs.meta │ ├── UIToolKitExtensions.cs.meta │ ├── UIToolKitExtensions.cs │ └── JsonExtensions.cs ├── RuntimeObjects │ ├── IDataBinder.cs.meta │ ├── BindableAttributes.cs.meta │ └── IDataBinder.cs ├── ScopeLifeKeeperExtensions.cs.meta ├── BBBirder.UnityVue.asmdef └── Experimental~ │ └── ReactiveDynamic.cs ├── LICENSE.md.meta ├── README.md.meta ├── package.json.meta ├── Editor.meta ├── Internals.meta ├── Runtime.meta ├── Tests.meta ├── Documentation.meta ├── Editor ├── DataSource.meta ├── Extensions.meta ├── UnityVue.Editor.asmdef.meta ├── Extensions │ ├── StringExtension.cs │ └── StringExtension.cs.meta ├── OdinProcessor.cs.meta ├── RefDataDrawer.cs.meta ├── ComputedOdinDrawer.cs.meta ├── RefDataOdinDrawer.cs.meta ├── ScopeItemUI.uxml.meta ├── TrackerWindowUI.uxml.meta ├── RefDataOdinDrawer.cs ├── TrackerWindow.cs.meta ├── ComputedOdinDrawer.cs ├── UnityVue.Editor.asmdef ├── ScopeItemUI.uxml ├── RefDataDrawer.cs ├── TrackerWindowUI.uxml └── OdinProcessor.cs ├── Samples~ └── SimpleCompute │ ├── SimpleCompute.unity.meta │ ├── BBBirder.UnityVue.SimpleCompute.asmdef.meta │ ├── CubeData.cs.meta │ ├── BBBirder.UnityVue.SimpleCompute.asmdef │ └── CubeData.cs ├── Tests ├── BBBirder.UnityVue.Tests.asmdef.meta ├── BasicTests.cs.meta ├── CollectionTests.cs.meta ├── LifeKeeperTests.cs.meta ├── BBBirder.UnityVue.Tests.asmdef ├── LifeKeeperTests.cs ├── BasicTests.cs └── CollectionTests.cs ├── Internals ├── BBBirder.UnityVue.Internals.asmdef.meta ├── AssemblyInfo.cs.meta ├── BBBirder.UnityVue.Internals.asmdef └── AssemblyInfo.cs ├── .github └── workflows │ └── ci.yml ├── DotNetProj~ ├── Shared │ ├── IDataProxy.cs │ └── BBBirder.UnityVue.csproj ├── Test │ ├── Test.csproj │ └── Program.cs ├── UnityVue.SG │ ├── Resources │ │ └── ImplementInterfaceTemplate.txt │ ├── BinderAttributeTargetUnusedSuppressor.cs │ ├── UnityVue.SG.csproj │ ├── NotGenerated.Designer.cs │ ├── Templates.Designer.cs │ ├── LowAccessibility.Designer.cs │ ├── Extension.cs │ ├── Generator.cs │ ├── Templates.resx │ └── NotGenerated.resx └── UnityVueCSharp.sln ├── package.json ├── DynamicExpresso.Core.dll.meta ├── LICENSE.md ├── UnityVue.SG.dll.meta └── README.md /.npmignore: -------------------------------------------------------------------------------- 1 | VSProj~ 2 | .github 3 | .gitrepo 4 | -------------------------------------------------------------------------------- /UnityVue.SG.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labbbirder/UnityVue/HEAD/UnityVue.SG.dll -------------------------------------------------------------------------------- /DynamicExpresso.Core.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labbbirder/UnityVue/HEAD/DynamicExpresso.Core.dll -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/res/imgDelete.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/labbbirder/UnityVue/HEAD/Runtime/Unity.MonoBehaviours/res/imgDelete.png -------------------------------------------------------------------------------- /Runtime/DataSource/IValuedData.cs: -------------------------------------------------------------------------------- 1 | namespace BBBirder.UnityVue 2 | { 3 | public interface IValuedData : IWatchable 4 | { 5 | T GetValue(); 6 | } 7 | } -------------------------------------------------------------------------------- /LICENSE.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 936e6916cece4a948a3f918ea0be1466 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b3a194fdd53c4b948bf15392358274c4 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("BBBirder.UnityVue.Editor")] 4 | [assembly: InternalsVisibleTo("BBBirder.UnityVue.Tests")] 5 | 6 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: fd8de9c61bccc984394c003e3ea37fc2 3 | PackageManifestImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 241338e350dcf9c4e9fc0d41b85c2ea9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Internals.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cbc95766b3227d644aa18cbe688c6166 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c9d237a5db92a644ea0cd4572a30eaad 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7c048d00d4684474f9961c7aec67a6c9 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Documentation.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bc90efd8f0df3b344b64451e270b3400 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Core.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3dbf6385568718841bb37b23c10ecb18 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Utils.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5d3835c100ffc2b4a89b4cae23041655 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/DataSource.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ec5df4991c21499488c253329282777f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/Extensions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5c3205c5a3eece64ca26c7e6031fee32 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Editor/UnityVue.Editor.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a60dbd22165f16c41bb4cb182ecd9250 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/DataSource.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2131198695a45154c8e77a2f933b0ea8 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Extends.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ef29dbfebe074e144b1a88c32ccaf699 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Extensions.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e755605adb49fe541b9f5d4604e5fc30 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/BBBirder.UnityVue.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 341d2edef5a2cea4397119d73079cae4 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Extends/UGUIEx.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 419f61eaf2a2d644ab8350c05307c589 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/RuntimeObjects.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 18a17e4c31505e646a6b21be01f1d81e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/SimpleCompute/SimpleCompute.unity.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 777ed4734edc0d742b40d43c4b35b384 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Extends/FairyGUIEx.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9f24736b5a803ea42871c9a1f1ed3843 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Extends/UIToolkitEx.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 12985d7bbb4f94e419373dcfee97aa55 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 06d96817b5f6e044f941226a05a2a199 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/BBBirder.UnityVue.Tests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 49bc6ddab129c6c4a99d80193f4bb6e7 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Internals/BBBirder.UnityVue.Internals.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 95aeb07dadfa03a45a01222c5726ee41 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/res.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db3cad0709e99f64a9ad1cc1e3eb5f40 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Samples~/SimpleCompute/BBBirder.UnityVue.SimpleCompute.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6a2ba03bcc55bc049859544172b276fd 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Editor/Extensions/StringExtension.cs: -------------------------------------------------------------------------------- 1 | 2 | using System.Text.RegularExpressions; 3 | 4 | static partial class StringExtension 5 | { 6 | public static bool IsValidVarname(this string input) 7 | { 8 | return Regex.IsMatch(input, @"^[_a-zA-Z]+[_a-zA-Z0-9]*$"); 9 | } 10 | } -------------------------------------------------------------------------------- /Runtime/DataSource/IgnoreProxyAttribute.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | namespace BBBirder.UnityVue 4 | { 5 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Class)] 6 | public class IgnoreProxyAttribute : Attribute 7 | { 8 | 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Tests/BasicTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3c370978087a05546b87b2fd6d678626 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/OdinProcessor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3e600b28d15eba342ac2a82593ec7dfc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/RefDataDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f382463643f52364682660822b1b5294 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/AssemblyInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8f7228ae6b98fd34493f26487dbe3761 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/Logger.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 53d5b04932c035743a57d9f0f8e15792 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/CollectionTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 79e09087172f4bb4d9b60b72baea696c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/LifeKeeperTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 087b71db5f364074c997a1503c7f8669 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ComputedOdinDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ba4c42f8fbee68488bd616cd0e76f58 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/RefDataOdinDrawer.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: aac7ae352373f4346a26a102c0fa6299 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Internals/AssemblyInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f78734f44d6a061439cba7030c9baa1e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/IWatchable.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: d82ebbd66e96d2748875a17a07578284 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/WatchScope.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f76c955aa7a634e40a5a0f256ba938b5 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/RList.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 493d6fd584284a64293759d1302810aa 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/RSet.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6ef011cfb93b0bf4ab5377f21fd6a252 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/RefData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e8562fe9d61bc1a4a8767bba62fd5e2f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/Signal.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 87301043f4f800b43b3489c3363546bc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/UnityVueDriver.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 04435bde327873a4aa8e3a9e30da1899 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Utils/CastUtils.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5f90f0efd03365b438a5e96a4d9714c2 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/CSReactive.Update.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8133e307bbaa30c4b92fcac822d7c926 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/CSReactive.Watch.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 02b20af805c6c5c46916fde55e02617b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/DataFlowRegistry.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 6795e1586a31be24d9580b9137e7af7b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/GlobalTrackerData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2c9be9011f7491c4e81935b395030f84 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/IScopeLifeKeeper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0ca87f93034db71448e246ae983735dc 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Core/ScopeCollection.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 249853ae7fb471d48918906add7198ca 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/Computed.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 70118c9582a48f643bc6205330bb6c32 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/EventChannel.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f88bee814106196409090afb69ce804a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/IDataProxy.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 11edad6ebffb7184c8b76fb72979740f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/IValuedData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e89aac45c97bb77419253bba3b1a12c7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/RDictionary.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 193fc1379935d224380aa47bc79402d9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/RSortedSet.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: dc588093728e84f46adc87817361acb9 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Samples~/SimpleCompute/CubeData.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ee067027b37245245ab2204f34b3ba5f 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/Extensions/StringExtension.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7f0b0a1641a289c4abd2e4420b7ffef7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/CollectionBase.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 91b4c577d478e0441b330c4ff8edcf98 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/ReactiveAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: a1d691f428dd087409f28cbaed8d13c7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Extensions/JsonExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 85f4136108fd4d746a173681009baf02 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Extensions/WatchedExtension.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7e6e4a7190d2b1a44a5708754ed92969 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/RuntimeObjects/IDataBinder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0cffc303a2027794b808a64bd88b8e30 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/ScopeLifeKeeperExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e0c7b37f455f2c3468c0e25a130ffefb 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/RTime.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3452e4399c51b1c4ea3fa3daaed909b7 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/DataSource/IgnoreProxyAttribute.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8b091a8c3e409be4495fd5a0b328306b 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Extensions/UIToolKitExtensions.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cd409ef52c3b0bc47b16c700f426ba51 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/RuntimeObjects/BindableAttributes.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9bc36eb972c533f41aef61ae6b7cba24 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataProvider.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e573fb143f7c16f479ef9e95920fcdd0 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Create Tag 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - uses: actions/checkout@v2 13 | - uses: Klemensas/action-autotag@stable 14 | with: 15 | GITHUB_TOKEN: "${{ secrets.GITHUB_TOKEN }}" 16 | -------------------------------------------------------------------------------- /Runtime/DataSource/AtomicCollectionOperation.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 878d1aa3ab6c0554f9068f9d71f2397c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/ComponentBinder.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2f8f25b05ff20ec43b82299ea1a9950e 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataFlowGroup.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 562b03cf85acf414d9bbd9c805cd4b69 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DestroyTrigger.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 83a0f338e32d0274cb158809b4729537 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/ReactiveBehaviour.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 1ea2a77ed0303e140bd6c88c6d443e7c 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/ScopeItemUI.uxml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eeadd96cb39786a40b1b3e65a0d53b44 3 | ScriptedImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 2 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} 11 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/UnityObject_GetLifeKeeper.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 528d0f0e95cc3284484282e1f92fc77d 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Editor/TrackerWindowUI.uxml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 374bab72a44196644aec4294896ae047 3 | ScriptedImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 2 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} 11 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataBinderUI.uxml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: eb06b019921e7884dbfdeb06e17b60f5 3 | ScriptedImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 2 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} 11 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataBinderExpressionUI.uxml.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 67a9fedd041e41c48a972331b10b7c21 3 | ScriptedImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 2 7 | userData: 8 | assetBundleName: 9 | assetBundleVariant: 10 | script: {fileID: 13804, guid: 0000000000000000e000000000000000, type: 0} 11 | -------------------------------------------------------------------------------- /Runtime/Core/IScopeLifeKeeper.cs: -------------------------------------------------------------------------------- 1 | namespace BBBirder.UnityVue 2 | { 3 | public interface IScopeLifeKeeper 4 | { 5 | bool IsAlive { get; } 6 | /// 7 | /// NOTE: Remember to call `OnEnteredEnableState()` after state set to `true` 8 | /// 9 | bool IsEnabled { get; } 10 | 11 | SimpleList Scopes { get; } 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/RTime.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace BBBirder.UnityVue 4 | { 5 | public static class RTime 6 | { 7 | public static float time => UnityVueDriver.time; 8 | public static float fixedTime => UnityVueDriver.fixedTime; 9 | public static float unscaledTime => UnityVueDriver.unscaledTime; 10 | public static float fixedUnscaledTime => UnityVueDriver.fixedUnscaledTime; 11 | } 12 | } -------------------------------------------------------------------------------- /Internals/BBBirder.UnityVue.Internals.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBBirder.UnityVue.Internals", 3 | "rootNamespace": "", 4 | "references": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": false, 8 | "overrideReferences": false, 9 | "precompiledReferences": [], 10 | "autoReferenced": false, 11 | "defineConstraints": [], 12 | "versionDefines": [], 13 | "noEngineReferences": false 14 | } -------------------------------------------------------------------------------- /Editor/RefDataOdinDrawer.cs: -------------------------------------------------------------------------------- 1 | #if ODIN_INSPECTOR 2 | 3 | using System; 4 | using Sirenix.OdinInspector.Editor; 5 | using UnityEditor; 6 | using UnityEngine; 7 | 8 | namespace BBBirder.UnityVue.Editor 9 | { 10 | public class RefDataOdinDrawer : OdinValueDrawer> 11 | { 12 | protected override void DrawPropertyLayout(GUIContent label) 13 | { 14 | Property.Children[nameof(RefData.Value)].Draw(label); 15 | } 16 | } 17 | } 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /DotNetProj~/Shared/IDataProxy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace BBBirder.UnityVue 5 | { 6 | public class WatchablePayload { } 7 | public interface IWatchable 8 | { 9 | WatchablePayload Payload { get; } 10 | } 11 | 12 | public partial interface IDataProxy : IWatchable 13 | { 14 | void VisitWatchableMembers(Action visitor); 15 | } 16 | 17 | public class BindableAttribute : Attribute 18 | { 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /DotNetProj~/Test/Test.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Exe 5 | net6.0 6 | enable 7 | enable 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/ComponentBinderEditor.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 60f9e05b690f8ed429165c410c1b3eb1 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: 7 | - uiAssetRoot: {fileID: 9197481963319205126, guid: eb06b019921e7884dbfdeb06e17b60f5, type: 3} 8 | - uiAssetElement: {fileID: 9197481963319205126, guid: 67a9fedd041e41c48a972331b10b7c21, type: 3} 9 | executionOrder: 0 10 | icon: {instanceID: 0} 11 | userData: 12 | assetBundleName: 13 | assetBundleVariant: 14 | -------------------------------------------------------------------------------- /Editor/TrackerWindow.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: f6599d3c8cd84bb4f82072d62933bc8a 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: 7 | - m_ViewDataDictionary: {instanceID: 0} 8 | - rootUIAsset: {fileID: 9197481963319205126, guid: 374bab72a44196644aec4294896ae047, type: 3} 9 | - elementUIAsset: {fileID: 9197481963319205126, guid: eeadd96cb39786a40b1b3e65a0d53b44, type: 3} 10 | executionOrder: 0 11 | icon: {instanceID: 0} 12 | userData: 13 | assetBundleName: 14 | assetBundleVariant: 15 | -------------------------------------------------------------------------------- /Internals/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Buffers; 2 | using System.Runtime.CompilerServices; 3 | 4 | [assembly: InternalsVisibleTo("BBBirder.UnityVue")] 5 | [assembly: InternalsVisibleTo("BBBirder.UnityVue.Editor")] 6 | 7 | 8 | namespace BBBirder 9 | { 10 | /// 11 | /// Shared properties belonging to current module. 12 | /// 13 | /// 14 | internal static class ModuleProps 15 | { 16 | public static readonly ArrayPool ArrayPool = ArrayPool.Create(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /Editor/ComputedOdinDrawer.cs: -------------------------------------------------------------------------------- 1 | #if ODIN_INSPECTOR 2 | 3 | using System; 4 | using Sirenix.OdinInspector.Editor; 5 | using UnityEditor; 6 | using UnityEngine; 7 | 8 | namespace BBBirder.UnityVue.Editor 9 | { 10 | public class ComputedOdinDrawer : OdinValueDrawer> 11 | { 12 | protected override void DrawPropertyLayout(GUIContent label) 13 | { 14 | var v = Property.ValueEntry.WeakSmartValue as Computed; 15 | EditorGUILayout.LabelField(label?.text ?? "", v is null ? "" : v.Value.ToString()); 16 | } 17 | } 18 | } 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /Samples~/SimpleCompute/BBBirder.UnityVue.SimpleCompute.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBBirder.UnityVue.SimpleCompute", 3 | "rootNamespace": "", 4 | "references": [ 5 | "BBBirder.UnityVue", 6 | "BBBirder.UnityInjection", 7 | "com.bbbirder.directattribute" 8 | ], 9 | "includePlatforms": [], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": false, 12 | "overrideReferences": false, 13 | "precompiledReferences": [], 14 | "autoReferenced": true, 15 | "defineConstraints": [], 16 | "versionDefines": [], 17 | "noEngineReferences": false 18 | } -------------------------------------------------------------------------------- /Editor/UnityVue.Editor.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBBirder.UnityVue.Editor", 3 | "rootNamespace": "BBBirder.UnityVue.Editor", 4 | "references": [ 5 | "BBBirder.UnityVue", 6 | "BBBirder.UnityInjection", 7 | "BBBirder.Utils.Editor" 8 | ], 9 | "includePlatforms": [ 10 | "Editor" 11 | ], 12 | "excludePlatforms": [], 13 | "allowUnsafeCode": false, 14 | "overrideReferences": false, 15 | "precompiledReferences": [], 16 | "autoReferenced": true, 17 | "defineConstraints": [], 18 | "versionDefines": [], 19 | "noEngineReferences": false 20 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.bbbirder.unity-vue", 3 | "displayName": "Unity Vue", 4 | "description": "纯C#下实现的面向数据模块", 5 | "version": "1.4.6", 6 | "hideInEditor": false, 7 | "author": "bbbirder <502100554@qq.com>", 8 | "dependencies": { 9 | "com.bbbirder.unity-injection": "2.1.4", 10 | "com.bbbirder.utils": "0.1.0", 11 | "org.nuget.system.runtime.compilerservices.unsafe": "6.1.2" 12 | }, 13 | "samples": [ 14 | { 15 | "displayName": "SimpleCompute", 16 | "path": "Samples~/SimpleCompute" 17 | } 18 | ], 19 | "gitHead": "8856af7f13f652d12f057d26aa666a0b10b92d04" 20 | } 21 | -------------------------------------------------------------------------------- /Runtime/Core/GlobalTrackerData.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | 4 | namespace BBBirder.UnityVue 5 | { 6 | public partial class GlobalTrackerData 7 | { 8 | public static readonly GlobalTrackerData Instance = new(); 9 | #if ENABLE_UNITY_VUE_TRACKER 10 | public bool Enabled { get; private set; } = true; 11 | public RList> scopes { get; set; } = new(); 12 | static GlobalTrackerData() 13 | { 14 | CSReactive.Reactive(Instance); 15 | } 16 | #else 17 | public bool Enabled { get; private set; } = false; 18 | #endif 19 | } 20 | 21 | #if ENABLE_UNITY_VUE_TRACKER 22 | partial class GlobalTrackerData : IDataProxy { } 23 | #endif 24 | 25 | } -------------------------------------------------------------------------------- /DotNetProj~/UnityVue.SG/Resources/ImplementInterfaceTemplate.txt: -------------------------------------------------------------------------------- 1 | // NOTE: THIS IS AN AUTO-GENERATED FILE, NEVER MODIFY IT! 2 | // Generated by UnityVue 3 | // Author: bbbirder (labbbirder) 4 | // Assembly: {{module_name}} 5 | using System; 6 | using System.Collections.Generic; 7 | using System.Reflection; 8 | using BBBirder.UnityVue; 9 | 10 | {{ (target_namespace | string.empty) ? "" : "namespace "+target_namespace+"{" }} 11 | 12 | {{~ for declaringType in declaring_types ~}} 13 | partial {{declaringType.keyword}} {{declaringType.name}} { 14 | {{~ end ~}} 15 | [field: NonSerialized] WatchablePayload IWatchable.Payload { get; } = new(); 16 | {{~ for declaringType in declaring_types ~}} 17 | } 18 | {{~ end ~}} 19 | 20 | {{ (target_namespace | string.empty) ? "" : "}" }} 21 | -------------------------------------------------------------------------------- /DynamicExpresso.Core.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 48fe2b0cadb7a9e4580151fd09d3243d 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | validateReferences: 1 13 | platformData: 14 | - first: 15 | Any: 16 | second: 17 | enabled: 1 18 | settings: {} 19 | - first: 20 | Editor: Editor 21 | second: 22 | enabled: 0 23 | settings: 24 | DefaultValueInitialized: true 25 | - first: 26 | Windows Store Apps: WindowsStoreApps 27 | second: 28 | enabled: 0 29 | settings: 30 | CPU: AnyCPU 31 | userData: 32 | assetBundleName: 33 | assetBundleVariant: 34 | -------------------------------------------------------------------------------- /Runtime/BBBirder.UnityVue.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBBirder.UnityVue", 3 | "rootNamespace": "BBBirder.UnityVue", 4 | "references": [ 5 | "BBBirder.DirectAttribute", 6 | "BBBirder.UnityInjection", 7 | "BBBirder.UnityInjection.Editor", 8 | "BBBirder.Utils", 9 | "BBBirder.UnityVue.Internals" 10 | ], 11 | "includePlatforms": [], 12 | "excludePlatforms": [], 13 | "allowUnsafeCode": true, 14 | "overrideReferences": true, 15 | "precompiledReferences": [ 16 | "DynamicExpresso.Core.dll", 17 | "Sirenix.OdinInspector.Attributes.dll", 18 | "System.Runtime.CompilerServices.Unsafe.dll" 19 | ], 20 | "autoReferenced": true, 21 | "defineConstraints": [], 22 | "versionDefines": [], 23 | "noEngineReferences": false 24 | } 25 | -------------------------------------------------------------------------------- /Tests/BBBirder.UnityVue.Tests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "BBBirder.UnityVue.Tests", 3 | "rootNamespace": "", 4 | "references": [ 5 | "UnityEngine.TestRunner", 6 | "UnityEditor.TestRunner", 7 | "BBBirder.UnityVue", 8 | "com.bbbirder.directattribute", 9 | "BBBirder.UnityInjection" 10 | ], 11 | "includePlatforms": [], 12 | "excludePlatforms": [], 13 | "allowUnsafeCode": false, 14 | "overrideReferences": true, 15 | "precompiledReferences": [ 16 | "nunit.framework.dll", 17 | "Sirenix.OdinInspector.Attributes.dll", 18 | "Newtonsoft.Json.dll" 19 | ], 20 | "autoReferenced": false, 21 | "defineConstraints": [ 22 | "UNITY_INCLUDE_TESTS" 23 | ], 24 | "versionDefines": [], 25 | "noEngineReferences": false 26 | } 27 | -------------------------------------------------------------------------------- /Editor/ScopeItemUI.uxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DestroyTrigger.cs: -------------------------------------------------------------------------------- 1 | using UnityEngine; 2 | 3 | namespace BBBirder.UnityVue 4 | { 5 | internal class DestroyTrigger : MonoBehaviour, IScopeLifeKeeper 6 | { 7 | public bool IsAlive => !!this; 8 | private RefData _isEnabled = new(false); 9 | public virtual bool IsEnabled => InternalEnabledState; 10 | 11 | protected internal bool InternalEnabledState 12 | { 13 | get => _isEnabled; 14 | private set => _isEnabled.Value = value; 15 | } 16 | 17 | public SimpleList Scopes { get; } = new(); 18 | 19 | protected virtual void OnEnable() 20 | { 21 | InternalEnabledState = true; 22 | } 23 | 24 | protected virtual void OnDisable() 25 | { 26 | InternalEnabledState = false; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Samples~/SimpleCompute/CubeData.cs: -------------------------------------------------------------------------------- 1 | using BBBirder.UnityVue; 2 | using UnityEngine; 3 | 4 | [ExecuteAlways] 5 | public partial class CubeData : MonoBehaviour 6 | { 7 | void Start() 8 | { 9 | CSReactive.Reactive(this); 10 | this.WatchEffect(() => 11 | { 12 | var halfArea = (Length * Width) + (Width * Height) + (Length * Height); 13 | Area = halfArea * 2; 14 | }); 15 | 16 | this.WatchEffect(() => 17 | { 18 | Volume = Length * Width * Height; 19 | }); 20 | 21 | this.Compute(() => Length + Width + Height, v => Sum = v); 22 | } 23 | } 24 | 25 | partial class CubeData : IDataProxy 26 | { 27 | public float Length { get; set; } 28 | public float Width { get; set; } 29 | public float Height { get; set; } 30 | 31 | public float Sum { get; set; } 32 | public float Area { get; set; } 33 | public float Volume { get; set; } 34 | } 35 | -------------------------------------------------------------------------------- /Runtime/DataSource/Signal.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | namespace BBBirder.UnityVue 4 | { 5 | /// 6 | /// Used to listen and trigger an arbitrary state change. 7 | /// 8 | /// 9 | /// { 13 | /// signal.Detect(); 14 | /// Debug.Log("something happened"); 15 | /// }); 16 | /// 17 | /// stateChangeSignal.Trigger(); // outputs: "something happened" 18 | /// ]]> 19 | /// 20 | /// 21 | /// 22 | public class Signal 23 | { 24 | RefData inner = CSReactive.Ref(false); 25 | 26 | [MethodImpl(MethodImplOptions.NoOptimization)] 27 | public void Detect() 28 | { 29 | _ = inner.Value; 30 | } 31 | 32 | public void Trigger() 33 | { 34 | inner.Value ^= true; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /Runtime/DataSource/CollectionBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace BBBirder.UnityVue 6 | { 7 | public abstract partial class CollectionBase : IWatchableCollection 8 | { 9 | [field: NonSerialized] CollectionOperationType IWatchableCollection.operation { get; set; } 10 | [field: NonSerialized] public Action onAddItem { get; set; } 11 | [field: NonSerialized] public Action onRemoveItem { get; set; } 12 | [field: NonSerialized] public Action onClearItems { get; set; } 13 | 14 | [field: NonSerialized] WatchablePayload IWatchable.Payload { get; } = new(); 15 | 16 | public abstract object RawGet(object key); 17 | 18 | public abstract bool RawSet(object key, object value); 19 | 20 | public abstract void ClearAll(); 21 | 22 | public abstract void RemoveByKey(object key); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /Editor/RefDataDrawer.cs: -------------------------------------------------------------------------------- 1 | using UnityEditor; 2 | using UnityEngine; 3 | 4 | namespace BBBirder.UnityVue.Editor 5 | { 6 | [CustomPropertyDrawer(typeof(RefData<>), true)] 7 | public class RefDataDrawer : PropertyDrawer 8 | { 9 | public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) 10 | { 11 | var innerProp = property.FindPropertyRelative("__rawObject"); 12 | if (innerProp == null) 13 | { 14 | EditorGUI.LabelField(position, label); 15 | return; 16 | } 17 | 18 | EditorGUI.BeginChangeCheck(); 19 | EditorGUI.PropertyField(position, innerProp, label); 20 | // f = EditorGUI.FloatField(position, f); 21 | if (EditorGUI.EndChangeCheck()) 22 | { 23 | var refData = property.GetPropertyDesc().value as IWatchable; 24 | refData.Payload.onAfterSet?.Invoke(refData, "Value"); 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /DotNetProj~/Test/Program.cs: -------------------------------------------------------------------------------- 1 | 2 | using BBBirder.UnityVue; 3 | using com.asd.DDd; 4 | using System; 5 | 6 | var obj = new SkillData(); 7 | 8 | ; (obj as IDataProxy).VisitWatchableMembers(m => Console.WriteLine(m)); 9 | Console.WriteLine("Hello world"); 10 | namespace com.asd 11 | { 12 | namespace DDd 13 | { 14 | public partial record Root 15 | { 16 | internal partial class Foo : IDataProxy 17 | { 18 | int IWatchable.SyncId { get; set; } 19 | 20 | internal string name; 21 | private Bar bar; 22 | private int age; 23 | private List.Enumerator en; 24 | 25 | } 26 | internal class Bar : Foo { } 27 | } 28 | 29 | public partial class SkillData : IDataProxy 30 | { 31 | private float cooldown; 32 | private float cooldownMax; 33 | private BattlerData battler = new(); 34 | } 35 | public partial class BattlerData : IDataProxy 36 | { 37 | 38 | } 39 | 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 labbbirder 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. -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataBinderUI.uxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /Runtime/RuntimeObjects/IDataBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Buffers; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | 6 | namespace BBBirder.UnityVue 7 | { 8 | public interface IDataBinder : IScopeLifeKeeper 9 | { 10 | bool IsBinded { get; set; } 11 | // List ScopesFromMember { get; } 12 | void OnBind(); 13 | void OnUnbind(); 14 | 15 | void Bind() 16 | { 17 | if (IsBinded) return; 18 | 19 | IsBinded = true; 20 | OnBind(); 21 | 22 | var scp = default(WatchScope); 23 | scp = this.Watch(() => IsEnabled, v => 24 | { 25 | if (v) 26 | { 27 | scp.Dispose(); 28 | foreach (var a in this.GetBindAttributes()) 29 | { 30 | a.Enable(this); 31 | } 32 | } 33 | }); 34 | scp.Update(); 35 | } 36 | 37 | void Unbind() 38 | { 39 | if (!IsBinded) return; 40 | 41 | IsBinded = false; 42 | OnUnbind(); 43 | this.ReleaseScopes(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataProvider.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | #if ODIN_INSPECTOR 5 | using Sirenix.OdinInspector; 6 | #endif 7 | using UnityEngine; 8 | using UnityEngine.Pool; 9 | 10 | namespace BBBirder.UnityVue 11 | { 12 | [Obsolete("Need Review")] 13 | public abstract class DataProvider : ReactiveBehaviour 14 | { 15 | [Reactive] public IWatchable TypelessData { get; set; } 16 | public abstract Type DataType { get; } 17 | } 18 | 19 | [Obsolete("Need Review")] 20 | public abstract class DataProvider : DataProvider where T : IWatchable 21 | { 22 | #if ODIN_INSPECTOR 23 | [ShowInInspector] 24 | #endif 25 | public T Data 26 | { 27 | get => (T)TypelessData; 28 | set => TypelessData = value; 29 | } 30 | public override Type DataType => typeof(T); 31 | 32 | public static DataProvider Instance 33 | { 34 | get; 35 | private set; 36 | } 37 | 38 | protected virtual void Awake() 39 | { 40 | Instance = this; 41 | } 42 | 43 | protected override void OnDestroy() 44 | { 45 | base.OnDestroy(); 46 | if (Instance == this) Instance = null; 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /Runtime/DataSource/AtomicCollectionOperation.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using UnityEngine.Assertions; 3 | 4 | namespace BBBirder.UnityVue 5 | { 6 | public struct AtomicCollectionOperation : IDisposable 7 | { 8 | bool hasValue; 9 | IWatchableCollection collection; 10 | CollectionOperationType prevOperation; 11 | object key, item; 12 | internal AtomicCollectionOperation(IWatchableCollection collection, CollectionOperationType operation, object key, object item) 13 | { 14 | Assert.IsNotNull(collection); 15 | hasValue = true; 16 | this.collection = collection; 17 | this.key = key; 18 | this.item = item; 19 | prevOperation = collection.operation; 20 | collection.operation = operation; 21 | } 22 | 23 | public void Dispose() 24 | { 25 | if (!hasValue) return; 26 | switch (collection.operation) 27 | { 28 | case CollectionOperationType.Add: 29 | collection.onAddItem?.Invoke(collection, key, item); 30 | break; 31 | case CollectionOperationType.Remove: 32 | collection.onRemoveItem?.Invoke(collection, key, item); 33 | break; 34 | case CollectionOperationType.Clear: 35 | collection.onClearItems?.Invoke(collection); 36 | break; 37 | } 38 | collection.operation = prevOperation; 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataBinderExpressionUI.uxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /Editor/TrackerWindowUI.uxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /UnityVue.SG.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ff864acdcb3f57d429801fa010d1fa62 3 | labels: 4 | - RoslynAnalyzer 5 | PluginImporter: 6 | externalObjects: {} 7 | serializedVersion: 2 8 | iconMap: {} 9 | executionOrder: {} 10 | defineConstraints: [] 11 | isPreloaded: 0 12 | isOverridable: 1 13 | isExplicitlyReferenced: 1 14 | validateReferences: 1 15 | platformData: 16 | - first: 17 | : Any 18 | second: 19 | enabled: 0 20 | settings: 21 | Exclude Android: 1 22 | Exclude Editor: 1 23 | Exclude Linux64: 1 24 | Exclude OSXUniversal: 1 25 | Exclude WebGL: 1 26 | Exclude Win: 1 27 | Exclude Win64: 1 28 | - first: 29 | Android: Android 30 | second: 31 | enabled: 0 32 | settings: 33 | AndroidSharedLibraryType: Executable 34 | CPU: ARMv7 35 | - first: 36 | Any: 37 | second: 38 | enabled: 0 39 | settings: {} 40 | - first: 41 | Editor: Editor 42 | second: 43 | enabled: 0 44 | settings: 45 | CPU: AnyCPU 46 | DefaultValueInitialized: true 47 | OS: AnyOS 48 | - first: 49 | Standalone: Linux64 50 | second: 51 | enabled: 0 52 | settings: 53 | CPU: None 54 | - first: 55 | Standalone: OSXUniversal 56 | second: 57 | enabled: 0 58 | settings: 59 | CPU: None 60 | - first: 61 | Standalone: Win 62 | second: 63 | enabled: 0 64 | settings: 65 | CPU: None 66 | - first: 67 | Standalone: Win64 68 | second: 69 | enabled: 0 70 | settings: 71 | CPU: None 72 | - first: 73 | Windows Store Apps: WindowsStoreApps 74 | second: 75 | enabled: 0 76 | settings: 77 | CPU: AnyCPU 78 | userData: 79 | assetBundleName: 80 | assetBundleVariant: 81 | -------------------------------------------------------------------------------- /Runtime/DataSource/EventChannel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace BBBirder.UnityVue 6 | { 7 | /// 8 | /// A pure data helps to do event-like sending and receiving. 9 | /// 10 | public partial class EventChannel : CollectionBase 11 | { 12 | [NonSerialized] private readonly object _dummy = 0.BoxNumber(); 13 | [NonSerialized] Dictionary, Action> lut = new(); 14 | public override void ClearAll() 15 | { 16 | } 17 | 18 | public void Emit(T evt) 19 | { 20 | ; (this as IWatchableCollection).onAddItem?.Invoke(this, _dummy, evt); 21 | } 22 | 23 | public void AddListener(Action listener) 24 | { 25 | if (!lut.TryGetValue(listener, out var realListener)) 26 | { 27 | lut.Add(listener, realListener = (collection, _, evt) => listener((T)evt)); 28 | } 29 | 30 | ; (this as IWatchableCollection).onAddItem += realListener; 31 | } 32 | 33 | public void RemoveListener(Action listener) 34 | { 35 | if (lut.TryGetValue(listener, out var realListener)) 36 | { 37 | ; (this as IWatchableCollection).onAddItem -= realListener; 38 | lut.Remove(listener); 39 | } 40 | } 41 | 42 | public void ClearAllListeners() 43 | { 44 | lut.Clear(); 45 | ; (this as IWatchableCollection).onAddItem = null; 46 | } 47 | 48 | public override object RawGet(object key) 49 | { 50 | return null; 51 | } 52 | 53 | public override bool RawSet(object key, object value) 54 | { 55 | return false; 56 | } 57 | 58 | public override void RemoveByKey(object key) 59 | { 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /Runtime/Extensions/UIToolKitExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Linq.Expressions; 4 | using System.Numerics; 5 | using System.Reflection; 6 | using System.Runtime.CompilerServices; 7 | using UnityEngine.Assertions; 8 | using UnityEngine.UIElements; 9 | using static BBBirder.UnityVue.CastUtils; 10 | 11 | namespace BBBirder.UnityVue 12 | { 13 | public static class UIToolKitExtensions 14 | { 15 | #warning TODO: 非DEBUG模式下可以考虑更高效的实现 16 | public static WatchScope Bind(this INotifyValueChanged control, Expression> getter) 17 | { 18 | var bodyExp = getter.Body is UnaryExpression castOp ? castOp.Operand : getter.Body; 19 | var memberExp = bodyExp as MemberExpression; 20 | Assert.IsNotNull(memberExp, $"{bodyExp.NodeType} must be a member getter"); 21 | var property = memberExp.Member as PropertyInfo; 22 | Assert.IsNotNull(memberExp, "member must be a property"); 23 | var targetGetter = Expression.Lambda(memberExp.Expression).Compile() as Func; 24 | var target = targetGetter(); 25 | 26 | Func memberSetCaster = property.PropertyType.IsAssignableFrom(typeof(T)) ? 27 | null : v => DynamicCast(v, property.PropertyType); 28 | Func ctrlSetCaster = typeof(T).IsAssignableFrom(property.PropertyType) ? 29 | null : m => (T)DynamicCast(m, typeof(T)); 30 | control.RegisterValueChangedCallback(e => 31 | { 32 | property.SetValue(target, memberSetCaster != null ? memberSetCaster(e.newValue) : e.newValue); 33 | }); 34 | var scope = CSReactive.WatchEffect(() => 35 | { 36 | var memberValue = property.GetValue(target); 37 | control.SetValueWithoutNotify(ctrlSetCaster != null ? ctrlSetCaster(memberValue) : (T)memberValue); 38 | }); 39 | return scope; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /DotNetProj~/UnityVue.SG/BinderAttributeTargetUnusedSuppressor.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Immutable; 2 | using System.Linq; 3 | using BBBirder.UnityVue; 4 | using Microsoft.CodeAnalysis; 5 | using Microsoft.CodeAnalysis.Diagnostics; 6 | 7 | namespace UnityVue.SG 8 | { 9 | [DiagnosticAnalyzer(LanguageNames.CSharp)] 10 | public class BinderAttributeTargetUnusedSuppressor : DiagnosticSuppressor 11 | { 12 | private static readonly SuppressionDescriptor SuppressIDE0051 = 13 | new ( 14 | id: "SUPPRESS_IDE0051", 15 | suppressedDiagnosticId: "IDE0051", 16 | justification: "Suppress IDE0051 for private members marked with BindableAttribute"); 17 | 18 | public override ImmutableArray SupportedSuppressions 19 | => ImmutableArray.Create(SuppressIDE0051); 20 | 21 | public override void ReportSuppressions(SuppressionAnalysisContext context) 22 | { 23 | foreach (var diagnostic in context.ReportedDiagnostics) 24 | { 25 | if (diagnostic.Id == "IDE0051") 26 | { 27 | var tree = diagnostic.Location.SourceTree; 28 | if (tree is null) continue; 29 | 30 | var node = tree.GetRoot().FindNode(diagnostic.Location.SourceSpan); 31 | var symbol = context.GetSemanticModel(tree).GetDeclaredSymbol(node); 32 | if (symbol != null) 33 | { 34 | bool hasBindableAttribute = symbol.GetAttributes() 35 | .Any(attr => attr.AttributeClass.IsTypeOrSubTypeOf()); 36 | 37 | if (hasBindableAttribute) 38 | { 39 | context.ReportSuppression(Suppression.Create(SuppressIDE0051, diagnostic)); 40 | } 41 | } 42 | } 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /Runtime/DataSource/Computed.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | namespace BBBirder.UnityVue 5 | { 6 | public partial class Computed : IValuedData, IWatchable 7 | { 8 | internal T cached; 9 | WatchScope scope; 10 | Func getter; 11 | [field: NonSerialized] public WatchablePayload Payload { get; } = new(); 12 | 13 | public T Value 14 | { 15 | get 16 | { 17 | var topScope = CSReactive.s_executingScope; 18 | 19 | if (scope == null) return default; 20 | 21 | if (scope.isDirty) 22 | { 23 | CSReactive.RunScope(scope); 24 | } 25 | 26 | if (topScope != null) 27 | { 28 | foreach (var collection in scope.includedTables) 29 | { 30 | collection.Add(topScope); 31 | topScope.includedTables.Add(collection); 32 | } 33 | } 34 | 35 | return cached; 36 | } 37 | } 38 | 39 | [Obsolete("Use CSReactive.Computed instead")] 40 | internal Computed(Func getter) 41 | { 42 | this.getter = getter; 43 | } 44 | 45 | public T GetValue() => Value; 46 | 47 | internal void SetScope(WatchScope scope) 48 | { 49 | scope.isDirty = true; 50 | scope.autoClearDirty = false; 51 | this.scope = scope; 52 | } 53 | 54 | public void Update() 55 | { 56 | cached = getter(); 57 | } 58 | 59 | public static implicit operator T(Computed computed) => computed is null ? default : computed.Value; 60 | 61 | // public static implicit operator Func(Computed computed) => () => computed.Value; 62 | 63 | object IWatchable.RawGet(object key) => null; 64 | bool IWatchable.RawSet(object key, object value) => false; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /Runtime/Core/ScopeCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | 6 | namespace BBBirder.UnityVue 7 | { 8 | [DebuggerDisplay("accessed {accessSource.Item2} of {accessSource.Item1}")] 9 | public class ScopeCollection : ICollection 10 | { 11 | public (IWatchable watchable, object key) accessSource; // used for debug, can be removed safely 12 | // 一个Collection通常不会有太多元素,所以使用List实现 13 | private List m_List; 14 | public int Count => m_List.Count; 15 | 16 | public bool IsReadOnly => false; 17 | 18 | public WatchScope this[int index] 19 | { 20 | get => m_List[index]; 21 | } 22 | 23 | public ScopeCollection(int Capacity = 4) 24 | { 25 | m_List = new(Capacity); 26 | } 27 | 28 | public void Add(WatchScope scope) 29 | { 30 | if (Contains(scope)) return; 31 | m_List.Add(scope); 32 | } 33 | 34 | public bool Remove(WatchScope scope) 35 | { 36 | return m_List.Remove(scope); 37 | } 38 | 39 | public bool Contains(WatchScope scope) 40 | { 41 | return m_List.Contains(scope); 42 | } 43 | 44 | public void CopyTo(WatchScope[] array) 45 | { 46 | m_List.CopyTo(array); 47 | } 48 | 49 | public void Clear() 50 | { 51 | m_List.Clear(); 52 | } 53 | 54 | public void CopyTo(WatchScope[] array, int arrayIndex) 55 | { 56 | m_List.CopyTo(array, arrayIndex); 57 | } 58 | 59 | public List.Enumerator GetEnumerator() 60 | { 61 | return m_List.GetEnumerator(); 62 | } 63 | 64 | IEnumerator IEnumerable.GetEnumerator() 65 | { 66 | return GetEnumerator(); 67 | } 68 | 69 | IEnumerator IEnumerable.GetEnumerator() 70 | { 71 | return GetEnumerator(); 72 | } 73 | 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/DataFlowGroup.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using BBBirder.UnityVue; 5 | using UnityEngine; 6 | 7 | namespace BBBirder 8 | { 9 | public partial class DataFlowGroup : ReactiveBehaviour 10 | { 11 | [SerializeField] bool autoBind; 12 | public ReactiveBehaviour[] involvedComponents; 13 | List scopes = new(); 14 | public override bool IsEnabled 15 | { 16 | get 17 | { 18 | foreach (var comp in involvedComponents) 19 | { 20 | if (!comp.IsEnabled) return false; 21 | } 22 | 23 | return true; 24 | } 25 | } 26 | 27 | public override void OnBind() 28 | { 29 | DataFlowRegistry.BindAll(involvedComponents, this, scopes); 30 | // print(scopes.Count); 31 | } 32 | 33 | protected override void Awake() 34 | { 35 | base.Awake(); 36 | } 37 | 38 | protected override void OnDestroy() 39 | { 40 | base.OnDestroy(); 41 | } 42 | 43 | public override void OnUnbind() 44 | { 45 | foreach (var scp in scopes) 46 | { 47 | scp.Dispose(); 48 | } 49 | 50 | scopes.Clear(); 51 | } 52 | 53 | public void Reset() 54 | { 55 | CollectionPool.Get>(out var reactiveBehaviours); 56 | GetComponentsInChildren(reactiveBehaviours); 57 | involvedComponents = reactiveBehaviours 58 | .Where(b => b && DataFlowRegistry.HasPipeEnds(b.GetType())) 59 | .ToArray(); 60 | } 61 | 62 | internal void CollectComponents(bool includeChildren) 63 | { 64 | if (includeChildren) 65 | { 66 | involvedComponents = GetComponentsInChildren(true); 67 | } 68 | else 69 | { 70 | involvedComponents = GetComponents(); 71 | } 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /DotNetProj~/UnityVueCSharp.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.3.32825.248 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Test", "Test\Test.csproj", "{5BED740A-BDF3-4DC5-BCE4-19AB04260915}" 7 | EndProject 8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnityVue.SG", "UnityVue.SG\UnityVue.SG.csproj", "{1146ECD2-1D1A-431B-921E-94CB6ADEA1AE}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BBBirder.UnityVue", "Shared\BBBirder.UnityVue.csproj", "{15735B00-C04F-46E3-B772-3DCFF8B6AE5F}" 11 | EndProject 12 | Global 13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 14 | Debug|Any CPU = Debug|Any CPU 15 | Release|Any CPU = Release|Any CPU 16 | EndGlobalSection 17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 18 | {5BED740A-BDF3-4DC5-BCE4-19AB04260915}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 19 | {5BED740A-BDF3-4DC5-BCE4-19AB04260915}.Debug|Any CPU.Build.0 = Debug|Any CPU 20 | {5BED740A-BDF3-4DC5-BCE4-19AB04260915}.Release|Any CPU.ActiveCfg = Release|Any CPU 21 | {5BED740A-BDF3-4DC5-BCE4-19AB04260915}.Release|Any CPU.Build.0 = Release|Any CPU 22 | {1146ECD2-1D1A-431B-921E-94CB6ADEA1AE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 23 | {1146ECD2-1D1A-431B-921E-94CB6ADEA1AE}.Debug|Any CPU.Build.0 = Debug|Any CPU 24 | {1146ECD2-1D1A-431B-921E-94CB6ADEA1AE}.Release|Any CPU.ActiveCfg = Release|Any CPU 25 | {1146ECD2-1D1A-431B-921E-94CB6ADEA1AE}.Release|Any CPU.Build.0 = Release|Any CPU 26 | {15735B00-C04F-46E3-B772-3DCFF8B6AE5F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 27 | {15735B00-C04F-46E3-B772-3DCFF8B6AE5F}.Debug|Any CPU.Build.0 = Debug|Any CPU 28 | {15735B00-C04F-46E3-B772-3DCFF8B6AE5F}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {15735B00-C04F-46E3-B772-3DCFF8B6AE5F}.Release|Any CPU.Build.0 = Release|Any CPU 30 | EndGlobalSection 31 | GlobalSection(SolutionProperties) = preSolution 32 | HideSolutionNode = FALSE 33 | EndGlobalSection 34 | GlobalSection(ExtensibilityGlobals) = postSolution 35 | SolutionGuid = {43BEBBF1-90E1-4E53-B61A-2125F74DBF44} 36 | EndGlobalSection 37 | EndGlobal 38 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/ReactiveBehaviour.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace BBBirder.UnityVue 6 | { 7 | public abstract partial class ReactiveBehaviour : MonoBehaviour, IWatchable, IDataBinder 8 | { 9 | [field: NonSerialized] WatchablePayload IWatchable.Payload { get; } = new(); 10 | public RefData _isEnabled = new(false); 11 | 12 | [field: NonSerialized] SimpleList IScopeLifeKeeper.Scopes { get; } = new(); 13 | [field: NonSerialized] public bool IsBinded { get; set; } 14 | 15 | public virtual bool IsEnabled => InternalEnabledState; 16 | 17 | protected internal bool InternalEnabledState 18 | { 19 | get => _isEnabled; 20 | private set => _isEnabled.Value = value; 21 | } 22 | 23 | bool IScopeLifeKeeper.IsAlive => !!this; 24 | public IDataBinder AsDataBinder => this; 25 | 26 | protected virtual void OnEnable() 27 | { 28 | InternalEnabledState = true; 29 | } 30 | 31 | protected virtual void OnDisable() 32 | { 33 | InternalEnabledState = false; 34 | } 35 | 36 | public object RawGet(object key) 37 | { 38 | ReactiveAttribute.TryGetInternal(this, key, out var value); 39 | return value; 40 | } 41 | 42 | public bool RawSet(object key, object value) 43 | { 44 | return ReactiveAttribute.TrySetInternal(this, key, value); 45 | } 46 | 47 | /// 48 | /// Init `ReactiveBehaviour`, in which this will be watch, meanwhile, property IsBind will be watch. 49 | /// Once Isbind is set to TRUE, all watching members will be bind immediately. 50 | /// 51 | protected virtual void Awake() 52 | { 53 | AsDataBinder.Bind(); 54 | } 55 | 56 | protected virtual void OnDestroy() 57 | { 58 | AsDataBinder.Unbind(); 59 | ; (this as IWatchable).Payload.Clear(); 60 | } 61 | 62 | public virtual void OnBind() { } 63 | public virtual void OnUnbind() { } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /DotNetProj~/Shared/BBBirder.UnityVue.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {15735B00-C04F-46E3-B772-3DCFF8B6AE5F} 8 | Library 9 | Properties 10 | BBBirder.UnityVue 11 | BBBirder.UnityVue 12 | v4.8 13 | 512 14 | true 15 | 9.0 16 | 17 | 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /Editor/OdinProcessor.cs: -------------------------------------------------------------------------------- 1 | #if ODIN_INSPECTOR 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Linq; 5 | using System.Reflection; 6 | using Sirenix.OdinInspector; 7 | using Sirenix.OdinInspector.Editor; 8 | using UnityEngine; 9 | 10 | namespace BBBirder.UnityVue.Editor 11 | { 12 | public class RefDataOdinProcessor : OdinAttributeProcessor> 13 | { 14 | public override void ProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member, List attributes) 15 | { 16 | if (member.Name == nameof(RefData.Value)) 17 | attributes.Add(new ShowInInspectorAttribute()); 18 | } 19 | public override void ProcessSelfAttributes(InspectorProperty property, List attributes) 20 | { 21 | attributes.Add(new HideReferenceObjectPickerAttribute()); 22 | } 23 | } 24 | 25 | public class ComputedOdinProcessor : OdinAttributeProcessor> 26 | { 27 | public override void ProcessSelfAttributes(InspectorProperty property, List attributes) 28 | { 29 | attributes.Add(new HideReferenceObjectPickerAttribute()); 30 | } 31 | public override void ProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member, List attributes) 32 | { 33 | if (member.Name == nameof(Computed.Value)) 34 | { 35 | attributes.Add(new ShowInInspectorAttribute()); 36 | attributes.Add(new DisplayAsStringAttribute()); 37 | } 38 | } 39 | } 40 | 41 | public class DataProxyOdinProcessor : OdinAttributeProcessor 42 | { 43 | public override void ProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member, List attributes) 44 | { 45 | if (member is PropertyInfo property && IDataProxy.IsPropertyValid(property)) 46 | attributes.Add(new ShowInInspectorAttribute()); 47 | } 48 | } 49 | 50 | public class NotifyAttributeOdinProcessor : OdinAttributeProcessor 51 | { 52 | public override void ProcessChildMemberAttributes(InspectorProperty parentProperty, MemberInfo member, List attributes) 53 | { 54 | var notifyAttribute = attributes.OfType().FirstOrDefault(); 55 | if (notifyAttribute != null) 56 | { 57 | attributes.Add(new ShowInInspectorAttribute()); 58 | attributes.Add(new OnValueChangedAttribute($"@(this as IWatchable).Payload.onAfterSet?.Invoke(this,\"{notifyAttribute.TargetProperty}\")")); 59 | } 60 | } 61 | } 62 | } 63 | #endif 64 | -------------------------------------------------------------------------------- /DotNetProj~/UnityVue.SG/UnityVue.SG.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | netstandard2.0 5 | false 6 | 9.0 7 | bbbirder 8 | False 9 | true 10 | 11 | 12 | 13 | $(DefineConstants)TRACE;SCRIBAN_NO_ASYNC; 14 | 15 | 16 | 17 | $(DefineConstants)TRACE;SCRIBAN_NO_ASYNC; 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | True 33 | True 34 | LowAccessibility.resx 35 | 36 | 37 | True 38 | True 39 | NotGenerated.resx 40 | 41 | 42 | True 43 | True 44 | Templates.resx 45 | 46 | 47 | 48 | 49 | 50 | ResXFileCodeGenerator 51 | LowAccessibility.Designer.cs 52 | 53 | 54 | ResXFileCodeGenerator 55 | NotGenerated.Designer.cs 56 | 57 | 58 | PublicResXFileCodeGenerator 59 | Templates.Designer.cs 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /Runtime/DataSource/RefData.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | 5 | namespace BBBirder.UnityVue 6 | { 7 | [Serializable] 8 | public partial class RefData : IValuedData, IWatchable 9 | { 10 | // static bool s_allowImplicitConversion; 11 | 12 | // static RefData() 13 | // { 14 | // s_allowImplicitConversion = true 15 | // && typeof(T) != typeof(RefData) 16 | // && typeof(T) != typeof(object) 17 | // ; 18 | // } 19 | 20 | [UnityEngine.SerializeField] T __rawObject; 21 | 22 | [field: NonSerialized] WatchablePayload IWatchable.Payload { get; } = new(); 23 | 24 | IWatchable AsDataProxy => this; 25 | 26 | public T Value 27 | { 28 | get 29 | { 30 | AsDataProxy.Payload.onBeforeGet?.Invoke(this, "Value"); 31 | return __rawObject; 32 | } 33 | set 34 | { 35 | if (EqualityComparer.Default.Equals(__rawObject, value)) return; 36 | __rawObject = value; 37 | AsDataProxy.Payload.onAfterSet?.Invoke(this, "Value"); 38 | } 39 | } 40 | 41 | public RefData() 42 | { 43 | // mostly, deserialized by Unity 44 | // CSReactive.MakeProxy(this); 45 | } 46 | 47 | public RefData(T t) 48 | { 49 | __rawObject = t; 50 | } 51 | 52 | public T GetValue() => Value; 53 | 54 | bool RawSet(object key, TValue value) 55 | { 56 | if (key is not "Value") 57 | { 58 | return false; 59 | } 60 | 61 | __rawObject = RuntimeConverter.Convert(value); 62 | return true; 63 | } 64 | 65 | object IWatchable.RawGet(object key) 66 | { 67 | if (key is not "Value") 68 | { 69 | return null; 70 | } 71 | 72 | return __rawObject; 73 | } 74 | 75 | bool IWatchable.RawSet(object key, object value) 76 | { 77 | if (key is not "Value") 78 | { 79 | return false; 80 | } 81 | 82 | __rawObject = (T)value; 83 | return true; 84 | } 85 | 86 | public override string ToString() 87 | { 88 | return $"RefData<{TypeInfo.Info.shortName}>[{Value?.ToString()}]"; 89 | } 90 | 91 | public static implicit operator T(RefData self) 92 | { 93 | return self.Value; 94 | } 95 | 96 | // public static implicit operator RefData(T value) 97 | // { 98 | // if (s_allowImplicitConversion) 99 | // { 100 | // return CSReactive.Ref(value); 101 | // } 102 | // else 103 | // { 104 | // throw new($"RefData<{TypeInfo.Info.shortName}> is not allowed to convert implicitly, use `CSReactive.Ref` instead."); 105 | // } 106 | // } 107 | 108 | } 109 | } 110 | -------------------------------------------------------------------------------- /Tests/LifeKeeperTests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using BBBirder.UnityInjection; 5 | using BBBirder.UnityVue; 6 | using NUnit.Framework; 7 | using UnityEngine; 8 | using UnityEngine.TestTools; 9 | class BehaviourTest : ReactiveBehaviour 10 | { 11 | 12 | } 13 | 14 | class ScriptableObjectTest : ScriptableObject 15 | { 16 | 17 | } 18 | 19 | public class LifeKeeperTests : IPrebuildSetup 20 | { 21 | public static IEnumerable GetKeeperSources() 22 | { 23 | var goKeeper1 = new GameObject("LifeKeeper1") 24 | { 25 | hideFlags = HideFlags.HideAndDontSave 26 | }; 27 | yield return new TestCaseData(goKeeper1.GetLifeKeeper(),// DestroyTrigger 28 | new Action(() => GameObject.DestroyImmediate(goKeeper1)), 29 | new Action(enabled => goKeeper1.SetActive(enabled)) 30 | ); 31 | 32 | var goKeeper2 = new GameObject("LifeKeeper2") 33 | { 34 | hideFlags = HideFlags.HideAndDontSave 35 | }; 36 | var behav = goKeeper2.AddComponent(); 37 | yield return new TestCaseData(behav, // ReactiveBehaviour 38 | new Action(() => GameObject.DestroyImmediate(behav)), 39 | new Action(enabled => behav.enabled = enabled) 40 | ); 41 | 42 | var so = ScriptableObjectTest.CreateInstance(); 43 | so.hideFlags = HideFlags.HideAndDontSave; 44 | yield return new TestCaseData(so.GetLifeKeeper(), // Polling 45 | new Action(() => GameObject.DestroyImmediate(so)), 46 | null 47 | ); 48 | 49 | 50 | } 51 | 52 | [Test] 53 | [TestCaseSource(nameof(GetKeeperSources))] 54 | public void LifeKeeper_Enable_And_Destroy_Should_Works(IScopeLifeKeeper keeper, Action destroyer, Action enableSetter) 55 | { 56 | var cube = new Cube() 57 | { 58 | Width = 1, 59 | Height = 2, 60 | Length = 3, 61 | }; 62 | 63 | var volume0 = 0f; 64 | keeper.WatchEffect(() => 65 | { 66 | var c = cube; 67 | volume0 = c.Length * c.Width * c.Height; 68 | 69 | }, ScopeFlushMode.Immediate); 70 | 71 | Assert.AreEqual(6, volume0); 72 | 73 | cube.Width = cube.Height = cube.Length = 2; 74 | Assert.AreEqual(8, volume0); 75 | 76 | if (enableSetter != null) 77 | { 78 | enableSetter(false); 79 | 80 | cube.Width = cube.Height = cube.Length = 3; 81 | Assert.AreEqual(8, volume0); 82 | 83 | keeper.UpdateDirtyScopes(); 84 | Assert.AreEqual(27, volume0); 85 | 86 | cube.Width = cube.Height = cube.Length = 2; 87 | 88 | enableSetter(true); 89 | Assert.AreEqual(8, volume0); 90 | } 91 | 92 | destroyer(); 93 | 94 | UnityVueDriver.CheckAndRemoveDestroyedUnityObjectReferences(); 95 | 96 | cube.Width = cube.Height = cube.Length = 3; 97 | Assert.AreEqual(8, volume0); 98 | } 99 | 100 | 101 | public void Setup() 102 | { 103 | InjectionDriver.Instance.InstallAllAssemblies(); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /Runtime/Utils/CastUtils.cs: -------------------------------------------------------------------------------- 1 | 2 | using System; 3 | using System.Linq; 4 | using System.Runtime.CompilerServices; 5 | 6 | namespace BBBirder.UnityVue 7 | { 8 | public static class CastUtils 9 | { 10 | const int MIN_BOX_NUMBER = -256; 11 | const int MAX_BOX_NUMBER = 512; 12 | private static object[] boxed_numbers; 13 | public static readonly object True = true; 14 | public static readonly object False = false; 15 | 16 | static CastUtils() 17 | { 18 | boxed_numbers = new object[MAX_BOX_NUMBER - MIN_BOX_NUMBER]; 19 | for (int i = MIN_BOX_NUMBER; i < MAX_BOX_NUMBER; i++) 20 | { 21 | boxed_numbers[i - MIN_BOX_NUMBER] = i; 22 | } 23 | } 24 | 25 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 26 | public static object BoxNumber(this int n) 27 | { 28 | if (n >= MAX_BOX_NUMBER || n < MIN_BOX_NUMBER) 29 | { 30 | return n; //boxing 31 | } 32 | else 33 | { 34 | return boxed_numbers[n - MIN_BOX_NUMBER]; 35 | } 36 | } 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | public static object BoxNumber(this uint n) => BoxNumber((int)n); 40 | 41 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 42 | public static object BoxNumber(this byte n) => BoxNumber((int)n); 43 | 44 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 45 | public static object BoxNumber(this sbyte n) => BoxNumber((int)n); 46 | 47 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 48 | public static object BoxNumber(this short n) => BoxNumber((int)n); 49 | 50 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 51 | public static object BoxNumber(this ushort n) => BoxNumber((int)n); 52 | 53 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 54 | public static object BoxNumber(this bool n) => n ? True : False; 55 | 56 | 57 | public static object DynamicCast(object v, Type targetType) 58 | { 59 | if (v == null) return null; 60 | var targetTypeCode = Type.GetTypeCode(targetType); 61 | return targetTypeCode switch 62 | { 63 | // stub: code 2 64 | TypeCode.Boolean => Convert.ToBoolean(v), 65 | TypeCode.Char => Convert.ToChar(v), 66 | TypeCode.SByte => Convert.ToSByte(v), 67 | TypeCode.Byte => Convert.ToByte(v), 68 | TypeCode.Int16 => Convert.ToInt16(v), 69 | TypeCode.UInt16 => Convert.ToUInt16(v), 70 | TypeCode.Int32 => Convert.ToInt32(v), 71 | TypeCode.UInt32 => Convert.ToUInt32(v), 72 | TypeCode.Int64 => Convert.ToInt64(v), 73 | TypeCode.UInt64 => Convert.ToUInt64(v), 74 | TypeCode.Single => Convert.ToSingle(v), 75 | TypeCode.Double => Convert.ToDouble(v), 76 | TypeCode.Decimal => Convert.ToDecimal(v), 77 | TypeCode.DateTime => Convert.ToDateTime(v), 78 | // stub: code 17 79 | TypeCode.String => Convert.ToString(v), 80 | // stub: code 19 81 | _ => v, 82 | }; 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/ComponentBinder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using DynamicExpresso; 5 | using DynamicExpresso.Exceptions; 6 | using UnityEngine; 7 | 8 | namespace BBBirder.UnityVue 9 | { 10 | [Obsolete("Need Review")] 11 | public class ComponentBinder : ReactiveBehaviour 12 | { 13 | [Serializable] 14 | public struct ExpressionItem 15 | { 16 | public bool enable; 17 | public string expression; 18 | } 19 | public Component target; 20 | public List expressions = new() { new() { enable = true } }; 21 | public DataProvider dataProvider; 22 | private Dictionary activeScopes = new(); 23 | 24 | void Start() 25 | { 26 | var data = dataProvider.TypelessData; 27 | 28 | foreach (var expression in expressions) 29 | { 30 | if (!expression.enable) continue; 31 | StartExpression(expression.expression); 32 | } 33 | } 34 | 35 | public void StartExpression(string expression) 36 | { 37 | if (!Application.isPlaying) return; 38 | 39 | var data = dataProvider?.TypelessData; 40 | if (data is null) return; 41 | 42 | var action = CreatePreparedInterpreter().Parse(expression, new Parameter("this", dataProvider.DataType, null)); 43 | if (!activeScopes.ContainsKey(expression)) 44 | { 45 | var scp = CSReactive.WatchEffect(() => action.Invoke(data)); 46 | activeScopes.TryAdd(expression, scp); 47 | } 48 | } 49 | 50 | public void StopExpression(string expression) 51 | { 52 | if (!Application.isPlaying) return; 53 | if (activeScopes.TryGetValue(expression, out var scp)) 54 | { 55 | scp.Dispose(); 56 | } 57 | activeScopes.Remove(expression); 58 | } 59 | 60 | public Interpreter CreatePreparedInterpreter() 61 | { 62 | Interpreter interpreter = new Interpreter(); 63 | interpreter.Reference(typeof(Vector2)); 64 | interpreter.Reference(typeof(Vector3)); 65 | interpreter.Reference(typeof(Debug)); 66 | interpreter.SetVariable("target", target, target.GetType()); 67 | return interpreter; 68 | } 69 | 70 | internal string CompileTest(string expression) 71 | { 72 | if (!dataProvider) return null; 73 | try 74 | { 75 | CreatePreparedInterpreter().Parse(expression, new Parameter("this", dataProvider.DataType, null)); 76 | } 77 | catch (ParseException e) 78 | { 79 | return e.GetType().Name + ": " + expression.Insert(e.Position, "") + ""; 80 | } 81 | return null; 82 | } 83 | 84 | public override void OnBind() 85 | { 86 | foreach (var expression in expressions) 87 | { 88 | if (!expression.enable) continue; 89 | StartExpression(expression.expression); 90 | } 91 | } 92 | public override void OnUnbind() 93 | { 94 | foreach (var expression in expressions) 95 | { 96 | StopExpression(expression.expression); 97 | } 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /Runtime/Core/Logger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace BBBirder.UnityVue 4 | { 5 | public enum LoggerLevel 6 | { 7 | Verbose, 8 | Info, 9 | Warning, 10 | Error, 11 | } 12 | 13 | internal static class Logger 14 | { 15 | private static bool InUnityEnv; 16 | internal static LoggerLevel loggerLevel = LoggerLevel.Verbose; 17 | static Logger() 18 | { 19 | InUnityEnv = AppDomain.CurrentDomain.FriendlyName.Contains("Unity", StringComparison.OrdinalIgnoreCase); 20 | InUnityEnv = true; 21 | } 22 | 23 | #if UNITY_2021_3_OR_NEWER 24 | [UnityEngine.HideInCallstack] 25 | #endif 26 | public static void Verbose(params object[] args) 27 | { 28 | if (loggerLevel > LoggerLevel.Verbose) return; 29 | if (InUnityEnv) 30 | { 31 | #if UNITY_EDITOR 32 | UnityEngine.Debug.Log("[UnityVue] " + string.Join(" ", args)); 33 | #endif 34 | } 35 | else 36 | { 37 | using var scp = new ConsoleColorScope(ConsoleColor.Gray); 38 | Console.WriteLine("[UnityVue] " + string.Join(" ", args)); 39 | } 40 | } 41 | 42 | #if UNITY_2021_3_OR_NEWER 43 | [UnityEngine.HideInCallstack] 44 | #endif 45 | public static void Info(params object[] args) 46 | { 47 | if (loggerLevel > LoggerLevel.Info) return; 48 | if (InUnityEnv) 49 | { 50 | #if UNITY_EDITOR 51 | UnityEngine.Debug.Log("[UnityVue] " + string.Join(" ", args)); 52 | #endif 53 | } 54 | else 55 | { 56 | using var scp = new ConsoleColorScope(ConsoleColor.Cyan); 57 | Console.WriteLine("[UnityVue] " + string.Join(" ", args)); 58 | } 59 | } 60 | 61 | #if UNITY_2021_3_OR_NEWER 62 | [UnityEngine.HideInCallstack] 63 | #endif 64 | public static void Warning(params object[] args) 65 | { 66 | if (loggerLevel > LoggerLevel.Warning) return; 67 | if (InUnityEnv) 68 | { 69 | #if UNITY_EDITOR 70 | UnityEngine.Debug.LogWarning("[UnityVue] " + string.Join(" ", args)); 71 | #endif 72 | } 73 | else 74 | { 75 | using var scp = new ConsoleColorScope(ConsoleColor.Yellow); 76 | Console.WriteLine("[UnityVue] " + string.Join(" ", args)); 77 | } 78 | } 79 | 80 | #if UNITY_2021_3_OR_NEWER 81 | [UnityEngine.HideInCallstack] 82 | #endif 83 | public static void Error(params object[] args) 84 | { 85 | if (loggerLevel > LoggerLevel.Error) return; 86 | if (InUnityEnv) 87 | { 88 | #if UNITY_EDITOR 89 | if (args.Length == 1 && args[0] is Exception e) 90 | { 91 | UnityEngine.Debug.LogException(e); 92 | 93 | } 94 | else 95 | { 96 | UnityEngine.Debug.LogError("[UnityVue] " + string.Join(" ", args)); 97 | } 98 | #endif 99 | } 100 | else 101 | { 102 | Console.Error.WriteLine("[UnityVue] " + string.Join(" ", args)); 103 | } 104 | } 105 | 106 | struct ConsoleColorScope : IDisposable 107 | { 108 | ConsoleColor prevColor; 109 | public ConsoleColorScope(ConsoleColor color) 110 | { 111 | prevColor = Console.ForegroundColor; 112 | Console.ForegroundColor = color; 113 | } 114 | 115 | public void Dispose() 116 | { 117 | Console.ForegroundColor = prevColor; 118 | } 119 | } 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /DotNetProj~/UnityVue.SG/NotGenerated.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace UnityVue.SG { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class NotGenerated { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal NotGenerated() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UnityVue.SG.NotGenerated", typeof(NotGenerated).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性,对 51 | /// 使用此强类型资源类的所有资源查找执行重写。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// 查找类似 generated fail 的本地化字符串。 65 | /// 66 | internal static string AnalyzerDescription { 67 | get { 68 | return ResourceManager.GetString("AnalyzerDescription", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// 查找类似 OB001 的本地化字符串。 74 | /// 75 | internal static string AnalyzerID { 76 | get { 77 | return ResourceManager.GetString("AnalyzerID", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// 查找类似 fail to generate data proxy, reason: {0} 的本地化字符串。 83 | /// 84 | internal static string AnalyzerMessageFormat { 85 | get { 86 | return ResourceManager.GetString("AnalyzerMessageFormat", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// 查找类似 generated fail 的本地化字符串。 92 | /// 93 | internal static string AnalyzerTitle { 94 | get { 95 | return ResourceManager.GetString("AnalyzerTitle", resourceCulture); 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # UnityVue 2 | 3 | ![mono support](http://img.shields.io/badge/Mono-support-green) 4 | ![il2cpp support](http://img.shields.io/badge/IL2CPP-support-green) 5 | ![GitHub last commit](http://img.shields.io/github/last-commit/labbbirder/UnityVue) 6 | ![GitHub package.json version](http://img.shields.io/github/package-json/v/labbbirder/UnityVue) 7 | 8 | Unity纯C#版的VUE,运行时高效,运行时0GC。 9 | ## FEATURES 10 | 实现了几乎所有VUE特性,自行简单封装后可以无缝对接FGUI、UGUI、UTK等几乎所有UI方案 11 | * 支持全平台 12 | * 运行时无GC 13 | * 递归代理 14 | * 数据变化时,对相关作用域做脏标记。当前帧的Update结束后,对脏作用域进行刷新。 15 | * 支持List、Array等数组成员 16 | * 可自定义更新时机 : LateUpdate(post) & Immediate(sync) 17 | * ~~代理函数: Reactive & Ref~~ (可监听数据不再需要初始化) 18 | * 绑定函数: Watch & Compute & WatchEffect & Bind 19 | * MonoBehaviour响应式 20 | 21 | 其他功能 22 | * 数据可视化调试 (支持OdinInspector) 23 | * 作用域可视化调试 24 | * 出现循环读写情况时,控制台会输出警告 25 | * 响应式GameObject和组件 26 | * 作用域可以与任意一个引用类型绑定,同生命周期 27 | 28 | ## INSTALL 29 | 30 | execute command line: 31 | 32 | ```bash 33 | openupm add com.bbbirder.unity-vue 34 | ``` 35 | 36 | ## QUICK START 37 | 添加命名空间 38 | ```csharp 39 | using BBBirder.UnityVue; 40 | ``` 41 | 42 | 定义一个类型 43 | ```csharp 44 | using BBBirder.UnityVue; 45 | using Sirenix.OdinInspector; 46 | partial class CubeData : IDataProxy 47 | { 48 | [ShowInInspector] 49 | public float Length { get; set; } = 1; 50 | [ShowInInspector] 51 | public float Width { get; set; } = 1; 52 | [ShowInInspector] 53 | public float Height { get; set; } = 1; 54 | 55 | [ShowInInspector] 56 | public float Sum { get; set; } 57 | 58 | [ShowInInspector] 59 | public float Area { get; set; } 60 | 61 | [ShowInInspector] 62 | public float Volume { get; set; } 63 | } 64 | ``` 65 | 66 | 实现响应式 67 | ```csharp 68 | using UnityEngine; 69 | 70 | [ExecuteAlways] 71 | partial class CubeData : MonoBehaviour 72 | { 73 | 74 | void Awake() 75 | { 76 | CSReactive.Reactive(this); 77 | 78 | this.WatchEffect(() => 79 | { 80 | var halfArea = (Length * Width) + (Width * Height) + (Length * Height); 81 | Area = halfArea * 2; 82 | }); 83 | 84 | this.WatchEffect(() => 85 | { 86 | Volume = Length * Width * Height; 87 | }); 88 | 89 | this.Compute(() => Length + Width + Height, v => Sum = v); 90 | } 91 | } 92 | 93 | ``` 94 | 95 | ## Major Concepts 96 | 97 | ### IScopeLifeKeeper 98 | 99 | 作用域的生命管理对象。比如,一个Component下有多个作用域,当Component销毁时,这些作用域也要一并销毁,那么,此Component就适合作为一个`IScopeLifeKeeper`。同理,一个UI实体类也可以作为一个`IScopeLifeKeeper`。 100 | 101 | ### ReactiveBehaviour 102 | 103 | 继承自MonoBehaviour,并提供了数据绑定接口。 104 | 105 | ```csharp 106 | public class MyComp : ReactiveBehaviour 107 | { 108 | public RefData age = new(); 109 | public RefData ageNextYear = new(); 110 | 111 | [Watch] 112 | public int __WatchAge 113 | { 114 | get => age; 115 | set => ageNextYear.Value = value + 1; 116 | } 117 | 118 | [Watch(ScopeFlushMode.Immediate)] // 指定更新时机 119 | public int __WriteNextYearAge 120 | { 121 | get => age; 122 | set => print($"on set age to {value}"); 123 | } 124 | 125 | [Watch] 126 | // 使用WatchArgument`1包装类型获取上一个数值(previous value) 127 | public WatchArgument __WatchAge 128 | { 129 | get => age; 130 | set 131 | { 132 | var (curr,prev) = value; 133 | print($"age changed from {prev} to {curr}"); 134 | } 135 | } 136 | 137 | // 修改age会间接触发此方法更新 138 | [WatchEffect] 139 | void __PrintAges() 140 | { 141 | print($"age next year is {ageNextYear.Value}"); 142 | } 143 | 144 | public void Update() 145 | { 146 | if (Input.KeyDown(KeyCode.A)) 147 | { 148 | age.Value++; 149 | } 150 | } 151 | } 152 | 153 | ``` 154 | 155 | ## NOTES 156 | ### DynamicExpresso 157 | DynamicExpresso.dll并非官方原版,不要盲目更新它。此程序集在官方的基础上做了一些改动,已使其支持WebGL 158 | 159 | DynamicExpresso可以用在响应式组件或GameObject上,如:在Inspector下,给一个Component的字段赋字符串表达式 160 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/res/imgDelete.png.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9640e0395b3b07a4dbc07db0bae45a5b 3 | TextureImporter: 4 | internalIDToNameTable: [] 5 | externalObjects: {} 6 | serializedVersion: 12 7 | mipmaps: 8 | mipMapMode: 0 9 | enableMipMap: 0 10 | sRGBTexture: 1 11 | linearTexture: 0 12 | fadeOut: 0 13 | borderMipMap: 0 14 | mipMapsPreserveCoverage: 0 15 | alphaTestReferenceValue: 0.5 16 | mipMapFadeDistanceStart: 1 17 | mipMapFadeDistanceEnd: 3 18 | bumpmap: 19 | convertToNormalMap: 0 20 | externalNormalMap: 0 21 | heightScale: 0.25 22 | normalMapFilter: 0 23 | flipGreenChannel: 0 24 | isReadable: 0 25 | streamingMipmaps: 0 26 | streamingMipmapsPriority: 0 27 | vTOnly: 0 28 | ignoreMipmapLimit: 0 29 | grayScaleToAlpha: 0 30 | generateCubemap: 6 31 | cubemapConvolution: 0 32 | seamlessCubemap: 0 33 | textureFormat: 1 34 | maxTextureSize: 2048 35 | textureSettings: 36 | serializedVersion: 2 37 | filterMode: 1 38 | aniso: 1 39 | mipBias: 0 40 | wrapU: 1 41 | wrapV: 1 42 | wrapW: 0 43 | nPOTScale: 0 44 | lightmap: 0 45 | compressionQuality: 50 46 | spriteMode: 1 47 | spriteExtrude: 1 48 | spriteMeshType: 1 49 | alignment: 0 50 | spritePivot: {x: 0.5, y: 0.5} 51 | spritePixelsToUnits: 100 52 | spriteBorder: {x: 0, y: 0, z: 0, w: 0} 53 | spriteGenerateFallbackPhysicsShape: 1 54 | alphaUsage: 1 55 | alphaIsTransparency: 1 56 | spriteTessellationDetail: -1 57 | textureType: 8 58 | textureShape: 1 59 | singleChannelComponent: 0 60 | flipbookRows: 1 61 | flipbookColumns: 1 62 | maxTextureSizeSet: 0 63 | compressionQualitySet: 0 64 | textureFormatSet: 0 65 | ignorePngGamma: 0 66 | applyGammaDecoding: 0 67 | swizzle: 50462976 68 | cookieLightType: 0 69 | platformSettings: 70 | - serializedVersion: 3 71 | buildTarget: DefaultTexturePlatform 72 | maxTextureSize: 2048 73 | resizeAlgorithm: 0 74 | textureFormat: -1 75 | textureCompression: 1 76 | compressionQuality: 50 77 | crunchedCompression: 0 78 | allowsAlphaSplitting: 0 79 | overridden: 0 80 | ignorePlatformSupport: 0 81 | androidETC2FallbackOverride: 0 82 | forceMaximumCompressionQuality_BC6H_BC7: 0 83 | - serializedVersion: 3 84 | buildTarget: WebGL 85 | maxTextureSize: 2048 86 | resizeAlgorithm: 0 87 | textureFormat: -1 88 | textureCompression: 1 89 | compressionQuality: 50 90 | crunchedCompression: 0 91 | allowsAlphaSplitting: 0 92 | overridden: 0 93 | ignorePlatformSupport: 0 94 | androidETC2FallbackOverride: 0 95 | forceMaximumCompressionQuality_BC6H_BC7: 0 96 | - serializedVersion: 3 97 | buildTarget: Standalone 98 | maxTextureSize: 2048 99 | resizeAlgorithm: 0 100 | textureFormat: -1 101 | textureCompression: 1 102 | compressionQuality: 50 103 | crunchedCompression: 0 104 | allowsAlphaSplitting: 0 105 | overridden: 0 106 | ignorePlatformSupport: 0 107 | androidETC2FallbackOverride: 0 108 | forceMaximumCompressionQuality_BC6H_BC7: 0 109 | - serializedVersion: 3 110 | buildTarget: Server 111 | maxTextureSize: 2048 112 | resizeAlgorithm: 0 113 | textureFormat: -1 114 | textureCompression: 1 115 | compressionQuality: 50 116 | crunchedCompression: 0 117 | allowsAlphaSplitting: 0 118 | overridden: 0 119 | ignorePlatformSupport: 0 120 | androidETC2FallbackOverride: 0 121 | forceMaximumCompressionQuality_BC6H_BC7: 0 122 | spriteSheet: 123 | serializedVersion: 2 124 | sprites: [] 125 | outline: [] 126 | physicsShape: [] 127 | bones: [] 128 | spriteID: 5e97eb03825dee720800000000000000 129 | internalID: 0 130 | vertices: [] 131 | indices: 132 | edges: [] 133 | weights: [] 134 | secondaryTextures: [] 135 | nameFileIdTable: {} 136 | mipmapLimitGroupName: 137 | pSDRemoveMatte: 0 138 | userData: 139 | assetBundleName: 140 | assetBundleVariant: 141 | -------------------------------------------------------------------------------- /DotNetProj~/UnityVue.SG/Templates.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // 5 | // Changes to this file may cause incorrect behavior and will be lost if 6 | // the code is regenerated. 7 | // 8 | //------------------------------------------------------------------------------ 9 | 10 | namespace UnityVue.SG { 11 | using System; 12 | 13 | 14 | /// 15 | /// A strongly-typed resource class, for looking up localized strings, etc. 16 | /// 17 | // This class was auto-generated by the StronglyTypedResourceBuilder 18 | // class via a tool like ResGen or Visual Studio. 19 | // To add or remove a member, edit your .ResX file then rerun ResGen 20 | // with the /str option, or rebuild your VS project. 21 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 22 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 23 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 24 | public class Templates { 25 | 26 | private static global::System.Resources.ResourceManager resourceMan; 27 | 28 | private static global::System.Globalization.CultureInfo resourceCulture; 29 | 30 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 31 | internal Templates() { 32 | } 33 | 34 | /// 35 | /// Returns the cached ResourceManager instance used by this class. 36 | /// 37 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 38 | public static global::System.Resources.ResourceManager ResourceManager { 39 | get { 40 | if (object.ReferenceEquals(resourceMan, null)) { 41 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UnityVue.SG.Templates", typeof(Templates).Assembly); 42 | resourceMan = temp; 43 | } 44 | return resourceMan; 45 | } 46 | } 47 | 48 | /// 49 | /// Overrides the current thread's CurrentUICulture property for all 50 | /// resource lookups using this strongly typed resource class. 51 | /// 52 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 53 | public static global::System.Globalization.CultureInfo Culture { 54 | get { 55 | return resourceCulture; 56 | } 57 | set { 58 | resourceCulture = value; 59 | } 60 | } 61 | 62 | /// 63 | /// Looks up a localized string similar to // NOTE: THIS IS AN AUTO-GENERATED FILE, NEVER MODIFY IT! 64 | /// // Generated by UnityVue 65 | /// // Author: bbbirder (labbbirder) 66 | /// // Assembly: {{module_name}} 67 | ///using System; 68 | ///using System.Collections.Generic; 69 | ///using System.Reflection; 70 | ///using BBBirder.UnityVue; 71 | /// 72 | ///{{ (target_namespace | string.empty) ? "" : "namespace "+target_namespace+"{" }} 73 | /// 74 | ///{{~ for declaringType in declaring_types ~}} 75 | ///partial {{declaringType.keyword}} {{declaringType.name}} { 76 | ///{{~ end ~}} 77 | /// {{~ for m in auto_impl_properties ~}} 78 | /// [field: NonSeri [rest of string was truncated]";. 79 | /// 80 | public static string ImplementInterfaceTemplate { 81 | get { 82 | return ResourceManager.GetString("ImplementInterfaceTemplate", resourceCulture); 83 | } 84 | } 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /DotNetProj~/UnityVue.SG/LowAccessibility.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // 此代码由工具生成。 4 | // 运行时版本:4.0.30319.42000 5 | // 6 | // 对此文件的更改可能会导致不正确的行为,并且如果 7 | // 重新生成代码,这些更改将会丢失。 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace UnityVue.SG { 12 | using System; 13 | 14 | 15 | /// 16 | /// 一个强类型的资源类,用于查找本地化的字符串等。 17 | /// 18 | // 此类是由 StronglyTypedResourceBuilder 19 | // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 20 | // 若要添加或移除成员,请编辑 .ResX 文件,然后重新运行 ResGen 21 | // (以 /str 作为命令选项),或重新生成 VS 项目。 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class LowAccessibility { 26 | 27 | private static global::System.Resources.ResourceManager resourceMan; 28 | 29 | private static global::System.Globalization.CultureInfo resourceCulture; 30 | 31 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 32 | internal LowAccessibility() { 33 | } 34 | 35 | /// 36 | /// 返回此类使用的缓存的 ResourceManager 实例。 37 | /// 38 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 39 | internal static global::System.Resources.ResourceManager ResourceManager { 40 | get { 41 | if (object.ReferenceEquals(resourceMan, null)) { 42 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("UnityVue.SG.LowAccessibility", typeof(LowAccessibility).Assembly); 43 | resourceMan = temp; 44 | } 45 | return resourceMan; 46 | } 47 | } 48 | 49 | /// 50 | /// 重写当前线程的 CurrentUICulture 属性,对 51 | /// 使用此强类型资源类的所有资源查找执行重写。 52 | /// 53 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 54 | internal static global::System.Globalization.CultureInfo Culture { 55 | get { 56 | return resourceCulture; 57 | } 58 | set { 59 | resourceCulture = value; 60 | } 61 | } 62 | 63 | /// 64 | /// 查找类似 Accessibility Too Low 的本地化字符串。 65 | /// 66 | internal static string AnalyzerDescription { 67 | get { 68 | return ResourceManager.GetString("AnalyzerDescription", resourceCulture); 69 | } 70 | } 71 | 72 | /// 73 | /// 查找类似 BBBIRDER002 的本地化字符串。 74 | /// 75 | internal static string AnalyzerID { 76 | get { 77 | return ResourceManager.GetString("AnalyzerID", resourceCulture); 78 | } 79 | } 80 | 81 | /// 82 | /// 查找类似 The lowest allowed accessibility for Type {0} (its declaring types as well) is internal 的本地化字符串。 83 | /// 84 | internal static string AnalyzerMessageFormat { 85 | get { 86 | return ResourceManager.GetString("AnalyzerMessageFormat", resourceCulture); 87 | } 88 | } 89 | 90 | /// 91 | /// 查找类似 Accessibility Too Low 的本地化字符串。 92 | /// 93 | internal static string AnalyzerTitle { 94 | get { 95 | return ResourceManager.GetString("AnalyzerTitle", resourceCulture); 96 | } 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/UnityObject_GetLifeKeeper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using UnityEngine; 4 | 5 | namespace BBBirder.UnityVue 6 | { 7 | public static class UnityExtensions 8 | { 9 | static Dictionary s_cancellationRegisteredUnityObject = new(); 10 | static Action s_releaseByCancellation; 11 | 12 | static UnityExtensions() 13 | { 14 | s_releaseByCancellation = ReleaseByCancellation; 15 | } 16 | 17 | static void ReleaseByCancellation(object state) 18 | { 19 | var behaviour = state as MonoBehaviour; 20 | 21 | if (s_cancellationRegisteredUnityObject.TryGetValue(behaviour, out var lifeKeeper)) 22 | { 23 | lifeKeeper.Release(); 24 | s_cancellationRegisteredUnityObject.Remove(behaviour); 25 | } 26 | } 27 | 28 | /// 29 | /// The a proper LifeKeeper for this Unity Object. 30 | /// 31 | /// 32 | /// Disabled Object can still receive updates when it set to True. 33 | /// 34 | public static IScopeLifeKeeper GetLifeKeeper(this UnityEngine.Object unityObject) 35 | { 36 | if (unityObject is IScopeLifeKeeper lifeKeeper) return lifeKeeper; 37 | 38 | if (unityObject is MonoBehaviour behaviour) 39 | { 40 | if (!s_cancellationRegisteredUnityObject.TryGetValue(behaviour, out var behaviourLifeKeeper)) 41 | { 42 | var cancellationToken = behaviour.destroyCancellationToken; 43 | behaviourLifeKeeper = new BehaviourLifeKeeper() 44 | { 45 | behaviour = behaviour, 46 | }; 47 | cancellationToken.Register(s_releaseByCancellation, behaviour); 48 | s_cancellationRegisteredUnityObject[behaviour] = behaviourLifeKeeper; 49 | } 50 | 51 | return behaviourLifeKeeper; 52 | } 53 | 54 | if (unityObject is GameObject go) 55 | { 56 | var trigger = go.GetComponent(); 57 | if (!trigger) trigger = go.AddComponent(); 58 | 59 | return trigger; 60 | } 61 | 62 | if (unityObject is Transform trans) 63 | { 64 | var trigger = trans.GetComponent(); 65 | if (!trigger) trigger = trans.gameObject.AddComponent(); 66 | 67 | return trigger; 68 | } 69 | 70 | if (!UnityVueDriver.TryGetPollingLifeKeeper(unityObject, out var pollingLifeKeeper)) 71 | { 72 | pollingLifeKeeper = new PollingLifeKeeper() 73 | { 74 | lifeDetector = () => unityObject, 75 | enableDetector = unityObject is Behaviour hehav 76 | ? () => hehav.isActiveAndEnabled 77 | : () => true, 78 | }; 79 | UnityVueDriver.RegisterPollingLifeKeeper(unityObject, pollingLifeKeeper); 80 | } 81 | 82 | return pollingLifeKeeper; 83 | } 84 | 85 | } 86 | 87 | internal class BehaviourLifeKeeper : IScopeLifeKeeper 88 | { 89 | public MonoBehaviour behaviour; 90 | public SimpleList Scopes { get; } = new(); 91 | public bool IsAlive => behaviour; 92 | public bool IsEnabled => true; 93 | 94 | internal void Release() 95 | { 96 | this.ReleaseScopes(); 97 | behaviour = default; 98 | } 99 | } 100 | 101 | public class PollingLifeKeeper : IScopeLifeKeeper 102 | { 103 | public Func lifeDetector; 104 | public Func enableDetector; 105 | public SimpleList Scopes { get; } = new(); 106 | public bool IsAlive => lifeDetector(); 107 | public bool IsEnabled => true; 108 | 109 | internal void Release() 110 | { 111 | this.ReleaseScopes(); 112 | lifeDetector = null; 113 | } 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /DotNetProj~/UnityVue.SG/Extension.cs: -------------------------------------------------------------------------------- 1 | using Microsoft.CodeAnalysis; 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Diagnostics; 5 | using System.Linq; 6 | 7 | namespace UnityVue.SG 8 | { 9 | internal static class Extensions 10 | { 11 | 12 | public static string GetSimpleName(this INamespaceSymbol ns) 13 | { 14 | if (ns.IsGlobalNamespace) 15 | { 16 | return ""; 17 | } 18 | return ns.ToString(); 19 | } 20 | 21 | public static bool IsFullNameEquals(this INamedTypeSymbol type) 22 | { 23 | 24 | return type.ContainingNamespace.GetSimpleName() == typeof(T).Namespace 25 | && type.Name == typeof(T).Name 26 | ; 27 | } 28 | 29 | public static string GetFullName(this ITypeSymbol type) 30 | { 31 | return type.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat 32 | .WithGlobalNamespaceStyle(SymbolDisplayGlobalNamespaceStyle.Omitted)); 33 | } 34 | 35 | //public static string GetFullName(INamedTypeSymbol type) 36 | //{ 37 | // var typesChain = type.GetContainingTypesIncludingSelf().Reverse(); 38 | 39 | // var ns = typesChain.First().ContainingNamespace.GetSimpleName(); 40 | 41 | // if (!string.IsNullOrEmpty(ns)) 42 | // { 43 | // return ns + "." + string.Join(".", typesChain.Select(t=>t.Name)); 44 | // } 45 | // else 46 | // { 47 | // return string.Join(".", typesChain.Select(t => t.Name)); 48 | // } 49 | //} 50 | 51 | public static IEnumerable GetContainingTypes(this INamedTypeSymbol type, bool includeSelf = true) 52 | { 53 | if (!includeSelf) 54 | { 55 | type = type?.BaseType; 56 | } 57 | 58 | while (type != null) 59 | { 60 | yield return type; 61 | type = type.ContainingType; 62 | } 63 | } 64 | 65 | public static IEnumerable GetBaseTypes(this ITypeSymbol type, bool includeSelf = true) 66 | { 67 | if (!includeSelf) 68 | { 69 | type = type?.BaseType; 70 | } 71 | 72 | while (type != null) 73 | { 74 | yield return type; 75 | type = type.BaseType; 76 | } 77 | } 78 | 79 | public static bool IsInternalAccessible(this INamedTypeSymbol type) 80 | { 81 | foreach (var declType in type.GetContainingTypes()) 82 | { 83 | if (declType.DeclaredAccessibility < Accessibility.Internal) return false; 84 | } 85 | return true; 86 | } 87 | 88 | public static bool IsTypeOrSubTypeOf(this ITypeSymbol symbol) 89 | { 90 | if (typeof(T).IsInterface) 91 | { 92 | foreach (var interf in symbol.AllInterfaces) 93 | { 94 | if (interf is INamedTypeSymbol namedType && namedType.IsFullNameEquals()) return true; 95 | } 96 | } 97 | else 98 | { 99 | foreach (var baseType in symbol.GetBaseTypes()) 100 | { 101 | if (baseType is INamedTypeSymbol namedType && namedType.IsFullNameEquals()) return true; 102 | } 103 | } 104 | return false; 105 | } 106 | 107 | public static IEnumerable GetAttributes(this ISymbol type) where T : Attribute 108 | { 109 | return type.GetAttributes().Where(a => a.AttributeClass.IsFullNameEquals()).Select(ToAttribute); 110 | } 111 | 112 | public static T GetAttribute(this ISymbol type) where T : Attribute 113 | { 114 | return type.GetAttributes().FirstOrDefault(); 115 | } 116 | 117 | private static T ToAttribute(this AttributeData data) where T : Attribute 118 | { 119 | if (data is null) return null; 120 | var constructorArguments = data.ConstructorArguments.Select(a => a.Value).ToArray(); 121 | var attribute = Activator.CreateInstance(typeof(T), constructorArguments); 122 | foreach (var pair in data.NamedArguments) 123 | { 124 | var name = pair.Key; 125 | var value = pair.Value.Value; 126 | attribute.GetType().GetProperty(name)?.SetValue(attribute, value); 127 | attribute.GetType().GetField(name)?.SetValue(attribute, value); 128 | } 129 | return attribute as T; 130 | } 131 | 132 | 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /Runtime/Unity.MonoBehaviours/ComponentBinderEditor.cs: -------------------------------------------------------------------------------- 1 | #if UNITY_EDITOR 2 | using System; 3 | using System.Collections; 4 | using System.Collections.Generic; 5 | using UnityEditor; 6 | using UnityEditor.UIElements; 7 | using UnityEditorInternal; 8 | using UnityEngine; 9 | using UnityEngine.UIElements; 10 | 11 | namespace BBBirder.UnityVue 12 | { 13 | [CustomEditor(typeof(ComponentBinder))] 14 | public class DataBinderEditor : Editor 15 | { 16 | ComponentBinder binder => target as ComponentBinder; 17 | const string ROOT_UI_GUID = "eb06b019921e7884dbfdeb06e17b60f5"; 18 | const string ELEMENT_UI_GUID = "67a9fedd041e41c48a972331b10b7c21"; 19 | // [SerializeField] VisualTreeAsset uiAssetRoot; 20 | // [SerializeField] VisualTreeAsset uiAssetElement; 21 | public override VisualElement CreateInspectorGUI() 22 | { 23 | binder.expressions ??= new(); 24 | var uiAssetRoot = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(ROOT_UI_GUID)); 25 | var uiAssetElement = AssetDatabase.LoadAssetAtPath(AssetDatabase.GUIDToAssetPath(ELEMENT_UI_GUID)); 26 | var uiRoot = uiAssetRoot.CloneTree(); 27 | var elements = uiRoot.Q("elements"); 28 | var btnAdd = uiRoot.Q