Merge branch 'main' into internal-merge
# Conflicts: # .github/workflows/linux.yml # .github/workflows/macos.yml # .github/workflows/release.yml # .github/workflows/windows.yml # source/funkin/menus/FreeplayState.hx # source/openfl/utils/Assets.hx
This commit is contained in:
@@ -12,6 +12,8 @@ jobs:
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
|
||||
@@ -12,6 +12,8 @@ jobs:
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
|
||||
@@ -12,6 +12,8 @@ jobs:
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
|
||||
@@ -22,6 +22,8 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download Windows Full Build
|
||||
uses: dawidd6/action-download-artifact@v8
|
||||
|
||||
@@ -12,6 +12,8 @@ jobs:
|
||||
steps:
|
||||
- name: Pulling the new commit
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setting up Haxe
|
||||
uses: krdlab/setup-haxe@v2
|
||||
with:
|
||||
|
||||
@@ -165,6 +165,8 @@ class Flags {
|
||||
// Font configuration
|
||||
public static var DEFAULT_FONT:String = "vcr.ttf";
|
||||
public static var DEFAULT_FONT_SIZE:Int = 16;
|
||||
|
||||
public static var DEFAULT_ALT_ANIM_SUFFIX:String = "-alt";
|
||||
|
||||
// to translate these you need to convert them into ids
|
||||
// Resume -> pause.resume
|
||||
|
||||
@@ -440,11 +440,9 @@ final class CoolUtil
|
||||
* @param fadeIn
|
||||
*/
|
||||
@:noUsing public static function playMenuSong(fadeIn:Bool = false) {
|
||||
if (FlxG.sound.music == null || !FlxG.sound.music.playing)
|
||||
{
|
||||
if (FlxG.sound.music == null || !FlxG.sound.music.playing) {
|
||||
playMusic(Paths.music(Flags.DEFAULT_MENU_MUSIC), true, fadeIn ? 0 : 1, true, 102);
|
||||
if (fadeIn)
|
||||
FlxG.sound.music.fadeIn(4, 0, 0.7);
|
||||
if (fadeIn) FlxG.sound.music.fadeIn(4, 0, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,11 +146,10 @@ class CharterSelectionScreen extends EditorTreeMenuScreen {
|
||||
|
||||
var screen = parent.tree.last();
|
||||
var idx = 0;
|
||||
while (!(screen.members[idx] is Separator)) idx++;
|
||||
while (!(screen.members[idx] is Separator || idx >= screen.members.length)) idx++;
|
||||
screen.insert(idx, makeChartOption(name, curSong.variant != null && curSong.variant != "" ? curSong.variant : null, curSong.name));
|
||||
|
||||
// Add to Meta
|
||||
var metaPath = '$songFolder/meta${curSong.variant != null && curSong.variant == "" ? "-" + curSong.variant : ""}.json';
|
||||
var metaPath = '$songFolder/meta${curSong.variant != null && curSong.variant != "" ? "-" + curSong.variant : ""}.json';
|
||||
CoolUtil.safeSaveFile(metaPath, Chart.makeMetaSaveable(curSong));
|
||||
}
|
||||
#end
|
||||
|
||||
+80
-37
@@ -126,8 +126,7 @@ class Note extends FlxSprite
|
||||
|
||||
static var DEFAULT_FIELDS:Array<String> = ["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;
|
||||
override function set_clipRect(rect:FlxRect):FlxRect {
|
||||
@:bypassAccessor clipRect = rect;
|
||||
|
||||
if (frames != null)
|
||||
frame = frames.frames[animation.frameIndex];
|
||||
@: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;
|
||||
}
|
||||
|
||||
@@ -1657,7 +1657,7 @@ class PlayState extends MusicBeatState
|
||||
if (strLine.characters != null) // Alt anim Idle
|
||||
for (character in strLine.characters) {
|
||||
if (character == null) continue;
|
||||
character.idleSuffix = event.params[1] ? "-alt" : "";
|
||||
character.idleSuffix = event.params[1] ? strLine.defaultAnimSuffix : "";
|
||||
}
|
||||
}
|
||||
case "Play Animation":
|
||||
|
||||
+66
-19
@@ -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<String> = [];
|
||||
|
||||
private inline function set_extraCopyFields(val:Array<String>)
|
||||
return extraCopyFields = val == null ? [] : val;
|
||||
@:noCompletion public var __cachedCopyFields:Array<Array<OneOfTwo<String, Int>>> = null;
|
||||
|
||||
private function set_extraCopyFields(val:Array<String>) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
* Which animation suffix on characters that should be used when hitting notes.
|
||||
*/
|
||||
public var animSuffix(default, set):String = "";
|
||||
/**
|
||||
* The current animation suffix the strumline should use. Note that setting this will only take effect upon the alt. animation being reset.
|
||||
*/
|
||||
public var defaultAnimSuffix:String = Flags.DEFAULT_ALT_ANIM_SUFFIX;
|
||||
/**
|
||||
* TODO: Write documentation about this being a variable that can help when making multi key
|
||||
*/
|
||||
@@ -468,11 +472,11 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
return animSuffix = str;
|
||||
}
|
||||
private inline function set_altAnim(b:Bool):Bool {
|
||||
animSuffix = b ? "-alt" : "";
|
||||
animSuffix = b ? defaultAnimSuffix : "";
|
||||
return b;
|
||||
}
|
||||
private inline function get_altAnim():Bool {
|
||||
return animSuffix == "-alt";
|
||||
return animSuffix == defaultAnimSuffix;
|
||||
}
|
||||
#end
|
||||
}
|
||||
@@ -43,8 +43,8 @@ class Options
|
||||
public static var framerate:Int = 120;
|
||||
public static var gpuOnlyBitmaps:Bool = #if (mac || web) false #else true #end; // causes issues on mac and web
|
||||
public static var language = "en"; // default to english, Flags.DEFAULT_LANGUAGE should not modify this
|
||||
public static var streamedMusic:Bool = true;
|
||||
public static var streamedVocals:Bool = true;
|
||||
public static var streamedMusic:Bool = false;
|
||||
public static var streamedVocals:Bool = false;
|
||||
public static var quality:Int = 1;
|
||||
public static var allowConfigWarning:Bool = true;
|
||||
#if MODCHARTING_FEATURES
|
||||
|
||||
@@ -67,7 +67,14 @@ class AdvancedGameplayOptions extends TreeMenuScreen {
|
||||
public function new() {
|
||||
super('optionsMenu.advanced', 'optionsTree.gameplay.advanced-desc', 'GameplayOptions.Advanced.');
|
||||
|
||||
add(new Checkbox(getNameID('streamedMusic'), getDescID('streamedMusic'), 'streamedMusic'));
|
||||
add(new Checkbox(getNameID('streamedVocals'), getDescID('streamedVocals'), 'streamedVocals'));
|
||||
// Remove locked whenever this PR from FunkinCrew is merged.
|
||||
// https://github.com/FunkinCrew/lime/pull/57
|
||||
for (checkbox in [
|
||||
new Checkbox(getNameID('streamedMusic'), getDescID('streamedMusic'), 'streamedMusic'),
|
||||
new Checkbox(getNameID('streamedVocals'), getDescID('streamedVocals'), 'streamedVocals')
|
||||
]) {
|
||||
checkbox.locked = true;
|
||||
add(checkbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user