1 Commits

Author SHA1 Message Date
ayang
97d28ed9ba refactor: 迁移到 easy-live2d 并重构相关代码 2025-06-11 22:29:27 +08:00
5 changed files with 231 additions and 845 deletions

View File

@@ -37,12 +37,12 @@
"@vueuse/core": "^13.3.0",
"ant-design-vue": "^4.2.6",
"dayjs": "^1.11.13",
"easy-live2d": "^0.3.2",
"es-toolkit": "^1.38.0",
"is-url": "^1.2.4",
"nanoid": "^5.1.5",
"pinia": "^3.0.3",
"pixi-live2d-display": "^0.4.0",
"pixi.js": "^6.5.10",
"pixi.js": "^8.10.1",
"tauri-plugin-macos-permissions-api": "^2.3.0",
"vue": "^3.5.16",
"vue-markdown-render": "^2.2.1",

888
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

View File

@@ -43,11 +43,11 @@ export function useModel() {
await resolveResource(path)
const data = await live2d.load(path)
await live2d.load(path)
handleResize()
// handleResize()
Object.assign(modelStore, data)
// Object.assign(modelStore, data)
} catch (error) {
message.error(String(error))
}

110
src/utils/live2d copy.ts Normal file
View File

@@ -0,0 +1,110 @@
import type { Cubism4InternalModel } from 'pixi-live2d-display'
import { convertFileSrc } from '@tauri-apps/api/core'
import { readDir, readTextFile } from '@tauri-apps/plugin-fs'
import { Cubism4ModelSettings, Live2DModel } from 'pixi-live2d-display'
import { Application, Ticker } from 'pixi.js'
import { join } from './path'
Live2DModel.registerTicker(Ticker)
class Live2d {
private app: Application | null = null
public model: Live2DModel | null = null
constructor() { }
private mount() {
const view = document.getElementById('live2dCanvas') as HTMLCanvasElement
this.app = new Application({
view,
resizeTo: window,
backgroundAlpha: 0,
autoDensity: true,
resolution: devicePixelRatio,
})
}
public async load(path: string) {
if (!this.app) {
this.mount()
}
this.destroy()
const files = await readDir(path)
const modelFile = files.find(file => file.name.endsWith('.model3.json'))
if (!modelFile) {
throw new Error('未找到模型主配置文件,请确认模型文件是否完整。')
}
const modelPath = join(path, modelFile.name)
const modelJSON = JSON.parse(await readTextFile(modelPath))
const modelSettings = new Cubism4ModelSettings({
...modelJSON,
url: convertFileSrc(modelPath),
})
modelSettings.replaceFiles((file) => {
return convertFileSrc(join(path, file))
})
this.model = await Live2DModel.from(modelSettings)
this.app?.stage.addChild(this.model)
const { motions, expressions } = modelSettings
return {
motions,
expressions,
}
}
public destroy() {
this.model?.destroy()
}
public playMotion(group: string, index: number) {
return this.model?.motion(group, index)
}
public playExpressions(index: number) {
return this.model?.expression(index)
}
public getCoreModel() {
const internalModel = this.model?.internalModel as Cubism4InternalModel
return internalModel?.coreModel
}
public getParameterRange(id: string) {
const coreModel = this.getCoreModel()
const index = coreModel?.getParameterIndex(id)
const min = coreModel?.getParameterMinimumValue(index)
const max = coreModel?.getParameterMaximumValue(index)
return {
min,
max,
}
}
public setParameterValue(id: string, value: number) {
const coreModel = this.getCoreModel()
return coreModel?.setParameterValueById?.(id, Number(value))
}
}
const live2d = new Live2d()
export default live2d

View File

@@ -1,24 +1,30 @@
import type { Cubism4InternalModel } from 'pixi-live2d-display'
import type { Sprite } from 'pixi.js'
import { convertFileSrc } from '@tauri-apps/api/core'
import { readDir, readTextFile } from '@tauri-apps/plugin-fs'
import { Cubism4ModelSettings, Live2DModel } from 'pixi-live2d-display'
import { Config, CubismSetting, Live2DSprite, LogLevel } from 'easy-live2d'
import { Application, Ticker } from 'pixi.js'
import { join } from './path'
Live2DModel.registerTicker(Ticker)
Config.MotionGroupIdle = 'Idle'
Config.MouseFollow = false
Config.CubismLoggingLevel = LogLevel.LogLevel_Off
class Live2d {
private app: Application | null = null
public model: Live2DModel | null = null
public model: Sprite | null = null
constructor() { }
private mount() {
private async initApp() {
if (this.app) return
const view = document.getElementById('live2dCanvas') as HTMLCanvasElement
this.app = new Application({
this.app = new Application()
await this.app.init({
view,
resizeTo: window,
backgroundAlpha: 0,
@@ -28,9 +34,7 @@ class Live2d {
}
public async load(path: string) {
if (!this.app) {
this.mount()
}
this.initApp()
this.destroy()
@@ -46,25 +50,27 @@ class Live2d {
const modelJSON = JSON.parse(await readTextFile(modelPath))
const modelSettings = new Cubism4ModelSettings({
...modelJSON,
url: convertFileSrc(modelPath),
const modelSetting = new CubismSetting({
modelJSON,
})
modelSettings.replaceFiles((file) => {
modelSetting.redirectPath(({ file }) => {
return convertFileSrc(join(path, file))
})
this.model = await Live2DModel.from(modelSettings)
this.model = new Live2DSprite({
modelSetting,
ticker: Ticker.shared,
})
this.app?.stage.addChild(this.model)
const { motions, expressions } = modelSettings
// const { motions, expressions } = modelSettings
return {
motions,
expressions,
}
// return {
// motions,
// expressions,
// }
}
public destroy() {
@@ -72,36 +78,36 @@ class Live2d {
}
public playMotion(group: string, index: number) {
return this.model?.motion(group, index)
// return this.model?.motion(group, index)
}
public playExpressions(index: number) {
return this.model?.expression(index)
// return this.model?.expression(index)
}
public getCoreModel() {
const internalModel = this.model?.internalModel as Cubism4InternalModel
// const internalModel = this.model?.internalModel as Cubism4InternalModel
return internalModel?.coreModel
// return internalModel?.coreModel
}
public getParameterRange(id: string) {
const coreModel = this.getCoreModel()
// const coreModel = this.getCoreModel()
const index = coreModel?.getParameterIndex(id)
const min = coreModel?.getParameterMinimumValue(index)
const max = coreModel?.getParameterMaximumValue(index)
// const index = coreModel?.getParameterIndex(id)
// const min = coreModel?.getParameterMinimumValue(index)
// const max = coreModel?.getParameterMaximumValue(index)
return {
min,
max,
min: 0,
max: 1,
}
}
public setParameterValue(id: string, value: number) {
const coreModel = this.getCoreModel()
// const coreModel = this.getCoreModel()
return coreModel?.setParameterValueById?.(id, Number(value))
// return coreModel?.setParameterValueById?.(id, Number(value))
}
}