Skip to content

Commit

Permalink
keep order of sprites & sounds (#720)
Browse files Browse the repository at this point in the history
  • Loading branch information
nighca authored Aug 9, 2024
1 parent a63333b commit 2b0440d
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 5 deletions.
40 changes: 39 additions & 1 deletion spx-gui/src/models/project/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Sprite } from '../sprite'
import { Animation } from '../animation'
import { Sound } from '../sound'
import { Costume } from '../costume'
import { fromText } from '../common/file'
import { fromText, type Files } from '../common/file'
import { Project } from '.'

function mockFile(name = 'mocked') {
Expand Down Expand Up @@ -35,4 +35,42 @@ describe('Project', () => {
await project.loadGameFiles(files)
expect(project.sprites[0].animations[0].sound).toBe(project.sounds[0].name)
})

it('should preserve order for sprites & sounds however files are sorted', async () => {
const project = makeProject()

project.sprites[0].setName('Sprite1')
const sprite3 = new Sprite('Sprite3')
project.addSprite(sprite3)
const sprite2 = new Sprite('Sprite2')
project.addSprite(sprite2)

project.sounds[0].setName('sound1')
const sound3 = new Sound('sound3', mockFile())
project.addSound(sound3)
const sound2 = new Sound('sound2', mockFile())
project.addSound(sound2)

const files = project.exportGameFiles()

const reversedFiles = Object.keys(files)
.reverse()
.reduce<Files>((acc, key) => {
acc[key] = files[key]
return acc
}, {})
await project.loadGameFiles(reversedFiles)
expect(project.sprites.map((s) => s.name)).toEqual(['Sprite1', 'Sprite3', 'Sprite2'])
expect(project.sounds.map((s) => s.name)).toEqual(['sound1', 'sound3', 'sound2'])

const shuffledFiles = Object.keys(files)
.sort(() => Math.random() - 0.5)
.reduce<Files>((acc, key) => {
acc[key] = files[key]
return acc
}, {})
await project.loadGameFiles(shuffledFiles)
expect(project.sprites.map((s) => s.name)).toEqual(['Sprite1', 'Sprite3', 'Sprite2'])
expect(project.sounds.map((s) => s.name)).toEqual(['sound1', 'sound3', 'sound2'])
})
})
32 changes: 28 additions & 4 deletions spx-gui/src/models/project/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ type RawProjectConfig = RawStageConfig & {
// TODO: support other types in zorder
zorder?: string[]
run?: RunConfig
/**
* Sprite order info, used by Go+ Builder to determine the order of sprites.
* `builderSpriteOrder` is [builder-only data](https://github.com/goplus/builder/issues/714#issuecomment-2274863055), whose name should be prefixed with `builder_` as a convention.
*/
builder_spriteOrder?: string[]
/**
* Sound order info, used by Go+ Builder to determine the order of sounds.
* `builderSoundOrder` is [builder-only data](https://github.com/goplus/builder/issues/714#issuecomment-2274863055), whose name should be prefixed with `builder_` as a convention.
*/
builder_soundOrder?: string[]
// TODO: camera
}

Expand Down Expand Up @@ -264,17 +274,22 @@ export class Project extends Disposable {
if (configFile != null) {
Object.assign(config, await toConfig(configFile))
}
const { zorder, ...stageConfig } = config
const {
zorder,
builder_spriteOrder: spriteOrder,
builder_soundOrder: soundOrder,
...stageConfig
} = config
const [stage, sounds, sprites] = await Promise.all([
Stage.load(stageConfig, files),
Sound.loadAll(files),
Sprite.loadAll(files)
])
this.stage = stage
this.sprites.splice(0).forEach((s) => s.dispose())
sprites.forEach((s) => this.addSprite(s))
orderBy(sprites, spriteOrder).forEach((s) => this.addSprite(s))
this.sounds.splice(0).forEach((s) => s.dispose())
sounds.forEach((s) => this.addSound(s))
orderBy(sounds, soundOrder).forEach((s) => this.addSound(s))
this.zorder = zorder ?? []
this.autoSelect()
}
Expand All @@ -291,7 +306,9 @@ export class Project extends Disposable {
width: stageConfig.map?.width,
height: stageConfig.map?.height
},
zorder: this.zorder
zorder: this.zorder,
builder_spriteOrder: this.sprites.map((s) => s.name),
builder_soundOrder: this.sounds.map((s) => s.name)
}
files[projectConfigFilePath] = fromConfig(projectConfigFileName, config)
Object.assign(files, stageFiles)
Expand Down Expand Up @@ -487,3 +504,10 @@ export class Project extends Disposable {
export function fullName(owner: string, name: string) {
return `${owner}/${name}`
}

function orderBy<T extends Sprite | Sound>(list: T[], order: string[] | undefined) {
if (order == null) return list
return list.slice().sort((a, b) => {
return order.indexOf(a.name) - order.indexOf(b.name)
})
}

0 comments on commit 2b0440d

Please sign in to comment.