概述
StateUI (Lua)是以StateMachine
为基础,建立分层状态机以及State
和UI Window
的交互规则,在框架层内建State
切换时对应State
内Window
的Open
/Close
规则。
StateDriver | |-- Initialize <==> InitWindow | |-- Login <==> LoginWindow | |-- SelectRole <==> SelectRoleWindow CreateRoleWindow | |-- Gaming | | |-- Camp <==> BottomBar | |-- Role <==> BottomBar, TopBar, ... | | | |-- ... | |-- Fight <==> BottomBar, TopBar, ChatBar, ... | | | |-- ... | |-- Pet <==> BottomBar, ... | |-- ...
|
开发规范
StateUI试图建立一种开发规范,明确规定State与Window的访问权限。哪些代码应该在State中实现,哪些又需要在Window中实现。
- Window内应该仅处理本Window的UI控件,不能直接操纵其他Window和场景
- Window仅能向所属的State发送Event
- Window仅能读取(Get)所属State的指定数据
- Window仅能关闭自己
- State可以Open/Close目标Window
- State可以发送Message给所有Visible的Window
- State可以向父State发送Event
StateUI的默认规则是:
进入State后,之前的所有Window都会被默认Close。
快速开始
- 实现
IWindowProvider
(详情参看IWindowProvider
节)
GameWindowProvider = class("GameWindowProvider", IWindowProvider)
|
- 启动
StateDriver
(详情参看StateDriver
节)
local driver = StateDriver.new(GameWindowProvider.new())
|
Initialize = class("Initialize", State)
|
driver:ChangeState(Initialize.new())
|
StateDriver
StateDriver
是StateUI的驱动器,是整个模块的入口。StateUI本身并不直接处理Window的行为,而是依靠外部注入IWindowProvider
的实体对象来间接应用StateUI的逻辑。
self:Update(deltaTime)
self:Destroy()
|
IWindowProvider
应用层需要实现IWindowProvider
接口,然后注入到StateDriver
中。从而StateUI可以真正使用规则影响目标Window
。
function M:OnInit() end
function M:OnDestroy() end
function M:Create(name) end
function M:Destroy(name) end
function M:Show(name) end
function M:Hide(name) end
function M:Open(name, iwindow, ...) end
function M:Close(name, iwindow) end
|
State
State只需操作关心的Window
的Open
和Close
即可,不关心的Window
会被框架层自动Close
。
State 扩展
local M = class("MyState", State)
function M:OnEnter(ctx) end
function M:OnExit() end
function M:OnUpdate(deltaTime) end
|
State 切换
使用ChangeState(state, ctx)
切换状态,并将传入的state
作为返回值返回。其中ctx
为可以携带的上下文参数,可以不填。
进入/切换当前State
self:GetParent():ChangeState(state)
|
退出当前State
self:GetParent():ChangeState(nil)
|
进入/切换子State
退出子State
State向上抛出Event
使用self:Upcast(event, ...)
向父级State
抛出Event
。
self:Upcast("Navigate", 1)
|
父级State处理下层State抛出的Event
实现OnNotify
加上Event名称
组成的函数。
function M:OnNotifyNavigate(index) end
|
Window
在StateUI中,Window
分为两种:普通Window
和固定Window
。
类型 |
行为 |
普通Window |
Window的状态在进入子State后会默认关闭。也就是,如果父State打开普通Window并保持打开状态,那么进入子State后,该Window会被自动关闭。 |
固定Window |
Window的状态在进入子State后会被保留。也就是,如果父State打开固定Window并保持打开状态,那么进入子State后,该Window还是会保持打开状态。 |
在StateUI中,Window
的打开方式有两种:普通Open
和排队Open
。
类型 |
行为 |
普通Open |
目标Window被直接打开。 |
排队Open |
目标Window进入打开的排队系统,若处于第一位,则直接打开,否则在队列中等待,直到排在前面的Window被关闭。 |
State可操作Window的接口
self:PreloadWindow(window)
self:OpenWindow(window, ...)
self:OpenFixedWindow(window, ...)
self:OpenWindowQueued(window, ...)
self:OpenFixedWindowQueued(window, ...)
self:CloseWindow(window, ...)
self:ClearQueuedWindows()
self:IsWindowOpened(window)
self:EnableDomain()
|
向Window发送Message
通过self:SendWindowMessage(messge, ...)
向所有有效(显示中
)的Window
发送消息。
self:SendWindowMessage("Progress", 0.1)
|
UICtrl接收State发送的Message
实现OnState
加上Message名称
组成的函数。
function M:OnStateProgress(progress) end
|
UICtrl
UICtrl应只关心自己Window内的逻辑,只能发送Event
和读取(Get
)目标属性。
初始化/清理
Window
被Open(创建
/显示
)的时候,会调用UICtrl的OnOpen
方法;反之,被Close(隐藏
/销毁
)的时候会调用UICtrl的OnClose
方法。Window
被重新创建的时候会调用OnCreate
方法;而销毁时会调用OnDestroy
方法。
注意:由于Open可能只是显示目标Window,其背后的资源并未被释放,因此一些消息绑定操作请确保在OnClose中解绑,防止消息触发重入。
function M:OnCreate() end
function M:OnDestroy() end
function M:OnOpen(data) end
function M:OnClose() end
|
Close自己
UICtrl可以直接关闭自己所属的Window
。
发送Event
通过self:Notify(event, ...)
发送Event
。
self:Notify("Print", "Hello")
|
State处理Event
实现OnNotify
加上Event名称
组成的函数。
function M:OnNotifyPrint(obj) end
|
Get属性
UICtrl可以通过self:Get(name, ...)
获取State
层暴露的数据。
local name = self:Get("ID", ...)
|
State处理属性读取
实现OnGet
加上属性名称组成的函数。
function M:OnGetID() return 1 end
|