Skip to content

Commit b4734bb

Browse files
committed
use inferred animation bindings from aigc
1 parent 9a6205e commit b4734bb

File tree

4 files changed

+27
-8
lines changed

4 files changed

+27
-8
lines changed

spx-gui/src/apis/aigc.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
type UniversalUrl
1414
} from './common'
1515
import type { AssetExtraSettings, AssetType } from './asset'
16+
import type { State } from '@/models/sprite.ts'
1617

1718
export type ProjectSettings = {
1819
name: string
@@ -277,6 +278,7 @@ export async function enrichAssetSettings(
277278
export type SpriteContentSettings = {
278279
costumes: CostumeSettings[]
279280
animations: AnimationSettings[]
281+
animationBindings?: Record<State, string | undefined>
280282
}
281283

282284
export async function genSpriteContentSettings(

spx-gui/src/models/gen/aigc-mock.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '@/apis/aigc'
1818
import { AnimationLoopMode, ArtStyle, BackdropCategory, Perspective, SpriteCategory } from '@/apis/common'
1919
import * as aigcApis from '@/apis/aigc'
20+
import { State } from '@/models/sprite.ts'
2021

2122
export function setupAigcMock() {
2223
vi.mock('@/apis/aigc', { spy: true })
@@ -167,7 +168,14 @@ export class MockAigcApis {
167168
loopMode: AnimationLoopMode.Loopable,
168169
referenceFrameUrl: null
169170
}
170-
]
171+
],
172+
animationBindings: {
173+
[State.Default]: 'walk',
174+
[State.Die]: undefined,
175+
[State.Step]: 'jump',
176+
[State.Turn]: undefined,
177+
[State.Glide]: undefined
178+
}
171179
}
172180
}
173181

spx-gui/src/models/gen/sprite-gen.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as fileHelpers from '@/models/common/file'
66
import { makeProject } from '../common/test'
77
import { setupAigcMock, MockAigcApis } from './aigc-mock'
88
import { SpriteGen } from './sprite-gen'
9+
import { State } from '../sprite'
910
import type { CostumeGen } from './costume-gen'
1011
import type { AnimationGen } from './animation-gen'
1112
import { RotationStyle } from '../sprite'
@@ -145,6 +146,8 @@ describe('SpriteGen', () => {
145146
expect(sprite.animations.length).toBe(2)
146147
expect(sprite.animations[0].name).toBe('walk')
147148
expect(sprite.animations[1].name).toBe('jump')
149+
expect(sprite.getAnimationBoundStates(sprite.animations[0].id)).toEqual([State.Default])
150+
expect(sprite.getAnimationBoundStates(sprite.animations[1].id)).toEqual([State.Step])
148151
})
149152

150153
it('should validate sprite name correctly', async () => {

spx-gui/src/models/gen/sprite-gen.ts

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export class SpriteGen extends Disposable {
3838
private genImagesTask: Task<TaskType.GenerateCostume>
3939
private genImagesPhase: Phase<File[]>
4040
private prepareContentPhase: Phase<void>
41+
private inferredAnimationBindings: Record<State, string | undefined> | null = null
4142

4243
constructor(i18n: I18n, project: Project, initialDescription = '') {
4344
super()
@@ -181,9 +182,17 @@ export class SpriteGen extends Disposable {
181182
generatedAnimations.forEach((a) => {
182183
if (!sprite.animations.includes(a)) {
183184
sprite.addAnimation(a)
184-
// Auto bind to default state if no default animation is set
185-
if (sprite.getDefaultAnimation() == null) {
186-
sprite.setAnimationBoundStates(a.id, [State.Default])
185+
// Auto bind to states based on inferred animation bindings if available.
186+
// If the animation name has been changed by user, the binding may not be applied.
187+
const inferredBindings = this.inferredAnimationBindings
188+
if (inferredBindings != null) {
189+
const animationName = a.name
190+
const statesToBind = Object.entries(inferredBindings)
191+
.filter(([, name]) => name === animationName)
192+
.map(([state]) => state as State)
193+
if (statesToBind.length > 0) {
194+
sprite.setAnimationBoundStates(a.id, statesToBind)
195+
}
187196
}
188197
}
189198
})
@@ -195,10 +204,6 @@ export class SpriteGen extends Disposable {
195204
)
196205
}
197206

198-
get isPreparePhase() {
199-
return this.contentPreparingState.status !== 'finished'
200-
}
201-
202207
get contentPreparingState() {
203208
return this.prepareContentPhase.state
204209
}
@@ -223,6 +228,7 @@ export class SpriteGen extends Disposable {
223228

224229
// Generate additional costumes & animations
225230
const settings = await genSpriteContentSettings(this.settings)
231+
this.inferredAnimationBindings = settings.animationBindings ?? null
226232
this.costumes.push(
227233
...settings.costumes.map((s) => new CostumeGen(this, project, { ...s, referenceCostumeId: defaultCostume.id }))
228234
)

0 commit comments

Comments
 (0)