reduce the millions of maps. needs further testing
Co-authored-by: Ne_Eo <NeeEoo@users.noreply.github.com> Co-authored-by: ⍚~Nex <NexIsDumb@users.noreply.github.com>
This commit is contained in:
co-authored by
Ne_Eo
⍚~Nex
parent
f2a1e20c75
commit
661b22b515
@@ -5,13 +5,33 @@ import funkin.menus.ui.effects.RegionEffect;
|
|||||||
import flixel.animation.FlxAnimation;
|
import flixel.animation.FlxAnimation;
|
||||||
import flixel.util.FlxDirectionFlags;
|
import flixel.util.FlxDirectionFlags;
|
||||||
import flixel.math.FlxPoint;
|
import flixel.math.FlxPoint;
|
||||||
|
import flixel.FlxTypes;
|
||||||
|
|
||||||
import haxe.xml.Access;
|
import haxe.xml.Access;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
using flixel.util.FlxColorTransformUtil;
|
using flixel.util.FlxColorTransformUtil;
|
||||||
|
|
||||||
enum abstract AlphabetAlignment(Int) from Int to Int {
|
@:structInit
|
||||||
|
class AlphabetLetterData {
|
||||||
|
@:optional public var isDefault:Bool = false;
|
||||||
|
public var anim:String; // should this be FlxAnimation?
|
||||||
|
public var x:Float;
|
||||||
|
public var y:Float;
|
||||||
|
public var advance:Null<Float>;
|
||||||
|
// Precalculated values for angle
|
||||||
|
public var sin:Float;
|
||||||
|
public var cos:Float;
|
||||||
|
public var scaleX:Float;
|
||||||
|
public var scaleY:Float;
|
||||||
|
|
||||||
|
// If null, render spooping as usual I see
|
||||||
|
public var components:Array<AlphabetLetterData>; // components with components lol
|
||||||
|
}
|
||||||
|
|
||||||
|
// we also need to store components somehow
|
||||||
|
|
||||||
|
enum abstract AlphabetAlignment(ByteUInt) from ByteUInt to ByteUInt {
|
||||||
var LEFT;
|
var LEFT;
|
||||||
var CENTER;
|
var CENTER;
|
||||||
var RIGHT;
|
var RIGHT;
|
||||||
@@ -34,7 +54,7 @@ enum abstract AlphabetAlignment(Int) from Int to Int {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum abstract CaseMode(Int) from Int to Int {
|
enum abstract CaseMode(ByteUInt) from ByteUInt to ByteUInt {
|
||||||
var NONE;
|
var NONE;
|
||||||
var UPPER;
|
var UPPER;
|
||||||
var LOWER;
|
var LOWER;
|
||||||
@@ -52,7 +72,7 @@ enum abstract CaseMode(Int) from Int to Int {
|
|||||||
class NewAlphabet extends FlxSprite {
|
class NewAlphabet extends FlxSprite {
|
||||||
public var effects:Array<RegionEffect> = [];
|
public var effects:Array<RegionEffect> = [];
|
||||||
var __renderData:AlphabetRenderData;
|
var __renderData:AlphabetRenderData;
|
||||||
|
|
||||||
public var text(default, set):String = "";
|
public var text(default, set):String = "";
|
||||||
@:isVar public var textWidth(get, set):Float;
|
@:isVar public var textWidth(get, set):Float;
|
||||||
public var textHeight(get, null):Float;
|
public var textHeight(get, null):Float;
|
||||||
@@ -73,12 +93,10 @@ class NewAlphabet extends FlxSprite {
|
|||||||
var defaultAdvance:Float = 40.0;
|
var defaultAdvance:Float = 40.0;
|
||||||
var lineGap:Float = 75.0;
|
var lineGap:Float = 75.0;
|
||||||
var fps:Float = 24.0;
|
var fps:Float = 24.0;
|
||||||
var defaults:Map<String, String> = [];
|
var letterData:Map<String, AlphabetLetterData> = [];
|
||||||
var anims:Map<String, String> = [];
|
var defaults:Array<AlphabetLetterData> = [null, null, null];
|
||||||
|
var loaded:Array<Array<String>> = [[], [], []];
|
||||||
var failedLetters:Array<String> = [];
|
var failedLetters:Array<String> = [];
|
||||||
var xOffset:Map<String, Float> = [];
|
|
||||||
var yOffset:Map<String, Float> = [];
|
|
||||||
var advances:Map<String, Float> = [];
|
|
||||||
|
|
||||||
public function new(?x:Float, ?y:Float, ?font:String = "bold") {
|
public function new(?x:Float, ?y:Float, ?font:String = "bold") {
|
||||||
super(x, y);
|
super(x, y);
|
||||||
@@ -86,7 +104,7 @@ class NewAlphabet extends FlxSprite {
|
|||||||
this.__renderData = new AlphabetRenderData(this);
|
this.__renderData = new AlphabetRenderData(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function update(elapsed:Float) {
|
override function update(elapsed:Float):Void {
|
||||||
//super.update(elapsed);
|
//super.update(elapsed);
|
||||||
// FLXOBJECT UPDATE
|
// FLXOBJECT UPDATE
|
||||||
#if FLX_DEBUG
|
#if FLX_DEBUG
|
||||||
@@ -107,10 +125,10 @@ class NewAlphabet extends FlxSprite {
|
|||||||
|
|
||||||
__animTime += elapsed;
|
__animTime += elapsed;
|
||||||
for (effect in effects)
|
for (effect in effects)
|
||||||
effect.effectTime += FlxG.elapsed * effect.speed;
|
effect.effectTime += elapsed * effect.speed;
|
||||||
}
|
}
|
||||||
|
|
||||||
override function draw() {
|
override function draw():Void {
|
||||||
__ogForceScreen = forceIsOnScreen;
|
__ogForceScreen = forceIsOnScreen;
|
||||||
forceIsOnScreen = true;
|
forceIsOnScreen = true;
|
||||||
super.draw();
|
super.draw();
|
||||||
@@ -120,7 +138,7 @@ class NewAlphabet extends FlxSprite {
|
|||||||
return false; // maybe ill get simple render working another time??? not right now tho.
|
return false; // maybe ill get simple render working another time??? not right now tho.
|
||||||
}
|
}
|
||||||
|
|
||||||
override function drawComplex(camera:FlxCamera) {
|
override function drawComplex(camera:FlxCamera):Void {
|
||||||
forceIsOnScreen = __ogForceScreen;
|
forceIsOnScreen = __ogForceScreen;
|
||||||
|
|
||||||
if (__queueResize)
|
if (__queueResize)
|
||||||
@@ -140,12 +158,14 @@ class NewAlphabet extends FlxSprite {
|
|||||||
frameOffset.x -= (textWidth - __laneWidths[0]) * alignmentMultiplier;
|
frameOffset.x -= (textWidth - __laneWidths[0]) * alignmentMultiplier;
|
||||||
|
|
||||||
var isGraphicsShader = shader != null && shader is flixel.graphics.tile.FlxGraphicsShader;
|
var isGraphicsShader = shader != null && shader is flixel.graphics.tile.FlxGraphicsShader;
|
||||||
var offsetMult = (1 - transformMult) * 255;
|
var offsetMult = (1 - transformMult) * 255;
|
||||||
var ogRed:Float = colorTransform.redMultiplier;
|
var ogRed:Float = colorTransform.redMultiplier;
|
||||||
var ogGreen:Float = colorTransform.greenMultiplier;
|
var ogGreen:Float = colorTransform.greenMultiplier;
|
||||||
var ogBlue:Float = colorTransform.blueMultiplier;
|
var ogBlue:Float = colorTransform.blueMultiplier;
|
||||||
var ogAlpha:Float = colorTransform.alphaMultiplier;
|
var ogAlpha:Float = colorTransform.alphaMultiplier;
|
||||||
|
|
||||||
|
var frameTime = Math.floor(__animTime * fps);
|
||||||
|
|
||||||
for (i in 0...daText.length) {
|
for (i in 0...daText.length) {
|
||||||
__renderData.reset(this, ogRed, ogGreen, ogBlue, ogAlpha, daText.charAt(i));
|
__renderData.reset(this, ogRed, ogGreen, ogBlue, ogAlpha, daText.charAt(i));
|
||||||
for (effect in effects) {
|
for (effect in effects) {
|
||||||
@@ -162,17 +182,18 @@ class NewAlphabet extends FlxSprite {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var anim = getLetterAnim(letter);
|
var data = getData(letter);
|
||||||
var advance:Float = getAdvance(letter, anim);
|
var anim = getLetterAnim(letter, data);
|
||||||
|
var advance:Float = getAdvance(letter, anim, data);
|
||||||
|
|
||||||
if (anim == null || __renderData.alpha <= 0.0) {
|
if (anim == null || __renderData.alpha <= 0.0) {
|
||||||
frameOffset.x -= advance;
|
frameOffset.x -= advance;
|
||||||
} else {
|
} else {
|
||||||
var frameToGet = Math.floor(__animTime * fps) % anim.numFrames;
|
var frameToGet = frameTime % anim.numFrames;
|
||||||
frame = frames.frames[anim.frames[frameToGet]];
|
frame = frames.frames[anim.frames[frameToGet]];
|
||||||
|
|
||||||
var offsetX = (xOffset.exists(letter) ? xOffset.get(letter) : 0) + __renderData.offsetX;
|
var offsetX = data.x + __renderData.offsetX;
|
||||||
var offsetY = frame.sourceSize.y - lineGap + (yOffset.exists(letter) ? yOffset.get(letter) : 0) + __renderData.offsetY;
|
var offsetY = frame.sourceSize.y - lineGap + data.y + __renderData.offsetY;
|
||||||
frameOffset.x += offsetX;
|
frameOffset.x += offsetX;
|
||||||
frameOffset.y += offsetY;
|
frameOffset.y += offsetY;
|
||||||
if (!isOnScreen(camera)) {
|
if (!isOnScreen(camera)) {
|
||||||
@@ -194,12 +215,12 @@ class NewAlphabet extends FlxSprite {
|
|||||||
frameOffset.x -= advance;
|
frameOffset.x -= advance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setColorTransform(ogRed, ogGreen, ogBlue, ogAlpha, 0, 0, 0, 0);
|
setColorTransform(ogRed, ogGreen, ogBlue, ogAlpha, 0, 0, 0, 0);
|
||||||
frameOffset.set(ogOffX, ogOffY);
|
frameOffset.set(ogOffX, ogOffY);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function updateHitbox() {
|
override function updateHitbox():Void {
|
||||||
width = Math.abs(scale.x) * textWidth;
|
width = Math.abs(scale.x) * textWidth;
|
||||||
height = Math.abs(scale.y) * textHeight;
|
height = Math.abs(scale.y) * textHeight;
|
||||||
offset.set(-0.5 * (width - textWidth), -0.5 * (height - textHeight));
|
offset.set(-0.5 * (width - textWidth), -0.5 * (height - textHeight));
|
||||||
@@ -226,50 +247,61 @@ class NewAlphabet extends FlxSprite {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
__laneWidths[curLine] += getAdvance(letter);
|
var data = getData(letter);
|
||||||
|
__laneWidths[curLine] += getAdvance(letter, getLetterAnim(letter, data), data);
|
||||||
@:bypassAccessor textWidth = Math.max(textWidth, __laneWidths[curLine]);
|
@:bypassAccessor textWidth = Math.max(textWidth, __laneWidths[curLine]);
|
||||||
}
|
}
|
||||||
|
|
||||||
origin.set(textWidth * 0.5 + originOffset.x, textHeight * 0.5 + originOffset.y);
|
origin.set(textWidth * 0.5 + originOffset.x, textHeight * 0.5 + originOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAdvance(letter:String, ?anim:FlxAnimation):Float {
|
function getAdvance(letter:String, anim:FlxAnimation, ?data:AlphabetLetterData):Float {
|
||||||
var advance:Null<Float> = defaultAdvance;
|
// we should calculate this in checkNode
|
||||||
if(advances.exists(letter)) {
|
if (anim == null)
|
||||||
advance = advances.get(letter);
|
return defaultAdvance;
|
||||||
} else {
|
// t
|
||||||
var anim = anim != null ? anim : getLetterAnim(letter);
|
if(data != null) {
|
||||||
if(anim != null)
|
if (data.advance != null)
|
||||||
advance = frames.frames[anim.frames[0]].sourceSize.x;
|
return data.advance;
|
||||||
advances.set(letter, advance);
|
return data.advance = frames.frames[anim.frames[0]].sourceSize.x;
|
||||||
}
|
}
|
||||||
return advance;
|
return defaultAdvance;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getLetterAnim(char:String):FlxAnimation {
|
function getData(char:String):AlphabetLetterData {
|
||||||
if (failedLetters.contains(char)) return null;
|
if (failedLetters.contains(char)) return null;
|
||||||
if (animation.exists(char)) return animation.getByName(char);
|
for (i in 0...3) { // this feels wrong
|
||||||
|
if (loaded[i].contains(char))
|
||||||
var charCode:Int = char.charCodeAt(0);
|
return defaults[i];
|
||||||
|
|
||||||
var anim:String = null;
|
|
||||||
if (anims.exists(char))
|
|
||||||
anim = anims.get(char);
|
|
||||||
|
|
||||||
if (anim == null) {
|
|
||||||
if (charCode >= 'A'.code && charCode <= 'A'.code && defaults.exists("UPPER"))
|
|
||||||
anim = defaults.get("UPPER").replace("LETTER", char);
|
|
||||||
else if (charCode >= 'a'.code && charCode <= 'z'.code && defaults.exists("LOWER"))
|
|
||||||
anim = defaults.get("LOWER").replace("LETTER", char);
|
|
||||||
else
|
|
||||||
anim = defaults.get("<NORMAL>").replace("LETTER", char);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(anim == null) {
|
var data:AlphabetLetterData = null;
|
||||||
|
if (letterData.exists(char))
|
||||||
|
data = letterData.get(char);
|
||||||
|
|
||||||
|
if (data == null) {
|
||||||
|
var charCode:Int = char.charCodeAt(0);
|
||||||
|
if (charCode >= 'A'.code && charCode <= 'Z'.code && defaults[CaseMode.UPPER] != null)
|
||||||
|
data = defaults[CaseMode.UPPER];
|
||||||
|
else if (charCode >= 'a'.code && charCode <= 'z'.code && defaults[CaseMode.LOWER] != null)
|
||||||
|
data = defaults[CaseMode.LOWER];
|
||||||
|
else
|
||||||
|
data = defaults[CaseMode.NONE];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(data == null) {
|
||||||
failedLetters.push(char);
|
failedLetters.push(char);
|
||||||
return null;
|
return null;
|
||||||
}
|
} else if (data.isDefault)
|
||||||
|
loaded[defaults.indexOf(data)].push(char);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLetterAnim(char:String, data:AlphabetLetterData):FlxAnimation {
|
||||||
|
if (data == null) return null;
|
||||||
|
if (animation.exists(char)) return animation.getByName(char);
|
||||||
|
|
||||||
|
var anim = (data.isDefault) ? data.anim.replace("LETTER", char) : data.anim;
|
||||||
animation.addByPrefix(char, anim, fps);
|
animation.addByPrefix(char, anim, fps);
|
||||||
if (!animation.exists(char)) {
|
if (!animation.exists(char)) {
|
||||||
failedLetters.push(char);
|
failedLetters.push(char);
|
||||||
@@ -278,7 +310,7 @@ class NewAlphabet extends FlxSprite {
|
|||||||
return animation.getByName(char);
|
return animation.getByName(char);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkNode(node:Xml) {
|
function checkNode(node:Xml):Void {
|
||||||
switch (node.nodeName) {
|
switch (node.nodeName) {
|
||||||
case "spritesheet":
|
case "spritesheet":
|
||||||
if (frames == null)
|
if (frames == null)
|
||||||
@@ -288,25 +320,65 @@ class NewAlphabet extends FlxSprite {
|
|||||||
frames.pushFrame(frame);
|
frames.pushFrame(frame);
|
||||||
}
|
}
|
||||||
case "defaultAnim":
|
case "defaultAnim":
|
||||||
defaults.set(node.get("casing").getDefault("<NORMAL>").toUpperCase(), node.firstChild().nodeValue);
|
var idx = ["UPPER", "LOWER"].indexOf(node.get("casing").toUpperCase()) + 1;
|
||||||
|
|
||||||
|
var angle:Float = Std.parseFloat(node.get("angle")).getDefault(0.0);
|
||||||
|
var angleCos = Math.cos(angle);
|
||||||
|
var angleSin = Math.sin(angle);
|
||||||
|
|
||||||
|
defaults[idx] = {
|
||||||
|
isDefault: true,
|
||||||
|
anim: node.firstChild().nodeValue,
|
||||||
|
|
||||||
|
x: 0.0,
|
||||||
|
y: 0.0,
|
||||||
|
advance: defaultAdvance,
|
||||||
|
|
||||||
|
scaleX: Std.parseFloat(node.get("scaleX")).getDefault(1.0),
|
||||||
|
scaleY: Std.parseFloat(node.get("scaleY")).getDefault(1.0),
|
||||||
|
|
||||||
|
cos: angleCos,
|
||||||
|
sin: angleSin,
|
||||||
|
|
||||||
|
components: null
|
||||||
|
};
|
||||||
case "anim":
|
case "anim":
|
||||||
|
if(!node.exists("char")) throw "[Alphabet] <anim> must have a char attribute";
|
||||||
var char = node.get("char");
|
var char = node.get("char");
|
||||||
anims.set(char, node.firstChild().nodeValue);
|
|
||||||
if (node.exists("advance")) {
|
var angle:Float = Std.parseFloat(node.get("angle")).getDefault(0.0);
|
||||||
var advance = Std.parseFloat(node.get("advance")).getDefault(defaultAdvance);
|
var angleCos = Math.cos(angle);
|
||||||
advances.set(char, advance);
|
var angleSin = Math.sin(angle);
|
||||||
}
|
|
||||||
if (node.exists("x")) {
|
var xOff:Float = -Std.parseFloat(node.get("x")).getDefault(0.0);
|
||||||
// negative since flixel is weird
|
var yOff:Float = Std.parseFloat(node.get("y")).getDefault(0.0);
|
||||||
var xOff = -Std.parseFloat(node.get("x")).getDefault(0.0);
|
var advance:Null<Float> = (node.exists("advance")) ? {
|
||||||
xOffset.set(char, xOff);
|
var _:Null<Float> = Std.parseFloat(node.get("advance"));
|
||||||
}
|
if(CoolUtil.isNaN(_))
|
||||||
if (node.exists("y")) {
|
_ = null;
|
||||||
var yOff = Std.parseFloat(node.get("y")).getDefault(0.0);
|
_;
|
||||||
yOffset.set(char, yOff);
|
} : null;
|
||||||
}
|
|
||||||
case "languageSection":
|
letterData.set(char, {
|
||||||
|
isDefault: false,
|
||||||
|
anim: node.firstChild().nodeValue,
|
||||||
|
|
||||||
|
x: xOff,
|
||||||
|
y: yOff,
|
||||||
|
advance: advance,
|
||||||
|
|
||||||
|
scaleX: Std.parseFloat(node.get("scaleX")).getDefault(1.0),
|
||||||
|
scaleY: Std.parseFloat(node.get("scaleY")).getDefault(1.0),
|
||||||
|
|
||||||
|
cos: angleCos,
|
||||||
|
sin: angleSin,
|
||||||
|
|
||||||
|
components: null
|
||||||
|
});
|
||||||
|
case "languageSection": // used to only parse characters if a specific language is selected
|
||||||
|
if(!node.exists("langs")) throw "[Alphabet] <languageSection> must have a langs attribute";
|
||||||
var langs = [for (lang in node.get("langs").split(",")) lang.trim()];
|
var langs = [for (lang in node.get("langs").split(",")) lang.trim()];
|
||||||
|
// maybe add a way to toggle this off? like force it to add all
|
||||||
if (langs.contains(Options.language)) {
|
if (langs.contains(Options.language)) {
|
||||||
for (langNode in node.elements())
|
for (langNode in node.elements())
|
||||||
checkNode(langNode);
|
checkNode(langNode);
|
||||||
@@ -314,17 +386,15 @@ class NewAlphabet extends FlxSprite {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadFont(value:String) {
|
function loadFont(value:String):Void {
|
||||||
__queueResize = true;
|
__queueResize = true;
|
||||||
|
|
||||||
var xml:Xml = Xml.parse(Assets.getText(Paths.xml("alphabet/" + value))).firstElement();
|
var xml:Xml = Xml.parse(Assets.getText(Paths.xml("alphabet/" + value))).firstElement();
|
||||||
|
|
||||||
// reset old values
|
// reset old values
|
||||||
defaults = new Map();
|
letterData = new Map();
|
||||||
anims = new Map();
|
defaults = [null, null, null];
|
||||||
advances = new Map();
|
loaded = [[], [], []];
|
||||||
xOffset = new Map();
|
|
||||||
yOffset = new Map();
|
|
||||||
failedLetters = [];
|
failedLetters = [];
|
||||||
|
|
||||||
defaultAdvance = Std.parseFloat(xml.get("advance")).getDefault(40.0);
|
defaultAdvance = Std.parseFloat(xml.get("advance")).getDefault(40.0);
|
||||||
@@ -339,7 +409,7 @@ class NewAlphabet extends FlxSprite {
|
|||||||
checkNode(node);
|
checkNode(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
override function destroy() {
|
override function destroy():Void {
|
||||||
originOffset = FlxDestroyUtil.destroy(originOffset);
|
originOffset = FlxDestroyUtil.destroy(originOffset);
|
||||||
failedLetters = [];
|
failedLetters = [];
|
||||||
super.destroy();
|
super.destroy();
|
||||||
|
|||||||
Reference in New Issue
Block a user