Skip to content

Commit

Permalink
load zip file
Browse files Browse the repository at this point in the history
  • Loading branch information
LemonNekoGH committed Jan 2, 2025
1 parent 1cf3abd commit d53007e
Show file tree
Hide file tree
Showing 13 changed files with 203 additions and 127 deletions.
6 changes: 2 additions & 4 deletions packages/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,8 @@
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
"typecheck": "npm run typecheck:node && npm run typecheck:web",
"start": "electron-vite preview",
"dev": "electron .",
"dev:desktop": "npm run build && electron .",
"build": "npm run typecheck && electron-vite build",
"build": "npm run typecheck && electron-vite build && rm -rf ./out/renderer && cp -r ../stage/desktop/dist/ ./out/renderer",
"postinstall": "electron-builder install-app-deps",
"build:unpack": "npm run build && electron-builder --dir",
"build:win": "npm run build && electron-builder --win",
Expand All @@ -23,8 +22,7 @@
},
"dependencies": {
"@electron-toolkit/preload": "^3.0.0",
"@electron-toolkit/utils": "^3.0.0",
"@proj-airi/stage": "workspace:*"
"@electron-toolkit/utils": "^3.0.0"
},
"devDependencies": {
"@electron-toolkit/eslint-config": "^1.0.2",
Expand Down
2 changes: 1 addition & 1 deletion packages/desktop/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ function createWindow(): void {
})
}
else {
mainWindow.loadFile(join(__dirname, '../../../stage/dist/index.html'))
mainWindow.loadFile(join(__dirname, '../../out/renderer/index.html'))
}

ipcMain.on('move-window', (_, dx, dy) => {
Expand Down
45 changes: 45 additions & 0 deletions packages/stage/desktop/App.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<script setup lang="ts">
import { ref } from 'vue'
import DesktopInteractiveArea from '../src/components/Layouts/DesktopInteractiveArea.vue'
import Stage from '../src/components/Widgets/Stage.vue'
const dragDelay = ref(0)
const isDragging = ref(false)
function handleMouseDown() {
dragDelay.value = window.setTimeout(() => {
isDragging.value = true
}, 500)
}
function handleMouseUp() {
clearTimeout(dragDelay.value)
isDragging.value = false
}
function handleMouseMove(event: MouseEvent) {
if (isDragging.value) {
window.electron.ipcRenderer.send('move-window', event.movementX, event.movementY)
}
}
</script>

<template>
<div relative max-h="[100vh]" max-w="[100vw]" p="2" flex="~ col" z-2 h-full overflow-hidden @mousedown="handleMouseDown" @mouseup="handleMouseUp" @mousemove="handleMouseMove">
<div relative h-full w-full items-end gap-2 class="view">
<Stage h-full w-full flex-1 mb="<md:18" />
<DesktopInteractiveArea class="interaction-area block" pointer-events-none absolute bottom-0 w-full opacity-0 transition="opacity duration-250" />
</div>
</div>
</template>

<style lang="less" scoped>
.view {
&:hover {
.interaction-area {
opacity: 1;
pointer-events: auto;
}
}
}
</style>
18 changes: 16 additions & 2 deletions packages/stage/desktop/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,21 @@
import { app } from '../src/app'
import { autoAnimatePlugin } from '@formkit/auto-animate/vue'
import Tres from '@tresjs/core'
import { MotionPlugin } from '@vueuse/motion'
import { createPinia } from 'pinia'
import { createApp } from 'vue'
import { i18n } from '../src/modules/i18n'
import App from './App.vue'

import '@unocss/reset/tailwind.css'
import 'uno.css'
import './main.css'

app.mount('#app')
const pinia = createPinia()

createApp(App)
.use(MotionPlugin)
.use(autoAnimatePlugin)
.use(pinia)
.use(i18n)
.use(Tres)
.mount('#app')
1 change: 1 addition & 0 deletions packages/stage/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"@xsai/shared-chat": "^0.0.22",
"@xsai/stream-text": "^0.0.22",
"defu": "^6.1.4",
"jszip": "^3.10.1",
"nprogress": "^0.2.0",
"ofetch": "^1.4.1",
"onnxruntime-web": "^1.20.1",
Expand Down
53 changes: 0 additions & 53 deletions packages/stage/src/app.ts

This file was deleted.

7 changes: 5 additions & 2 deletions packages/stage/src/components/Widgets/Stage.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ import { useQueue } from '../../composables/queue'
import { useDelayMessageQueue, useEmotionsMessageQueue, useMessageContentQueue } from '../../composables/queues'
import { llmInferenceEndToken } from '../../constants'
import { Voice } from '../../constants/elevenlabs'
import { EMOTION_EmotionMotionName_value, EMOTION_VRMExpressionName_value, EmotionThinkMotionName } from '../../constants/emotions'
import { EMOTION_EmotionMotionName_value, EMOTION_VRMExpressionName_value, EmotionThinkMotionName } from '../../constants/emotions'
import { useAudioContext, useSpeakingStore } from '../../stores/audio'
import { useChatStore } from '../../stores/chat'
import { useLLM } from '../../stores/llm'
import { useSettings } from '../../stores/settings'
import Live2DScene from '../Scenes/Live2D.vue'
import VRMScene from '../Scenes/VRM.vue'
import '../../utils/live2d-zip-loader'
const live2DViewerRef = ref<{ setMotion: (motionName: string) => Promise<void> }>()
const vrmViewerRef = ref<{ setExpression: (expression: string) => void }>()
Expand Down Expand Up @@ -183,7 +186,7 @@ onUnmounted(() => {
v-if="stageView === '2d'"
ref="live2DViewerRef"
:mouth-open-size="mouthOpenSize"
model="/assets/live2d/models/hiyori_pro_zh/runtime/hiyori_pro_t11.model3.json"
model="./assets/live2d/models/hiyori_pro_zh.zip"
min-w="50% <lg:full" min-h="100 sm:100" h-full w-full flex-1
/>
<VRMScene
Expand Down
13 changes: 7 additions & 6 deletions packages/stage/src/constants/emotions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,14 @@ export enum Emotion {

export const EMOTION_VALUES = Object.values(Emotion)

export const EmotionHappyMotionName = 'EmotionHappy'
// FIXME: need a editor to remap the motion
export const EmotionHappyMotionName = 'Tap'
export const EmotionSadMotionName = 'EmotionSad'
export const EmotionAngryMotionName = 'EmotionAngry'
export const EmotionAwkwardMotionName = 'EmotionAwkward'
export const EmotionThinkMotionName = 'EmotionThink'
export const EmotionSurpriseMotionName = 'EmotionSurprise'
export const EmotionQuestionMotionName = 'EmotionQuestion'
export const EmotionAngryMotionName = 'Tap@Body'
export const EmotionAwkwardMotionName = 'FlickDown'
export const EmotionThinkMotionName = 'Flick'
export const EmotionSurpriseMotionName = 'Flick'
export const EmotionQuestionMotionName = 'Flick@Body'

export const EMOTION_EmotionMotionName_value = {
[Emotion.Happy]: EmotionHappyMotionName,
Expand Down
55 changes: 50 additions & 5 deletions packages/stage/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,52 @@
import { app } from './app'
import '@unocss/reset/tailwind.css'
import './styles/main.css'
import type { Router } from 'vue-router'
import { autoAnimatePlugin } from '@formkit/auto-animate/vue'
import Tres from '@tresjs/core'
import { MotionPlugin } from '@vueuse/motion'
import NProgress from 'nprogress'
import { createPinia } from 'pinia'
import { setupLayouts } from 'virtual:generated-layouts'
import { createApp } from 'vue'
import { createRouter, createWebHashHistory, createWebHistory } from 'vue-router'

import 'uno.css'
import { routes } from 'vue-router/auto-routes'

app.mount('#app')
import App from './App.vue'
import { i18n } from './modules/i18n'

const pinia = createPinia()
const routeRecords = setupLayouts(routes)

let router: Router
if (import.meta.env.VITE_APP_TARGET_HUGGINGFACE_SPACE)
router = createRouter({ routes: routeRecords, history: createWebHashHistory() })
else
router = createRouter({ routes: routeRecords, history: createWebHistory() })

router.beforeEach((to, from) => {
if (to.path !== from.path)
NProgress.start()
})

router.afterEach(() => {
NProgress.done()
})

router.isReady()
.then(async () => {
if (import.meta.env.VITE_APP_TARGET_HUGGINGFACE_SPACE) {
return
}

const { registerSW } = await import('virtual:pwa-register')
registerSW({ immediate: true })
})
.catch(() => {})

createApp(App)
.use(MotionPlugin)
.use(autoAnimatePlugin)
.use(router)
.use(pinia)
.use(i18n)
.use(Tres)
.mount('#app')
46 changes: 1 addition & 45 deletions packages/stage/src/pages/index.vue
Original file line number Diff line number Diff line change
@@ -1,41 +1,18 @@
<script setup lang="ts">
import { useDark } from '@vueuse/core'
import { ref } from 'vue'
import Cross from '../components/Backgrounds/Cross.vue'
import AnimatedBackground from '../components/Layouts/AnimatedBackground.vue'
import DesktopInteractiveArea from '../components/Layouts/DesktopInteractiveArea.vue'
import Header from '../components/Layouts/Header.vue'
import InteractiveArea from '../components/Layouts/InteractiveArea.vue'
import MobileHeader from '../components/Layouts/MobileHeader.vue'
import Stage from '../components/Widgets/Stage.vue'
import { isPlatformDesktop } from '../utils/platform'
const dark = useDark()
const dragDelay = ref(0)
const isDragging = ref(false)
function handleMouseDown() {
dragDelay.value = window.setTimeout(() => {
isDragging.value = true
}, 1000)
}
function handleMouseUp() {
clearTimeout(dragDelay.value)
isDragging.value = false
}
function handleMouseMove(event: MouseEvent) {
if (isDragging.value) {
window.electron.ipcRenderer.send('move-window', event.movementX, event.movementY)
}
}
</script>

<template>
<Cross v-if="!isPlatformDesktop()" h-full w-full>
<Cross h-full w-full>
<AnimatedBackground h-full w-full :fill-color="dark ? '#563544' : '#f8e8f2'">
<div relative max-h="[100vh]" max-w="[100vw]" p="2" flex="~ col" z-2 h-full overflow-hidden>
<Header class="flex <md:hidden" />
Expand All @@ -48,30 +25,9 @@ function handleMouseMove(event: MouseEvent) {
</div>
</AnimatedBackground>
</Cross>
<div v-else relative max-h="[100vh]" max-w="[100vw]" p="2" flex="~ col" z-2 h-full overflow-hidden @mousedown="handleMouseDown" @mouseup="handleMouseUp" @mousemove="handleMouseMove">
<div relative h-full w-full items-end gap-2 class="view">
<Stage h-full w-full flex-1 mb="<md:18" />
<DesktopInteractiveArea class="interaction-area block" pointer-events-none absolute bottom-0 w-full opacity-0 transition="opacity duration-250" />
</div>
</div>
</template>

<route lang="yaml">
meta:
layout: default
</route>

<style lang="less">
.view {
&:hover {
.interaction-area {
opacity: 1;
pointer-events: auto;
}
}
}
.move-window {
app-region: drag;
}
</style>
33 changes: 33 additions & 0 deletions packages/stage/src/utils/live2d-zip-loader.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import JSZip from 'jszip'
import { ZipLoader } from 'pixi-live2d-display/cubism4'

ZipLoader.zipReader = (data: Blob, _url: string) => JSZip.loadAsync(data)

ZipLoader.readText = (jsZip: JSZip, path: string) => {
const file = jsZip.file(path)

if (!file) {
throw new Error(`Cannot find file: ${path}`)
}

return file.async('text')
}

ZipLoader.getFilePaths = (jsZip: JSZip) => {
const paths: string[] = []

jsZip.forEach(relativePath => paths.push(relativePath))

return Promise.resolve(paths)
}

ZipLoader.getFiles = (jsZip: JSZip, paths: string[]) =>
Promise.all(paths.map(
async (path) => {
const fileName = path.slice(path.lastIndexOf('/') + 1)

const blob = await jsZip.file(path)!.async('blob')

return new File([blob], fileName)
},
))
Loading

0 comments on commit d53007e

Please sign in to comment.