From 590f88087f2a4af30c78600aa0beca4a892b0a5f Mon Sep 17 00:00:00 2001 From: nighca Date: Fri, 24 Jan 2025 09:48:09 +0800 Subject: [PATCH] exclude animation costumes for completion --- spx-gui/src/models/animation.ts | 14 ++--- tools/spxls/internal/server/completion.go | 4 +- tools/spxls/internal/server/spx_resource.go | 69 ++++++++++++++++----- 3 files changed, 62 insertions(+), 25 deletions(-) diff --git a/spx-gui/src/models/animation.ts b/spx-gui/src/models/animation.ts index 4c2932148..62bd17c79 100644 --- a/spx-gui/src/models/animation.ts +++ b/spx-gui/src/models/animation.ts @@ -26,8 +26,8 @@ export type AnimationInits = { export type RawAnimationConfig = { builder_id?: string - frameFrom?: number | string - frameTo?: number | string + frameFrom?: string + frameTo?: string frameFps?: number onStart?: ActionConfig @@ -134,12 +134,12 @@ export class Animation extends Disposable { costumes: Costume[], { sounds, includeId = true }: AnimationExportLoadOptions ): [animation: Animation, animationCostumeNames: string[]] { - frameFrom = frameFrom ?? from - frameTo = frameTo ?? to + const finalFrom = frameFrom ?? from + const finalTo = frameTo ?? to frameFps = frameFps ?? fps - if (frameFrom == null || frameTo == null) throw new Error(`from and to expected for Animation ${name}`) - const fromIndex = getCostumeIndex(costumes, frameFrom) - const toIndex = getCostumeIndex(costumes, frameTo) + if (finalFrom == null || finalTo == null) throw new Error(`from and to expected for Animation ${name}`) + const fromIndex = getCostumeIndex(costumes, finalFrom) + const toIndex = getCostumeIndex(costumes, finalTo) const animationCostumes = costumes.slice(fromIndex, toIndex + 1).map((c) => c.clone(true)) const duration = animationCostumes.length / (frameFps ?? defaultFps) // drop spx `duration`, which is different from ours diff --git a/tools/spxls/internal/server/completion.go b/tools/spxls/internal/server/completion.go index ec5c44201..5b1f12d1b 100644 --- a/tools/spxls/internal/server/completion.go +++ b/tools/spxls/internal/server/completion.go @@ -654,8 +654,8 @@ func (ctx *completionContext) collectTypeSpecific(typ types.Type) error { expectedSpxSprite := ctx.getSpxSpriteResource() for _, spxSprite := range ctx.result.spxResourceSet.sprites { if expectedSpxSprite == nil || spxSprite == expectedSpxSprite { - spxResourceIds = slices.Grow(spxResourceIds, len(spxSprite.Costumes)) - for _, spxSpriteCostume := range spxSprite.Costumes { + spxResourceIds = slices.Grow(spxResourceIds, len(spxSprite.NormalCostumes)) + for _, spxSpriteCostume := range spxSprite.NormalCostumes { spxResourceIds = append(spxResourceIds, SpxSpriteCostumeResourceID{spxSprite.Name, spxSpriteCostume.Name}) } } diff --git a/tools/spxls/internal/server/spx_resource.go b/tools/spxls/internal/server/spx_resource.go index 68fa921f9..5bacc7629 100644 --- a/tools/spxls/internal/server/spx_resource.go +++ b/tools/spxls/internal/server/spx_resource.go @@ -176,13 +176,26 @@ func NewSpxResourceSet(rootFS fs.FS) (*SpxResourceSet, error) { // Process animations. sprite.Animations = make([]SpxSpriteAnimationResource, 0, len(sprite.FAnimations)) - for animName := range sprite.FAnimations { + for animName, fAnim := range sprite.FAnimations { sprite.Animations = append(sprite.Animations, SpxSpriteAnimationResource{ - ID: SpxSpriteAnimationResourceID{SpriteName: spriteName, AnimationName: animName}, - Name: animName, + ID: SpxSpriteAnimationResourceID{SpriteName: spriteName, AnimationName: animName}, + Name: animName, + FromIndex: getCostumeIndex(fAnim.FrameFrom, sprite.Costumes), + ToIndex: getCostumeIndex(fAnim.FrameTo, sprite.Costumes), }) } + // Process normal costumes. + sprite.NormalCostumes = make([]SpxSpriteCostumeResource, 0, len(sprite.Costumes)) + for i, costume := range sprite.Costumes { + isAnimation := slices.ContainsFunc(sprite.Animations, func(anim SpxSpriteAnimationResource) bool { + return anim.includeCostume(i) + }) + if !isAnimation { + sprite.NormalCostumes = append(sprite.NormalCostumes, costume) + } + } + set.sprites[spriteName] = &sprite } @@ -265,15 +278,22 @@ func (id SpxSoundResourceID) URI() SpxResourceURI { return SpxResourceURI(fmt.Sprintf("spx://resources/sounds/%s", id.SoundName)) } +type spxSpriteFAnimation struct { + FrameFrom string `json:"frameFrom"` + FrameTo string `json:"frameTo"` +} + // SpxSpriteResource represents an spx sprite resource. type SpxSpriteResource struct { - ID SpxSpriteResourceID `json:"-"` - Name string `json:"name"` - Costumes []SpxSpriteCostumeResource `json:"costumes"` - CostumeIndex int `json:"costumeIndex"` - FAnimations map[string]json.RawMessage `json:"fAnimations"` - Animations []SpxSpriteAnimationResource `json:"-"` - DefaultAnimation string `json:"defaultAnimation"` + ID SpxSpriteResourceID `json:"-"` + Name string `json:"name"` + Costumes []SpxSpriteCostumeResource `json:"costumes"` + // NormalCostumes includes all costumes except animation costumes. + NormalCostumes []SpxSpriteCostumeResource `json:"-"` + CostumeIndex int `json:"costumeIndex"` + FAnimations map[string]spxSpriteFAnimation `json:"fAnimations"` + Animations []SpxSpriteAnimationResource `json:"-"` + DefaultAnimation string `json:"defaultAnimation"` } // SpxSpriteResourceID is the ID of an spx sprite resource. @@ -315,10 +335,9 @@ func (sprite *SpxSpriteResource) Animation(name string) *SpxSpriteAnimationResou // SpxSpriteCostumeResource represents an spx sprite costume resource. type SpxSpriteCostumeResource struct { - ID SpxSpriteCostumeResourceID `json:"-"` - Index int `json:"index"` - Name string `json:"name"` - Path string `json:"path"` + ID SpxSpriteCostumeResourceID `json:"-"` + Name string `json:"name"` + Path string `json:"path"` } // SpxSpriteCostumeResourceID is the ID of an spx sprite costume resource. @@ -339,8 +358,17 @@ func (id SpxSpriteCostumeResourceID) URI() SpxResourceURI { // SpxSpriteAnimationResource represents an spx sprite animation resource. type SpxSpriteAnimationResource struct { - ID SpxSpriteAnimationResourceID `json:"-"` - Name string `json:"name"` + ID SpxSpriteAnimationResourceID `json:"-"` + Name string `json:"name"` + FromIndex *int `json:"-"` + ToIndex *int `json:"-"` +} + +func (a *SpxSpriteAnimationResource) includeCostume(index int) bool { + if a.FromIndex == nil || a.ToIndex == nil { + return false + } + return *a.FromIndex <= index && index <= *a.ToIndex } // SpxSpriteAnimationResourceID is the ID of an spx sprite animation resource. @@ -382,3 +410,12 @@ func (id SpxWidgetResourceID) Name() string { func (id SpxWidgetResourceID) URI() SpxResourceURI { return SpxResourceURI(fmt.Sprintf("spx://resources/widgets/%s", id.WidgetName)) } + +func getCostumeIndex(name string, costumes []SpxSpriteCostumeResource) *int { + for i, costume := range costumes { + if costume.Name == name { + return &i + } + } + return nil +}