diff --git a/source/funkin/game/Note.hx b/source/funkin/game/Note.hx index 82879bd3d..e3d88625a 100644 --- a/source/funkin/game/Note.hx +++ b/source/funkin/game/Note.hx @@ -126,8 +126,7 @@ class Note extends FlxSprite static var DEFAULT_FIELDS:Array = ["time", "id", "type", "sLen"]; - public function new(strumLine:StrumLine, noteData:ChartNote, sustain:Bool = false, sustainLength:Float = 0, sustainOffset:Float = 0, ?prev:Note) - { + public function new(strumLine:StrumLine, noteData:ChartNote, sustain:Bool = false, sustainLength:Float = 0, sustainOffset:Float = 0, ?prev:Note) { super(); moves = false; @@ -241,23 +240,13 @@ class Note extends FlxSprite */ public var strumRelativePos:Bool = true; - override function drawComplex(camera:FlxCamera) { - var downscrollCam = (camera is HudCamera ? ({var _:HudCamera=cast camera;_;}).downscroll : false); - if (updateFlipY) flipY = (isSustainNote && flipSustain) && (downscrollCam != (__strum != null && __strum.getScrollSpeed(this) < 0)); - if (downscrollCam && __strum != null) { - final xx = x; - x += origin.x - offset.x; - x -= __strum.x; x *= -1; x += __strum.x; - x -= origin.x - offset.x; - x += __strum.width; // ??? maybe this isnt good - super.drawComplex(camera); - x = xx; - } else - super.drawComplex(camera); - } - - static var __notePosFrameOffset:FlxPoint = new FlxPoint(); - static var __posPoint:FlxPoint = new FlxPoint(); + @:dox(hide) static var __lastAngle:Float = Math.NaN; + @:dox(hide) static var __lastAngleSin:Float = 0; + @:dox(hide) static var __lastAngleCos:Float = 0; + @:dox(hide) static var __lastStrumW:Float = Math.NaN; + @:dox(hide) static var __lastStrumH:Float = Math.NaN; + @:dox(hide) static var __lastStrumHalfW:Float = 0; + @:dox(hide) static var __lastStrumHalfH:Float = 0; override function draw() { @:privateAccess var oldDefaultCameras = FlxCamera._defaultCameras; @@ -266,16 +255,28 @@ class Note extends FlxSprite var negativeScroll = isSustainNote && strumRelativePos && lastScrollSpeed < 0; if (negativeScroll) y -= height; if (__strum != null && strumRelativePos) { - final pos = __posPoint.set(x, y); - // distance = pos.y , we can use it safely like this - final xx = -origin.x + offset.x + (pos.y * Math.cos((__noteAngle + 90) * FlxAngle.TO_RAD)); - final yy = -origin.y + offset.y + (pos.y * Math.sin((__noteAngle + 90) * FlxAngle.TO_RAD)); - setPosition( - xx + __strum.x + (__strum.width * 0.5), - yy + __strum.y + (__strum.height * 0.5) - ); + final originalX = x; + final originalY = y; + + if (__noteAngle != __lastAngle) { + __lastAngle = __noteAngle; + final result = FlxMath.fastSinCos((__noteAngle + 90) * FlxAngle.TO_RAD); + __lastAngleSin = result.sin; + __lastAngleCos = result.cos; + } + + if (__strum.width != __lastStrumW || __strum.height != __lastStrumH) { + __lastStrumW = __strum.width; + __lastStrumH = __strum.height; + __lastStrumHalfW = __strum.width * 0.5; + __lastStrumHalfH = __strum.height * 0.5; + } + + x = -origin.x + offset.x + (originalY * __lastAngleCos) + __strum.x + __lastStrumHalfW; + y = -origin.y + offset.y + (originalY * __lastAngleSin) + __strum.y + __lastStrumHalfH; super.draw(); - setPosition(pos.x, pos.y); + x = originalX; + y = originalY; } else { super.draw(); } @@ -284,6 +285,38 @@ class Note extends FlxSprite @:privateAccess FlxCamera._defaultCameras = oldDefaultCameras; } + var __lastDownscrollCam:Bool = false; + var __lastX:Float = 0; + + @:noCompletion @:dox(hide) override function isOnScreen(?camera:FlxCamera):Bool { + var downscrollCam = (Std.isOfType(camera, HudCamera) ? cast(camera, HudCamera).downscroll : false); + + if (downscrollCam == __lastDownscrollCam) + return super.isOnScreen(camera); + else + __lastX = x; + + if (updateFlipY) flipY = (isSustainNote && flipSustain) && (downscrollCam != (__strum != null && __strum.getScrollSpeed(this) < 0)); + if (downscrollCam && __strum != null) { + x = -x + 2 * (__strum.x - origin.x + offset.x) + __strum.width; + } + final isOnScreen = super.isOnScreen(camera); + return isOnScreen; + } + + override function drawComplex(camera:FlxCamera):Void { + super.drawComplex(camera); + + if (__lastDownscrollCam) { + __lastDownscrollCam = false; + x = __lastX; + } + } + + public function isOnScreenOriginal(?camera:FlxCamera):Bool { + return super.isOnScreen(camera); + } + // The * 0.5 is so that it's easier to hit them too late, instead of too early public var earlyPressWindow:Float = 0.5; public var latePressWindow:Float = 1; @@ -294,7 +327,7 @@ class Note extends FlxSprite if (lastScrollSpeed != scrollSpeed) { lastScrollSpeed = scrollSpeed; if (nextSustain != null) { - scale.y = (sustainLength * 0.45 * Math.abs(scrollSpeed)) / frameHeight; + scale.y = (sustainLength * 0.45 * scrollSpeed) / frameHeight; updateHitbox(); scale.y += gapFix / frameHeight; } @@ -304,18 +337,28 @@ class Note extends FlxSprite } public function updateSustainClip() if (wasGoodHit && !noSustainClip) { - var t = CoolUtil.bound((Conductor.songPosition - strumTime) / height * 0.45 * Math.abs(lastScrollSpeed), 0, 1); - var rect = clipRect == null ? FlxRect.get() : clipRect; - clipRect = rect.set(0, frameHeight * t, frameWidth, frameHeight * (1 - t)); + var t = CoolUtil.bound((Conductor.songPosition - strumTime) / height * 0.45 * lastScrollSpeed, 0, 1); + @:bypassAccessor { + if (clipRect == null) clipRect = FlxRect.get(); + clipRect.set(0, frameHeight * t, frameWidth, frameHeight * (1 - t)); + } + @:privateAccess { + if (frame != null && _frame != null) + _frame = frame.clipTo(clipRect, _frame); + } } @:noCompletion - override function set_clipRect(rect:FlxRect):FlxRect - { - clipRect = rect; - - if (frames != null) - frame = frames.frames[animation.frameIndex]; + override function set_clipRect(rect:FlxRect):FlxRect { + @:bypassAccessor clipRect = rect; + + @:privateAccess if (frame != null) { + if (rect != null && _frame != null) + _frame = frame.clipTo(rect, _frame); + else if (_frame != null) + _frame = frame.copyTo(_frame); + dirty = true; + } return rect; } diff --git a/source/funkin/game/Strum.hx b/source/funkin/game/Strum.hx index b075aad85..ede6360fe 100644 --- a/source/funkin/game/Strum.hx +++ b/source/funkin/game/Strum.hx @@ -2,6 +2,7 @@ package funkin.game; import flixel.math.FlxPoint; import flixel.math.FlxAngle; +import flixel.util.typeLimit.OneOfTwo; import funkin.backend.system.Conductor; class Strum extends FlxSprite { @@ -52,8 +53,27 @@ class Strum extends FlxSprite { public var updateNotesPosY:Bool = true; public var extraCopyFields(default, set):Array = []; - private inline function set_extraCopyFields(val:Array) - return extraCopyFields = val == null ? [] : val; + @:noCompletion public var __cachedCopyFields:Array>> = null; + + private function set_extraCopyFields(val:Array) { + extraCopyFields = val == null ? [] : val; + __cachedCopyFields = null; + return extraCopyFields; + } + + private inline function __initCachedCopyFields() { + if (__cachedCopyFields != null) return; + __cachedCopyFields = [for (field in extraCopyFields) CoolUtil.parsePropertyString(field)]; + } + + private inline function __applyCopyFields(daNote:Note) { + for (i in 0...extraCopyFields.length) { + final parsed = __cachedCopyFields[i]; + final fromProp = CoolUtil.parseProperty(this, parsed); + final toProp = CoolUtil.parseProperty(daNote, parsed); + toProp.setValue(fromProp.getValue()); + } + } /** * Whenever the strum is pressed. @@ -129,13 +149,28 @@ class Strum extends FlxSprite { } public override function draw() { - lastDrawCameras = cameras.copy(); + if (cameras.length == 1) { + if (lastDrawCameras.length != 1 || lastDrawCameras[0] != cameras[0]) { + lastDrawCameras = [cameras[0]]; + } + } else { + lastDrawCameras = cameras.copy(); + } super.draw(); } @:noCompletion public static inline final PIX180:Float = 565.4866776461628; // 180 * Math.PI @:noCompletion public static final N_WIDTHDIV2:Float = Note.swagWidth / 2; // DEPRECATED + static var __lastStrumW:Float = Math.NaN; + static var __lastStrumH:Float = Math.NaN; + static var __lastStrumHalfW:Float = 0; + static var __lastStrumHalfH:Float = 0; + static var __noteOffset:FlxPoint = FlxPoint.get(); + static var __lastNoteAngle:Float = Math.NaN; + static var __lastAngleCos:Float = 0; + static var __lastAngleSin:Float = 0; + /** * Updates the position of a note. * @param daNote The note @@ -153,8 +188,10 @@ class Strum extends FlxSprite { } updateNotePos(daNote); - for (field in extraCopyFields) - CoolUtil.cloneProperty(daNote, field, this); // TODO: make this cached to reduce the reflection calls - Neo + if (extraCopyFields.length > 0) { + __initCachedCopyFields(); + __applyCopyFields(daNote); + } } private inline function updateNotePos(daNote:Note) { @@ -169,24 +206,34 @@ class Strum extends FlxSprite { if (daNote.isSustainNote) daNote.y += daNote.height * 0.5; } } else { + if (width != __lastStrumW || height != __lastStrumH) { + __lastStrumW = width; + __lastStrumH = height; + __lastStrumHalfW = width * 0.5; + __lastStrumHalfH = height * 0.5; + } + + if (daNote.__noteAngle != __lastNoteAngle) { + __lastNoteAngle = daNote.__noteAngle; + final result = FlxMath.fastSinCos((__lastNoteAngle + 90) * FlxAngle.TO_RAD); + __lastAngleCos = result.cos; + __lastAngleSin = result.sin; + } + final speed = getScrollSpeed(daNote); final distance = (daNote.strumTime - Conductor.songPosition) * 0.45 * speed; - final __noteAngle = FlxMath.fastSinCos((daNote.__noteAngle + 90) * FlxAngle.TO_RAD); - final angleX = __noteAngle.cos; - final angleY = __noteAngle.sin; - final _noteOffset = FlxPoint.get(angleX * distance, angleY * distance); - _noteOffset.x += -daNote.origin.x + daNote.offset.x; - _noteOffset.y += -daNote.origin.y + daNote.offset.y; + __noteOffset.set(__lastAngleCos * distance, __lastAngleSin * distance); + __noteOffset.x += -daNote.origin.x + daNote.offset.x; + __noteOffset.y += -daNote.origin.y + daNote.offset.y; if (daNote.isSustainNote) { - final m = (daNote.height * 0.5 * (speed < 0 ? -1 : 1)); // daNote.height works better than this.height in this case ??? - _noteOffset.x += angleX * m; - _noteOffset.y += angleY * m; + final m = (daNote.height * 0.5 * (speed < 0 ? -1 : 1)); + __noteOffset.x += __lastAngleCos * m; + __noteOffset.y += __lastAngleSin * m; } - _noteOffset.x += x + (width * 0.5); - _noteOffset.y += y + (height * 0.5); - if (shouldX) daNote.x = _noteOffset.x; - if (shouldY) daNote.y = _noteOffset.y; - _noteOffset.put(); + __noteOffset.x += x + __lastStrumHalfW; + __noteOffset.y += y + __lastStrumHalfH; + if (shouldX) daNote.x = __noteOffset.x; + if (shouldY) daNote.y = __noteOffset.y; } } }