Skip to content

Commit

Permalink
Fix pump noteskins
Browse files Browse the repository at this point in the history
  • Loading branch information
tillvit committed Jul 31, 2024
1 parent be812f4 commit c89fbfd
Show file tree
Hide file tree
Showing 39 changed files with 361 additions and 225 deletions.
83 changes: 54 additions & 29 deletions app/src/chart/component/notefield/Notefield.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,29 @@ export class NoteWrapper extends Container {

this.addChild(object, this.icon)

object.nf.noteskin?.onUpdate(this, cr => {
if (object.nf.noteskin === undefined) {
EventHandler.on("noteskinLoaded", () => this.loadEventHandler())
} else {
this.loadEventHandler()
}
}

loadEventHandler() {
this.object.nf.noteskin!.onUpdate(this, cr => {
if (!Options.chart.drawIcons) {
this.icon.visible = false
return
}
if (object.nf.noteskinOptions?.hideIcons?.includes(object.note.type)) {
if (
this.object.nf.noteskinOptions?.hideIcons?.includes(
this.object.note.type
)
) {
this.icon.visible = false
return
}
this.icon.visible = true
if (object.note.type == "Fake") {
if (this.object.note.type == "Fake") {
this.icon.visible = cr.chartManager.getMode() != EditMode.Play
}
})
Expand All @@ -86,6 +98,17 @@ export class NoteObject extends Container {
super()
this.note = note
this.nf = notefield

if (this.nf.noteskin === undefined) {
EventHandler.on("noteskinLoaded", () => {
this.loadElement(note)
})
} else {
this.loadElement(note)
}
}

loadElement(note: TapNotedataEntry) {
const element = this.nf.noteskin!.getElement(
{
element: note.type,
Expand Down Expand Up @@ -132,6 +155,7 @@ export class HoldObject extends Container {
private readonly metrics
private readonly ns
readonly nf
private loaded = false

constructor(notefield: Notefield, note: HoldNotedataEntry) {
super()
Expand All @@ -142,6 +166,25 @@ export class HoldObject extends Container {
this.ns = notefield.noteskin!
this.nf = notefield
this.metrics = this.ns.metrics

active.visible = false

this.active = active
this.inactive = inactive

this.addChild(inactive, active)

if (notefield.noteskin === undefined) {
EventHandler.on("noteskinLoaded", () => {
this.loadElements()
})
} else {
this.loadElements()
}
}

loadElements() {
if (this.loaded) return
;(this.elements as any) = {}
for (const state of ["Active", "Inactive"] as const) {
;(this.elements[state] as any) = {}
Expand All @@ -162,18 +205,12 @@ export class HoldObject extends Container {
} else {
this.elements[state][part] = element
}
;(state == "Active" ? active : inactive).addChild(
;(state == "Active" ? this.active : this.inactive).addChild(
this.elements[state][part]
)
}
}

active.visible = false

this.active = active
this.inactive = inactive

this.addChild(inactive, active)
this.loaded = true
}

getNoteskinElement(element: string) {
Expand All @@ -196,6 +233,7 @@ export class HoldObject extends Container {
}

setBrightness(brightness: number) {
if (!this.loaded) return
const states = ["Active", "Inactive"] as const
const items = ["Body", "TopCap", "BottomCap"] as const
for (const state of states) {
Expand All @@ -212,6 +250,7 @@ export class HoldObject extends Container {
}

setLength(length: number) {
if (!this.loaded) return
const states = ["Active", "Inactive"] as const
const sign = Math.sign(length)
const absLength = Math.abs(length)
Expand Down Expand Up @@ -242,10 +281,13 @@ export class HoldObject extends Container {
}

this.elements[state].TopCap.y =
absLength + this.metrics[`${this.note.type}BodyTopOffset`]
this.metrics[`${this.note.type}BodyTopOffset`]
const bottomCapScale = Math.abs(this.elements[state].BottomCap.scale.y)
this.elements[state].BottomCap.scale.y =
length < 0 ? -bottomCapScale : bottomCapScale
const topCapScale = Math.abs(this.elements[state].TopCap.scale.y)
this.elements[state].TopCap.scale.y =
length < 0 ? -topCapScale : topCapScale

this.elements[state].Body.height *= sign
this.elements[state].Body.y *= sign
Expand Down Expand Up @@ -502,23 +544,6 @@ export class Notefield extends Container implements ChartRendererComponent {
}

createNote(note: NotedataEntry): NoteWrapper {
if (this.noteskin === undefined) {
const a = new Container() as NoteObject
a.type = "note"
a.note = {
beat: 0,
type: "Tap",
col: 0,
warped: false,
fake: false,
second: 0,
quant: 4,
}
return new NoteWrapper(a)
}
const ns = this.noteskin
const col = this.getColumnName(note.col)
const opts = { note, columnName: col, columnNumber: note.col }
switch (note.type) {
case "Tap":
case "Lift":
Expand Down
10 changes: 1 addition & 9 deletions app/src/chart/gameTypes/noteskin/NoteskinRegistry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -210,15 +210,7 @@ NoteskinRegistry.register({
})
NoteskinRegistry.register({
id: "starlight-vivid",
gameTypes: [
"dance-single",
"dance-double",
"dance-couple",
"dance-solo",
"dance-solodouble",
"dance-threepanel",
"dance-threedouble",
],
gameTypes: ["dance-single", "dance-double", "dance-couple"],
path: "./dance/starlight-vivid",
title: "SLNEXXT-vivid",
subtitle: "from STARLiGHT-NEXXT",
Expand Down
19 changes: 10 additions & 9 deletions app/src/chart/gameTypes/noteskin/_template/HoldBody.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,15 +88,16 @@ export class AnimatedHoldBody extends HoldBody {

updateTexture() {
const currentFrame = this.currentFrame
this._previousFrame !== currentFrame &&
((this._previousFrame = currentFrame),
(this._texture = this._textures[currentFrame]),
(this._textureID = -1),
(this._textureTrimmedID = -1),
(this._cachedTint = 16777215),
(this.uvs = this._texture._uvs.uvsFloat32),
this.updateAnchor && this._anchor.copyFrom(this._texture.defaultAnchor),
this.onFrameChange?.(this.currentFrame))
if (this._previousFrame !== currentFrame) {
this._previousFrame = currentFrame
this.texture = this._textures[currentFrame]
this._textureID = -1
this._textureTrimmedID = -1
this._cachedTint = 16777215
this.uvs = this._texture._uvs.uvsFloat32
if (this.updateAnchor) this._anchor.copyFrom(this._texture.defaultAnchor)
this.onFrameChange?.(this.currentFrame)
}
}

destroy(options?: IDestroyOptions | boolean) {
Expand Down
17 changes: 6 additions & 11 deletions app/src/chart/gameTypes/noteskin/_template/HoldTail.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { IDestroyOptions, Texture, Ticker, UPDATE_PRIORITY } from "pixi.js"
import { VertCropSprite } from "../../../../util/VertCropSprite"
import { HoldBody } from "./HoldBody"

export class HoldTail extends VertCropSprite {
constructor(texture: Texture, holdWidth = 64) {
Expand All @@ -17,7 +16,7 @@ export class HoldTail extends VertCropSprite {
}
}

export class AnimatedHoldBody extends HoldBody {
export class AnimatedHoldTail extends HoldTail {
private _playing = false
private _autoUpdate = false
private _isConnectedToTicker = false
Expand Down Expand Up @@ -85,15 +84,11 @@ export class AnimatedHoldBody extends HoldBody {

updateTexture() {
const currentFrame = this.currentFrame
this._previousFrame !== currentFrame &&
((this._previousFrame = currentFrame),
(this._texture = this._textures[currentFrame]),
(this._textureID = -1),
(this._textureTrimmedID = -1),
(this._cachedTint = 16777215),
(this.uvs = this._texture._uvs.uvsFloat32),
this.updateAnchor && this._anchor.copyFrom(this._texture.defaultAnchor),
this.onFrameChange?.(this.currentFrame))
if (this._previousFrame !== currentFrame) {
this._previousFrame = currentFrame
this.texture = this._textures[currentFrame]
this.onFrameChange?.(this.currentFrame)
}
}

destroy(options?: IDestroyOptions | boolean) {
Expand Down
158 changes: 158 additions & 0 deletions app/src/chart/gameTypes/noteskin/_template/HoldTopCap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
import {
IDestroyOptions,
Sprite,
Texture,
Ticker,
UPDATE_PRIORITY,
} from "pixi.js"

export class HoldTopCap extends Sprite {
constructor(texture: Texture, holdWidth = 64, reverse = false) {
super(texture)
this.scale.set(holdWidth / this.texture.width)
this.anchor.x = 0.5
if (reverse) {
this.rotation = Math.PI
}
this.texture.on("update", () => {
this.scale.set(holdWidth / this.texture.width)
})
}
}

export class AnimatedHoldTopCap extends HoldTopCap {
private _playing = false
private _autoUpdate = false
private _isConnectedToTicker = false
private _tickerUpdate = this.update.bind(this)
private _currentTime = 0
private _textures!: Texture[]
private _previousFrame: number | null = null

onComplete: (() => void) | null = null
onLoop: (() => void) | null = null
onFrameChange: ((frame: number) => void) | null = null
animationSpeed = 1
loop = false
updateAnchor = false
constructor(textures: Texture[], holdWidth: number) {
super(textures[0], holdWidth)
this.textures = textures
}

stop() {
if (this._playing) {
this._playing = false
if (this._autoUpdate && this._isConnectedToTicker) {
Ticker.shared.remove(this._tickerUpdate)
this._isConnectedToTicker = false
}
}
}
play() {
if (!this._playing) {
this._playing = true
if (this._autoUpdate && !this._isConnectedToTicker) {
Ticker.shared.add(this._tickerUpdate, this, UPDATE_PRIORITY.HIGH)
this._isConnectedToTicker = true
}
}
}

gotoAndStop(frameNumber: number) {
this.stop()
this.currentFrame = frameNumber
}
gotoAndPlay(frameNumber: number) {
this.currentFrame = frameNumber
this.play()
}

update(deltaTime: number) {
if (!this._playing) return
const elapsed = this.animationSpeed * deltaTime,
previousFrame = this.currentFrame
this._currentTime += elapsed
this._currentTime < 0 && !this.loop
? (this.gotoAndStop(0), this.onComplete?.())
: this._currentTime >= this._textures.length && !this.loop
? (this.gotoAndStop(this._textures.length - 1), this.onComplete?.())
: previousFrame !== this.currentFrame &&
(this.loop &&
this.onLoop &&
((this.animationSpeed > 0 && this.currentFrame < previousFrame) ||
(this.animationSpeed < 0 && this.currentFrame > previousFrame)) &&
this.onLoop(),
this.updateTexture())
}

updateTexture() {
const currentFrame = this.currentFrame
if (this._previousFrame !== currentFrame) {
this._previousFrame = currentFrame
this.texture = this._textures[currentFrame]
this.onFrameChange?.(this.currentFrame)
}
}

destroy(options?: IDestroyOptions | boolean) {
this.stop(),
super.destroy(options),
(this.onComplete = null),
(this.onFrameChange = null),
(this.onLoop = null)
}

get totalFrames() {
return this._textures?.length ?? 0
}

get textures() {
return this._textures ?? []
}

set textures(value: Texture[]) {
this._textures = value
this._previousFrame = null
this.gotoAndStop(0)
this.updateTexture()
}

get currentFrame() {
let currentFrame = Math.floor(this._currentTime) % this._textures.length
return (
currentFrame < 0 && (currentFrame += this._textures.length), currentFrame
)
}

set currentFrame(value) {
if (value < 0 || value > this.totalFrames - 1)
throw new Error(
`[AnimatedSprite]: Invalid frame index value ${value}, expected to be between 0 and totalFrames ${this.totalFrames}.`
)
const previousFrame = this.currentFrame
;(this._currentTime = value),
previousFrame !== this.currentFrame && this.updateTexture()
}

get playing() {
return this._playing
}

get autoUpdate() {
return this._autoUpdate
}

set autoUpdate(value) {
value !== this._autoUpdate &&
((this._autoUpdate = value),
!this._autoUpdate && this._isConnectedToTicker
? (Ticker.shared.remove(this._tickerUpdate),
(this._isConnectedToTicker = !1))
: this._autoUpdate &&
!this._isConnectedToTicker &&
this._playing &&
(Ticker.shared.add(this._tickerUpdate),
(this._isConnectedToTicker = !0)))
}
}
Loading

0 comments on commit c89fbfd

Please sign in to comment.