diff --git a/apps/stage-web/src/pages/devtools/polaroid.vue b/apps/stage-web/src/pages/devtools/polaroid.vue
index a581f91ac..202a1eeb5 100644
--- a/apps/stage-web/src/pages/devtools/polaroid.vue
+++ b/apps/stage-web/src/pages/devtools/polaroid.vue
@@ -1,11 +1,15 @@
diff --git a/packages/stage-ui/src/components/Scenes/Stage.vue b/packages/stage-ui/src/components/Scenes/Stage.vue
index a4c859fe1..52796ba25 100644
--- a/packages/stage-ui/src/components/Scenes/Stage.vue
+++ b/packages/stage-ui/src/components/Scenes/Stage.vue
@@ -27,6 +27,7 @@ import { useLive2d } from '../../stores/live2d'
import { useSpeechStore } from '../../stores/modules/speech'
import { useProvidersStore } from '../../stores/providers'
import { useSettings } from '../../stores/settings'
+import { useVRM } from '../../stores/vrm'
withDefaults(defineProps<{
paused?: boolean
@@ -41,12 +42,34 @@ const db = ref()
const vrmViewerRef = ref<{ setExpression: (expression: string) => void }>()
-const { stageModelRenderer, stageViewControlsEnabled, live2dDisableFocus, stageModelSelectedUrl } = storeToRefs(useSettings())
+const settingsStore = useSettings()
+const { stageModelRenderer, stageViewControlsEnabled, live2dDisableFocus, stageModelSelectedUrl } = storeToRefs(settingsStore)
const { mouthOpenSize } = storeToRefs(useSpeakingStore())
const { audioContext, calculateVolume } = useAudioContext()
const { onBeforeMessageComposed, onBeforeSend, onTokenLiteral, onTokenSpecial, onStreamEnd, onAssistantResponseEnd } = useChatStore()
const providersStore = useProvidersStore()
+const live2dStore = useLive2d()
+const vrmStore = useVRM()
+
+const showStage = ref(true)
+
+live2dStore.onShouldUpdateView(async () => {
+ showStage.value = false
+ await settingsStore.updateStageModel()
+ setTimeout(() => {
+ showStage.value = true
+ }, 100)
+})
+
+vrmStore.onShouldUpdateView(async () => {
+ showStage.value = false
+ await settingsStore.updateStageModel()
+ setTimeout(() => {
+ showStage.value = true
+ }, 100)
+})
+
const audioAnalyser = ref()
const nowSpeaking = ref(false)
const lipSyncStarted = ref(false)
@@ -229,7 +252,7 @@ onMounted(async () => {
{
:disable-focus-at="live2dDisableFocus"
/>
-import { FieldRange } from '@proj-airi/ui'
-import { ref } from 'vue'
-
-import PoppinMarkdown from './PoppinMarkdown.web.vue'
-
-import {
- createCutePopupAnimator,
- createFadeAnimator,
- createFloatAnimator,
- createPopupAnimator,
- createStackAnimator,
-} from './animators'
-
-const duration = ref(750)
-
-// Sample markdown content
-const markdownText = ref(`# Hello World
-
-This is **bold text** and *italic text*.
-
-Here's a list:
-- Item 1
-- Item 2
-- Item 3
-
-\`\`\`javascript
-console.log('Hello, world!');
-\`\`\`
-
-> This is a blockquote with some **bold** content.
-
-And here's a [link](https://example.com) and some inline \`code\`.`)
-
-const chatMarkdown = ref(`Hi! I can help you with **markdown**. Here are some examples:
-
-- *Italics* and **bold** text
-- \`inline code\` snippets
-- Even [links](https://example.com)
-
-\`\`\`typescript
-function greet(name: string) {
- console.log(\`Hello, \${name}!\`);
-}
-\`\`\`
-
-What would you like to know?`)
-
-function createMarkdownStream(text: string) {
- return new ReadableStream({
- start(controller) {
- const bytes = new TextEncoder().encode(text)
- let index = 0
- const interval = setInterval(() => {
- if (index < bytes.length) {
- controller.enqueue(bytes.subarray(index, index + 1))
- index++
- }
- else {
- clearInterval(interval)
- controller.close()
- }
- }, 30 + 50 * Math.random()) // Faster for better demo
- },
- })
-}
-
-const streamingMarkdown = createMarkdownStream(`# Streaming Markdown Demo
-
-This text is being **streamed** character by character!
-
-## Features
-
-- Real-time *markdown* rendering
-- **Character-by-character** animation
-- Support for \`code\` and other elements
-
-\`\`\`javascript
-// Code blocks appear as complete units
-const message = "Hello from streaming markdown!";
-console.log(message);
-\`\`\`
-
-> Blockquotes work too with **mixed** formatting.
-
-Pretty cool, right?`)
-
-const chatStreamingMarkdown = createMarkdownStream(`🤖 **AI Assistant**: Hello! I can help you with various tasks.
-
-Here's what I can do:
-- Answer questions about **programming**
-- Help with \`code debugging\`
-- Explain *technical concepts*
-
-\`\`\`python
-# Example: Python function
-def greet_user(name):
- return f"Hello, {name}! How can I help?"
-
-print(greet_user("Developer"))
-\`\`\`
-
-> 💡 **Tip**: I stream my responses in real-time for a better experience!
-
-What would you like to work on today?`)
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/packages/stage-ui/src/components/Widgets/PoppinText/PoppinMarkdown.web.vue b/packages/stage-ui/src/components/Widgets/PoppinText/PoppinMarkdown.web.vue
deleted file mode 100644
index d9e10b0ab..000000000
--- a/packages/stage-ui/src/components/Widgets/PoppinText/PoppinMarkdown.web.vue
+++ /dev/null
@@ -1,212 +0,0 @@
-
-
-
-
-
-
diff --git a/packages/stage-ui/src/stores/display-models.ts b/packages/stage-ui/src/stores/display-models.ts
index ec183141a..bf2ec71e6 100644
--- a/packages/stage-ui/src/stores/display-models.ts
+++ b/packages/stage-ui/src/stores/display-models.ts
@@ -39,8 +39,8 @@ export interface DisplayModelURL {
}
const displayModelsPresets: DisplayModel[] = [
- { id: 'preset-live2d-1', format: DisplayModelFormat.Live2dZip, type: 'url', url: '/assets/live2d/models/hiyori_pro_zh.zip', name: 'Hiyori (Pro)', previewImage: '/assets/live2d/models/hiyori_free_zh/avatar.png', importedAt: 1733113886840 },
- { id: 'preset-live2d-2', format: DisplayModelFormat.Live2dZip, type: 'url', url: '/assets/live2d/models/hiyori_free_zh.zip', name: 'Hiyori (Free)', previewImage: '/assets/live2d/models/hiyori_free_zh/avatar.png', importedAt: 1733113886840 },
+ { id: 'preset-live2d-1', format: DisplayModelFormat.Live2dZip, type: 'url', url: '/assets/live2d/models/hiyori_pro_zh.zip', name: 'Hiyori (Pro)', previewImage: '/assets/live2d/models/hiyori_pro_zh/avatar.png', importedAt: 1733113886840 },
+ { id: 'preset-live2d-2', format: DisplayModelFormat.Live2dZip, type: 'url', url: '/assets/live2d/models/hiyori_free_zh.zip', name: 'Hiyori (Free)', previewImage: '/assets/live2d/models/hiyori_pro_zh/avatar.png', importedAt: 1733113886840 },
]
export const useDisplayModelsStore = defineStore('display-models', () => {
diff --git a/packages/stage-ui/src/stores/settings.ts b/packages/stage-ui/src/stores/settings.ts
index 277062643..ca941d26c 100644
--- a/packages/stage-ui/src/stores/settings.ts
+++ b/packages/stage-ui/src/stores/settings.ts
@@ -35,7 +35,7 @@ export const useSettings = defineStore('settings', () => {
const language = useLocalStorage('settings/language', '')
- const stageModelSelected = useLocalStorage('settings/stage/model', undefined)
+ const stageModelSelected = useLocalStorage('settings/stage/model', 'preset-live2d-1')
const stageModelSelectedDisplayModel = ref()
const stageModelSelectedUrl = ref()
const stageModelRenderer = ref<'live2d' | 'vrm' | 'disabled'>()
@@ -56,17 +56,6 @@ export const useSettings = defineStore('settings', () => {
return
}
- if (model.type === 'file') {
- if (stageModelSelectedUrl.value) {
- URL.revokeObjectURL(stageModelSelectedUrl.value)
- }
-
- stageModelSelectedUrl.value = URL.createObjectURL(model.file)
- }
- else {
- stageModelSelectedUrl.value = model.url
- }
-
switch (model.format) {
case DisplayModelFormat.Live2dZip:
stageModelRenderer.value = 'live2d'
@@ -79,6 +68,17 @@ export const useSettings = defineStore('settings', () => {
break
}
+ if (model.type === 'file') {
+ if (stageModelSelectedUrl.value) {
+ URL.revokeObjectURL(stageModelSelectedUrl.value)
+ }
+
+ stageModelSelectedUrl.value = URL.createObjectURL(model.file)
+ }
+ else {
+ stageModelSelectedUrl.value = model.url
+ }
+
stageModelSelectedDisplayModel.value = model
}