Merge branch 'translations-system' into alphabet-editor

This commit is contained in:
Ne_Eo
2024-11-03 22:48:11 +01:00
82 changed files with 2091 additions and 1388 deletions
+2 -2
View File
@@ -12,8 +12,8 @@ Also, the command `.\cne test` uses the source assets folder instead of the expo
## Codename Engine
Codename Engine is a new Friday Night Funkin' Engine aimed at simplifying modding, along with extensiblity and ease of use.<br>
Make sure to read the wiki and join the Discord server linked there!<br>
#### It includes many new features, as seen [here](FEATURES.md)<br>
### Before making issues or need help with something, check our website [HERE](https://fnf-cne-devs.github.io/) (it contains a wiki of how to mod with EXAMPLES, an api, lists of mods made with Codename Engine and more)!!!
#### The Engine includes many new features, as seen [here](FEATURES.md)<br>
#### Wanna see the new features added in the most recent update? Click [here](PATCHNOTES.md)<br>
## How to download
Binary file not shown.
+70 -27
View File
@@ -2,33 +2,76 @@
<letters fps="24">
<bold spritesheet="menus/alphabet-bold">
<!-- Bold Letters !-->
<letter char="A" anim="A bold" />
<letter char="B" anim="B bold" />
<letter char="C" anim="C bold" />
<letter char="D" anim="D bold" />
<letter char="E" anim="E bold" />
<letter char="F" anim="F bold" />
<letter char="G" anim="G bold" />
<letter char="H" anim="H bold" />
<letter char="I" anim="I bold" />
<letter char="J" anim="J bold" />
<letter char="K" anim="K bold" />
<letter char="L" anim="L bold" />
<letter char="M" anim="M bold" />
<letter char="N" anim="N bold" />
<letter char="O" anim="O bold" />
<letter char="P" anim="P bold" />
<letter char="Q" anim="Q bold" />
<letter char="R" anim="R bold" />
<letter char="S" anim="S bold" />
<letter char="T" anim="T bold" />
<letter char="U" anim="U bold" />
<letter char="V" anim="V bold" />
<letter char="W" anim="W bold" />
<letter char="X" anim="X bold" />
<letter char="Y" anim="Y bold" />
<letter char="Z" anim="Z bold" />
<letter char=">" anim="> Bold" />
<letter char="A" anim="character-a" />
<letter char="B" anim="character-b" />
<letter char="C" anim="character-c" />
<letter char="D" anim="character-d" />
<letter char="E" anim="character-e" />
<letter char="F" anim="character-f" />
<letter char="G" anim="character-g" />
<letter char="H" anim="character-h" />
<letter char="I" anim="character-i" />
<letter char="J" anim="character-j" />
<letter char="K" anim="character-k" />
<letter char="L" anim="character-l" />
<letter char="M" anim="character-m" />
<letter char="N" anim="character-n" />
<letter char="O" anim="character-o" />
<letter char="P" anim="character-p" />
<letter char="Q" anim="character-q" />
<letter char="R" anim="character-r" />
<letter char="S" anim="character-s" />
<letter char="T" anim="character-t" />
<letter char="U" anim="character-u" />
<letter char="V" anim="character-v" />
<letter char="W" anim="character-w" />
<letter char="X" anim="character-x" />
<letter char="Y" anim="character-y" />
<letter char="Z" anim="character-z" />
<letter char="&amp;" anim="character-ampersand" />
<letter char="&lt;" anim="character-anglebracket-left" />
<letter char="&gt;" anim="character-anglebracket-right" />
<letter char="*" anim="character-asterisk" />
<letter char="@" anim="character-at" />
<letter char="\" anim="character-backslash" />
<letter char="`" anim="character-backtick" />
<letter char="^" anim="character-caret" />
<letter char=":" anim="character-colon" />
<letter char="," anim="character-comma" />
<letter char="{" anim="character-curlybracket-left" />
<letter char="}" anim="character-curlybracket-right" />
<letter char="$" anim="character-dollar" />
<letter char='"' anim="character-doublequote" />
<letter char="=" anim="character-equal" />
<letter char="!" anim="character-exclamationmark" />
<letter char="-" anim="character-hyphen" />
<letter char="%" anim="character-percent" />
<letter char="." anim="character-period" />
<letter char="+" anim="character-plus" />
<letter char="#" anim="character-pound" />
<letter char="?" anim="character-questionmark" />
<letter char="(" anim="character-roundbracket-left" />
<letter char=")" anim="character-roundbracket-right" />
<letter char=";" anim="character-semicolon" />
<letter char="'" anim="character-singlequote" />
<letter char="/" anim="character-slash" />
<letter char="[" anim="character-squarebracket-left" />
<letter char="]" anim="character-squarebracket-right" />
<letter char="~" anim="character-tilde" />
<letter char="_" anim="character-underscore" />
<letter char="|" anim="character-verticalbar" />
<letter char="0" anim="character-zero" />
<letter char="1" anim="character-one" />
<letter char="2" anim="character-two" />
<letter char="3" anim="character-three" />
<letter char="4" anim="character-four" />
<letter char="5" anim="character-five" />
<letter char="6" anim="character-six" />
<letter char="7" anim="character-seven" />
<letter char="8" anim="character-eight" />
<letter char="9" anim="character-nine" />
</bold>
<normal spritesheet="menus/alphabet">
<!-- Symbols !-->
+45 -2
View File
@@ -1,6 +1,49 @@
<!DOCTYPE codename-engine-alphabet-font>
<alphabetFont fps="24" advance="50" lineGap="75" forceCasing="upper">
<alphabetFont fps="24" advance="50" lineGap="75" forceCasing="lower">
<spritesheet>menus/alphabet-bold</spritesheet>
<defaultAnim>LETTER bold</defaultAnim>
<defaultAnim>character-LETTER0</defaultAnim>
<anim char="&amp;">character-ampersand</anim>
<anim char="&lt;">character-anglebracket-left</anim>
<anim char="&gt;">character-anglebracket-right</anim>
<anim char="*" y="30">character-asterisk</anim>
<anim char="@">character-at</anim>
<anim char="\">character-backslash</anim>
<anim char="`" y="40">character-backtick</anim>
<anim char="^" y="30">character-caret</anim>
<anim char=":" y="10">character-colon</anim>
<anim char="," y="-15">character-comma</anim>
<anim char="{">character-curlybracket-left</anim>
<anim char="}">character-curlybracket-right</anim>
<anim char="$">character-dollar</anim>
<anim char='"' y="35">character-doublequote0</anim>
<anim char="=" y="20">character-equal</anim>
<anim char="!">character-exclamationmark</anim>
<anim char="-" y="25">character-hyphen</anim>
<anim char="%">character-percent</anim>
<anim char=".">character-period</anim>
<anim char="+" y="10">character-plus</anim>
<anim char="#">character-pound</anim>
<anim char="?">character-questionmark0</anim>
<anim char="(">character-roundbracket-left</anim>
<anim char=")">character-roundbracket-right</anim>
<anim char=";" y="-15">character-semicolon</anim>
<anim char="'" y="35">character-singlequote</anim>
<anim char="/">character-slash</anim>
<anim char="[">character-squarebracket-left</anim>
<anim char="]">character-squarebracket-right</anim>
<anim char="~" y="20">character-tilde0</anim>
<anim char="_">character-underscore0</anim>
<anim char="|">character-verticalbar0</anim>
<anim char="0">character-zero</anim>
<anim char="1">character-one</anim>
<anim char="2">character-two</anim>
<anim char="3">character-three</anim>
<anim char="4">character-four</anim>
<anim char="5">character-five</anim>
<anim char="6">character-six</anim>
<anim char="7">character-seven</anim>
<anim char="8">character-eight</anim>
<anim char="9">character-nine</anim>
</alphabetFont>
+6 -2
View File
@@ -1,13 +1,17 @@
<!DOCTYPE codename-engine-alphabet-font>
<alphabetFont fps="24" advance="30" lineGap="70" useColorOffsets="true">
<alphabetFont fps="24" advance="30" lineGap="70" colorMode="offsets">
<spritesheet>menus/alphabet</spritesheet>
<defaultAnim casing="upper">LETTER capital</defaultAnim>
<defaultAnim casing="lower">LETTER lowercase</defaultAnim>
<defaultAnim>LETTER</defaultAnim>
<anim char="g" y="-15">g lowercase</anim>
<anim char="j" y="-15">j lowercase</anim>
<anim char="p" y="-15">p lowercase</anim>
<anim char="q" y="-15">q lowercase</anim>
<anim char="y" y="-15">y lowercase</anim>
<anim char="$">dollarsign</anim>
<anim char="#">hashtag</anim>
<anim char="&amp;">amp</anim>
<anim char="→" y="9">right arrow</anim>
<anim char="←" y="9">left arrow</anim>
-7
View File
@@ -1,7 +0,0 @@
<!DOCTYPE codename-mod-credits>
<!-- TEMPLATE FOR CUSTOM CREDITS!!! -->
<menu name="Mod Credits" desc="Modify mod credits here">
<!-- \/ You can also set the portrait shader as false as you can see below in the github one -->
<credit name="Credit Example" desc="Click me to know more about me!" icon="credit icon example" size="130" url="https://youtu.be/fugtxz1znVw"/>
<github user="NexIsDumb" customName="Nex is Dumb" desc="The bitch who made these credits menus" size="100" portrait="false" color="#808080"/>
</menu>
-15
View File
@@ -1,15 +0,0 @@
<!DOCTYPE codename-mod-options>
<!-- TEMPLATE FOR CUSTOM OPTIONS!!! -->
<menu name="Mod Options" desc="Modify mod options here">
<checkbox id="checkboxExample" name="Checkbox example" />
<number id="numberExample" name="Number example" min="0" max="10" change="1"/>
<choice id="choiceExample" name="Choice Example">
<value name="Disabled" value="disabled"/>
<value name="This only" value="thisOnly"/>
<value name="All" value="all"/>
</choice>
<menu name="Submenu Example" desc="Submenu test">
<checkbox id="levelOfIdk2" name="Level of idk" />
</menu>
</menu>
+2 -2
View File
@@ -1,6 +1,6 @@
function postHide() {
if(curTween != null) {
if(animation.curAnim?.name == 'angry-show') curTween.cancel();
if(getAnimName() == 'angry-show') curTween.cancel();
else curTween.percent = 1;
}
}
}
+1 -1
View File
@@ -7,7 +7,7 @@
<anim name="danceRight" anim="gfDance" indices="15,16,17,18,19,20,21,22,23,24,25,26,27,28,29" />
</sprite>
<titleEnter sprite="titleEnter" x="-150" y="-100" />
<!-- <titleEnter sprite="titleEnter" x="100" y="576" /> --> <!-- FlxG.height * 0.8 -->
</sprites>
<intro length="16">
Binary file not shown.
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 179 KiB

+514 -153
View File
@@ -1,153 +1,514 @@
<?xml version="1.0" encoding="utf-8"?>
<TextureAtlas imagePath="Alphabet_Bold.png">
<!-- Created with Adobe Animate version 23.0.0.407 -->
<!-- http://www.adobe.com/products/animate.html -->
<SubTexture name="0 bold0000" x="0" y="0" width="56" height="74"/>
<SubTexture name="0 bold0001" x="0" y="0" width="56" height="74"/>
<SubTexture name="0 bold0002" x="56" y="0" width="56" height="74"/>
<SubTexture name="0 bold0003" x="56" y="0" width="56" height="74"/>
<SubTexture name="1 bold0000" x="112" y="0" width="52" height="70"/>
<SubTexture name="1 bold0001" x="112" y="0" width="52" height="70"/>
<SubTexture name="1 bold0002" x="164" y="0" width="52" height="70"/>
<SubTexture name="1 bold0003" x="164" y="0" width="52" height="70"/>
<SubTexture name="2 bold0000" x="216" y="0" width="59" height="73"/>
<SubTexture name="2 bold0001" x="216" y="0" width="59" height="73"/>
<SubTexture name="2 bold0002" x="275" y="0" width="59" height="73"/>
<SubTexture name="2 bold0003" x="275" y="0" width="59" height="73"/>
<SubTexture name="3 bold0000" x="334" y="0" width="57" height="72"/>
<SubTexture name="3 bold0001" x="334" y="0" width="57" height="72"/>
<SubTexture name="3 bold0002" x="391" y="0" width="56" height="72" frameX="0" frameY="0" frameWidth="57" frameHeight="72"/>
<SubTexture name="3 bold0003" x="391" y="0" width="56" height="72" frameX="0" frameY="0" frameWidth="57" frameHeight="72"/>
<SubTexture name="4 bold0000" x="447" y="0" width="58" height="69"/>
<SubTexture name="4 bold0001" x="447" y="0" width="58" height="69"/>
<SubTexture name="4 bold0002" x="505" y="0" width="58" height="69"/>
<SubTexture name="4 bold0003" x="505" y="0" width="58" height="69"/>
<SubTexture name="5 bold0000" x="563" y="0" width="56" height="71" frameX="0" frameY="0" frameWidth="56" frameHeight="72"/>
<SubTexture name="5 bold0001" x="563" y="0" width="56" height="71" frameX="0" frameY="0" frameWidth="56" frameHeight="72"/>
<SubTexture name="5 bold0002" x="619" y="0" width="56" height="72"/>
<SubTexture name="5 bold0003" x="619" y="0" width="56" height="72"/>
<SubTexture name="6 bold0000" x="675" y="0" width="53" height="68"/>
<SubTexture name="6 bold0001" x="675" y="0" width="53" height="68"/>
<SubTexture name="6 bold0002" x="728" y="0" width="53" height="68"/>
<SubTexture name="6 bold0003" x="728" y="0" width="53" height="68"/>
<SubTexture name="7 bold0000" x="781" y="0" width="54" height="73"/>
<SubTexture name="7 bold0001" x="781" y="0" width="54" height="73"/>
<SubTexture name="7 bold0002" x="835" y="0" width="54" height="73"/>
<SubTexture name="7 bold0003" x="835" y="0" width="54" height="73"/>
<SubTexture name="8 bold0000" x="889" y="0" width="54" height="70"/>
<SubTexture name="8 bold0001" x="889" y="0" width="54" height="70"/>
<SubTexture name="8 bold0002" x="943" y="0" width="54" height="70"/>
<SubTexture name="8 bold0003" x="943" y="0" width="54" height="70"/>
<SubTexture name="9 bold0000" x="0" y="74" width="53" height="68"/>
<SubTexture name="9 bold0001" x="0" y="74" width="53" height="68"/>
<SubTexture name="9 bold0002" x="53" y="74" width="53" height="67" frameX="0" frameY="0" frameWidth="53" frameHeight="68"/>
<SubTexture name="9 bold0003" x="53" y="74" width="53" height="67" frameX="0" frameY="0" frameWidth="53" frameHeight="68"/>
<SubTexture name="> Bold0000" x="106" y="74" width="51" height="73" frameX="0" frameY="0" frameWidth="52" frameHeight="73"/>
<SubTexture name="> Bold0001" x="106" y="74" width="51" height="73" frameX="0" frameY="0" frameWidth="52" frameHeight="73"/>
<SubTexture name="> Bold0002" x="157" y="74" width="52" height="73"/>
<SubTexture name="> Bold0003" x="157" y="74" width="52" height="73"/>
<SubTexture name="A bold0000" x="209" y="74" width="54" height="67"/>
<SubTexture name="A bold0001" x="209" y="74" width="54" height="67"/>
<SubTexture name="A bold0002" x="263" y="74" width="54" height="67"/>
<SubTexture name="A bold0003" x="263" y="74" width="54" height="67"/>
<SubTexture name="B bold0000" x="317" y="74" width="46" height="70"/>
<SubTexture name="B bold0001" x="317" y="74" width="46" height="70"/>
<SubTexture name="B bold0002" x="363" y="74" width="46" height="70"/>
<SubTexture name="B bold0003" x="363" y="74" width="46" height="70"/>
<SubTexture name="C bold0000" x="409" y="74" width="55" height="66"/>
<SubTexture name="C bold0001" x="409" y="74" width="55" height="66"/>
<SubTexture name="C bold0002" x="464" y="74" width="54" height="65" frameX="0" frameY="-1" frameWidth="55" frameHeight="66"/>
<SubTexture name="C bold0003" x="464" y="74" width="54" height="65" frameX="0" frameY="-1" frameWidth="55" frameHeight="66"/>
<SubTexture name="D bold0000" x="518" y="74" width="53" height="67"/>
<SubTexture name="D bold0001" x="518" y="74" width="53" height="67"/>
<SubTexture name="D bold0002" x="571" y="74" width="53" height="67"/>
<SubTexture name="D bold0003" x="571" y="74" width="53" height="67"/>
<SubTexture name="E bold0000" x="624" y="74" width="43" height="66"/>
<SubTexture name="E bold0001" x="624" y="74" width="43" height="66"/>
<SubTexture name="E bold0002" x="667" y="74" width="43" height="66"/>
<SubTexture name="E bold0003" x="667" y="74" width="43" height="66"/>
<SubTexture name="F bold0000" x="710" y="74" width="43" height="67"/>
<SubTexture name="F bold0001" x="710" y="74" width="43" height="67"/>
<SubTexture name="F bold0002" x="753" y="74" width="43" height="67"/>
<SubTexture name="F bold0003" x="753" y="74" width="43" height="67"/>
<SubTexture name="G bold0000" x="796" y="74" width="54" height="70"/>
<SubTexture name="G bold0001" x="796" y="74" width="54" height="70"/>
<SubTexture name="G bold0002" x="850" y="74" width="54" height="70"/>
<SubTexture name="G bold0003" x="850" y="74" width="54" height="70"/>
<SubTexture name="H bold0000" x="904" y="74" width="45" height="66"/>
<SubTexture name="H bold0001" x="904" y="74" width="45" height="66"/>
<SubTexture name="H bold0002" x="949" y="74" width="44" height="66" frameX="0" frameY="0" frameWidth="45" frameHeight="66"/>
<SubTexture name="H bold0003" x="949" y="74" width="44" height="66" frameX="0" frameY="0" frameWidth="45" frameHeight="66"/>
<SubTexture name="I bold0000" x="0" y="147" width="43" height="64"/>
<SubTexture name="I bold0001" x="0" y="147" width="43" height="64"/>
<SubTexture name="I bold0002" x="43" y="147" width="43" height="64"/>
<SubTexture name="I bold0003" x="43" y="147" width="43" height="64"/>
<SubTexture name="J bold0000" x="86" y="147" width="54" height="70"/>
<SubTexture name="J bold0001" x="86" y="147" width="54" height="70"/>
<SubTexture name="J bold0002" x="140" y="147" width="54" height="70"/>
<SubTexture name="J bold0003" x="140" y="147" width="54" height="70"/>
<SubTexture name="K bold0000" x="194" y="147" width="44" height="69"/>
<SubTexture name="K bold0001" x="194" y="147" width="44" height="69"/>
<SubTexture name="K bold0002" x="238" y="147" width="44" height="69"/>
<SubTexture name="K bold0003" x="238" y="147" width="44" height="69"/>
<SubTexture name="L bold0000" x="282" y="147" width="41" height="66"/>
<SubTexture name="L bold0001" x="282" y="147" width="41" height="66"/>
<SubTexture name="L bold0002" x="323" y="147" width="41" height="66"/>
<SubTexture name="L bold0003" x="323" y="147" width="41" height="66"/>
<SubTexture name="M bold0000" x="364" y="147" width="56" height="63"/>
<SubTexture name="M bold0001" x="364" y="147" width="56" height="63"/>
<SubTexture name="M bold0002" x="420" y="147" width="56" height="63"/>
<SubTexture name="M bold0003" x="420" y="147" width="56" height="63"/>
<SubTexture name="N bold0000" x="476" y="147" width="45" height="65"/>
<SubTexture name="N bold0001" x="476" y="147" width="45" height="65"/>
<SubTexture name="N bold0002" x="521" y="147" width="45" height="65"/>
<SubTexture name="N bold0003" x="521" y="147" width="45" height="65"/>
<SubTexture name="O bold0000" x="566" y="147" width="50" height="69"/>
<SubTexture name="O bold0001" x="566" y="147" width="50" height="69"/>
<SubTexture name="O bold0002" x="616" y="147" width="50" height="69"/>
<SubTexture name="O bold0003" x="616" y="147" width="50" height="69"/>
<SubTexture name="P bold0000" x="666" y="147" width="46" height="70"/>
<SubTexture name="P bold0001" x="666" y="147" width="46" height="70"/>
<SubTexture name="P bold0002" x="712" y="147" width="46" height="70"/>
<SubTexture name="P bold0003" x="712" y="147" width="46" height="70"/>
<SubTexture name="Q bold0000" x="758" y="147" width="52" height="67"/>
<SubTexture name="Q bold0001" x="758" y="147" width="52" height="67"/>
<SubTexture name="Q bold0002" x="810" y="147" width="52" height="67"/>
<SubTexture name="Q bold0003" x="810" y="147" width="52" height="67"/>
<SubTexture name="R bold0000" x="862" y="147" width="47" height="66"/>
<SubTexture name="R bold0001" x="862" y="147" width="47" height="66"/>
<SubTexture name="R bold0002" x="909" y="147" width="47" height="66"/>
<SubTexture name="R bold0003" x="909" y="147" width="47" height="66"/>
<SubTexture name="S bold0000" x="956" y="147" width="49" height="66"/>
<SubTexture name="S bold0001" x="956" y="147" width="49" height="66"/>
<SubTexture name="S bold0002" x="0" y="217" width="49" height="66"/>
<SubTexture name="S bold0003" x="0" y="217" width="49" height="66"/>
<SubTexture name="T bold0000" x="49" y="217" width="44" height="64"/>
<SubTexture name="T bold0001" x="49" y="217" width="44" height="64"/>
<SubTexture name="T bold0002" x="93" y="217" width="44" height="64"/>
<SubTexture name="T bold0003" x="93" y="217" width="44" height="64"/>
<SubTexture name="U bold0000" x="137" y="217" width="44" height="59"/>
<SubTexture name="U bold0001" x="137" y="217" width="44" height="59"/>
<SubTexture name="U bold0002" x="181" y="217" width="44" height="59"/>
<SubTexture name="U bold0003" x="181" y="217" width="44" height="59"/>
<SubTexture name="V bold0000" x="225" y="217" width="54" height="66"/>
<SubTexture name="V bold0001" x="225" y="217" width="54" height="66"/>
<SubTexture name="V bold0002" x="279" y="217" width="54" height="66"/>
<SubTexture name="V bold0003" x="279" y="217" width="54" height="66"/>
<SubTexture name="W bold0000" x="333" y="217" width="58" height="63"/>
<SubTexture name="W bold0001" x="333" y="217" width="58" height="63"/>
<SubTexture name="W bold0002" x="391" y="217" width="58" height="63"/>
<SubTexture name="W bold0003" x="391" y="217" width="58" height="63"/>
<SubTexture name="X bold0000" x="449" y="217" width="55" height="67"/>
<SubTexture name="X bold0001" x="449" y="217" width="55" height="67"/>
<SubTexture name="X bold0002" x="504" y="217" width="55" height="67"/>
<SubTexture name="X bold0003" x="504" y="217" width="55" height="67"/>
<SubTexture name="Y bold0000" x="559" y="217" width="54" height="69"/>
<SubTexture name="Y bold0001" x="559" y="217" width="54" height="69"/>
<SubTexture name="Y bold0002" x="613" y="217" width="54" height="69"/>
<SubTexture name="Y bold0003" x="613" y="217" width="54" height="69"/>
<SubTexture name="Z bold0000" x="667" y="217" width="52" height="65"/>
<SubTexture name="Z bold0001" x="667" y="217" width="52" height="65"/>
<SubTexture name="Z bold0002" x="719" y="217" width="52" height="65"/>
<SubTexture name="Z bold0003" x="719" y="217" width="52" height="65"/>
</TextureAtlas>
<?xml version="1.0" encoding="UTF-8"?>
<!--
Created with Funkin Packer v0.1.3 https://neeeoo.github.io/funkin-packer/
-->
<TextureAtlas imagePath="alphabet-bold.png" width="768" height="805">
<SubTexture name="character-a0000" x="49" y="364" width="54" height="67" frameX="-0" frameY="-0" frameWidth="54" frameHeight="67"/>
<SubTexture name="character-a0001" x="49" y="364" width="54" height="67" frameX="-0" frameY="-0" frameWidth="54" frameHeight="67"/>
<SubTexture name="character-a0002" x="232" y="359" width="54" height="67" frameX="-0" frameY="-0" frameWidth="54" frameHeight="67"/>
<SubTexture name="character-a0003" x="232" y="359" width="54" height="67" frameX="-0" frameY="-0" frameWidth="54" frameHeight="67"/>
<SubTexture name="character-ampersand0000" x="2" y="216" width="58" height="68" frameX="-0" frameY="-0" frameWidth="59" frameHeight="68"/>
<SubTexture name="character-ampersand0001" x="2" y="216" width="58" height="68" frameX="-0" frameY="-0" frameWidth="59" frameHeight="68"/>
<SubTexture name="character-ampersand0002" x="123" y="213" width="58" height="68" frameX="-0" frameY="-0" frameWidth="59" frameHeight="68"/>
<SubTexture name="character-ampersand0003" x="123" y="213" width="58" height="68" frameX="-0" frameY="-0" frameWidth="59" frameHeight="68"/>
<SubTexture name="character-anglebracket-left0000" x="610" y="209" width="42" height="68" frameX="-0" frameY="-0" frameWidth="42" frameHeight="68"/>
<SubTexture name="character-anglebracket-left0001" x="610" y="209" width="42" height="68" frameX="-0" frameY="-0" frameWidth="42" frameHeight="68"/>
<SubTexture name="character-anglebracket-left0002" x="614" y="70" width="42" height="68" frameX="-0" frameY="-0" frameWidth="42" frameHeight="68"/>
<SubTexture name="character-anglebracket-left0003" x="614" y="70" width="42" height="68" frameX="-0" frameY="-0" frameWidth="42" frameHeight="68"/>
<SubTexture name="character-anglebracket-right0000" x="423" y="570" width="44" height="69" frameX="-0" frameY="-0" frameWidth="45" frameHeight="69"/>
<SubTexture name="character-anglebracket-right0001" x="423" y="570" width="44" height="69" frameX="-0" frameY="-0" frameWidth="45" frameHeight="69"/>
<SubTexture name="character-anglebracket-right0002" x="568" y="71" width="44" height="69" frameX="-0" frameY="-0" frameWidth="45" frameHeight="69"/>
<SubTexture name="character-anglebracket-right0003" x="568" y="71" width="44" height="69" frameX="-0" frameY="-0" frameWidth="45" frameHeight="69"/>
<SubTexture name="character-ash0000" x="82" y="2" width="75" height="68" frameX="-0" frameY="-0" frameWidth="75" frameHeight="68"/>
<SubTexture name="character-ash0001" x="82" y="2" width="75" height="68" frameX="-0" frameY="-0" frameWidth="75" frameHeight="68"/>
<SubTexture name="character-ash0002" x="82" y="72" width="75" height="68" frameX="-0" frameY="-0" frameWidth="75" frameHeight="68"/>
<SubTexture name="character-ash0003" x="82" y="72" width="75" height="68" frameX="-0" frameY="-0" frameWidth="75" frameHeight="68"/>
<SubTexture name="character-asterisk0000" x="504" y="365" width="40" height="33" frameX="-0" frameY="-0" frameWidth="40" frameHeight="33"/>
<SubTexture name="character-asterisk0001" x="504" y="365" width="40" height="33" frameX="-0" frameY="-0" frameWidth="40" frameHeight="33"/>
<SubTexture name="character-asterisk0002" x="722" y="413" width="40" height="33" frameX="-0" frameY="-0" frameWidth="40" frameHeight="33"/>
<SubTexture name="character-asterisk0003" x="722" y="413" width="40" height="33" frameX="-0" frameY="-0" frameWidth="40" frameHeight="33"/>
<SubTexture name="character-at0000" x="82" y="142" width="66" height="68" frameX="-0" frameY="-0" frameWidth="66" frameHeight="68"/>
<SubTexture name="character-at0001" x="82" y="142" width="66" height="68" frameX="-0" frameY="-0" frameWidth="66" frameHeight="68"/>
<SubTexture name="character-at0002" x="2" y="146" width="66" height="68" frameX="-0" frameY="-0" frameWidth="66" frameHeight="68"/>
<SubTexture name="character-at0003" x="2" y="146" width="66" height="68" frameX="-0" frameY="-0" frameWidth="66" frameHeight="68"/>
<SubTexture name="character-b0000" x="551" y="365" width="46" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-b0001" x="551" y="365" width="46" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-b0002" x="213" y="563" width="45" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-b0003" x="213" y="563" width="45" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-backslash0000" x="463" y="227" width="51" height="67" frameX="-0" frameY="-0" frameWidth="51" frameHeight="67"/>
<SubTexture name="character-backslash0001" x="463" y="227" width="51" height="67" frameX="-0" frameY="-0" frameWidth="51" frameHeight="67"/>
<SubTexture name="character-backslash0002" x="504" y="296" width="51" height="67" frameX="-0" frameY="-0" frameWidth="51" frameHeight="67"/>
<SubTexture name="character-backslash0003" x="504" y="296" width="51" height="67" frameX="-0" frameY="-0" frameWidth="51" frameHeight="67"/>
<SubTexture name="character-backtick0000" x="731" y="655" width="33" height="31" frameX="-0" frameY="-0" frameWidth="33" frameHeight="31"/>
<SubTexture name="character-backtick0001" x="731" y="655" width="33" height="31" frameX="-0" frameY="-0" frameWidth="33" frameHeight="31"/>
<SubTexture name="character-backtick0002" x="568" y="713" width="33" height="31" frameX="-0" frameY="-0" frameWidth="33" frameHeight="31"/>
<SubTexture name="character-backtick0003" x="568" y="713" width="33" height="31" frameX="-0" frameY="-0" frameWidth="33" frameHeight="31"/>
<SubTexture name="character-c0000" x="374" y="2" width="54" height="66" frameX="-0" frameY="-0" frameWidth="55" frameHeight="66"/>
<SubTexture name="character-c0001" x="374" y="2" width="54" height="66" frameX="-0" frameY="-0" frameWidth="55" frameHeight="66"/>
<SubTexture name="character-c0002" x="407" y="270" width="54" height="64" frameX="-0" frameY="-1" frameWidth="55" frameHeight="66"/>
<SubTexture name="character-c0003" x="407" y="270" width="54" height="64" frameX="-0" frameY="-1" frameWidth="55" frameHeight="66"/>
<SubTexture name="character-caret0000" x="694" y="74" width="46" height="34" frameX="-0" frameY="-0" frameWidth="46" frameHeight="34"/>
<SubTexture name="character-caret0001" x="694" y="74" width="46" height="34" frameX="-0" frameY="-0" frameWidth="46" frameHeight="34"/>
<SubTexture name="character-caret0002" x="687" y="480" width="46" height="34" frameX="-0" frameY="-0" frameWidth="46" frameHeight="34"/>
<SubTexture name="character-caret0003" x="687" y="480" width="46" height="34" frameX="-0" frameY="-0" frameWidth="46" frameHeight="34"/>
<SubTexture name="character-colon0000" x="744" y="301" width="22" height="49" frameX="-0" frameY="-0" frameWidth="22" frameHeight="49"/>
<SubTexture name="character-colon0001" x="744" y="301" width="22" height="49" frameX="-0" frameY="-0" frameWidth="22" frameHeight="49"/>
<SubTexture name="character-colon0002" x="744" y="352" width="22" height="49" frameX="-0" frameY="-0" frameWidth="22" frameHeight="49"/>
<SubTexture name="character-colon0003" x="744" y="352" width="22" height="49" frameX="-0" frameY="-0" frameWidth="22" frameHeight="49"/>
<SubTexture name="character-comma0000" x="456" y="756" width="25" height="32" frameX="-0" frameY="-0" frameWidth="25" frameHeight="32"/>
<SubTexture name="character-comma0001" x="456" y="756" width="25" height="32" frameX="-0" frameY="-0" frameWidth="25" frameHeight="32"/>
<SubTexture name="character-comma0002" x="385" y="764" width="25" height="32" frameX="-0" frameY="-0" frameWidth="25" frameHeight="32"/>
<SubTexture name="character-comma0003" x="385" y="764" width="25" height="32" frameX="-0" frameY="-0" frameWidth="25" frameHeight="32"/>
<SubTexture name="character-curlybracket-left0000" x="548" y="548" width="46" height="68" frameX="-0" frameY="-0" frameWidth="46" frameHeight="68"/>
<SubTexture name="character-curlybracket-left0001" x="548" y="548" width="46" height="68" frameX="-0" frameY="-0" frameWidth="46" frameHeight="68"/>
<SubTexture name="character-curlybracket-left0002" x="493" y="550" width="46" height="68" frameX="-0" frameY="-0" frameWidth="46" frameHeight="68"/>
<SubTexture name="character-curlybracket-left0003" x="493" y="550" width="46" height="68" frameX="-0" frameY="-0" frameWidth="46" frameHeight="68"/>
<SubTexture name="character-curlybracket-right0000" x="50" y="572" width="47" height="67" frameX="-0" frameY="-0" frameWidth="47" frameHeight="67"/>
<SubTexture name="character-curlybracket-right0001" x="50" y="572" width="47" height="67" frameX="-0" frameY="-0" frameWidth="47" frameHeight="67"/>
<SubTexture name="character-curlybracket-right0002" x="521" y="2" width="47" height="67" frameX="-0" frameY="-0" frameWidth="47" frameHeight="67"/>
<SubTexture name="character-curlybracket-right0003" x="521" y="2" width="47" height="67" frameX="-0" frameY="-0" frameWidth="47" frameHeight="67"/>
<SubTexture name="character-d0000" x="444" y="430" width="53" height="66" frameX="-0" frameY="-0" frameWidth="53" frameHeight="67"/>
<SubTexture name="character-d0001" x="444" y="430" width="53" height="66" frameX="-0" frameY="-0" frameWidth="53" frameHeight="67"/>
<SubTexture name="character-d0002" x="49" y="433" width="53" height="67" frameX="-0" frameY="-0" frameWidth="53" frameHeight="67"/>
<SubTexture name="character-d0003" x="49" y="433" width="53" height="67" frameX="-0" frameY="-0" frameWidth="53" frameHeight="67"/>
<SubTexture name="character-dollar0000" x="499" y="478" width="47" height="70" frameX="-0" frameY="-0" frameWidth="47" frameHeight="70"/>
<SubTexture name="character-dollar0001" x="499" y="478" width="47" height="70" frameX="-0" frameY="-0" frameWidth="47" frameHeight="70"/>
<SubTexture name="character-dollar0002" x="444" y="498" width="47" height="70" frameX="-0" frameY="-0" frameWidth="47" frameHeight="70"/>
<SubTexture name="character-dollar0003" x="444" y="498" width="47" height="70" frameX="-0" frameY="-0" frameWidth="47" frameHeight="70"/>
<SubTexture name="character-doublequote0000" x="687" y="581" width="47" height="32" frameX="-0" frameY="-0" frameWidth="47" frameHeight="32"/>
<SubTexture name="character-doublequote0001" x="687" y="581" width="47" height="32" frameX="-0" frameY="-0" frameWidth="47" frameHeight="32"/>
<SubTexture name="character-doublequote0002" x="86" y="707" width="47" height="32" frameX="-0" frameY="-0" frameWidth="47" frameHeight="32"/>
<SubTexture name="character-doublequote0003" x="86" y="707" width="47" height="32" frameX="-0" frameY="-0" frameWidth="47" frameHeight="32"/>
<SubTexture name="character-doublequote-alt0000" x="415" y="227" width="39" height="41" frameX="-1" frameY="-0" frameWidth="40" frameHeight="41"/>
<SubTexture name="character-doublequote-alt0001" x="415" y="227" width="39" height="41" frameX="-1" frameY="-0" frameWidth="40" frameHeight="41"/>
<SubTexture name="character-doublequote-alt0002" x="598" y="505" width="40" height="41" frameX="-0" frameY="-0" frameWidth="40" frameHeight="41"/>
<SubTexture name="character-doublequote-alt0003" x="598" y="505" width="40" height="41" frameX="-0" frameY="-0" frameWidth="40" frameHeight="41"/>
<SubTexture name="character-e0000" x="642" y="505" width="43" height="65" frameX="-0" frameY="-0" frameWidth="43" frameHeight="66"/>
<SubTexture name="character-e0001" x="642" y="505" width="43" height="65" frameX="-0" frameY="-0" frameWidth="43" frameHeight="66"/>
<SubTexture name="character-e0002" x="642" y="572" width="43" height="65" frameX="-0" frameY="-0" frameWidth="43" frameHeight="66"/>
<SubTexture name="character-e0003" x="642" y="572" width="43" height="65" frameX="-0" frameY="-0" frameWidth="43" frameHeight="66"/>
<SubTexture name="character-eight0000" x="380" y="501" width="49" height="67" frameX="-0" frameY="-0" frameWidth="49" frameHeight="67"/>
<SubTexture name="character-eight0001" x="380" y="501" width="49" height="67" frameX="-0" frameY="-0" frameWidth="49" frameHeight="67"/>
<SubTexture name="character-eight0002" x="2" y="502" width="49" height="67" frameX="-0" frameY="-0" frameWidth="49" frameHeight="67"/>
<SubTexture name="character-eight0003" x="2" y="502" width="49" height="67" frameX="-0" frameY="-0" frameWidth="49" frameHeight="67"/>
<SubTexture name="character-equal0000" x="362" y="156" width="48" height="34" frameX="-0" frameY="-0" frameWidth="48" frameHeight="34"/>
<SubTexture name="character-equal0001" x="362" y="156" width="48" height="34" frameX="-0" frameY="-0" frameWidth="48" frameHeight="34"/>
<SubTexture name="character-equal0002" x="694" y="38" width="48" height="34" frameX="-0" frameY="-0" frameWidth="48" frameHeight="34"/>
<SubTexture name="character-equal0003" x="694" y="38" width="48" height="34" frameX="-0" frameY="-0" frameWidth="48" frameHeight="34"/>
<SubTexture name="character-ethel0000" x="2" y="2" width="78" height="70" frameX="-0" frameY="-0" frameWidth="79" frameHeight="70"/>
<SubTexture name="character-ethel0001" x="2" y="2" width="78" height="70" frameX="-0" frameY="-0" frameWidth="79" frameHeight="70"/>
<SubTexture name="character-ethel0002" x="2" y="74" width="78" height="70" frameX="-0" frameY="-0" frameWidth="79" frameHeight="70"/>
<SubTexture name="character-ethel0003" x="2" y="74" width="78" height="70" frameX="-0" frameY="-0" frameWidth="79" frameHeight="70"/>
<SubTexture name="character-exclamationmark0000" x="2" y="642" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-exclamationmark0001" x="2" y="642" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-exclamationmark0002" x="313" y="635" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-exclamationmark0003" x="313" y="635" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-f0000" x="599" y="352" width="43" height="67" frameX="-0" frameY="-0" frameWidth="43" frameHeight="67"/>
<SubTexture name="character-f0001" x="599" y="352" width="43" height="67" frameX="-0" frameY="-0" frameWidth="43" frameHeight="67"/>
<SubTexture name="character-f0002" x="605" y="281" width="43" height="67" frameX="-0" frameY="-0" frameWidth="43" frameHeight="67"/>
<SubTexture name="character-f0003" x="605" y="281" width="43" height="67" frameX="-0" frameY="-0" frameWidth="43" frameHeight="67"/>
<SubTexture name="character-five0000" x="516" y="210" width="46" height="69" frameX="-0" frameY="-0" frameWidth="47" frameHeight="69"/>
<SubTexture name="character-five0001" x="516" y="210" width="46" height="69" frameX="-0" frameY="-0" frameWidth="47" frameHeight="69"/>
<SubTexture name="character-five0002" x="557" y="281" width="46" height="69" frameX="-0" frameY="-0" frameWidth="47" frameHeight="69"/>
<SubTexture name="character-five0003" x="557" y="281" width="46" height="69" frameX="-0" frameY="-0" frameWidth="47" frameHeight="69"/>
<SubTexture name="character-four0000" x="398" y="359" width="52" height="69" frameX="-0" frameY="-0" frameWidth="53" frameHeight="69"/>
<SubTexture name="character-four0001" x="398" y="359" width="52" height="69" frameX="-0" frameY="-0" frameWidth="53" frameHeight="69"/>
<SubTexture name="character-four0002" x="362" y="85" width="52" height="69" frameX="-0" frameY="-0" frameWidth="53" frameHeight="69"/>
<SubTexture name="character-four0003" x="362" y="85" width="52" height="69" frameX="-0" frameY="-0" frameWidth="53" frameHeight="69"/>
<SubTexture name="character-g0000" x="183" y="282" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-g0001" x="183" y="282" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-g0002" x="123" y="283" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-g0003" x="123" y="283" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-h0000" x="570" y="2" width="44" height="66" frameX="-0" frameY="-0" frameWidth="45" frameHeight="66"/>
<SubTexture name="character-h0001" x="570" y="2" width="44" height="66" frameX="-0" frameY="-0" frameWidth="45" frameHeight="66"/>
<SubTexture name="character-h0002" x="598" y="437" width="44" height="66" frameX="-0" frameY="-0" frameWidth="45" frameHeight="66"/>
<SubTexture name="character-h0003" x="598" y="437" width="44" height="66" frameX="-0" frameY="-0" frameWidth="45" frameHeight="66"/>
<SubTexture name="character-hyphen0000" x="408" y="720" width="49" height="20" frameX="-0" frameY="-0" frameWidth="49" frameHeight="20"/>
<SubTexture name="character-hyphen0001" x="408" y="720" width="49" height="20" frameX="-0" frameY="-0" frameWidth="49" frameHeight="20"/>
<SubTexture name="character-hyphen0002" x="224" y="718" width="49" height="20" frameX="-0" frameY="-0" frameWidth="49" frameHeight="20"/>
<SubTexture name="character-hyphen0003" x="224" y="718" width="49" height="20" frameX="-0" frameY="-0" frameWidth="49" frameHeight="20"/>
<SubTexture name="character-i0000" x="644" y="350" width="43" height="64" frameX="-0" frameY="-0" frameWidth="43" frameHeight="64"/>
<SubTexture name="character-i0001" x="644" y="350" width="43" height="64" frameX="-0" frameY="-0" frameWidth="43" frameHeight="64"/>
<SubTexture name="character-i0002" x="650" y="279" width="43" height="64" frameX="-0" frameY="-0" frameWidth="43" frameHeight="64"/>
<SubTexture name="character-i0003" x="650" y="279" width="43" height="64" frameX="-0" frameY="-0" frameWidth="43" frameHeight="64"/>
<SubTexture name="character-j0000" x="2" y="286" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-j0001" x="2" y="286" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-j0002" x="57" y="292" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-j0003" x="57" y="292" width="53" height="70" frameX="-0" frameY="-0" frameWidth="54" frameHeight="70"/>
<SubTexture name="character-k0000" x="564" y="210" width="44" height="69" frameX="-0" frameY="-0" frameWidth="44" frameHeight="69"/>
<SubTexture name="character-k0001" x="564" y="210" width="44" height="69" frameX="-0" frameY="-0" frameWidth="44" frameHeight="69"/>
<SubTexture name="character-k0002" x="596" y="548" width="44" height="69" frameX="-0" frameY="-0" frameWidth="44" frameHeight="69"/>
<SubTexture name="character-k0003" x="596" y="548" width="44" height="69" frameX="-0" frameY="-0" frameWidth="44" frameHeight="69"/>
<SubTexture name="character-l0000" x="644" y="416" width="40" height="66" frameX="-0" frameY="-0" frameWidth="41" frameHeight="66"/>
<SubTexture name="character-l0001" x="644" y="416" width="40" height="66" frameX="-0" frameY="-0" frameWidth="41" frameHeight="66"/>
<SubTexture name="character-l0002" x="654" y="206" width="41" height="66" frameX="-0" frameY="-0" frameWidth="41" frameHeight="66"/>
<SubTexture name="character-l0003" x="654" y="206" width="41" height="66" frameX="-0" frameY="-0" frameWidth="41" frameHeight="66"/>
<SubTexture name="character-m0000" x="222" y="428" width="56" height="63" frameX="-0" frameY="-0" frameWidth="56" frameHeight="63"/>
<SubTexture name="character-m0001" x="222" y="428" width="56" height="63" frameX="-0" frameY="-0" frameWidth="56" frameHeight="63"/>
<SubTexture name="character-m0002" x="280" y="429" width="56" height="63" frameX="-0" frameY="-0" frameWidth="56" frameHeight="63"/>
<SubTexture name="character-m0003" x="280" y="429" width="56" height="63" frameX="-0" frameY="-0" frameWidth="56" frameHeight="63"/>
<SubTexture name="character-n0000" x="280" y="2" width="45" height="65" frameX="-0" frameY="-0" frameWidth="45" frameHeight="65"/>
<SubTexture name="character-n0001" x="280" y="2" width="45" height="65" frameX="-0" frameY="-0" frameWidth="45" frameHeight="65"/>
<SubTexture name="character-n0002" x="569" y="142" width="45" height="65" frameX="-0" frameY="-0" frameWidth="45" frameHeight="65"/>
<SubTexture name="character-n0003" x="569" y="142" width="45" height="65" frameX="-0" frameY="-0" frameWidth="45" frameHeight="65"/>
<SubTexture name="character-nine0000" x="288" y="359" width="53" height="68" frameX="-0" frameY="-0" frameWidth="53" frameHeight="68"/>
<SubTexture name="character-nine0001" x="288" y="359" width="53" height="68" frameX="-0" frameY="-0" frameWidth="53" frameHeight="68"/>
<SubTexture name="character-nine0002" x="343" y="359" width="53" height="68" frameX="-0" frameY="-0" frameWidth="53" frameHeight="68"/>
<SubTexture name="character-nine0003" x="343" y="359" width="53" height="68" frameX="-0" frameY="-0" frameWidth="53" frameHeight="68"/>
<SubTexture name="character-o0000" x="452" y="336" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-o0001" x="452" y="336" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-o0002" x="415" y="156" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-o0003" x="415" y="156" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-one0000" x="338" y="429" width="51" height="69" frameX="-0" frameY="-0" frameWidth="51" frameHeight="69"/>
<SubTexture name="character-one0001" x="338" y="429" width="51" height="69" frameX="-0" frameY="-0" frameWidth="51" frameHeight="69"/>
<SubTexture name="character-one0002" x="391" y="430" width="51" height="69" frameX="-0" frameY="-0" frameWidth="51" frameHeight="69"/>
<SubTexture name="character-one0003" x="391" y="430" width="51" height="69" frameX="-0" frameY="-0" frameWidth="51" frameHeight="69"/>
<SubTexture name="character-p0000" x="156" y="564" width="45" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-p0001" x="156" y="564" width="45" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-p0002" x="103" y="565" width="45" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-p0003" x="103" y="565" width="45" height="70" frameX="-0" frameY="-0" frameWidth="46" frameHeight="70"/>
<SubTexture name="character-percent0000" x="221" y="2" width="57" height="66" frameX="-0" frameY="-0" frameWidth="57" frameHeight="67"/>
<SubTexture name="character-percent0001" x="221" y="2" width="57" height="66" frameX="-0" frameY="-0" frameWidth="57" frameHeight="67"/>
<SubTexture name="character-percent0002" x="243" y="151" width="57" height="66" frameX="-0" frameY="-0" frameWidth="57" frameHeight="67"/>
<SubTexture name="character-percent0003" x="243" y="151" width="57" height="66" frameX="-0" frameY="-0" frameWidth="57" frameHeight="67"/>
<SubTexture name="character-period0000" x="605" y="677" width="23" height="18" frameX="-0" frameY="-0" frameWidth="23" frameHeight="18"/>
<SubTexture name="character-period0001" x="605" y="677" width="23" height="18" frameX="-0" frameY="-0" frameWidth="23" frameHeight="18"/>
<SubTexture name="character-period0002" x="289" y="781" width="23" height="18" frameX="-0" frameY="-0" frameWidth="23" frameHeight="18"/>
<SubTexture name="character-period0003" x="289" y="781" width="23" height="18" frameX="-0" frameY="-0" frameWidth="23" frameHeight="18"/>
<SubTexture name="character-plus0000" x="260" y="629" width="51" height="50" frameX="-0" frameY="-0" frameWidth="51" frameHeight="50"/>
<SubTexture name="character-plus0001" x="260" y="629" width="51" height="50" frameX="-0" frameY="-0" frameWidth="51" frameHeight="50"/>
<SubTexture name="character-plus0002" x="203" y="635" width="51" height="50" frameX="-0" frameY="-0" frameWidth="51" frameHeight="50"/>
<SubTexture name="character-plus0003" x="203" y="635" width="51" height="50" frameX="-0" frameY="-0" frameWidth="51" frameHeight="50"/>
<SubTexture name="character-pound0000" x="159" y="73" width="58" height="67" frameX="-0" frameY="-0" frameWidth="58" frameHeight="67"/>
<SubTexture name="character-pound0001" x="159" y="73" width="58" height="67" frameX="-0" frameY="-0" frameWidth="58" frameHeight="67"/>
<SubTexture name="character-pound0002" x="183" y="213" width="58" height="67" frameX="-0" frameY="-0" frameWidth="58" frameHeight="67"/>
<SubTexture name="character-pound0003" x="183" y="213" width="58" height="67" frameX="-0" frameY="-0" frameWidth="58" frameHeight="67"/>
<SubTexture name="character-q0000" x="467" y="141" width="51" height="67" frameX="-0" frameY="-0" frameWidth="52" frameHeight="67"/>
<SubTexture name="character-q0001" x="467" y="141" width="51" height="67" frameX="-0" frameY="-0" frameWidth="52" frameHeight="67"/>
<SubTexture name="character-q0002" x="468" y="2" width="51" height="67" frameX="-0" frameY="-0" frameWidth="52" frameHeight="67"/>
<SubTexture name="character-q0003" x="468" y="2" width="51" height="67" frameX="-0" frameY="-0" frameWidth="52" frameHeight="67"/>
<SubTexture name="character-questionmark0000" x="416" y="70" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-questionmark0001" x="416" y="70" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-questionmark0002" x="499" y="407" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-questionmark0003" x="499" y="407" width="50" height="69" frameX="-0" frameY="-0" frameWidth="50" frameHeight="69"/>
<SubTexture name="character-questionmark-alt0000" x="219" y="73" width="50" height="76" frameX="-0" frameY="-2" frameWidth="51" frameHeight="78"/>
<SubTexture name="character-questionmark-alt0001" x="219" y="73" width="50" height="76" frameX="-0" frameY="-2" frameWidth="51" frameHeight="78"/>
<SubTexture name="character-questionmark-alt0002" x="70" y="212" width="51" height="78" frameX="-0" frameY="-0" frameWidth="51" frameHeight="78"/>
<SubTexture name="character-questionmark-alt0003" x="70" y="212" width="51" height="78" frameX="-0" frameY="-0" frameWidth="51" frameHeight="78"/>
<SubTexture name="character-r0000" x="520" y="142" width="47" height="66" frameX="-0" frameY="-0" frameWidth="47" frameHeight="66"/>
<SubTexture name="character-r0001" x="520" y="142" width="47" height="66" frameX="-0" frameY="-0" frameWidth="47" frameHeight="66"/>
<SubTexture name="character-r0002" x="374" y="570" width="47" height="66" frameX="-0" frameY="-0" frameWidth="47" frameHeight="66"/>
<SubTexture name="character-r0003" x="374" y="570" width="47" height="66" frameX="-0" frameY="-0" frameWidth="47" frameHeight="66"/>
<SubTexture name="character-roundbracket-left0000" x="469" y="620" width="34" height="67" frameX="-0" frameY="-0" frameWidth="34" frameHeight="67"/>
<SubTexture name="character-roundbracket-left0001" x="469" y="620" width="34" height="67" frameX="-0" frameY="-0" frameWidth="34" frameHeight="67"/>
<SubTexture name="character-roundbracket-left0002" x="505" y="620" width="34" height="67" frameX="-0" frameY="-0" frameWidth="34" frameHeight="67"/>
<SubTexture name="character-roundbracket-left0003" x="505" y="620" width="34" height="67" frameX="-0" frameY="-0" frameWidth="34" frameHeight="67"/>
<SubTexture name="character-roundbracket-right0000" x="99" y="637" width="34" height="68" frameX="-0" frameY="-0" frameWidth="34" frameHeight="68"/>
<SubTexture name="character-roundbracket-right0001" x="99" y="637" width="34" height="68" frameX="-0" frameY="-0" frameWidth="34" frameHeight="68"/>
<SubTexture name="character-roundbracket-right0002" x="50" y="641" width="34" height="68" frameX="-0" frameY="-0" frameWidth="34" frameHeight="68"/>
<SubTexture name="character-roundbracket-right0003" x="50" y="641" width="34" height="68" frameX="-0" frameY="-0" frameWidth="34" frameHeight="68"/>
<SubTexture name="character-s0000" x="274" y="561" width="48" height="66" frameX="-0" frameY="-0" frameWidth="49" frameHeight="66"/>
<SubTexture name="character-s0001" x="274" y="561" width="48" height="66" frameX="-0" frameY="-0" frameWidth="49" frameHeight="66"/>
<SubTexture name="character-s0002" x="324" y="567" width="48" height="66" frameX="-0" frameY="-0" frameWidth="49" frameHeight="66"/>
<SubTexture name="character-s0003" x="324" y="567" width="48" height="66" frameX="-0" frameY="-0" frameWidth="49" frameHeight="66"/>
<SubTexture name="character-semicolon0000" x="719" y="110" width="24" height="63" frameX="-0" frameY="-0" frameWidth="24" frameHeight="63"/>
<SubTexture name="character-semicolon0001" x="719" y="110" width="24" height="63" frameX="-0" frameY="-0" frameWidth="24" frameHeight="63"/>
<SubTexture name="character-semicolon0002" x="687" y="516" width="24" height="63" frameX="-0" frameY="-0" frameWidth="24" frameHeight="63"/>
<SubTexture name="character-semicolon0003" x="687" y="516" width="24" height="63" frameX="-0" frameY="-0" frameWidth="24" frameHeight="63"/>
<SubTexture name="character-seven0000" x="53" y="502" width="48" height="68" frameX="-0" frameY="-0" frameWidth="48" frameHeight="69"/>
<SubTexture name="character-seven0001" x="53" y="502" width="48" height="68" frameX="-0" frameY="-0" frameWidth="48" frameHeight="69"/>
<SubTexture name="character-seven0002" x="548" y="478" width="48" height="68" frameX="-0" frameY="-0" frameWidth="48" frameHeight="69"/>
<SubTexture name="character-seven0003" x="548" y="478" width="48" height="68" frameX="-0" frameY="-0" frameWidth="48" frameHeight="69"/>
<SubTexture name="character-singlequote0000" x="327" y="746" width="27" height="31" frameX="-0" frameY="-0" frameWidth="27" frameHeight="31"/>
<SubTexture name="character-singlequote0001" x="327" y="746" width="27" height="31" frameX="-0" frameY="-0" frameWidth="27" frameHeight="31"/>
<SubTexture name="character-singlequote0002" x="356" y="747" width="27" height="31" frameX="-0" frameY="-0" frameWidth="27" frameHeight="31"/>
<SubTexture name="character-singlequote0003" x="356" y="747" width="27" height="31" frameX="-0" frameY="-0" frameWidth="27" frameHeight="31"/>
<SubTexture name="character-six0000" x="299" y="219" width="54" height="68" frameX="-0" frameY="-0" frameWidth="54" frameHeight="68"/>
<SubTexture name="character-six0001" x="299" y="219" width="54" height="68" frameX="-0" frameY="-0" frameWidth="54" frameHeight="68"/>
<SubTexture name="character-six0002" x="352" y="289" width="53" height="68" frameX="-0" frameY="-0" frameWidth="54" frameHeight="68"/>
<SubTexture name="character-six0003" x="352" y="289" width="53" height="68" frameX="-0" frameY="-0" frameWidth="54" frameHeight="68"/>
<SubTexture name="character-slash0000" x="468" y="71" width="50" height="68" frameX="-0" frameY="-0" frameWidth="50" frameHeight="68"/>
<SubTexture name="character-slash0001" x="468" y="71" width="50" height="68" frameX="-0" frameY="-0" frameWidth="50" frameHeight="68"/>
<SubTexture name="character-slash0002" x="222" y="493" width="50" height="68" frameX="-0" frameY="-0" frameWidth="50" frameHeight="68"/>
<SubTexture name="character-slash0003" x="222" y="493" width="50" height="68" frameX="-0" frameY="-0" frameWidth="50" frameHeight="68"/>
<SubTexture name="character-squarebracket-left0000" x="348" y="638" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-squarebracket-left0001" x="348" y="638" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-squarebracket-left0002" x="383" y="638" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-squarebracket-left0003" x="383" y="638" width="33" height="70" frameX="-0" frameY="-0" frameWidth="33" frameHeight="70"/>
<SubTexture name="character-squarebracket-right0000" x="658" y="68" width="34" height="70" frameX="-0" frameY="-0" frameWidth="34" frameHeight="70"/>
<SubTexture name="character-squarebracket-right0001" x="658" y="68" width="34" height="70" frameX="-0" frameY="-0" frameWidth="34" frameHeight="70"/>
<SubTexture name="character-squarebracket-right0002" x="150" y="636" width="34" height="70" frameX="-0" frameY="-0" frameWidth="34" frameHeight="70"/>
<SubTexture name="character-squarebracket-right0003" x="150" y="636" width="34" height="70" frameX="-0" frameY="-0" frameWidth="34" frameHeight="70"/>
<SubTexture name="character-t0000" x="616" y="2" width="44" height="64" frameX="-0" frameY="-0" frameWidth="44" frameHeight="64"/>
<SubTexture name="character-t0001" x="616" y="2" width="44" height="64" frameX="-0" frameY="-0" frameWidth="44" frameHeight="64"/>
<SubTexture name="character-t0002" x="616" y="140" width="44" height="64" frameX="-0" frameY="-0" frameWidth="44" frameHeight="64"/>
<SubTexture name="character-t0003" x="616" y="140" width="44" height="64" frameX="-0" frameY="-0" frameWidth="44" frameHeight="64"/>
<SubTexture name="character-three0000" x="520" y="71" width="46" height="69" frameX="-0" frameY="-0" frameWidth="46" frameHeight="69"/>
<SubTexture name="character-three0001" x="520" y="71" width="46" height="69" frameX="-0" frameY="-0" frameWidth="46" frameHeight="69"/>
<SubTexture name="character-three0002" x="2" y="571" width="46" height="69" frameX="-0" frameY="-0" frameWidth="46" frameHeight="69"/>
<SubTexture name="character-three0003" x="2" y="571" width="46" height="69" frameX="-0" frameY="-0" frameWidth="46" frameHeight="69"/>
<SubTexture name="character-tilde0000" x="2" y="714" width="52" height="28" frameX="-0" frameY="-0" frameWidth="52" frameHeight="28"/>
<SubTexture name="character-tilde0001" x="2" y="714" width="52" height="28" frameX="-0" frameY="-0" frameWidth="52" frameHeight="28"/>
<SubTexture name="character-tilde0002" x="685" y="690" width="52" height="28" frameX="-0" frameY="-0" frameWidth="52" frameHeight="28"/>
<SubTexture name="character-tilde0003" x="685" y="690" width="52" height="28" frameX="-0" frameY="-0" frameWidth="52" frameHeight="28"/>
<SubTexture name="character-tilde-alt0000" x="256" y="681" width="55" height="35" frameX="-0" frameY="-0" frameWidth="55" frameHeight="35"/>
<SubTexture name="character-tilde-alt0001" x="256" y="681" width="55" height="35" frameX="-0" frameY="-0" frameWidth="55" frameHeight="35"/>
<SubTexture name="character-tilde-alt0002" x="662" y="140" width="55" height="34" frameX="-0" frameY="-0" frameWidth="55" frameHeight="35"/>
<SubTexture name="character-tilde-alt0003" x="662" y="140" width="55" height="34" frameX="-0" frameY="-0" frameWidth="55" frameHeight="35"/>
<SubTexture name="character-two0000" x="161" y="494" width="50" height="68" frameX="-0" frameY="-0" frameWidth="51" frameHeight="68"/>
<SubTexture name="character-two0001" x="161" y="494" width="50" height="68" frameX="-0" frameY="-0" frameWidth="51" frameHeight="68"/>
<SubTexture name="character-two0002" x="104" y="495" width="50" height="68" frameX="-0" frameY="-0" frameWidth="51" frameHeight="68"/>
<SubTexture name="character-two0003" x="104" y="495" width="50" height="68" frameX="-0" frameY="-0" frameWidth="51" frameHeight="68"/>
<SubTexture name="character-u0000" x="2" y="441" width="44" height="59" frameX="-0" frameY="-0" frameWidth="44" frameHeight="59"/>
<SubTexture name="character-u0001" x="2" y="441" width="44" height="59" frameX="-0" frameY="-0" frameWidth="44" frameHeight="59"/>
<SubTexture name="character-u0002" x="639" y="639" width="44" height="59" frameX="-0" frameY="-0" frameWidth="44" frameHeight="59"/>
<SubTexture name="character-u0003" x="639" y="639" width="44" height="59" frameX="-0" frameY="-0" frameWidth="44" frameHeight="59"/>
<SubTexture name="character-underscore0000" x="603" y="724" width="56" height="18" frameX="-0" frameY="-0" frameWidth="56" frameHeight="18"/>
<SubTexture name="character-underscore0001" x="603" y="724" width="56" height="18" frameX="-0" frameY="-0" frameWidth="56" frameHeight="18"/>
<SubTexture name="character-underscore0002" x="166" y="708" width="56" height="18" frameX="-0" frameY="-0" frameWidth="56" frameHeight="18"/>
<SubTexture name="character-underscore0003" x="166" y="708" width="56" height="18" frameX="-0" frameY="-0" frameWidth="56" frameHeight="18"/>
<SubTexture name="character-underscore-alt0000" x="605" y="700" width="65" height="22" frameX="-0" frameY="-0" frameWidth="65" frameHeight="22"/>
<SubTexture name="character-underscore-alt0001" x="605" y="700" width="65" height="22" frameX="-0" frameY="-0" frameWidth="65" frameHeight="22"/>
<SubTexture name="character-underscore-alt0002" x="672" y="720" width="65" height="22" frameX="-0" frameY="-0" frameWidth="65" frameHeight="22"/>
<SubTexture name="character-underscore-alt0003" x="672" y="720" width="65" height="22" frameX="-0" frameY="-0" frameWidth="65" frameHeight="22"/>
<SubTexture name="character-v0000" x="166" y="426" width="54" height="66" frameX="-0" frameY="-0" frameWidth="54" frameHeight="66"/>
<SubTexture name="character-v0001" x="166" y="426" width="54" height="66" frameX="-0" frameY="-0" frameWidth="54" frameHeight="66"/>
<SubTexture name="character-v0002" x="105" y="427" width="54" height="66" frameX="-0" frameY="-0" frameWidth="54" frameHeight="66"/>
<SubTexture name="character-v0003" x="105" y="427" width="54" height="66" frameX="-0" frameY="-0" frameWidth="54" frameHeight="66"/>
<SubTexture name="character-verticalbar0000" x="721" y="345" width="21" height="66" frameX="-0" frameY="-0" frameWidth="21" frameHeight="66"/>
<SubTexture name="character-verticalbar0001" x="721" y="345" width="21" height="66" frameX="-0" frameY="-0" frameWidth="21" frameHeight="66"/>
<SubTexture name="character-verticalbar0002" x="744" y="2" width="21" height="66" frameX="-0" frameY="-0" frameWidth="21" frameHeight="66"/>
<SubTexture name="character-verticalbar0003" x="744" y="2" width="21" height="66" frameX="-0" frameY="-0" frameWidth="21" frameHeight="66"/>
<SubTexture name="character-verticalbar-alt0000" x="739" y="175" width="16" height="76" frameX="-0" frameY="-0" frameWidth="16" frameHeight="77"/>
<SubTexture name="character-verticalbar-alt0001" x="739" y="175" width="16" height="76" frameX="-0" frameY="-0" frameWidth="16" frameHeight="77"/>
<SubTexture name="character-verticalbar-alt0002" x="745" y="70" width="16" height="76" frameX="-0" frameY="-0" frameWidth="16" frameHeight="77"/>
<SubTexture name="character-verticalbar-alt0003" x="745" y="70" width="16" height="76" frameX="-0" frameY="-0" frameWidth="16" frameHeight="77"/>
<SubTexture name="character-w0000" x="302" y="141" width="58" height="63" frameX="-0" frameY="-0" frameWidth="58" frameHeight="63"/>
<SubTexture name="character-w0001" x="302" y="141" width="58" height="63" frameX="-0" frameY="-0" frameWidth="58" frameHeight="63"/>
<SubTexture name="character-w0002" x="355" y="206" width="58" height="62" frameX="-0" frameY="-0" frameWidth="58" frameHeight="63"/>
<SubTexture name="character-w0003" x="355" y="206" width="58" height="62" frameX="-0" frameY="-0" frameWidth="58" frameHeight="63"/>
<SubTexture name="character-x0000" x="238" y="290" width="55" height="67" frameX="-0" frameY="-0" frameWidth="55" frameHeight="67"/>
<SubTexture name="character-x0001" x="238" y="290" width="55" height="67" frameX="-0" frameY="-0" frameWidth="55" frameHeight="67"/>
<SubTexture name="character-x0002" x="295" y="290" width="55" height="67" frameX="-0" frameY="-0" frameWidth="55" frameHeight="67"/>
<SubTexture name="character-x0003" x="295" y="290" width="55" height="67" frameX="-0" frameY="-0" frameWidth="55" frameHeight="67"/>
<SubTexture name="character-y0000" x="271" y="70" width="54" height="69" frameX="-0" frameY="-0" frameWidth="54" frameHeight="69"/>
<SubTexture name="character-y0001" x="271" y="70" width="54" height="69" frameX="-0" frameY="-0" frameWidth="54" frameHeight="69"/>
<SubTexture name="character-y0002" x="243" y="219" width="54" height="69" frameX="-0" frameY="-0" frameWidth="54" frameHeight="69"/>
<SubTexture name="character-y0003" x="243" y="219" width="54" height="69" frameX="-0" frameY="-0" frameWidth="54" frameHeight="69"/>
<SubTexture name="character-z0000" x="274" y="494" width="51" height="65" frameX="-0" frameY="-0" frameWidth="52" frameHeight="65"/>
<SubTexture name="character-z0001" x="274" y="494" width="51" height="65" frameX="-0" frameY="-0" frameWidth="52" frameHeight="65"/>
<SubTexture name="character-z0002" x="327" y="500" width="51" height="65" frameX="-0" frameY="-0" frameWidth="52" frameHeight="65"/>
<SubTexture name="character-z0003" x="327" y="500" width="51" height="65" frameX="-0" frameY="-0" frameWidth="52" frameHeight="65"/>
<SubTexture name="character-zero0000" x="178" y="354" width="52" height="70" frameX="-0" frameY="-0" frameWidth="53" frameHeight="70"/>
<SubTexture name="character-zero0001" x="178" y="354" width="52" height="70" frameX="-0" frameY="-0" frameWidth="53" frameHeight="70"/>
<SubTexture name="character-zero0002" x="112" y="355" width="52" height="70" frameX="-0" frameY="-0" frameWidth="53" frameHeight="70"/>
<SubTexture name="character-zero0003" x="112" y="355" width="52" height="70" frameX="-0" frameY="-0" frameWidth="53" frameHeight="70"/>
<SubTexture name="diacritic-acute-fill0000" x="727" y="327" width="14" height="16" frameX="-0" frameY="-0" frameWidth="14" frameHeight="16"/>
<SubTexture name="diacritic-acute-fill0001" x="727" y="327" width="14" height="16" frameX="-0" frameY="-0" frameWidth="14" frameHeight="16"/>
<SubTexture name="diacritic-acute-fill0002" x="186" y="656" width="14" height="16" frameX="-0" frameY="-0" frameWidth="14" frameHeight="16"/>
<SubTexture name="diacritic-acute-fill0003" x="186" y="656" width="14" height="16" frameX="-0" frameY="-0" frameWidth="14" frameHeight="16"/>
<SubTexture name="diacritic-acute-outline0000" x="197" y="728" width="25" height="26" frameX="-0" frameY="-0" frameWidth="25" frameHeight="26"/>
<SubTexture name="diacritic-acute-outline0001" x="197" y="728" width="25" height="26" frameX="-0" frameY="-0" frameWidth="25" frameHeight="26"/>
<SubTexture name="diacritic-acute-outline0002" x="147" y="755" width="25" height="26" frameX="-0" frameY="-0" frameWidth="25" frameHeight="26"/>
<SubTexture name="diacritic-acute-outline0003" x="147" y="755" width="25" height="26" frameX="-0" frameY="-0" frameWidth="25" frameHeight="26"/>
<SubTexture name="diacritic-apostophe-fill0000" x="264" y="785" width="17" height="17" frameX="-0" frameY="-0" frameWidth="17" frameHeight="17"/>
<SubTexture name="diacritic-apostophe-fill0001" x="264" y="785" width="17" height="17" frameX="-0" frameY="-0" frameWidth="17" frameHeight="17"/>
<SubTexture name="diacritic-apostophe-fill0002" x="469" y="598" width="17" height="17" frameX="-0" frameY="-0" frameWidth="17" frameHeight="17"/>
<SubTexture name="diacritic-apostophe-fill0003" x="469" y="598" width="17" height="17" frameX="-0" frameY="-0" frameWidth="17" frameHeight="17"/>
<SubTexture name="diacritic-apostophe-outline0000" x="662" y="38" width="29" height="26" frameX="-0" frameY="-0" frameWidth="29" frameHeight="26"/>
<SubTexture name="diacritic-apostophe-outline0001" x="662" y="38" width="29" height="26" frameX="-0" frameY="-0" frameWidth="29" frameHeight="26"/>
<SubTexture name="diacritic-apostophe-outline0002" x="412" y="764" width="29" height="26" frameX="-0" frameY="-0" frameWidth="29" frameHeight="26"/>
<SubTexture name="diacritic-apostophe-outline0003" x="412" y="764" width="29" height="26" frameX="-0" frameY="-0" frameWidth="29" frameHeight="26"/>
<SubTexture name="diacritic-breve-fill0000" x="142" y="783" width="30" height="15" frameX="-0" frameY="-0" frameWidth="30" frameHeight="15"/>
<SubTexture name="diacritic-breve-fill0001" x="142" y="783" width="30" height="15" frameX="-0" frameY="-0" frameWidth="30" frameHeight="15"/>
<SubTexture name="diacritic-breve-fill0002" x="174" y="788" width="29" height="15" frameX="-1" frameY="-0" frameWidth="30" frameHeight="15"/>
<SubTexture name="diacritic-breve-fill0003" x="174" y="788" width="29" height="15" frameX="-1" frameY="-0" frameWidth="30" frameHeight="15"/>
<SubTexture name="diacritic-breve-outline0000" x="2" y="744" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-breve-outline0001" x="2" y="744" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-breve-outline0002" x="42" y="747" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-breve-outline0003" x="42" y="747" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-cadilla-fill0000" x="174" y="755" width="19" height="31" frameX="-0" frameY="-0" frameWidth="19" frameHeight="31"/>
<SubTexture name="diacritic-cadilla-fill0001" x="174" y="755" width="19" height="31" frameX="-0" frameY="-0" frameWidth="19" frameHeight="31"/>
<SubTexture name="diacritic-cadilla-fill0002" x="483" y="756" width="19" height="30" frameX="-0" frameY="-1" frameWidth="19" frameHeight="31"/>
<SubTexture name="diacritic-cadilla-fill0003" x="483" y="756" width="19" height="30" frameX="-0" frameY="-1" frameWidth="19" frameHeight="31"/>
<SubTexture name="diacritic-cadilla-outline0000" x="377" y="710" width="29" height="35" frameX="-0" frameY="-0" frameWidth="29" frameHeight="35"/>
<SubTexture name="diacritic-cadilla-outline0001" x="377" y="710" width="29" height="35" frameX="-0" frameY="-0" frameWidth="29" frameHeight="35"/>
<SubTexture name="diacritic-cadilla-outline0002" x="135" y="708" width="29" height="35" frameX="-0" frameY="-0" frameWidth="29" frameHeight="35"/>
<SubTexture name="diacritic-cadilla-outline0003" x="135" y="708" width="29" height="35" frameX="-0" frameY="-0" frameWidth="29" frameHeight="35"/>
<SubTexture name="diacritic-circumflex-fill0000" x="235" y="770" width="27" height="14" frameX="-1" frameY="-0" frameWidth="28" frameHeight="14"/>
<SubTexture name="diacritic-circumflex-fill0001" x="235" y="770" width="27" height="14" frameX="-1" frameY="-0" frameWidth="28" frameHeight="14"/>
<SubTexture name="diacritic-circumflex-fill0002" x="452" y="407" width="27" height="14" frameX="-1" frameY="-0" frameWidth="28" frameHeight="14"/>
<SubTexture name="diacritic-circumflex-fill0003" x="452" y="407" width="27" height="14" frameX="-1" frameY="-0" frameWidth="28" frameHeight="14"/>
<SubTexture name="diacritic-circumflex-outline0000" x="2" y="771" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-circumflex-outline0001" x="2" y="771" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-circumflex-outline0002" x="42" y="774" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-circumflex-outline0003" x="42" y="774" width="38" height="25" frameX="-0" frameY="-0" frameWidth="38" frameHeight="25"/>
<SubTexture name="diacritic-dot-fill0000" x="186" y="674" width="12" height="11" frameX="-0" frameY="-1" frameWidth="12" frameHeight="12"/>
<SubTexture name="diacritic-dot-fill0001" x="186" y="674" width="12" height="11" frameX="-0" frameY="-1" frameWidth="12" frameHeight="12"/>
<SubTexture name="diacritic-dot-fill0002" x="502" y="210" width="12" height="11" frameX="-0" frameY="-1" frameWidth="12" frameHeight="12"/>
<SubTexture name="diacritic-dot-fill0003" x="502" y="210" width="12" height="11" frameX="-0" frameY="-1" frameWidth="12" frameHeight="12"/>
<SubTexture name="diacritic-dot-outline0000" x="694" y="110" width="23" height="23" frameX="-0" frameY="-0" frameWidth="23" frameHeight="23"/>
<SubTexture name="diacritic-dot-outline0001" x="694" y="110" width="23" height="23" frameX="-0" frameY="-0" frameWidth="23" frameHeight="23"/>
<SubTexture name="diacritic-dot-outline0002" x="224" y="740" width="23" height="23" frameX="-0" frameY="-0" frameWidth="23" frameHeight="23"/>
<SubTexture name="diacritic-dot-outline0003" x="224" y="740" width="23" height="23" frameX="-0" frameY="-0" frameWidth="23" frameHeight="23"/>
<SubTexture name="diacritic-hookabove-fill0000" x="469" y="570" width="20" height="26" frameX="-0" frameY="-0" frameWidth="20" frameHeight="26"/>
<SubTexture name="diacritic-hookabove-fill0001" x="469" y="570" width="20" height="26" frameX="-0" frameY="-0" frameWidth="20" frameHeight="26"/>
<SubTexture name="diacritic-hookabove-fill0002" x="745" y="148" width="20" height="25" frameX="-0" frameY="-1" frameWidth="20" frameHeight="26"/>
<SubTexture name="diacritic-hookabove-fill0003" x="745" y="148" width="20" height="25" frameX="-0" frameY="-1" frameWidth="20" frameHeight="26"/>
<SubTexture name="diacritic-hookabove-outline0000" x="735" y="476" width="30" height="35" frameX="-0" frameY="-0" frameWidth="30" frameHeight="35"/>
<SubTexture name="diacritic-hookabove-outline0001" x="735" y="476" width="30" height="35" frameX="-0" frameY="-0" frameWidth="30" frameHeight="35"/>
<SubTexture name="diacritic-hookabove-outline0002" x="736" y="572" width="30" height="35" frameX="-0" frameY="-0" frameWidth="30" frameHeight="35"/>
<SubTexture name="diacritic-hookabove-outline0003" x="736" y="572" width="30" height="35" frameX="-0" frameY="-0" frameWidth="30" frameHeight="35"/>
<SubTexture name="diacritic-hookhorizontal-fill0000" x="662" y="176" width="33" height="23" frameX="-0" frameY="-0" frameWidth="33" frameHeight="23"/>
<SubTexture name="diacritic-hookhorizontal-fill0001" x="662" y="176" width="33" height="23" frameX="-0" frameY="-0" frameWidth="33" frameHeight="23"/>
<SubTexture name="diacritic-hookhorizontal-fill0002" x="327" y="780" width="33" height="23" frameX="-0" frameY="-0" frameWidth="33" frameHeight="23"/>
<SubTexture name="diacritic-hookhorizontal-fill0003" x="327" y="780" width="33" height="23" frameX="-0" frameY="-0" frameWidth="33" frameHeight="23"/>
<SubTexture name="diacritic-hookhorizontal-outline0000" x="463" y="296" width="39" height="34" frameX="-0" frameY="-0" frameWidth="39" frameHeight="34"/>
<SubTexture name="diacritic-hookhorizontal-outline0001" x="463" y="296" width="39" height="34" frameX="-0" frameY="-0" frameWidth="39" frameHeight="34"/>
<SubTexture name="diacritic-hookhorizontal-outline0002" x="551" y="437" width="39" height="34" frameX="-0" frameY="-0" frameWidth="39" frameHeight="34"/>
<SubTexture name="diacritic-hookhorizontal-outline0003" x="551" y="437" width="39" height="34" frameX="-0" frameY="-0" frameWidth="39" frameHeight="34"/>
<SubTexture name="diacritic-hookside-fill0000" x="212" y="151" width="28" height="50" frameX="-0" frameY="-0" frameWidth="28" frameHeight="50"/>
<SubTexture name="diacritic-hookside-fill0001" x="212" y="151" width="28" height="50" frameX="-0" frameY="-0" frameWidth="28" frameHeight="50"/>
<SubTexture name="diacritic-hookside-fill0002" x="327" y="85" width="28" height="50" frameX="-0" frameY="-0" frameWidth="28" frameHeight="50"/>
<SubTexture name="diacritic-hookside-fill0003" x="327" y="85" width="28" height="50" frameX="-0" frameY="-0" frameWidth="28" frameHeight="50"/>
<SubTexture name="diacritic-hookside-outline0000" x="430" y="2" width="34" height="62" frameX="-0" frameY="-0" frameWidth="34" frameHeight="62"/>
<SubTexture name="diacritic-hookside-outline0001" x="430" y="2" width="34" height="62" frameX="-0" frameY="-0" frameWidth="34" frameHeight="62"/>
<SubTexture name="diacritic-hookside-outline0002" x="686" y="416" width="34" height="62" frameX="-0" frameY="-0" frameWidth="34" frameHeight="62"/>
<SubTexture name="diacritic-hookside-outline0003" x="686" y="416" width="34" height="62" frameX="-0" frameY="-0" frameWidth="34" frameHeight="62"/>
<SubTexture name="diacritic-hookvertical-fill0000" x="507" y="737" width="23" height="35" frameX="-0" frameY="-0" frameWidth="23" frameHeight="35"/>
<SubTexture name="diacritic-hookvertical-fill0001" x="507" y="737" width="23" height="35" frameX="-0" frameY="-0" frameWidth="23" frameHeight="35"/>
<SubTexture name="diacritic-hookvertical-fill0002" x="532" y="737" width="23" height="35" frameX="-0" frameY="-0" frameWidth="23" frameHeight="35"/>
<SubTexture name="diacritic-hookvertical-fill0003" x="532" y="737" width="23" height="35" frameX="-0" frameY="-0" frameWidth="23" frameHeight="35"/>
<SubTexture name="diacritic-hookvertical-outline0000" x="731" y="615" width="34" height="38" frameX="-0" frameY="-1" frameWidth="34" frameHeight="39"/>
<SubTexture name="diacritic-hookvertical-outline0001" x="731" y="615" width="34" height="38" frameX="-0" frameY="-1" frameWidth="34" frameHeight="39"/>
<SubTexture name="diacritic-hookvertical-outline0002" x="727" y="261" width="34" height="38" frameX="-0" frameY="-1" frameWidth="34" frameHeight="39"/>
<SubTexture name="diacritic-hookvertical-outline0003" x="727" y="261" width="34" height="38" frameX="-0" frameY="-1" frameWidth="34" frameHeight="39"/>
<SubTexture name="diacritic-horn-fill0000" x="481" y="407" width="15" height="18" frameX="-0" frameY="-0" frameWidth="16" frameHeight="18"/>
<SubTexture name="diacritic-horn-fill0001" x="481" y="407" width="15" height="18" frameX="-0" frameY="-0" frameWidth="16" frameHeight="18"/>
<SubTexture name="diacritic-horn-fill0002" x="186" y="636" width="15" height="18" frameX="-0" frameY="-0" frameWidth="16" frameHeight="18"/>
<SubTexture name="diacritic-horn-fill0003" x="186" y="636" width="15" height="18" frameX="-0" frameY="-0" frameWidth="16" frameHeight="18"/>
<SubTexture name="diacritic-horn-outline0000" x="116" y="772" width="24" height="25" frameX="-0" frameY="-0" frameWidth="24" frameHeight="26"/>
<SubTexture name="diacritic-horn-outline0001" x="116" y="772" width="24" height="25" frameX="-0" frameY="-0" frameWidth="24" frameHeight="26"/>
<SubTexture name="diacritic-horn-outline0002" x="82" y="777" width="24" height="25" frameX="-0" frameY="-0" frameWidth="24" frameHeight="26"/>
<SubTexture name="diacritic-horn-outline0003" x="82" y="777" width="24" height="25" frameX="-0" frameY="-0" frameWidth="24" frameHeight="26"/>
<SubTexture name="diacritic-macron-fill0000" x="557" y="352" width="34" height="10" frameX="-1" frameY="-0" frameWidth="35" frameHeight="10"/>
<SubTexture name="diacritic-macron-fill0001" x="557" y="352" width="34" height="10" frameX="-1" frameY="-0" frameWidth="35" frameHeight="10"/>
<SubTexture name="diacritic-macron-fill0002" x="516" y="281" width="34" height="9" frameX="-1" frameY="-1" frameWidth="35" frameHeight="10"/>
<SubTexture name="diacritic-macron-fill0003" x="516" y="281" width="34" height="9" frameX="-1" frameY="-1" frameWidth="35" frameHeight="10"/>
<SubTexture name="diacritic-macron-outline0000" x="459" y="734" width="46" height="20" frameX="-0" frameY="-0" frameWidth="46" frameHeight="20"/>
<SubTexture name="diacritic-macron-outline0001" x="459" y="734" width="46" height="20" frameX="-0" frameY="-0" frameWidth="46" frameHeight="20"/>
<SubTexture name="diacritic-macron-outline0002" x="408" y="742" width="46" height="20" frameX="-0" frameY="-0" frameWidth="46" frameHeight="20"/>
<SubTexture name="diacritic-macron-outline0003" x="408" y="742" width="46" height="20" frameX="-0" frameY="-0" frameWidth="46" frameHeight="20"/>
<SubTexture name="diacritic-ogonek-fill0000" x="195" y="756" width="18" height="28" frameX="-0" frameY="-1" frameWidth="19" frameHeight="29"/>
<SubTexture name="diacritic-ogonek-fill0001" x="195" y="756" width="18" height="28" frameX="-0" frameY="-1" frameWidth="19" frameHeight="29"/>
<SubTexture name="diacritic-ogonek-fill0002" x="249" y="740" width="18" height="28" frameX="-0" frameY="-1" frameWidth="19" frameHeight="29"/>
<SubTexture name="diacritic-ogonek-fill0003" x="249" y="740" width="18" height="28" frameX="-0" frameY="-1" frameWidth="19" frameHeight="29"/>
<SubTexture name="diacritic-ogonek-outline0000" x="56" y="711" width="28" height="34" frameX="-0" frameY="-0" frameWidth="28" frameHeight="34"/>
<SubTexture name="diacritic-ogonek-outline0001" x="56" y="711" width="28" height="34" frameX="-0" frameY="-0" frameWidth="28" frameHeight="34"/>
<SubTexture name="diacritic-ogonek-outline0002" x="86" y="741" width="28" height="34" frameX="-0" frameY="-0" frameWidth="28" frameHeight="34"/>
<SubTexture name="diacritic-ogonek-outline0003" x="86" y="741" width="28" height="34" frameX="-0" frameY="-0" frameWidth="28" frameHeight="34"/>
<SubTexture name="diacritic-ring-fill0000" x="385" y="747" width="19" height="15" frameX="-0" frameY="-1" frameWidth="19" frameHeight="16"/>
<SubTexture name="diacritic-ring-fill0001" x="385" y="747" width="19" height="15" frameX="-0" frameY="-1" frameWidth="19" frameHeight="16"/>
<SubTexture name="diacritic-ring-fill0002" x="362" y="780" width="19" height="15" frameX="-0" frameY="-1" frameWidth="19" frameHeight="16"/>
<SubTexture name="diacritic-ring-fill0003" x="362" y="780" width="19" height="15" frameX="-0" frameY="-1" frameWidth="19" frameHeight="16"/>
<SubTexture name="diacritic-ring-outline0000" x="166" y="728" width="29" height="25" frameX="-0" frameY="-0" frameWidth="29" frameHeight="25"/>
<SubTexture name="diacritic-ring-outline0001" x="166" y="728" width="29" height="25" frameX="-0" frameY="-0" frameWidth="29" frameHeight="25"/>
<SubTexture name="diacritic-ring-outline0002" x="116" y="745" width="29" height="25" frameX="-0" frameY="-0" frameWidth="29" frameHeight="25"/>
<SubTexture name="diacritic-ring-outline0003" x="116" y="745" width="29" height="25" frameX="-0" frameY="-0" frameWidth="29" frameHeight="25"/>
<SubTexture name="diacritic-sicilicus-fill0000" x="726" y="2" width="12" height="24" frameX="-0" frameY="-0" frameWidth="12" frameHeight="24"/>
<SubTexture name="diacritic-sicilicus-fill0001" x="726" y="2" width="12" height="24" frameX="-0" frameY="-0" frameWidth="12" frameHeight="24"/>
<SubTexture name="diacritic-sicilicus-fill0002" x="727" y="301" width="12" height="24" frameX="-0" frameY="-0" frameWidth="12" frameHeight="24"/>
<SubTexture name="diacritic-sicilicus-fill0003" x="727" y="301" width="12" height="24" frameX="-0" frameY="-0" frameWidth="12" frameHeight="24"/>
<SubTexture name="diacritic-sicilicus-outline0000" x="275" y="718" width="24" height="36" frameX="-0" frameY="-0" frameWidth="25" frameHeight="36"/>
<SubTexture name="diacritic-sicilicus-outline0001" x="275" y="718" width="24" height="36" frameX="-0" frameY="-0" frameWidth="25" frameHeight="36"/>
<SubTexture name="diacritic-sicilicus-outline0002" x="301" y="743" width="24" height="36" frameX="-0" frameY="-0" frameWidth="25" frameHeight="36"/>
<SubTexture name="diacritic-sicilicus-outline0003" x="301" y="743" width="24" height="36" frameX="-0" frameY="-0" frameWidth="25" frameHeight="36"/>
<SubTexture name="diacritic-stroke0-long-fill0000" x="205" y="794" width="55" height="7" frameX="-0" frameY="-0" frameWidth="55" frameHeight="7"/>
<SubTexture name="diacritic-stroke0-long-fill0001" x="205" y="794" width="55" height="7" frameX="-0" frameY="-0" frameWidth="55" frameHeight="7"/>
<SubTexture name="diacritic-stroke0-long-fill0002" x="205" y="794" width="55" height="7" frameX="-0" frameY="-0" frameWidth="55" frameHeight="7"/>
<SubTexture name="diacritic-stroke0-long-fill0003" x="205" y="794" width="55" height="7" frameX="-0" frameY="-0" frameWidth="55" frameHeight="7"/>
<SubTexture name="diacritic-stroke0-long-outline0000" x="186" y="687" width="68" height="19" frameX="-0" frameY="-0" frameWidth="68" frameHeight="19"/>
<SubTexture name="diacritic-stroke0-long-outline0001" x="186" y="687" width="68" height="19" frameX="-0" frameY="-0" frameWidth="68" frameHeight="19"/>
<SubTexture name="diacritic-stroke0-long-outline0002" x="464" y="689" width="68" height="19" frameX="-0" frameY="-0" frameWidth="68" frameHeight="19"/>
<SubTexture name="diacritic-stroke0-long-outline0003" x="464" y="689" width="68" height="19" frameX="-0" frameY="-0" frameWidth="68" frameHeight="19"/>
<SubTexture name="diacritic-stroke0-short-fill0000" x="2" y="798" width="30" height="5" frameX="-0" frameY="-0" frameWidth="30" frameHeight="5"/>
<SubTexture name="diacritic-stroke0-short-fill0001" x="2" y="798" width="30" height="5" frameX="-0" frameY="-0" frameWidth="30" frameHeight="5"/>
<SubTexture name="diacritic-stroke0-short-fill0002" x="224" y="708" width="30" height="5" frameX="-0" frameY="-0" frameWidth="30" frameHeight="5"/>
<SubTexture name="diacritic-stroke0-short-fill0003" x="224" y="708" width="30" height="5" frameX="-0" frameY="-0" frameWidth="30" frameHeight="5"/>
<SubTexture name="diacritic-stroke0-short-outline0000" x="355" y="270" width="43" height="17" frameX="-0" frameY="-0" frameWidth="43" frameHeight="17"/>
<SubTexture name="diacritic-stroke0-short-outline0001" x="355" y="270" width="43" height="17" frameX="-0" frameY="-0" frameWidth="43" frameHeight="17"/>
<SubTexture name="diacritic-stroke0-short-outline0002" x="407" y="336" width="43" height="17" frameX="-0" frameY="-0" frameWidth="43" frameHeight="17"/>
<SubTexture name="diacritic-stroke0-short-outline0003" x="407" y="336" width="43" height="17" frameX="-0" frameY="-0" frameWidth="43" frameHeight="17"/>
<SubTexture name="diacritic-stroke30-fill0000" x="464" y="710" width="50" height="22" frameX="-0" frameY="-0" frameWidth="50" frameHeight="22"/>
<SubTexture name="diacritic-stroke30-fill0001" x="464" y="710" width="50" height="22" frameX="-0" frameY="-0" frameWidth="50" frameHeight="22"/>
<SubTexture name="diacritic-stroke30-fill0002" x="516" y="713" width="50" height="22" frameX="-0" frameY="-0" frameWidth="50" frameHeight="22"/>
<SubTexture name="diacritic-stroke30-fill0003" x="516" y="713" width="50" height="22" frameX="-0" frameY="-0" frameWidth="50" frameHeight="22"/>
<SubTexture name="diacritic-stroke30-outline0000" x="541" y="677" width="62" height="34" frameX="-0" frameY="-0" frameWidth="62" frameHeight="34"/>
<SubTexture name="diacritic-stroke30-outline0001" x="541" y="677" width="62" height="34" frameX="-0" frameY="-0" frameWidth="62" frameHeight="34"/>
<SubTexture name="diacritic-stroke30-outline0002" x="662" y="2" width="62" height="34" frameX="-0" frameY="-0" frameWidth="62" frameHeight="34"/>
<SubTexture name="diacritic-stroke30-outline0003" x="662" y="2" width="62" height="34" frameX="-0" frameY="-0" frameWidth="62" frameHeight="34"/>
<SubTexture name="diacritic-stroke45-long-fill0000" x="541" y="618" width="47" height="56" frameX="-0" frameY="-0" frameWidth="47" frameHeight="57"/>
<SubTexture name="diacritic-stroke45-long-fill0001" x="541" y="618" width="47" height="56" frameX="-0" frameY="-0" frameWidth="47" frameHeight="57"/>
<SubTexture name="diacritic-stroke45-long-fill0002" x="590" y="619" width="47" height="56" frameX="-0" frameY="-0" frameWidth="47" frameHeight="57"/>
<SubTexture name="diacritic-stroke45-long-fill0003" x="590" y="619" width="47" height="56" frameX="-0" frameY="-0" frameWidth="47" frameHeight="57"/>
<SubTexture name="diacritic-stroke45-long-outline0000" x="150" y="142" width="60" height="69" frameX="-0" frameY="-0" frameWidth="60" frameHeight="69"/>
<SubTexture name="diacritic-stroke45-long-outline0001" x="150" y="142" width="60" height="69" frameX="-0" frameY="-0" frameWidth="60" frameHeight="69"/>
<SubTexture name="diacritic-stroke45-long-outline0002" x="159" y="2" width="60" height="69" frameX="-0" frameY="-0" frameWidth="60" frameHeight="69"/>
<SubTexture name="diacritic-stroke45-long-outline0003" x="159" y="2" width="60" height="69" frameX="-0" frameY="-0" frameWidth="60" frameHeight="69"/>
<SubTexture name="diacritic-stroke45-short-fill0000" x="313" y="707" width="30" height="34" frameX="-0" frameY="-0" frameWidth="30" frameHeight="34"/>
<SubTexture name="diacritic-stroke45-short-fill0001" x="313" y="707" width="30" height="34" frameX="-0" frameY="-0" frameWidth="30" frameHeight="34"/>
<SubTexture name="diacritic-stroke45-short-fill0002" x="345" y="710" width="30" height="34" frameX="-0" frameY="-0" frameWidth="30" frameHeight="34"/>
<SubTexture name="diacritic-stroke45-short-fill0003" x="345" y="710" width="30" height="34" frameX="-0" frameY="-0" frameWidth="30" frameHeight="34"/>
<SubTexture name="diacritic-stroke45-short-outline0000" x="418" y="641" width="44" height="49" frameX="-0" frameY="-0" frameWidth="44" frameHeight="49"/>
<SubTexture name="diacritic-stroke45-short-outline0001" x="418" y="641" width="44" height="49" frameX="-0" frameY="-0" frameWidth="44" frameHeight="49"/>
<SubTexture name="diacritic-stroke45-short-outline0002" x="685" y="639" width="44" height="49" frameX="-0" frameY="-0" frameWidth="44" frameHeight="49"/>
<SubTexture name="diacritic-stroke45-short-outline0003" x="685" y="639" width="44" height="49" frameX="-0" frameY="-0" frameWidth="44" frameHeight="49"/>
<SubTexture name="diacritic-stroke60-fill0000" x="689" y="345" width="30" height="69" frameX="-0" frameY="-0" frameWidth="31" frameHeight="69"/>
<SubTexture name="diacritic-stroke60-fill0001" x="689" y="345" width="30" height="69" frameX="-0" frameY="-0" frameWidth="31" frameHeight="69"/>
<SubTexture name="diacritic-stroke60-fill0002" x="695" y="274" width="30" height="69" frameX="-0" frameY="-0" frameWidth="31" frameHeight="69"/>
<SubTexture name="diacritic-stroke60-fill0003" x="695" y="274" width="30" height="69" frameX="-0" frameY="-0" frameWidth="31" frameHeight="69"/>
<SubTexture name="diacritic-stroke60-outline0000" x="327" y="2" width="45" height="81" frameX="-0" frameY="-0" frameWidth="45" frameHeight="81"/>
<SubTexture name="diacritic-stroke60-outline0001" x="327" y="2" width="45" height="81" frameX="-0" frameY="-0" frameWidth="45" frameHeight="81"/>
<SubTexture name="diacritic-stroke60-outline0002" x="2" y="358" width="45" height="81" frameX="-0" frameY="-0" frameWidth="45" frameHeight="81"/>
<SubTexture name="diacritic-stroke60-outline0003" x="2" y="358" width="45" height="81" frameX="-0" frameY="-0" frameWidth="45" frameHeight="81"/>
<SubTexture name="diacritic-stroke90-long-fill0000" x="661" y="724" width="7" height="70" frameX="-0" frameY="-0" frameWidth="8" frameHeight="70"/>
<SubTexture name="diacritic-stroke90-long-fill0001" x="661" y="724" width="7" height="70" frameX="-0" frameY="-0" frameWidth="8" frameHeight="70"/>
<SubTexture name="diacritic-stroke90-long-fill0002" x="203" y="564" width="7" height="69" frameX="-0" frameY="-1" frameWidth="8" frameHeight="70"/>
<SubTexture name="diacritic-stroke90-long-fill0003" x="203" y="564" width="7" height="69" frameX="-0" frameY="-1" frameWidth="8" frameHeight="70"/>
<SubTexture name="diacritic-stroke90-long-outline0000" x="697" y="176" width="19" height="83" frameX="-0" frameY="-0" frameWidth="19" frameHeight="83"/>
<SubTexture name="diacritic-stroke90-long-outline0001" x="697" y="176" width="19" height="83" frameX="-0" frameY="-0" frameWidth="19" frameHeight="83"/>
<SubTexture name="diacritic-stroke90-long-outline0002" x="718" y="176" width="19" height="83" frameX="-0" frameY="-0" frameWidth="19" frameHeight="83"/>
<SubTexture name="diacritic-stroke90-long-outline0003" x="718" y="176" width="19" height="83" frameX="-0" frameY="-0" frameWidth="19" frameHeight="83"/>
<SubTexture name="diacritic-stroke90-short-fill0000" x="443" y="764" width="7" height="39" frameX="-0" frameY="-0" frameWidth="7" frameHeight="39"/>
<SubTexture name="diacritic-stroke90-short-fill0001" x="443" y="764" width="7" height="39" frameX="-0" frameY="-0" frameWidth="7" frameHeight="39"/>
<SubTexture name="diacritic-stroke90-short-fill0002" x="213" y="494" width="7" height="39" frameX="-0" frameY="-0" frameWidth="7" frameHeight="39"/>
<SubTexture name="diacritic-stroke90-short-fill0003" x="213" y="494" width="7" height="39" frameX="-0" frameY="-0" frameWidth="7" frameHeight="39"/>
<SubTexture name="diacritic-stroke90-short-outline0000" x="739" y="688" width="19" height="51" frameX="-0" frameY="-0" frameWidth="19" frameHeight="51"/>
<SubTexture name="diacritic-stroke90-short-outline0001" x="739" y="688" width="19" height="51" frameX="-0" frameY="-0" frameWidth="19" frameHeight="51"/>
<SubTexture name="diacritic-stroke90-short-outline0002" x="739" y="741" width="19" height="51" frameX="-0" frameY="-0" frameWidth="19" frameHeight="51"/>
<SubTexture name="diacritic-stroke90-short-outline0003" x="739" y="741" width="19" height="51" frameX="-0" frameY="-0" frameWidth="19" frameHeight="51"/>
<SubTexture name="diacritic-tilde-fill0000" x="599" y="421" width="33" height="14" frameX="-1" frameY="-1" frameWidth="34" frameHeight="15"/>
<SubTexture name="diacritic-tilde-fill0001" x="599" y="421" width="33" height="14" frameX="-1" frameY="-1" frameWidth="34" frameHeight="15"/>
<SubTexture name="diacritic-tilde-fill0002" x="467" y="210" width="33" height="14" frameX="-1" frameY="-1" frameWidth="34" frameHeight="15"/>
<SubTexture name="diacritic-tilde-fill0003" x="467" y="210" width="33" height="14" frameX="-1" frameY="-1" frameWidth="34" frameHeight="15"/>
<SubTexture name="diacritic-tilde-outline0000" x="722" y="448" width="44" height="26" frameX="-0" frameY="-0" frameWidth="44" frameHeight="27"/>
<SubTexture name="diacritic-tilde-outline0001" x="722" y="448" width="44" height="26" frameX="-0" frameY="-0" frameWidth="44" frameHeight="27"/>
<SubTexture name="diacritic-tilde-outline0002" x="418" y="692" width="44" height="26" frameX="-0" frameY="-0" frameWidth="44" frameHeight="27"/>
<SubTexture name="diacritic-tilde-outline0003" x="418" y="692" width="44" height="26" frameX="-0" frameY="-0" frameWidth="44" frameHeight="27"/>
<SubTexture name="diacritic-titlo-fill0000" x="644" y="484" width="37" height="16" frameX="-0" frameY="-1" frameWidth="37" frameHeight="17"/>
<SubTexture name="diacritic-titlo-fill0001" x="644" y="484" width="37" height="16" frameX="-0" frameY="-1" frameWidth="37" frameHeight="17"/>
<SubTexture name="diacritic-titlo-fill0002" x="687" y="615" width="37" height="16" frameX="-0" frameY="-1" frameWidth="37" frameHeight="17"/>
<SubTexture name="diacritic-titlo-fill0003" x="687" y="615" width="37" height="16" frameX="-0" frameY="-1" frameWidth="37" frameHeight="17"/>
<SubTexture name="diacritic-titlo-outline0000" x="713" y="516" width="47" height="26" frameX="-0" frameY="-0" frameWidth="47" frameHeight="27"/>
<SubTexture name="diacritic-titlo-outline0001" x="713" y="516" width="47" height="26" frameX="-0" frameY="-0" frameWidth="47" frameHeight="27"/>
<SubTexture name="diacritic-titlo-outline0002" x="713" y="544" width="47" height="26" frameX="-0" frameY="-0" frameWidth="47" frameHeight="27"/>
<SubTexture name="diacritic-titlo-outline0003" x="713" y="544" width="47" height="26" frameX="-0" frameY="-0" frameWidth="47" frameHeight="27"/>
<SubTexture name="diacritic-verticalline-fill0000" x="672" y="700" width="8" height="15" frameX="-0" frameY="-1" frameWidth="8" frameHeight="17"/>
<SubTexture name="diacritic-verticalline-fill0001" x="672" y="700" width="8" height="15" frameX="-0" frameY="-1" frameWidth="8" frameHeight="17"/>
<SubTexture name="diacritic-verticalline-fill0002" x="301" y="718" width="8" height="15" frameX="-0" frameY="-1" frameWidth="8" frameHeight="17"/>
<SubTexture name="diacritic-verticalline-fill0003" x="301" y="718" width="8" height="15" frameX="-0" frameY="-1" frameWidth="8" frameHeight="17"/>
<SubTexture name="diacritic-verticalline-outline0000" x="215" y="765" width="18" height="27" frameX="-0" frameY="-0" frameWidth="18" frameHeight="27"/>
<SubTexture name="diacritic-verticalline-outline0001" x="215" y="765" width="18" height="27" frameX="-0" frameY="-0" frameWidth="18" frameHeight="27"/>
<SubTexture name="diacritic-verticalline-outline0002" x="269" y="756" width="18" height="27" frameX="-0" frameY="-0" frameWidth="18" frameHeight="27"/>
<SubTexture name="diacritic-verticalline-outline0003" x="269" y="756" width="18" height="27" frameX="-0" frameY="-0" frameWidth="18" frameHeight="27"/>
</TextureAtlas>
+6 -3
View File
@@ -4,10 +4,11 @@
<str id="editor.autosavingIn">Autosaving in {0} seconds{1}</str>
<str id="editor.autosavingCanceledSuffix">(Canceled)!</str>
<str id="editor.saveClose">Save &amp; Close</str>
<str id="editor.save">Save</str>
<str id="editor.close">Close</str>
<str id="editor.ok">Ok</str>
<str id="editor.cancel">Cancel</str>
<str id="editor.save">Save</str>
<str id="editor.saveClose">Save &amp; Close</str>
<str id="editor.close">Close</str>
</group>
<group name="CharterSelection" prefix="charterSelection.">
@@ -260,9 +261,11 @@
<!-- Character Editor -->
<group name="CharacterSelection" prefix="characterSelection.">
<str id="acceptFolder">Press ACCEPT to edit this folder.</str>
<str id="acceptCharacter">Press ACCEPT to edit this character.</str>
<str id="newCharacter">New Character</str>
<str id="desc">Select a character to edit</str>
<str id="desc-folder">Select a character to edit in {0}</str>
<group name="Warnings" prefix="warnings.">
<str id="notImplemented-title">New Character: Feature Not Implemented!</str>
+4 -1
View File
@@ -72,7 +72,8 @@
<group name="BetaWarning">
<str id="betaWarning.title">WARNING</str>
<str id="betaWarning.desc">This engine is still in a *{0}* state. That means *majority of the features* are either *buggy* or *non finished*. If you find any bugs, please report them to the Codename Engine GitHub.\n\nPress {1} to continue</str>
<str id="betaWarning.desc">This engine is still in a *{0}* state. That means *majority of the features* are either *buggy* or *non finished*. If you find any bugs, please report them to the Codename Engine GitHub.</str>
<str id="betaWarning.proceed">Press {0} to continue</str>
</group>
<group name="Updater">
@@ -100,5 +101,7 @@
<str id="diff.easy">Easy</str>
<str id="diff.normal">Normal</str>
<str id="diff.hard">Hard</str>
<str id="diff.erect">Erect</str>
<str id="diff.nightmare">Nightmare</str>
</group>
</language>
+1 -2
View File
@@ -42,8 +42,7 @@
<str id="category.engine">Engine</str>
<group name="engine" prefix="engine.">
<!-- Change this to / when alphabet has it -->
<str id="switchMod">Change Mod or Mode</str>
<str id="switchMod">Mod/Mode</str>
</group>
</group>
+7 -9
View File
@@ -3,19 +3,17 @@
// Used for editors
int steps = 16;
int stepsInside = 2;
float strength = 0.0075;
const int steps = 16;
const int stepsInside = 2;
const float strength = 0.0075;
vec4 getColor(vec2 pos) {
vec2 ps = (pos);
ps = clamp(ps, vec2(0.0), 1.0 - (1.0 / openfl_TextureSize.xy));
return flixel_texture2D(bitmap, (ps));
pos = clamp(pos, vec2(0.0), vec2(1.0));//1.0 - (1.0 / openfl_TextureSize.xy));
return flixel_texture2D(bitmap, pos);
}
void main() {
// vec2 camPos = getCamPos(openfl_TextureCoordv);
vec2 camPos = openfl_TextureCoordv;
if (camPos.x < 0.0 || camPos.x > 1.0 || camPos.y < 0.0 || camPos.y > 1.0)
return;
vec4 color = getColor(camPos);
float fsteps = float(steps);
+15 -44
View File
@@ -2,58 +2,29 @@
// Used for editors (faster)
//#define iResolution _camSize
#define getTexture textureCam
#define iResolution openfl_TextureSize
//#define getTexture flixel_texture2D
float uBlur = 0.015;
float uBrightness = 0.6;
const float uBlur = 0.015;
const float uBrightness = 0.6;
vec4 getColor(vec2 pos) {
vec2 ps = (pos);
if (ps.x < 0.0) ps.x = 0.0;
//else if (ps.x > 1.0 - (1.0 / iResolution.x)) ps.x = 1.0 - (1.0 / iResolution.x);
else if (ps.x > 1.0) return vec4(0.0);
if (ps.y < 0.0) ps.y = 0.0;
//else if (ps.y > 1.0 - (1.0 / iResolution.y)) return ps.y = 1.0 - (1.0 / iResolution.y);
else if (ps.y > 1.0) return vec4(0.0);
return flixel_texture2D(bitmap, (ps));
pos = clamp(pos, vec2(0.0), vec2(1.0));//1.0 - (1.0 / openfl_TextureSize.xy));
return flixel_texture2D(bitmap, pos);
}
vec2 fixvec2(float x, float y) { // makes an uv the same across sizes
vec2 val = vec2(x, y);
val.xy *= vec2(1280.0, 720.0);
val.xy /= iResolution.xy;
return val;
}
vec2 fixvec2(vec2 uv) { // makes an uv the same across sizes
vec2 val = uv;
val.xy *= vec2(1280.0, 720.0);
val.xy /= iResolution.xy;
return val;
}
uniform sampler2D noiseTexture;
uniform vec2 noiseTextureSize;
vec2 random(vec2 p) {
p = vec2(dot(p,vec2(127.1,311.7)),dot(p,vec2(269.5,183.3)));
return fract(sin(p)*4375.5);
p *= openfl_TextureSize;
return texture2D(noiseTexture, p / noiseTextureSize).rg - vec2(0.5);
}
void main() {
vec2 camPos = (openfl_TextureCoordv);
//vec2 camPos = openfl_TextureCoordv;
if (camPos.x < 0.0 || camPos.x > 1.0 || camPos.y < 0.0 || camPos.y > 1.0)
return;
vec2 camPos = openfl_TextureCoordv;
vec2 blur = vec2(uBlur) * vec2(1.0, openfl_TextureSize.x / openfl_TextureSize.y);
//vec4 color = getColor(camPos);
vec2 blur = vec2(uBlur) * vec2(1.0, iResolution.x / iResolution.y);
vec4 a = getColor(camPos+(random(camPos)*blur - blur / 2.0)) * uBrightness;
a += getColor(camPos+(random(camPos+0.1)*blur - blur / 2.0)) * uBrightness;
a += getColor(camPos+(random(camPos+0.2)*blur - blur / 2.0)) * uBrightness;
//a += getColor(camPos+(random(camPos+0.3)*blur - blur / 2.0)) * uBrightness;
gl_FragColor = a / 3.0;
vec4 a = getColor(camPos+random(camPos)*blur);
a += getColor(camPos+random(camPos+0.1)*blur);
//a += getColor(camPos+random(camPos+0.2)*blur);
//a += getColor(camPos+random(camPos+0.3)*blur);
gl_FragColor = (a / 2.0) * uBrightness;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 192 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 769 KiB

-3
View File
@@ -118,9 +118,6 @@
<!-- Comment this out to disable multithreading !-->
<haxedef name="ALLOW_MULTITHREADING" unless="web || flash" />
<!-- Comment this out to disable titlescreen.xml !-->
<haxedef name="TITLESCREEN_XML" />
<!-- Comment this out to disable mods folder !-->
<haxedef name="MOD_SUPPORT" unless="web"/>
+6 -2
View File
@@ -219,7 +219,7 @@ class StringTools {
If `start` is the empty String `""`, the result is true.
**/
public static #if (java || python || (js && js_es >= 6)) inline #end function startsWith(s:String, start:String):Bool {
public static #if (java || python || (js && js_es >= 6) || cpp) inline #end function startsWith(s:String, start:String):Bool {
#if java
return (cast s : java.NativeString).startsWith(start);
#elseif hl
@@ -230,6 +230,8 @@ class StringTools {
return (cast s).startsWith(start);
#elseif lua
return untyped __lua__("{0}:sub(1, #{1}) == {1}", s, start);
#elseif cpp
return untyped s.__StartsWith(start);
#else
return (s.length >= start.length && s.indexOf(start, 0) == 0);
#end
@@ -242,7 +244,7 @@ class StringTools {
If `end` is the empty String `""`, the result is true.
**/
public static #if (java || python || (js && js_es >= 6)) inline #end function endsWith(s:String, end:String):Bool {
public static #if (java || python || (js && js_es >= 6) || cpp) inline #end function endsWith(s:String, end:String):Bool {
#if java
return (cast s : java.NativeString).endsWith(end);
#elseif hl
@@ -255,6 +257,8 @@ class StringTools {
return (cast s).endsWith(end);
#elseif lua
return end == "" || untyped __lua__("{0}:sub(-#{1}) == {1}", s, end);
#elseif cpp
return untyped s.__EndsWith(end);
#else
var elen = end.length;
var slen = s.length;
+1 -1
View File
@@ -87,7 +87,7 @@ class Flx3DCamera extends FlxCamera {
default: new OBJParser();
}, (event:Asset3DEvent) -> {
if (event.asset != null && event.asset.assetType == Asset3DType.MESH) {
var mesh:Mesh = cast(event.asset, Mesh);
var mesh:Mesh = cast event.asset;
if (material != null)
mesh.material = material;
meshes.push(mesh);
+1 -1
View File
@@ -60,7 +60,7 @@ class Flx3DView extends FlxView3D {
default: new OBJParser();
}, (event:Asset3DEvent) -> {
if (event.asset != null && event.asset.assetType == Asset3DType.MESH) {
var mesh:Mesh = cast(event.asset, Mesh);
var mesh:Mesh = cast event.asset;
if (material != null)
mesh.material = material;
meshes.push(mesh);
+3 -3
View File
@@ -4,12 +4,12 @@ import funkin.backend.system.interfaces.IBeatReceiver;
class MusicBeatGroup extends FlxTypedSpriteGroup<FlxSprite> implements IBeatReceiver {
public function beatHit(curBeat:Int) {
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).beatHit(curBeat);
for(e in members) if (e is IBeatReceiver) ({var _:IBeatReceiver = cast e;_;}).beatHit(curBeat);
}
public function stepHit(curStep:Int) {
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).stepHit(curStep);
for(e in members) if (e is IBeatReceiver) ({var _:IBeatReceiver = cast e;_;}).stepHit(curStep);
}
public function measureHit(curMeasure:Int) {
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure);
for(e in members) if (e is IBeatReceiver) ({var _:IBeatReceiver = cast e;_;}).measureHit(curMeasure);
}
}
+6 -5
View File
@@ -192,19 +192,19 @@ class MusicBeatState extends FlxState implements IBeatReceiver
@:dox(hide) public function stepHit(curStep:Int):Void
{
for(e in members) if (e != null && e is IBeatReceiver) cast(e, IBeatReceiver).stepHit(curStep);
for(e in members) if (e != null && e is IBeatReceiver) ({var _:IBeatReceiver=cast e;_;}).stepHit(curStep);
call("stepHit", [curStep]);
}
@:dox(hide) public function beatHit(curBeat:Int):Void
{
for(e in members) if (e != null && e is IBeatReceiver) cast(e, IBeatReceiver).beatHit(curBeat);
for(e in members) if (e != null && e is IBeatReceiver) ({var _:IBeatReceiver=cast e;_;}).beatHit(curBeat);
call("beatHit", [curBeat]);
}
@:dox(hide) public function measureHit(curMeasure:Int):Void
{
for(e in members) if (e != null && e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure);
for(e in members) if (e != null && e is IBeatReceiver) ({var _:IBeatReceiver=cast e;_;}).measureHit(curMeasure);
call("measureHit", [curMeasure]);
}
@@ -278,8 +278,9 @@ class MusicBeatState extends FlxState implements IBeatReceiver
public override function resetSubState() {
super.resetSubState();
if (subState != null && subState is MusicBeatSubstate) {
cast(subState, MusicBeatSubstate).parent = this;
cast(subState, MusicBeatSubstate).onSubstateOpen();
var subState:MusicBeatSubstate = cast subState;
subState.parent = this;
subState.onSubstateOpen();
}
}
}
+5 -4
View File
@@ -181,19 +181,19 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
@:dox(hide) public function stepHit(curStep:Int):Void
{
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).stepHit(curStep);
for(e in members) if (e is IBeatReceiver) ({var _:IBeatReceiver=cast e;_;}).stepHit(curStep);
call("stepHit", [curStep]);
}
@:dox(hide) public function beatHit(curBeat:Int):Void
{
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).beatHit(curBeat);
for(e in members) if (e is IBeatReceiver) ({var _:IBeatReceiver=cast e;_;}).beatHit(curBeat);
call("beatHit", [curBeat]);
}
@:dox(hide) public function measureHit(curMeasure:Int):Void
{
for(e in members) if (e is IBeatReceiver) cast(e, IBeatReceiver).measureHit(curMeasure);
for(e in members) if (e is IBeatReceiver) ({var _:IBeatReceiver=cast e;_;}).measureHit(curMeasure);
call("measureHit", [curMeasure]);
}
@@ -256,7 +256,8 @@ class MusicBeatSubstate extends FlxSubState implements IBeatReceiver
public override function resetSubState() {
if (subState != null && subState is MusicBeatSubstate) {
cast(subState, MusicBeatSubstate).parent = this;
var subState:MusicBeatSubstate = cast subState;
subState.parent = this;
super.resetSubState();
if (subState != null)
cast(subState, MusicBeatSubstate).onSubstateOpen();
+8
View File
@@ -124,6 +124,14 @@ class Paths
return getPath('data/characters/$character.xml', null);
}
/**
* Gets the name of a registered font.
* @param font The font's path (if it's already passed as a font name, the same name will be returned)
*/
inline static public function getFontName(font:String) {
return OpenFlAssets.exists(font, FONT) ? OpenFlAssets.getFont(font).fontName : font;
}
public static inline function font(key:String) {
return getPath('fonts/$key');
}
@@ -33,8 +33,8 @@ class MultiThreadedScript implements IFlxDestroyable implements IHScriptCustomBe
if (parentScript != null) {
if (script is HScript && parentScript is HScript) {
var hscript = cast(script, HScript);
var parentHScript = cast(parentScript, HScript);
var hscript:HScript = cast script;
var parentHScript:HScript = cast parentScript;
hscript.interp.variables = parentHScript.interp.variables;
hscript.interp.publicVariables = parentHScript.interp.publicVariables;
@@ -0,0 +1,21 @@
package funkin.backend.scripting.events;
import funkin.game.Character;
import haxe.xml.Access;
final class CharacterNodeEvent extends CancellableEvent {
/**
* The character instance
*/
public var character:Character;
/**
* The node which is currently being parsed
*/
public var node:Access;
/**
* The name of the node, quicker access than e.node.name
*/
public var name:String;
}
@@ -0,0 +1,16 @@
package funkin.backend.scripting.events;
import funkin.game.Character;
import haxe.xml.Access;
final class CharacterXMLEvent extends CancellableEvent {
/**
* The character instance
*/
public var character:Character;
/**
* The xml
*/
public var xml:Access;
}
+6 -2
View File
@@ -181,7 +181,11 @@ class Conductor
private static var __updateMeasure:Bool;
private static function update() {
if (FlxG.state != null && FlxG.state is MusicBeatState && cast(FlxG.state, MusicBeatState).cancelConductorUpdate) return;
if (FlxG.state != null && FlxG.state is MusicBeatState) {
var state:MusicBeatState = cast FlxG.state;
if(state.cancelConductorUpdate)
return;
}
__updateSongPos(FlxG.elapsed);
@@ -233,7 +237,7 @@ class Conductor
var state = FlxG.state;
while(state != null) {
if (state is IBeatReceiver && (state.subState == null || state.persistentUpdate)) {
var st = cast(state, IBeatReceiver);
var st:IBeatReceiver = cast state;
if (curStep > oldStep) {
for(i in oldStep...curStep) {
st.stepHit(i+1);
+50 -15
View File
@@ -11,8 +11,7 @@ class Logs {
public static var nativeTrace = Log.trace;
public static function init() {
Log.trace = function(v : Dynamic, ?infos : Null<haxe.PosInfos>) {
Log.trace = function(v:Dynamic, ?infos:Null<haxe.PosInfos>) {
var data = [
logText('${infos.fileName}:${infos.lineNumber}: ', CYAN),
logText(Std.string(v))
@@ -28,22 +27,48 @@ class Logs {
__showInConsole(prepareColoredTrace(data, TRACE));
};
LogFrontEnd.onLogs = function(Data, Style, FireOnce) {
LogFrontEnd.onLogs = function(data, style, fireOnce) {
var prefix = "[FLIXEL]";
var color:ConsoleColor = LIGHTGRAY;
var level:Level = INFO;
if (Style == LogStyle.CONSOLE) {prefix = "> "; color = WHITE; level = INFO; } else
if (Style == LogStyle.ERROR) {prefix = "[FLIXEL]"; color = RED; level = ERROR; } else
if (Style == LogStyle.NORMAL) {prefix = "[FLIXEL]"; color = WHITE; level = INFO; } else
if (Style == LogStyle.NOTICE) {prefix = "[FLIXEL]"; color = GREEN; level = VERBOSE;} else
if (Style == LogStyle.WARNING) {prefix = "[FLIXEL]"; color = YELLOW; level = WARNING;}
if (style == LogStyle.CONSOLE) // cant place a switch here as these arent inline values - Nex
{
prefix = "> ";
color = WHITE;
level = INFO;
}
else if (style == LogStyle.ERROR)
{
prefix = "[FLIXEL]";
color = RED;
level = ERROR;
}
else if (style == LogStyle.NORMAL)
{
prefix = "[FLIXEL]";
color = WHITE;
level = INFO;
}
else if (style == LogStyle.NOTICE)
{
prefix = "[FLIXEL]";
color = GREEN;
level = VERBOSE;
}
else if (style == LogStyle.WARNING)
{
prefix = "[FLIXEL]";
color = YELLOW;
level = WARNING;
}
var d:Dynamic = Data;
var d:Dynamic = data;
if (!(d is Array))
d = [d];
var a:Array<Dynamic> = d;
var strs = [for(e in a) Std.string(e)];
for(e in strs) {
for(e in strs)
{
Logs.trace('$prefix $e', level, color);
}
};
@@ -55,7 +80,8 @@ class Logs {
logText('[ '),
logText('${Std.string(time.getHours()).addZeros(2)}:${Std.string(time.getMinutes()).addZeros(2)}:${Std.string(time.getSeconds()).addZeros(2)}', DARKMAGENTA),
logText(' |'),
switch(level) {
switch (level)
{
case WARNING: logText(' WARNING ', DARKYELLOW);
case ERROR: logText(' ERROR ', DARKRED);
case TRACE: logText(' TRACE ', GRAY);
@@ -79,7 +105,7 @@ class Logs {
}
public static function __showInConsole(text:Array<LogText>) {
#if sys
#if (sys && !mobile)
while(__showing) {
Sys.sleep(0.05);
}
@@ -91,15 +117,23 @@ class Logs {
NativeAPI.setConsoleColors();
Sys.print("\r\n");
__showing = false;
#elseif mobile
while(__showing) {
Sys.sleep(0.05);
}
__showing = true;
@:privateAccess
Sys.print([for(t in text) t.text].join(""));
__showing = false;
#else
@:privateAccess
nativeTrace([for(t in text) t.text].join(""));
#end
}
public static function traceColored(text:Array<LogText>, level:Level = INFO) {
public static function traceColored(text:Array<LogText>, level:Level = INFO)
__showInConsole(prepareColoredTrace(text, level));
}
public static function trace(text:String, level:Level = INFO, color:ConsoleColor = LIGHTGRAY, ?prefix:String) {
var text = [logText(text, color)];
if(prefix != null) text.insert(0, getPrefix(prefix));
@@ -144,7 +178,8 @@ enum abstract Level(Int) {
var SUCCESS = 5;
var FAILURE = 6;
}
typedef LogText = {
var text:String;
var color:ConsoleColor;
}
}
+9
View File
@@ -1,5 +1,6 @@
package funkin.backend.system;
import funkin.backend.utils.translations.FormatUtil;
import flixel.addons.transition.FlxTransitionSprite.GraphicTransTileDiamond;
import flixel.addons.transition.FlxTransitionableState;
import flixel.addons.transition.TransitionData;
@@ -58,6 +59,12 @@ class Main extends Sprite
public static var gameThreads:Array<Thread> = [];
#end
public static function preInit() {
funkin.backend.utils.NativeAPI.registerAsDPICompatible();
funkin.backend.system.CommandLineHandler.parseCommandLine(Sys.args());
funkin.backend.system.Main.fixWorkingDirectory();
}
public function new()
{
super();
@@ -166,6 +173,8 @@ class Main extends Sprite
}
public static function refreshAssets() {
WindowUtils.resetTitle();
FlxSoundTray.volumeChangeSFX = Paths.sound('menu/volume');
FlxSoundTray.volumeUpChangeSFX = null;
FlxSoundTray.volumeDownChangeSFX = null;
@@ -91,7 +91,7 @@ class SystemInfo extends FramerateCategory {
#end
if(openfl.display3D.Context3D.__glMemoryTotalAvailable != -1) {
var vRAMBytes:UInt = cast(flixel.FlxG.stage.context3D.gl.getParameter(openfl.display3D.Context3D.__glMemoryTotalAvailable), UInt);
var vRAMBytes:UInt = cast flixel.FlxG.stage.context3D.gl.getParameter(openfl.display3D.Context3D.__glMemoryTotalAvailable);
if (vRAMBytes == 1000 || vRAMBytes == 1 || vRAMBytes <= 0)
Logs.error('Unable to grab GPU VRAM');
else
@@ -62,6 +62,7 @@ class AudioSwitchFix {
}
}
@:dox(hide)
typedef PlayingSound = {
var sound:FlxSound;
var time:Float;
@@ -20,10 +20,10 @@ class CrashHandler {
public static function onUncaughtError(e:UncaughtErrorEvent) {
var m:String = e.error;
if (Std.isOfType(e.error, Error)) {
var err = cast(e.error, Error);
var err:Error = cast e.error;
m = '${err.message}';
} else if (Std.isOfType(e.error, ErrorEvent)) {
var err = cast(e.error, ErrorEvent);
var err:ErrorEvent = cast e.error;
m = '${err.text}';
}
var stack = CallStack.exceptionStack();
+5 -2
View File
@@ -626,7 +626,7 @@ class CoolUtil
var fmt = new FlxTextFormat();
fmt.format.color = Reflect.hasField(fmtt, "color") ? FlxColor.fromString(fmtt.color) : text.color;
fmt.format.font = Reflect.hasField(fmtt, "font") ? Paths.font(fmtt.font) : text.font;
fmt.format.font = Reflect.hasField(fmtt, "font") ? Paths.getFontName(Paths.font(fmtt.font)) : text.font;
fmt.format.size = Reflect.hasField(fmtt, "size") ? Std.parseInt(fmtt.size) : text.size;
fmt.format.italic = Reflect.hasField(fmtt, "italic") ? fmtt.italic == "true" : text.italic;
fmt.format.bold = Reflect.hasField(fmtt, "bold") ? fmtt.bold == "true" : text.bold;
@@ -751,7 +751,10 @@ class CoolUtil
*/
@:noUsing public static inline function openURL(url:String) {
#if linux
Sys.command('/usr/bin/xdg-open', [url]);
// generally `xdg-open` should work in every distro
var cmd = Sys.command("xdg-open", [url]);
// run old command JUST IN CASE it fails, which it shouldn't
if (cmd != 0) cmd = Sys.command("/usr/bin/xdg-open", [url]);
#else
FlxG.openURL(url);
#end
+4 -2
View File
@@ -140,14 +140,16 @@ class MemoryUtil {
reg.match(process.stdout.readAll().toString());
if (process.exitCode() == 0) return reg.matched(1);
#elseif linux
var process = new HiddenProcess("sudo", ["dmidecode", "--type", "17"]);
/*var process = new HiddenProcess("sudo", ["dmidecode", "--type", "17"]);
if (process.exitCode() != 0) return "Unknown";
var lines = process.stdout.readAll().toString().split("\n");
for (line in lines) {
if (line.startsWith("Type:")) {
return line.substring("Type:".length).trim();
}
}
}*/
// TODO: sort of unsafe? also requires users to use `sudo`
// when launching the engine through the CLI, REIMPLEMENT LATER.
#end
return "Unknown";
}
+2 -2
View File
@@ -113,8 +113,8 @@ class NativeAPI {
if(backgroundColor == NONE)
backgroundColor = BLACK;
var fg = cast(foregroundColor, Int);
var bg = cast(backgroundColor, Int);
var fg:Int = cast foregroundColor;
var bg:Int = cast backgroundColor;
Windows.setConsoleColors((bg * 16) + fg);
#elseif sys
Sys.print("\x1b[0m");
+53 -1
View File
@@ -6,6 +6,13 @@ import funkin.backend.FunkinSprite.XMLAnimType;
import funkin.backend.FunkinSprite;
import funkin.game.Character;
import funkin.backend.system.ErrorCode;
import funkin.backend.FunkinSprite.XMLAnimType;
import flixel.util.FlxColor;
import haxe.xml.Access;
import funkin.backend.scripting.Script;
import funkin.backend.scripting.DummyScript;
import funkin.backend.scripting.ScriptPack;
import flixel.util.typeLimit.OneOfTwo;
import funkin.backend.system.interfaces.IOffsetCompatible;
import haxe.xml.Access;
@@ -252,7 +259,7 @@ class XMLUtil {
cast(sprite, IOffsetCompatible).addOffset(animData.name, animData.x, animData.y);
if (sprite is FunkinSprite) {
var xmlSpr = cast(sprite, FunkinSprite);
var xmlSpr:FunkinSprite = cast sprite;
var name = animData.name;
switch(animData.animType) {
case BEAT:
@@ -328,6 +335,51 @@ class XMLUtil {
}
}
class XMLImportedScriptInfo {
public var path:String;
public var shortLived:Bool = false;
public var loadBefore:Bool = true;
public var importStageSprites:Bool = false; // maybe will change later?? - Nex
public var parentScriptPack:ScriptPack = null;
public function new(path:String, parentScriptPack:ScriptPack) {
this.parentScriptPack = parentScriptPack;
this.path = path;
}
public function getScript():Script
return parentScriptPack == null ? null : parentScriptPack.getByPath(path);
public static function prepareInfos(node:Access, parentScriptPack:ScriptPack, ?onScriptPreLoad:XMLImportedScriptInfo->Void):XMLImportedScriptInfo {
if (!node.has.script || parentScriptPack == null) return null;
var folder = node.getAtt("folder").getDefault("data/scripts/");
if (!folder.endsWith("/")) folder += "/";
var path = Paths.script(folder + node.getAtt("script"));
var daScript = Script.create(path);
if (daScript is DummyScript) {
Logs.trace('Script Extension at ${path} does not exist.', ERROR);
return null;
}
var infos = new XMLImportedScriptInfo(daScript.path, parentScriptPack);
infos.shortLived = node.getAtt("isShortLived") == "true" || node.getAtt("shortLived") == "true";
infos.importStageSprites = node.getAtt("importStageSprites") == "true";
@:privateAccess infos.loadBefore = shouldLoadBefore(node);
if (onScriptPreLoad != null) onScriptPreLoad(infos);
parentScriptPack.add(daScript);
daScript.set("scriptInfo", infos);
daScript.load();
return infos;
}
@:dox(hide) public static inline function shouldLoadBefore(node:Access):Bool
return node.getAtt("loadBefore") != "false";
}
typedef AnimData = {
var name:String;
var anim:String;
@@ -5,7 +5,7 @@ package funkin.backend.utils.translations;
*
* For example if the parameter list is just an `Int` which is `9`, `You have been blue balled {0} times` becomes `You have been blue balled 9 times`.
*/
class FormatUtil {
final class FormatUtil {
private static var cache:Map<String, IFormatInfo> = new Map();
private static var cacheStr:Map<String, IFormatInfo> = new Map();
@@ -87,14 +87,17 @@ class ParamFormatInfo implements IFormatInfo {
public function format(params:Array<Dynamic>):String {
if (params == null) params = [];
var str:String = "";
for (i=>s in strings) {
str += s;
if (i < indexes.length)
str += params[indexes[i]];
}
var lenStr = strings.length;
var lenInd = indexes.length;
return str;
var arr = new haxe.ds.Vector<String>(lenStr + ((lenStr < lenInd) ? lenStr : lenInd));
var i = 0;
for (idx=>s in strings) {
arr[i++] = s;
if (idx < lenInd)
arr[i++] = Std.string(params[indexes[idx]]);
}
return arr.join("");
}
public function toString():String {
+1 -1
View File
@@ -206,7 +206,7 @@ class EditorPickerOption extends FlxTypedSpriteGroup<FlxSprite> {
iconSpr.x = 25 + ((height - iconSpr.width) / 2);
iconSpr.y = (height - iconSpr.height) / 2;
label = new Alphabet(25 + iconSpr.width + 25, 0, name, true);
label = new Alphabet(25 + iconSpr.width + 25, 0, name, "bold");
label.y = (height - label.height) / 2;
selectionBG = new FlxSprite().makeGraphic(1, 1, -1);
@@ -4,6 +4,7 @@ import funkin.game.Character;
import funkin.options.OptionsScreen;
import funkin.options.type.IconOption;
import funkin.options.type.NewOption;
import funkin.options.type.TextOption;
import funkin.options.type.OptionType;
class CharacterSelection extends EditorTreeMenu
@@ -16,22 +17,46 @@ class CharacterSelection extends EditorTreeMenu
bgType = "charter";
super.create();
var modsList:Array<String> = Character.getList(true);
var isMods:Bool = true;
var modsList:Array<String> = Character.getList(true, true);
var list:Array<OptionType> = [
for (char in (modsList.length == 0 ? Character.getList(false) : modsList))
new IconOption(char, translate("acceptCharacter"), Character.getIconFromCharName(char),
function() {
FlxG.switchState(new CharacterEditor(char));
})
];
if(modsList.length == 0) {
modsList = Character.getList(false, true);
isMods = false;
}
var newChar = translate("newCharacter");
list.insert(0, new NewOption(newChar, newChar, function() {
openSubState(new UIWarningSubstate(translate("warnings.notImplemented-title"), translate("warnings.notImplemented-body"), [
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}}
]));
}));
function generateList(modsList:Array<String>, isMods:Bool, folderPath:String = ""):Array<OptionType> {
var list:Array<OptionType> = [];
for(char in modsList) {
if(char.endsWith("/")) {
var folderName = CoolUtil.getFilename(char.substr(0, char.length-1));
list.push(new TextOption(folderName + " >", translate("acceptFolder"), function() {
var newModsList = Character.getList(isMods, true, char);
var newList:Array<OptionType> = generateList(newModsList, isMods, folderPath + folderName + "/");
optionsTree.add(new OptionsScreen(folderPath + folderName, translate("desc-folder", [folderPath + folderName + "/"]), newList));
}));
} else {
list.push(new IconOption(char, translate("acceptCharacter"), Character.getIconFromCharName(folderPath + char, char),
function() {
FlxG.switchState(new CharacterEditor(folderPath + char));
})
);
}
}
var newChar = translate("newCharacter");
list.insert(0, new NewOption(newChar, newChar, function() {
openSubState(new UIWarningSubstate(translate("warnings.notImplemented-title"), translate("warnings.notImplemented-body"), [
{label: TU.translate("editor.ok"), color: 0xFFFF0000, onClick: function(t) {}}
]));
}));
return list;
}
var list = generateList(modsList, isMods);
main = new OptionsScreen(TU.translate("characterEditor.name"), translate("desc"), list);
+29 -16
View File
@@ -681,7 +681,8 @@ class Charter extends UIState {
}
for (group in [notesGroup, eventsGroup]) {
cast(group, FlxTypedGroup<Dynamic>).forEach(function(s) {
var group:FlxTypedGroup<Dynamic> = cast group;
group.forEach(function(s) {
s.selected = false;
if (gridActionType == NONE) {
if (s is CharterNote) {
@@ -746,21 +747,27 @@ class Charter extends UIState {
selectionBox.bHeight = Std.int(Math.abs(mousePos.y - dragStartPos.y));
} else {
if (FlxG.keys.pressed.SHIFT) {
for (group in [notesGroup, eventsGroup])
for(n in cast(group, FlxTypedGroup<Dynamic>))
for (group in [notesGroup, eventsGroup]) {
var group:FlxTypedGroup<Dynamic> = cast group;
for(n in group)
if (n.handleSelection(selectionBox) && selection.contains(n))
selection.remove(n);
}
} else if (FlxG.keys.pressed.CONTROL) {
for (group in [notesGroup, eventsGroup])
for(n in cast(group, FlxTypedGroup<Dynamic>))
for (group in [notesGroup, eventsGroup]) {
var group:FlxTypedGroup<Dynamic> = cast group;
for(n in group)
if (n.handleSelection(selectionBox) && !selection.contains(n))
selection.push(n);
}
} else {
selection = [];
for (group in [notesGroup, eventsGroup])
for(n in cast(group, FlxTypedGroup<Dynamic>))
for (group in [notesGroup, eventsGroup]) {
var group:FlxTypedGroup<Dynamic> = cast group;
for(n in group)
if (n.handleSelection(selectionBox))
selection.push(n);
}
}
selection = __fixSelection(selection);
@@ -816,8 +823,14 @@ class Charter extends UIState {
changePoint.put();
}
if (s is CharterNote) cast(s, CharterNote).snappedToStrumline = true;
if (s is UISprite) cast(s, UISprite).cursor = BUTTON;
if (s is CharterNote) {
var s:CharterNote = cast s;
s.snappedToStrumline = true;
}
if (s is UISprite) {
var s:UISprite = cast s;
s.cursor = BUTTON;
}
}
if (!(verticalChange == 0 && horizontalChange == 0)) {
notesGroup.sortNotes(); eventsGroup.sortEvents();
@@ -1022,9 +1035,9 @@ class Charter extends UIState {
if (selection.length <= 0) return [];
notesGroup.autoSort = false;
for (objects in [notesGroup, eventsGroup]) {
var group = cast(objects, FlxTypedGroup<Dynamic>);
var member = 0;
for (group in [notesGroup, eventsGroup]) {
var group:FlxTypedGroup<Dynamic> = cast group;
var member:Int = 0;
while(member < group.members.length) {
var s = group.members[member];
if (selection.contains(s))
@@ -1188,7 +1201,7 @@ class Charter extends UIState {
noteTypeText.x = noteTopButton.x + noteTopButton.bWidth + 6;
noteTypeText.y = Std.int((noteTopButton.bHeight - noteTypeText.height) / 2);
}
noteTypeText.text = '($noteType) ${noteTypes[noteType-1] == null ? TU.translate("noteTypes.default") : noteTypes[noteType-1]}';
noteTypeText.text = '($noteType) ' + (noteTypes[noteType-1] == null ? TU.translate("charter.noteTypes.default") : noteTypes[noteType-1]);
super.update(elapsed);
@@ -1384,7 +1397,7 @@ class Charter extends UIState {
var note:CharterNote = cast s;
CNote(note.step - minStep, note.id, note.strumLineID, note.susLength, note.type);
} else if (s is CharterEvent) {
var event = cast(s,CharterEvent);
var event:CharterEvent = cast s;
CEvent(event.step - minStep, [for (event in event.events) Reflect.copy(event)]);
}
];
@@ -1969,9 +1982,9 @@ typedef SelectionDragChange = {
public inline function loop(onNote:CharterNote->Void, ?onEvent:CharterEvent->Void, ?draggableOnly:Bool = true) {
for (s in this) {
if (s is CharterNote && onNote != null && (draggableOnly ? s.draggable: true))
onNote(cast(s, CharterNote));
onNote(cast s);
else if (s is CharterEvent && onEvent != null && (draggableOnly ? s.draggable: true))
onEvent(cast(s, CharterEvent));
onEvent(cast s);
}
}
}
@@ -63,7 +63,7 @@ class CharterEvent extends UISliceSprite implements ICharterSelectable {
generateDefaultIcon(event.name);
case "Camera Movement":
// custom icon for camera movement
var state = cast(FlxG.state, Charter);
var state:Charter = cast FlxG.state;
if (event.params != null && event.params[0] != null && event.params[0] >= 0 && event.params[0] < state.strumLines.length) {
// camera movement, use health icon
var icon = Character.getIconFromCharName(state.strumLines.members[event.params[0]].strumLine.characters[0]);
@@ -38,7 +38,7 @@ class CharterEventAdd extends UISliceSprite {
curCharterEvent = null;
this.step = step;
this.y = (step * 40) - (bHeight / 2);
text.text = TU.translate("editors.addEvent");
text.text = TU.translate("charter.addEvent");
framesOffset = 0;
x = -(bWidth = 37 + Math.ceil(text.width));
}
@@ -46,7 +46,7 @@ class CharterEventAdd extends UISliceSprite {
public function updateEdit(event:CharterEvent) {
curCharterEvent = event;
this.y = event.y;
text.text = TU.translate("editors.editEvent");
text.text = TU.translate("charter.editEvent");
framesOffset = 9;
x = -(bWidth = 27 + Math.ceil(text.width) + event.bWidth);
}
@@ -174,7 +174,11 @@ class CharterEventScreen extends UISubstateWindow {
colorWheel;
case TDropDown(options):
addLabel();
var dropdown = new UIDropDown(eventName.x, y, 320, 32, options, Std.int(Math.abs(options.indexOf(cast value))));
var optionIndex = options.indexOf(cast value);
if(optionIndex < 0) {
optionIndex = 0;
}
var dropdown = new UIDropDown(eventName.x, y, 320, 32, options, optionIndex);
paramsPanel.add(dropdown); paramsFields.push(dropdown);
dropdown;
case TCharacter:
@@ -33,7 +33,7 @@ class CharterNoteGroup extends FlxTypedGroup<CharterNote> {
noteFunc(__loopSprite);
}
for(c in Charter.selection.copy())
if (c != null && c is CharterNote) noteFunc(cast (c, CharterNote));
if (c != null && c is CharterNote) noteFunc(cast c);
__currentlyLooping = oldCur;
}
@@ -47,7 +47,7 @@ class CharterNoteHoverer extends CharterNote {
for (s in Charter.selection) {
if (s != null && s.draggable && s is CharterNote) {
var draggingNote:CharterNote = cast(s, CharterNote);
var draggingNote:CharterNote = cast s;
y = (draggingNote.step + verticalChange);
if (!FlxG.keys.pressed.SHIFT)
y -= ((draggingNote.step + verticalChange)
+4 -2
View File
@@ -55,8 +55,10 @@ class UIFileExplorer extends UISliceSprite {
if (uiElement != null) {
uiElement.alpha = alpha;
if (uiElement is UIButton)
cast(uiElement, UIButton).selectable = selectable;
if (uiElement is UIButton) {
var uiElement:UIButton = cast uiElement;
uiElement.selectable = selectable;
}
}
}
+14 -1
View File
@@ -1,5 +1,8 @@
package funkin.editors.ui;
import openfl.display.ShaderParameter;
import openfl.display.ShaderInput;
import openfl.filters.ShaderFilter;
import flixel.tweens.FlxTween;
import funkin.backend.shaders.CustomShader;
import openfl.filters.ShaderFilter;
@@ -7,7 +10,17 @@ import openfl.filters.ShaderFilter;
// TODO: make UIWarningSubstate extend this
class UISubstateWindow extends MusicBeatSubstate {
var camShaders:Array<FlxCamera> = [];
var blurShader:CustomShader = new CustomShader(Options.intensiveBlur ? "engine/editorBlur" : "engine/editorBlurFast");
var blurShader:CustomShader = {
var _ = new CustomShader(Options.intensiveBlur ? "engine/editorBlur" : "engine/editorBlurFast");
if(!Options.intensiveBlur) {
var noiseTexture:ShaderInput<openfl.display.BitmapData> = _.data.noiseTexture;
noiseTexture.input = Assets.getBitmapData("assets/shaders/noise256.png");
noiseTexture.wrap = REPEAT;
var noiseTextureSize:ShaderParameter<Float> = _.data.noiseTextureSize;
noiseTextureSize.value = [noiseTexture.input.width, noiseTexture.input.height];
}
_;
};
var titleSpr:UIText;
var messageSpr:UIText;
+6 -3
View File
@@ -21,9 +21,12 @@ class UITopMenu extends UISliceSprite {
public override function update(elapsed:Float) {
anyMenuOpened = false;
for(c in members) if (cast(c, UITopMenuButton).curMenu.contextMenuOpened()) {
anyMenuOpened = true;
break;
for(c in members) {
var c:UITopMenuButton = cast c;
if (c.curMenu.contextMenuOpened()) {
anyMenuOpened = true;
break;
}
}
super.update(elapsed);
+1 -1
View File
@@ -5,7 +5,7 @@ import funkin.editors.ui.UIContextMenu.UIContextMenuOption;
class UIUtil {
public static function follow(spr:FlxSprite, target:FlxSprite, x:Float = 0, y:Float = 0) {
spr.cameras = target is UISprite ? cast(target, UISprite).__lastDrawCameras : target.cameras;
spr.cameras = target is UISprite ? ({var _:UISprite = cast target;_;}).__lastDrawCameras : target.cameras;
spr.setPosition(target.x + x, target.y + y);
spr.scrollFactor.set(target.scrollFactor.x, target.scrollFactor.y);
}
+14 -1
View File
@@ -1,5 +1,8 @@
package funkin.editors.ui;
import openfl.display.ShaderParameter;
import openfl.display.ShaderInput;
import openfl.filters.ShaderFilter;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import funkin.backend.shaders.CustomShader;
@@ -7,7 +10,17 @@ import openfl.filters.ShaderFilter;
class UIWarningSubstate extends MusicBeatSubstate {
var camShaders:Array<FlxCamera> = [];
var blurShader:CustomShader = new CustomShader(Options.intensiveBlur ? "engine/editorBlur" : "engine/editorBlurFast");
var blurShader:CustomShader = {
var _ = new CustomShader(Options.intensiveBlur ? "engine/editorBlur" : "engine/editorBlurFast");
if(!Options.intensiveBlur) {
var noiseTexture:ShaderInput<openfl.display.BitmapData> = _.data.noiseTexture;
noiseTexture.input = Assets.getBitmapData("assets/shaders/noise256.png");
noiseTexture.wrap = REPEAT;
var noiseTextureSize:ShaderParameter<Float> = _.data.noiseTextureSize;
noiseTextureSize.value = [noiseTexture.input.width, noiseTexture.input.height];
}
_;
};
var title:String;
var message:String;
+85 -25
View File
@@ -8,6 +8,9 @@ import flixel.util.FlxColor;
import funkin.backend.FunkinSprite;
import funkin.backend.scripting.DummyScript;
import funkin.backend.scripting.Script;
import funkin.backend.scripting.ScriptPack;
import funkin.backend.scripting.events.CharacterNodeEvent;
import funkin.backend.scripting.events.CharacterXMLEvent;
import funkin.backend.scripting.events.DanceEvent;
import funkin.backend.scripting.events.DirectionAnimEvent;
import funkin.backend.scripting.events.PlayAnimContext;
@@ -44,8 +47,13 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
public var cameraOffset:FlxPoint = FlxPoint.get(0, 0);
public var globalOffset:FlxPoint = FlxPoint.get(0, 0);
public var script:Script;
public var xml:Access;
public var scripts:ScriptPack;
public var xmlImportedScripts:Array<XMLImportedScriptInfo> = [];
public var script(default, set):Script;
public function prepareInfos(node:Access)
return XMLImportedScriptInfo.prepareInfos(node, scripts, (infos) -> xmlImportedScripts.push(infos));
public var idleSuffix:String = "";
public var stunned(default, set):Bool = false;
@@ -72,16 +80,15 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
script = Script.create(Paths.script(Path.withoutExtension(Paths.xml('characters/$curCharacter')), null, true));
else
script = new DummyScript(curCharacter);
script.setParent(this);
script.load();
buildCharacter(xml);
script.call("create");
scripts.call("create");
if (script == null)
script = new DummyScript(curCharacter);
script.call("postCreate");
scripts.call("postCreate");
}
@:noCompletion var __swappedLeftRightAnims:Bool = false;
@@ -118,7 +125,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
override function update(elapsed:Float) {
super.update(elapsed);
script.call("update", [elapsed]);
scripts.call("update", [elapsed]);
if (stunned) {
__stunnedTime += elapsed;
if (__stunnedTime > 5 / 60)
@@ -137,7 +144,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
if(debugMode) return;
var event = EventManager.get(DanceEvent).recycle(danced);
script.call("onDance", [event]);
scripts.call("onDance", [event]);
if (event.cancelled) return;
if (isDanceLeftDanceRight)
@@ -167,14 +174,14 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
*/
public var danceOnBeat:Bool = true;
public override function beatHit(curBeat:Int) {
script.call("beatHit", [curBeat]);
scripts.call("beatHit", [curBeat]);
if (danceOnBeat && (curBeat + beatOffset) % beatInterval == 0 && !__lockAnimThisFrame)
tryDance();
}
public override function stepHit(curStep:Int)
script.call("stepHit", [curStep]);
scripts.call("stepHit", [curStep]);
@:noCompletion var __reverseDrawProcedure:Bool = false;
public override function getScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect {
@@ -237,7 +244,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
public override function playAnim(AnimName:String, ?Force:Bool, Context:PlayAnimContext = NONE, Reversed:Bool = false, Frame:Int = 0) {
var event = EventManager.get(PlayAnimEvent).recycle(AnimName, Force, Reversed, Frame, Context);
script.call("onPlayAnim", [event]);
scripts.call("onPlayAnim", [event]);
if (event.cancelled) return;
super.playAnim(event.animName, event.force, event.context, event.reverse, event.startingFrame);
@@ -252,16 +259,16 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
var event = EventManager.get(PointEvent).recycle(
midpoint.x + (isPlayer ? -100 : 150) + globalOffset.x + cameraOffset.x,
midpoint.y - 100 + globalOffset.y + cameraOffset.y);
script.call("onGetCamPos", [event]);
scripts.call("onGetCamPos", [event]);
midpoint.put();
return new FlxPoint(event.x, event.y);
}
public override function destroy() {
if(script != null) {
script.call('destroy');
script.destroy();
if(scripts != null) {
scripts.call('destroy');
scripts.destroy();
}
super.destroy();
@@ -304,9 +311,18 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
}
public inline function buildCharacter(xml:Access) {
this.xml = xml; // Modders wassup :D
for(node in xml.elements)
switch(node.name) {
case "use-extension" | "extension" | "ext":
if (!XMLImportedScriptInfo.shouldLoadBefore(node)) continue;
prepareInfos(node);
}
xml = scripts.event("onCharacterXMLParsed", EventManager.get(CharacterXMLEvent).recycle(this, xml)).xml;
sprite = curCharacter;
spriteAnimType = BEAT;
this.xml = xml; // Modders wassup :D
if (xml.x.exists("isPlayer")) playerOffsets = (xml.x.get("isPlayer") == "true");
if (xml.x.exists("x")) globalOffset.x = Std.parseFloat(xml.x.get("x"));
@@ -314,7 +330,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
if (xml.x.exists("gameOverChar")) gameOverCharacter = xml.x.get("gameOverChar");
if (xml.x.exists("camx")) cameraOffset.x = Std.parseFloat(xml.x.get("camx"));
if (xml.x.exists("camy")) cameraOffset.y = Std.parseFloat(xml.x.get("camy"));
if (xml.x.exists("holdTime")) holdTime = CoolUtil.getDefault(Std.parseFloat(xml.x.get("holdTime")), 4);
if (xml.x.exists("holdTime")) holdTime = Std.parseFloat(xml.x.get("holdTime")).getDefaultFloat(4);
if (xml.x.exists("flipX")) flipX = (xml.x.get("flipX") == "true");
if (xml.x.exists("icon")) icon = xml.x.get("icon");
if (xml.x.exists("color")) iconColor = FlxColor.fromString(xml.x.get("color"));
@@ -330,9 +346,19 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
if (hasInterval) beatInterval = Std.parseInt(xml.x.get("interval"));
loadSprite(Paths.image('characters/$sprite'));
for(node in xml.elements) {
switch(node.name) {
case "anim":
XMLUtil.addXMLAnimation(this, node);
case "use-extension" | "extension" | "ext":
if (XMLImportedScriptInfo.shouldLoadBefore(node)) continue;
prepareInfos(node);
default:
// nothing
}
for (anim in xml.nodes.anim)
XMLUtil.addXMLAnimation(this, anim);
scripts.event("onCharacterNodeParsed", EventManager.get(CharacterNodeEvent).recycle(this, node, node.name));
}
for (attribute in xml.x.attributes())
if (!characterProperties.contains(attribute))
@@ -340,6 +366,14 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
fixChar(__switchAnims, !hasInterval);
dance();
for (info in xmlImportedScripts) if (info.shortLived) {
var script = info.getScript();
if (script == null) continue;
scripts.remove(script);
script.destroy();
}
}
public static var characterProperties:Array<String> = [
@@ -423,6 +457,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
return stunned = b;
}
// ---- Backwards compat ----
// Interval at which the character will dance (higher number = slower dance)
@:noCompletion public var danceInterval(get, set):Int;
@:noCompletion private function set_danceInterval(v:Int)
@@ -430,13 +465,29 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
@:noCompletion private function get_danceInterval()
return beatInterval;
private function set_script(script:Script):Script {
if (scripts == null) (scripts = new ScriptPack("Character")).setParent(this);
var lastIndex = scripts.scripts.indexOf(this.script);
if(lastIndex >= 0) {
if(script == null) // last != null && new == null
scripts.scripts.splice(lastIndex, 1);
else // last != null && new != null
scripts.scripts[lastIndex] = script;
} else if(script != null) // last == null
scripts.insert(0, script);
return this.script = script;
}
// ---- end of Backwards compat ----
public static var FALLBACK_CHARACTER:String = "bf";
public static var FALLBACK_DEAD_CHARACTER:String = "bf-dead";
public static function getXMLFromCharName(character:OneOfTwo<String, Character>):Access {
var char:Character = null;
if (character is Character) {
char = cast(character, Character);
char = cast character;
character = char.curCharacter;
}
@@ -468,9 +519,10 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
return xml;
}
public static function getIconFromCharName(?character:String) {
public static function getIconFromCharName(?character:String, ?defaultIcon:String = null) {
if(character == null) return "face";
var icon:String = character;
if(defaultIcon == null) defaultIcon = character;
var icon:String = defaultIcon;
var xml:Access = getXMLFromCharName(character);
if (xml != null && xml.x.exists("icon")) icon = xml.x.get("icon");
@@ -478,9 +530,17 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
return icon;
}
public static function getList(?mods:Bool = false):Array<String>
return [
for (path in Paths.getFolderContent('data/characters/', true, mods ? MODS : BOTH))
if (Path.extension(path) == "xml") CoolUtil.getFilename(path)
];
public static function getList(?mods:Bool = false, includeFolders:Bool = false, folder:String = 'data/characters/'):Array<String> {
var list:Array<String> = [];
if(includeFolders) {
for (path in Paths.getFolderDirectories(folder, true, mods ? MODS : BOTH)) {
if(!path.endsWith("/")) path += "/";
list.push(path);
}
}
for (path in Paths.getFolderContent(folder, true, mods ? MODS : BOTH))
if (Path.extension(path) == "xml")
list.push(CoolUtil.getFilename(path));
return list;
}
}
+3 -5
View File
@@ -90,11 +90,9 @@ class HealthIcon extends FlxSprite
if (animation.curAnim != null) {
var i:Int = -1;
var oldKey:Int = -1;
for(k=>icon in healthSteps) {
if (k > oldKey && k < health * 100) {
oldKey = k;
i = icon;
}
for (k=>icon in healthSteps) if (k > oldKey && k <= health * 100) {
oldKey = k;
i = icon;
}
if (i >= 0 && curAnimState != i) {
var event = EventManager.get(funkin.backend.scripting.events.HealthIconChangeEvent).recycle(i, this);
+1 -1
View File
@@ -213,7 +213,7 @@ class Note extends FlxSprite
public var strumRelativePos:Bool = true;
override function drawComplex(camera:FlxCamera) {
var downscrollCam = (camera is HudCamera ? cast(camera, HudCamera).downscroll : false);
var downscrollCam = (camera is HudCamera ? ({var _:HudCamera=cast camera;_;}).downscroll : false);
flipY = (isSustainNote && flipSustain) && (downscrollCam != (__strum != null && __strum.getScrollSpeed(this) < 0));
if (downscrollCam) {
frameOffset.y += __notePosFrameOffset.y * 2;
+23 -8
View File
@@ -160,6 +160,11 @@ class PlayState extends MusicBeatState
* Boyfriend character
*/
public var boyfriend(get, set):Character;
/**
* Boyfriend character
* Same as boyfriend, just shorter
**/
public var bf(get, set):Character;
/**
* Strum line position
@@ -868,12 +873,12 @@ class PlayState extends MusicBeatState
Conductor.songPosition = 0;
Conductor.songPosition -= Conductor.crochet * introLength - Conductor.songOffset;
var swagCounter:Int = 0;
startTimer = new FlxTimer().start(Conductor.crochet / 1000, function(tmr:FlxTimer)
{
countdown(swagCounter++);
}, introLength);
if(introLength > 0) {
var swagCounter:Int = 0;
startTimer = new FlxTimer().start(Conductor.crochet / 1000, (tmr:FlxTimer) -> {
countdown(swagCounter++);
}, introLength);
}
scripts.call("onPostStartCountdown");
}
@@ -1050,7 +1055,7 @@ class PlayState extends MusicBeatState
vocals.pause();
}
if (!startTimer.finished)
if (startTimer != null && !startTimer.finished)
startTimer.active = false;
}
@@ -1070,7 +1075,7 @@ class PlayState extends MusicBeatState
resyncVocals();
}
if (!startTimer.finished)
if (startTimer != null && !startTimer.finished)
startTimer.active = true;
paused = false;
@@ -1858,6 +1863,16 @@ class PlayState extends MusicBeatState
strumLines.members[1].characters = [bf];
return bf;
}
private function set_bf(bf:Character):Character {
if (strumLines != null && strumLines.members[1] != null)
strumLines.members[1].characters = [bf];
return bf;
}
private function get_bf():Character {
if (strumLines != null && strumLines.members[1] != null)
return strumLines.members[1].characters[0];
return null;
}
private function get_dad():Character {
if (strumLines != null && strumLines.members[0] != null)
return strumLines.members[0].characters[0];
+9 -47
View File
@@ -2,6 +2,9 @@ package funkin.game;
import flixel.FlxState;
import flixel.math.FlxPoint;
import haxe.xml.Access;
import funkin.backend.utils.XMLUtil.XMLImportedScriptInfo;
import funkin.backend.system.interfaces.IBeatReceiver;
import funkin.backend.scripting.DummyScript;
import funkin.backend.scripting.Script;
import funkin.backend.scripting.events.StageNodeEvent;
@@ -30,6 +33,9 @@ class Stage extends FlxBasic implements IBeatReceiver {
public function setStagesSprites(script:Script)
for (k=>e in stageSprites) script.set(k, e);
public function prepareInfos(node:Access)
return XMLImportedScriptInfo.prepareInfos(node, PlayState.instance.scripts, (infos) -> xmlImportedScripts.push(infos));
public function new(stage:String, ?state:FlxState) {
super();
@@ -136,7 +142,7 @@ class Stage extends FlxBasic implements IBeatReceiver {
PlayState.instance.add(PlayState.instance.comboGroup);
PlayState.instance.comboGroup;
case "use-extension" | "extension" | "ext":
if (__shouldLoadBefore(node) || XMLImportedScriptInfo.prepareInfos(node, this) == null) continue;
if (XMLImportedScriptInfo.shouldLoadBefore(node) || prepareInfos(node) == null) continue;
null;
default: null;
}
@@ -201,13 +207,10 @@ class Stage extends FlxBasic implements IBeatReceiver {
@:dox(hide) private function __pushNcheckNode(array:Array<Access>, node:Access) {
array.push(node);
if ((node.name == "use-extension" || node.name == "extension" || node.name == "ext") && __shouldLoadBefore(node))
XMLImportedScriptInfo.prepareInfos(node, this);
if ((node.name == "use-extension" || node.name == "extension" || node.name == "ext") && XMLImportedScriptInfo.shouldLoadBefore(node))
prepareInfos(node);
}
@:dox(hide) private static inline function __shouldLoadBefore(node:Access):Bool
return node.getAtt("loadBefore") != "false";
public function addCharPos(name:String, node:Access, ?nonXMLInfo:StageCharPosInfo):StageCharPos {
var charPos = new StageCharPos();
charPos.visible = charPos.active = false;
@@ -317,45 +320,4 @@ typedef StageCharPosInfo = {
var y:Float;
var flip:Bool;
var scroll:Float;
}
class XMLImportedScriptInfo {
public var path:String;
public var shortLived:Bool = false;
public var loadBefore:Bool = true;
public var importStageSprites:Bool = false;
public function new(path:String)
this.path = path;
public function getScript():Script
return PlayState.instance == null ? null : PlayState.instance.scripts.getByPath(path);
public static function prepareInfos(node:Access, ?stage:Stage):XMLImportedScriptInfo {
if (!node.has.script || PlayState.instance == null) return null;
var folder = node.getAtt("folder").getDefault("data/scripts/");
if (!folder.endsWith("/")) folder += "/";
var path = Paths.script(folder + node.getAtt("script"));
var daScript = Script.create(path);
if (daScript is DummyScript) {
var msg = 'Script Extension at ${path} does not exist';
if (stage != null) msg += ' through stage "${stage.stageName}"';
Logs.trace(msg + ".", ERROR);
return null;
}
var infos = new XMLImportedScriptInfo(daScript.path);
infos.shortLived = node.getAtt("isShortLived") == "true";
infos.importStageSprites = node.getAtt("importStageSprites") == "true";
@:privateAccess infos.loadBefore = Stage.__shouldLoadBefore(node);
if (stage != null) stage.xmlImportedScripts.push(infos);
PlayState.instance.scripts.add(daScript);
daScript.set("scriptInfo", infos);
daScript.load();
return infos;
}
}
+1 -1
View File
@@ -318,7 +318,7 @@ class StrumLine extends FlxTypedGroup<Strum> {
babyArrow.scrollSpeed = data.scrollSpeed;
var event = EventManager.get(StrumCreationEvent).recycle(babyArrow, PlayState.instance.strumLines.members.indexOf(this), i, animPrefix);
event.__doAnimation = !MusicBeatState.skipTransIn;
event.__doAnimation = !MusicBeatState.skipTransIn && (PlayState.instance != null ? PlayState.instance.introLength > 0 : true);
event = PlayState.instance.scripts.event("onStrumCreation", event);
if (!event.cancelled) {
@@ -91,7 +91,7 @@ class DialogueCutscene extends Cutscene {
musicVolume: node.has.musicVolume ? (volume = Std.parseFloat(node.att.speed).getDefaultFloat(0.8)) : null,
changeMusic: node.has.changeMusic ? FlxG.sound.load(Paths.music(node.att.changeMusic), volume, true) : null,
playSound: node.has.playSound ? FlxG.sound.load(Paths.sound(node.att.playSound)) : null,
nextSound: node.has.nextSound ? FlxG.sound.load(Paths.music(node.att.nextSound)) : null,
nextSound: node.has.nextSound ? FlxG.sound.load(Paths.sound(node.att.nextSound)) : null,
textSound: null
};
@@ -217,4 +217,4 @@ typedef DialogueLine = {
var nextSound:FlxSound;
var textSound:FlxSound;
var changeDefAnim:String;
}
}
+2 -2
View File
@@ -13,13 +13,13 @@ class BetaWarningState extends MusicBeatState {
public override function create() {
super.create();
titleAlphabet = new Alphabet(0, 0, TU.translate("betaWarning.title"), true);
titleAlphabet = new Alphabet(0, 0, TU.translate("betaWarning.title"), "bold");
titleAlphabet.screenCenter(X);
add(titleAlphabet);
disclaimer = new FunkinText(16, titleAlphabet.y + titleAlphabet.height + 10, FlxG.width - 32, "", 32);
disclaimer.alignment = CENTER;
disclaimer.applyMarkup(TU.translate("betaWarning.desc", [Main.releaseCycle, "ENTER"]),
disclaimer.applyMarkup(TU.translate("betaWarning.desc", [Main.releaseCycle]) + "\n\n" + TU.translate("betaWarning.proceed", ["ENTER"]),
[
new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFFF4444), "*")
]
+1 -1
View File
@@ -130,7 +130,7 @@ class FreeplayState extends MusicBeatState
for (i in 0...songs.length)
{
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, songs[i].displayName, true, false);
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, songs[i].displayName, "bold");
songText.isMenuItem = true;
songText.targetY = i;
grpSongs.add(songText);
+1 -1
View File
@@ -163,7 +163,7 @@ class MainMenuState extends MusicBeatState
var event = event("onSelectItem", EventManager.get(NameEvent).recycle(daChoice));
if (event.cancelled) return;
switch (daChoice)
switch (event.name)
{
case 'story mode': FlxG.switchState(new StoryMenuState());
case 'freeplay': FlxG.switchState(new FreeplayState());
+1 -1
View File
@@ -28,7 +28,7 @@ class ModSwitchMenu extends MusicBeatSubstate {
alphabets = new FlxTypedGroup<Alphabet>();
for(mod in mods) {
var a = new Alphabet(0, 0, mod == null ? TU.translate("mods.disableMods") : mod, true);
var a = new Alphabet(0, 0, mod == null ? TU.translate("mods.disableMods") : mod, "bold");
if(mod == ModsFolder.currentModFolder)
a.color = FlxColor.LIME;
a.isMenuItem = true;
+5 -3
View File
@@ -14,6 +14,7 @@ import funkin.editors.charter.Charter;
import funkin.menus.StoryMenuState;
import funkin.options.OptionsMenu;
import funkin.options.keybinds.KeybindsOptions;
import funkin.options.TreeMenu;
class PauseSubState extends MusicBeatSubstate
{
@@ -107,7 +108,7 @@ class PauseSubState extends MusicBeatSubstate
for (i in 0...menuItems.length)
{
var pauseId = "pause." + TU.raw2Id(menuItems[i]);
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, TU.translate(pauseId), true, false);
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, TU.translate(pauseId), "bold");
songText.isMenuItem = true;
songText.targetY = i;
grpMenuShit.add(songText);
@@ -167,9 +168,10 @@ class PauseSubState extends MusicBeatSubstate
persistentDraw = false;
openSubState(new KeybindsOptions());
case "Change Options":
TreeMenu.lastState = PlayState;
FlxG.switchState(new OptionsMenu());
case "Exit to charter":
FlxG.switchState(new funkin.editors.charter.Charter(PlayState.SONG.meta.name, PlayState.difficulty, false));
FlxG.switchState(new Charter(PlayState.SONG.meta.name, PlayState.difficulty, false));
case "Exit to menu":
if (PlayState.chartingMode && Charter.undos.unsaved)
game.saveWarn(false);
@@ -217,4 +219,4 @@ class PauseSubState extends MusicBeatSubstate
item.alpha = (item.targetY == 0) ? 1 : 0.6;
}
}
}
}
@@ -40,7 +40,7 @@ class PlaytestingWarningSubstate extends MusicBeatSubstate
bg.scrollFactor.set();
add(bg);
titleAlphabet = new Alphabet(0, 140, TU.translate("playtesting.warningTitle"), true);
titleAlphabet = new Alphabet(0, 140, TU.translate("playtesting.warningTitle"), "bold");
titleAlphabet.screenCenter(X);
add(titleAlphabet);
+9 -2
View File
@@ -114,6 +114,12 @@ class StoryMenuState extends MusicBeatState {
}
}
// default difficulty should be the middle difficulty in the array
// to be consistent with base game and whatnot, you know the drill
curDifficulty = Math.floor(weeks[0].difficulties.length * 0.5);
// debug stuff lol
Logs.trace('Middle Difficulty for Week 1 is ${weeks[0].difficulties[curDifficulty]} (ID: $curDifficulty)');
changeWeek(0, true);
DiscordUtil.call("onMenuLoaded", ["Story Menu"]);
@@ -163,6 +169,7 @@ class StoryMenuState extends MusicBeatState {
if (!force) CoolUtil.playMenuSFX();
for(k=>e in weekSprites.members) {
e.targetY = k - curWeek;
e.alpha = k == curWeek ? 1.0 : 0.6;
}
var str = new StringBuf();
str.add(TU.translate("story.tracks") + "\n\n");
@@ -354,13 +361,13 @@ class StoryMenuState extends MusicBeatState {
if (char.animation.exists("confirm"))
char.animation.play("confirm");
PlayState.loadWeek(weeks[curWeek], weeks[curWeek].difficulties[curDifficulty]);
PlayState.loadWeek(event.week, event.difficulty);
new FlxTimer().start(1, function(tmr:FlxTimer)
{
FlxG.switchState(new PlayState());
});
weekSprites.members[curWeek].startFlashing();
weekSprites.members[event.weekID].startFlashing();
}
}
+23 -61
View File
@@ -25,8 +25,6 @@ class TitleState extends MusicBeatState
public var textGroup:FlxGroup;
public var ngSpr:FlxSprite;
public var wackyImage:FlxSprite;
override public function create():Void
{
curWacky = FlxG.random.getObject(getIntroTextShit());
@@ -40,9 +38,6 @@ class TitleState extends MusicBeatState
DiscordUtil.call("onMenuLoaded", ["Title Screen"]);
}
var logoBl:FlxSprite;
var gfDance:FlxSprite;
var danceLeft:Bool = false;
var titleText:FlxSprite;
var titleScreenSprites:MusicBeatGroup;
@@ -56,11 +51,9 @@ class TitleState extends MusicBeatState
var bg:FlxSprite = new FlxSprite().makeSolid(FlxG.width, FlxG.height, FlxColor.BLACK);
add(bg);
#if TITLESCREEN_XML
titleScreenSprites = new MusicBeatGroup();
add(titleScreenSprites);
loadXML();
#end
if (titleText == null) {
titleText = new FlxSprite(100, FlxG.height * 0.8);
@@ -78,16 +71,6 @@ class TitleState extends MusicBeatState
blackScreen = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
add(blackScreen);
#if !TITLESCREEN_XML
ngSpr = new FlxSprite(0, FlxG.height * 0.52).loadAnimatedGraphic(Paths.image('newgrounds_logo'));
add(ngSpr);
ngSpr.visible = false;
ngSpr.setGraphicSize(Std.int(ngSpr.width * 0.8));
ngSpr.updateHitbox();
ngSpr.screenCenter(X);
ngSpr.antialiasing = true;
#end
FlxG.mouse.visible = false;
if (initialized)
@@ -192,7 +175,7 @@ class TitleState extends MusicBeatState
for (i=>text in textArray)
{
if (text == "" || text == null) continue;
var money:Alphabet = new Alphabet(0, (i * 60) + 200, text, true, false);
var money:Alphabet = new Alphabet(0, (i * 60) + 200, text, "bold");
money.screenCenter(X);
textGroup.add(money);
}
@@ -200,7 +183,7 @@ class TitleState extends MusicBeatState
public function addMoreText(text:String)
{
var coolText:Alphabet = new Alphabet(0, (textGroup.length * 60) + 200, text, true, false);
var coolText:Alphabet = new Alphabet(0, (textGroup.length * 60) + 200, text, "bold");
coolText.screenCenter(X);
textGroup.add(coolText);
}
@@ -217,7 +200,6 @@ class TitleState extends MusicBeatState
{
super.beatHit(curBeat);
#if TITLESCREEN_XML
if (curBeat >= titleLength || skippedIntro) {
if (!skippedIntro) skipIntro();
return;
@@ -225,27 +207,8 @@ class TitleState extends MusicBeatState
var introText = titleLines[curBeat];
if (introText != null)
introText.show();
#else
switch (curBeat)
{
case 1: createCoolText(['ninjamuffin99', 'phantomArcade', 'kawaisprite', 'evilsk8er']);
case 3: addMoreText('present');
case 4: deleteCoolText();
case 5: createCoolText(['In association', 'with']);
case 7: addMoreText('newgrounds'); ngSpr.visible = true;
case 8: deleteCoolText(); ngSpr.visible = false;
case 9: createCoolText([curWacky[0]]);
case 11: addMoreText(curWacky[1]);
case 12: deleteCoolText();
case 13: addMoreText('Friday');
case 14: addMoreText('Night');
case 15: addMoreText('Funkin');
case 16: skipIntro();
}
#end
}
#if TITLESCREEN_XML
public var xml:Access;
public var titleLength:Int = 16;
public var titleLines:Map<Int, IntroText> = [
@@ -267,12 +230,14 @@ class TitleState extends MusicBeatState
15 => new IntroText(['Friday', 'Night', "Funkin'"]),
];
public var titleSprites:Map<String, FlxSprite> = [];
public function loadXML() {
try {
xml = new Access(Xml.parse(Assets.getText(Paths.xml('titlescreen/titlescreen'))).firstElement());
if (xml.hasNode.intro) {
titleLines = [];
if (xml.node.intro.has.length) titleLength = CoolUtil.getDefault(Std.parseInt(xml.node.intro.att.length), 16);
if (xml.node.intro.has.length) titleLength = Std.parseInt(xml.node.intro.att.length).getDefault(16);
for(node in xml.nodes.sprites) {
var parentFolder:String = node.getAtt("folder").getDefault("");
if (parentFolder != "" && !parentFolder.endsWith("/")) parentFolder += "/";
@@ -284,26 +249,28 @@ class TitleState extends MusicBeatState
default:
titleScreenSprites.add(spr);
}
if(node.has.name) titleSprites[node.att.name] = spr;
}
}
for(text in xml.node.intro.nodes.text) {
var beat:Int = CoolUtil.getDefault(text.has.beat ? Std.parseInt(text.att.beat) : null, 0);
var beat:Int = text.has.beat ? Std.parseInt(text.att.beat).getDefault(0) : 0;
var texts:Array<OneOfTwo<String, TitleStateImage>> = [];
for(e in text.elements) {
switch(e.name) {
for(node in text.elements) {
switch(node.name) {
case "line":
if (!e.has.text) continue;
texts.push(e.att.text);
if (!node.has.text) continue;
texts.push(node.att.text);
case "introtext":
if (!e.has.line) continue;
texts.push('{introText${e.att.line}}');
if (!node.has.line) continue;
texts.push('{introText${node.att.line}}');
case "sprite":
if (!e.has.path) continue;
var name:String = e.has.name ? e.att.name : null;
var path:String = e.att.path;
var flipX:Bool = e.has.flipX ? e.att.flipX == "true" : false;
var flipY:Bool = e.has.flipY ? e.att.flipY == "true" : false;
var scale:Float = e.has.scale ? CoolUtil.getDefault(Std.parseFloat(e.att.scale), 1) : 1;
if (!node.has.path) continue;
var name:String = node.has.name ? node.att.name : null;
var path:String = node.att.path;
var flipX:Bool = node.has.flipX ? node.att.flipX == "true" : false;
var flipY:Bool = node.has.flipY ? node.att.flipY == "true" : false;
var scale:Float = node.has.scale ? Std.parseFloat(node.att.scale).getDefault(1) : 1;
texts.push({
name: name,
path: path,
@@ -320,7 +287,6 @@ class TitleState extends MusicBeatState
Logs.error('Failed to load titlescreen XML: $e');
}
}
#end
var skippedIntro:Bool = false;
@@ -328,10 +294,6 @@ class TitleState extends MusicBeatState
{
if (!skippedIntro)
{
#if !TITLESCREEN_XML
remove(ngSpr);
#end
FlxG.camera.flash(FlxColor.WHITE, 4);
remove(blackScreen);
blackScreen.destroy();
@@ -361,7 +323,7 @@ class IntroText {
var image:TitleStateImage = e;
if (image.path == null) continue;
var scale:Float = CoolUtil.getDefault(image.scale, 1);
var scale:Float = image.scale.getDefault(1);
var yPos:Float = 200;
if(state.textGroup.members.length > 0) {
@@ -370,8 +332,8 @@ class IntroText {
}
var sprite = new FlxSprite(0, yPos).loadAnimatedGraphic(Paths.image(image.path));
sprite.flipX = CoolUtil.getDefault(image.flipX, false);
sprite.flipY = CoolUtil.getDefault(image.flipY, false);
sprite.flipX = image.flipX.getDefault(false);
sprite.flipY = image.flipY.getDefault(false);
sprite.scale.set(scale, scale);
sprite.updateHitbox();
sprite.screenCenter(X);
@@ -11,9 +11,11 @@ using StringTools;
class CreditsCodename extends funkin.options.OptionsScreen {
public var error:Bool = false;
public var author:String = "FNF-CNE-Devs";
public var totalContributions:Int = 0;
public var mainDevCol:FlxColor = 0xFF9C35D5;
public var minContrCol:FlxColor = 0xFFB4A7DA;
public var totalContributions:Int = 0;
public var contribFormats:Array<FlxTextFormatMarkerPair> = [];
public override function new()
{
@@ -58,12 +60,17 @@ class CreditsCodename extends funkin.options.OptionsScreen {
if(parent == null || parent.treeParent == null) return;
var text:String = parent.treeParent.pathDesc.text;
parent.treeParent.pathDesc.text = "";
parent.treeParent.pathDesc.applyMarkup(text, [
parent.treeParent.pathDesc.applyMarkup(text, contribFormats = [
new FlxTextFormatMarkerPair(new FlxTextFormat(mainDevCol), '*'),
new FlxTextFormatMarkerPair(new FlxTextFormat(FlxColor.interpolate(minContrCol, mainDevCol, Options.contributors[curSelected].contributions / totalContributions)), '~')
]);
}
override function close() {
super.close();
for (frmt in contribFormats) parent.treeParent.pathDesc.removeFormat(frmt.format);
}
public function checkUpdate():Bool {
var curTime:Float = Date.now().getTime();
if(Options.lastUpdated != null && curTime < Options.lastUpdated + 120000) return false; // Fuck you Github rate limits - Nex
+607 -243
View File
@@ -1,284 +1,648 @@
package funkin.menus.ui;
import flixel.group.FlxSpriteGroup;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import funkin.backend.assets.AssetsLibraryList;
import funkin.backend.assets.IModsAssetLibrary;
import funkin.backend.assets.LimeLibrarySymbol;
import flixel.util.typeLimit.OneOfTwo;
import haxe.ds.Vector;
import funkin.menus.ui.effects.RegionEffect;
import flixel.animation.FlxAnimation;
import flixel.util.FlxDirectionFlags;
import flixel.math.FlxPoint;
import flixel.math.FlxAngle;
import flixel.FlxTypes;
import haxe.xml.Access;
import openfl.utils.AssetLibrary;
using StringTools;
using flixel.util.FlxColorTransformUtil;
/**
* Loosely based on FlxTypeText lolol
*/
class Alphabet extends FlxSpriteGroup
{
public var delay:Float = 0.05;
public var paused:Bool = false;
@:structInit
final class AlphabetComponent {
public var anim:String;
public var x:Float;
public var y:Float;
// Precalculated values for angle
public var shouldRotate:Bool;
public var sin:Float;
public var cos:Float;
public var scaleX:Float;
public var scaleY:Float;
public var hasColorMode:Bool;
public var colorMode:ColorMode;
}
@:structInit
final class AlphabetLetterData {
@:optional public var isDefault:Bool = false;
public var advance:Float;
public var advanceEmpty:Bool;
public var components:Array<AlphabetComponent>;
}
enum abstract AlphabetAlignment(ByteUInt) from ByteUInt to ByteUInt {
var LEFT;
var CENTER;
var RIGHT;
public function getMultiplier():Float {
return switch(this) {
case CENTER: 0.5;
case RIGHT: 1.0;
default: 0.0;
}
}
@:from
public static function fromString(value:String):AlphabetAlignment
return switch(value) {
case "left": LEFT;
case "center": CENTER;
case "right": RIGHT;
default: LEFT;
}
}
enum abstract CaseMode(ByteUInt) from ByteUInt to ByteUInt {
var NONE;
var UPPER;
var LOWER;
@:from
public static function fromString(value:String):CaseMode
return switch(value) {
case "none": NONE;
case "upper": UPPER;
case "lower": LOWER;
default: NONE;
}
}
enum abstract ColorMode(ByteInt) from ByteInt to ByteInt {
var TINT = 0;
var OFFSET = 1;
var NONE = 2;
public function setColorTransform(color:openfl.geom.ColorTransform, red:Float, green:Float, blue:Float, alpha:Float) {
var moduloWorkaround:Int = this;
var tintMult = Math.max(-moduloWorkaround + 1, 0);
var tintOffset = Math.min(moduloWorkaround, 1);
var offsetMult = (moduloWorkaround % 2) * 255;
color.redMultiplier = red * tintMult + tintOffset;
color.greenMultiplier = green * tintMult + tintOffset;
color.blueMultiplier = blue * tintMult + tintOffset;
color.redOffset = red * offsetMult;
color.greenOffset = green * offsetMult;
color.blueOffset = blue * offsetMult;
color.alphaMultiplier = alpha;
}
}
class Alphabet extends FlxSprite {
public var effects:Array<RegionEffect> = [];
var __renderData:AlphabetRenderData;
var __component:AlphabetComponent;
public var text(default, set):String = "";
@:isVar public var textWidth(get, set):Float;
public var textHeight(get, null):Float;
public var alignment:AlphabetAlignment = LEFT;
public var forceCase:CaseMode = NONE;
var __laneWidths:Array<Float> = []; // TODO: add alignment.
var __forceWidth:Float = 0.0; // TODO: implement functionality for this.
var __queueResize:Bool = false;
var __animTime:Float = 0.0;
var __ogForceScreen:Bool = false;
public var originOffset:FlxPoint = FlxPoint.get();
public var font(default, set):String;
var colorMode:ColorMode = TINT;
var defaultAdvance:Float = 40.0;
var lineGap:Float = 75.0;
var fps:Float = 24.0;
var letterData:Map<String, AlphabetLetterData> = [];
var defaults:Vector<AlphabetLetterData> = {
var v = new Vector(3);
v[0] = null;
v[1] = null;
v[2] = null;
v;
};
var loaded:Vector<Array<String>> = {
var v = new Vector(3);
v[0] = [];
v[1] = [];
v[2] = [];
v;
};
var failedLetters:Array<String> = [];
// for menu shit
public var targetY:Float = 0;
public var isMenuItem:Bool = false;
public var text:String = "";
var _finalText:String = "";
var _curText:String = "";
var yMulti:Float = 1;
// custom shit
// amp, backslash, question mark, apostrophy, comma, angry faic, period
var lastSprite:AlphaCharacter;
var xPosResetted:Bool = false;
var splitWords:Array<String> = [];
var isBold:Bool = false;
private override function set_color(c:Int):Int {
for(e in group.members) {
if (e is AlphaCharacter) {
var char = cast(e, AlphaCharacter);
char.setColor(c, isBold);
}
}
return super.set_color(c);
}
// TODO: fix this shit refreshing
public function refreshAlphabetXML(path:String) {
AlphaCharacter.__alphaPath = Paths.getAssetsRoot() + path;
try {
var xml = new Access(Xml.parse(Assets.getText(path)).firstElement());
AlphaCharacter.boldAnims = [];
AlphaCharacter.letterAnims = [];
AlphaCharacter.boldAlphabetPath = AlphaCharacter.letterAlphabetPath = 'ui/alphabet';
for(e in xml.elements) {
var bold = e.name == "bold";
var list = bold ? AlphaCharacter.boldAnims : AlphaCharacter.letterAnims;
if (e.has.spritesheet) {
if (bold)
AlphaCharacter.boldAlphabetPath = e.att.spritesheet;
else
AlphaCharacter.letterAlphabetPath = e.att.spritesheet;
}
for(e in e.nodes.letter) {
if (!e.has.char || !e.has.anim) continue;
var name = e.att.char;
var anim = e.att.anim;
list[name] = anim;
}
}
} catch(e) {
trace(e.details());
}
}
public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false)
{
public function new(?x:Float, ?y:Float, ?text:String = "", ?font:OneOfTwo<String, Bool> = "normal") {
super(x, y);
this.text = text;
this.font = (font is String) ? font : ((font == true) ? "bold" : "normal"); // == true just in case
this.__renderData = new AlphabetRenderData(this);
}
_finalText = this.text = text;
isBold = bold;
var alphabetPath = Paths.xml("alphabet");
if (Paths.getAssetsRoot() + alphabetPath != AlphaCharacter.__alphaPath) {
refreshAlphabetXML(alphabetPath);
}
#if MOD_SUPPORT else {
var libThing = new LimeLibrarySymbol(alphabetPath);
if (libThing.library is AssetLibrary) {
var library = AssetsLibraryList.getCleanLibrary(libThing.library);
if (library is IModsAssetLibrary) {
var modLib = cast(library, IModsAssetLibrary);
@:privateAccess
if (!modLib.__isCacheValid(library.cachedBytes, libThing.symbolName)) {
refreshAlphabetXML(alphabetPath);
}
}
}
}
override function update(elapsed:Float):Void {
//super.update(elapsed);
// FLXOBJECT UPDATE
#if FLX_DEBUG
@:privateAccess FlxBasic.activeCount += 1;
#end
if (text != "")
{
if (typed)
{
startTypedText();
}
else
{
addText();
}
}
}
last.set(x, y);
public function addText()
{
doSplitWords();
if (path != null && path.active)
path.update(elapsed);
var xPos:Float = 0;
var curRow:Int = 0;
for (i=>character in splitWords)
{
if (lastSprite != null)
xPos = lastSprite.x + lastSprite.width - x;
if (moves)
updateMotion(elapsed);
if (xPosResetted && !(xPosResetted = false)) xPos = 0;
wasTouching = touching;
touching = FlxDirectionFlags.NONE;
// FLXOBJECT UPDATE END
var letter:AlphaCharacter = new AlphaCharacter(xPos, 0);
letter.row = curRow;
if (isBold)
letter.createBold(character);
else
letter.createLetter(character);
__animTime += elapsed;
for (effect in effects)
effect.effectTime += elapsed * effect.speed;
// anim not found
if (!letter.visible)
xPos += 40;
letter.setColor(color, isBold);
add(letter);
lastSprite = letter;
if (_finalText.fastCodeAt(i) == "\n".code)
{
xPosResetted = true;
curRow += 1;
}
}
}
function doSplitWords():Void
{
splitWords = _finalText.split("");
}
//public var personTalking:String = 'gf';
public function startTypedText():Void
{
_finalText = text;
doSplitWords();
// trace(arrayShit);
var loopNum:Int = 0;
var xPos:Float = 0;
var curRow:Int = 0;
new FlxTimer().start(0.05, function(tmr:FlxTimer)
{
// trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
if (_finalText.fastCodeAt(loopNum) == "\n".code)
{
yMulti += 1;
xPosResetted = true;
xPos = 0;
curRow += 1;
}
loopNum += 1;
tmr.time = FlxG.random.float(0.04, 0.09);
}, splitWords.length);
}
override function update(elapsed:Float)
{
super.update(elapsed);
if (isMenuItem)
{
var scaledY = FlxMath.remapToRange(targetY, 0, 1, 0, 1.3);
if (isMenuItem) {
var scaledY = targetY * 1.3;
y = CoolUtil.fpsLerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16);
x = CoolUtil.fpsLerp(x, (targetY * 20) + 90, 0.16);
}
if (text != _finalText) {
_finalText = text;
for(e in members)
e.destroy();
members.clear();
lastSprite = null;
addText();
}
}
override function draw() {
override function draw():Void {
__ogForceScreen = forceIsOnScreen;
forceIsOnScreen = true;
super.draw();
}
}
class AlphaCharacter extends FlxSprite
{
@:dox(hide) @:noCompletion public static var __alphaPath:String = null;
override function isSimpleRender(?camera:FlxCamera):Bool {
return false; // maybe ill get simple render working another time??? not right now tho.
}
public static var letterAlphabetPath:String;
public static var boldAlphabetPath:String;
override function drawComplex(camera:FlxCamera):Void {
forceIsOnScreen = __ogForceScreen;
public static var boldAnims:Map<String, String> = [];
public static var letterAnims:Map<String, String> = [];
if (__queueResize)
recalcSizes();
var curLine = 0;
var lastLine = 0;
var daText = switch (forceCase) {
case UPPER: text.toUpperCase();
case LOWER: text.toLowerCase();
case NONE: text;
}
public var row:Int = 0;
var alignmentMultiplier = alignment.getMultiplier();
public function setColor(c:FlxColor, isBold:Bool) {
if (isBold) {
colorTransform.redMultiplier = c.redFloat;
colorTransform.greenMultiplier = c.greenFloat;
colorTransform.blueMultiplier = c.blueFloat;
} else {
colorTransform.redOffset = c.red;
colorTransform.greenOffset = c.green;
colorTransform.blueOffset = c.blue;
var ogOffX = frameOffset.x;
var ogOffY = frameOffset.y;
frameOffset.x -= (textWidth - __laneWidths[0]) * alignmentMultiplier;
var isGraphicsShader = shader != null && shader is flixel.graphics.tile.FlxGraphicsShader;
var ogRed:Float = colorTransform.redMultiplier;
var ogGreen:Float = colorTransform.greenMultiplier;
var ogBlue:Float = colorTransform.blueMultiplier;
var ogAlpha:Float = colorTransform.alphaMultiplier;
var frameTime = Math.floor(__animTime * fps);
for (i in 0...daText.length) {
__renderData.reset(this, ogRed, ogGreen, ogBlue, ogAlpha, daText.charAt(i));
for (effect in effects) {
if (effect.willModify(i, i - lastLine, __renderData))
effect.modify(i, i - lastLine, __renderData);
}
var letter = __renderData.letter;
if (letter == "\n") {
curLine++;
lastLine = i + 1;
frameOffset.x = ogOffX - (textWidth - __laneWidths[curLine]) * alignmentMultiplier;
frameOffset.y -= lineGap;
continue;
}
var data = getData(letter);
if (data == null) {
frameOffset.x -= defaultAdvance;
continue;
}
var advance:Float = Math.NaN;
for (i in 0...data.components.length) {
__component = data.components[i];
var anim = getLetterAnim(letter, data, __component, i);
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;
frame = frames.frames[anim.frames[frameToGet]];
var offsetX = __component.x + __renderData.offsetX;
var offsetY = frame.sourceSize.y - lineGap + __component.y + __renderData.offsetY;
frameOffset.x += offsetX;
frameOffset.y += offsetY;
if (!isOnScreen(camera)) {
frameOffset.y -= offsetY;
frameOffset.x -= offsetX;
break;
}
if (isGraphicsShader)
shader.setCamSize(_frame.frame.x, _frame.frame.y, _frame.frame.width, _frame.frame.height);
if (__component.hasColorMode)
__component.colorMode.setColorTransform(colorTransform, __renderData.red, __renderData.green, __renderData.blue, __renderData.alpha);
else
colorMode.setColorTransform(colorTransform, __renderData.red, __renderData.green, __renderData.blue, __renderData.alpha);
drawLetter(camera);
frameOffset.y -= offsetY;
frameOffset.x -= offsetX;
}
frameOffset.x -= advance;
}
__component = null;
setColorTransform(ogRed, ogGreen, ogBlue, ogAlpha, 0, 0, 0, 0);
frameOffset.set(ogOffX, ogOffY);
}
function drawLetter(camera) {
_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(__component.shouldRotate) _matrix.rotateWithTrig(__component.cos, __component.sin);
_matrix.translate(_frame.frame.width * 0.5, _frame.frame.height * 0.5);
_matrix.translate(-origin.x, -origin.y);
if (frameOffsetAngle != null && frameOffsetAngle != angle)
{
var angleOff = (frameOffsetAngle - angle) * FlxAngle.TO_RAD;
var cos = Math.cos(angleOff);
var sin = Math.sin(angleOff);
// cos doesnt need to be negated
_matrix.rotateWithTrig(cos, -sin);
_matrix.translate(-frameOffset.x, -frameOffset.y);
_matrix.rotateWithTrig(cos, sin);
}
else
_matrix.translate(-frameOffset.x, -frameOffset.y);
_matrix.scale(scale.x, scale.y);
if (bakedRotationAngle <= 0)
{
updateTrig();
if (angle != 0)
_matrix.rotateWithTrig(_cosAngle, _sinAngle);
}
getScreenPosition(_point, camera).subtractPoint(offset);
_point.add(origin.x, origin.y);
_matrix.translate(_point.x, _point.y);
if (isPixelPerfectRender(camera))
{
_matrix.tx = Math.floor(_matrix.tx);
_matrix.ty = Math.floor(_matrix.ty);
}
doAdditionalMatrixStuff(_matrix, camera);
if (layer != null)
layer.drawPixels(this, camera, _frame, framePixels, _matrix, colorTransform, blend, antialiasing, shaderEnabled ? shader : null);
else
camera.drawPixels(_frame, framePixels, _matrix, colorTransform, blend, antialiasing, shaderEnabled ? shader : null);
}
override function updateHitbox():Void {
offset.set(-0.5 * (width - textWidth), -0.5 * (height - textHeight));
origin.set(textWidth * 0.5 + originOffset.x, textHeight * 0.5 + originOffset.y);
}
function recalcSizes():Void {
__queueResize = false;
var curLine = 0;
var daText = switch (forceCase) {
case UPPER: text.toUpperCase();
case LOWER: text.toLowerCase();
case NONE: text;
}
@:bypassAccessor textWidth = 0;
textHeight = lineGap;
__laneWidths = [0];
for (i in 0...daText.length) {
var letter = daText.charAt(i);
if (letter == "\n") {
textHeight += lineGap;
__laneWidths.push(0);
curLine++;
continue;
}
var data = getData(letter);
__laneWidths[curLine] += (data != null) ? getAdvance(letter, getLetterAnim(letter, data, data.components[0], 0), data) : defaultAdvance;
@:bypassAccessor textWidth = Math.max(textWidth, __laneWidths[curLine]);
}
origin.set(textWidth * 0.5 + originOffset.x, textHeight * 0.5 + originOffset.y);
}
function getAdvance(letter:String, anim:FlxAnimation, data:AlphabetLetterData):Float {
if (anim == null)
return defaultAdvance;
if (data.advanceEmpty && !data.isDefault) {
data.advanceEmpty = false;
data.advance = frames.frames[anim.frames[0]].sourceSize.x;
}
return (data.isDefault) ? frames.frames[anim.frames[0]].sourceSize.x : data.advance;
}
function getData(char:String):AlphabetLetterData {
if (failedLetters.contains(char)) return null;
for (i in 0...3) { // this feels wrong
if (loaded[i].contains(char))
return defaults[i];
}
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);
return null;
} else if (data.isDefault)
loaded[defaultsIndexOf(data)].push(char);
return data;
}
final function defaultsIndexOf(data:AlphabetLetterData):Int {
//while(i < defaults.length) {
for(i in 0...3) {
if(defaults[i] == data)
return i;
}
return -1;
}
function getLetterAnim(char:String, data:AlphabetLetterData, component:AlphabetComponent, index:Int):FlxAnimation {
if (data == null) return null;
var name = char + Std.string(index);
if (animation.exists(name)) return animation.getByName(name);
var anim = (data.isDefault) ?
component.anim.replace("LETTER", char) :
component.anim;
animation.addByPrefix(name, anim, fps);
if (!animation.exists(name)) {
failedLetters.push(char);
return null;
}
return animation.getByName(name);
}
function checkNode(node:Xml):Void {
switch (node.nodeName) {
case "spritesheet":
if (frames == null)
frames = Paths.getFrames(node.firstChild().nodeValue);
else {
for (frame in Paths.getFrames(node.firstChild().nodeValue).frames)
frames.pushFrame(frame);
}
case "defaultAnim":
var idx = ["UPPER", "LOWER"].indexOf(node.get("casing").toUpperCase()) + 1;
var rad:Float = Std.parseFloat(node.get("angle")).getDefaultFloat(0.0) * FlxAngle.TO_RAD;
var angleCos = Math.cos(rad);
var angleSin = Math.sin(rad);
var res:AlphabetLetterData = {
isDefault: true,
advance: 0.0,
advanceEmpty: true,
components: [{
anim: node.firstChild().nodeValue,
x: 0.0,
y: 0.0,
scaleX: Std.parseFloat(node.get("scaleX")).getDefaultFloat(1.0),
scaleY: Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0),
shouldRotate: rad != 0,
cos: angleCos,
sin: angleSin,
hasColorMode: false,
colorMode: 0
}]
}
defaults[idx] = res;
case "composite":
if(!node.exists("char")) {
Logs.error("<composite> must have a char attribute", "Alphabet");
return;
}
var char = node.get("char");
var advance:Float = Std.parseFloat(node.get("advance"));
var components:Array<AlphabetComponent> = [];
for (component in node.elementsNamed("component")) {
if(!component.exists("anim")) {
Logs.error("<component> must have a anim attribute", "Alphabet");
return;
}
var rad:Float = Std.parseFloat(component.get("angle")).getDefaultFloat(0.0) * FlxAngle.TO_RAD;
var angleCos = Math.cos(rad);
var angleSin = Math.sin(rad);
var xOff:Float = -Std.parseFloat(component.get("x")).getDefaultFloat(0.0);
var yOff:Float = Std.parseFloat(component.get("y")).getDefaultFloat(0.0);
var colorMode = ["tint", "offsets", "none"].indexOf(component.get("colorMode"));
components.push({
anim: component.get("anim"),
x: xOff,
y: yOff,
scaleX: Std.parseFloat(component.get("scaleX")).getDefaultFloat(1.0),
scaleY: Std.parseFloat(component.get("scaleY")).getDefaultFloat(1.0),
shouldRotate: rad != 0,
cos: angleCos,
sin: angleSin,
hasColorMode: colorMode >= 0,
colorMode: colorMode
});
}
letterData.set(char, {
isDefault: false,
advance: advance,
advanceEmpty: Math.isNaN(advance),
components: components
});
case "anim":
if(!node.exists("char")) {
Logs.error("<anim> must have a char attribute", "Alphabet");
return;
}
var char = node.get("char");
var rad:Float = Std.parseFloat(node.get("angle")).getDefaultFloat(0.0) * FlxAngle.TO_RAD;
var angleCos = Math.cos(rad);
var angleSin = Math.sin(rad);
var xOff:Float = -Std.parseFloat(node.get("x")).getDefaultFloat(0.0);
var yOff:Float = Std.parseFloat(node.get("y")).getDefaultFloat(0.0);
var advance:Float = Std.parseFloat(node.get("advance"));
var colorMode = ["tint", "offsets", "none"].indexOf(node.get("colorMode"));
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),
shouldRotate: rad != 0,
cos: angleCos,
sin: angleSin,
hasColorMode: colorMode >= 0,
colorMode: colorMode
}]
});
case "languageSection": // used to only parse characters if a specific language is selected
if(!node.exists("langs")) {
Logs.error("<languageSection> must have a langs attribute", "Alphabet");
return;
}
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)) {
for (langNode in node.elements())
checkNode(langNode);
}
}
}
public function new(x:Float, y:Float)
{
super(x, y);
antialiasing = true;
}
function loadFont(value:String):Void {
__queueResize = true;
public function createBold(letter:String)
{
if(!boldAnims.exists(letter))
letter = letter.toUpperCase();
if (!boldAnims.exists(letter)) {
visible = false;
active = false;
scale.set();
width = 40;
return;
var xml:Xml = Xml.parse(Assets.getText(Paths.xml("alphabet/" + value))).firstElement();
// reset old values
letterData = new Map();
defaults = {
var v = new Vector(3);
v[0] = null;
v[1] = null;
v[2] = null;
v;
}
frames = Paths.getFrames(boldAlphabetPath);
animation.addByPrefix(letter, boldAnims[letter], 24);
animation.play(letter);
updateHitbox();
y += row * height;
}
public function createLetter(letter:String):Void
{
if (!letterAnims.exists(letter)) {
visible = false;
active = false;
scale.set();
width = 40;
return;
loaded = {
var v = new Vector(3);
v[0] = [];
v[1] = [];
v[2] = [];
v;
}
frames = Paths.getFrames(letterAlphabetPath);
animation.addByPrefix(letter, letterAnims[letter], 24);
animation.play(letter);
updateHitbox();
failedLetters = [];
y = (110 - height);
y += row * 60;
defaultAdvance = Std.parseFloat(xml.get("advance")).getDefaultFloat(40.0);
lineGap = Std.parseFloat(xml.get("lineGap")).getDefaultFloat(75.0);
fps = Std.parseFloat(xml.get("fps")).getDefaultFloat(24.0);
forceCase = xml.get("forceCasing").getDefault("none").toLowerCase();
colorMode = (["offsets", "none"].indexOf(xml.get("colorMode")) + 1);
frames = null;
for (node in xml.elements())
checkNode(node);
}
}
override function destroy():Void {
originOffset = FlxDestroyUtil.destroy(originOffset);
failedLetters = [];
super.destroy();
}
function get_textWidth():Float {
if (__queueResize)
recalcSizes();
return textWidth;
}
function set_textWidth(value:Float):Float {
if(!__queueResize)
__queueResize = __forceWidth != value;
return __forceWidth = value;
}
override function get_width():Float {
return textWidth * scale.x;
}
override function get_height():Float {
return textHeight * scale.y;
}
function get_textHeight():Float {
if (__queueResize)
recalcSizes();
return textHeight;
}
function set_text(value:String):String {
if(!__queueResize)
__queueResize = text != value;
return text = value;
}
function set_font(value:String):String {
if (font != value) {
loadFont(font = value);
}
return value;
}
}
+284
View File
@@ -0,0 +1,284 @@
package funkin.menus.ui;
import flixel.group.FlxSpriteGroup;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
import funkin.backend.assets.AssetsLibraryList;
import funkin.backend.assets.IModsAssetLibrary;
import funkin.backend.assets.LimeLibrarySymbol;
import haxe.xml.Access;
import openfl.utils.AssetLibrary;
using StringTools;
/**
* Loosely based on FlxTypeText lolol
*/
class ClassicAlphabet extends FlxSpriteGroup
{
public var delay:Float = 0.05;
public var paused:Bool = false;
// for menu shit
public var targetY:Float = 0;
public var isMenuItem:Bool = false;
public var text:String = "";
var _finalText:String = "";
var _curText:String = "";
var yMulti:Float = 1;
// custom shit
// amp, backslash, question mark, apostrophy, comma, angry faic, period
var lastSprite:AlphaCharacter;
var xPosResetted:Bool = false;
var splitWords:Array<String> = [];
var isBold:Bool = false;
private override function set_color(c:Int):Int {
for(e in group.members) {
if (e is AlphaCharacter) {
var char:AlphaCharacter = cast e;
char.setColor(c, isBold);
}
}
return super.set_color(c);
}
// TODO: fix this shit refreshing
public function refreshAlphabetXML(path:String) {
AlphaCharacter.__alphaPath = Paths.getAssetsRoot() + path;
try {
var xml = new Access(Xml.parse(Assets.getText(path)).firstElement());
AlphaCharacter.boldAnims = [];
AlphaCharacter.letterAnims = [];
AlphaCharacter.boldAlphabetPath = AlphaCharacter.letterAlphabetPath = 'ui/alphabet';
for(e in xml.elements) {
var bold = e.name == "bold";
var list = bold ? AlphaCharacter.boldAnims : AlphaCharacter.letterAnims;
if (e.has.spritesheet) {
if (bold)
AlphaCharacter.boldAlphabetPath = e.att.spritesheet;
else
AlphaCharacter.letterAlphabetPath = e.att.spritesheet;
}
for(e in e.nodes.letter) {
if (!e.has.char || !e.has.anim) continue;
var name = e.att.char;
var anim = e.att.anim;
list[name] = anim;
}
}
} catch(e) {
trace(e.details());
}
}
public function new(x:Float, y:Float, text:String = "", ?bold:Bool = false, typed:Bool = false)
{
super(x, y);
_finalText = this.text = text;
isBold = bold;
var alphabetPath = Paths.xml("alphabet");
if (Paths.getAssetsRoot() + alphabetPath != AlphaCharacter.__alphaPath) {
refreshAlphabetXML(alphabetPath);
}
#if MOD_SUPPORT else {
var libThing = new LimeLibrarySymbol(alphabetPath);
if (libThing.library is AssetLibrary) {
var library = AssetsLibraryList.getCleanLibrary(libThing.library);
if (library is IModsAssetLibrary) {
var modLib = cast(library, IModsAssetLibrary);
@:privateAccess
if (!modLib.__isCacheValid(library.cachedBytes, libThing.symbolName)) {
refreshAlphabetXML(alphabetPath);
}
}
}
}
#end
if (text != "")
{
if (typed)
{
startTypedText();
}
else
{
addText();
}
}
}
public function addText()
{
doSplitWords();
var xPos:Float = 0;
var curRow:Int = 0;
for (i=>character in splitWords)
{
if (lastSprite != null)
xPos = lastSprite.x + lastSprite.width - x;
if (xPosResetted && !(xPosResetted = false)) xPos = 0;
var letter:AlphaCharacter = new AlphaCharacter(xPos, 0);
letter.row = curRow;
if (isBold)
letter.createBold(character);
else
letter.createLetter(character);
// anim not found
if (!letter.visible)
xPos += 40;
letter.setColor(color, isBold);
add(letter);
lastSprite = letter;
if (_finalText.fastCodeAt(i) == "\n".code)
{
xPosResetted = true;
curRow += 1;
}
}
}
function doSplitWords():Void
{
splitWords = _finalText.split("");
}
//public var personTalking:String = 'gf';
public function startTypedText():Void
{
_finalText = text;
doSplitWords();
// trace(arrayShit);
var loopNum:Int = 0;
var xPos:Float = 0;
var curRow:Int = 0;
new FlxTimer().start(0.05, function(tmr:FlxTimer)
{
// trace(_finalText.fastCodeAt(loopNum) + " " + _finalText.charAt(loopNum));
if (_finalText.fastCodeAt(loopNum) == "\n".code)
{
yMulti += 1;
xPosResetted = true;
xPos = 0;
curRow += 1;
}
loopNum += 1;
tmr.time = FlxG.random.float(0.04, 0.09);
}, splitWords.length);
}
override function update(elapsed:Float)
{
super.update(elapsed);
if (isMenuItem)
{
var scaledY = FlxMath.remapToRange(targetY, 0, 1, 0, 1.3);
y = CoolUtil.fpsLerp(y, (scaledY * 120) + (FlxG.height * 0.48), 0.16);
x = CoolUtil.fpsLerp(x, (targetY * 20) + 90, 0.16);
}
if (text != _finalText) {
_finalText = text;
for(e in members)
e.destroy();
members.clear();
lastSprite = null;
addText();
}
}
override function draw() {
super.draw();
}
}
class AlphaCharacter extends FlxSprite
{
@:dox(hide) @:noCompletion public static var __alphaPath:String = null;
public static var letterAlphabetPath:String;
public static var boldAlphabetPath:String;
public static var boldAnims:Map<String, String> = [];
public static var letterAnims:Map<String, String> = [];
public var row:Int = 0;
public function setColor(c:FlxColor, isBold:Bool) {
if (isBold) {
colorTransform.redMultiplier = c.redFloat;
colorTransform.greenMultiplier = c.greenFloat;
colorTransform.blueMultiplier = c.blueFloat;
} else {
colorTransform.redOffset = c.red;
colorTransform.greenOffset = c.green;
colorTransform.blueOffset = c.blue;
}
}
public function new(x:Float, y:Float)
{
super(x, y);
antialiasing = true;
}
public function createBold(letter:String)
{
if(!boldAnims.exists(letter))
letter = letter.toUpperCase();
if (!boldAnims.exists(letter)) {
visible = false;
active = false;
scale.set();
width = 40;
return;
}
frames = Paths.getFrames(boldAlphabetPath);
animation.addByPrefix(letter, boldAnims[letter], 24);
animation.play(letter);
updateHitbox();
y += row * height;
}
public function createLetter(letter:String):Void
{
if (!letterAnims.exists(letter)) {
visible = false;
active = false;
scale.set();
width = 40;
return;
}
frames = Paths.getFrames(letterAlphabetPath);
animation.addByPrefix(letter, letterAnims[letter], 24);
animation.play(letter);
updateHitbox();
y = (110 - height);
y += row * 60;
}
}
-593
View File
@@ -1,593 +0,0 @@
package funkin.menus.ui;
import haxe.ds.Vector;
import funkin.menus.ui.effects.RegionEffect;
import flixel.animation.FlxAnimation;
import flixel.util.FlxDirectionFlags;
import flixel.math.FlxPoint;
import flixel.FlxTypes;
import haxe.xml.Access;
using StringTools;
using flixel.util.FlxColorTransformUtil;
@:structInit
final class AlphabetOutline {
public var anim:String;
public var x:Float;
public var y:Float;
}
@:structInit
final class AlphabetComponentData {
public var anim:String;
@:optional public var outline:AlphabetOutline;
}
@:structInit
final class AlphabetComponent {
public var data:AlphabetComponentData;
public var x:Float;
public var y:Float;
// Precalculated values for angle
public var sin:Float;
public var cos:Float;
public var scaleX:Float;
public var scaleY:Float;
}
@:structInit
final class AlphabetLetterData {
@:optional public var isDefault:Bool = false;
public var advance:Float;
public var advanceEmpty:Bool;
public var components:Array<AlphabetComponent>;
}
enum abstract AlphabetAlignment(ByteUInt) from ByteUInt to ByteUInt {
var LEFT;
var CENTER;
var RIGHT;
public function getMultiplier():Float {
return switch(this) {
case CENTER: 0.5;
case RIGHT: 1.0;
default: 0.0;
}
}
@:from
public static function fromString(value:String):AlphabetAlignment
return switch(value) {
case "left": LEFT;
case "center": CENTER;
case "right": RIGHT;
default: LEFT;
}
}
enum abstract CaseMode(ByteUInt) from ByteUInt to ByteUInt {
var NONE;
var UPPER;
var LOWER;
@:from
public static function fromString(value:String):CaseMode
return switch(value) {
case "none": NONE;
case "upper": UPPER;
case "lower": LOWER;
default: NONE;
}
}
class NewAlphabet extends FlxSprite {
public var effects:Array<RegionEffect> = [];
var __renderData:AlphabetRenderData;
public var text(default, set):String = "";
@:isVar public var textWidth(get, set):Float;
public var textHeight(get, null):Float;
public var alignment:AlphabetAlignment = LEFT;
public var forceCase:CaseMode = NONE;
var __laneWidths:Array<Float> = []; // TODO: add alignment.
var __forceWidth:Float = 0.0; // TODO: implement functionality for this.
var __queueResize:Bool = false;
var __animTime:Float = 0.0;
var __ogForceScreen:Bool = false;
public var originOffset:FlxPoint = FlxPoint.get();
public var font(default, set):String;
var transformMult:ByteUInt = 1; // 1 if multipliers (tint), 0 if offset.
var defaultAdvance:Float = 40.0;
var lineGap:Float = 75.0;
var fps:Float = 24.0;
var letterData:Map<String, AlphabetLetterData> = [];
var allComponents:Map<String, AlphabetComponentData> = [];
var defaults:Vector<AlphabetLetterData> = {
var v = new Vector(3);
v[0] = null;
v[1] = null;
v[2] = null;
v;
};
var loaded:Vector<Array<String>> = {
var v = new Vector(3);
v[0] = [];
v[1] = [];
v[2] = [];
v;
};
var failedLetters:Array<String> = [];
public function new(?x:Float, ?y:Float, ?font:String = "bold") {
super(x, y);
this.font = font;
this.__renderData = new AlphabetRenderData(this);
}
override function update(elapsed:Float):Void {
//super.update(elapsed);
// FLXOBJECT UPDATE
#if FLX_DEBUG
@:privateAccess FlxBasic.activeCount += 1;
#end
last.set(x, y);
if (path != null && path.active)
path.update(elapsed);
if (moves)
updateMotion(elapsed);
wasTouching = touching;
touching = FlxDirectionFlags.NONE;
// FLXOBJECT UPDATE END
__animTime += elapsed;
for (effect in effects)
effect.effectTime += elapsed * effect.speed;
}
override function draw():Void {
__ogForceScreen = forceIsOnScreen;
forceIsOnScreen = true;
super.draw();
}
override function isSimpleRender(?camera:FlxCamera):Bool {
return false; // maybe ill get simple render working another time??? not right now tho.
}
override function drawComplex(camera:FlxCamera):Void {
forceIsOnScreen = __ogForceScreen;
if (__queueResize)
recalcSizes();
var curLine = 0;
var lastLine = 0;
var daText = switch (forceCase) {
case UPPER: text.toUpperCase();
case LOWER: text.toLowerCase();
case NONE: text;
}
var alignmentMultiplier = alignment.getMultiplier();
var ogOffX = frameOffset.x;
var ogOffY = frameOffset.y;
frameOffset.x -= (textWidth - __laneWidths[0]) * alignmentMultiplier;
var isGraphicsShader = shader != null && shader is flixel.graphics.tile.FlxGraphicsShader;
var offsetMult = (1 - transformMult) * 255;
var ogRed:Float = colorTransform.redMultiplier;
var ogGreen:Float = colorTransform.greenMultiplier;
var ogBlue:Float = colorTransform.blueMultiplier;
var ogAlpha:Float = colorTransform.alphaMultiplier;
var frameTime = Math.floor(__animTime * fps);
for (i in 0...daText.length) {
__renderData.reset(this, ogRed, ogGreen, ogBlue, ogAlpha, daText.charAt(i));
for (effect in effects) {
if (effect.willModify(i, i - lastLine, __renderData))
effect.modify(i, i - lastLine, __renderData);
}
var letter = __renderData.letter;
if (letter == "\n") {
curLine++;
lastLine = i + 1;
frameOffset.x = ogOffX - (textWidth - __laneWidths[curLine]) * alignmentMultiplier;
frameOffset.y -= lineGap;
continue;
}
var data = getData(letter);
if (data == null) {
frameOffset.x -= defaultAdvance;
continue;
}
var advance:Float = Math.NaN;
for (i => com in data.components) {
var anim = getLetterAnim(letter, data, com, i);
advance = (Math.isNaN(advance)) ? getAdvance(letter, anim, data) : advance;
if (anim == null || __renderData.alpha <= 0.0) {
frameOffset.x -= advance;
break; // shouldnt this be like continue?
}
var frameToGet = frameTime % anim.numFrames;
frame = frames.frames[anim.frames[frameToGet]];
var offsetX = com.x + __renderData.offsetX;
var offsetY = frame.sourceSize.y - lineGap + com.y + __renderData.offsetY;
frameOffset.x += offsetX;
frameOffset.y += offsetY;
if (!isOnScreen(camera)) {
frameOffset.y -= offsetY;
frameOffset.x -= offsetX + advance;
break;
}
if (isGraphicsShader)
shader.setCamSize(_frame.frame.x, _frame.frame.y, _frame.frame.width, _frame.frame.height);
setColorTransform(
__renderData.red * transformMult, __renderData.green * transformMult, __renderData.blue * transformMult, __renderData.alpha,
Math.round(__renderData.red * offsetMult), Math.round(__renderData.green * offsetMult), Math.round(__renderData.blue * offsetMult), 0
);
super.drawComplex(camera);
frameOffset.y -= offsetY;
frameOffset.x -= offsetX + advance;
}
}
setColorTransform(ogRed, ogGreen, ogBlue, ogAlpha, 0, 0, 0, 0);
frameOffset.set(ogOffX, ogOffY);
}
override function updateHitbox():Void {
width = Math.abs(scale.x) * textWidth;
height = Math.abs(scale.y) * textHeight;
offset.set(-0.5 * (width - textWidth), -0.5 * (height - textHeight));
origin.set(textWidth * 0.5 + originOffset.x, textHeight * 0.5 + originOffset.y);
}
function recalcSizes():Void {
__queueResize = false;
var curLine = 0;
var daText = switch (forceCase) {
case UPPER: text.toUpperCase();
case LOWER: text.toLowerCase();
case NONE: text;
}
@:bypassAccessor textWidth = 0;
textHeight = lineGap;
__laneWidths = [0];
for (i in 0...daText.length) {
var letter = daText.charAt(i);
if (letter == "\n") {
textHeight += lineGap;
__laneWidths.push(0);
curLine++;
continue;
}
var data = getData(letter);
__laneWidths[curLine] += (data != null) ? getAdvance(letter, getLetterAnim(letter, data, data.components[0], 0), data) : defaultAdvance;
@:bypassAccessor textWidth = Math.max(textWidth, __laneWidths[curLine]);
}
origin.set(textWidth * 0.5 + originOffset.x, textHeight * 0.5 + originOffset.y);
}
function getAdvance(letter:String, anim:FlxAnimation, data:AlphabetLetterData):Float {
if (anim == null)
return defaultAdvance;
if (data.advanceEmpty && !data.isDefault) {
data.advanceEmpty = false;
data.advance = frames.frames[anim.frames[0]].sourceSize.x;
}
return (data.isDefault) ? frames.frames[anim.frames[0]].sourceSize.x : data.advance;
}
function getData(char:String):AlphabetLetterData {
if (failedLetters.contains(char)) return null;
for (i in 0...3) { // this feels wrong
if (loaded[i].contains(char))
return defaults[i];
}
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);
return null;
} else if (data.isDefault)
loaded[defaultsIndexOf(data)].push(char);
return data;
}
final function defaultsIndexOf(data:AlphabetLetterData):Int {
//while(i < defaults.length) {
for(i in 0...3) {
if(defaults[i] == data)
return i;
}
return -1;
}
function getLetterAnim(char:String, data:AlphabetLetterData, component:AlphabetComponent, index:Int):FlxAnimation {
if (data == null) return null;
var name = char + Std.string(index);
if (animation.exists(name)) return animation.getByName(name);
var anim = (data.isDefault) ?
component.data.anim.replace("LETTER", char) :
component.data.anim;
animation.addByPrefix(name, anim, fps);
if (!animation.exists(name)) {
failedLetters.push(char);
return null;
}
return animation.getByName(name);
}
function checkNode(node:Xml):Void {
switch (node.nodeName) {
case "spritesheet":
if (frames == null)
frames = Paths.getFrames(node.firstChild().nodeValue);
else {
for (frame in Paths.getFrames(node.firstChild().nodeValue).frames)
frames.pushFrame(frame);
}
case "defaultAnim":
var idx = ["UPPER", "LOWER"].indexOf(node.get("casing").toUpperCase()) + 1;
var angle:Float = Std.parseFloat(node.get("angle")).getDefaultFloat(0.0);
var angleCos = Math.cos(angle);
var angleSin = Math.sin(angle);
// register character as component
allComponents.set("DEFAULT_" + idx, {
anim: node.firstChild().nodeValue.trim(),
outline: null
});
var res:AlphabetLetterData = {
isDefault: true,
advance: 0.0,
advanceEmpty: true,
components: [{
data: allComponents.get("DEFAULT_" + idx),
x: 0.0,
y: 0.0,
scaleX: Std.parseFloat(node.get("scaleX")).getDefaultFloat(1.0),
scaleY: Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0),
cos: angleCos,
sin: angleSin
}]
}
defaults[idx] = res;
case "component-data":
if(!node.exists("id")) {
Logs.error("<component-data> must have an id attribute", "Alphabet");
return;
}
var id = node.get("id");
var anim = node.firstChild().nodeValue.trim();
var outline:AlphabetOutline = null;
if(node.firstElement() != null) {
var outlineNode = node.firstElement();
switch(outlineNode.nodeName) {
case "outline":
outline = {
anim: outlineNode.firstChild().nodeValue.trim(),
x: Std.parseFloat(outlineNode.get("x")).getDefaultFloat(0.0),
y: Std.parseFloat(outlineNode.get("y")).getDefaultFloat(0.0)
};
}
}
allComponents.set(id, {
anim: anim,
outline: outline
});
case "composite":
if(!node.exists("char")) {
Logs.error("<composite> must have a char attribute", "Alphabet");
return;
}
var char = node.get("char");
var advance:Float = Std.parseFloat(node.get("advance"));
var components:Array<AlphabetComponent> = [];
for (component in node.elementsNamed("component")) {
if(!component.exists("id")) {
Logs.error("<component> must have a id attribute", "Alphabet");
return;
}
var angle:Float = Std.parseFloat(component.get("angle")).getDefaultFloat(0.0);
var angleCos = Math.cos(angle);
var angleSin = Math.sin(angle);
var xOff:Float = -Std.parseFloat(component.get("x")).getDefaultFloat(0.0);
var yOff:Float = Std.parseFloat(component.get("y")).getDefaultFloat(0.0);
var componentId = component.get("id").trim();
if(!allComponents.exists(componentId)) {
Logs.error("Component with id '" + componentId + "' does not exist", "Alphabet");
return;
}
components.push({
data: allComponents.get(componentId),
x: xOff,
y: yOff,
scaleX: Std.parseFloat(component.get("scaleX")).getDefaultFloat(1.0),
scaleY: Std.parseFloat(component.get("scaleY")).getDefaultFloat(1.0),
cos: angleCos,
sin: angleSin
});
}
letterData.set(char, {
isDefault: false,
advance: advance,
advanceEmpty: Math.isNaN(advance),
components: components
});
case "anim":
if(!node.exists("char")) {
Logs.error("<anim> must have a char attribute", "Alphabet");
return;
}
var char = node.get("char");
var angle:Float = Std.parseFloat(node.get("angle")).getDefaultFloat(0.0);
var angleCos = Math.cos(angle);
var angleSin = Math.sin(angle);
var xOff:Float = -Std.parseFloat(node.get("x")).getDefaultFloat(0.0);
var yOff:Float = Std.parseFloat(node.get("y")).getDefaultFloat(0.0);
var advance:Float = Std.parseFloat(node.get("advance"));
// register character as component
allComponents.set(char, {
anim: node.firstChild().nodeValue,
outline: null
});
letterData.set(char, {
isDefault: false,
advance: advance,
advanceEmpty: Math.isNaN(advance),
components: [{
data: allComponents.get(char),
x: xOff,
y: yOff,
scaleX: Std.parseFloat(node.get("scaleX")).getDefaultFloat(1.0),
scaleY: Std.parseFloat(node.get("scaleY")).getDefaultFloat(1.0),
cos: angleCos,
sin: angleSin
}]
});
case "languageSection": // used to only parse characters if a specific language is selected
if(!node.exists("langs")) {
Logs.error("<languageSection> must have a langs attribute", "Alphabet");
return;
}
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)) {
for (langNode in node.elements())
checkNode(langNode);
}
}
}
function loadFont(value:String):Void {
__queueResize = true;
var xml:Xml = Xml.parse(Assets.getText(Paths.xml("alphabet/" + value))).firstElement();
// reset old values
letterData = new Map();
defaults = {
var v = new Vector(3);
v[0] = null;
v[1] = null;
v[2] = null;
v;
}
loaded = {
var v = new Vector(3);
v[0] = [];
v[1] = [];
v[2] = [];
v;
}
failedLetters = [];
defaultAdvance = Std.parseFloat(xml.get("advance")).getDefaultFloat(40.0);
lineGap = Std.parseFloat(xml.get("lineGap")).getDefaultFloat(75.0);
fps = Std.parseFloat(xml.get("fps")).getDefaultFloat(24.0);
forceCase = xml.get("forceCasing").getDefault("none").toLowerCase();
transformMult = (xml.get("useColorOffsets") == "true") ? 0 : 1;
frames = null;
for (node in xml.elements())
checkNode(node);
}
override function destroy():Void {
originOffset = FlxDestroyUtil.destroy(originOffset);
failedLetters = [];
super.destroy();
}
function get_textWidth():Float {
if (__queueResize)
recalcSizes();
return textWidth;
}
function set_textWidth(value:Float):Float {
if(!__queueResize)
__queueResize = __forceWidth != value;
return __forceWidth = value;
}
function get_textHeight():Float {
if (__queueResize)
recalcSizes();
return textHeight;
}
function set_text(value:String):String {
if(!__queueResize)
__queueResize = text != value;
return text = value;
}
function set_font(value:String):String {
if (font != value) {
loadFont(font = value);
}
return value;
}
}
@@ -3,7 +3,7 @@ package funkin.menus.ui.effects;
import flixel.util.FlxColor;
class AlphabetRenderData {
public var parent:NewAlphabet;
public var parent:Alphabet;
public var letter:String;
public var offsetX:Float = 0;
public var offsetY:Float = 0;
@@ -13,11 +13,11 @@ class AlphabetRenderData {
public var blue:Float = 0;
public var alpha:Float = 1;
public function new(parent:NewAlphabet) {
public function new(parent:Alphabet) {
this.parent = parent;
}
public function reset(parent:NewAlphabet, red:Float, green:Float, blue:Float, alpha:Float, letter:String) {
public function reset(parent:Alphabet, red:Float, green:Float, blue:Float, alpha:Float, letter:String) {
this.parent = parent;
this.letter = letter;
this.offsetX = 0;
@@ -20,7 +20,7 @@ class KeybindSetting extends FlxTypedSpriteGroup<FlxSprite> {
public function new(x:Float, y:Float, name:String, value:String, ?sparrowIcon:String, ?sparrowAnim:String) {
super();
this.value = value;
title = new Alphabet(0, 0, name, true);
title = new Alphabet(0, 0, name, "bold");
add(title);
var controlArrayP1:Array<FlxKey> = Reflect.field(Options, 'P1_${value}');
@@ -31,12 +31,13 @@ class KeybindSetting extends FlxTypedSpriteGroup<FlxSprite> {
for(i in 1...3) {
var b = null;
var bx = FlxG.width * (0.25 * (i+1)) - x;
if (i == 1)
b = bind1 = new Alphabet(0, 0, "", false);
b = bind1 = new Alphabet(bx, 0, "", "normal");
else
b = bind2 = new Alphabet(0, 0, "", false);
b = bind2 = new Alphabet(bx, 0, "", "normal");
b.setPosition(FlxG.width * (0.25 * (i+1)) - x, -60);
//b.setPosition(FlxG.width * (0.25 * (i+1)) - x, -60);
add(b);
}
updateText();
@@ -19,7 +19,7 @@ class KeybindsOptions extends MusicBeatSubstate {
public var categories:Array<KeybindCategory> = [];
public function translate(id:String, ?args:Array<Dynamic>)
return TU.translate("Keybinds." + id, args);
return TU.translate("KeybindsOptions." + id, args);
public var settingCam:FlxCamera;
@@ -148,7 +148,7 @@ class KeybindsOptions extends MusicBeatSubstate {
var k:Int = 0;
for(category in categories) {
k++;
var title = new Alphabet(0, k * 75, category.name, true);
var title = new Alphabet(0, k * 75, category.name, "bold");
title.screenCenter(X);
add(title);
+2 -2
View File
@@ -37,8 +37,8 @@ class ArrayOption extends OptionType {
this.optionName = optionName;
add(__text = new Alphabet(100, 20, text, true));
add(__selectiontext = new Alphabet(__text.width + 120, -30, formatTextOption(), false));
add(__text = new Alphabet(100, 20, text, "bold"));
add(__selectiontext = new Alphabet(__text.width + 120, 20, formatTextOption(), "normal"));
rawText = text;
}
+2 -2
View File
@@ -39,8 +39,8 @@ class NumOption extends OptionType {
this.changeVal = changeVal;
this.optionName = optionName;
add(__text = new Alphabet(100, 20, text, true));
add(__number = new Alphabet(__text.width + 120, -30, ': $currentSelection', false));
add(__text = new Alphabet(100, 20, text, "bold"));
add(__number = new Alphabet(__text.width + 120, 20, ': $currentSelection', "normal"));
rawText = text;
}
+1 -1
View File
@@ -20,7 +20,7 @@ class TextOption extends OptionType {
public function new(text:String, desc:String, ?suffix:String = "", ?selectCallback:Void->Void = null) {
super(desc);
this.selectCallback = selectCallback;
add(__text = new Alphabet(100, 20, text, true));
add(__text = new Alphabet(100, 20, text, "bold"));
this.suffix = suffix;
rawText = text;
}
+5 -4
View File
@@ -367,7 +367,10 @@ class System
#elseif mac
Sys.command("/usr/bin/open", [path]);
#elseif linux
Sys.command("/usr/bin/xdg-open", [path]);
// generally `xdg-open` should work in every distro
var cmd = Sys.command("xdg-open", [path, "&"]);
// run old command JUST IN CASE it fails, which it shouldn't
if (cmd != 0) cmd = Sys.command("/usr/bin/xdg-open", [path, "&"]);
#elseif (js && html5)
Browser.window.open(path, "_blank");
#elseif flash
@@ -602,9 +605,7 @@ class System
{
// executes first!!
#if (sys && !macro)
funkin.backend.utils.NativeAPI.registerAsDPICompatible();
funkin.backend.system.CommandLineHandler.parseCommandLine(Sys.args());
funkin.backend.system.Main.fixWorkingDirectory();
funkin.backend.system.Main.preInit();
#end
if (__applicationEntryPoint == null)