From 8378ff2b56c94e8d7ff63d8d7f035557e17903e5 Mon Sep 17 00:00:00 2001 From: SrtHero278 Date: Thu, 28 Nov 2024 11:09:45 -0800 Subject: [PATCH] finished outlines might need more testing --- assets/data/alphabet/bold.xml | 4 +- source/funkin/menus/ui/Alphabet.hx | 161 ++++++++++++++++++----------- 2 files changed, 102 insertions(+), 63 deletions(-) diff --git a/assets/data/alphabet/bold.xml b/assets/data/alphabet/bold.xml index da24f577..0cf0db99 100644 --- a/assets/data/alphabet/bold.xml +++ b/assets/data/alphabet/bold.xml @@ -18,7 +18,7 @@ character-dollar character-doublequote0 character-equal - character-exclamationmark + character-exclamationmark0 character-hyphen character-percent character-period @@ -51,6 +51,6 @@ - + \ No newline at end of file diff --git a/source/funkin/menus/ui/Alphabet.hx b/source/funkin/menus/ui/Alphabet.hx index 12c3fac8..ed1b99a1 100644 --- a/source/funkin/menus/ui/Alphabet.hx +++ b/source/funkin/menus/ui/Alphabet.hx @@ -23,6 +23,7 @@ final class AlphabetOutline { } @:structInit final class AlphabetComponent { + @:optional public var refIndex:Null; public var anim:String; public var x:Float; public var y:Float; @@ -37,8 +38,6 @@ final class AlphabetComponent { public var hasColorMode:Bool; public var colorMode:ColorMode; - - @:optional public var outline:Null; } @:structInit @@ -47,6 +46,7 @@ final class AlphabetLetterData { public var advance:Float; public var advanceEmpty:Bool; public var components:Array; + public var startIndex:Int = 0; } enum abstract AlphabetAlignment(ByteUInt) from ByteUInt to ByteUInt { @@ -117,7 +117,8 @@ class Alphabet extends FlxSprite { public var effects:Array = []; var __renderData:AlphabetRenderData; var __component:AlphabetComponent; - var __outline:AlphabetOutline; + var __useDrawScale:Bool = false; + var __drawScale:FlxPoint = FlxPoint.get(1, 1); public var text(default, set):String = ""; @:isVar public var textWidth(get, set):Float; @@ -241,6 +242,7 @@ class Alphabet extends FlxSprite { var isMonospace = renderMode == MONOSPACE; for (i in 0...daText.length) { + var cantrace = i == daText.length - 1; __renderData.reset(this, ogRed, ogGreen, ogBlue, ogAlpha, daText.charAt(i)); for (effect in effects) { if (effect.willModify(i, i - lastLine, __renderData)) @@ -268,16 +270,40 @@ class Alphabet extends FlxSprite { for (i in 0...data.components.length) { __component = data.components[i]; var anim = getLetterAnim(letter, data, __component, i); + //if (cantrace) + //trace(anim.name + " | " + __component.anim + " | " + frames.frames[anim.frames[0]]); advance = (Math.isNaN(advance)) ? getAdvance(letter, anim, data) : advance; if (anim == null || __renderData.alpha <= 0.0) break; // shouldnt this be like continue? var frameToGet = frameTime % anim.numFrames; - var fillFrame = frames.frames[anim.frames[frameToGet]]; + frame = frames.frames[anim.frames[frameToGet]]; var offsetX = __component.x + __renderData.offsetX; - var offsetY = fillFrame.sourceSize.y - lineGap + __component.y + __renderData.offsetY; + var offsetY = frame.sourceSize.y - lineGap + __component.y + __renderData.offsetY; + __useDrawScale = false; + if (__component.refIndex != null) { + var actualIdx = __component.refIndex + data.startIndex; + //trace(__component.anim + " | " + data.components[actualIdx].anim); + var refAnim = getLetterAnim(letter, data, data.components[actualIdx], actualIdx); + var refFrameIdx = frameTime % refAnim.numFrames; + var refFrame = frames.frames[refAnim.frames[refFrameIdx]]; + + var diff = Math.min( + (frame.sourceSize.x - refFrame.sourceSize.x) * __component.scaleX, + (frame.sourceSize.y - refFrame.sourceSize.y) * __component.scaleY + ); + offsetX += diff * 0.5; + offsetY = refFrame.sourceSize.y - lineGap + __component.y + __renderData.offsetY + diff * 0.5; + + __useDrawScale = true; + __drawScale.set( + (refFrame.sourceSize.x * __component.scaleX + diff) / frame.sourceSize.x, + (refFrame.sourceSize.y * __component.scaleY + diff) / frame.sourceSize.y + ); + } + if (isMonospace) offsetX -= (defaultAdvance - advance) * 0.5; frameOffset.x += offsetX; @@ -293,29 +319,6 @@ class Alphabet extends FlxSprite { else colorMode.setColorTransform(colorTransform, __renderData.red, __renderData.green, __renderData.blue, __renderData.alpha); - if (__component.outline != null) { - __outline = __component.outline; - var outlineAnim = getLetterOutline(letter, __component, i); - if (outlineAnim != null) { - var frameToGet = frameTime % outlineAnim.numFrames; - frame = frames.frames[outlineAnim.frames[frameToGet]]; - - var offfx = (fillFrame.sourceSize.x - frame.sourceSize.x) * __component.scaleX + __outline.x; - var offfy = (fillFrame.sourceSize.y - frame.sourceSize.y) * __component.scaleY + __outline.y; - - frameOffset.x += offfx; - frameOffset.y += offfy; - - if (isGraphicsShader) - shader.setCamSize(_frame.frame.x, _frame.frame.y, _frame.frame.width, _frame.frame.height); - - drawLetter(camera); - frameOffset.x -= offfx; - frameOffset.y -= offfy; - } - } - - frame = fillFrame; if (isGraphicsShader) shader.setCamSize(_frame.frame.x, _frame.frame.y, _frame.frame.width, _frame.frame.height); drawLetter(camera); @@ -335,7 +338,10 @@ class Alphabet extends FlxSprite { _frame.prepareMatrix(_matrix, ANGLE_0, checkFlipX() != camera.flipX, checkFlipY() != camera.flipY); _matrix.translate(_frame.frame.width * -0.5, _frame.frame.height * -0.5); - _matrix.scale(__component.scaleX, __component.scaleY); + if (__useDrawScale) + _matrix.scale(__drawScale.x, __drawScale.y); + else + _matrix.scale(__component.scaleX, __component.scaleY); if(__component.shouldRotate) _matrix.rotateWithTrig(__component.cos, __component.sin); _matrix.translate(_frame.frame.width * 0.5, _frame.frame.height * 0.5); @@ -409,7 +415,7 @@ class Alphabet extends FlxSprite { } var data = getData(letter); - __laneWidths[curLine] += (data != null) ? getAdvance(letter, getLetterAnim(letter, data, data.components[0], 0), data) : defaultAdvance; + __laneWidths[curLine] += (data != null) ? getAdvance(letter, getLetterAnim(letter, data, data.components[data.startIndex], data.startIndex), data) : defaultAdvance; @:bypassAccessor textWidth = Math.max(textWidth, __laneWidths[curLine]); } @@ -495,7 +501,7 @@ class Alphabet extends FlxSprite { return animation.getByName(name); } - function getLetterOutline(char:String, component:AlphabetComponent, index:Int) { + /*function getLetterOutline(char:String, component:AlphabetComponent, index:Int) { var name = char + "Outline" + Std.string(index); if (failedOutlines.contains(name)) return null; if (animation.exists(name)) return animation.getByName(name); @@ -506,7 +512,7 @@ class Alphabet extends FlxSprite { return null; } return animation.getByName(name); - } + }*/ function checkNode(node:Xml):Void { switch (node.nodeName) { @@ -544,7 +550,8 @@ class Alphabet extends FlxSprite { hasColorMode: false, colorMode: 0 - }] + }], + startIndex: 0 } defaults[idx] = res; @@ -553,6 +560,8 @@ class Alphabet extends FlxSprite { Logs.error(" must have a char attribute", "Alphabet"); return; } + var startIndex:Int = 0; + var componentsPushed:Int = 0; var char = node.get("char"); var advance:Float = Std.parseFloat(node.get("advance")); var components:Array = []; @@ -569,16 +578,30 @@ class Alphabet extends FlxSprite { var xOff:Float = -Std.parseFloat(component.get("x")).getDefaultFloat(0.0); var yOff:Float = Std.parseFloat(component.get("y")).getDefaultFloat(0.0); + var xScale:Float = Std.parseFloat(component.get("scaleX")).getDefaultFloat(1.0); + var yScale:Float = Std.parseFloat(component.get("scaleY")).getDefaultFloat(1.0); var colorMode = ["tint", "offsets", "none"].indexOf(component.get("colorMode")); - var outline:AlphabetOutline = null; if (component.get("hasOutline") == "true") { - outline = { + components.insert(startIndex, { + refIndex: componentsPushed, anim: component.get("outline"), - x: Std.parseFloat(component.get("outlineX")).getDefaultFloat(0.0), - y: Std.parseFloat(component.get("outlineY")).getDefaultFloat(0.0) - } + + x: xOff + Std.parseFloat(component.get("outlineX")).getDefaultFloat(0.0) * xScale, + y: yOff + Std.parseFloat(component.get("outlineY")).getDefaultFloat(0.0) * yScale, + scaleX: xScale, + scaleY: yScale, + + shouldRotate: angle != 0, + angle: angle, + cos: angleCos, + sin: angleSin, + + hasColorMode: colorMode >= 0, + colorMode: colorMode, + }); + ++startIndex; } components.push({ @@ -586,8 +609,8 @@ class Alphabet extends FlxSprite { x: xOff, y: yOff, - scaleX: Std.parseFloat(component.get("scaleX")).getDefaultFloat(1.0), - scaleY: Std.parseFloat(component.get("scaleY")).getDefaultFloat(1.0), + scaleX: xScale, + scaleY: yScale, shouldRotate: angle != 0, angle: angle, @@ -596,14 +619,15 @@ class Alphabet extends FlxSprite { hasColorMode: colorMode >= 0, colorMode: colorMode, - outline: outline }); + ++componentsPushed; } letterData.set(char, { isDefault: false, advance: advance, advanceEmpty: Math.isNaN(advance), - components: components + components: components, + startIndex: startIndex }); case "anim": if(!node.exists("char")) { @@ -619,30 +643,22 @@ class Alphabet extends FlxSprite { var xOff:Float = -Std.parseFloat(node.get("x")).getDefaultFloat(0.0); var yOff:Float = Std.parseFloat(node.get("y")).getDefaultFloat(0.0); + var xScale:Float = Std.parseFloat(node.get("scaleX")).getDefaultFloat(1.0); + var yScale:Float = Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0); var advance:Float = Std.parseFloat(node.get("advance")); var colorMode = ["tint", "offsets", "none"].indexOf(node.get("colorMode")); - var outline:AlphabetOutline = null; + var components:Array = []; if (node.get("hasOutline") == "true") { - outline = { + components.insert(0, { + refIndex: 0, anim: node.get("outline"), - x: Std.parseFloat(node.get("outlineX")).getDefaultFloat(0.0), - y: Std.parseFloat(node.get("outlineY")).getDefaultFloat(0.0) - } - } - letterData.set(char, { - isDefault: false, - advance: advance, - advanceEmpty: Math.isNaN(advance), - components: [{ - anim: node.firstChild().nodeValue, - - x: xOff, - y: yOff, - scaleX: Std.parseFloat(node.get("scaleX")).getDefaultFloat(1.0), - scaleY: Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0), + x: xOff + Std.parseFloat(node.get("outlineX")).getDefaultFloat(0.0) * xScale, + y: yOff + Std.parseFloat(node.get("outlineY")).getDefaultFloat(0.0) * yScale, + scaleX: xScale, + scaleY: yScale, shouldRotate: angle != 0, angle: angle, @@ -651,8 +667,31 @@ class Alphabet extends FlxSprite { hasColorMode: colorMode >= 0, colorMode: colorMode, - outline: outline - }] + }); + } + + components.push({ + anim: node.firstChild().nodeValue, + + x: xOff, + y: yOff, + scaleX: xScale, + scaleY: yScale, + + shouldRotate: angle != 0, + angle: angle, + cos: angleCos, + sin: angleSin, + + hasColorMode: colorMode >= 0, + colorMode: colorMode, + }); + letterData.set(char, { + isDefault: false, + advance: advance, + advanceEmpty: Math.isNaN(advance), + components: components, + startIndex: (node.get("hasOutline") == "true") ? 1 : 0 }); case "languageSection": // used to only parse characters if a specific language is selected if(!node.exists("langs")) {