2022-12-29 12:02:48 +08:00
|
|
|
|
import { message } from 'ant-design-vue';
|
|
|
|
|
import { MessageApi } from 'ant-design-vue/lib/message';
|
2023-05-13 21:47:37 +08:00
|
|
|
|
import { isNil } from 'lodash-es';
|
2023-02-21 23:22:03 +08:00
|
|
|
|
import { Animation, sleep, TimingFn } from 'mutate-animate';
|
2023-06-21 17:10:06 +08:00
|
|
|
|
import { ref } from 'vue';
|
2024-01-18 15:25:33 +08:00
|
|
|
|
import { EVENT_KEY_CODE_MAP, KeyCode } from './keyCodes';
|
2023-04-28 23:58:07 +08:00
|
|
|
|
import axios from 'axios';
|
|
|
|
|
import { decompressFromBase64 } from 'lz-string';
|
2023-06-20 11:56:25 +08:00
|
|
|
|
import { parseColor } from './webgl/utils';
|
2024-01-19 16:07:59 +08:00
|
|
|
|
import { Keyboard, KeyboardEmits } from '@/core/main/custom/keyboard';
|
2024-04-23 21:43:26 +08:00
|
|
|
|
import { fixedUi, mainUi } from '@/core/main/init/ui';
|
2024-01-19 16:07:59 +08:00
|
|
|
|
import { isAssist } from '@/core/main/custom/hotkey';
|
2024-04-23 21:43:26 +08:00
|
|
|
|
import { logger } from '@/core/common/logger';
|
2022-11-16 23:01:23 +08:00
|
|
|
|
|
2022-11-21 20:00:34 +08:00
|
|
|
|
type CanParseCss = keyof {
|
|
|
|
|
[P in keyof CSSStyleDeclaration as CSSStyleDeclaration[P] extends string
|
|
|
|
|
? P extends string
|
|
|
|
|
? P
|
|
|
|
|
: never
|
|
|
|
|
: never]: CSSStyleDeclaration[P];
|
|
|
|
|
};
|
|
|
|
|
|
2022-11-16 23:01:23 +08:00
|
|
|
|
export default function init() {
|
2023-04-28 23:58:07 +08:00
|
|
|
|
return {
|
|
|
|
|
has,
|
|
|
|
|
getDamageColor,
|
|
|
|
|
parseCss,
|
|
|
|
|
tip,
|
|
|
|
|
changeLocalStorage,
|
|
|
|
|
swapChapter
|
|
|
|
|
};
|
2022-11-16 23:01:23 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 判定一个值是否不是undefined或null
|
|
|
|
|
* @param value 要判断的值
|
|
|
|
|
*/
|
|
|
|
|
export function has<T>(value: T): value is NonNullable<T> {
|
|
|
|
|
return !isNil(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 根据伤害大小获取颜色
|
|
|
|
|
* @param damage 伤害大小
|
|
|
|
|
*/
|
2022-12-27 23:31:14 +08:00
|
|
|
|
export function getDamageColor(damage: number): Color {
|
2022-11-16 23:01:23 +08:00
|
|
|
|
if (typeof damage !== 'number') return '#f00';
|
|
|
|
|
if (damage === 0) return '#2f2';
|
|
|
|
|
if (damage < 0) return '#7f7';
|
|
|
|
|
if (damage < core.status.hero.hp / 3) return '#fff';
|
|
|
|
|
if (damage < (core.status.hero.hp * 2) / 3) return '#ff4';
|
2022-12-30 14:14:28 +08:00
|
|
|
|
if (damage < core.status.hero.hp) return '#f93';
|
|
|
|
|
return '#f22';
|
2022-11-16 23:01:23 +08:00
|
|
|
|
}
|
2022-11-19 11:30:14 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置画布的长宽
|
|
|
|
|
* @param canvas 画布
|
|
|
|
|
* @param w 宽度
|
|
|
|
|
* @param h 高度
|
|
|
|
|
*/
|
|
|
|
|
export function setCanvasSize(
|
|
|
|
|
canvas: HTMLCanvasElement,
|
|
|
|
|
w: number,
|
|
|
|
|
h: number
|
|
|
|
|
): void {
|
|
|
|
|
canvas.width = w;
|
|
|
|
|
canvas.height = h;
|
|
|
|
|
canvas.style.width = `${w}px`;
|
|
|
|
|
canvas.style.height = `${h}px`;
|
|
|
|
|
}
|
2022-11-19 18:15:42 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获取事件中的keycode对应的键
|
|
|
|
|
* @param key 要获取的键
|
|
|
|
|
*/
|
|
|
|
|
export function keycode(key: number) {
|
|
|
|
|
return EVENT_KEY_CODE_MAP[key];
|
|
|
|
|
}
|
2022-11-21 20:00:34 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 解析css字符串为CSSStyleDeclaration对象
|
|
|
|
|
* @param css 要解析的css字符串
|
|
|
|
|
*/
|
|
|
|
|
export function parseCss(css: string): Partial<Record<CanParseCss, string>> {
|
2024-04-23 21:43:26 +08:00
|
|
|
|
if (css.length === 0) return {};
|
|
|
|
|
|
|
|
|
|
let pointer = -1;
|
|
|
|
|
let inProp = true;
|
|
|
|
|
let prop = '';
|
|
|
|
|
let value = '';
|
|
|
|
|
let upper = false;
|
2022-11-21 20:00:34 +08:00
|
|
|
|
const res: Partial<Record<CanParseCss, string>> = {};
|
|
|
|
|
|
2024-04-23 21:43:26 +08:00
|
|
|
|
while (++pointer < css.length) {
|
|
|
|
|
const char = css[pointer];
|
|
|
|
|
|
|
|
|
|
if ((char === ' ' || char === '\n' || char === '\r') && inProp) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (char === '-' && inProp) {
|
|
|
|
|
if (prop.length !== 0) {
|
|
|
|
|
upper = true;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (char === ':') {
|
|
|
|
|
if (!inProp) {
|
|
|
|
|
logger.error(
|
|
|
|
|
3,
|
|
|
|
|
`Syntax error in parsing CSS: Unexpected ':'. Col: ${pointer}. CSS string: '${css}'`
|
|
|
|
|
);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
inProp = false;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (char === ';') {
|
|
|
|
|
if (prop.length === 0) continue;
|
|
|
|
|
if (inProp) {
|
|
|
|
|
logger.error(
|
|
|
|
|
4,
|
|
|
|
|
`Syntax error in parsing CSS: Unexpected ';'. Col: ${pointer}. CSS string: '${css}'`
|
|
|
|
|
);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
res[prop as CanParseCss] = value.trim();
|
|
|
|
|
inProp = true;
|
|
|
|
|
prop = '';
|
|
|
|
|
value = '';
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (upper) {
|
|
|
|
|
if (!inProp) {
|
|
|
|
|
logger.error(
|
|
|
|
|
5,
|
|
|
|
|
`Syntax error in parsing CSS: Missing property name after '-'. Col: ${pointer}. CSS string: '${css}'`
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
prop += char.toUpperCase();
|
|
|
|
|
upper = false;
|
|
|
|
|
} else {
|
|
|
|
|
if (inProp) prop += char;
|
|
|
|
|
else value += char;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (inProp && prop.length > 0) {
|
|
|
|
|
logger.error(
|
|
|
|
|
6,
|
|
|
|
|
`Syntax error in parsing CSS: Unexpected end of css, expecting ':'. Col: ${pointer}. CSS string: '${css}'`
|
|
|
|
|
);
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
if (!inProp && value.trim().length === 0) {
|
|
|
|
|
logger.error(
|
|
|
|
|
7,
|
|
|
|
|
`Syntax error in parsing CSS: Unexpected end of css, expecting property value. Col: ${pointer}. CSS string: '${css}'`
|
|
|
|
|
);
|
|
|
|
|
return res;
|
2022-11-21 20:00:34 +08:00
|
|
|
|
}
|
2024-04-23 21:43:26 +08:00
|
|
|
|
if (prop.length > 0) res[prop as CanParseCss] = value.trim();
|
|
|
|
|
|
2022-11-21 20:00:34 +08:00
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-23 21:43:26 +08:00
|
|
|
|
export function stringifyCSS(css: Partial<Record<CanParseCss, string>>) {
|
|
|
|
|
let str = '';
|
|
|
|
|
|
|
|
|
|
for (const [key, value] of Object.entries(css)) {
|
|
|
|
|
let pointer = -1;
|
|
|
|
|
let prop = '';
|
|
|
|
|
while (++pointer < key.length) {
|
|
|
|
|
const char = key[pointer];
|
|
|
|
|
if (char.toLowerCase() === char) {
|
|
|
|
|
prop += char;
|
|
|
|
|
} else {
|
|
|
|
|
prop += `-${char.toLowerCase()}`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
str += `${prop}:${value};`;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return str;
|
|
|
|
|
}
|
|
|
|
|
|
2022-11-21 20:00:34 +08:00
|
|
|
|
/**
|
|
|
|
|
* 使用打字机效果显示一段文字
|
|
|
|
|
* @param str 要打出的字符串
|
2022-11-30 16:42:44 +08:00
|
|
|
|
* @param time 打出总用时,默认1秒,当第四个参数是true时,该项为每个字的平均时间
|
2022-11-21 20:00:34 +08:00
|
|
|
|
* @param timing 打出时的速率曲线,默认为线性变化
|
2022-11-30 16:42:44 +08:00
|
|
|
|
* @param avr 是否将第二个参数视为每个字的平均时间
|
2022-11-21 20:00:34 +08:00
|
|
|
|
* @returns 文字的响应式变量
|
|
|
|
|
*/
|
|
|
|
|
export function type(
|
|
|
|
|
str: string,
|
|
|
|
|
time: number = 1000,
|
2022-11-30 16:42:44 +08:00
|
|
|
|
timing: TimingFn = n => n,
|
|
|
|
|
avr: boolean = false
|
2022-11-21 20:00:34 +08:00
|
|
|
|
): Ref<string> {
|
|
|
|
|
const toShow = eval('`' + str + '`') as string;
|
2022-11-30 16:42:44 +08:00
|
|
|
|
if (typeof toShow !== 'string') {
|
|
|
|
|
throw new TypeError('Error str type in typing!');
|
|
|
|
|
}
|
2022-12-29 00:26:12 +08:00
|
|
|
|
if (toShow.startsWith('!!html')) return ref(toShow);
|
2022-11-30 16:42:44 +08:00
|
|
|
|
if (avr) time *= toShow.length;
|
2022-11-21 20:00:34 +08:00
|
|
|
|
const ani = new Animation();
|
|
|
|
|
const content = ref('');
|
|
|
|
|
const all = toShow.length;
|
|
|
|
|
|
|
|
|
|
const fn = (time: number) => {
|
|
|
|
|
if (!has(time)) return;
|
|
|
|
|
const now = ani.x;
|
|
|
|
|
content.value = toShow.slice(0, Math.floor(now));
|
|
|
|
|
if (Math.floor(now) === all) {
|
|
|
|
|
ani.ticker.destroy();
|
2022-11-30 16:42:44 +08:00
|
|
|
|
content.value = toShow;
|
2022-11-21 20:00:34 +08:00
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ani.ticker.add(fn);
|
|
|
|
|
|
|
|
|
|
ani.mode(timing).time(time).move(all, 0);
|
|
|
|
|
|
2022-12-31 19:49:43 +08:00
|
|
|
|
setTimeout(() => ani.ticker.destroy(), time + 100);
|
|
|
|
|
|
2022-11-21 20:00:34 +08:00
|
|
|
|
return content;
|
|
|
|
|
}
|
2022-12-29 12:02:48 +08:00
|
|
|
|
|
|
|
|
|
export function tip(
|
|
|
|
|
type: Exclude<keyof MessageApi, 'open' | 'config' | 'destroy'>,
|
|
|
|
|
text: string
|
|
|
|
|
) {
|
|
|
|
|
message[type]({
|
|
|
|
|
content: text,
|
|
|
|
|
class: 'antdv-message'
|
|
|
|
|
});
|
|
|
|
|
}
|
2022-12-30 23:28:27 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 设置文字分段换行等
|
|
|
|
|
* @param str 文字
|
|
|
|
|
*/
|
|
|
|
|
export function splitText(str: string[]) {
|
|
|
|
|
return str
|
|
|
|
|
.map((v, i, a) => {
|
|
|
|
|
if (/^\d+\./.test(v)) return `${' '.repeat(12)}${v}`;
|
|
|
|
|
else if (
|
|
|
|
|
(has(a[i - 1]) && v !== '<br>' && a[i - 1] === '<br>') ||
|
|
|
|
|
i === 0
|
|
|
|
|
) {
|
|
|
|
|
return `${' '.repeat(8)}${v}`;
|
|
|
|
|
} else return v;
|
|
|
|
|
})
|
|
|
|
|
.join('');
|
|
|
|
|
}
|
2023-01-15 20:09:02 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 在下一帧执行某个函数
|
|
|
|
|
* @param cb 执行的函数
|
|
|
|
|
*/
|
|
|
|
|
export function nextFrame(cb: (time: number) => void) {
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
requestAnimationFrame(cb);
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-01-23 14:38:50 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 下载一个画布对应的图片
|
|
|
|
|
* @param canvas 画布
|
|
|
|
|
* @param name 图片名称
|
|
|
|
|
*/
|
|
|
|
|
export function downloadCanvasImage(
|
|
|
|
|
canvas: HTMLCanvasElement,
|
|
|
|
|
name: string
|
|
|
|
|
): void {
|
|
|
|
|
const data = canvas.toDataURL('image/png');
|
|
|
|
|
download(data, name);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 下载一个文件
|
|
|
|
|
* @param content 下载的内容
|
|
|
|
|
* @param name 文件名称
|
|
|
|
|
*/
|
|
|
|
|
export function download(content: string, name: string) {
|
|
|
|
|
const a = document.createElement('a');
|
|
|
|
|
a.download = `${name}.png`;
|
|
|
|
|
a.href = content;
|
|
|
|
|
document.body.appendChild(a);
|
|
|
|
|
a.click();
|
|
|
|
|
document.body.removeChild(a);
|
|
|
|
|
}
|
2023-02-21 23:22:03 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 间隔一段时间调用一个函数
|
|
|
|
|
* @param funcs 函数列表
|
|
|
|
|
* @param interval 调用间隔
|
|
|
|
|
*/
|
2023-02-21 23:27:40 +08:00
|
|
|
|
export async function doByInterval(
|
|
|
|
|
funcs: (() => void)[],
|
|
|
|
|
interval: number,
|
|
|
|
|
awaitFirst: boolean = false
|
|
|
|
|
) {
|
2023-06-21 17:10:06 +08:00
|
|
|
|
if (awaitFirst) {
|
|
|
|
|
await sleep(interval);
|
|
|
|
|
}
|
2023-02-21 23:22:03 +08:00
|
|
|
|
for await (const fn of funcs) {
|
|
|
|
|
fn();
|
2023-06-21 17:10:06 +08:00
|
|
|
|
await sleep(interval);
|
2023-02-21 23:22:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
2023-02-23 23:10:57 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 更改一个本地存储
|
2024-02-01 19:31:49 +08:00
|
|
|
|
* @deprecated
|
2023-02-23 23:10:57 +08:00
|
|
|
|
* @param name 要更改的信息
|
|
|
|
|
* @param fn 更改时执行的函数
|
|
|
|
|
* @param defaultValue 如果不存在时获取的默认值
|
|
|
|
|
*/
|
|
|
|
|
export function changeLocalStorage<T>(
|
|
|
|
|
name: string,
|
|
|
|
|
fn: (data: T) => T,
|
|
|
|
|
defaultValue?: T
|
|
|
|
|
) {
|
|
|
|
|
const now = core.getLocalStorage(name, defaultValue);
|
|
|
|
|
const to = fn(now);
|
|
|
|
|
core.setLocalStorage(name, to);
|
|
|
|
|
}
|
2023-04-28 23:58:07 +08:00
|
|
|
|
|
|
|
|
|
export async function swapChapter(chapter: number, hard: number) {
|
|
|
|
|
const h = hard === 2 ? 'hard' : 'easy';
|
|
|
|
|
const save = await axios.get(
|
|
|
|
|
`${import.meta.env.BASE_URL}swap/${chapter}.${h}.h5save`,
|
|
|
|
|
{
|
|
|
|
|
responseType: 'text',
|
|
|
|
|
responseEncoding: 'utf-8'
|
|
|
|
|
}
|
|
|
|
|
);
|
|
|
|
|
const data = JSON.parse(decompressFromBase64(save.data));
|
|
|
|
|
|
|
|
|
|
core.loadData(data.data, () => {
|
|
|
|
|
core.removeFlag('__fromLoad__');
|
|
|
|
|
core.drawTip('读档成功');
|
|
|
|
|
});
|
|
|
|
|
}
|
2023-06-17 18:02:48 +08:00
|
|
|
|
|
|
|
|
|
export function ensureArray<T>(arr: T): T extends any[] ? T : T[] {
|
|
|
|
|
// @ts-ignore
|
|
|
|
|
return arr instanceof Array ? arr : [arr];
|
|
|
|
|
}
|
2023-06-20 11:56:25 +08:00
|
|
|
|
|
|
|
|
|
export function pColor(color: string) {
|
2023-06-21 15:43:22 +08:00
|
|
|
|
const arr = parseColor(color);
|
|
|
|
|
arr[3] ??= 1;
|
2023-07-08 11:44:00 +08:00
|
|
|
|
return `rgba(${arr.join(',')})` as Color;
|
2023-06-20 11:56:25 +08:00
|
|
|
|
}
|
2023-08-08 13:29:22 +08:00
|
|
|
|
|
2024-01-18 15:25:33 +08:00
|
|
|
|
/**
|
|
|
|
|
* 删除数组内的某个项,返回删除后的数组
|
|
|
|
|
* @param arr 要操作的数组
|
|
|
|
|
* @param ele 要删除的项
|
|
|
|
|
*/
|
2023-08-08 13:29:22 +08:00
|
|
|
|
export function deleteWith<T>(arr: T[], ele: T): T[] {
|
|
|
|
|
const index = arr.indexOf(ele);
|
|
|
|
|
if (index === -1) return arr;
|
|
|
|
|
arr.splice(index, 1);
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
2023-08-08 16:44:43 +08:00
|
|
|
|
|
2023-11-18 11:33:24 +08:00
|
|
|
|
export function spliceBy<T>(arr: T[], from: T): T[] {
|
|
|
|
|
const index = arr.indexOf(from);
|
|
|
|
|
if (index === -1) return arr;
|
|
|
|
|
arr.splice(index);
|
|
|
|
|
return arr;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-08 16:44:43 +08:00
|
|
|
|
export async function triggerFullscreen(full: boolean) {
|
2024-02-01 19:31:49 +08:00
|
|
|
|
if (!Mota.Plugin.inited) return;
|
|
|
|
|
const { maxGameScale } = Mota.Plugin.require('utils_g');
|
2023-08-08 16:44:43 +08:00
|
|
|
|
if (!!document.fullscreenElement && !full) {
|
|
|
|
|
await document.exitFullscreen();
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
maxGameScale(1);
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
if (full && !document.fullscreenElement) {
|
|
|
|
|
await document.body.requestFullscreen();
|
|
|
|
|
requestAnimationFrame(() => {
|
|
|
|
|
maxGameScale();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
2023-08-09 12:27:57 +08:00
|
|
|
|
|
2023-08-18 11:45:18 +08:00
|
|
|
|
/**
|
|
|
|
|
* 根据布尔值数组转换成一个二进制数
|
|
|
|
|
* @param arr 要转换的布尔值数组
|
|
|
|
|
*/
|
2023-08-09 12:27:57 +08:00
|
|
|
|
export function generateBinary(arr: boolean[]) {
|
|
|
|
|
let num = 0;
|
|
|
|
|
arr.forEach((v, i) => {
|
|
|
|
|
if (v) {
|
|
|
|
|
num += 1 << i;
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
return num;
|
|
|
|
|
}
|
2023-12-01 21:47:43 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 获得某个状态的中文名
|
|
|
|
|
* @param name 要获取的属性名
|
|
|
|
|
*/
|
|
|
|
|
export function getStatusLabel(name: string) {
|
|
|
|
|
return (
|
|
|
|
|
{
|
|
|
|
|
name: '名称',
|
|
|
|
|
lv: '等级',
|
|
|
|
|
hpmax: '生命回复',
|
|
|
|
|
hp: '生命',
|
|
|
|
|
manamax: '魔力上限',
|
|
|
|
|
mana: '额外攻击',
|
|
|
|
|
atk: '攻击',
|
|
|
|
|
def: '防御',
|
|
|
|
|
mdef: '智慧',
|
|
|
|
|
money: '金币',
|
|
|
|
|
exp: '经验',
|
|
|
|
|
point: '加点',
|
|
|
|
|
steps: '步数',
|
|
|
|
|
up: '升级',
|
|
|
|
|
none: '无'
|
|
|
|
|
}[name] || name
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-12-17 18:11:58 +08:00
|
|
|
|
|
|
|
|
|
export function flipBinary(num: number, col: number) {
|
|
|
|
|
const n = 1 << col;
|
2023-12-18 17:10:28 +08:00
|
|
|
|
if (num & n) return num & ~n;
|
2023-12-17 18:11:58 +08:00
|
|
|
|
else return num | n;
|
|
|
|
|
}
|
2024-01-18 15:25:33 +08:00
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 唤起虚拟键盘,并获取到一次按键操作
|
|
|
|
|
* @param emitAssist 是否可以获取辅助按键,为true时,如果按下辅助按键,那么会立刻返回该按键,
|
|
|
|
|
* 否则会视为开关辅助按键
|
|
|
|
|
* @param assist 初始化的辅助按键
|
|
|
|
|
*/
|
|
|
|
|
export function getVitualKeyOnce(
|
|
|
|
|
emitAssist: boolean = false,
|
2024-01-19 22:09:48 +08:00
|
|
|
|
assist: number = 0,
|
|
|
|
|
emittable: KeyCode[] = []
|
2024-01-18 15:25:33 +08:00
|
|
|
|
): Promise<KeyboardEmits> {
|
|
|
|
|
return new Promise(res => {
|
2024-01-19 16:07:59 +08:00
|
|
|
|
const key = Keyboard.get('full')!;
|
2024-01-18 17:07:03 +08:00
|
|
|
|
key.withAssist(assist);
|
|
|
|
|
const id = mainUi.open('virtualKey', { keyboard: key });
|
|
|
|
|
key.on('emit', (item, assist, index, ev) => {
|
|
|
|
|
ev.preventDefault();
|
|
|
|
|
if (emitAssist) {
|
2024-01-19 22:09:48 +08:00
|
|
|
|
if (emittable.length === 0 || emittable.includes(item.key)) {
|
|
|
|
|
res({ key: item.key, assist: 0 });
|
|
|
|
|
key.disposeScope();
|
|
|
|
|
mainUi.close(id);
|
|
|
|
|
}
|
2024-01-18 17:07:03 +08:00
|
|
|
|
} else {
|
2024-01-19 22:09:48 +08:00
|
|
|
|
if (
|
|
|
|
|
!isAssist(item.key) &&
|
|
|
|
|
(emittable.length === 0 || emittable.includes(item.key))
|
|
|
|
|
) {
|
2024-01-18 17:07:03 +08:00
|
|
|
|
res({ key: item.key, assist });
|
|
|
|
|
key.disposeScope();
|
2024-01-19 16:07:59 +08:00
|
|
|
|
mainUi.close(id);
|
2024-01-18 17:07:03 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2024-01-18 15:25:33 +08:00
|
|
|
|
});
|
|
|
|
|
}
|
2024-04-21 13:37:27 +08:00
|
|
|
|
|
|
|
|
|
export function formatSize(size: number) {
|
|
|
|
|
return size < 1 << 10
|
|
|
|
|
? `${size.toFixed(2)}B`
|
|
|
|
|
: size < 1 << 20
|
|
|
|
|
? `${(size / (1 << 10)).toFixed(2)}KB`
|
|
|
|
|
: size < 1 << 30
|
|
|
|
|
? `${(size / (1 << 20)).toFixed(2)}MB`
|
|
|
|
|
: `${(size / (1 << 30)).toFixed(2)}GB`;
|
|
|
|
|
}
|
2024-04-21 15:45:06 +08:00
|
|
|
|
|
|
|
|
|
let num = 0;
|
|
|
|
|
export function requireUniqueSymbol() {
|
|
|
|
|
return num++;
|
|
|
|
|
}
|
2024-04-23 21:43:26 +08:00
|
|
|
|
|
|
|
|
|
export function openDanmakuPoster() {
|
|
|
|
|
if (!fixedUi.hasName('danmakuEditor')) {
|
|
|
|
|
fixedUi.open('danmakuEditor');
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function getIconHeight(icon: AllIds | 'hero') {
|
|
|
|
|
if (icon === 'hero') {
|
|
|
|
|
if (core.isPlaying()) {
|
|
|
|
|
return (
|
|
|
|
|
core.material.images.images[core.status.hero.image].height / 4
|
|
|
|
|
);
|
|
|
|
|
} else {
|
|
|
|
|
return 48;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return core.getBlockInfo(icon)?.height ?? 32;
|
|
|
|
|
}
|