Merge branch 'new-editors' into zoro-charterstuffs
This commit is contained in:
@@ -170,16 +170,18 @@ function postUpdate(elapsed) {
|
||||
if (enableCameraHacks) {
|
||||
for(p in strumLines)
|
||||
p.notes.forEach(function(n) {
|
||||
if(n.isSustainNote) return; // hacky fix for hold
|
||||
n.y -= n.y % daPixelZoom;
|
||||
n.x -= n.x % daPixelZoom;
|
||||
});
|
||||
}
|
||||
|
||||
var zoom = 1 / daPixelZoom / Math.min(FlxG.scaleMode.scale.x, FlxG.scaleMode.scale.y);
|
||||
for(e in pixellyCameras) {
|
||||
if (!e.exists) continue;
|
||||
e.zoom = 1 / daPixelZoom / Math.min(FlxG.scaleMode.scale.x, FlxG.scaleMode.scale.y);
|
||||
e.zoom = zoom;
|
||||
}
|
||||
for(e in pixellyShaders) {
|
||||
e.pixelZoom = 1 / daPixelZoom / Math.min(FlxG.scaleMode.scale.x, FlxG.scaleMode.scale.y);
|
||||
e.pixelZoom = zoom;
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,8 @@ function confText(text) {
|
||||
}
|
||||
|
||||
function destroy() {
|
||||
FlxG.cameras.remove(pauseCam);
|
||||
if(FlxG.cameras.list.contains(pauseCam))
|
||||
FlxG.cameras.remove(pauseCam);
|
||||
}
|
||||
|
||||
var canDoShit = true;
|
||||
|
||||
@@ -150,6 +150,8 @@
|
||||
<!-- Comment this out to disable dark mode windows -->
|
||||
<define name="DARK_MODE_WINDOW"/>
|
||||
|
||||
<haxedef name="analyzer-optimize" />
|
||||
|
||||
<haxedef name="VIDEO_CUTSCENES" if="VIDEO_CUTSCENES" />
|
||||
<haxedef name="UPDATE_CHECKING" if="UPDATE_CHECKING" />
|
||||
<haxedef name="DISCORD_RPC" if="DISCORD_RPC" />
|
||||
|
||||
@@ -105,16 +105,15 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
||||
public override function update(elapsed:Float)
|
||||
{
|
||||
super.update(elapsed);
|
||||
if (animateAtlas != null)
|
||||
animateAtlas.update(elapsed);
|
||||
|
||||
// hate how it looks like but hey at least its optimized and fast - Nex
|
||||
if (!debugMode && isAnimFinished()) {
|
||||
var name = getAnimName() + '-loop';
|
||||
if (animation.exists(name))
|
||||
if (hasAnimation(name))
|
||||
playAnim(name, false, lastAnimContext);
|
||||
}
|
||||
|
||||
if (animateAtlas != null)
|
||||
animateAtlas.update(elapsed);
|
||||
}
|
||||
|
||||
public function loadSprite(path:String, Unique:Bool = false, Key:String = null)
|
||||
|
||||
@@ -14,8 +14,9 @@ final class EventManager {
|
||||
var index = eventKeys.indexOf(c);
|
||||
if (index < 0) {
|
||||
eventKeys.push(c);
|
||||
eventValues.push(Type.createInstance(c, []));
|
||||
return cast eventValues.last();
|
||||
var ret;
|
||||
eventValues.push(ret = Type.createInstance(c, []));
|
||||
return cast ret;
|
||||
}
|
||||
|
||||
return cast eventValues[index];
|
||||
|
||||
@@ -1,10 +1,38 @@
|
||||
package funkin.backend.scripting;
|
||||
|
||||
class ModState extends MusicBeatState {
|
||||
|
||||
/**
|
||||
* Name of HScript file in assets/data/states.
|
||||
*/
|
||||
public static var lastName:String = null;
|
||||
public function new(stateName:String) {
|
||||
if (stateName != null)
|
||||
lastName = stateName;
|
||||
/**
|
||||
* Last Optional extra data.
|
||||
*/
|
||||
public static var lastData:Dynamic = null;
|
||||
|
||||
/**
|
||||
* Optional extra data.
|
||||
*/
|
||||
public var data:Dynamic = null;
|
||||
|
||||
/**
|
||||
* ModState Constructor.
|
||||
* Inherits from MusicBeatState and allows the execution of an HScript from assets/data/states passed via parameters.
|
||||
*
|
||||
* @param _stateName Name or path to a HScript file from assets/data/states.
|
||||
* @param _data Optional extra Dynamic data passed from a previous state (JSON suggested).
|
||||
*/
|
||||
public function new(_stateName:String, ?_data:Dynamic) {
|
||||
if(_stateName != null && _stateName != lastName) {
|
||||
lastName = _stateName;
|
||||
lastData = null;
|
||||
}
|
||||
|
||||
if(_data != null)
|
||||
lastData = _data;
|
||||
|
||||
data = lastData;
|
||||
super(true, lastName);
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,38 @@
|
||||
package funkin.backend.scripting;
|
||||
|
||||
class ModSubState extends MusicBeatSubstate {
|
||||
|
||||
/**
|
||||
* Name of HScript file in assets/data/states.
|
||||
*/
|
||||
public static var lastName:String = null;
|
||||
public function new(stateName:String) {
|
||||
if (stateName != null)
|
||||
lastName = stateName;
|
||||
/**
|
||||
* Last Optional extra data.
|
||||
*/
|
||||
public static var lastData:Dynamic = null;
|
||||
|
||||
/**
|
||||
* Optional extra data.
|
||||
*/
|
||||
public var data:Dynamic = null;
|
||||
|
||||
/**
|
||||
* ModSubState Constructor.
|
||||
* Inherits from MusicBeatSubstate and allows the execution of an HScript from assets/data/states passed via parameters.
|
||||
*
|
||||
* @param _stateName Name or path to a HScript file from assets/data/states.
|
||||
* @param _data Optional extra Dynamic data passed from a previous state (JSON suggested).
|
||||
*/
|
||||
public function new(_stateName:String, ?_data:Dynamic) {
|
||||
if(_stateName != null && _stateName != lastName) {
|
||||
lastName = _stateName;
|
||||
lastData = null;
|
||||
}
|
||||
|
||||
if(_data != null)
|
||||
lastData = _data;
|
||||
|
||||
data = lastData;
|
||||
super(true, lastName);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package funkin.backend.system;
|
||||
|
||||
import lime.utils.AssetLibrary;
|
||||
import lime.utils.AssetType;
|
||||
|
||||
import funkin.backend.assets.IModsAssetLibrary;
|
||||
import funkin.backend.assets.ScriptedAssetLibrary;
|
||||
|
||||
/**
|
||||
* A class that reads the `flags.ini` file, allowing to read settable Flags (customs too).
|
||||
*/
|
||||
@:build(funkin.backend.system.macros.FlagMacro.build())
|
||||
class Flags {
|
||||
public static var SONGS_LIST_MOD_MODE:Allow<"prepend", "override", "append"> = "override";
|
||||
public static var WEEKS_LIST_MOD_MODE:Allow<"prepend", "override", "append"> = "override";
|
||||
|
||||
// Internal stuff
|
||||
|
||||
@:bypass public static var customFlags:Map<String, String> = [];
|
||||
|
||||
public static function load() {
|
||||
var flags:Map<String, String> = [];
|
||||
|
||||
final flagsPath = Paths.getPath("flags.ini");
|
||||
|
||||
for(lib in Paths.assetsTree.libraries) {
|
||||
if(lib.exists(flagsPath, AssetType.TEXT)) {
|
||||
var data:String = lib.getAsset(flagsPath, AssetType.TEXT);
|
||||
var trimmed:String;
|
||||
var splitContent = [for(e in data.split("\n")) if ((trimmed = e.trim()) != "") trimmed];
|
||||
|
||||
for(line in splitContent) {
|
||||
if (line.startsWith(";")) continue;
|
||||
if (line.startsWith("#")) continue;
|
||||
if (line.startsWith("//")) continue;
|
||||
if(line.length == 0) continue;
|
||||
if(line.charAt(0) == "[" && line.charAt(line.length-1) == "]") continue;
|
||||
|
||||
var index = line.indexOf("=");
|
||||
if(index == -1) continue;
|
||||
var name = line.substr(0, index).trim();
|
||||
var value = line.substr(index+1).trim();
|
||||
|
||||
if (value.length > 1 && value.charCodeAt(0) == '"'.code && value.charCodeAt(value.length-1) == '"'.code)
|
||||
value = value.substr(1, value.length - 2);
|
||||
|
||||
if (value.length == 0 || name.length == 0)
|
||||
continue;
|
||||
|
||||
if(!flags.exists(name))
|
||||
flags[name] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
customFlags = [];
|
||||
reset();
|
||||
for(name=>value in flags)
|
||||
if(!parse(name, value)) {
|
||||
customFlags.set(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import funkin.backend.assets.ModsFolder;
|
||||
import funkin.backend.chart.EventsData;
|
||||
import funkin.menus.BetaWarningState;
|
||||
import funkin.menus.TitleState;
|
||||
import funkin.backend.system.framerate.Framerate;
|
||||
|
||||
/**
|
||||
* Simple state used for loading the game
|
||||
@@ -56,11 +57,15 @@ class MainState extends FlxState {
|
||||
|
||||
Main.refreshAssets();
|
||||
ModsFolder.onModSwitch.dispatch(ModsFolder.currentModFolder);
|
||||
Flags.load();
|
||||
DiscordUtil.init();
|
||||
EventsData.reloadEvents();
|
||||
ControlsUtil.loadCustomControls();
|
||||
TitleState.initialized = false;
|
||||
|
||||
if(Framerate.isLoaded)
|
||||
Framerate.instance.reload();
|
||||
|
||||
if (betaWarningShown)
|
||||
FlxG.switchState(new TitleState());
|
||||
else {
|
||||
|
||||
@@ -9,6 +9,9 @@ class CodenameBuildField extends TextField {
|
||||
defaultTextFormat = Framerate.textFormat;
|
||||
autoSize = LEFT;
|
||||
multiline = wordWrap = false;
|
||||
text = 'Codename Engine ${Main.releaseCycle}\nCommit ${GitCommitMacro.commitNumber} (${GitCommitMacro.commitHash})';
|
||||
reload();
|
||||
}
|
||||
|
||||
public function reload()
|
||||
text = 'Codename Engine ${Main.releaseCycle}\nCommit ${GitCommitMacro.commitNumber} (${GitCommitMacro.commitHash})';
|
||||
}
|
||||
|
||||
@@ -82,6 +82,16 @@ class Framerate extends Sprite {
|
||||
#end
|
||||
}
|
||||
|
||||
public function reload() {
|
||||
for(c in categories)
|
||||
c.reload();
|
||||
#if SHOW_BUILD_ON_FPS
|
||||
codenameBuildField.reload();
|
||||
#end
|
||||
memoryCounter.reload();
|
||||
fpsCounter.reload();
|
||||
}
|
||||
|
||||
private function __addCategory(category:FramerateCategory) {
|
||||
categories.push(category);
|
||||
__addToList(category);
|
||||
|
||||
@@ -39,6 +39,8 @@ class FramerateCategory extends Sprite {
|
||||
this.text.y = this.title.y + this.title.height + 2;
|
||||
}
|
||||
|
||||
public function reload() {}
|
||||
|
||||
public override function __enterFrame(t:Int) {
|
||||
if (alpha <= 0.05) return;
|
||||
super.__enterFrame(t);
|
||||
|
||||
@@ -1,28 +1,17 @@
|
||||
package funkin.backend.system.framerate;
|
||||
|
||||
import haxe.ds.Vector;
|
||||
import openfl.display.Sprite;
|
||||
import openfl.text.TextField;
|
||||
import openfl.text.TextFormat;
|
||||
|
||||
inline final FRAME_TIME_HISTORY = 20;
|
||||
|
||||
class FramerateCounter extends Sprite {
|
||||
public var fpsNum:TextField;
|
||||
public var fpsLabel:TextField;
|
||||
|
||||
public var fpsHistoryIndex:Int = 0;
|
||||
public var fpsHistory:Vector<Float>;
|
||||
public var lastFPS:Float = 0;
|
||||
|
||||
public function new() {
|
||||
super();
|
||||
|
||||
fpsHistory = new Vector(FRAME_TIME_HISTORY);
|
||||
// Initialize to 60 FPS, so that the initial estimation until we get enough data is always reasonable.
|
||||
for(i in 0...FRAME_TIME_HISTORY) {
|
||||
fpsHistory[i] = 1000.0 / 60.0;
|
||||
}
|
||||
|
||||
fpsNum = new TextField();
|
||||
fpsLabel = new TextField();
|
||||
|
||||
@@ -37,24 +26,14 @@ class FramerateCounter extends Sprite {
|
||||
}
|
||||
}
|
||||
|
||||
public function reload() {}
|
||||
|
||||
public override function __enterFrame(t:Int) {
|
||||
if (alpha <= 0.05) return;
|
||||
super.__enterFrame(t);
|
||||
|
||||
// todo use gpu time
|
||||
fpsHistory[fpsHistoryIndex] = FlxG.elapsed * 1000;
|
||||
fpsHistoryIndex = (fpsHistoryIndex + 1) % FRAME_TIME_HISTORY;
|
||||
|
||||
// Calculate average CPU time.
|
||||
// Code based on Godot's FPS counter.
|
||||
var cpuTime = 0.0;
|
||||
for(i in 0...FRAME_TIME_HISTORY) {
|
||||
cpuTime += fpsHistory[i];
|
||||
}
|
||||
cpuTime /= FRAME_TIME_HISTORY;
|
||||
cpuTime = Math.max(0.01, cpuTime); // Prevent unrealistically low values.
|
||||
|
||||
fpsNum.text = Std.string(Math.floor(1000.0 / cpuTime));
|
||||
lastFPS = CoolUtil.fpsLerp(lastFPS, FlxG.elapsed == 0 ? 0 : (1 / FlxG.elapsed), 0.25);
|
||||
fpsNum.text = Std.string(Math.floor(lastFPS));
|
||||
fpsLabel.x = fpsNum.x + fpsNum.width;
|
||||
fpsLabel.y = (fpsNum.y + fpsNum.height) - fpsLabel.height;
|
||||
}
|
||||
|
||||
@@ -29,6 +29,8 @@ class MemoryCounter extends Sprite {
|
||||
memoryPeakText.alpha = 0.5;
|
||||
}
|
||||
|
||||
public function reload() {}
|
||||
|
||||
public override function __enterFrame(t:Int) {
|
||||
if (alpha <= 0.05) return;
|
||||
super.__enterFrame(t);
|
||||
|
||||
@@ -0,0 +1,211 @@
|
||||
package funkin.backend.system.macros;
|
||||
|
||||
import haxe.macro.Context;
|
||||
import haxe.macro.Expr;
|
||||
|
||||
using StringTools;
|
||||
|
||||
using haxe.macro.Tools;
|
||||
|
||||
class FlagMacro {
|
||||
public static function build():Array<Field> {
|
||||
var fields = Context.getBuildFields();
|
||||
|
||||
var clRef = Context.getLocalClass();
|
||||
if (clRef == null)
|
||||
return fields;
|
||||
|
||||
var cl = clRef.get();
|
||||
|
||||
var resetExprs:Array<Expr> = [];
|
||||
var parserExprs:Array<Expr> = [];
|
||||
|
||||
for (field in fields) {
|
||||
var skip = false;
|
||||
for(meta in field.meta) {
|
||||
if(meta.name == ":bypass") {
|
||||
skip = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(skip) continue;
|
||||
|
||||
switch (field.kind) {
|
||||
case FVar(type, expr):
|
||||
if(expr == null)
|
||||
Context.error('Flag ' + field.name + ' must have a default value', field.pos);
|
||||
switch(expr.expr) {
|
||||
case EConst(CIdent("true")) | EConst(CIdent("false")):
|
||||
type = macro: Bool;
|
||||
default:
|
||||
if(type == null)
|
||||
Context.error('Flag ' + field.name + ' must have a type', field.pos);
|
||||
}
|
||||
|
||||
var parser:Expr = null;
|
||||
var customCheck:Expr = null;
|
||||
|
||||
switch(type) {
|
||||
case macro: Array<TrimmedString>:
|
||||
field.kind = FVar(macro: Array<String>, expr);
|
||||
parser = macro value.split(",").map((e) -> e.trim());
|
||||
case macro: Array<String>:
|
||||
parser = macro value.split(",");
|
||||
case macro: Array<Bool>:
|
||||
parser = macro value.split(",").map((e) -> {
|
||||
e = e.trim();
|
||||
e == "true" || e == "t" || e == "1";
|
||||
});
|
||||
case macro: Int:
|
||||
parser = macro Std.parseInt(value);
|
||||
case macro: String:
|
||||
parser = macro value;
|
||||
case macro: Bool:
|
||||
parser = macro value == "true" || value == "t" || value == "1";
|
||||
case TPath({name: "Allow", pack: [], params: params}):
|
||||
final NONE = 0;
|
||||
final STRING = 1;
|
||||
final INT = 2;
|
||||
var chosenType = NONE;
|
||||
|
||||
var values:Array<String> = [];
|
||||
|
||||
for(param in params) {
|
||||
switch(param) {
|
||||
case TPExpr(e):
|
||||
switch(e.expr) {
|
||||
case EConst(CString(s, kind)):
|
||||
if(chosenType != NONE && chosenType != STRING)
|
||||
Context.error("Flag " + field.name + " Allow<> can only have one type", field.pos);
|
||||
chosenType = STRING;
|
||||
|
||||
values.push(s);
|
||||
case EConst(CInt(num)):
|
||||
if(chosenType != NONE && chosenType != INT)
|
||||
Context.error("Flag " + field.name + " Allow<> can only have one type", field.pos);
|
||||
chosenType = INT;
|
||||
|
||||
values.push(num);
|
||||
default:
|
||||
Context.error("Flag " + field.name + " Allow<> unknown type", field.pos);
|
||||
}
|
||||
default:
|
||||
Context.error("Flag " + field.name + " Unknown type when using Allow<>", field.pos);
|
||||
}
|
||||
}
|
||||
|
||||
var didFind = false;
|
||||
for(v in values) {
|
||||
switch(expr.expr) {
|
||||
case EConst(CString(s, kind)):
|
||||
if(v == s)
|
||||
didFind = true;
|
||||
case EConst(CInt(num)):
|
||||
if(v == num)
|
||||
didFind = true;
|
||||
default:
|
||||
}
|
||||
}
|
||||
if(!didFind)
|
||||
Context.error("Flag " + field.name + "'s Allow<> must have a default value that is allowed, " + expr.toString() + " is not allowed", field.pos);
|
||||
|
||||
if(chosenType == NONE)
|
||||
Context.error("Flag " + field.name + "'s Allow<> must have atleast one value", field.pos);
|
||||
|
||||
var errorMessage = 'Flag ${field.name} must be one of ${values.join(", ")}';
|
||||
|
||||
var checkExpr = macro value == $v{values.shift()};
|
||||
for(v in values)
|
||||
checkExpr = macro $checkExpr || value == $v{v};
|
||||
|
||||
if(chosenType == STRING) {
|
||||
parser = macro value;
|
||||
field.kind = FVar(macro: String, expr);
|
||||
}
|
||||
else if(chosenType == INT) {
|
||||
parser = macro Std.parseInt(value);
|
||||
field.kind = FVar(macro: Int, expr);
|
||||
} else {
|
||||
field.kind = FVar(macro: Any, expr);
|
||||
}
|
||||
|
||||
customCheck = macro @:mergeBlock {
|
||||
if(name == $v{field.name}) {
|
||||
if($checkExpr)
|
||||
$i{field.name} = $parser;
|
||||
else
|
||||
throw $v{errorMessage};
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
case TPath({name: "Array", pack: []}):
|
||||
Context.error("Flag " + field.name + " cannot be an Array that isnt a String or Bool or TrimmedString", field.pos);
|
||||
case TPath({name: "Map", pack: []}):
|
||||
Context.error("Flag " + field.name + " cannot be a Map<K, V>", field.pos);
|
||||
default:
|
||||
Context.error("Flag " + field.name + " must be either a Bool, Int, String, Array<String>, Array<Bool> or Array<TrimmedString>", field.pos);
|
||||
}
|
||||
|
||||
if(parser == null) {
|
||||
Context.error("Flag " + field.name + " must be either a Bool, Int, String, Array<String>, Array<Bool> or Array<TrimmedString>", field.pos);
|
||||
continue;
|
||||
}
|
||||
|
||||
resetExprs.push(macro $i{field.name} = ${expr});
|
||||
|
||||
// parse(name: String, value: String)
|
||||
|
||||
if(customCheck != null) {
|
||||
parserExprs.push(customCheck);
|
||||
} else {
|
||||
parserExprs.push(macro @:mergeBlock {
|
||||
if(name == $v{field.name}) {
|
||||
$i{field.name} = $parser;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
|
||||
fields.push({
|
||||
name: "reset",
|
||||
access: [APublic, AStatic],
|
||||
kind: FFun({
|
||||
args: [],
|
||||
expr: macro $b{resetExprs},
|
||||
ret: macro: Void
|
||||
}),
|
||||
pos: Context.currentPos(),
|
||||
doc: null,
|
||||
meta: []
|
||||
});
|
||||
|
||||
fields.push({
|
||||
name: "parse",
|
||||
access: [APublic, AStatic],
|
||||
kind: FFun({
|
||||
args: [{name: "name", type: macro: String}, {name: "value", type: macro: String}],
|
||||
expr: macro {
|
||||
@:mergeBlock $b{parserExprs};
|
||||
|
||||
return false;
|
||||
},
|
||||
ret: macro: Bool
|
||||
}),
|
||||
pos: Context.currentPos(),
|
||||
doc: null,
|
||||
meta: []
|
||||
});
|
||||
|
||||
//var printer = new haxe.macro.Printer();
|
||||
//trace(printer.printField(fields[fields.length - 2]));
|
||||
//trace(printer.printField(fields[fields.length - 1]));
|
||||
|
||||
return fields;
|
||||
}
|
||||
}
|
||||
@@ -32,8 +32,8 @@ class FunkinParentDisabler extends FlxBasic {
|
||||
FlxTimer.globalManager._timers = [];
|
||||
|
||||
// cameras
|
||||
__cameras = [for(c in FlxG.cameras.list) if (c.active) c];
|
||||
for(c in __cameras) c.active = false;
|
||||
__cameras = [for(c in FlxG.cameras.list) if (!c.paused) c];
|
||||
for(c in __cameras) c.paused = true;
|
||||
|
||||
// sounds
|
||||
__sounds = [for(s in FlxG.sound.list) if (s.playing) s];
|
||||
@@ -41,9 +41,6 @@ class FunkinParentDisabler extends FlxBasic {
|
||||
}
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
@:privateAccess for(c in __cameras) c.updateFlashSpritePosition();
|
||||
}
|
||||
public override function draw() {}
|
||||
|
||||
public function reset() {
|
||||
@@ -63,7 +60,7 @@ class FunkinParentDisabler extends FlxBasic {
|
||||
for(t in __tweens) FlxTween.globalManager._tweens.push(t);
|
||||
for(t in __timers) FlxTimer.globalManager._timers.push(t);
|
||||
}
|
||||
for(c in __cameras) c.active = true;
|
||||
for(c in __cameras) c.paused = false;
|
||||
for(s in __sounds) s.play();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ final class IniUtil {
|
||||
var name = line.substr(0, index).trim();
|
||||
var value = line.substr(index+1).trim();
|
||||
|
||||
if (value.startsWith("\"") && value.endsWith("\""))
|
||||
if (value.length > 1 && value.charCodeAt(0) == '"'.code && value.charCodeAt(value.length-1) == '"'.code)
|
||||
value = value.substr(1, value.length - 2);
|
||||
|
||||
if (value.length == 0 || name.length == 0)
|
||||
|
||||
@@ -48,10 +48,12 @@ class CharterEvent extends UISliceSprite implements ICharterSelectable {
|
||||
var isBase64:Bool = false;
|
||||
var path:String = Paths.image('editors/charter/event-icons/$name');
|
||||
if (!Assets.exists(path)) path = Paths.image('editors/charter/event-icons/Unknown');
|
||||
if (Assets.exists(Paths.pack('events/$name'))) {
|
||||
var packimg = Assets.getText(Paths.pack('events/$name')).split('________PACKSEP________')[3];
|
||||
var packPath = Paths.pack('events/$name');
|
||||
if (Assets.exists(packPath)) {
|
||||
var packText = Assets.getText(packPath).split('________PACKSEP________');
|
||||
var packimg = packText[3];
|
||||
if (isBase64 = (packimg != null))
|
||||
path = Assets.getText(Paths.pack('events/$name')).split('________PACKSEP________')[3];
|
||||
path = packText[3];
|
||||
}
|
||||
var spr = new FlxSprite().loadGraphic(isBase64 ? openfl.display.BitmapData.fromBase64(path.trim(), 'UTF8') : path);
|
||||
return spr;
|
||||
|
||||
@@ -80,8 +80,6 @@ class SongCreationScreen extends UISubstateWindow {
|
||||
stepsPerBeatStepper = new UINumericStepper(beatsPerMeasureStepper.x + 30 + 24, beatsPerMeasureStepper.y, 4, 1, 0, 1, null, 54);
|
||||
songDataGroup.add(stepsPerBeatStepper);
|
||||
|
||||
var voicesUIText:UIText = null;
|
||||
|
||||
instExplorer = new UIFileExplorer(songNameTextBox.x, songNameTextBox.y + 32 + 36, null, null, Paths.SOUND_EXT, function (res) {
|
||||
var audioPlayer:UIAudioPlayer = new UIAudioPlayer(instExplorer.x + 8, instExplorer.y + 8, res);
|
||||
instExplorer.members.push(audioPlayer);
|
||||
@@ -98,11 +96,7 @@ class SongCreationScreen extends UISubstateWindow {
|
||||
voicesExplorer.uiElement = audioPlayer;
|
||||
});
|
||||
songDataGroup.add(voicesExplorer);
|
||||
|
||||
voicesUIText = addLabelOn(voicesExplorer, "Vocal Audio File");
|
||||
voicesUIText.applyMarkup(
|
||||
"Vocal Audio File $* Required$",
|
||||
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]);
|
||||
addLabelOn(voicesExplorer, "Vocal Audio File");
|
||||
|
||||
var menuTitle:UIText;
|
||||
menuDataGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Menus Data (Freeplay/Story)", 28));
|
||||
|
||||
@@ -362,7 +362,7 @@ class PlayState extends MusicBeatState
|
||||
* Speed at which the game camera zoom lerps to.
|
||||
*/
|
||||
public var camGameZoomLerp:Float = 0.05;
|
||||
|
||||
|
||||
/**
|
||||
* Camera zoom at which the hud lerps to.
|
||||
*/
|
||||
@@ -653,14 +653,14 @@ class PlayState extends MusicBeatState
|
||||
chars.push(char);
|
||||
}
|
||||
|
||||
var strOffset:Float = strumLine.strumLinePos == null ? (strumLine.type == 1 ? 0.75 : 0.25) : strumLine.strumLinePos;
|
||||
var strumScale:Float = (strumLine.strumScale == null ? 1 : strumLine.strumScale);
|
||||
var strumSpacing:Float = (strumLine.strumSpacing == null ? 1 : strumLine.strumSpacing);
|
||||
var keyCount:Int = (strumLine.keyCount == null ? 4 : strumLine.keyCount);
|
||||
|
||||
var startingPos:FlxPoint = strumLine.strumPos == null ?
|
||||
FlxPoint.get(StrumLine.calculateStartingXPos(strOffset, strumScale, strumSpacing, keyCount), this.strumLine.y) :
|
||||
FlxPoint.get(strumLine.strumPos[0] == 0 ? StrumLine.calculateStartingXPos(strOffset, strumScale, strumSpacing, keyCount) : strumLine.strumPos[0], strumLine.strumPos[1]);
|
||||
var strOffset:Float = strumLine.strumLinePos != null ? strumLine.strumLinePos : (strumLine.type == 1 ? 0.75 : 0.25);
|
||||
var strScale:Float = strumLine.strumScale != null ? strumLine.strumScale : 1;
|
||||
var strSpacing:Float = strumLine.strumSpacing == null ? 1 : strumLine.strumSpacing;
|
||||
var keyCount:Int = strumLine.keyCount == null ? 4 : strumLine.keyCount;
|
||||
var strXPos:Float = StrumLine.calculateStartingXPos(strOffset, strScale, strSpacing, keyCount);
|
||||
var startingPos:FlxPoint = strumLine.strumPos != null ?
|
||||
FlxPoint.get(strumLine.strumPos[0] == 0 ? strXPos : strumLine.strumPos[0], strumLine.strumPos[1]) :
|
||||
FlxPoint.get(strXPos, this.strumLine.y);
|
||||
var strLine = new StrumLine(chars,
|
||||
startingPos,
|
||||
strumLine.strumScale == null ? 1 : strumLine.strumScale,
|
||||
|
||||
@@ -152,7 +152,8 @@ class StrumLine extends FlxTypedGroup<Strum> {
|
||||
var scrollSpeed = strumLine.scrollSpeed;
|
||||
if(scrollSpeed == null) if (PlayState.instance != null) scrollSpeed = PlayState.instance.scrollSpeed;
|
||||
if(scrollSpeed == null) scrollSpeed = 1;
|
||||
notes.limit = 1500 / scrollSpeed;
|
||||
var limit = FlxG.height / 0.45;
|
||||
notes.limit = limit / scrollSpeed;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
|
||||
@@ -22,6 +22,8 @@ import flixel.math.FlxMath;
|
||||
import flixel.tweens.FlxEase;
|
||||
import flixel.util.FlxDestroyUtil;
|
||||
|
||||
import funkin.backend.system.Flags;
|
||||
|
||||
import funkin.menus.ui.Alphabet;
|
||||
import flixel.group.FlxGroup.FlxTypedGroup;
|
||||
import flixel.group.FlxSpriteGroup.FlxTypedSpriteGroup;
|
||||
|
||||
@@ -465,8 +465,17 @@ class FreeplaySonglist {
|
||||
public static function get(useTxt:Bool = true) {
|
||||
var songList = new FreeplaySonglist();
|
||||
|
||||
if (songList.getSongsFromSource(MODS, useTxt))
|
||||
songList.getSongsFromSource(SOURCE, useTxt);
|
||||
switch(Flags.SONGS_LIST_MOD_MODE) {
|
||||
case 'prepend':
|
||||
songList.getSongsFromSource(MODS, useTxt);
|
||||
songList.getSongsFromSource(SOURCE, useTxt);
|
||||
case 'append':
|
||||
songList.getSongsFromSource(SOURCE, useTxt);
|
||||
songList.getSongsFromSource(MODS, useTxt);
|
||||
default /*case 'override'*/:
|
||||
if (songList.getSongsFromSource(MODS, useTxt))
|
||||
songList.getSongsFromSource(SOURCE, useTxt);
|
||||
}
|
||||
|
||||
return songList;
|
||||
}
|
||||
|
||||
@@ -199,14 +199,24 @@ class StoryMenuState extends MusicBeatState {
|
||||
}
|
||||
}
|
||||
|
||||
intendedScore = FunkinSave.getWeekHighscore(weeks[curWeek].name, weeks[curWeek].difficulties[curDifficulty]).score;
|
||||
intendedScore = FunkinSave.getWeekHighscore(weeks[curWeek].id, weeks[curWeek].difficulties[curDifficulty]).score;
|
||||
}
|
||||
|
||||
public function loadXMLs() {
|
||||
// CoolUtil.coolTextFile(Paths.txt('freeplaySonglist'));
|
||||
var weeks:Array<String> = [];
|
||||
if (getWeeksFromSource(weeks, MODS))
|
||||
getWeeksFromSource(weeks, SOURCE);
|
||||
|
||||
switch(Flags.WEEKS_LIST_MOD_MODE) {
|
||||
case 'prepend':
|
||||
getWeeksFromSource(weeks, MODS);
|
||||
getWeeksFromSource(weeks, SOURCE);
|
||||
case 'append':
|
||||
getWeeksFromSource(weeks, SOURCE);
|
||||
getWeeksFromSource(weeks, MODS);
|
||||
default /*case 'override'*/:
|
||||
if (getWeeksFromSource(weeks, MODS))
|
||||
getWeeksFromSource(weeks, SOURCE);
|
||||
}
|
||||
|
||||
for(k=>weekName in weeks) {
|
||||
var week:Access = null;
|
||||
@@ -344,8 +354,8 @@ class StoryMenuState extends MusicBeatState {
|
||||
}
|
||||
|
||||
typedef WeekData = {
|
||||
var name:String;
|
||||
var id:String;
|
||||
var name:String; // name SHOULD NOT be used for loading week highscores, its just the name on the right side of the week, remember that next time!! - Nex
|
||||
var id:String; // id IS instead for saving and loading!! - Nex
|
||||
var sprite:String;
|
||||
var chars:Array<String>;
|
||||
var songs:Array<WeekSong>;
|
||||
|
||||
Reference in New Issue
Block a user