Cleaned up some code
This commit is contained in:
@@ -4,66 +4,66 @@ import openfl.display.BitmapData;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
class BitmapUtil {
|
||||
/**
|
||||
* Returns the most present color in a Bitmap.
|
||||
* @param bmap Bitmap
|
||||
* @return FlxColor Color that is the most present.
|
||||
*/
|
||||
public static function getMostPresentColor(bmap:BitmapData):FlxColor {
|
||||
// map containing all the colors and the number of times they've been assigned.
|
||||
var colorMap:Map<FlxColor, Float> = [];
|
||||
var color:FlxColor = 0;
|
||||
var fixedColor:FlxColor = 0;
|
||||
/**
|
||||
* Returns the most present color in a Bitmap.
|
||||
* @param bmap Bitmap
|
||||
* @return FlxColor Color that is the most present.
|
||||
*/
|
||||
public static function getMostPresentColor(bmap:BitmapData):FlxColor {
|
||||
// map containing all the colors and the number of times they've been assigned.
|
||||
var colorMap:Map<FlxColor, Float> = [];
|
||||
var color:FlxColor = 0;
|
||||
var fixedColor:FlxColor = 0;
|
||||
|
||||
for(y in 0...bmap.height) {
|
||||
for(x in 0...bmap.width) {
|
||||
color = bmap.getPixel32(x, y);
|
||||
fixedColor = 0xFF000000 + (color % 0x1000000);
|
||||
if (colorMap[fixedColor] == null)
|
||||
colorMap[fixedColor] = 0;
|
||||
colorMap[fixedColor] += color.alphaFloat;
|
||||
}
|
||||
}
|
||||
for(y in 0...bmap.height) {
|
||||
for(x in 0...bmap.width) {
|
||||
color = bmap.getPixel32(x, y);
|
||||
fixedColor = 0xFF000000 + (color % 0x1000000);
|
||||
if (colorMap[fixedColor] == null)
|
||||
colorMap[fixedColor] = 0;
|
||||
colorMap[fixedColor] += color.alphaFloat;
|
||||
}
|
||||
}
|
||||
|
||||
var mostPresentColor:FlxColor = 0;
|
||||
var mostPresentColorCount:Float = -1;
|
||||
for(c=>n in colorMap) {
|
||||
if (n > mostPresentColorCount) {
|
||||
mostPresentColorCount = n;
|
||||
mostPresentColor = c;
|
||||
}
|
||||
}
|
||||
return mostPresentColor;
|
||||
}
|
||||
/**
|
||||
* Returns the most present saturated color in a Bitmap.
|
||||
* @param bmap Bitmap
|
||||
* @return FlxColor Color that is the most present.
|
||||
*/
|
||||
public static function getMostPresentSaturatedColor(bmap:BitmapData):FlxColor {
|
||||
// map containing all the colors and the number of times they've been assigned.
|
||||
var colorMap:Map<FlxColor, Float> = [];
|
||||
var color:FlxColor = 0;
|
||||
var fixedColor:FlxColor = 0;
|
||||
var mostPresentColor:FlxColor = 0;
|
||||
var mostPresentColorCount:Float = -1;
|
||||
for(c=>n in colorMap) {
|
||||
if (n > mostPresentColorCount) {
|
||||
mostPresentColorCount = n;
|
||||
mostPresentColor = c;
|
||||
}
|
||||
}
|
||||
return mostPresentColor;
|
||||
}
|
||||
/**
|
||||
* Returns the most present saturated color in a Bitmap.
|
||||
* @param bmap Bitmap
|
||||
* @return FlxColor Color that is the most present.
|
||||
*/
|
||||
public static function getMostPresentSaturatedColor(bmap:BitmapData):FlxColor {
|
||||
// map containing all the colors and the number of times they've been assigned.
|
||||
var colorMap:Map<FlxColor, Float> = [];
|
||||
var color:FlxColor = 0;
|
||||
var fixedColor:FlxColor = 0;
|
||||
|
||||
for(y in 0...bmap.height) {
|
||||
for(x in 0...bmap.width) {
|
||||
color = bmap.getPixel32(x, y);
|
||||
fixedColor = 0xFF000000 + (color % 0x1000000);
|
||||
if (colorMap[fixedColor] == null)
|
||||
colorMap[fixedColor] = 0;
|
||||
colorMap[fixedColor] += color.alphaFloat * 0.33 + (0.67 * (color.saturation * (2 * (color.lightness > 0.5 ? 0.5 - (color.lightness) : color.lightness))));
|
||||
}
|
||||
}
|
||||
for(y in 0...bmap.height) {
|
||||
for(x in 0...bmap.width) {
|
||||
color = bmap.getPixel32(x, y);
|
||||
fixedColor = 0xFF000000 + (color % 0x1000000);
|
||||
if (colorMap[fixedColor] == null)
|
||||
colorMap[fixedColor] = 0;
|
||||
colorMap[fixedColor] += color.alphaFloat * 0.33 + (0.67 * (color.saturation * (2 * (color.lightness > 0.5 ? 0.5 - (color.lightness) : color.lightness))));
|
||||
}
|
||||
}
|
||||
|
||||
var mostPresentColor:FlxColor = 0;
|
||||
var mostPresentColorCount:Float = -1;
|
||||
for(c=>n in colorMap) {
|
||||
if (n > mostPresentColorCount) {
|
||||
mostPresentColorCount = n;
|
||||
mostPresentColor = c;
|
||||
}
|
||||
}
|
||||
return mostPresentColor;
|
||||
}
|
||||
var mostPresentColor:FlxColor = 0;
|
||||
var mostPresentColorCount:Float = -1;
|
||||
for(c=>n in colorMap) {
|
||||
if (n > mostPresentColorCount) {
|
||||
mostPresentColorCount = n;
|
||||
mostPresentColor = c;
|
||||
}
|
||||
}
|
||||
return mostPresentColor;
|
||||
}
|
||||
}
|
||||
+111
-111
@@ -11,142 +11,142 @@ import lime.app.Application;
|
||||
#end
|
||||
|
||||
class DiscordUtil {
|
||||
public static var currentID:String = null;
|
||||
public static var discordThread:#if DISCORD_RPC Thread #else Dynamic #end = null;
|
||||
public static var ready:Bool = false;
|
||||
public static var data:DiscordJson = null;
|
||||
public static var currentID:String = null;
|
||||
public static var discordThread:#if DISCORD_RPC Thread #else Dynamic #end = null;
|
||||
public static var ready:Bool = false;
|
||||
public static var data:DiscordJson = null;
|
||||
|
||||
public static function init() {
|
||||
#if DISCORD_RPC
|
||||
reloadJsonData();
|
||||
discordThread = Thread.create(function() {
|
||||
while (true)
|
||||
{
|
||||
while(!ready) {
|
||||
Sys.sleep(1/60);
|
||||
}
|
||||
trace("Processing Discord RPC...");
|
||||
DiscordRpc.process();
|
||||
Sys.sleep(2);
|
||||
}
|
||||
});
|
||||
|
||||
public static function init() {
|
||||
#if DISCORD_RPC
|
||||
reloadJsonData();
|
||||
discordThread = Thread.create(function() {
|
||||
while (true)
|
||||
{
|
||||
while(!ready) {
|
||||
Sys.sleep(1/60);
|
||||
}
|
||||
trace("Processing Discord RPC...");
|
||||
DiscordRpc.process();
|
||||
Sys.sleep(2);
|
||||
}
|
||||
});
|
||||
|
||||
Application.current.onExit.add(function(exitCode) {
|
||||
shutdown();
|
||||
});
|
||||
#end
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
public static function reloadJsonData() {
|
||||
#if DISCORD_RPC
|
||||
data = {};
|
||||
var jsonPath = Paths.json("config/discord");
|
||||
if (Assets.exists(jsonPath)) {
|
||||
try {
|
||||
data = Json.parse(Assets.getText(jsonPath));
|
||||
} catch(e) {
|
||||
Logs.trace('Couldn\'t load Discord RPC configuration: ${e.toString()}', ERROR);
|
||||
}
|
||||
}
|
||||
trace(data);
|
||||
data.setFieldDefault("clientID", "1027994136193810442");
|
||||
data.setFieldDefault("logoKey", "icon");
|
||||
data.setFieldDefault("logoText", Application.current.meta.get('title'));
|
||||
public static function reloadJsonData() {
|
||||
#if DISCORD_RPC
|
||||
data = {};
|
||||
var jsonPath = Paths.json("config/discord");
|
||||
if (Assets.exists(jsonPath)) {
|
||||
try {
|
||||
data = Json.parse(Assets.getText(jsonPath));
|
||||
} catch(e) {
|
||||
Logs.trace('Couldn\'t load Discord RPC configuration: ${e.toString()}', ERROR);
|
||||
}
|
||||
}
|
||||
trace(data);
|
||||
data.setFieldDefault("clientID", "1027994136193810442");
|
||||
data.setFieldDefault("logoKey", "icon");
|
||||
data.setFieldDefault("logoText", Application.current.meta.get('title'));
|
||||
|
||||
changeClientID(data.clientID);
|
||||
#end
|
||||
}
|
||||
changeClientID(data.clientID);
|
||||
#end
|
||||
}
|
||||
|
||||
public static function changePresence(details:String, state:String, ?smallImageKey : String) {
|
||||
#if DISCORD_RPC
|
||||
changePresenceAdvanced({
|
||||
state: state,
|
||||
details: details,
|
||||
smallImageKey: smallImageKey
|
||||
});
|
||||
#end
|
||||
}
|
||||
public static function changePresence(details:String, state:String, ?smallImageKey : String) {
|
||||
#if DISCORD_RPC
|
||||
changePresenceAdvanced({
|
||||
state: state,
|
||||
details: details,
|
||||
smallImageKey: smallImageKey
|
||||
});
|
||||
#end
|
||||
}
|
||||
|
||||
public static function changeSongPresence(details:String, state:String, audio:FlxSound, ?smallImageKey : String) {
|
||||
#if DISCORD_RPC
|
||||
var start:Float = 0;
|
||||
var end:Float = 0;
|
||||
public static function changeSongPresence(details:String, state:String, audio:FlxSound, ?smallImageKey : String) {
|
||||
#if DISCORD_RPC
|
||||
var start:Float = 0;
|
||||
var end:Float = 0;
|
||||
|
||||
if (audio != null && audio.playing) {
|
||||
start = Date.now().getTime();
|
||||
end = start + (audio.length - audio.time);
|
||||
}
|
||||
if (audio != null && audio.playing) {
|
||||
start = Date.now().getTime();
|
||||
end = start + (audio.length - audio.time);
|
||||
}
|
||||
|
||||
changePresenceAdvanced({
|
||||
state: state,
|
||||
details: details,
|
||||
smallImageKey: smallImageKey,
|
||||
startTimestamp: Std.int(start / 1000),
|
||||
endTimestamp: Std.int(end / 1000)
|
||||
});
|
||||
#end
|
||||
}
|
||||
changePresenceAdvanced({
|
||||
state: state,
|
||||
details: details,
|
||||
smallImageKey: smallImageKey,
|
||||
startTimestamp: Std.int(start / 1000),
|
||||
endTimestamp: Std.int(end / 1000)
|
||||
});
|
||||
#end
|
||||
}
|
||||
|
||||
public static function changePresenceAdvanced(data:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end) {
|
||||
#if DISCORD_RPC
|
||||
if (data == null) return;
|
||||
public static function changePresenceAdvanced(data:#if DISCORD_RPC DiscordPresenceOptions #else Dynamic #end) {
|
||||
#if DISCORD_RPC
|
||||
if (data == null) return;
|
||||
|
||||
if (data.largeImageKey == null)
|
||||
data.largeImageKey = DiscordUtil.data.logoKey;
|
||||
if (data.largeImageText == null)
|
||||
data.largeImageText = DiscordUtil.data.logoText;
|
||||
|
||||
#if GLOBAL_SCRIPT
|
||||
var event = funkin.scripting.GlobalScript.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data));
|
||||
if (event.cancelled) return;
|
||||
|
||||
#end
|
||||
DiscordRpc.presence(data);
|
||||
#end
|
||||
}
|
||||
public static function changeClientID(id:String) {
|
||||
#if DISCORD_RPC
|
||||
if (currentID != null) {
|
||||
DiscordRpc.shutdown();
|
||||
}
|
||||
if (data.largeImageKey == null)
|
||||
data.largeImageKey = DiscordUtil.data.logoKey;
|
||||
if (data.largeImageText == null)
|
||||
data.largeImageText = DiscordUtil.data.logoText;
|
||||
|
||||
ready = false;
|
||||
#if GLOBAL_SCRIPT
|
||||
var event = funkin.scripting.GlobalScript.event("onDiscordPresenceUpdate", EventManager.get(DiscordPresenceUpdateEvent).recycle(data));
|
||||
if (event.cancelled) return;
|
||||
|
||||
DiscordRpc.start({
|
||||
#end
|
||||
DiscordRpc.presence(data);
|
||||
#end
|
||||
}
|
||||
public static function changeClientID(id:String) {
|
||||
#if DISCORD_RPC
|
||||
if (currentID != null) {
|
||||
DiscordRpc.shutdown();
|
||||
}
|
||||
|
||||
ready = false;
|
||||
|
||||
DiscordRpc.start({
|
||||
clientID: id,
|
||||
onReady: function() {
|
||||
Logs.trace('Discord RPC started');
|
||||
ready = true;
|
||||
},
|
||||
Logs.trace('Discord RPC started');
|
||||
ready = true;
|
||||
},
|
||||
onError: onError,
|
||||
onDisconnected: onDisconnected
|
||||
});
|
||||
currentID = id;
|
||||
currentID = id;
|
||||
|
||||
#end
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
public static function shutdown() {
|
||||
#if DISCORD_RPC
|
||||
DiscordRpc.shutdown();
|
||||
#end
|
||||
}
|
||||
public static function shutdown() {
|
||||
#if DISCORD_RPC
|
||||
DiscordRpc.shutdown();
|
||||
#end
|
||||
}
|
||||
|
||||
|
||||
// HANDLERS
|
||||
#if DISCORD_RPC
|
||||
static function onError(_code:Int, _message:String) {
|
||||
Logs.trace('Discord RPC Error: ${_message} (Code: $_code)', ERROR);
|
||||
}
|
||||
// HANDLERS
|
||||
#if DISCORD_RPC
|
||||
static function onError(_code:Int, _message:String) {
|
||||
Logs.trace('Discord RPC Error: ${_message} (Code: $_code)', ERROR);
|
||||
}
|
||||
|
||||
static function onDisconnected(_code:Int, _message:String) {
|
||||
Logs.trace('Discord RPC Disconnected: ${_message} (Code: $_code)', WARNING);
|
||||
}
|
||||
#end
|
||||
static function onDisconnected(_code:Int, _message:String) {
|
||||
Logs.trace('Discord RPC Disconnected: ${_message} (Code: $_code)', WARNING);
|
||||
}
|
||||
#end
|
||||
}
|
||||
|
||||
typedef DiscordJson = {
|
||||
var ?clientID:String;
|
||||
var ?logoKey:String;
|
||||
var ?logoText:String;
|
||||
var ?clientID:String;
|
||||
var ?logoKey:String;
|
||||
var ?logoText:String;
|
||||
}
|
||||
@@ -4,12 +4,12 @@ import funkin.scripting.Script;
|
||||
import funkin.scripting.MultiThreadedScript;
|
||||
|
||||
class EngineUtil {
|
||||
/**
|
||||
* Starts a new multithreaded script.
|
||||
* This script will share all the variables with the current one, which means already existing callbacks will be replaced by new ones on conflict.
|
||||
* @param path
|
||||
*/
|
||||
public static function startMultithreadedScript(path:String) {
|
||||
return new MultiThreadedScript(path, Script.curScript);
|
||||
}
|
||||
/**
|
||||
* Starts a new multithreaded script.
|
||||
* This script will share all the variables with the current one, which means already existing callbacks will be replaced by new ones on conflict.
|
||||
* @param path
|
||||
*/
|
||||
public static function startMultithreadedScript(path:String) {
|
||||
return new MultiThreadedScript(path, Script.curScript);
|
||||
}
|
||||
}
|
||||
@@ -7,37 +7,37 @@ import flixel.util.FlxColor;
|
||||
* Gets rid of precision issues with `FlxColor.interpolate`
|
||||
*/
|
||||
class FlxInterpolateColor {
|
||||
public var red:Float = 0;
|
||||
public var green:Float = 0;
|
||||
public var blue:Float = 0;
|
||||
public var alpha:Float = 0;
|
||||
public var red:Float = 0;
|
||||
public var green:Float = 0;
|
||||
public var blue:Float = 0;
|
||||
public var alpha:Float = 0;
|
||||
|
||||
public var color(get, set):FlxColor;
|
||||
public var color(get, set):FlxColor;
|
||||
|
||||
private inline function get_color()
|
||||
return FlxColor.fromRGBFloat(red, green, blue, alpha);
|
||||
private inline function get_color()
|
||||
return FlxColor.fromRGBFloat(red, green, blue, alpha);
|
||||
|
||||
private inline function set_color(c:FlxColor):FlxColor {
|
||||
red = c.redFloat;
|
||||
green = c.greenFloat;
|
||||
blue = c.blueFloat;
|
||||
alpha = c.alphaFloat;
|
||||
return c;
|
||||
}
|
||||
private inline function set_color(c:FlxColor):FlxColor {
|
||||
red = c.redFloat;
|
||||
green = c.greenFloat;
|
||||
blue = c.blueFloat;
|
||||
alpha = c.alphaFloat;
|
||||
return c;
|
||||
}
|
||||
|
||||
public inline function toString()
|
||||
return '[FlxInterpolateColor - (R:${red} | G:${green} | B:${blue} | A:${alpha})]';
|
||||
public function new(color:FlxColor) {
|
||||
this.color = color;
|
||||
}
|
||||
public inline function toString()
|
||||
return '[FlxInterpolateColor - (R:${red} | G:${green} | B:${blue} | A:${alpha})]';
|
||||
public function new(color:FlxColor) {
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public function lerpTo(color:FlxColor, ratio:Float) {
|
||||
red = (color.redFloat - red) * ratio + red;
|
||||
public function lerpTo(color:FlxColor, ratio:Float) {
|
||||
red = (color.redFloat - red) * ratio + red;
|
||||
green = (color.greenFloat - green) * ratio + green;
|
||||
blue = (color.blueFloat - blue) * ratio + blue;
|
||||
alpha = (color.alphaFloat - alpha) * ratio + alpha;
|
||||
}
|
||||
}
|
||||
|
||||
public inline function fpsLerpTo(color:FlxColor, ratio:Float)
|
||||
lerpTo(color, ratio * 60 * FlxG.elapsed);
|
||||
public inline function fpsLerpTo(color:FlxColor, ratio:Float)
|
||||
lerpTo(color, ratio * 60 * FlxG.elapsed);
|
||||
}
|
||||
@@ -5,36 +5,36 @@ package funkin.utils;
|
||||
* DOESNT SUPPORT CATEGORIES YET!!
|
||||
*/
|
||||
class IniUtil {
|
||||
public static inline function parseAsset(assetPath:String, ?defaultVariables:Map<String, String>)
|
||||
return parseString(Assets.getText(assetPath), defaultVariables);
|
||||
public static inline function parseAsset(assetPath:String, ?defaultVariables:Map<String, String>)
|
||||
return parseString(Assets.getText(assetPath), defaultVariables);
|
||||
|
||||
public static function parseString(data:String, ?defaultVariables:Map<String, String>) {
|
||||
var trimmed:String;
|
||||
var splitContent = [for(e in data.split("\n")) if ((trimmed = e.trim()) != "") trimmed];
|
||||
|
||||
var finalMap:Map<String, String> = [];
|
||||
if (defaultVariables != null)
|
||||
for(k=>e in defaultVariables)
|
||||
finalMap[k] = e;
|
||||
public static function parseString(data:String, ?defaultVariables:Map<String, String>) {
|
||||
var trimmed:String;
|
||||
var splitContent = [for(e in data.split("\n")) if ((trimmed = e.trim()) != "") trimmed];
|
||||
|
||||
for(line in splitContent) {
|
||||
// comment
|
||||
if (line.startsWith(";")) continue;
|
||||
// categories; not supported yet
|
||||
if (line.startsWith("[") && line.endsWith("]")) continue;
|
||||
var finalMap:Map<String, String> = [];
|
||||
if (defaultVariables != null)
|
||||
for(k=>e in defaultVariables)
|
||||
finalMap[k] = e;
|
||||
|
||||
var index = line.indexOf("=");
|
||||
var name = line.substr(0, index).trim();
|
||||
var value = line.substr(index+1).trim();
|
||||
for(line in splitContent) {
|
||||
// comment
|
||||
if (line.startsWith(";")) continue;
|
||||
// categories; not supported yet
|
||||
if (line.startsWith("[") && line.endsWith("]")) continue;
|
||||
|
||||
if (value.startsWith("\"") && value.endsWith("\""))
|
||||
value = value.substr(1, value.length - 2);
|
||||
var index = line.indexOf("=");
|
||||
var name = line.substr(0, index).trim();
|
||||
var value = line.substr(index+1).trim();
|
||||
|
||||
if (value.length == 0 || name.length == 0)
|
||||
continue;
|
||||
|
||||
finalMap[name] = value;
|
||||
}
|
||||
return finalMap;
|
||||
}
|
||||
if (value.startsWith("\"") && value.endsWith("\""))
|
||||
value = value.substr(1, value.length - 2);
|
||||
|
||||
if (value.length == 0 || name.length == 0)
|
||||
continue;
|
||||
|
||||
finalMap[name] = value;
|
||||
}
|
||||
return finalMap;
|
||||
}
|
||||
}
|
||||
@@ -4,84 +4,84 @@ import flixel.util.FlxColor;
|
||||
import flixel.text.FlxText;
|
||||
|
||||
class MarkdownUtil {
|
||||
public static function applyMarkdownText(text:FlxText, str:String) {
|
||||
text.textField.htmlText = Markdown.markdownToHtml(prepareMarkdown(str));
|
||||
var changes:Array<FlxTextFormatMarkerPair> = [
|
||||
createAdvancedMarkerPair("{title}", 0xFFFFFFFF, text.size * 2, false, true, true),
|
||||
createAdvancedMarkerPair("{subtitle}", 0xFFFFFFFF, text.size * 1.5, false, true, true),
|
||||
createAdvancedMarkerPair("{subsubtitle}", 0xFFFFFFFF, text.size * 1.25, false, true, true),
|
||||
createAdvancedMarkerPair("{ident1}", 0xFFFFFFFF, null, false, false, false, text.size * 2, true),
|
||||
createAdvancedMarkerPair("{ident2}", 0xFFFFFFFF, null, false, false, false, text.size * 4, true),
|
||||
createAdvancedMarkerPair("{ident3}", 0xFFFFFFFF, null, false, false, false, text.size * 6, true),
|
||||
createAdvancedMarkerPair("{ident4}", 0xFFFFFFFF, null, false, false, false, text.size * 8, true),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFF00, false, true), "{o}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF0000, false, true), "{r}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF00FF08, false, true), "{g}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF7D7D7D, false, true), "{gray}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF222222), "{italic}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF666666), "{bold}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF888888), "{bold-italic}"),
|
||||
];
|
||||
public static function applyMarkdownText(text:FlxText, str:String) {
|
||||
text.textField.htmlText = Markdown.markdownToHtml(prepareMarkdown(str));
|
||||
var changes:Array<FlxTextFormatMarkerPair> = [
|
||||
createAdvancedMarkerPair("{title}", 0xFFFFFFFF, text.size * 2, false, true, true),
|
||||
createAdvancedMarkerPair("{subtitle}", 0xFFFFFFFF, text.size * 1.5, false, true, true),
|
||||
createAdvancedMarkerPair("{subsubtitle}", 0xFFFFFFFF, text.size * 1.25, false, true, true),
|
||||
createAdvancedMarkerPair("{ident1}", 0xFFFFFFFF, null, false, false, false, text.size * 2, true),
|
||||
createAdvancedMarkerPair("{ident2}", 0xFFFFFFFF, null, false, false, false, text.size * 4, true),
|
||||
createAdvancedMarkerPair("{ident3}", 0xFFFFFFFF, null, false, false, false, text.size * 6, true),
|
||||
createAdvancedMarkerPair("{ident4}", 0xFFFFFFFF, null, false, false, false, text.size * 8, true),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFF00, false, true), "{o}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF0000, false, true), "{r}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF00FF08, false, true), "{g}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFF7D7D7D, false, true), "{gray}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF222222), "{italic}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF666666), "{bold}"),
|
||||
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFFFFFF, false, true, 0xFF888888), "{bold-italic}"),
|
||||
];
|
||||
|
||||
text.applyMarkup(
|
||||
parseWarnings(text.textField.text),
|
||||
changes
|
||||
);
|
||||
@:privateAccess {
|
||||
// hacky fix for the text cutting when bigger text formats are used
|
||||
text._regen = true;
|
||||
text.regenGraphic();
|
||||
text._regen = true;
|
||||
text.regenGraphic();
|
||||
}
|
||||
}
|
||||
text.applyMarkup(
|
||||
parseWarnings(text.textField.text),
|
||||
changes
|
||||
);
|
||||
@:privateAccess {
|
||||
// hacky fix for the text cutting when bigger text formats are used
|
||||
text._regen = true;
|
||||
text.regenGraphic();
|
||||
text._regen = true;
|
||||
text.regenGraphic();
|
||||
}
|
||||
}
|
||||
|
||||
public static function createAdvancedMarkerPair(marker:String, color:FlxColor, size:Null<Float>, bold:Bool = false, italic:Bool = false, ?underline:Bool = false, ?blockIndent:Int, ?bullet:Bool) {
|
||||
@:privateAccess {
|
||||
var format = new FlxTextFormat(color, bold, italic);
|
||||
format.format.size = size == null ? null : Std.int(size);
|
||||
format.format.underline = underline;
|
||||
format.format.blockIndent = blockIndent;
|
||||
format.format.bullet = bullet;
|
||||
return new FlxTextFormatMarkerPair(format, marker);
|
||||
}
|
||||
}
|
||||
public static function createAdvancedMarkerPair(marker:String, color:FlxColor, size:Null<Float>, bold:Bool = false, italic:Bool = false, ?underline:Bool = false, ?blockIndent:Int, ?bullet:Bool) {
|
||||
@:privateAccess {
|
||||
var format = new FlxTextFormat(color, bold, italic);
|
||||
format.format.size = size == null ? null : Std.int(size);
|
||||
format.format.underline = underline;
|
||||
format.format.blockIndent = blockIndent;
|
||||
format.format.bullet = bullet;
|
||||
return new FlxTextFormatMarkerPair(format, marker);
|
||||
}
|
||||
}
|
||||
|
||||
public static function parseWarnings(text:String) {
|
||||
text = text.replace(" ", " ");
|
||||
text = parseEmote(text, "⚠", "{o}(!)", "{o}");
|
||||
text = parseEmote(text, "❌", "{r}(X)", "{r}");
|
||||
text = parseEmote(text, "✔", "{g}(+)", "{g}");
|
||||
return text;
|
||||
}
|
||||
public static function parseWarnings(text:String) {
|
||||
text = text.replace(" ", " ");
|
||||
text = parseEmote(text, "⚠", "{o}(!)", "{o}");
|
||||
text = parseEmote(text, "❌", "{r}(X)", "{r}");
|
||||
text = parseEmote(text, "✔", "{g}(+)", "{g}");
|
||||
return text;
|
||||
}
|
||||
|
||||
public static function prepareMarkdown(text:String) {
|
||||
text = "\n" + text;
|
||||
text = parseEmote(text, "\n- ", "\n{ident1} • ", "{ident1}");
|
||||
text = parseEmote(text, "\n - ", "\n{ident2} • ", "{ident2}");
|
||||
text = parseEmote(text, "\n - ", "\n{ident3} • ", "{ident3}");
|
||||
text = parseEmote(text, "\n - ", "\n{ident4} • ", "{ident4}");
|
||||
text = parseEmote(text, "\n> ", "\n{gray}", "{gray}");
|
||||
text = parseEmote(text, "\n### ", "\n{subsubtitle}", "{subsubtitle}");
|
||||
text = parseEmote(text, "\n## ", "\n{subtitle}", "{subtitle}");
|
||||
text = parseEmote(text, "\n# ", "\n{title}", "{title}");
|
||||
text = parseEmote(text, "***", "{bold-italic}", "{bold-italic}", "***");
|
||||
text = parseEmote(text, "**", "{bold}", "{bold}", "**");
|
||||
text = parseEmote(text, "*", "{italic}", "{italic}", "*");
|
||||
text = parseEmote(text, "_", "{italic}", "{italic}", "*");
|
||||
text = parseEmote(text, "__", "{bold}", "{bold}", "*");
|
||||
text.substr("\n".length);
|
||||
return text;
|
||||
}
|
||||
public static function prepareMarkdown(text:String) {
|
||||
text = "\n" + text;
|
||||
text = parseEmote(text, "\n- ", "\n{ident1} • ", "{ident1}");
|
||||
text = parseEmote(text, "\n - ", "\n{ident2} • ", "{ident2}");
|
||||
text = parseEmote(text, "\n - ", "\n{ident3} • ", "{ident3}");
|
||||
text = parseEmote(text, "\n - ", "\n{ident4} • ", "{ident4}");
|
||||
text = parseEmote(text, "\n> ", "\n{gray}", "{gray}");
|
||||
text = parseEmote(text, "\n### ", "\n{subsubtitle}", "{subsubtitle}");
|
||||
text = parseEmote(text, "\n## ", "\n{subtitle}", "{subtitle}");
|
||||
text = parseEmote(text, "\n# ", "\n{title}", "{title}");
|
||||
text = parseEmote(text, "***", "{bold-italic}", "{bold-italic}", "***");
|
||||
text = parseEmote(text, "**", "{bold}", "{bold}", "**");
|
||||
text = parseEmote(text, "*", "{italic}", "{italic}", "*");
|
||||
text = parseEmote(text, "_", "{italic}", "{italic}", "*");
|
||||
text = parseEmote(text, "__", "{bold}", "{bold}", "*");
|
||||
text.substr("\n".length);
|
||||
return text;
|
||||
}
|
||||
|
||||
public static function parseEmote(text:String, emote:String, beginning:String, end:String, emoteEnd:String = "\n") {
|
||||
var index:Int;
|
||||
while((index = text.indexOf(emote)) >= 0) {
|
||||
var nextIndex = text.indexOf(emoteEnd, index + emote.length);
|
||||
if (nextIndex < 0)
|
||||
nextIndex = text.length;
|
||||
text = text.substr(0, index) + beginning + text.substring(index + emote.length, nextIndex) + end + (emote == emoteEnd ? "" : emoteEnd) + text.substring(nextIndex + emoteEnd.length);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
public static function parseEmote(text:String, emote:String, beginning:String, end:String, emoteEnd:String = "\n") {
|
||||
var index:Int;
|
||||
while((index = text.indexOf(emote)) >= 0) {
|
||||
var nextIndex = text.indexOf(emoteEnd, index + emote.length);
|
||||
if (nextIndex < 0)
|
||||
nextIndex = text.length;
|
||||
text = text.substr(0, index) + beginning + text.substring(index + emote.length, nextIndex) + end + (emote == emoteEnd ? "" : emoteEnd) + text.substring(nextIndex + emoteEnd.length);
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class MemoryUtil {
|
||||
}
|
||||
|
||||
public static function init() {}
|
||||
|
||||
|
||||
public static function clearMinor() {
|
||||
#if (cpp || java || neko)
|
||||
Gc.run(false);
|
||||
|
||||
@@ -4,12 +4,12 @@ import lime.app.Application;
|
||||
|
||||
/**
|
||||
* Small util that allows you to load any function from ndlls via `getFunction`.
|
||||
*
|
||||
*
|
||||
* NDLLs must be in your mod's "ndlls" folder, and must follow this name scheme:
|
||||
* - `name-windows.ndll` for Windows targeted ndlls
|
||||
* - `name-linux.ndll` for Linux targeted ndlls
|
||||
* - `name-mac.ndll` for Mac targeted ndlls
|
||||
*
|
||||
*
|
||||
* If:
|
||||
* - The platform does not support NDLLs
|
||||
* - The NDLL is not found
|
||||
@@ -17,52 +17,52 @@ import lime.app.Application;
|
||||
* then an empty function will be returned instead, and a message will be shown in logs.
|
||||
*/
|
||||
class NdllUtil {
|
||||
#if NDLLS_SUPPORTED
|
||||
#if windows public static final os:String = "windows"; #end
|
||||
#if linux public static final os:String = "linux"; #end
|
||||
#if macos public static final os:String = "mac"; #end
|
||||
#if android public static final os:String = "android"; #end
|
||||
#end
|
||||
#if NDLLS_SUPPORTED
|
||||
#if windows public static final os:String = "windows"; #end
|
||||
#if linux public static final os:String = "linux"; #end
|
||||
#if macos public static final os:String = "mac"; #end
|
||||
#if android public static final os:String = "android"; #end
|
||||
#end
|
||||
|
||||
/**
|
||||
* Returns an function from a Haxe NDLL.
|
||||
*
|
||||
* @param ndll Name of the NDLL.
|
||||
* @param name Name of the function.
|
||||
* @param args Number of arguments of that function.
|
||||
*/
|
||||
public static function getFunction(ndll:String, name:String, args:Int) {
|
||||
#if NDLLS_SUPPORTED
|
||||
return getFunctionFromPath(Paths.ndll('$ndll-$os'), name, args);
|
||||
#else
|
||||
Logs.trace('NDLLs are not supported on this platform.', WARNING);
|
||||
return function() {};
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an function from a Haxe NDLL at specified path.
|
||||
*
|
||||
* @param ndll Asset path to the NDLL.
|
||||
* @param name Name of the function.
|
||||
* @param args Number of arguments of that function.
|
||||
*/
|
||||
public static function getFunctionFromPath(ndll:String, name:String, args:Int) {
|
||||
#if NDLLS_SUPPORTED
|
||||
if (!Assets.exists(ndll)) {
|
||||
Logs.trace('Couldn\'t find ndll at ${ndll}.', WARNING);
|
||||
return function() {};
|
||||
/**
|
||||
* Returns an function from a Haxe NDLL.
|
||||
*
|
||||
* @param ndll Name of the NDLL.
|
||||
* @param name Name of the function.
|
||||
* @param args Number of arguments of that function.
|
||||
*/
|
||||
public static function getFunction(ndll:String, name:String, args:Int) {
|
||||
#if NDLLS_SUPPORTED
|
||||
return getFunctionFromPath(Paths.ndll('$ndll-$os'), name, args);
|
||||
#else
|
||||
Logs.trace('NDLLs are not supported on this platform.', WARNING);
|
||||
return function() {};
|
||||
#end
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an function from a Haxe NDLL at specified path.
|
||||
*
|
||||
* @param ndll Asset path to the NDLL.
|
||||
* @param name Name of the function.
|
||||
* @param args Number of arguments of that function.
|
||||
*/
|
||||
public static function getFunctionFromPath(ndll:String, name:String, args:Int) {
|
||||
#if NDLLS_SUPPORTED
|
||||
if (!Assets.exists(ndll)) {
|
||||
Logs.trace('Couldn\'t find ndll at ${ndll}.', WARNING);
|
||||
return function() {};
|
||||
}
|
||||
var func = lime.system.CFFI.load(Assets.getPath(ndll), name, args);
|
||||
|
||||
if (func == null) {
|
||||
|
||||
if (func == null) {
|
||||
Logs.trace('Method ${name} in ndll ${ndll} with ${args} args was not found.', ERROR);
|
||||
return function() {};
|
||||
return function() {};
|
||||
}
|
||||
return func;
|
||||
#else
|
||||
Logs.trace('NDLLs are not supported on this platform.', WARNING);
|
||||
#end
|
||||
return function() {};
|
||||
}
|
||||
return func;
|
||||
#else
|
||||
Logs.trace('NDLLs are not supported on this platform.', WARNING);
|
||||
#end
|
||||
return function() {};
|
||||
}
|
||||
}
|
||||
@@ -2,31 +2,31 @@ package funkin.utils;
|
||||
|
||||
#if ALLOW_MULTITHREADING
|
||||
class ThreadUtil {
|
||||
/**
|
||||
* Creates a new Thread with an error handler.
|
||||
* @param func Function to execute
|
||||
* @param autoRestart Whenever the thread should auto restart itself after crashing.
|
||||
*/
|
||||
public static function createSafe(func:Void->Void, autoRestart:Bool = false) {
|
||||
if (autoRestart) {
|
||||
return sys.thread.Thread.create(function() {
|
||||
while(true) {
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
trace(e.details());
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return sys.thread.Thread.create(function() {
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
trace(e.details());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Creates a new Thread with an error handler.
|
||||
* @param func Function to execute
|
||||
* @param autoRestart Whenever the thread should auto restart itself after crashing.
|
||||
*/
|
||||
public static function createSafe(func:Void->Void, autoRestart:Bool = false) {
|
||||
if (autoRestart) {
|
||||
return sys.thread.Thread.create(function() {
|
||||
while(true) {
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
trace(e.details());
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
return sys.thread.Thread.create(function() {
|
||||
try {
|
||||
func();
|
||||
} catch(e) {
|
||||
trace(e.details());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#end
|
||||
@@ -13,34 +13,34 @@ using StringTools;
|
||||
*/
|
||||
class XMLUtil {
|
||||
|
||||
/**
|
||||
* Applies a property XML node to an object.
|
||||
* @param object Object to which the xml property will be applied
|
||||
* @param property `property` node.
|
||||
*/
|
||||
public static function applyXMLProperty(object:Dynamic, property:Access):ErrorCode {
|
||||
if (!property.has.name || !property.has.type || !property.has.value) {
|
||||
Logs.trace('Failed to apply XML property: XML Element misses name, type, or value attributes.', WARNING);
|
||||
return MISSING_PROPERTY;
|
||||
}
|
||||
/**
|
||||
* Applies a property XML node to an object.
|
||||
* @param object Object to which the xml property will be applied
|
||||
* @param property `property` node.
|
||||
*/
|
||||
public static function applyXMLProperty(object:Dynamic, property:Access):ErrorCode {
|
||||
if (!property.has.name || !property.has.type || !property.has.value) {
|
||||
Logs.trace('Failed to apply XML property: XML Element misses name, type, or value attributes.', WARNING);
|
||||
return MISSING_PROPERTY;
|
||||
}
|
||||
|
||||
var value:Dynamic = switch(property.att.type.toLowerCase()) {
|
||||
case "float" | "number": Std.parseFloat(property.att.value);
|
||||
case "int" | "integer" | "color": Std.parseInt(property.att.value);
|
||||
case "string" | "str" | "text": property.att.value;
|
||||
case "bool" | "boolean": property.att.value.toLowerCase() == "true";
|
||||
default: return TYPE_INCORRECT;
|
||||
}
|
||||
if (value == null) return VALUE_NULL;
|
||||
var value:Dynamic = switch(property.att.type.toLowerCase()) {
|
||||
case "float" | "number": Std.parseFloat(property.att.value);
|
||||
case "int" | "integer" | "color": Std.parseInt(property.att.value);
|
||||
case "string" | "str" | "text": property.att.value;
|
||||
case "bool" | "boolean": property.att.value.toLowerCase() == "true";
|
||||
default: return TYPE_INCORRECT;
|
||||
}
|
||||
if (value == null) return VALUE_NULL;
|
||||
|
||||
try {
|
||||
Reflect.setProperty(object, property.att.name, value);
|
||||
} catch(e) {
|
||||
Logs.trace('Failed to apply XML property: $e on ${Type.getClass(object)}', WARNING);
|
||||
return REFLECT_ERROR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
try {
|
||||
Reflect.setProperty(object, property.att.name, value);
|
||||
} catch(e) {
|
||||
Logs.trace('Failed to apply XML property: $e on ${Type.getClass(object)}', WARNING);
|
||||
return REFLECT_ERROR;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new sprite based on a XML node.
|
||||
@@ -69,11 +69,11 @@ class XMLUtil {
|
||||
if (node.has.scrollx) {
|
||||
var scroll:Null<Float> = Std.parseFloat(node.att.scrollx);
|
||||
if (scroll != null) spr.scrollFactor.x = scroll;
|
||||
}
|
||||
}
|
||||
if (node.has.scrolly) {
|
||||
var scroll:Null<Float> = Std.parseFloat(node.att.scrolly);
|
||||
if (scroll != null) spr.scrollFactor.y = scroll;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.has.antialiasing) spr.antialiasing = node.att.antialiasing == "true";
|
||||
if (node.has.scale) {
|
||||
@@ -83,7 +83,7 @@ class XMLUtil {
|
||||
if (node.has.updateHitbox && node.att.updateHitbox == "true") spr.updateHitbox();
|
||||
|
||||
spr.zoomFactor = Std.parseFloat(node.getAtt("zoomfactor")).getDefault(spr.zoomFactor);
|
||||
|
||||
|
||||
for(anim in node.nodes.anim)
|
||||
addXMLAnimation(spr, anim);
|
||||
|
||||
@@ -116,7 +116,7 @@ class XMLUtil {
|
||||
if (i != null)
|
||||
animData.indices.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return animData;
|
||||
}
|
||||
@@ -164,9 +164,9 @@ class XMLUtil {
|
||||
// nothing
|
||||
}
|
||||
}
|
||||
return OK;
|
||||
return OK;
|
||||
}
|
||||
return MISSING_PROPERTY;
|
||||
return MISSING_PROPERTY;
|
||||
}
|
||||
|
||||
public static inline function fixXMLText(text:String) {
|
||||
|
||||
+191
-191
@@ -24,81 +24,81 @@ using StringTools;
|
||||
// import ZipUtils; var e = ZipUtils.createZipFile("gjnsdghs.ycemod"); ZipUtils.writeFolderToZip(e, "./mods/Friday Night Funkin'/", "Friday Night Funkin'/"); e.flush(); e.close();
|
||||
|
||||
class ZipUtil {
|
||||
public static var bannedNames:Array<String> = [".git", ".gitignore", ".github", ".vscode", ".gitattributes", "readme.txt"];
|
||||
public static var bannedNames:Array<String> = [".git", ".gitignore", ".github", ".vscode", ".gitattributes", "readme.txt"];
|
||||
|
||||
/**
|
||||
* [Description] Uncompresses `zip` into the `destFolder` folder
|
||||
* @param zip
|
||||
* @param destFolder
|
||||
* @param zip
|
||||
* @param destFolder
|
||||
*/
|
||||
public static function uncompressZip(zip:Reader, destFolder:String, ?prefix:String, ?prog:ZipProgress):ZipProgress {
|
||||
// we never know
|
||||
FileSystem.createDirectory(destFolder);
|
||||
|
||||
var fields = zip.read();
|
||||
var fields = zip.read();
|
||||
|
||||
try {
|
||||
if (prefix != null) {
|
||||
var f = fields;
|
||||
fields = new List<Entry>();
|
||||
for(field in f) {
|
||||
if (field.fileName.startsWith(prefix)) {
|
||||
fields.push(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prog == null)
|
||||
prog = new ZipProgress();
|
||||
prog.fileCount = fields.length;
|
||||
for(k=>field in fields) {
|
||||
prog.curFile = k;
|
||||
var isFolder = field.fileName.endsWith("/") && field.fileSize == 0;
|
||||
if (isFolder) {
|
||||
FileSystem.createDirectory('${destFolder}/${field.fileName}');
|
||||
} else {
|
||||
var split = [for(e in field.fileName.split("/")) e.trim()];
|
||||
split.pop();
|
||||
FileSystem.createDirectory('${destFolder}/${split.join("/")}');
|
||||
|
||||
var data = unzip(field);
|
||||
File.saveBytes('${destFolder}/${field.fileName}', data);
|
||||
}
|
||||
}
|
||||
prog.curFile = fields.length;
|
||||
prog.done = true;
|
||||
} catch(e) {
|
||||
prog.done = true;
|
||||
prog.error = e;
|
||||
}
|
||||
return prog;
|
||||
try {
|
||||
if (prefix != null) {
|
||||
var f = fields;
|
||||
fields = new List<Entry>();
|
||||
for(field in f) {
|
||||
if (field.fileName.startsWith(prefix)) {
|
||||
fields.push(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prog == null)
|
||||
prog = new ZipProgress();
|
||||
prog.fileCount = fields.length;
|
||||
for(k=>field in fields) {
|
||||
prog.curFile = k;
|
||||
var isFolder = field.fileName.endsWith("/") && field.fileSize == 0;
|
||||
if (isFolder) {
|
||||
FileSystem.createDirectory('${destFolder}/${field.fileName}');
|
||||
} else {
|
||||
var split = [for(e in field.fileName.split("/")) e.trim()];
|
||||
split.pop();
|
||||
FileSystem.createDirectory('${destFolder}/${split.join("/")}');
|
||||
|
||||
var data = unzip(field);
|
||||
File.saveBytes('${destFolder}/${field.fileName}', data);
|
||||
}
|
||||
}
|
||||
prog.curFile = fields.length;
|
||||
prog.done = true;
|
||||
} catch(e) {
|
||||
prog.done = true;
|
||||
prog.error = e;
|
||||
}
|
||||
return prog;
|
||||
}
|
||||
|
||||
#if (!macro && sys)
|
||||
public static function uncompressZipAsync(zip:Reader, destFolder:String, ?prog:ZipProgress, ?prefix:String):ZipProgress {
|
||||
if (prog == null)
|
||||
prog = new ZipProgress();
|
||||
Thread.create(function() {
|
||||
uncompressZip(zip, destFolder, prefix, prog);
|
||||
});
|
||||
return prog;
|
||||
}
|
||||
#end
|
||||
#if (!macro && sys)
|
||||
public static function uncompressZipAsync(zip:Reader, destFolder:String, ?prog:ZipProgress, ?prefix:String):ZipProgress {
|
||||
if (prog == null)
|
||||
prog = new ZipProgress();
|
||||
Thread.create(function() {
|
||||
uncompressZip(zip, destFolder, prefix, prog);
|
||||
});
|
||||
return prog;
|
||||
}
|
||||
#end
|
||||
|
||||
/**
|
||||
* [Description] Returns a `zip.Reader` instance from path.
|
||||
* @param zipPath
|
||||
* @return Reader
|
||||
*/
|
||||
public static function openZip(zipPath:String):Reader {
|
||||
return new ZipReader(File.read(zipPath));
|
||||
}
|
||||
/**
|
||||
* [Description] Returns a `zip.Reader` instance from path.
|
||||
* @param zipPath
|
||||
* @return Reader
|
||||
*/
|
||||
public static function openZip(zipPath:String):Reader {
|
||||
return new ZipReader(File.read(zipPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* [Description] Copy of haxe's Zip unzip function cause lime replaced it.
|
||||
* @param f Zip entry
|
||||
*/
|
||||
public static function unzip(f:Entry) {
|
||||
/**
|
||||
* [Description] Copy of haxe's Zip unzip function cause lime replaced it.
|
||||
* @param f Zip entry
|
||||
*/
|
||||
public static function unzip(f:Entry) {
|
||||
if (!f.compressed)
|
||||
return f.data;
|
||||
var c = new haxe.zip.Uncompress(-15);
|
||||
@@ -113,156 +113,156 @@ class ZipUtil {
|
||||
return f.data;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Description] Creates a ZIP file at the specified location and returns the Writer.
|
||||
* @param path
|
||||
* @return Writer
|
||||
*/
|
||||
public static function createZipFile(path:String):ZipWriter {
|
||||
var output = File.write(path);
|
||||
return new ZipWriter(output);
|
||||
}
|
||||
/**
|
||||
* [Description] Creates a ZIP file at the specified location and returns the Writer.
|
||||
* @param path
|
||||
* @return Writer
|
||||
*/
|
||||
public static function createZipFile(path:String):ZipWriter {
|
||||
var output = File.write(path);
|
||||
return new ZipWriter(output);
|
||||
}
|
||||
|
||||
/**
|
||||
[Description] Writes the entirety of a folder to a zip file.
|
||||
@param zip ZIP file to write to
|
||||
@param path Folder path
|
||||
@param prefix (Additional) allows you to set a prefix in the zip itself.
|
||||
**/
|
||||
public static function writeFolderToZip(zip:ZipWriter, path:String, ?prefix:String, ?prog:ZipProgress, ?whitelist:Array<String>):ZipProgress {
|
||||
if (prefix == null) prefix = "";
|
||||
if (whitelist == null) whitelist = [];
|
||||
if (prog == null) prog = new ZipProgress();
|
||||
/**
|
||||
[Description] Writes the entirety of a folder to a zip file.
|
||||
@param zip ZIP file to write to
|
||||
@param path Folder path
|
||||
@param prefix (Additional) allows you to set a prefix in the zip itself.
|
||||
**/
|
||||
public static function writeFolderToZip(zip:ZipWriter, path:String, ?prefix:String, ?prog:ZipProgress, ?whitelist:Array<String>):ZipProgress {
|
||||
if (prefix == null) prefix = "";
|
||||
if (whitelist == null) whitelist = [];
|
||||
if (prog == null) prog = new ZipProgress();
|
||||
|
||||
try {
|
||||
var curPath:Array<String> = ['$path'];
|
||||
var destPath:Array<String> = [];
|
||||
if (prefix != "") {
|
||||
prefix = prefix.replace("\\", "/");
|
||||
while(prefix.charAt(0) == "/") prefix = prefix.substr(1);
|
||||
while(prefix.charAt(prefix.length-1) == "/") prefix = prefix.substr(0, prefix.length-1);
|
||||
destPath.push(prefix);
|
||||
}
|
||||
|
||||
var files:Array<StrNameLabel> = [];
|
||||
|
||||
var doFolder:Void->Void = null;
|
||||
(doFolder = function() {
|
||||
var path = curPath.join("/");
|
||||
var zipPath = destPath.join("/");
|
||||
for(e in FileSystem.readDirectory(path)) {
|
||||
if (bannedNames.contains(e.toLowerCase()) && !whitelist.contains(e.toLowerCase())) continue;
|
||||
if (FileSystem.isDirectory('$path/$e')) {
|
||||
// is directory, so loop into that function again
|
||||
for(p in [curPath, destPath]) p.push(e);
|
||||
doFolder();
|
||||
for(p in [curPath, destPath]) p.pop();
|
||||
} else {
|
||||
// is file, put it in the list
|
||||
var zipPath = '$zipPath/$e';
|
||||
while(zipPath.charAt(0) == "/") zipPath = zipPath.substr(1);
|
||||
files.push(new StrNameLabel('$path/$e', zipPath));
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
prog.fileCount = files.length;
|
||||
for(k=>file in files) {
|
||||
prog.curFile = k;
|
||||
|
||||
var fileContent = File.getBytes(file.name);
|
||||
var fileInfo = FileSystem.stat(file.name);
|
||||
var entry:Entry = {
|
||||
fileName: file.label,
|
||||
fileSize: fileInfo.size,
|
||||
fileTime: Date.now(),
|
||||
dataSize: 0,
|
||||
data: fileContent,
|
||||
crc32: Crc32.make(fileContent),
|
||||
compressed: false
|
||||
};
|
||||
Tools.compress(entry, 1);
|
||||
zip.writeFile(entry);
|
||||
}
|
||||
zip.writeCDR();
|
||||
} catch(e) {
|
||||
prog.error = e;
|
||||
}
|
||||
prog.done = true;
|
||||
return prog;
|
||||
}
|
||||
try {
|
||||
var curPath:Array<String> = ['$path'];
|
||||
var destPath:Array<String> = [];
|
||||
if (prefix != "") {
|
||||
prefix = prefix.replace("\\", "/");
|
||||
while(prefix.charAt(0) == "/") prefix = prefix.substr(1);
|
||||
while(prefix.charAt(prefix.length-1) == "/") prefix = prefix.substr(0, prefix.length-1);
|
||||
destPath.push(prefix);
|
||||
}
|
||||
|
||||
public static function writeFolderToZipAsync(zip:ZipWriter, path:String, ?prefix:String):ZipProgress {
|
||||
var zipProg = new ZipProgress();
|
||||
Thread.create(function() {
|
||||
writeFolderToZip(zip, path, prefix, zipProg);
|
||||
});
|
||||
return zipProg;
|
||||
}
|
||||
var files:Array<StrNameLabel> = [];
|
||||
|
||||
/**
|
||||
* [Description] Converts an `Array<Entry>` to a `List<Entry>`.
|
||||
* @param array
|
||||
* @return List<Entry>
|
||||
*/
|
||||
public static function arrayToList(array:Array<Entry>):List<Entry> {
|
||||
var list = new List<Entry>();
|
||||
for(e in array) list.push(e);
|
||||
return list;
|
||||
}
|
||||
var doFolder:Void->Void = null;
|
||||
(doFolder = function() {
|
||||
var path = curPath.join("/");
|
||||
var zipPath = destPath.join("/");
|
||||
for(e in FileSystem.readDirectory(path)) {
|
||||
if (bannedNames.contains(e.toLowerCase()) && !whitelist.contains(e.toLowerCase())) continue;
|
||||
if (FileSystem.isDirectory('$path/$e')) {
|
||||
// is directory, so loop into that function again
|
||||
for(p in [curPath, destPath]) p.push(e);
|
||||
doFolder();
|
||||
for(p in [curPath, destPath]) p.pop();
|
||||
} else {
|
||||
// is file, put it in the list
|
||||
var zipPath = '$zipPath/$e';
|
||||
while(zipPath.charAt(0) == "/") zipPath = zipPath.substr(1);
|
||||
files.push(new StrNameLabel('$path/$e', zipPath));
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
prog.fileCount = files.length;
|
||||
for(k=>file in files) {
|
||||
prog.curFile = k;
|
||||
|
||||
var fileContent = File.getBytes(file.name);
|
||||
var fileInfo = FileSystem.stat(file.name);
|
||||
var entry:Entry = {
|
||||
fileName: file.label,
|
||||
fileSize: fileInfo.size,
|
||||
fileTime: Date.now(),
|
||||
dataSize: 0,
|
||||
data: fileContent,
|
||||
crc32: Crc32.make(fileContent),
|
||||
compressed: false
|
||||
};
|
||||
Tools.compress(entry, 1);
|
||||
zip.writeFile(entry);
|
||||
}
|
||||
zip.writeCDR();
|
||||
} catch(e) {
|
||||
prog.error = e;
|
||||
}
|
||||
prog.done = true;
|
||||
return prog;
|
||||
}
|
||||
|
||||
public static function writeFolderToZipAsync(zip:ZipWriter, path:String, ?prefix:String):ZipProgress {
|
||||
var zipProg = new ZipProgress();
|
||||
Thread.create(function() {
|
||||
writeFolderToZip(zip, path, prefix, zipProg);
|
||||
});
|
||||
return zipProg;
|
||||
}
|
||||
|
||||
/**
|
||||
* [Description] Converts an `Array<Entry>` to a `List<Entry>`.
|
||||
* @param array
|
||||
* @return List<Entry>
|
||||
*/
|
||||
public static function arrayToList(array:Array<Entry>):List<Entry> {
|
||||
var list = new List<Entry>();
|
||||
for(e in array) list.push(e);
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
class ZipProgress {
|
||||
public var error:Exception = null;
|
||||
|
||||
public var curFile:Int = 0;
|
||||
public var fileCount:Int = 0;
|
||||
public var done:Bool = false;
|
||||
public var percentage(get, null):Float;
|
||||
public var error:Exception = null;
|
||||
|
||||
private function get_percentage() {
|
||||
return fileCount <= 0 ? 0 : curFile / fileCount;
|
||||
}
|
||||
public var curFile:Int = 0;
|
||||
public var fileCount:Int = 0;
|
||||
public var done:Bool = false;
|
||||
public var percentage(get, null):Float;
|
||||
|
||||
public function new() {}
|
||||
private function get_percentage() {
|
||||
return fileCount <= 0 ? 0 : curFile / fileCount;
|
||||
}
|
||||
|
||||
public function new() {}
|
||||
}
|
||||
|
||||
class ZipReader extends Reader {
|
||||
public var files:List<Entry>;
|
||||
public var files:List<Entry>;
|
||||
|
||||
public override function read() {
|
||||
if (files != null) return files;
|
||||
try {
|
||||
var files = super.read();
|
||||
return this.files = files;
|
||||
} catch(e) {
|
||||
}
|
||||
return new List<Entry>();
|
||||
}
|
||||
public override function read() {
|
||||
if (files != null) return files;
|
||||
try {
|
||||
var files = super.read();
|
||||
return this.files = files;
|
||||
} catch(e) {
|
||||
}
|
||||
return new List<Entry>();
|
||||
}
|
||||
}
|
||||
|
||||
class ZipWriter extends Writer {
|
||||
public function flush() {
|
||||
o.flush();
|
||||
}
|
||||
public function flush() {
|
||||
o.flush();
|
||||
}
|
||||
|
||||
public function writeFile(entry:Entry) {
|
||||
writeEntryHeader(entry);
|
||||
o.writeFullBytes(entry.data, 0, entry.data.length);
|
||||
}
|
||||
public function writeFile(entry:Entry) {
|
||||
writeEntryHeader(entry);
|
||||
o.writeFullBytes(entry.data, 0, entry.data.length);
|
||||
}
|
||||
|
||||
public function close() {
|
||||
o.close();
|
||||
}
|
||||
public function close() {
|
||||
o.close();
|
||||
}
|
||||
}
|
||||
|
||||
class StrNameLabel {
|
||||
public var name:String;
|
||||
public var label:String;
|
||||
public var name:String;
|
||||
public var label:String;
|
||||
|
||||
public function new(name:String, label:String) {
|
||||
this.name = name;
|
||||
this.label = label;
|
||||
}
|
||||
public function new(name:String, label:String) {
|
||||
this.name = name;
|
||||
this.label = label;
|
||||
}
|
||||
}
|
||||
#end
|
||||
Reference in New Issue
Block a user