spine资源引入
This commit is contained in:
1 parent
166b5015c2
commit
5f4667f736
25 files changed
+31151
-9082
No files matched your search
@@ -1,5 +1,7 @@
|
||||
import { defineStore } from 'pinia'
|
||||
import { EmitterConfig, defaultConfig, ParticleState, type SceneCollider } from '../core/particleEmitter'
|
||||
import type { SpineSceneObject } from '../spine/spineTypes'
|
||||
import { releaseSpineAsset } from '../spine/spineAssetRegistry'
|
||||
|
||||
export interface ParticleSystem {
|
||||
id: number
|
||||
@@ -22,6 +24,8 @@ export interface ScenePath {
|
||||
x: number
|
||||
y: number
|
||||
rotation: number
|
||||
scaleX: number
|
||||
scaleY: number
|
||||
closed: boolean
|
||||
color: string
|
||||
preset: '' | 'circle' | 'square' | 'polygon' | 'star'
|
||||
@@ -48,6 +52,8 @@ export interface SettingsState {
|
||||
showAxisLabels: boolean
|
||||
/** 坐标轴数值颜色(#rrggbb) */
|
||||
axisColor: string
|
||||
/** 是否在画布中显示已加载的 Spine 动画资源 */
|
||||
showSpineResources: boolean
|
||||
}
|
||||
|
||||
export interface TimelineState {
|
||||
@@ -70,6 +76,7 @@ export interface TimelineState {
|
||||
let seq = 1
|
||||
let colliderSeq = 1
|
||||
let pathSeq = 1
|
||||
let spineSeq = 1
|
||||
|
||||
export const useParticleStore = defineStore('particle', {
|
||||
state: () => ({
|
||||
@@ -77,12 +84,13 @@ export const useParticleStore = defineStore('particle', {
|
||||
systems: [] as ParticleSystem[],
|
||||
colliders: [] as CollisionBody[],
|
||||
paths: [] as ScenePath[],
|
||||
spines: [] as SpineSceneObject[],
|
||||
activeId: 0,
|
||||
activeObjectType: 'particle' as SceneObjectType,
|
||||
activeObjectId: 0,
|
||||
// 与 Spine 编辑器默认时间基准对齐:1 秒 = 30 帧。
|
||||
timeline: { playing: true, loop: true, frame: 0, totalFrames: 60, fps: 30, recorded: false, animation: 'animation' } as TimelineState,
|
||||
settings: { tickEnabled: false, axisFontSize: 12, tickWidth: 1, showAxisLabels: true, axisColor: '#7a86ad' } as SettingsState,
|
||||
settings: { tickEnabled: false, axisFontSize: 12, tickWidth: 1, showAxisLabels: true, axisColor: '#7a86ad', showSpineResources: true } as SettingsState,
|
||||
}),
|
||||
getters: {
|
||||
activeSystemCount: (s) => s.systems.length,
|
||||
@@ -136,6 +144,8 @@ export const useParticleStore = defineStore('particle', {
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotation: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
radius: 50,
|
||||
radiusX: 70,
|
||||
radiusY: 45,
|
||||
@@ -161,6 +171,8 @@ export const useParticleStore = defineStore('particle', {
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotation: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
closed: false,
|
||||
color: '#ff933e',
|
||||
preset: '',
|
||||
@@ -171,6 +183,33 @@ export const useParticleStore = defineStore('particle', {
|
||||
this.activeObjectId = path.id
|
||||
return path
|
||||
},
|
||||
addSpine() {
|
||||
const id = spineSeq++
|
||||
const spine: SpineSceneObject = {
|
||||
id,
|
||||
name: `SpineSkeleton${id}`,
|
||||
enabled: true,
|
||||
x: 0,
|
||||
y: 0,
|
||||
rotation: 0,
|
||||
scaleX: 1,
|
||||
scaleY: 1,
|
||||
timeOffset: 0,
|
||||
skeletonFileName: '',
|
||||
atlasFileName: '',
|
||||
textureFileNames: [],
|
||||
selectedAnimation: '',
|
||||
animations: [],
|
||||
bones: [],
|
||||
assetVersion: 0,
|
||||
status: 'empty',
|
||||
error: '',
|
||||
}
|
||||
this.spines.push(spine)
|
||||
this.activeObjectType = 'spine'
|
||||
this.activeObjectId = spine.id
|
||||
return spine
|
||||
},
|
||||
selectSceneObject(type: SceneObjectType, id: number) {
|
||||
this.activeObjectType = type
|
||||
this.activeObjectId = id
|
||||
@@ -194,10 +233,48 @@ export const useParticleStore = defineStore('particle', {
|
||||
this.activeObjectId = fallback?.id ?? this.paths[0]?.id ?? 0
|
||||
}
|
||||
},
|
||||
removeSpine(id: number) {
|
||||
releaseSpineAsset(id)
|
||||
const index = this.spines.findIndex((item) => item.id === id)
|
||||
if (index >= 0) this.spines.splice(index, 1)
|
||||
if (this.activeObjectType === 'spine' && this.activeObjectId === id) {
|
||||
const particle = this.systems[0]
|
||||
const collider = this.colliders[0]
|
||||
const path = this.paths[0]
|
||||
const spine = this.spines[0]
|
||||
if (particle) {
|
||||
this.activeObjectType = 'particle'
|
||||
this.activeObjectId = particle.id
|
||||
this.activeId = particle.id
|
||||
} else if (collider) {
|
||||
this.activeObjectType = 'collision'
|
||||
this.activeObjectId = collider.id
|
||||
} else if (path) {
|
||||
this.activeObjectType = 'path'
|
||||
this.activeObjectId = path.id
|
||||
} else {
|
||||
this.activeObjectType = 'spine'
|
||||
this.activeObjectId = spine?.id ?? 0
|
||||
}
|
||||
}
|
||||
this.recalcTotalFrames()
|
||||
},
|
||||
play() { this.timeline.playing = true },
|
||||
pause() { this.timeline.playing = false },
|
||||
togglePlay() { this.timeline.playing = !this.timeline.playing },
|
||||
toStart() { this.timeline.frame = 0 },
|
||||
previousFrame() {
|
||||
this.timeline.playing = false
|
||||
this.timeline.frame = Math.max(0, this.timeline.frame - 1)
|
||||
},
|
||||
nextFrame() {
|
||||
this.timeline.playing = false
|
||||
this.timeline.frame = Math.min(Math.max(0, this.timeline.totalFrames - 1), this.timeline.frame + 1)
|
||||
},
|
||||
toEnd() {
|
||||
this.timeline.playing = false
|
||||
this.timeline.frame = Math.max(0, this.timeline.totalFrames - 1)
|
||||
},
|
||||
toggleLoop() { this.timeline.loop = !this.timeline.loop },
|
||||
setFrame(f: number) {
|
||||
this.timeline.frame = Math.max(0, Math.min(f, this.timeline.totalFrames - 1))
|
||||
@@ -220,6 +297,12 @@ export const useParticleStore = defineStore('particle', {
|
||||
const end = Math.max(0, Number(c.delay) || 0) + emissionDuration + particleLife
|
||||
if (end > maxSec) maxSec = end
|
||||
}
|
||||
for (const spine of this.spines) {
|
||||
const animation = spine.animations.find((item) => item.name === spine.selectedAnimation)
|
||||
if (!animation) continue
|
||||
const end = Math.max(0, Number(spine.timeOffset) || 0) + Math.max(0, animation.duration || 0)
|
||||
if (end > maxSec) maxSec = end
|
||||
}
|
||||
const frames = Math.max(1, Math.ceil(maxSec * fps))
|
||||
this.timeline.totalFrames = frames
|
||||
// clamp 当前帧
|
||||
|
||||
Reference in new issue
Block a user