refactor: UI 系统及其在渲染端的初始化

This commit is contained in:
unanmed 2026-10-08 19:02:04 +08:00
parent c466949ce0
commit acfb9c117d
7 changed files with 105 additions and 20 deletions

View File

@ -1,13 +1,23 @@
import { IExcitation, IExcitationDivider } from '@motajs/animate';
import { IRenderTreeRoot } from '@motajs/render';
import { IRendererUsing } from '@motajs/render-vue';
import { UIController } from '@motajs/system';
import {
IUIController,
IUIDefaultPropsBase,
UIComponent
} from '@motajs/system';
import { IBGMPlayer, IMotaAudioContext, ISoundPlayer } from '@motajs/audio';
import { ICoreState } from '@user/data-state';
import { ISaveSystem } from './save';
import { ITextureManager } from './material';
import { IMapRenderer, IMapExtensionManager } from './map';
export interface IGameUIPropsBase<
T extends UIComponent = UIComponent
> extends IUIDefaultPropsBase<T> {
readonly state: IClientBase;
}
export interface IClientBase extends ICoreState {
/** 存档系统 */
readonly save: ISaveSystem;
@ -34,9 +44,9 @@ export interface IClientBase extends ICoreState {
/** 渲染器使用对象,供组件内注册渲染激励与事件监听 */
readonly using: IRendererUsing;
/** 主场景的 UI 控制器,管理游戏主场景的 UI 显示 */
readonly sceneController: UIController;
readonly sceneController: IUIController<IGameUIPropsBase>;
/** 主界面的 UI 控制器,管理游戏主界面的 UI 显示 */
readonly mainUIController: UIController;
readonly mainUIController: IUIController<IGameUIPropsBase>;
}
export interface IClientBaseExtended {

View File

@ -13,7 +13,8 @@ import {
ITextureManager,
TextureManager,
ISaveSystem,
SaveSystem
SaveSystem,
IGameUIPropsBase
} from '@user/client-base';
import {
IMapRenderer,
@ -38,9 +39,10 @@ import {
} from './shared';
import { WebLoadStarter } from '@motajs/loader';
import { IRendererUsing, RendererUsing } from '@motajs/render-vue';
import { UIController } from '@motajs/system';
import { IUIController, UIController } from '@motajs/system';
import { createApp } from './render';
import { LoadSceneUI } from './render/ui/load';
import { createUIPropsBase } from './ui/func';
export class ClientCore extends CoreState implements IClientCore {
// Layer 4 渲染基础层
@ -56,8 +58,8 @@ export class ClientCore extends CoreState implements IClientCore {
readonly mainMapRenderer: IMapRenderer;
readonly expandMapRenderer: IMapRenderer;
readonly mainMapExtension: IMapExtensionManager;
readonly sceneController: UIController;
readonly mainUIController: UIController;
readonly sceneController: IUIController<IGameUIPropsBase>;
readonly mainUIController: IUIController<IGameUIPropsBase>;
// Layer 5 渲染顶层
@ -121,8 +123,11 @@ export class ClientCore extends CoreState implements IClientCore {
this.mainMapRenderer = new MapRenderer(this.materials);
this.mainMapExtension = new MapExtensionManager(this.mainMapRenderer);
this.expandMapRenderer = new MapRenderer(this.materials);
this.sceneController = new UIController('main-scene');
this.mainUIController = new UIController('main-ui');
this.sceneController = new UIController<IGameUIPropsBase>();
this.mainUIController = new UIController<IGameUIPropsBase>();
const pbCreator = createUIPropsBase(this);
this.sceneController.setPropsBaseCreator(pbCreator);
this.mainUIController.setPropsBaseCreator(pbCreator);
//#endregion
@ -131,6 +136,9 @@ export class ClientCore extends CoreState implements IClientCore {
this.init();
}
/**
* 初始化渲染端主对象
*/
private async init() {
createApp(this.sceneController.render()).mount(this.renderer);
this.sceneController.open(LoadSceneUI, {});

View File

@ -0,0 +1,26 @@
import {
IUIController,
IUIInstance,
UIComponent,
UIPropsBaseCreator
} from '@motajs/system';
import { IClientBase, IGameUIPropsBase } from '@user/client-base';
/**
* 创建游戏 UI 基础参数的构造函数
* @param state 游戏状态对象
*/
export function createUIPropsBase(
state: IClientBase
): UIPropsBaseCreator<IGameUIPropsBase> {
return (
instance: IUIInstance<UIComponent, IGameUIPropsBase>,
controller: IUIController<IGameUIPropsBase>
): IGameUIPropsBase => {
return {
instance,
controller,
state
};
};
}

View File

@ -73,6 +73,7 @@
"71": "Passive replay command needs a ReplayCommandResult status transfering by IReplayPassiveHandler.next, but system got a undefined.",
"72": "Replay error when replaying $1 replay step, detailed error message will show together with this error info.",
"73": "No passive replay needed currently, but a 'getPassive' call detected, check if there's an issue on replay array or your replay logic.",
"74": "A UI base props creator binding is needed before using ui controller.",
"2001": "Replay($1): Replay parameter count mismatch: expected $2, got $3.",
"2002": "Replay($1): Replay parameter type mismatch: index $2, expected $3, got $4.",
"2003": "Replay(move): Expected hero to be stopped before execute moving step.",

View File

@ -30,16 +30,18 @@ export const UIContainer = defineComponent<IUIContainerProps>(props => {
);
}
return elements.concat(
data.stack.map((v, i) => (
<v.ui.component
{...v.vBind}
key={v.key}
controller={data}
instance={v}
hidden={v.hidden.value}
zIndex={i * 5}
></v.ui.component>
))
data.stack.map((v, i) => {
const pb = data.createPropsBase(v);
return (
<v.ui.component
{...v.vBind}
{...pb}
key={v.key}
hidden={v.hidden.value}
zIndex={i * 5}
></v.ui.component>
);
})
);
};
}, containerConfig);

View File

@ -6,7 +6,8 @@ import {
UIComponent,
IUIDefaultPropsBase,
IUICustomStrategy,
UIRawProps
UIRawProps,
UIPropsBaseCreator
} from './types';
import { UIInstance } from './instance';
import {
@ -20,6 +21,7 @@ import {
VNode
} from 'vue';
import { UIContainer } from './container';
import { logger } from '@motajs/common';
export class UIController<
PB extends IUIDefaultPropsBase<any>
@ -34,6 +36,8 @@ export class UIController<
/** 当前的自定义 UI 控制策略 */
private strategy: IUICustomStrategy<PB>;
/** UI 基础参数的构造函数 */
private creator: UIPropsBaseCreator<PB> | null = null;
/** 是否维持背景 UI */
private keepBack: boolean = false;
@ -52,6 +56,20 @@ export class UIController<
this.strategy = new UILastOnlyStrategy();
}
setPropsBaseCreator(creator: UIPropsBaseCreator<PB> | null): void {
this.creator = creator;
}
createPropsBase(instance: IUIInstance<UIComponent, PB>): PB {
if (!this.creator) {
logger.error(74);
// @ts-expect-error 不存在构造函数时的
return { instance, controller: this } as PB;
} else {
return this.creator(instance, this);
}
}
setBackground<C extends UIComponent>(
background: IGameUI<C> | null,
vBind: UIRawProps<C, PB>

View File

@ -112,6 +112,14 @@ export type UIRawProps<
PB extends IUIDefaultPropsBase<any>
> = Omit<Props<C>, keyof PB>;
/**
* UI 基础 Props 参数的构造函数
*/
export type UIPropsBaseCreator<PB extends IUIDefaultPropsBase<any>> = (
instance: IUIInstance<UIComponent, PB>,
controller: IUIController<PB>
) => PB;
export interface IUIController<PB extends IUIDefaultPropsBase<any>> {
/** 当前的 UI 栈 */
readonly stack: IUIInstance[];
@ -125,6 +133,18 @@ export interface IUIController<PB extends IUIDefaultPropsBase<any>> {
/** 当前是否显示背景的响应式对象,用于容器响应式判断是否需要显示背景 */
readonly showBack: Ref<boolean>;
/**
* 设置基础参数的构造函数
* @param creator UI 基础 Props 参数的构造函数
*/
setPropsBaseCreator(creator: UIPropsBaseCreator<PB> | null): void;
/**
* 创建对应 UI 实例对象的基础参数
* @param instance UI 实例对象
*/
createPropsBase(instance: IUIInstance<UIComponent, PB>): PB;
/**
* 设置控制器的背景 UI
* @param background 背景 UI