@@ -24,6 +24,7 @@ A package that brings data-binding to your Unity project.
24
24
- [ How To Use] ( #joystick-how-to-use )
25
25
- [ Data-binding] ( #data-binding )
26
26
- [ Create custom control] ( #create-custom-control )
27
+ - [ Source code generator] ( #source-code-generator )
27
28
- [ External Assets] ( #link-external-assets )
28
29
- [ UniTask] ( #unitask )
29
30
- [ Performance] ( #rocket-performance )
@@ -879,8 +880,6 @@ public class Image : VisualElement
879
880
}
880
881
881
882
public new class UxmlFactory : UxmlFactory <Image , UxmlTraits > {}
882
-
883
- public new class UxmlTraits : VisualElement .UxmlTraits {}
884
883
}
885
884
```
886
885
@@ -899,7 +898,7 @@ public class BindableImage : Image, IBindableElement
899
898
_imagePathBindingData ??= BindingImagePath .ToPropertyBindingData ();
900
899
901
900
_imageProperty = objectProvider .RentReadOnlyProperty <Texture2D >(context , _imagePathBindingData );
902
- _imageProperty .ValueChanged += OnImageValueChanged ;
901
+ _imageProperty .ValueChanged += OnImagePropertyValueChanged ;
903
902
904
903
SetImage (_imageProperty .Value );
905
904
}
@@ -911,7 +910,7 @@ public class BindableImage : Image, IBindableElement
911
910
return ;
912
911
}
913
912
914
- _imageProperty .ValueChanged -= OnImageValueChanged ;
913
+ _imageProperty .ValueChanged -= OnImagePropertyValueChanged ;
915
914
916
915
objectProvider .ReturnReadOnlyProperty (_imageProperty );
917
916
@@ -920,7 +919,7 @@ public class BindableImage : Image, IBindableElement
920
919
SetImage (null );
921
920
}
922
921
923
- private void OnImageValueChanged (object sender , Texture2D newImage )
922
+ private void OnImagePropertyValueChanged (object sender , Texture2D newImage )
924
923
{
925
924
SetImage (newImage );
926
925
}
@@ -961,6 +960,181 @@ public class ImageViewerViewModel : IBindingContext
961
960
</UXML >
962
961
```
963
962
963
+ ### Source code generator
964
+
965
+ The best way to speed up the creation of custom ` VisualElement ` is to use source code generators. With this powerful tool, you can achieve the same great results with minimal boilerplate code and focus on what really matters: programming!
966
+
967
+ Let's create the ` BindableImage ` control, but this time using source code generators.
968
+
969
+ For a visual element without bindings, we will use a [ UnityUxmlGenerator] ( https://github.com/LibraStack/UnityUxmlGenerator ) .
970
+
971
+ ``` csharp
972
+ [UxmlElement ]
973
+ public partial class Image : VisualElement
974
+ {
975
+ public void SetImage (Texture2D image )
976
+ {
977
+ style .backgroundImage = new StyleBackground (image );
978
+ }
979
+ }
980
+ ```
981
+
982
+ <details ><summary ><b >Generated code</b ></summary >
983
+ <br />
984
+
985
+ ` Image.UxmlFactory.g.cs `
986
+
987
+ ``` csharp
988
+ partial class Image
989
+ {
990
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityUxmlGenerator" , " 1.0.0.0" )]
991
+ public new class UxmlFactory : global ::UnityEngine .UIElements .UxmlFactory <Image , UxmlTraits >
992
+ {
993
+ }
994
+ }
995
+ ```
996
+
997
+ </details >
998
+
999
+ For a bindable visual element, we will use a [ UnityMvvmToolkit.Generator] ( https://github.com/LibraStack/UnityMvvmToolkit.Generator ) .
1000
+
1001
+ ``` csharp
1002
+ [BindableElement ]
1003
+ public partial class BindableImage : Image
1004
+ {
1005
+ [BindableProperty ]
1006
+ private IReadOnlyProperty <Texture2D > _imageProperty ;
1007
+
1008
+ partial void AfterSetBindingContext (IBindingContext context , IObjectProvider objectProvider )
1009
+ {
1010
+ SetImage (_imageProperty ? .Value );
1011
+ }
1012
+
1013
+ partial void AfterResetBindingContext (IObjectProvider objectProvider )
1014
+ {
1015
+ SetImage (null );
1016
+ }
1017
+
1018
+ partial void OnImagePropertyValueChanged ([CanBeNull ] Texture2D value )
1019
+ {
1020
+ SetImage (value );
1021
+ }
1022
+ }
1023
+ ```
1024
+
1025
+ <details ><summary ><b >Generated code</b ></summary >
1026
+ <br />
1027
+
1028
+ ` BindableImage.Bindings.g.cs `
1029
+
1030
+ ``` csharp
1031
+ partial class BindableImage : global ::UnityMvvmToolkit .Core .Interfaces .IBindableElement
1032
+ {
1033
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1034
+ private global ::UnityMvvmToolkit .Core .PropertyBindingData ? _imageBindingData ;
1035
+
1036
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1037
+ [global ::System .Diagnostics .CodeAnalysis .ExcludeFromCodeCoverage ]
1038
+ public void SetBindingContext (global::UnityMvvmToolkit.Core.Interfaces.IBindingContext context ,
1039
+ global::UnityMvvmToolkit.Core.Interfaces.IObjectProvider objectProvider )
1040
+ {
1041
+ BeforeSetBindingContext (context , objectProvider );
1042
+
1043
+ if (string .IsNullOrWhiteSpace (BindingImagePath ) == false )
1044
+ {
1045
+ _imageBindingData ??=
1046
+ global :: UnityMvvmToolkit .Core .Extensions .StringExtensions .ToPropertyBindingData (BindingImagePath ! );
1047
+ _imageProperty = objectProvider .RentReadOnlyProperty <global ::UnityEngine .Texture2D >(context , _imageBindingData ! );
1048
+ _imageProperty ! .ValueChanged += OnImagePropertyValueChanged ;
1049
+ }
1050
+
1051
+ AfterSetBindingContext (context , objectProvider );
1052
+ }
1053
+
1054
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1055
+ [global ::System .Diagnostics .CodeAnalysis .ExcludeFromCodeCoverage ]
1056
+ public void ResetBindingContext (global::UnityMvvmToolkit.Core.Interfaces.IObjectProvider objectProvider )
1057
+ {
1058
+ BeforeResetBindingContext (objectProvider );
1059
+
1060
+ if (_imageProperty != null )
1061
+ {
1062
+ _imageProperty ! .ValueChanged -= OnImagePropertyValueChanged ;
1063
+ objectProvider .ReturnReadOnlyProperty (_imageProperty );
1064
+ _imageProperty = null ;
1065
+ }
1066
+
1067
+ AfterResetBindingContext (objectProvider );
1068
+ }
1069
+
1070
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1071
+ [global ::System .Diagnostics .CodeAnalysis .ExcludeFromCodeCoverage ]
1072
+ private void OnImagePropertyValueChanged (object sender , global::UnityEngine.Texture2D value )
1073
+ {
1074
+ OnImagePropertyValueChanged (value );
1075
+ }
1076
+
1077
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1078
+ partial void BeforeSetBindingContext (global::UnityMvvmToolkit.Core.Interfaces.IBindingContext context ,
1079
+ global::UnityMvvmToolkit.Core.Interfaces.IObjectProvider objectProvider );
1080
+
1081
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1082
+ partial void AfterSetBindingContext (global::UnityMvvmToolkit.Core.Interfaces.IBindingContext context ,
1083
+ global::UnityMvvmToolkit.Core.Interfaces.IObjectProvider objectProvider );
1084
+
1085
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1086
+ partial void BeforeResetBindingContext (global::UnityMvvmToolkit.Core.Interfaces.IObjectProvider objectProvider );
1087
+
1088
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1089
+ partial void AfterResetBindingContext (global::UnityMvvmToolkit.Core.Interfaces.IObjectProvider objectProvider );
1090
+
1091
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1092
+ partial void OnImagePropertyValueChanged (global::UnityEngine.Texture2D value );
1093
+ }
1094
+ ```
1095
+
1096
+ ` BindableImage.Uxml.g.cs `
1097
+
1098
+ ``` csharp
1099
+ partial class BindableImage
1100
+ {
1101
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1102
+ [global ::System .Diagnostics .CodeAnalysis .ExcludeFromCodeCoverage ]
1103
+ private string BindingImagePath { get ; set ; }
1104
+
1105
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1106
+ public new class UxmlFactory : global ::UnityEngine .UIElements .UxmlFactory <BindableImage , UxmlTraits >
1107
+ {
1108
+ }
1109
+
1110
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1111
+ public new class UxmlTraits : global ::BindableUIElements .Image .UxmlTraits
1112
+ {
1113
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1114
+ private readonly global::UnityEngine.UIElements.UxmlStringAttributeDescription _bindingImagePath = new ()
1115
+ { name = " binding-image-path" , defaultValue = " " };
1116
+
1117
+ [global ::System .CodeDom .Compiler .GeneratedCodeAttribute (" UnityMvvmToolkit.Generator" , " 1.0.0.0" )]
1118
+ [global ::System .Diagnostics .CodeAnalysis .ExcludeFromCodeCoverage ]
1119
+ public override void Init (global::UnityEngine.UIElements.VisualElement visualElement ,
1120
+ global::UnityEngine.UIElements.IUxmlAttributes bag ,
1121
+ global::UnityEngine.UIElements.CreationContext context )
1122
+ {
1123
+ base .Init (visualElement , bag , context );
1124
+
1125
+ var control = (BindableImage ) visualElement ;
1126
+ control .BindingImagePath = _bindingImagePath .GetValueFromBag (bag , context );
1127
+ }
1128
+ }
1129
+ }
1130
+ ```
1131
+
1132
+ </details >
1133
+
1134
+ As you can see, using [ UnityUxmlGenerator] ( https://github.com/LibraStack/UnityUxmlGenerator ) and [ UnityMvvmToolkit.Generator] ( https://github.com/LibraStack/UnityMvvmToolkit.Generator ) we can achieve the same results but with just a few lines of code.
1135
+
1136
+ > ** Note:** The [ UnityMvvmToolkit.Generator] ( https://github.com/LibraStack/UnityMvvmToolkit.Generator ) is available exclusively for my [ patrons] ( https://patreon.com/DimaChebanov ) .
1137
+
964
1138
## :link : External Assets
965
1139
966
1140
### UniTask
0 commit comments