mirror of
https://github.com/unanmed/HumanBreak.git
synced 2025-04-25 00:23:25 +08:00
Compare commits
2 Commits
109e77d6a2
...
0cc76bd475
Author | SHA1 | Date | |
---|---|---|---|
0cc76bd475 | |||
5b2f42f692 |
@ -1,9 +1,9 @@
|
|||||||
import { computed, defineComponent, VNode } from 'vue';
|
import { defineComponent, VNode } from 'vue';
|
||||||
import { IUIMountable, UIComponent } from './shared';
|
import { IUIMountable } from './shared';
|
||||||
import { SetupComponentOptions } from '@/module';
|
import { SetupComponentOptions } from '@/module';
|
||||||
|
|
||||||
export interface UIContainerProps {
|
export interface UIContainerProps {
|
||||||
controller: IUIMountable<UIComponent>;
|
controller: IUIMountable;
|
||||||
}
|
}
|
||||||
|
|
||||||
const containerConfig = {
|
const containerConfig = {
|
||||||
@ -13,18 +13,29 @@ const containerConfig = {
|
|||||||
export const UIContainer = defineComponent<UIContainerProps>(props => {
|
export const UIContainer = defineComponent<UIContainerProps>(props => {
|
||||||
const data = props.controller;
|
const data = props.controller;
|
||||||
const back = data.backIns;
|
const back = data.backIns;
|
||||||
const show = computed(() => data.stack.filter(v => !v.hidden));
|
|
||||||
return (): VNode[] => {
|
return (): VNode[] => {
|
||||||
const elements: VNode[] = [];
|
const elements: VNode[] = [];
|
||||||
const b = back.value;
|
const b = back.value;
|
||||||
if (b && data.showBack.value && !b.hidden) {
|
if (b && data.showBack.value && !b.hidden) {
|
||||||
elements.push(
|
elements.push(
|
||||||
<b.ui.component {...b.vBind} key={b.key}></b.ui.component>
|
<b.ui.component
|
||||||
|
{...b.vBind}
|
||||||
|
controller={data}
|
||||||
|
instance={b}
|
||||||
|
key={b.key}
|
||||||
|
hidden={b.hidden}
|
||||||
|
></b.ui.component>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return elements.concat(
|
return elements.concat(
|
||||||
show.value.map(v => (
|
data.stack.map(v => (
|
||||||
<v.ui.component {...v.vBind} key={v.key}></v.ui.component>
|
<v.ui.component
|
||||||
|
{...v.vBind}
|
||||||
|
key={v.key}
|
||||||
|
controller={data}
|
||||||
|
instance={v}
|
||||||
|
hidden={v.hidden}
|
||||||
|
></v.ui.component>
|
||||||
))
|
))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -5,9 +5,9 @@ import {
|
|||||||
IKeepController,
|
IKeepController,
|
||||||
IUIInstance,
|
IUIInstance,
|
||||||
IUIMountable,
|
IUIMountable,
|
||||||
UIComponent
|
UIComponent,
|
||||||
|
UIProps
|
||||||
} from './shared';
|
} from './shared';
|
||||||
import { Props } from '@/core/render';
|
|
||||||
import { UIInstance } from './instance';
|
import { UIInstance } from './instance';
|
||||||
import {
|
import {
|
||||||
computed,
|
computed,
|
||||||
@ -35,13 +35,13 @@ export const enum UIMode {
|
|||||||
Custom
|
Custom
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUICustomConfig<C extends UIComponent> {
|
export interface IUICustomConfig {
|
||||||
/**
|
/**
|
||||||
* 打开一个新的 UI
|
* 打开一个新的 UI
|
||||||
* @param ins 要打开的 UI 实例
|
* @param ins 要打开的 UI 实例
|
||||||
* @param stack 当前的 UI 栈,还未将 UI 实例加入栈中
|
* @param stack 当前的 UI 栈,还未将 UI 实例加入栈中
|
||||||
*/
|
*/
|
||||||
open(ins: IUIInstance<C>, stack: IUIInstance<C>[]): void;
|
open(ins: IUIInstance, stack: IUIInstance[]): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 关闭一个 UI
|
* 关闭一个 UI
|
||||||
@ -49,7 +49,7 @@ export interface IUICustomConfig<C extends UIComponent> {
|
|||||||
* @param stack 当前的 UI 栈,还未将 UI 实例移除
|
* @param stack 当前的 UI 栈,还未将 UI 实例移除
|
||||||
* @param index 这个 UI 实例在 UI 栈中的索引
|
* @param index 这个 UI 实例在 UI 栈中的索引
|
||||||
*/
|
*/
|
||||||
close(ins: IUIInstance<C>, stack: IUIInstance<C>[], index: number): void;
|
close(ins: IUIInstance, stack: IUIInstance[], index: number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏一个 UI
|
* 隐藏一个 UI
|
||||||
@ -57,7 +57,7 @@ export interface IUICustomConfig<C extends UIComponent> {
|
|||||||
* @param stack 当前的 UI 栈
|
* @param stack 当前的 UI 栈
|
||||||
* @param index 这个 UI 实例在 UI 栈中的索引
|
* @param index 这个 UI 实例在 UI 栈中的索引
|
||||||
*/
|
*/
|
||||||
hide(ins: IUIInstance<C>, stack: IUIInstance<C>[], index: number): void;
|
hide(ins: IUIInstance, stack: IUIInstance[], index: number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示一个 UI
|
* 显示一个 UI
|
||||||
@ -65,32 +65,32 @@ export interface IUICustomConfig<C extends UIComponent> {
|
|||||||
* @param stack 当前的 UI 栈
|
* @param stack 当前的 UI 栈
|
||||||
* @param index 这个 UI 实例在 UI 栈中的索引
|
* @param index 这个 UI 实例在 UI 栈中的索引
|
||||||
*/
|
*/
|
||||||
show(ins: IUIInstance<C>, stack: IUIInstance<C>[], index: number): void;
|
show(ins: IUIInstance, stack: IUIInstance[], index: number): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 更新所有 UI 的显示,一般会在显示模式更改时调用
|
* 更新所有 UI 的显示,一般会在显示模式更改时调用
|
||||||
* @param stack 当前的 UI 栈
|
* @param stack 当前的 UI 栈
|
||||||
*/
|
*/
|
||||||
update(stack: IUIInstance<C>[]): void;
|
update(stack: IUIInstance[]): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface UIControllerEvent {}
|
interface UIControllerEvent {}
|
||||||
|
|
||||||
export class UIController<C extends UIComponent = UIComponent>
|
export class UIController
|
||||||
extends EventEmitter<UIControllerEvent>
|
extends EventEmitter<UIControllerEvent>
|
||||||
implements IUIMountable<C>
|
implements IUIMountable
|
||||||
{
|
{
|
||||||
static controllers: Map<string, UIController> = new Map();
|
static controllers: Map<string, UIController> = new Map();
|
||||||
|
|
||||||
/** 当前的 ui 栈 */
|
/** 当前的 ui 栈 */
|
||||||
readonly stack: IUIInstance<C>[] = reactive([]);
|
readonly stack: IUIInstance[] = reactive([]);
|
||||||
/** UI 显示方式 */
|
/** UI 显示方式 */
|
||||||
mode: UIMode = UIMode.LastOnlyStack;
|
mode: UIMode = UIMode.LastOnlyStack;
|
||||||
/** 这个 UI 实例的背景,当这个 UI 处于显示模式时,会显示背景 */
|
/** 这个 UI 实例的背景,当这个 UI 处于显示模式时,会显示背景 */
|
||||||
background?: IGameUI<C>;
|
background?: IGameUI;
|
||||||
|
|
||||||
/** 背景 UI 实例 */
|
/** 背景 UI 实例 */
|
||||||
readonly backIns: ShallowRef<IUIInstance<C> | null> = shallowRef(null);
|
readonly backIns: ShallowRef<IUIInstance | null> = shallowRef(null);
|
||||||
/** 当前是否显示背景 UI */
|
/** 当前是否显示背景 UI */
|
||||||
readonly showBack: ComputedRef<boolean> = computed(
|
readonly showBack: ComputedRef<boolean> = computed(
|
||||||
() => this.userShowBack.value && this.sysShowBack.value
|
() => this.userShowBack.value && this.sysShowBack.value
|
||||||
@ -102,7 +102,7 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** 自定义显示模式下的配置信息 */
|
/** 自定义显示模式下的配置信息 */
|
||||||
private config?: IUICustomConfig<C>;
|
private config?: IUICustomConfig;
|
||||||
/** 是否维持背景 UI */
|
/** 是否维持背景 UI */
|
||||||
private keepBack: boolean = false;
|
private keepBack: boolean = false;
|
||||||
/** 用户是否显示背景 UI */
|
/** 用户是否显示背景 UI */
|
||||||
@ -134,7 +134,7 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
* 设置背景 UI
|
* 设置背景 UI
|
||||||
* @param back 这个 UI 控制器的背景 UI
|
* @param back 这个 UI 控制器的背景 UI
|
||||||
*/
|
*/
|
||||||
setBackground(back: IGameUI<C>) {
|
setBackground(back: IGameUI) {
|
||||||
this.background = back;
|
this.background = back;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,13 +171,12 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
open<T extends UIComponent>(
|
||||||
* 打开一个 ui
|
ui: IGameUI<T>,
|
||||||
* @param ui 要打开的 ui
|
vBind: UIProps<T>,
|
||||||
* @param vBind 传递给这个 ui 的响应式数据
|
alwaysShow: boolean = false
|
||||||
*/
|
): IUIInstance<T> {
|
||||||
open(ui: IGameUI<C>, vBind: Props<C>) {
|
const ins = new UIInstance(ui, vBind, alwaysShow);
|
||||||
const ins = new UIInstance(ui, vBind);
|
|
||||||
switch (this.mode) {
|
switch (this.mode) {
|
||||||
case UIMode.LastOnly:
|
case UIMode.LastOnly:
|
||||||
case UIMode.LastOnlyStack:
|
case UIMode.LastOnlyStack:
|
||||||
@ -196,11 +195,7 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
return ins;
|
return ins;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
close(ui: IUIInstance) {
|
||||||
* 关闭一个 ui
|
|
||||||
* @param ui 要关闭的 ui 实例
|
|
||||||
*/
|
|
||||||
close(ui: UIInstance<C>) {
|
|
||||||
const index = this.stack.indexOf(ui);
|
const index = this.stack.indexOf(ui);
|
||||||
if (index === -1) return;
|
if (index === -1) return;
|
||||||
switch (this.mode) {
|
switch (this.mode) {
|
||||||
@ -239,7 +234,16 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
this.keepBack = false;
|
this.keepBack = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
hide(ins: IUIInstance<C>): void {
|
closeAll(ui?: IGameUI): void {
|
||||||
|
if (!ui) {
|
||||||
|
this.stack.splice(0);
|
||||||
|
} else {
|
||||||
|
const list = this.stack.filter(v => v.ui === ui);
|
||||||
|
list.forEach(v => this.close(v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hide(ins: IUIInstance): void {
|
||||||
const index = this.stack.indexOf(ins);
|
const index = this.stack.indexOf(ins);
|
||||||
if (index === -1) return;
|
if (index === -1) return;
|
||||||
if (this.mode === UIMode.Custom) {
|
if (this.mode === UIMode.Custom) {
|
||||||
@ -249,7 +253,7 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
show(ins: IUIInstance<C>): void {
|
show(ins: IUIInstance): void {
|
||||||
const index = this.stack.indexOf(ins);
|
const index = this.stack.indexOf(ins);
|
||||||
if (index === -1) return;
|
if (index === -1) return;
|
||||||
if (this.mode === UIMode.Custom) {
|
if (this.mode === UIMode.Custom) {
|
||||||
@ -290,7 +294,7 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
* 使用自定义的显示模式
|
* 使用自定义的显示模式
|
||||||
* @param config 自定义显示模式的配置
|
* @param config 自定义显示模式的配置
|
||||||
*/
|
*/
|
||||||
showCustom(config: IUICustomConfig<C>) {
|
showCustom(config: IUICustomConfig) {
|
||||||
this.mode = UIMode.Custom;
|
this.mode = UIMode.Custom;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
config.update(this.stack);
|
config.update(this.stack);
|
||||||
@ -300,10 +304,8 @@ export class UIController<C extends UIComponent = UIComponent>
|
|||||||
* 获取一个元素上的 ui 控制器
|
* 获取一个元素上的 ui 控制器
|
||||||
* @param id 要获取的 ui 控制器的唯一标识符
|
* @param id 要获取的 ui 控制器的唯一标识符
|
||||||
*/
|
*/
|
||||||
static getController<T extends UIComponent>(
|
static getController(id: string): UIController | null {
|
||||||
id: string
|
const res = this.controllers.get(id);
|
||||||
): UIController<T> | null {
|
|
||||||
const res = this.controllers.get(id) as UIController<T>;
|
|
||||||
return res ?? null;
|
return res ?? null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { Props } from '@/core/render';
|
import { Props } from '@/core/render';
|
||||||
import { IGameUI, IUIInstance, UIComponent } from './shared';
|
import { IGameUI, IUIInstance, UIComponent, UIProps } from './shared';
|
||||||
import EventEmitter from 'eventemitter3';
|
import EventEmitter from 'eventemitter3';
|
||||||
import { markRaw, mergeProps } from 'vue';
|
import { markRaw, mergeProps } from 'vue';
|
||||||
|
|
||||||
@ -21,7 +21,8 @@ export class UIInstance<C extends UIComponent>
|
|||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
ui: IGameUI<C>,
|
ui: IGameUI<C>,
|
||||||
public vBind: Props<C>
|
public vBind: UIProps<C>,
|
||||||
|
public readonly alwaysShow: boolean = false
|
||||||
) {
|
) {
|
||||||
super();
|
super();
|
||||||
this.ui = markRaw(ui);
|
this.ui = markRaw(ui);
|
||||||
@ -30,13 +31,13 @@ export class UIInstance<C extends UIComponent>
|
|||||||
/**
|
/**
|
||||||
* 设置这个 UI 实例的响应式数据的值
|
* 设置这个 UI 实例的响应式数据的值
|
||||||
* @param data 要设置的值
|
* @param data 要设置的值
|
||||||
* @param merge 是将传入的值与原先的值合并(true),还是将当前值覆盖掉原先的值(false)
|
* @param merge 是将传入的值与原先的值合并(true),还是将当前值覆盖掉原先的值(false),默认合并
|
||||||
*/
|
*/
|
||||||
setVBind(data: Props<C>, merge: boolean = true) {
|
setVBind(data: Partial<Props<C>>, merge: boolean = true) {
|
||||||
if (merge) {
|
if (merge) {
|
||||||
this.vBind = mergeProps(this.vBind, data) as Props<C>;
|
this.vBind = mergeProps(this.vBind, data) as UIProps<C>;
|
||||||
} else {
|
} else {
|
||||||
this.vBind = data;
|
this.vBind = data as UIProps<C>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,17 @@ import { DefineComponent, DefineSetupFnComponent, Ref, ShallowRef } from 'vue';
|
|||||||
|
|
||||||
export type UIComponent = DefineSetupFnComponent<any> | DefineComponent;
|
export type UIComponent = DefineSetupFnComponent<any> | DefineComponent;
|
||||||
|
|
||||||
export interface IGameUI<C extends UIComponent> {
|
export interface UIComponentProps<T extends UIComponent = UIComponent> {
|
||||||
|
controller: IUIMountable;
|
||||||
|
instance: IUIInstance<T>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type UIProps<C extends UIComponent = UIComponent> = Omit<
|
||||||
|
Props<C>,
|
||||||
|
keyof UIComponentProps<C>
|
||||||
|
>;
|
||||||
|
|
||||||
|
export interface IGameUI<C extends UIComponent = UIComponent> {
|
||||||
/** 这个 UI 的名称 */
|
/** 这个 UI 的名称 */
|
||||||
readonly name: string;
|
readonly name: string;
|
||||||
/** 这个 UI 的组件 */
|
/** 这个 UI 的组件 */
|
||||||
@ -22,11 +32,11 @@ export interface IKeepController {
|
|||||||
unload(): void;
|
unload(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUIMountable<C extends UIComponent> {
|
export interface IUIMountable {
|
||||||
/** 当前的 UI 栈 */
|
/** 当前的 UI 栈 */
|
||||||
readonly stack: IUIInstance<C>[];
|
readonly stack: IUIInstance<UIComponent>[];
|
||||||
/** 当前的背景 UI */
|
/** 当前的背景 UI */
|
||||||
readonly backIns: ShallowRef<IUIInstance<C> | null>;
|
readonly backIns: ShallowRef<IUIInstance<UIComponent> | null>;
|
||||||
/** 当前是否显示背景 UI */
|
/** 当前是否显示背景 UI */
|
||||||
readonly showBack: Ref<boolean>;
|
readonly showBack: Ref<boolean>;
|
||||||
|
|
||||||
@ -34,13 +44,46 @@ export interface IUIMountable<C extends UIComponent> {
|
|||||||
* 隐藏一个 UI
|
* 隐藏一个 UI
|
||||||
* @param ins 要隐藏的 UI 实例
|
* @param ins 要隐藏的 UI 实例
|
||||||
*/
|
*/
|
||||||
hide(ins: IUIInstance<C>): void;
|
hide(ins: IUIInstance<UIComponent>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 显示一个 UI
|
* 显示一个 UI
|
||||||
* @param ins 要显示的 UI 实例
|
* @param ins 要显示的 UI 实例
|
||||||
*/
|
*/
|
||||||
show(ins: IUIInstance<C>): void;
|
show(ins: IUIInstance<UIComponent>): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 隐藏背景 UI
|
||||||
|
*/
|
||||||
|
hideBackground(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 显示背景 UI
|
||||||
|
*/
|
||||||
|
showBackground(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打开一个 ui
|
||||||
|
* @param ui 要打开的 ui
|
||||||
|
* @param vBind 传递给这个 ui 的响应式数据
|
||||||
|
* @param alwaysShow 这个 ui 是否保持开启,对于需要叠加显示的 ui 非常有用
|
||||||
|
*/
|
||||||
|
open<T extends UIComponent>(
|
||||||
|
ui: IGameUI<T>,
|
||||||
|
vBind: UIProps<T>,
|
||||||
|
alwaysShow?: boolean
|
||||||
|
): IUIInstance<T>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭一个 ui
|
||||||
|
* @param ui 要关闭的 ui 实例
|
||||||
|
*/
|
||||||
|
close(ui: IUIInstance<UIComponent>): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 关闭所有或指定类型的所有 UI
|
||||||
|
*/
|
||||||
|
closeAll(ui?: IGameUI<UIComponent>): void;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 维持背景,直到下次所有 UI 都被关闭
|
* 维持背景,直到下次所有 UI 都被关闭
|
||||||
@ -48,15 +91,17 @@ export interface IUIMountable<C extends UIComponent> {
|
|||||||
keep(): IKeepController;
|
keep(): IKeepController;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IUIInstance<C extends UIComponent> {
|
export interface IUIInstance<C extends UIComponent = UIComponent> {
|
||||||
/** 这个 ui 实例的唯一 key,用于 vue */
|
/** 这个 ui 实例的唯一 key,用于 vue */
|
||||||
readonly key: number;
|
readonly key: number;
|
||||||
/** 这个 ui 实例的 ui 信息 */
|
/** 这个 ui 实例的 ui 信息 */
|
||||||
readonly ui: IGameUI<C>;
|
readonly ui: IGameUI<C>;
|
||||||
/** 传递给这个 ui 实例的响应式数据 */
|
/** 传递给这个 ui 实例的响应式数据 */
|
||||||
readonly vBind: Props<C>;
|
readonly vBind: UIProps<C>;
|
||||||
/** 当前元素是否被隐藏 */
|
/** 当前元素是否被隐藏 */
|
||||||
readonly hidden: boolean;
|
readonly hidden: boolean;
|
||||||
|
/** 是否永远保持开启 */
|
||||||
|
readonly alwaysShow: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 隐藏这个 ui
|
* 隐藏这个 ui
|
||||||
|
@ -5,6 +5,7 @@ import { TextContent, TextContentExpose, TextContentProps } from './textbox';
|
|||||||
import { SetupComponentOptions } from './types';
|
import { SetupComponentOptions } from './types';
|
||||||
import { TextAlign } from './textboxTyper';
|
import { TextAlign } from './textboxTyper';
|
||||||
import { Page, PageExpose } from './page';
|
import { Page, PageExpose } from './page';
|
||||||
|
import { GameUI, IUIMountable } from '@/core/system';
|
||||||
|
|
||||||
export interface ConfirmBoxProps extends DefaultProps, TextContentProps {
|
export interface ConfirmBoxProps extends DefaultProps, TextContentProps {
|
||||||
text: string;
|
text: string;
|
||||||
@ -66,11 +67,11 @@ const confirmBoxProps = {
|
|||||||
* color="#333"
|
* color="#333"
|
||||||
* border="gold"
|
* border="gold"
|
||||||
* // 设置选项的字体
|
* // 设置选项的字体
|
||||||
* selFont="16px Verdana"
|
* selFont={new Font('Verdana', 16)}
|
||||||
* // 设置选项的文本颜色
|
* // 设置选项的文本颜色
|
||||||
* selFill="#d48"
|
* selFill="#d48"
|
||||||
* // 完全继承 TextContent 的参数,因此可以填写 fontFamily 参数指定文本字体
|
* // 完全继承 TextContent 的参数,因此可以填写 font 参数指定文本字体
|
||||||
* fontFamily="Arial"
|
* font={new Font('arial')}
|
||||||
* onYes={onYes}
|
* onYes={onYes}
|
||||||
* onNo={onNo}
|
* onNo={onNo}
|
||||||
* />
|
* />
|
||||||
@ -191,8 +192,11 @@ export const ConfirmBox = defineComponent<
|
|||||||
);
|
);
|
||||||
}, confirmBoxProps);
|
}, confirmBoxProps);
|
||||||
|
|
||||||
|
export type ChoiceKey = string | number | symbol;
|
||||||
|
export type ChoiceItem = [key: ChoiceKey, text: string];
|
||||||
|
|
||||||
export interface ChoicesProps extends DefaultProps, TextContentProps {
|
export interface ChoicesProps extends DefaultProps, TextContentProps {
|
||||||
choices: [key: string | number | symbol, text: string][];
|
choices: ChoiceItem[];
|
||||||
loc: ElementLocator;
|
loc: ElementLocator;
|
||||||
width: number;
|
width: number;
|
||||||
maxHeight?: number;
|
maxHeight?: number;
|
||||||
@ -206,12 +210,11 @@ export interface ChoicesProps extends DefaultProps, TextContentProps {
|
|||||||
titleFont?: Font;
|
titleFont?: Font;
|
||||||
titleFill?: CanvasStyle;
|
titleFill?: CanvasStyle;
|
||||||
pad?: number;
|
pad?: number;
|
||||||
defaultChoice?: string | number | symbol;
|
|
||||||
interval?: number;
|
interval?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type ChoicesEmits = {
|
export type ChoicesEmits = {
|
||||||
choice: (key: string | number | symbol) => void;
|
choose: (key: ChoiceKey) => void;
|
||||||
};
|
};
|
||||||
|
|
||||||
const choicesProps = {
|
const choicesProps = {
|
||||||
@ -230,16 +233,49 @@ const choicesProps = {
|
|||||||
'titleFont',
|
'titleFont',
|
||||||
'titleFill',
|
'titleFill',
|
||||||
'pad',
|
'pad',
|
||||||
'defaultChoice',
|
|
||||||
'interval'
|
'interval'
|
||||||
],
|
],
|
||||||
emits: ['choice']
|
emits: ['choose']
|
||||||
} satisfies SetupComponentOptions<
|
} satisfies SetupComponentOptions<
|
||||||
ChoicesProps,
|
ChoicesProps,
|
||||||
ChoicesEmits,
|
ChoicesEmits,
|
||||||
keyof ChoicesEmits
|
keyof ChoicesEmits
|
||||||
>;
|
>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 选项框组件,用于在多个选项中选择一个,例如样板的系统设置就由它实现。
|
||||||
|
* 参数参考 {@link ChoicesProps},事件参考 {@link ChoicesEmits}。用例如下:
|
||||||
|
* ```tsx
|
||||||
|
* <Choices
|
||||||
|
* // 选项数组,每一项是一个二元素数组,第一项表示这个选项的 id,在选中时会以此作为参数传递给事件
|
||||||
|
* // 第二项表示这一项的内容,即展示给玩家看的内容
|
||||||
|
* choices={[[0, '选项1'], [100, '选项2']]}
|
||||||
|
* // 选项框会自动计算宽度和高度,因此不需要手动指定,即使手动指定也无效
|
||||||
|
* loc={[240, 240, void 0, void 0, 0.5, 0.5]}
|
||||||
|
* text="请选择一项"
|
||||||
|
* title="选项"
|
||||||
|
* // 使用 winskin 图片作为背景
|
||||||
|
* winskin="winskin.png"
|
||||||
|
* // 使用颜色作为背景和边框,如果设置了 winskin,那么此参数无效
|
||||||
|
* color="#333"
|
||||||
|
* border="gold"
|
||||||
|
* // 调整每两个选项之间的间隔
|
||||||
|
* interval={12}
|
||||||
|
* // 设置选项的字体
|
||||||
|
* selFont={new Font('Verdana', 16)}
|
||||||
|
* // 设置选项的文本颜色
|
||||||
|
* selFill="#d48"
|
||||||
|
* // 设置标题的字体
|
||||||
|
* titleFont={new Font('Verdana', 16)}
|
||||||
|
* // 设置标题的文本颜色
|
||||||
|
* selFill="gold"
|
||||||
|
* // 完全继承 TextContent 的参数,因此可以填写 font 参数指定文本字体
|
||||||
|
* font={new Font('arial')}
|
||||||
|
* // 当选择某一项时触发
|
||||||
|
* onChoice={(choice) => console.log(choice)}
|
||||||
|
* />
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
export const Choices = defineComponent<
|
export const Choices = defineComponent<
|
||||||
ChoicesProps,
|
ChoicesProps,
|
||||||
ChoicesEmits,
|
ChoicesEmits,
|
||||||
@ -424,7 +460,7 @@ export const Choices = defineComponent<
|
|||||||
key.realize('confirm', () => {
|
key.realize('confirm', () => {
|
||||||
const page = pageCom.value?.now() ?? 1;
|
const page = pageCom.value?.now() ?? 1;
|
||||||
const index = page * choiceCountPerPage.value + selected.value;
|
const index = page * choiceCountPerPage.value + selected.value;
|
||||||
emit('choice', props.choices[index][0]);
|
emit('choose', props.choices[index][0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
return () => (
|
return () => (
|
||||||
@ -479,7 +515,7 @@ export const Choices = defineComponent<
|
|||||||
font={props.selFont}
|
font={props.selFont}
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
zIndex={5}
|
zIndex={5}
|
||||||
onClick={() => emit('choice', v[0])}
|
onClick={() => emit('choose', v[0])}
|
||||||
onSetText={(_, width, height) =>
|
onSetText={(_, width, height) =>
|
||||||
updateChoiceSize(i, width, height)
|
updateChoiceSize(i, width, height)
|
||||||
}
|
}
|
||||||
@ -492,3 +528,78 @@ export const Choices = defineComponent<
|
|||||||
</container>
|
</container>
|
||||||
);
|
);
|
||||||
}, choicesProps);
|
}, choicesProps);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出一个确认框,然后将确认结果返回
|
||||||
|
* @param controller UI 控制器
|
||||||
|
* @param text 确认文本内容
|
||||||
|
* @param loc 确认框的位置
|
||||||
|
* @param width 确认框的宽度
|
||||||
|
* @param props 额外的 props
|
||||||
|
*/
|
||||||
|
export function getConfirm(
|
||||||
|
controller: IUIMountable,
|
||||||
|
text: string,
|
||||||
|
loc: ElementLocator,
|
||||||
|
width: number,
|
||||||
|
props?: Partial<ConfirmBoxProps>
|
||||||
|
) {
|
||||||
|
return new Promise<boolean>(res => {
|
||||||
|
const instance = controller.open(
|
||||||
|
ConfirmBoxUI,
|
||||||
|
{
|
||||||
|
...(props ?? {}),
|
||||||
|
loc,
|
||||||
|
text,
|
||||||
|
width,
|
||||||
|
onYes: () => {
|
||||||
|
controller.close(instance);
|
||||||
|
res(true);
|
||||||
|
},
|
||||||
|
onNo: () => {
|
||||||
|
controller.close(instance);
|
||||||
|
res(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 弹出一个选择框,然后将选择结果返回
|
||||||
|
* @param controller UI 控制器
|
||||||
|
* @param choices 选择框的选项
|
||||||
|
* @param loc 选择框的位置
|
||||||
|
* @param width 选择框的宽度
|
||||||
|
* @param props 额外的 props
|
||||||
|
*/
|
||||||
|
export function getChoice<T extends ChoiceKey = ChoiceKey>(
|
||||||
|
controller: IUIMountable,
|
||||||
|
choices: ChoiceItem[],
|
||||||
|
loc: ElementLocator,
|
||||||
|
width: number,
|
||||||
|
props?: Partial<ChoicesProps>
|
||||||
|
) {
|
||||||
|
return new Promise<T>(res => {
|
||||||
|
const instance = controller.open(
|
||||||
|
ChoicesUI,
|
||||||
|
{
|
||||||
|
...(props ?? {}),
|
||||||
|
choices,
|
||||||
|
loc,
|
||||||
|
width,
|
||||||
|
onChoose: key => {
|
||||||
|
controller.close(instance);
|
||||||
|
res(key as T);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @see {@link ConfirmBox} */
|
||||||
|
export const ConfirmBoxUI = new GameUI('confirm-box', ConfirmBox);
|
||||||
|
/** @see {@link Choices} */
|
||||||
|
export const ChoicesUI = new GameUI('choices', Choices);
|
||||||
|
Loading…
Reference in New Issue
Block a user