import { DefaultProps, ElementLocator, Font } from '@motajs/render'; import { computed, defineComponent, ref } from 'vue'; import { SetupComponentOptions } from '../components'; import { DanmakuIcon, DoubleArrow, NumpadIcon, PauseIcon, PlayIcon, ReplayIcon, RetweetIcon, RollbackIcon, StepForward, ViewMapIcon } from '../components/icons'; import { generateBinary, getVitualKeyOnce, openDanmakuPoster } from '@motajs/legacy-ui'; import { gameKey } from '@motajs/system-action'; import { generateKeyboardEvent } from '@motajs/system-action'; import { transitioned } from '../use'; import { linear } from 'mutate-animate'; import { KeyCode } from '@motajs/client-base'; import { Progress } from '../components/misc'; interface ToolbarProps extends DefaultProps { loc?: ElementLocator; } type ToolbarEmits = { numpad: () => void; }; const toolbarProps = { props: ['loc'], emits: ['numpad'] } satisfies SetupComponentOptions< ToolbarProps, ToolbarEmits, keyof ToolbarEmits >; const im = (col: number, row: number): ElementLocator => { return [5 + 34 * col, 5 + 36 * row, 32, 32]; }; const ic = (col: number, row: number): ElementLocator => { return [7 + 34 * col, 7 + 36 * row, 28, 28]; }; const ic2 = (col: number, row: number): ElementLocator => { return [9 + 34 * col, 9 + 36 * row, 24, 24]; }; const middle = (col: number, row: number): ElementLocator => { return [21 + 34 * col, 21 + 36 * row, void 0, void 0, 0.5, 0.5]; }; const middle2 = ( col: number, row: number, width: number, height: number ): ElementLocator => { return [21 + 34 * col, 21 + 36 * row, width, height, 0.5, 0.5]; }; export const PlayingToolbar = defineComponent< ToolbarProps, ToolbarEmits, keyof ToolbarEmits >((props, { emit }) => { const bookIcon = core.statusBar.icons.book; const flyIcon = core.statusBar.icons.fly; const toolIcon = core.statusBar.icons.toolbox; const equipIcon = core.statusBar.icons.equipbox; const keyIcon = core.statusBar.icons.keyboard; const shopIcon = core.statusBar.icons.shop; const saveIcon = core.statusBar.icons.save; const loadIcon = core.statusBar.icons.load; const setIcon = core.statusBar.icons.settings; const iconFont = new Font('Verdana', 12); const book = () => core.openBook(true); const tool = () => core.openEquipbox(true); const fly = () => core.useFly(true); const save = () => core.save(true); const load = () => core.load(true); const equip = () => core.openEquipbox(true); const shop = () => core.openQuickShop(true); const key = () => { getVitualKeyOnce().then(value => { gameKey.emitKey( value.key, value.assist, 'up', generateKeyboardEvent(value.key, value.assist) ); }); }; const undo = () => core.doSL('autoSave', 'load'); const redo = () => core.doSL('autoSave', 'reload'); const numpad = () => emit('numpad'); const view = () => { if (core.isPlaying() && !core.isMoving() && !core.status.lockControl) { core.ui._drawViewMaps(); } }; const danmaku = () => requestAnimationFrame(openDanmakuPoster); const replay = () => core.ui._drawReplay(); const settings = () => core.openSettings(true); return () => ( ); }, toolbarProps); export interface ReplayingStatus { /** 是否正在播放 */ playing: boolean; /** 录像播放速度 */ speed: number; /** 已播放的长度 */ played: number; /** 总长度 */ total: number; } export interface ReplayingProps extends ToolbarProps { /** 录像播放状态 */ status: ReplayingStatus; } const replayingProps = { props: ['status', 'loc'] } satisfies SetupComponentOptions; export const ReplayingToolbar = defineComponent(props => { const status = props.status; const bookIcon = core.statusBar.icons.book; const saveIcon = core.statusBar.icons.save; const font1 = new Font('normal', 16); const font2 = new Font('Verdana', 12); const speedText = computed(() => `${status.speed}速`); const progress = computed(() => status.played / status.total); const progressText1 = computed(() => `${status.played}/${status.total}`); const progressText2 = computed( () => `${(progress.value * 100).toFixed(2)}%` ); const play = () => core.resumeReplay(); const pause = () => core.pauseReplay(); const stop = () => core.stopReplay(true); const speedDown = () => core.speedDownReplay(); const speedUp = () => core.speedUpReplay(); const book = () => core.openBook(true); const save = () => core.save(true); const view = () => { if (core.isPlaying() && !core.isMoving() && !core.status.lockControl) { core.ui._drawViewMaps(); } }; const rewind = () => core.rewindReplay(); const step = () => core.stepReplay(); return () => { return ( {status.playing ? ( ) : ( )} ); }; }, replayingProps); export const NumpadToolbar = defineComponent< ToolbarProps, ToolbarEmits, keyof ToolbarEmits >((props, { emit }) => { const numpad = () => emit('numpad'); const nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]; const ctrlEnabled = ref(false); const shiftEnabled = ref(false); const altEnabled = ref(false); const ctrlAlpha = transitioned(0, 100, linear())!; const shiftAlpha = transitioned(0, 100, linear())!; const altAlpha = transitioned(0, 100, linear())!; const ctrlColor = computed( () => `rgba(221,221,221,${ctrlAlpha.ref.value})` ); const ctrlTextColor = computed(() => { const rgb = Math.floor(255 - ctrlAlpha.ref.value * 255); return `rgba(${rgb},${rgb},${rgb},1)`; }); const shiftColor = computed( () => `rgba(221,221,221,${shiftAlpha.ref.value})` ); const shiftTextColor = computed(() => { const rgb = Math.floor(255 - shiftAlpha.ref.value * 255); return `rgba(${rgb},${rgb},${rgb},1)`; }); const altColor = computed(() => `rgba(221,221,221,${altAlpha.ref.value})`); const altTextColor = computed(() => { const rgb = Math.floor(255 - altAlpha.ref.value * 255); return `rgba(${rgb},${rgb},${rgb},1)`; }); const clickCtrl = () => { ctrlEnabled.value = !ctrlEnabled.value; ctrlAlpha.set(ctrlEnabled.value ? 1 : 0); }; const clickShift = () => { shiftEnabled.value = !shiftEnabled.value; shiftAlpha.set(shiftEnabled.value ? 1 : 0); }; const clickAlt = () => { altEnabled.value = !altEnabled.value; altAlpha.set(altEnabled.value ? 1 : 0); }; const clickNum = (num: number) => { const bin = generateBinary([ ctrlEnabled.value, shiftEnabled.value, altEnabled.value ]); const code = (KeyCode.Digit0 + num) as KeyCode; gameKey.emitKey(code, bin, 'up', generateKeyboardEvent(code, bin)); }; return () => ( {nums .map((v, i) => { const col = i % 5; const row = Math.floor(i / 5); return [ clickNum(v)} />, ]; }) .flat()} ); }, toolbarProps);