diff --git a/source/funkin/backend/system/Flags.hx b/source/funkin/backend/system/Flags.hx index 2311ed1f..61422401 100644 --- a/source/funkin/backend/system/Flags.hx +++ b/source/funkin/backend/system/Flags.hx @@ -10,6 +10,8 @@ import funkin.backend.assets.ScriptedAssetLibrary; class Flags { public static var FPS_BUILD_TEXT:String = "Commit ${build} (${commit})"; + // Internal stuff + @:bypass public static var customFlags:Map = []; public static function load() { diff --git a/source/funkin/backend/system/macros/FlagMacro.macro.hx b/source/funkin/backend/system/macros/FlagMacro.macro.hx index 21ff7acf..b1093bd9 100644 --- a/source/funkin/backend/system/macros/FlagMacro.macro.hx +++ b/source/funkin/backend/system/macros/FlagMacro.macro.hx @@ -44,10 +44,11 @@ class FlagMacro { } var parser:Expr = null; + var customCheck:Expr = null; switch(type) { case macro: Array: - field.kind = FVar(macro: Array, macro expr); + field.kind = FVar(macro: Array, expr); parser = macro value.split(",").map((e) -> e.trim()); case macro: Array: parser = macro value.split(","); @@ -62,6 +63,67 @@ class FlagMacro { 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 = []; + + for(param in params) { + switch(param) { + case TPExpr(e): + switch(e.expr) { + case EConst(CString(s, kind)): + if(chosenType != NONE && chosenType != STRING) + Context.error("Flags Allow<> can only have one type", field.pos); + chosenType = STRING; + + values.push(s); + case EConst(CInt(num)): + if(chosenType != NONE && chosenType != INT) + Context.error("Flags Allow<> can only have one type", field.pos); + chosenType = INT; + + values.push(num); + default: + Context.error("Flags Allow<> unknown type", field.pos); + } + default: + Context.error("Flags must be either a Bool, Int, String, Array, Array or Array", field.pos); + } + } + + if(chosenType == NONE) + Context.error("Flags Allow<> must have a type", field.pos); + + var errorMessage = 'Flags ${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('Flags cannot be an Array that isnt a String or Bool or TrimmedString', field.pos); @@ -79,12 +141,17 @@ class FlagMacro { resetExprs.push(macro $i{field.name} = ${expr}); // parse(name: String, value: String) - parserExprs.push(macro @:mergeBlock { - if(name == $v{field.name}) { - $i{field.name} = $parser; - return true; - } - }); + + if(customCheck != null) { + parserExprs.push(customCheck); + } else { + parserExprs.push(macro @:mergeBlock { + if(name == $v{field.name}) { + $i{field.name} = $parser; + return true; + } + }); + } default: // nothing } @@ -120,6 +187,10 @@ class FlagMacro { meta: [] }); + //var printer = new haxe.macro.Printer(); + //trace(printer.printField(fields[fields.length - 2])); + //trace(printer.printField(fields[fields.length - 1])); + return fields; } } \ No newline at end of file