diff --git a/CHANGELOG.md b/CHANGELOG.md
index 911911a..57c13b6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,17 +1,17 @@
-#### **#2024/6/17 发布UniVue v1.0.0**
+## **#2024/6/17 发布UniVue v1.0.0**
核心基础模块的完成
-#### **#2024/6/26修复UniVue v1.0.0中的BUG:**
+## **#2024/6/26修复UniVue v1.0.0中的BUG:**
1. 基于ViewConfig构建的视图时,可能会重复生成UIEvent和UIBundle的问题;
2. LoogGrid组件的布局错误问题;
-#### **#2024/6/26发布UniVue v1.0.1:核心模块优化**
+## **#2024/6/26发布UniVue v1.0.1**
1. 优化VMTable,UI更新的复杂度为O(1)常数级;
2. VueConfig继承自ScriptableObject;
@@ -20,17 +20,17 @@
-#### **#2024/6/27修复BUG**
+## **#2024/6/27修复BUG**
1. 当ViewConfig的视图名称与文件名称不一致时导致错误的视图构建;
-#### **#2024/6/27将版本v1.0.1合并为v1.0.0**
+## **#2024/6/27将版本v1.0.1合并为v1.0.0**
-#### **#2024/6/29发布版本v1.1.0**
+## **#2024/6/29发布版本v1.1.0**
1. IBindableModel继承新的接口IConsumableModel,此接口能够实现不要将模型绑定到视图而是直接将数据更新到UI上,这样可以为以下两种场景带来方便:
@@ -43,7 +43,7 @@
-#### **#2024/7/9发布版本v1.2.0**
+## **#2024/7/9发布版本v1.2.0**
1. **支持自定义规则**:对之前的规则引擎部分的代码进行完全重构,现在支持自定义规则(但是现在无法取代默认的规则实现),只需要实现接口IRuleFilter即可;
@@ -64,4 +64,15 @@
7. 修复AtomModel、GroupModel对枚举类型无法进行执行UpdateModel()的bug;
-8. 修复ModelUtil对枚举类型无法执行UpdateModel()的bug;
\ No newline at end of file
+8. 修复ModelUtil对枚举类型无法执行UpdateModel()的bug;
+
+
+
+## **#2024/7/12发布版本v1.3.0**
+
+1. 新增ViewLevel.Modal级别的视图等级,Modal模态视图打开时如果不关闭此视图无法打开任何视图(就是之前版本的forbid=true时行为);
+2. **优化System级别的视图的逻辑:现在System级别的视图为同级互斥。同级的含义指:具有相同的父视图,所有的根视图均为同一级。同级下永远只有一个System级别的视图被打开;**
+3. 当父视图没有被打开时不允许打开其子视图;
+4. 为事件系统新增IEntityMapper接口,为AOT编译提供基于非反射创建对象的实现,如果你的项目要进行IL2CPP编译,如果事件回调的参数有自定义的类型,你应该手动注册相应实体类型的接口实现,以实现事件回调时能够正确获得参数值;
+5. 优化视图的构建逻辑,**现在必须要求视图名称就是ViewObject.name,同时所有名称以"View"结尾的GameObject将被视为一个ViewObject对象**;
+6. 优化API的使用;
\ No newline at end of file
diff --git a/README.md b/README.md
index 83af534..874a3c5 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,37 @@
-## 版本功能一栏表
+## **开发说明**
+
+**说明:**由于每个版本的源码有变动,实现方式也有变化,之前下面讲解中使用的图中的某些函数的名字已经改名,可能某些流程也已经改变,但是由于个人精力有限,实在挤不出时间写更完善的文档了,只能每次一点一点的写。emmmm,如果你愿意和我一起维护这个开源项目,不妨联系我和我一起撸起袖子加油干!**QQ:2947897147**;
+
+我会在博客中对UniVue中的功能的使用进行讲解已经底层的实现逻辑、算法的实现。由于目前的电脑配置很差,开启Unity后录屏很卡,所有无法进行开视频进行讲解,emmm,后面升级装备了会在B站开视频进行讲解。保证最多一天的时间你就精通UniVue。
+
+CSDN个人博客:[Avalon712-CSDN博客](https://blog.csdn.net/m0_62135731?spm=1000.2115.3001.5343)
+
+这个仓库之后发布功能稳定的版本,因此很多最新的功能在这里是无法看见的,如果你想预览最新的功能,不妨fork一下这个仓库:https://github.com/Avalon712/UniVue-Develop 。这个仓库是我开发UniVue框架使用的项目,所有最新以及正在开发的功能都在这里可以看见,里面对每个功能都会有单元测试,也是学习UniVue框架的不二选择。
+
+
+
+**UniVue的扩展框架:UniVue源生成器**
+
+仓库地址:https://github.com/Avalon712/UniVue-SourceGenerator
+
+关于UniVue中源生成器更详细的说明,请看这篇博客:[UniVue更新日志:使用源生成器优化Model和ViewModel层的设计-CSDN博客](https://blog.csdn.net/m0_62135731/article/details/139525492?spm=1001.2014.3001.5501)
+
+
+
+**注:C#的源生器将会是完全替代反射的必要框架。通过生成低级代码完成对反射的替换,同时大幅度提高框架的易用性;**
+
+
+
+**版本说明**
+
+目前只对2021及其以上有支持,其它版本没试过,不知道什么情况,源码采用了很多C#9的语法,C#9似乎实在Unity2021开始支持的,如果你要使用源生器或许只能使用2021版本以上。同时不会对Unity都遗弃的功能进行支持,如:Text组件。因为如果对这些相同功能的组件也进行支持会导致ViewModel非常冗余,如果你要进行支持建议自己通过继承PropertyUI,然后看对于的组件是怎么实现更新逻辑的,照抄一遍就可以了。ViewModel的PropertyUI有将近30多个类,emmm,这就是我不打算支持的原因。后面PropertyUI还会进行扩展,可能会有70多个类。后续有时间了再看看要不要对2021版本以下的进行测试支持。
+
+
+
+## 版本核心功能一栏表
### **v1.0.0**
@@ -21,16 +51,23 @@
-**版本说明**
+### v1.1.0
-目前只对2021及其以上有支持,其它版本没试过,不知道什么情况,源码采用了很多C#9的语法,C#9似乎实在Unity2021开始支持的,如果你要使用源生器或许只能使用2021版本以上。同时不会对Unity都遗弃的功能进行支持,如:Text组件。因为如果对这些相同功能的组件也进行支持会导致ViewModel非常冗余,如果你要进行支持建议自己通过继承PropertyUI,然后看对于的组件是怎么实现更新逻辑的,照抄一遍就可以了。ViewModel的PropertyUI有将近40多个类,emmm,这就是我不打算支持的原因。后面PropertyUI还会进行扩展,可能会有70多个类。
+- **IConsumableModel接口**:在v1.0.0版本的基础上新增IConsumableModel接口的功能,实现更快的更新速度更少的查询缓存占用;
+- **源生成器同步更新至v1.1.0**:为支持IConsumableModel接口的功能,UniVue的源生成器提供了自动生成更新逻辑的代码;
-### v1.1.0
+### v1.2.0
-- **IConsumableModel接口**:在v1.0.0版本的基础上新增IConsumableModel接口的功能,实现更快的更新速度更少的查询缓存占用;
-- **源生成器同步更新至v1.1.0**:为支持IConsumableModel接口的功能,UniVue的源生成器提供了自动生成更新逻辑的代码;
+- **支持自定义规则**:v1.2.0版本中全面优化了规则引擎的代码,完全单独抽离出来成为一个独立的模块,UniVue的所有模块都依赖规则引擎模块;
+
+
+
+### v1.3.0
+
+- **新增Modal模态视图**:处于ViewLevel.Modal级别的视图被打开后,在关闭它之前,不允许任何视图再打开;
+- **优化System级别视图逻辑**:System级别的视图现在为同级互斥,具有相同父视图的视图为同一级,所有根视图(没有父视图的视图)为同一级;
@@ -48,24 +85,6 @@
-## **开发说明**
-
-**说明:**由于源码有变动,之前下面讲解中使用的图中的某些函数的名字已经改名,可能某些流程也已经改变,但是由于个人精力有限,实在挤不出时间写更完善的文档了,只能每次一点一点的写。emmmm,如果你愿意和我一起维护这个开源项目,不妨联系我和我一起撸起袖子加油干!**QQ:2947897147**;
-
-我会在博客中对UniVue中的功能的使用进行讲解已经底层的实现逻辑、算法的实现。由于目前的电脑配置很差,开启Unity后录屏很卡,所有无法进行开视频进行讲解,emmm,后面升级装备了会在B站开视频进行讲解。保证最多一天的时间你就精通UniVue。
-
-CSDN个人博客:[Avalon712-CSDN博客](https://blog.csdn.net/m0_62135731?spm=1000.2115.3001.5343)
-
-这个仓库之后发布功能稳定的版本,因此很多最新的功能在这里是无法看见的,如果你想预览最新的功能,不妨fork一下这个仓库:https://github.com/Avalon712/UniVue-Develop 。这个仓库是我开发UniVue框架使用的项目,所有最新以及正在开发的功能都在这里可以看见,里面对每个功能都会有单元测试,也是学习UniVue框架的不二选择。
-
-
-
-**UniVue的扩展框架:UniVue源生成器**
-
-仓库地址:https://github.com/Avalon712/UniVue-SourceGenerator
-
-关于UniVue中源生成器更详细的说明,请看这篇博客:[UniVue更新日志:使用源生成器优化Model和ViewModel层的设计-CSDN博客](https://blog.csdn.net/m0_62135731/article/details/139525492?spm=1001.2014.3001.5501)
-
## 一、简介
@@ -79,34 +98,34 @@ CSDN个人博客:[Avalon712-CSDN博客](https://blog.csdn.net/m0_62135731?spm=
### 视图加载流程
-
+见ViewBuilder类的实现
### 数据绑定流程
-
+见ViewUtil的实现
### UI更新流程
-
+见ViewUpdater或UIBundle的实现
### 模型更新流程
-
+见UIBundle的实现
### 事件触发流程
-
+见UIBundle、IBindableModel的实现
### 资源卸载流程
-
+见Vue
### 自动装配与卸载EventCall的执行逻辑
-
+见EventManager的实现
## 二、Model
@@ -306,7 +325,7 @@ UniVue除了提供实现数据、视图的双向绑定外还提供了强大的
这个枚举类定义了常见的命名风格。注意:无论是哪种命名风格,指定UI组件名称都是必要的。
-#### 2)NamingRuleEngine
+#### 2)RuleEngine
这个类实现了所有命名规则的解析、匹配。如果你的对命名还是不太清楚,可以看此类的源码,这个类是通过正则表达式来实现的解析和匹配。
@@ -747,6 +766,8 @@ UniVue除了提供实现数据、视图的双向绑定外还提供了强大的
注意,多个命名规则下的顺序:**数据绑定 & 路由事件 & 自定义事件**
+**注:在v1.2.0以后无需关系顺序,任意顺序都可,同时无需再使用" & "隔开,但是基于可读性的基础上仍然建议这么做。**
+
**举例说明:**
- Player_Level_Slider & Arg_Grade[level]_Slider
@@ -825,7 +846,7 @@ View中具有嵌套关系时,在创建被嵌套的视图时,无需指定view
在Unity的最上方的工具栏可以看见"**UniVue**"字样,点击,会出现提供的三个扩展功能。
-### ConfigEditorWindow**
+### ConfigEditorWindow
位置: **UniVu > ConfigEditor**
@@ -843,9 +864,16 @@ View中具有嵌套关系时,在创建被嵌套的视图时,无需指定view
- **以字符'~'开头的GameObject及其后代GameObject都不会被进行组件查找;**
- **以字符'@'开头的GameObject不会被进行组件查找,但是其后代GameObject会被进行查找;**
+- 你可以通过修改VueConfig文件修改上述字符,使用其它字符完成;
## 十、源生成器
-最近的大更新中使用了源生成器来提高效率,关于UniVue中的源生成器,请看这篇博客:[UniVue更新日志:使用源生成器优化Model和ViewModel层的设计-CSDN博客](https://blog.csdn.net/m0_62135731/article/details/139525492?spm=1001.2014.3001.5501)
\ No newline at end of file
+最近的大更新中使用了源生成器来提高效率,关于UniVue中的源生成器,请看这篇博客:[UniVue更新日志:使用源生成器优化Model和ViewModel层的设计-CSDN博客](https://blog.csdn.net/m0_62135731/article/details/139525492?spm=1001.2014.3001.5501)
+
+
+
+## 十一、规则引擎
+
+通过自定义实现IRuleFilter接口,使用规则引擎RuleEngine能够对任何ViewObject执行Filter操作,过滤完后你可以对过滤的结果进行自定义的处理。规则引擎是所有模块的基础,后续的所有核心功能都依赖规则引擎。
\ No newline at end of file
diff --git a/UniVue/Runtime/Evt/EntityMapper.cs b/UniVue/Runtime/Evt/EntityMapper.cs
index 6ac3483..84490d0 100644
--- a/UniVue/Runtime/Evt/EntityMapper.cs
+++ b/UniVue/Runtime/Evt/EntityMapper.cs
@@ -12,16 +12,11 @@ public sealed class EntityMapper
private EntityMapper() { }
///
- /// 将事件参数映射为一个对象类型
+ /// 通过反射创建实体对象
///
- /// 对象类型
- /// 参数
- /// 映射对象
- public static object Map(Type type, EventArg[] args)
+ public static object CreateEntity(Type type)
{
- object instance = Activator.CreateInstance(type);
- SetValues(instance, args);
- return instance;
+ return Activator.CreateInstance(type);
}
///
diff --git a/UniVue/Runtime/Evt/EventArg.cs b/UniVue/Runtime/Evt/EventArg.cs
index d54b0bc..bcb132a 100644
--- a/UniVue/Runtime/Evt/EventArg.cs
+++ b/UniVue/Runtime/Evt/EventArg.cs
@@ -33,7 +33,7 @@ internal EventArg(string name, UIType type, Component argUI)
public void SetArgumentValue(object value)
{
- SupportableArgType argType = EventUtil.GetSupportableArgType(value.GetType());
+ SupportableArgType argType = ReflectionUtil.GetSupportableArgType(value.GetType());
if (argType == SupportableArgType.None || ((int)argType) > 6)
{
diff --git a/UniVue/Runtime/Evt/EventCall.cs b/UniVue/Runtime/Evt/EventCall.cs
index eac8e8a..8d76593 100644
--- a/UniVue/Runtime/Evt/EventCall.cs
+++ b/UniVue/Runtime/Evt/EventCall.cs
@@ -86,27 +86,31 @@ private void SetParameterValues()
ParameterInfo parameter = parameters[i];
string argName = parameter.Name;
- SupportableArgType argType = EventUtil.GetSupportableArgType(parameter.ParameterType);
+ SupportableArgType argType = ReflectionUtil.GetSupportableArgType(parameter.ParameterType);
if (argType == SupportableArgType.None) { continue; }
if ((int)argType < 7)
{
- SetArgMatchValue(argName, parameter.ParameterType, ref i, ref argType, ref args);
+ SetArgMatchValue(argName, parameter.ParameterType, i, argType, args);
}
else
{
switch (argType)
{
case SupportableArgType.Custom:
- //重用之前创建的对象实例
- if (_parameters[i] != null)
+ IEntityMapper mapper = Vue.Event.GetEntityMapper(parameter.ParameterType);
+ if (mapper != null)
{
- EntityMapper.SetValues(_parameters[i], args);
+ if (_parameters[i] == null)
+ _parameters[i] = mapper.CreateEntity();
+ mapper.SetValues(_parameters[i], args);
}
else
{
- _parameters[i] = EntityMapper.Map(parameter.ParameterType, args);
+ if (_parameters[i] == null)
+ _parameters[i] = EntityMapper.CreateEntity(parameter.ParameterType);
+ EntityMapper.SetValues(_parameters[i], args);
}
break;
@@ -128,7 +132,7 @@ private void SetParameterValues()
}
}
- private void SetArgMatchValue(string argName, Type parameterType, ref int i, ref SupportableArgType argType, ref EventArg[] args)
+ private void SetArgMatchValue(string argName, Type parameterType, int i, SupportableArgType argType, EventArg[] args)
{
//除开以上类型,以下这些类型将进行参数名与类型都匹配成功才能设置
for (int j = 0; j < args.Length; j++)
@@ -204,17 +208,16 @@ private void SetArgMatchValue(string argName, Type parameterType, ref int i, ref
return;
}
- if (valueType != parameterType)
+ if (valueType == parameterType)
{
-#if UNITY_EDITOR
- LogUtil.Warning($"方法[{_call.Name}]: 参数名为{argName}的类型为{parameterType},与UI返回的事件参数类型{value.GetType()}不一致,无法正确进行赋值!");
-#endif
+ _parameters[i] = value;
}
+#if UNITY_EDITOR
else
{
- _parameters[i] = value;
+ LogUtil.Warning($"方法[{_call.Name}]: 参数名为{argName}的类型为{parameterType},与UI返回的事件参数类型{value.GetType()}不一致,无法正确进行赋值!");
}
-
+#endif
return;
}
}
diff --git a/UniVue/Runtime/Evt/EventManager.cs b/UniVue/Runtime/Evt/EventManager.cs
index 56d9cff..7497aa4 100644
--- a/UniVue/Runtime/Evt/EventManager.cs
+++ b/UniVue/Runtime/Evt/EventManager.cs
@@ -12,8 +12,13 @@ public sealed class EventManager
private List _events;
private List _calls;
private List _autowires;
+ private List _mappers;
- internal EventManager() { _events = new(18); _calls = new(18); }
+ internal EventManager()
+ {
+ _events = new List(20);
+ _calls = new List(10);
+ }
internal List Events => _events;
@@ -41,6 +46,27 @@ public void Signup(T register) where T : IEventRegister
}
}
+ ///
+ /// 注册实体映射,将EventArg[]映射为自定义对象
+ ///
+ public void RegisterMapper(IEntityMapper mapper)
+ {
+ if (_mappers == null)
+ _mappers = new List();
+ _mappers.Add(mapper);
+ }
+
+ public IEntityMapper GetEntityMapper(Type entityType)
+ {
+ if (_mappers == null) return null;
+ for (int i = 0; i < _mappers.Count; i++)
+ {
+ if (_mappers[i].EntityType == entityType)
+ return _mappers[i];
+ }
+ return null;
+ }
+
///
/// 自动装配EventCall
///
diff --git a/UniVue/Runtime/Evt/IEntityMapper.cs b/UniVue/Runtime/Evt/IEntityMapper.cs
new file mode 100644
index 0000000..409885a
--- /dev/null
+++ b/UniVue/Runtime/Evt/IEntityMapper.cs
@@ -0,0 +1,13 @@
+using System;
+
+namespace UniVue.Evt
+{
+ public interface IEntityMapper
+ {
+ public Type EntityType { get; }
+
+ public object CreateEntity();
+
+ public void SetValues(object entity, EventArg[] eventArgs);
+ }
+}
diff --git a/UniVue/Runtime/Evt/SupportableArgType.cs b/UniVue/Runtime/Evt/SupportableArgType.cs
new file mode 100644
index 0000000..94b8407
--- /dev/null
+++ b/UniVue/Runtime/Evt/SupportableArgType.cs
@@ -0,0 +1,24 @@
+
+namespace UniVue.Evt
+{
+ ///
+ /// EventCall支持的方法参数类型
+ ///
+ public enum SupportableArgType
+ {
+ ///
+ /// 不被支持的类型
+ ///
+ None,
+ Int,
+ Float,
+ String,
+ Enum,
+ Bool,
+ Sprite,
+ Custom,
+ UIEvent,
+ EventArg,
+ EventCall
+ }
+}
diff --git a/UniVue/Runtime/Rule/Filters/ModelFilter.cs b/UniVue/Runtime/Rule/Filters/ModelFilter.cs
index 4adf83e..50113d3 100644
--- a/UniVue/Runtime/Rule/Filters/ModelFilter.cs
+++ b/UniVue/Runtime/Rule/Filters/ModelFilter.cs
@@ -20,7 +20,9 @@ namespace UniVue.Rule
///
public sealed class ModelFilter : IRuleFilter
{
- private readonly int _typeFlag;
+ private int _typeFlag;
+ private bool _allowUIUpdateModel;
+
public string ModelName { get; private set; }
public IBindableModel Model { get; private set; }
@@ -29,15 +31,14 @@ public sealed class ModelFilter : IRuleFilter
public UIBundle Bundle { get; private set; }
- public ModelFilter(IBindableModel model, string modelName = null)
+ public ModelFilter(IBindableModel model, bool allowUIUpdateModel = true, string modelName = null)
{
_typeFlag = -1;
Model = model;
ModelType = model.GetType();
- ModelName = modelName;
- Bundle = null;
_typeFlag = GetTypeFlag();
ModelName = GetModelName();
+ _allowUIUpdateModel = allowUIUpdateModel;
}
public bool Check(ref (Component, UIType) component, List