Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
aaea25bf1f | ||
|
|
4d84e65cb5 | ||
|
|
f8f9d6eb4a | ||
|
|
6d3243b256 | ||
|
|
0cfb3e52c5 |
@@ -71,11 +71,11 @@ _**QOL = Quality of Life**_
|
|||||||
- Characters are located in `data/weeks/characters`.
|
- Characters are located in `data/weeks/characters`.
|
||||||
- Weeks are located in `data/weeks/weeks/`
|
- Weeks are located in `data/weeks/weeks/`
|
||||||
- If you need to rearrange the weeks in-game, you can use the `data/weeks/weeks.txt` file.
|
- If you need to rearrange the weeks in-game, you can use the `data/weeks/weeks.txt` file.
|
||||||
- Editors for Charts and Characters
|
- Editors for Charts and Characters (Stage coming soon)
|
||||||
- Undos/Redos supported
|
- Undos/Redos supported
|
||||||
- Warning on closing unsaved work
|
- Warning on closing unsaved work.
|
||||||
- Clean UI (for ocd freaks)
|
- Clean UI (for ocd freaks)
|
||||||
- Mature Chart editor
|
- Mature Chart editor (Character editor rework soon)
|
||||||
- Features not found in other editors!
|
- Features not found in other editors!
|
||||||
- Every single state & substate can be modified via HScript (`data/states/StateName.hx`)
|
- Every single state & substate can be modified via HScript (`data/states/StateName.hx`)
|
||||||
- **Instances launched via `lime test windows` will automatically use assets from source.**
|
- **Instances launched via `lime test windows` will automatically use assets from source.**
|
||||||
|
|||||||
@@ -2,13 +2,6 @@
|
|||||||
<character x="115" y="325" sprite="gf-christmas" icon="gf" color="#A5004D">
|
<character x="115" y="325" sprite="gf-christmas" icon="gf" color="#A5004D">
|
||||||
<anim name="danceLeft" anim="GF Dancing Beat" x="0" y="-9" fps="24" loop="false" indices="0..14"/>
|
<anim name="danceLeft" anim="GF Dancing Beat" x="0" y="-9" fps="24" loop="false" indices="0..14"/>
|
||||||
<anim name="danceRight" anim="GF Dancing Beat" x="0" y="-9" fps="24" loop="false" indices="15..30"/>
|
<anim name="danceRight" anim="GF Dancing Beat" x="0" y="-9" fps="24" loop="false" indices="15..30"/>
|
||||||
<anim name="singUP" anim="GF Up Note" x="0" y="-9" fps="24" loop="false"/>
|
|
||||||
<anim name="singDOWN" anim="GF Down Note" x="0" y="-9" fps="24" loop="false"/>
|
|
||||||
<anim name="singLEFT" anim="GF left note" x="0" y="-9" fps="24" loop="false"/>
|
|
||||||
<anim name="singRIGHT" anim="GF Right Note" x="0" y="-9" fps="24" loop="false"/>
|
|
||||||
<anim name="scared" anim="GF FEAR" x="0" y="-9" fps="24" loop="true"/>
|
|
||||||
<anim name="hairBlow" anim="GF Dancing Beat Hair blowing" x="0" y="-9" fps="24" loop="false" indices="0..3"/>
|
|
||||||
<anim name="hairFall" anim="GF Dancing Beat Hair Landing" x="0" y="-9" fps="24" loop="false" indices="0..11"/>
|
|
||||||
<anim name="cheer" anim="GF Cheer" x="0" y="-9" fps="24" loop="false"/>
|
<anim name="cheer" anim="GF Cheer" x="0" y="-9" fps="24" loop="false"/>
|
||||||
<anim name="sad" anim="gf sad" x="-51" y="306" fps="24" loop="true" indices="0..12"/>
|
<anim name="sad" anim="gf sad" x="-51" y="306" fps="24" loop="true" indices="0..12"/>
|
||||||
</character>
|
</character>
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
<!DOCTYPE codename-engine-character>
|
<!DOCTYPE codename-engine-character>
|
||||||
<character x="100" y="275" sprite="gf" icon="gf" color="#A5004D">
|
<character x="100" y="275" color="#A5004D">
|
||||||
<anim name="cheer" anim="GF Cheer" x="0" y="0" fps="24" loop="false"/>
|
<anim name="cheer" anim="GF Cheer"/>
|
||||||
<anim name="singUP" anim="GF Up Note" x="0" y="0" fps="24" loop="false"/>
|
<anim name="singUP" anim="GF Up Note"/>
|
||||||
<anim name="singLEFT" anim="GF left note" x="0" y="0" fps="24" loop="false"/>
|
<anim name="singLEFT" anim="GF left note"/>
|
||||||
<anim name="singRIGHT" anim="GF Right Note" x="0" y="0" fps="24" loop="false"/>
|
<anim name="singRIGHT" anim="GF Right Note"/>
|
||||||
<anim name="singDOWN" anim="GF Down Note" x="0" y="0" fps="24" loop="false"/>
|
<anim name="singDOWN" anim="GF Down Note"/>
|
||||||
<anim name="danceLeft" anim="GF Dancing Beat" x="0" y="0" fps="24" loop="false" indices="0..14"/>
|
<anim name="danceLeft" anim="GF Dancing Beat" indices="0..14"/>
|
||||||
<anim name="danceRight" anim="GF Dancing Beat" x="0" y="0" fps="24" loop="false" indices="15..30"/>
|
<anim name="danceRight" anim="GF Dancing Beat" indices="15..30"/>
|
||||||
<anim name="hairBlow" anim="GF Dancing Beat Hair blowing" x="0" y="0" fps="24" loop="true" indices="0,1,2,3"/>
|
<anim name="hairBlow" anim="GF Dancing Beat Hair blowing" loop="true" indices="0..3"/>
|
||||||
<anim name="hairFall" anim="GF Dancing Beat Hair Landing" x="0" y="0" fps="24" loop="false" indices="0..11"/>
|
<anim name="hairFall" anim="GF Dancing Beat Hair Landing" indices="0..11"/>
|
||||||
<anim name="scared" anim="GF FEAR" x="0" y="0" fps="24" loop="true"/>
|
<anim name="scared" anim="GF FEAR " loop="true"/>
|
||||||
<anim name="sad" anim="gf sad" x="0" y="0" fps="24" loop="true" indices="0..12"/>
|
<anim name="sad" anim="gf sad" x="-51" y="315" loop="true" indices="0..12"/>
|
||||||
</character>
|
</character>
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
# THIS FILE ISN'T NECESSARY,
|
|
||||||
# BUT YOU CAN USE IT TO SORT AND WHITELIST FREEPLAY SONGS
|
|
||||||
|
|
||||||
test
|
test
|
||||||
tutorial
|
tutorial
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
# THIS FILE ISN'T NECESSARY,
|
|
||||||
# BUT YOU CAN USE IT TO SORT AND WHITELIST GAME MODES
|
|
||||||
|
|
||||||
solo
|
|
||||||
opponent
|
|
||||||
coop
|
|
||||||
coop-switched
|
|
||||||
botplay
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"displayName": "Botplay Mode",
|
|
||||||
"modeID": "codename.botplay"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
<!DOCTYPE codename-engine-game-mode>
|
|
||||||
<mode name="Botplay Mode" id="codename.botplay"/>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"displayName": "Co-Op Mode (Switched)",
|
|
||||||
"modeID": "codename.coop-opponent",
|
|
||||||
"scripts": ["opponent", "coop"]
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
<!DOCTYPE codename-engine-game-mode>
|
|
||||||
<mode name="Co-Op Mode (Switched)" id="codename.coop-opponent">
|
|
||||||
<script>coop</script>
|
|
||||||
<script>opponent</script>
|
|
||||||
|
|
||||||
<!--
|
|
||||||
just a small example of what you could do with fields!!
|
|
||||||
<field name="switchStrums" type="bool" val="true"/>
|
|
||||||
<field name="strumSize" type="float" val="0.6"/>
|
|
||||||
-->
|
|
||||||
</mode>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"displayName": "Co-Op Mode",
|
|
||||||
"modeID": "codename.coop"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
<!DOCTYPE codename-engine-game-mode>
|
|
||||||
<mode name="Co-Op Mode" id="codename.coop"/>
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
solo
|
|
||||||
opponent
|
|
||||||
coop
|
|
||||||
coop-switched
|
|
||||||
botplay
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"displayName": "Opponent Mode",
|
|
||||||
"modeID": "codename.opponent"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
<!DOCTYPE codename-engine-game-mode>
|
|
||||||
<mode name="Opponent Mode" id="codename.opponent"/>
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
{
|
|
||||||
"displayName": "Solo Mode",
|
|
||||||
"modeID": "codename.solo"
|
|
||||||
}
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
<!DOCTYPE codename-engine-game-mode>
|
|
||||||
<mode name="Solo Mode" id="codename.solo"/>
|
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
<sprite name="fgSnow" x="-600" y="680" sprite="fgSnow"/>
|
<sprite name="fgSnow" x="-600" y="680" sprite="fgSnow"/>
|
||||||
|
|
||||||
|
|
||||||
<girlfriend x="540" y="110"/>
|
<girlfriend x="440" y="110"/>
|
||||||
<dad/>
|
<dad/>
|
||||||
<boyfriend x="1030" camyoffset="-150" camxoffset="-150"/>
|
<boyfriend x="1030" camyoffset="-150" camxoffset="-150"/>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# THIS FILE ISN'T NECESSARY,
|
# THIS FILE ISN'T NECESSARY,
|
||||||
# BUT YOU CAN USE IT TO SORT AND WHITELIST WEEKS
|
# BUT YOU CAN USE IT TO SORT WEEKS
|
||||||
|
|
||||||
tutorial
|
tutorial
|
||||||
week1
|
week1
|
||||||
@@ -1,28 +1,28 @@
|
|||||||
{"ATLAS": {"SPRITES":[
|
{"ATLAS":{"SPRITES":[
|
||||||
{"SPRITE" : {"name": "0000","x":1636,"y":275,"w":183,"h":115,"rotated": false}},
|
{"SPRITE":{"name":"0","x":1662,"y":282,"w":194,"h":117,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0001","x":215,"y":360,"w":84,"h":140,"rotated": false}},
|
{"SPRITE":{"name":"1","x":1790,"y":417,"w":92,"h":136,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0002","x":419,"y":358,"w":251,"h":121,"rotated": false}},
|
{"SPRITE":{"name":"2","x":1193,"y":539,"w":259,"h":123,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0003","x":1636,"y":394,"w":120,"h":65,"rotated": false}},
|
{"SPRITE":{"name":"3","x":483,"y":553,"w":125,"h":68,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0004","x":4,"y":360,"w":108,"h":126,"rotated": false}},
|
{"SPRITE":{"name":"4","x":1662,"y":417,"w":110,"h":127,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0005","x":674,"y":358,"w":102,"h":147,"rotated": false}},
|
{"SPRITE":{"name":"5","x":1886,"y":0,"w":105,"h":149,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0006","x":116,"y":360,"w":95,"h":130,"rotated": false}},
|
{"SPRITE":{"name":"6","x":1886,"y":167,"w":97,"h":130,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0007","x":2038,"y":4,"w":1,"h":4,"rotated": false}},
|
{"SPRITE":{"name":"7","x":1398,"y":0,"w":470,"h":264,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0008","x":4,"y":4,"w":411,"h":352,"rotated": false}},
|
{"SPRITE":{"name":"8","x":867,"y":0,"w":513,"h":254,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0009","x":419,"y":4,"w":398,"h":350,"rotated": false}},
|
{"SPRITE":{"name":"9","x":0,"y":372,"w":465,"h":270,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0010","x":1303,"y":275,"w":329,"h":162,"rotated": false}},
|
{"SPRITE":{"name":"10","x":1900,"y":315,"w":101,"h":118,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0011","x":303,"y":360,"w":90,"h":103,"rotated": false}},
|
{"SPRITE":{"name":"11","x":867,"y":272,"w":308,"h":367,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0012","x":1823,"y":4,"w":211,"h":236,"rotated": false}},
|
{"SPRITE":{"name":"12","x":483,"y":371,"w":338,"h":164,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0013","x":1823,"y":244,"w":208,"h":235,"rotated": false}},
|
{"SPRITE":{"name":"13","x":0,"y":0,"w":422,"h":354,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0014","x":821,"y":258,"w":478,"h":262,"rotated": false}},
|
{"SPRITE":{"name":"14","x":440,"y":0,"w":409,"h":353,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0015","x":821,"y":4,"w":521,"h":250,"rotated": false}},
|
{"SPRITE":{"name":"15","x":1900,"y":451,"w":92,"h":103,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0016","x":1346,"y":4,"w":473,"h":267,"rotated": false}}
|
{"SPRITE":{"name":"16","x":1193,"y":282,"w":218,"h":239,"rotated":false}},
|
||||||
]},
|
{"SPRITE":{"name":"17","x":1429,"y":282,"w":215,"h":237,"rotated":false}}]},
|
||||||
"meta": {
|
"meta":{
|
||||||
"app": "Adobe Animate",
|
"app":"Adobe Animate (Better TA Extension)",
|
||||||
"version": "22.0.5.191",
|
"version":"24.0.2.12",
|
||||||
"image": "spritemap1.png",
|
"image":"spritemap1.png",
|
||||||
"format": "RGBA8888",
|
"format":"RGBA8888",
|
||||||
"size": {"w":2043,"h":524},
|
"size":{"w":2031,"h":662},
|
||||||
"resolution": "1"
|
"resolution":"1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 134 KiB |
@@ -1,58 +1,40 @@
|
|||||||
{"ATLAS": {"SPRITES":[
|
{"ATLAS":{"SPRITES":[
|
||||||
{"SPRITE" : {"name": "0000","x":994,"y":1029,"w":187,"h":118,"rotated": false}},
|
{"SPRITE":{"name":"0","x":349,"y":867,"w":254,"h":136,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0001","x":1953,"y":524,"w":84,"h":140,"rotated": false}},
|
{"SPRITE":{"name":"1","x":1648,"y":328,"w":287,"h":363,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0002","x":471,"y":430,"w":258,"h":137,"rotated": false}},
|
{"SPRITE":{"name":"2","x":1571,"y":709,"w":185,"h":117,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0003","x":1300,"y":641,"w":122,"h":66,"rotated": false}},
|
{"SPRITE":{"name":"3","x":1686,"y":855,"w":86,"h":136,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0004","x":1825,"y":1078,"w":108,"h":126,"rotated": false}},
|
{"SPRITE":{"name":"4","x":349,"y":1021,"w":122,"h":68,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0005","x":360,"y":695,"w":103,"h":149,"rotated": false}},
|
{"SPRITE":{"name":"5","x":1774,"y":709,"w":110,"h":128,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0006","x":1945,"y":867,"w":95,"h":130,"rotated": false}},
|
{"SPRITE":{"name":"6","x":621,"y":867,"w":105,"h":148,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0007","x":2034,"y":4,"w":1,"h":4,"rotated": false}},
|
{"SPRITE":{"name":"7","x":1571,"y":844,"w":97,"h":131,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0008","x":943,"y":650,"w":309,"h":375,"rotated": false}},
|
{"SPRITE":{"name":"8","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0009","x":4,"y":4,"w":778,"h":422,"rotated": false}},
|
{"SPRITE":{"name":"9","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0010","x":786,"y":4,"w":761,"h":393,"rotated": false}},
|
{"SPRITE":{"name":"10","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0011","x":1551,"y":4,"w":411,"h":352,"rotated": false}},
|
{"SPRITE":{"name":"11","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0012","x":1551,"y":360,"w":398,"h":350,"rotated": false}},
|
{"SPRITE":{"name":"12","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0013","x":4,"y":1028,"w":329,"h":162,"rotated": false}},
|
{"SPRITE":{"name":"13","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0014","x":1945,"y":1001,"w":90,"h":103,"rotated": false}},
|
{"SPRITE":{"name":"14","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0015","x":1300,"y":401,"w":211,"h":236,"rotated": false}},
|
{"SPRITE":{"name":"15","x":800,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0016","x":782,"y":1029,"w":208,"h":235,"rotated": false}},
|
{"SPRITE":{"name":"16","x":1363,"y":1,"w":543,"h":308,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0017","x":782,"y":910,"w":117,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"17","x":1,"y":444,"w":771,"h":404,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0018","x":994,"y":1151,"w":117,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"18","x":791,"y":700,"w":302,"h":369,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0019","x":1937,"y":1108,"w":103,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"19","x":1111,"y":957,"w":120,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0020","x":1115,"y":1151,"w":117,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"20","x":1790,"y":855,"w":120,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0021","x":1654,"y":714,"w":287,"h":360,"rotated": false}},
|
{"SPRITE":{"name":"21","x":1790,"y":959,"w":106,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0022","x":471,"y":571,"w":179,"h":67,"rotated": false}},
|
{"SPRITE":{"name":"22","x":1249,"y":957,"w":120,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0023","x":654,"y":571,"w":118,"h":75,"rotated": false}},
|
{"SPRITE":{"name":"23","x":0,"y":0,"w":781,"h":425,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0024","x":1966,"y":223,"w":55,"h":112,"rotated": false}},
|
{"SPRITE":{"name":"24","x":0,"y":867,"w":331,"h":164,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0025","x":1966,"y":4,"w":64,"h":106,"rotated": false}},
|
{"SPRITE":{"name":"25","x":799,"y":328,"w":413,"h":354,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0026","x":1185,"y":1029,"w":67,"h":70,"rotated": false}},
|
{"SPRITE":{"name":"26","x":1230,"y":328,"w":400,"h":353,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0027","x":337,"y":1182,"w":122,"h":62,"rotated": false}},
|
{"SPRITE":{"name":"27","x":1387,"y":954,"w":90,"h":103,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0028","x":1647,"y":1078,"w":174,"h":97,"rotated": false}},
|
{"SPRITE":{"name":"28","x":1111,"y":700,"w":213,"h":239,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0029","x":360,"y":870,"w":82,"h":14,"rotated": false}},
|
{"SPRITE":{"name":"29","x":1342,"y":699,"w":211,"h":237,"rotated":false}}]},
|
||||||
{"SPRITE" : {"name": "0030","x":1647,"y":1179,"w":128,"h":61,"rotated": false}},
|
"meta":{
|
||||||
{"SPRITE" : {"name": "0031","x":463,"y":1182,"w":124,"h":58,"rotated": false}},
|
"app":"Adobe Animate (Better TA Extension)",
|
||||||
{"SPRITE" : {"name": "0032","x":1966,"y":114,"w":59,"h":105,"rotated": false}},
|
"version":"24.0.2.12",
|
||||||
{"SPRITE" : {"name": "0033","x":1953,"y":360,"w":87,"h":160,"rotated": false}},
|
"image":"spritemap1.png",
|
||||||
{"SPRITE" : {"name": "0034","x":1945,"y":714,"w":92,"h":149,"rotated": false}},
|
"format":"RGBA8888",
|
||||||
{"SPRITE" : {"name": "0035","x":1426,"y":641,"w":104,"h":42,"rotated": false}},
|
"size":{"w":1965,"h":1089},
|
||||||
{"SPRITE" : {"name": "0036","x":1953,"y":692,"w":73,"h":18,"rotated": false}},
|
"resolution":"1"
|
||||||
{"SPRITE" : {"name": "0037","x":1426,"y":687,"w":72,"h":19,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0038","x":360,"y":848,"w":72,"h":18,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0039","x":1953,"y":668,"w":73,"h":20,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0040","x":471,"y":650,"w":468,"h":256,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0041","x":786,"y":401,"w":510,"h":245,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0042","x":4,"y":430,"w":463,"h":261,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0043","x":360,"y":910,"w":418,"h":268,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0044","x":1256,"y":1008,"w":387,"h":271,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0045","x":1256,"y":714,"w":394,"h":290,"rotated": false}},
|
|
||||||
{"SPRITE" : {"name": "0046","x":4,"y":695,"w":352,"h":329,"rotated": false}}
|
|
||||||
]},
|
|
||||||
"meta": {
|
|
||||||
"app": "Adobe Animate",
|
|
||||||
"version": "22.0.5.191",
|
|
||||||
"image": "spritemap1.png",
|
|
||||||
"format": "RGBA8888",
|
|
||||||
"size": {"w":2044,"h":1283},
|
|
||||||
"resolution": "1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 228 KiB After Width: | Height: | Size: 453 KiB |
@@ -1,57 +1,55 @@
|
|||||||
{"ATLAS": {"SPRITES":[
|
{"ATLAS":{"SPRITES":[
|
||||||
{"SPRITE" : {"name": "0000","x":1623,"y":602,"w":287,"h":360,"rotated": false}},
|
{"SPRITE":{"name":"0","x":1129,"y":977,"w":86,"h":17,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0001","x":1310,"y":269,"w":309,"h":375,"rotated": false}},
|
{"SPRITE":{"name":"1","x":1690,"y":1012,"w":86,"h":17,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0002","x":4,"y":4,"w":420,"h":359,"rotated": false}},
|
{"SPRITE":{"name":"2","x":1656,"y":852,"w":126,"h":64,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0003","x":428,"y":4,"w":406,"h":358,"rotated": false}},
|
{"SPRITE":{"name":"3","x":1915,"y":841,"w":121,"h":77,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0004","x":4,"y":639,"w":336,"h":165,"rotated": false}},
|
{"SPRITE":{"name":"4","x":1382,"y":980,"w":131,"h":64,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0005","x":125,"y":808,"w":90,"h":103,"rotated": false}},
|
{"SPRITE":{"name":"5","x":1132,"y":283,"w":420,"h":270,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0006","x":1819,"y":4,"w":215,"h":242,"rotated": false}},
|
{"SPRITE":{"name":"6","x":1570,"y":277,"w":389,"h":273,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0007","x":1217,"y":648,"w":213,"h":240,"rotated": false}},
|
{"SPRITE":{"name":"7","x":0,"y":743,"w":397,"h":292,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0008","x":606,"y":660,"w":191,"h":120,"rotated": false}},
|
{"SPRITE":{"name":"8","x":431,"y":267,"w":354,"h":332,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0009","x":606,"y":784,"w":90,"h":151,"rotated": false}},
|
{"SPRITE":{"name":"9","x":1592,"y":568,"w":190,"h":117,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0010","x":344,"y":660,"w":258,"h":124,"rotated": false}},
|
{"SPRITE":{"name":"10","x":1444,"y":826,"w":86,"h":136,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0011","x":448,"y":859,"w":122,"h":67,"rotated": false}},
|
{"SPRITE":{"name":"11","x":723,"y":852,"w":260,"h":123,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0012","x":1914,"y":755,"w":108,"h":126,"rotated": false}},
|
{"SPRITE":{"name":"12","x":1548,"y":947,"w":124,"h":68,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0013","x":1914,"y":602,"w":103,"h":149,"rotated": false}},
|
{"SPRITE":{"name":"13","x":1001,"y":852,"w":110,"h":128,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0014","x":700,"y":784,"w":95,"h":130,"rotated": false}},
|
{"SPRITE":{"name":"14","x":1933,"y":0,"w":106,"h":148,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0015","x":2038,"y":4,"w":1,"h":4,"rotated": false}},
|
{"SPRITE":{"name":"15","x":1129,"y":828,"w":97,"h":131,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0016","x":838,"y":253,"w":468,"h":256,"rotated": false}},
|
{"SPRITE":{"name":"16","x":803,"y":283,"w":311,"h":369,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0017","x":838,"y":4,"w":510,"h":245,"rotated": false}},
|
{"SPRITE":{"name":"17","x":1592,"y":703,"w":167,"h":101,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0018","x":1352,"y":4,"w":463,"h":261,"rotated": false}},
|
{"SPRITE":{"name":"18","x":1835,"y":852,"w":57,"h":105,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0019","x":4,"y":367,"w":418,"h":268,"rotated": false}},
|
{"SPRITE":{"name":"19","x":1977,"y":270,"w":66,"h":104,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0020","x":826,"y":513,"w":387,"h":271,"rotated": false}},
|
{"SPRITE":{"name":"20","x":1910,"y":936,"w":70,"h":73,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0021","x":428,"y":366,"w":394,"h":290,"rotated": false}},
|
{"SPRITE":{"name":"21","x":1244,"y":828,"w":182,"h":69,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0022","x":1623,"y":269,"w":352,"h":329,"rotated": false}},
|
{"SPRITE":{"name":"22","x":1690,"y":934,"w":127,"h":60,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0023","x":1143,"y":788,"w":67,"h":70,"rotated": false}},
|
{"SPRITE":{"name":"23","x":418,"y":617,"w":287,"h":363,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0024","x":1033,"y":875,"w":122,"h":62,"rotated": false}},
|
{"SPRITE":{"name":"24","x":1244,"y":915,"w":120,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0025","x":1217,"y":513,"w":64,"h":106,"rotated": false}},
|
{"SPRITE":{"name":"25","x":1777,"y":748,"w":120,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0026","x":1979,"y":359,"w":55,"h":112,"rotated": false}},
|
{"SPRITE":{"name":"26","x":1933,"y":166,"w":106,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0027","x":799,"y":788,"w":98,"h":118,"rotated": false}},
|
{"SPRITE":{"name":"27","x":1915,"y":737,"w":120,"h":86,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0028","x":1979,"y":250,"w":59,"h":105,"rotated": false}},
|
{"SPRITE":{"name":"28","x":1800,"y":568,"w":89,"h":162,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0029","x":1434,"y":749,"w":87,"h":160,"rotated": false}},
|
{"SPRITE":{"name":"29","x":1907,"y":568,"w":95,"h":151,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0030","x":1525,"y":749,"w":92,"h":149,"rotated": false}},
|
{"SPRITE":{"name":"30","x":1977,"y":392,"w":61,"h":107,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0031","x":219,"y":887,"w":104,"h":42,"rotated": false}},
|
{"SPRITE":{"name":"31","x":415,"y":998,"w":107,"h":45,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0032","x":527,"y":811,"w":73,"h":18,"rotated": false}},
|
{"SPRITE":{"name":"32","x":727,"y":993,"w":77,"h":22,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0033","x":527,"y":788,"w":72,"h":19,"rotated": false}},
|
{"SPRITE":{"name":"33","x":634,"y":998,"w":75,"h":23,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0034","x":527,"y":833,"w":72,"h":18,"rotated": false}},
|
{"SPRITE":{"name":"34","x":822,"y":993,"w":75,"h":22,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0035","x":1217,"y":623,"w":73,"h":20,"rotated": false}},
|
{"SPRITE":{"name":"35","x":540,"y":998,"w":76,"h":24,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0036","x":344,"y":788,"w":179,"h":67,"rotated": false}},
|
{"SPRITE":{"name":"36","x":1445,"y":0,"w":470,"h":259,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0037","x":219,"y":808,"w":118,"h":75,"rotated": false}},
|
{"SPRITE":{"name":"37","x":431,"y":0,"w":513,"h":249,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0038","x":901,"y":875,"w":128,"h":61,"rotated": false}},
|
{"SPRITE":{"name":"38","x":962,"y":0,"w":465,"h":265,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0039","x":1914,"y":885,"w":124,"h":58,"rotated": false}},
|
{"SPRITE":{"name":"39","x":723,"y":670,"w":331,"h":164,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0040","x":901,"y":788,"w":117,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"40","x":0,"y":0,"w":413,"h":354,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0041","x":1022,"y":788,"w":117,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"41","x":0,"y":372,"w":400,"h":353,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0042","x":341,"y":859,"w":103,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"42","x":1548,"y":826,"w":90,"h":103,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0043","x":4,"y":808,"w":117,"h":83,"rotated": false}},
|
{"SPRITE":{"name":"43","x":1132,"y":571,"w":213,"h":239,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0044","x":1434,"y":648,"w":174,"h":97,"rotated": false}},
|
{"SPRITE":{"name":"44","x":1363,"y":571,"w":211,"h":237,"rotated":false}}]},
|
||||||
{"SPRITE" : {"name": "0045","x":1819,"y":250,"w":82,"h":14,"rotated": false}}
|
"meta":{
|
||||||
]},
|
"app":"Adobe Animate (Better TA Extension)",
|
||||||
"meta": {
|
"version":"24.0.2.12",
|
||||||
"app": "Adobe Animate",
|
"image":"spritemap1.png",
|
||||||
"version": "21.0.1.37179",
|
"format":"RGBA8888",
|
||||||
"image": "spritemap1.png",
|
"size":{"w":2064,"h":1065},
|
||||||
"format": "RGBA8888",
|
"resolution":"1"
|
||||||
"size": {"w":2043,"h":966},
|
|
||||||
"resolution": "1"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 165 KiB After Width: | Height: | Size: 265 KiB |
@@ -1,60 +1,60 @@
|
|||||||
{"ATLAS": {"SPRITES":[
|
{"ATLAS":{"SPRITES":[
|
||||||
{"SPRITE" : {"name": "0000","x":4076,"y":2,"w":9,"h":12,"rotated": false}},
|
{"SPRITE":{"name":"0","x":2834,"y":332,"w":12,"h":15,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0001","x":1957,"y":2,"w":524,"h":501,"rotated": false}},
|
{"SPRITE":{"name":"1","x":1476,"y":532,"w":527,"h":503,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0002","x":716,"y":2,"w":721,"h":621,"rotated": false}},
|
{"SPRITE":{"name":"2","x":733,"y":0,"w":725,"h":623,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0003","x":2331,"y":505,"w":139,"h":109,"rotated": false}},
|
{"SPRITE":{"name":"3","x":0,"y":659,"w":741,"h":304,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0004","x":3244,"y":725,"w":303,"h":170,"rotated": false}},
|
{"SPRITE":{"name":"4","x":2311,"y":0,"w":349,"h":540,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0005","x":1691,"y":516,"w":248,"h":277,"rotated": false}},
|
{"SPRITE":{"name":"5","x":759,"y":641,"w":583,"h":373,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0006","x":2495,"y":843,"w":173,"h":229,"rotated": false}},
|
{"SPRITE":{"name":"6","x":2021,"y":0,"w":272,"h":702,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0007","x":2,"y":642,"w":262,"h":221,"rotated": false}},
|
{"SPRITE":{"name":"7","x":1476,"y":0,"w":518,"h":514,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0008","x":2331,"y":616,"w":118,"h":117,"rotated": false}},
|
{"SPRITE":{"name":"8","x":0,"y":0,"w":715,"h":641,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0009","x":3549,"y":865,"w":261,"h":139,"rotated": false}},
|
{"SPRITE":{"name":"9","x":619,"y":1032,"w":205,"h":122,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0010","x":3209,"y":897,"w":202,"h":122,"rotated": false}},
|
{"SPRITE":{"name":"10","x":842,"y":1032,"w":205,"h":122,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0011","x":580,"y":913,"w":202,"h":122,"rotated": false}},
|
{"SPRITE":{"name":"11","x":2311,"y":558,"w":115,"h":112,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0012","x":2831,"y":304,"w":45,"h":42,"rotated": false}},
|
{"SPRITE":{"name":"12","x":2801,"y":947,"w":305,"h":172,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0013","x":1957,"y":505,"w":372,"h":311,"rotated": false}},
|
{"SPRITE":{"name":"13","x":2678,"y":0,"w":375,"h":314,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0014","x":1439,"y":516,"w":250,"h":325,"rotated": false}},
|
{"SPRITE":{"name":"14","x":2870,"y":332,"w":252,"h":328,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0015","x":716,"y":625,"w":235,"h":286,"rotated": false}},
|
{"SPRITE":{"name":"15","x":3071,"y":0,"w":239,"h":290,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0016","x":953,"y":625,"w":245,"h":249,"rotated": false}},
|
{"SPRITE":{"name":"16","x":3135,"y":678,"w":220,"h":246,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0017","x":3644,"y":373,"w":136,"h":133,"rotated": false}},
|
{"SPRITE":{"name":"17","x":3597,"y":248,"w":173,"h":231,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0018","x":2331,"y":735,"w":150,"h":91,"rotated": false}},
|
{"SPRITE":{"name":"18","x":3769,"y":0,"w":225,"h":190,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0019","x":3644,"y":508,"w":151,"h":95,"rotated": false}},
|
{"SPRITE":{"name":"19","x":1290,"y":1053,"w":131,"h":81,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0020","x":784,"y":913,"w":140,"h":90,"rotated": false}},
|
{"SPRITE":{"name":"20","x":3905,"y":814,"w":132,"h":85,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0021","x":3644,"y":605,"w":149,"h":92,"rotated": false}},
|
{"SPRITE":{"name":"21","x":1733,"y":1053,"w":122,"h":80,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0022","x":2670,"y":932,"w":144,"h":87,"rotated": false}},
|
{"SPRITE":{"name":"22","x":3905,"y":917,"w":129,"h":82,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0023","x":2670,"y":843,"w":152,"h":87,"rotated": false}},
|
{"SPRITE":{"name":"23","x":1589,"y":1053,"w":126,"h":78,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0024","x":4087,"y":2,"w":1,"h":4,"rotated": false}},
|
{"SPRITE":{"name":"24","x":1439,"y":1053,"w":132,"h":77,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0025","x":2831,"y":373,"w":411,"h":352,"rotated": false}},
|
{"SPRITE":{"name":"25","x":3778,"y":814,"w":109,"h":107,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0026","x":3244,"y":373,"w":398,"h":350,"rotated": false}},
|
{"SPRITE":{"name":"26","x":3124,"y":1123,"w":3,"h":7,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0027","x":266,"y":642,"w":329,"h":162,"rotated": false}},
|
{"SPRITE":{"name":"27","x":3145,"y":1123,"w":3,"h":7,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0028","x":597,"y":642,"w":90,"h":103,"rotated": false}},
|
{"SPRITE":{"name":"28","x":3673,"y":497,"w":260,"h":141,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0029","x":1200,"y":625,"w":211,"h":236,"rotated": false}},
|
{"SPRITE":{"name":"29","x":3788,"y":208,"w":237,"h":161,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0030","x":2831,"y":727,"w":208,"h":235,"rotated": false}},
|
{"SPRITE":{"name":"30","x":3542,"y":660,"w":218,"h":144,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0031","x":2483,"y":2,"w":738,"h":300,"rotated": false}},
|
{"SPRITE":{"name":"31","x":3124,"y":947,"w":301,"h":158,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0032","x":2483,"y":304,"w":346,"h":537,"rotated": false}},
|
{"SPRITE":{"name":"32","x":3371,"y":498,"w":284,"h":144,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0033","x":2,"y":865,"w":235,"h":158,"rotated": false}},
|
{"SPRITE":{"name":"33","x":0,"y":981,"w":295,"h":150,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0034","x":3812,"y":865,"w":216,"h":141,"rotated": false}},
|
{"SPRITE":{"name":"34","x":313,"y":981,"w":288,"h":145,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0035","x":2000,"y":818,"w":299,"h":155,"rotated": false}},
|
{"SPRITE":{"name":"35","x":3443,"y":942,"w":182,"h":212,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0036","x":1200,"y":863,"w":179,"h":208,"rotated": false}},
|
{"SPRITE":{"name":"36","x":3371,"y":255,"w":208,"h":225,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0037","x":1691,"y":818,"w":307,"h":154,"rotated": false}},
|
{"SPRITE":{"name":"37","x":3373,"y":660,"w":151,"h":264,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0038","x":3644,"y":702,"w":320,"h":161,"rotated": false}},
|
{"SPRITE":{"name":"38","x":3778,"y":656,"w":206,"h":140,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0039","x":266,"y":806,"w":312,"h":155,"rotated": false}},
|
{"SPRITE":{"name":"39","x":3557,"y":0,"w":194,"h":230,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0040","x":239,"y":963,"w":224,"h":108,"rotated": false}},
|
{"SPRITE":{"name":"40","x":2678,"y":485,"w":47,"h":44,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0041","x":3223,"y":2,"w":580,"h":369,"rotated": false}},
|
{"SPRITE":{"name":"41","x":2870,"y":678,"w":247,"h":251,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0042","x":3805,"y":2,"w":269,"h":698,"rotated": false}},
|
{"SPRITE":{"name":"42","x":2678,"y":332,"w":138,"h":135,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0043","x":1413,"y":843,"w":205,"h":222,"rotated": false}},
|
{"SPRITE":{"name":"43","x":1065,"y":1053,"w":207,"h":101,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0044","x":3041,"y":727,"w":166,"h":292,"rotated": false}},
|
{"SPRITE":{"name":"44","x":2452,"y":947,"w":331,"h":164,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0045","x":953,"y":876,"w":203,"h":137,"rotated": false}},
|
{"SPRITE":{"name":"45","x":2021,"y":720,"w":413,"h":354,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0046","x":1439,"y":2,"w":516,"h":512,"rotated": false}},
|
{"SPRITE":{"name":"46","x":2452,"y":558,"w":400,"h":353,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0047","x":2,"y":2,"w":712,"h":638,"rotated": false}},
|
{"SPRITE":{"name":"47","x":3951,"y":387,"w":90,"h":103,"rotated":false}},
|
||||||
{"SPRITE" : {"name": "0048","x":2301,"y":843,"w":192,"h":227,"rotated": false}}
|
{"SPRITE":{"name":"48","x":3140,"y":308,"w":213,"h":239,"rotated":false}},
|
||||||
]},
|
{"SPRITE":{"name":"49","x":3328,"y":0,"w":211,"h":237,"rotated":false}}]},
|
||||||
"meta": {
|
"meta":{
|
||||||
"app": "Adobe Animate",
|
"app":"Adobe Animate (Better TA Extension)",
|
||||||
"version": "21.0.1.37179",
|
"version":"24.0.2.12",
|
||||||
"image": "spritemap1.png",
|
"image":"spritemap1.png",
|
||||||
"format": "RGBA8888",
|
"format":"RGBA8888",
|
||||||
"size": {"w":4090,"h":1074},
|
"size":{"w":4061,"h":1154},
|
||||||
"resolution": "1"
|
"resolution":"1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 344 KiB After Width: | Height: | Size: 535 KiB |
@@ -433,6 +433,8 @@
|
|||||||
<str id="position">Position (X, Y)</str>
|
<str id="position">Position (X, Y)</str>
|
||||||
<str id="fps">FPS</str>
|
<str id="fps">FPS</str>
|
||||||
<str id="indices">Indices (Frames)</str>
|
<str id="indices">Indices (Frames)</str>
|
||||||
|
<str id="looping">Looping?</str>
|
||||||
|
<str id="label">Label</str>
|
||||||
</group>
|
</group>
|
||||||
|
|
||||||
<group name="CharacterSpriteScreen" prefix="characterSpriteScreen.">
|
<group name="CharacterSpriteScreen" prefix="characterSpriteScreen.">
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<print pretty="true">Preparing installation...</print>
|
<print pretty="true">Preparing installation...</print>
|
||||||
|
|
||||||
<!-- OpenFL & Lime (Required for Flixel) -->
|
<!-- OpenFL & Lime (Required for Flixel) -->
|
||||||
<git name="openfl" url="https://github.com/CodenameCrew/cne-openfl" />
|
<git name="openfl" url="https://github.com/CodenameCrew/cne-openfl" ref="old" />
|
||||||
<lib name="lime" version="8.1.2" />
|
<lib name="lime" version="8.1.2" />
|
||||||
<!-- <git name="lime" url="https://github.com/CodenameCrew/cne-lime" /> disabled for now until fixed -->
|
<!-- <git name="lime" url="https://github.com/CodenameCrew/cne-lime" /> disabled for now until fixed -->
|
||||||
|
|
||||||
@@ -14,11 +14,9 @@
|
|||||||
|
|
||||||
<!-- Other Libraries -->
|
<!-- Other Libraries -->
|
||||||
<git name="hscript-improved" url="https://github.com/CodenameCrew/hscript-improved" ref="codename-dev" />
|
<git name="hscript-improved" url="https://github.com/CodenameCrew/hscript-improved" ref="codename-dev" />
|
||||||
<git name="flxanimate" url="https://github.com/CodenameCrew/cne-flxanimate" />
|
|
||||||
<git name="hxdiscord_rpc" url="https://github.com/CodenameCrew/cne-hxdiscord_rpc" skipDeps="true" />
|
<git name="hxdiscord_rpc" url="https://github.com/CodenameCrew/cne-hxdiscord_rpc" skipDeps="true" />
|
||||||
<lib name="funkin-modchart" version="1.2.4" skipDeps="true" />
|
<lib name="funkin-modchart" version="1.2.4" skipDeps="true" />
|
||||||
<lib name="hxvlc" version="1.9.3" skipDeps="true" />
|
<lib name="hxvlc" version="1.9.3" skipDeps="true" />
|
||||||
<git name="bin-serializer" url="https://github.com/CodenameCrew/bin-serializer" />
|
|
||||||
|
|
||||||
<!-- Documentation and other features -->
|
<!-- Documentation and other features -->
|
||||||
<git name="away3d" url="https://github.com/CodenameCrew/away3d" />
|
<git name="away3d" url="https://github.com/CodenameCrew/away3d" />
|
||||||
@@ -33,6 +31,8 @@
|
|||||||
<lib global="true" name="format" /> <lib name="format" />
|
<lib global="true" name="format" /> <lib name="format" />
|
||||||
|
|
||||||
<git name="hxcpp" url="https://github.com/CodenameCrew/cne-hxcpp" />
|
<git name="hxcpp" url="https://github.com/CodenameCrew/cne-hxcpp" />
|
||||||
|
|
||||||
|
<git name="flixel-animate" url="https://github.com/MaybeMaru/flixel-animate/" skipDeps="true"/>
|
||||||
</if>
|
</if>
|
||||||
|
|
||||||
<!-- Hxcpp Building -->
|
<!-- Hxcpp Building -->
|
||||||
|
|||||||
@@ -3,20 +3,23 @@
|
|||||||
<!-- _________________________ Application Settings _________________________ -->
|
<!-- _________________________ Application Settings _________________________ -->
|
||||||
<app
|
<app
|
||||||
title="Friday Night Funkin' - Codename Engine" main="funkin.backend.system.Main"
|
title="Friday Night Funkin' - Codename Engine" main="funkin.backend.system.Main"
|
||||||
file="CodenameEngine" packageName="com.codenamecrew.codenameengine"
|
file="CodenameEngine" packageName="com.yoshman29.codenameengine"
|
||||||
package="com.codenamecrew.codenameengine"
|
package="com.yoshman29.codenameengine"
|
||||||
version="1.0.1" company="CodenameCrew" />
|
version="1.0.1" company="Yoshman29" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
CHANGE THE SAVE PATH & NAME FOR YOUR HARDCODED MOD HERE!
|
CHANGE THE SAVE PATH & NAME FOR YOUR MOD HERE!
|
||||||
-->
|
-->
|
||||||
<haxedef name="SAVE_PATH" value="CodenameCrew/CodenameEngine"/>
|
<haxedef name="SAVE_PATH" value="CodenameEngine"/>
|
||||||
<haxedef name="SAVE_NAME" value="save-default"/>
|
<haxedef name="SAVE_NAME" value="save-default"/>
|
||||||
|
|
||||||
|
<haxedef name="SAVE_OPTIONS_PATH" value="CodenameEngine"/>
|
||||||
|
<haxedef name="SAVE_OPTIONS_NAME" value="options"/>
|
||||||
|
|
||||||
<!--Switch Export with Unique ApplicationID and Icon-->
|
<!--Switch Export with Unique ApplicationID and Icon-->
|
||||||
<set name="APP_ID" value="0x0100f6c013bbc000" />
|
<set name="APP_ID" value="0x0100f6c013bbc000" />
|
||||||
|
|
||||||
<!-- DO NOT REMOVE!! ALLOWS ME TO DO REGIONS LIKE IN C# AND KEEP CODE ORGANIZED. REMOVING IT WOULD BREAK THE ENGINE -->
|
<!-- DO NOT REMOVE!! -->
|
||||||
<haxedef name="REGION" />
|
<haxedef name="REGION" />
|
||||||
|
|
||||||
<!--The flixel preloader is not accurate in Chrome. You can use it regularly if you embed the swf into a html file
|
<!--The flixel preloader is not accurate in Chrome. You can use it regularly if you embed the swf into a html file
|
||||||
@@ -69,7 +72,11 @@
|
|||||||
|
|
||||||
<!-- Comment this out to prevent extending classes in hscript.
|
<!-- Comment this out to prevent extending classes in hscript.
|
||||||
Reduces compilation time at the cost of limited HScript flexibility. !-->
|
Reduces compilation time at the cost of limited HScript flexibility. !-->
|
||||||
<define name="CUSTOM_CLASSES" unless="STRIPPED_COMPILE" />
|
<define name="CUSTOM_CLASSES" unless="STRIPPED_COMPILE"/>
|
||||||
|
|
||||||
|
<!-- Comment this out to disable support for abstracts in hscript.
|
||||||
|
Reduces compilation time at the cost of limited HScript flexibility. !-->
|
||||||
|
<define name="HSCRIPT_ABSTRACT_SUPPORT" unless="STRIPPED_COMPILE"/>
|
||||||
|
|
||||||
<!-- Comment this out to disable multithreading !-->
|
<!-- Comment this out to disable multithreading !-->
|
||||||
<haxedef name="ALLOW_MULTITHREADING" unless="web || flash" />
|
<haxedef name="ALLOW_MULTITHREADING" unless="web || flash" />
|
||||||
@@ -112,6 +119,24 @@
|
|||||||
<!-- Disable a optimization, to allow reflection to use more functions -->
|
<!-- Disable a optimization, to allow reflection to use more functions -->
|
||||||
<define name="FLX_NO_GENERIC" />
|
<define name="FLX_NO_GENERIC" />
|
||||||
|
|
||||||
|
<!-- _______________________________ Display Server ______________________________ -->
|
||||||
|
|
||||||
|
<haxedef name="LIME_CMD" value="${project.command}"/>
|
||||||
|
<define name="LIME_DISPLAY" if="${project.command == update} || ${project.command == display} || display || display_details" />
|
||||||
|
<haxedef name="LIME_DISPLAY" if="LIME_DISPLAY" />
|
||||||
|
|
||||||
|
<section if="LIME_DISPLAY">
|
||||||
|
<!-- For display server -->
|
||||||
|
<undefine name="COMPILE_ALL_CLASSES" />
|
||||||
|
<unset name="COMPILE_ALL_CLASSES" />
|
||||||
|
|
||||||
|
<undefine name="HSCRIPT_ABSTRACT_SUPPORT" />
|
||||||
|
<unset name="HSCRIPT_ABSTRACT_SUPPORT" />
|
||||||
|
|
||||||
|
<undefine name="CUSTOM_CLASSES" />
|
||||||
|
<unset name="CUSTOM_CLASSES" />
|
||||||
|
</section>
|
||||||
|
|
||||||
<!-- _______________________________ Libraries ______________________________ -->
|
<!-- _______________________________ Libraries ______________________________ -->
|
||||||
|
|
||||||
<!-- KEEP BOTH OF THESE AS THERE ARE SOME PARTICULAR CASES! -->
|
<!-- KEEP BOTH OF THESE AS THERE ARE SOME PARTICULAR CASES! -->
|
||||||
@@ -127,8 +152,7 @@
|
|||||||
<haxelib name="hxvlc" if="VIDEO_CUTSCENES" />
|
<haxelib name="hxvlc" if="VIDEO_CUTSCENES" />
|
||||||
<haxelib name="away3d" if="THREE_D_SUPPORT" />
|
<haxelib name="away3d" if="THREE_D_SUPPORT" />
|
||||||
<haxelib name="format" />
|
<haxelib name="format" />
|
||||||
<haxelib name="flxanimate" />
|
<haxelib name="flixel-animate" />
|
||||||
<haxelib name="bin-serializer" />
|
|
||||||
<haxelib name="nape-haxe4" if="NAPE_ENABLED"/>
|
<haxelib name="nape-haxe4" if="NAPE_ENABLED"/>
|
||||||
|
|
||||||
<haxelib name="hscript-improved" />
|
<haxelib name="hscript-improved" />
|
||||||
@@ -170,7 +194,7 @@
|
|||||||
|
|
||||||
<!-- ______________________________ Haxedefines _____________________________ -->
|
<!-- ______________________________ Haxedefines _____________________________ -->
|
||||||
|
|
||||||
<haxeflag name="--macro" value="funkin.backend.system.macros.BuildInfo.printBuildInfo()" />
|
<haxeflag name="--macro" value="funkin.backend.system.macros.BuildInfo.printBuildInfo()" unless="display" />
|
||||||
|
|
||||||
<haxedef name="FLX_NO_FOCUS_LOST_SCREEN" />
|
<haxedef name="FLX_NO_FOCUS_LOST_SCREEN" />
|
||||||
|
|
||||||
@@ -217,8 +241,10 @@
|
|||||||
<haxeflag name="--macro" value="modchart.backend.macros.Macro.includeFiles()"/>
|
<haxeflag name="--macro" value="modchart.backend.macros.Macro.includeFiles()"/>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
||||||
<section if="COMPILE_ALL_CLASSES">
|
<section if="COMPILE_ALL_CLASSES">
|
||||||
<haxeflag name="-dce" value="no" />
|
<haxeflag name="-dce" value="no" />
|
||||||
|
|
||||||
<haxeflag name="--macro" value="funkin.backend.system.macros.Macros.addAdditionalClasses()" />
|
<haxeflag name="--macro" value="funkin.backend.system.macros.Macros.addAdditionalClasses()" />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -1,92 +0,0 @@
|
|||||||
package funkin.backend;
|
|
||||||
|
|
||||||
import flixel.graphics.frames.FlxFrame;
|
|
||||||
import flixel.math.FlxAngle;
|
|
||||||
import flixel.math.FlxMatrix;
|
|
||||||
import openfl.display.BlendMode;
|
|
||||||
import openfl.geom.ColorTransform;
|
|
||||||
|
|
||||||
class FlxAnimate extends flxanimate.FlxAnimate {
|
|
||||||
static var rMatrix = new FlxMatrix();
|
|
||||||
|
|
||||||
override function drawLimb(limb:FlxFrame, _rMatrix:FlxMatrix, ?colorTransform:ColorTransform, ?blendMode:BlendMode)
|
|
||||||
{
|
|
||||||
if (alpha == 0 || colorTransform != null && (colorTransform.alphaMultiplier == 0 || colorTransform.alphaOffset == -255) || limb == null || limb.type == EMPTY)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (blendMode == null)
|
|
||||||
blendMode = BlendMode.NORMAL;
|
|
||||||
|
|
||||||
for (camera in cameras)
|
|
||||||
{
|
|
||||||
rMatrix.identity();
|
|
||||||
limb.prepareMatrix(rMatrix, FlxFrameAngle.ANGLE_0, _checkFlipX() != camera.flipX, _checkFlipY() != camera.flipY);
|
|
||||||
rMatrix.concat(_rMatrix);
|
|
||||||
if (!camera.visible || !camera.exists || !limbOnScreen(limb, _rMatrix, camera))
|
|
||||||
return;
|
|
||||||
|
|
||||||
getScreenPosition(_point, camera).subtractPoint(offset);
|
|
||||||
rMatrix.translate(-origin.x, -origin.y);
|
|
||||||
if (limb != _pivot) {
|
|
||||||
if (frameOffsetAngle != null && frameOffsetAngle != angle)
|
|
||||||
{
|
|
||||||
var angleOff = (frameOffsetAngle - angle) * FlxAngle.TO_RAD;
|
|
||||||
var cos = Math.cos(angleOff);
|
|
||||||
var sin = Math.sin(angleOff);
|
|
||||||
// cos doesn't need to be negated
|
|
||||||
rMatrix.rotateWithTrig(cos, -sin);
|
|
||||||
rMatrix.translate(-frameOffset.x, -frameOffset.y);
|
|
||||||
rMatrix.rotateWithTrig(cos, sin);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rMatrix.translate(-frameOffset.x, -frameOffset.y);
|
|
||||||
}
|
|
||||||
rMatrix.scale(scale.x, scale.y);
|
|
||||||
|
|
||||||
if (!matrixExposed && bakedRotationAngle <= 0)
|
|
||||||
{
|
|
||||||
updateTrig();
|
|
||||||
|
|
||||||
if (angle != 0)
|
|
||||||
rMatrix.rotateWithTrig(_cosAngle, _sinAngle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
rMatrix.a = rMatrix.d = 0.7 / camera.zoom;
|
|
||||||
|
|
||||||
if (matrixExposed)
|
|
||||||
{
|
|
||||||
rMatrix.concat(transformMatrix);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
rMatrix.concat(@:privateAccess flxanimate.FlxAnimate._skewMatrix);
|
|
||||||
}
|
|
||||||
|
|
||||||
_point.addPoint(origin);
|
|
||||||
if (isPixelPerfectRender(camera))
|
|
||||||
{
|
|
||||||
_point.floor();
|
|
||||||
}
|
|
||||||
|
|
||||||
rMatrix.translate(_point.x, _point.y);
|
|
||||||
camera.drawPixels(limb, null, rMatrix, colorTransform, blendMode, antialiasing, shaderEnabled ? shader : null);
|
|
||||||
#if FLX_DEBUG
|
|
||||||
FlxBasic.visibleCount++;
|
|
||||||
#end
|
|
||||||
}
|
|
||||||
|
|
||||||
// doesn't work, needs to be remade
|
|
||||||
// #if FLX_DEBUG
|
|
||||||
// if (FlxG.debugger.drawDebug)
|
|
||||||
// drawDebug();
|
|
||||||
// #end
|
|
||||||
}
|
|
||||||
|
|
||||||
override function limbOnScreen(limb:FlxFrame, m:FlxMatrix, ?Camera:FlxCamera)
|
|
||||||
{
|
|
||||||
// TODO: ACTUAL OPTIMIZATION
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,7 @@
|
|||||||
package funkin.backend;
|
package funkin.backend;
|
||||||
|
|
||||||
|
import animate.FlxAnimate;
|
||||||
|
import animate.FlxAnimateController.FlxAnimateAnimation;
|
||||||
import flixel.addons.effects.FlxSkewedSprite;
|
import flixel.addons.effects.FlxSkewedSprite;
|
||||||
import flixel.animation.FlxAnimation;
|
import flixel.animation.FlxAnimation;
|
||||||
import flixel.math.FlxMatrix;
|
import flixel.math.FlxMatrix;
|
||||||
@@ -7,7 +9,6 @@ import flixel.math.FlxPoint;
|
|||||||
import flixel.math.FlxRect;
|
import flixel.math.FlxRect;
|
||||||
import flixel.system.FlxAssets.FlxGraphicAsset;
|
import flixel.system.FlxAssets.FlxGraphicAsset;
|
||||||
import flixel.util.typeLimit.OneOfTwo;
|
import flixel.util.typeLimit.OneOfTwo;
|
||||||
import flxanimate.animate.FlxAnim.FlxSymbolAnimation;
|
|
||||||
import funkin.backend.scripting.events.sprite.PlayAnimContext;
|
import funkin.backend.scripting.events.sprite.PlayAnimContext;
|
||||||
import funkin.backend.system.interfaces.IBeatReceiver;
|
import funkin.backend.system.interfaces.IBeatReceiver;
|
||||||
import funkin.backend.system.interfaces.IOffsetCompatible;
|
import funkin.backend.system.interfaces.IOffsetCompatible;
|
||||||
@@ -15,6 +16,10 @@ import funkin.backend.utils.XMLUtil.AnimData;
|
|||||||
import funkin.backend.utils.XMLUtil.BeatAnim;
|
import funkin.backend.utils.XMLUtil.BeatAnim;
|
||||||
import funkin.backend.utils.XMLUtil.IXMLEvents;
|
import funkin.backend.utils.XMLUtil.IXMLEvents;
|
||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
|
import flixel.graphics.frames.FlxFrame;
|
||||||
|
import flixel.math.FlxAngle;
|
||||||
|
import animate.internal.RenderTexture;
|
||||||
|
import animate.FlxAnimateFrames;
|
||||||
|
|
||||||
enum abstract XMLAnimType(Int)
|
enum abstract XMLAnimType(Int)
|
||||||
{
|
{
|
||||||
@@ -43,7 +48,7 @@ enum abstract XMLAnimType(Int)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements IOffsetCompatible implements IXMLEvents
|
class FunkinSprite extends FlxAnimate implements IBeatReceiver implements IOffsetCompatible implements IXMLEvents
|
||||||
{
|
{
|
||||||
public var extra:Map<String, Dynamic> = [];
|
public var extra:Map<String, Dynamic> = [];
|
||||||
|
|
||||||
@@ -56,6 +61,9 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
public var animEnabled:Bool = true;
|
public var animEnabled:Bool = true;
|
||||||
public var zoomFactorEnabled:Bool = true;
|
public var zoomFactorEnabled:Bool = true;
|
||||||
|
|
||||||
|
//Backwards compatibility
|
||||||
|
public var animateAtlas(get, never):FunkinSprite;
|
||||||
|
|
||||||
public var globalCurFrame(get, set):Int;
|
public var globalCurFrame(get, set):Int;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -66,9 +74,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
public var beatOffset:Int = 0;
|
public var beatOffset:Int = 0;
|
||||||
public var skipNegativeBeats:Bool = false;
|
public var skipNegativeBeats:Bool = false;
|
||||||
|
|
||||||
public var animateAtlas:FlxAnimate;
|
public var animateSettings:FlxAnimateSettings = {};
|
||||||
@:noCompletion public var atlasPlayingAnim:String;
|
|
||||||
@:noCompletion public var atlasPath:String;
|
|
||||||
|
|
||||||
var _rect2:FlxRect;
|
var _rect2:FlxRect;
|
||||||
|
|
||||||
@@ -85,6 +91,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
}
|
}
|
||||||
|
|
||||||
moves = false;
|
moves = false;
|
||||||
|
applyStageMatrix = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -100,8 +107,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
@:privateAccess {
|
@:privateAccess {
|
||||||
spr.setPosition(source.x, source.y);
|
spr.setPosition(source.x, source.y);
|
||||||
spr.frames = source.frames;
|
spr.frames = source.frames;
|
||||||
if (casted != null && casted.animateAtlas != null && casted.atlasPath != null)
|
|
||||||
spr.loadSprite(casted.atlasPath);
|
|
||||||
spr.animation.copyFrom(source.animation);
|
spr.animation.copyFrom(source.animation);
|
||||||
spr.visible = source.visible;
|
spr.visible = source.visible;
|
||||||
spr.alpha = source.alpha;
|
spr.alpha = source.alpha;
|
||||||
@@ -111,8 +116,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
|
|
||||||
if (casted != null) {
|
if (casted != null) {
|
||||||
spr.skew.set(casted.skew.x, casted.skew.y);
|
spr.skew.set(casted.skew.x, casted.skew.y);
|
||||||
spr.transformMatrix = casted.transformMatrix;
|
|
||||||
spr.matrixExposed = casted.matrixExposed;
|
|
||||||
spr.animOffsets = casted.animOffsets.copy();
|
spr.animOffsets = casted.animOffsets.copy();
|
||||||
spr.zoomFactor = casted.zoomFactor;
|
spr.zoomFactor = casted.zoomFactor;
|
||||||
}
|
}
|
||||||
@@ -123,8 +126,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
public override function update(elapsed:Float)
|
public override function update(elapsed:Float)
|
||||||
{
|
{
|
||||||
super.update(elapsed);
|
super.update(elapsed);
|
||||||
if (animateAtlas != null)
|
|
||||||
animateAtlas.update(elapsed);
|
|
||||||
|
|
||||||
// hate how it looks like but hey at least its optimized and fast - Nex
|
// hate how it looks like but hey at least its optimized and fast - Nex
|
||||||
if (!debugMode && isAnimFinished()) {
|
if (!debugMode && isAnimFinished()) {
|
||||||
@@ -142,15 +143,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
public function loadSprite(path:String, Unique:Bool = false, Key:String = null)
|
public function loadSprite(path:String, Unique:Bool = false, Key:String = null)
|
||||||
{
|
{
|
||||||
var noExt = Path.withoutExtension(path);
|
var noExt = Path.withoutExtension(path);
|
||||||
if (Assets.exists('$noExt/Animation.json'))
|
frames = Paths.getFrames(path, true, null, null, animateSettings);
|
||||||
{
|
|
||||||
atlasPath = noExt;
|
|
||||||
animateAtlas = new FlxAnimate(x, y, noExt);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
frames = Paths.getFrames(path, true);
|
|
||||||
}
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -182,48 +175,9 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
|
|
||||||
// ANIMATE ATLAS DRAWING
|
// ANIMATE ATLAS DRAWING
|
||||||
#if REGION
|
#if REGION
|
||||||
public override function draw()
|
|
||||||
{
|
|
||||||
if (animateAtlas != null)
|
|
||||||
{
|
|
||||||
copyAtlasValues();
|
|
||||||
animateAtlas.draw();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
super.draw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function copyAtlasValues()
|
|
||||||
{
|
|
||||||
@:privateAccess {
|
|
||||||
animateAtlas.cameras = cameras; // investigate if we can use _cameras
|
|
||||||
animateAtlas.scrollFactor = scrollFactor;
|
|
||||||
animateAtlas.scale = scale;
|
|
||||||
animateAtlas.offset = offset;
|
|
||||||
animateAtlas.frameOffset = frameOffset;
|
|
||||||
animateAtlas.x = x;
|
|
||||||
animateAtlas.y = y;
|
|
||||||
animateAtlas.angle = angle;
|
|
||||||
animateAtlas.alpha = alpha;
|
|
||||||
animateAtlas.visible = visible;
|
|
||||||
animateAtlas.flipX = flipX;
|
|
||||||
animateAtlas.flipY = flipY;
|
|
||||||
animateAtlas.shader = shader;
|
|
||||||
animateAtlas.shaderEnabled = shaderEnabled;
|
|
||||||
animateAtlas.antialiasing = antialiasing;
|
|
||||||
animateAtlas.skew = skew;
|
|
||||||
animateAtlas.transformMatrix = transformMatrix;
|
|
||||||
animateAtlas.matrixExposed = matrixExposed;
|
|
||||||
animateAtlas.colorTransform = colorTransform;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override function destroy()
|
public override function destroy()
|
||||||
{
|
{
|
||||||
animateAtlas = FlxDestroyUtil.destroy(animateAtlas);
|
|
||||||
|
|
||||||
if (animOffsets != null) {
|
if (animOffsets != null) {
|
||||||
for (key in animOffsets.keys()) {
|
for (key in animOffsets.keys()) {
|
||||||
final point = animOffsets[key];
|
final point = animOffsets[key];
|
||||||
@@ -260,25 +214,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override function getScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect
|
|
||||||
{
|
|
||||||
if (camera == null)
|
|
||||||
camera = FlxG.camera;
|
|
||||||
|
|
||||||
newRect = super.getScreenBounds(newRect, camera);
|
|
||||||
|
|
||||||
if(__shouldDoZoomFactor()) {
|
|
||||||
__prepareZoomFactor(_rect2, camera);
|
|
||||||
newRect.set(
|
|
||||||
(newRect.x - _rect2.x) * _rect2.width + _rect2.x,
|
|
||||||
(newRect.y - _rect2.y) * _rect2.height + _rect2.y,
|
|
||||||
newRect.width * _rect2.width,
|
|
||||||
newRect.height * _rect2.height,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return newRect;
|
|
||||||
}
|
|
||||||
|
|
||||||
override public function isOnScreen(?camera:FlxCamera):Bool
|
override public function isOnScreen(?camera:FlxCamera):Bool
|
||||||
{
|
{
|
||||||
if (forceIsOnScreen)
|
if (forceIsOnScreen)
|
||||||
@@ -293,22 +228,6 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
return camera.containsRect(bounds);
|
return camera.containsRect(bounds);
|
||||||
}
|
}
|
||||||
|
|
||||||
// ZOOM FACTOR RENDERING
|
|
||||||
public override function doAdditionalMatrixStuff(matrix:FlxMatrix, camera:FlxCamera)
|
|
||||||
{
|
|
||||||
// no need to...
|
|
||||||
//super.doAdditionalMatrixStuff(matrix, camera);
|
|
||||||
if(__shouldDoZoomFactor()) {
|
|
||||||
__prepareZoomFactor(_rect, camera);
|
|
||||||
matrix.setTo(
|
|
||||||
matrix.a * _rect.width, matrix.b * _rect.height,
|
|
||||||
matrix.c * _rect.width, matrix.d * _rect.height,
|
|
||||||
(matrix.tx - _rect.x) * _rect.width + _rect.x,
|
|
||||||
(matrix.ty - _rect.y) * _rect.height + _rect.y,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OFFSETTING
|
// OFFSETTING
|
||||||
#if REGION
|
#if REGION
|
||||||
public var animOffsets:Map<String, FlxPoint> = new Map<String, FlxPoint>();
|
public var animOffsets:Map<String, FlxPoint> = new Map<String, FlxPoint>();
|
||||||
@@ -340,13 +259,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
Force = anim != null && anim.forced;
|
Force = anim != null && anim.forced;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animateAtlas != null)
|
animation.play(AnimName, Force, Reversed, Frame);
|
||||||
{
|
|
||||||
@:privateAccess
|
|
||||||
animateAtlas.anim.play(AnimName, Force, Reversed, Frame);
|
|
||||||
atlasPlayingAnim = AnimName;
|
|
||||||
}
|
|
||||||
else animation.play(AnimName, Force, Reversed, Frame);
|
|
||||||
|
|
||||||
var daOffset = getAnimOffset(AnimName);
|
var daOffset = getAnimOffset(AnimName);
|
||||||
frameOffset.set(daOffset.x, daOffset.y);
|
frameOffset.set(daOffset.x, daOffset.y);
|
||||||
@@ -355,7 +268,7 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
lastAnimContext = Context;
|
lastAnimContext = Context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline function addAnim(name:String, prefix:String, frameRate:Float = 24, ?looped:Bool, ?forced:Bool, ?indices:Array<Int>, x:Float = 0, y:Float = 0, animType:XMLAnimType = NONE)
|
public inline function addAnim(name:String, prefix:String, frameRate:Float = 24, ?looped:Bool, ?forced:Bool, ?indices:Array<Int>, x:Float = 0, y:Float = 0, animType:XMLAnimType = NONE, animateAtlasLabel:Bool = false)
|
||||||
{
|
{
|
||||||
return XMLUtil.addAnimToSprite(this, {
|
return XMLUtil.addAnimToSprite(this, {
|
||||||
name: name,
|
name: name,
|
||||||
@@ -366,22 +279,16 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
indices: indices,
|
indices: indices,
|
||||||
forced: forced
|
forced: forced,
|
||||||
|
label: animateAtlasLabel
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline function removeAnim(name:String)
|
public inline function removeAnim(name:String) {
|
||||||
{
|
animation.remove(name);
|
||||||
if (animateAtlas != null)
|
|
||||||
@:privateAccess animateAtlas.anim.animsMap.remove(name);
|
|
||||||
else
|
|
||||||
animation.remove(name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getAnim(name:String):OneOfTwo<FlxAnimation, FlxSymbolAnimation>
|
public function getAnim(name:String):OneOfTwo<FlxAnimation, FlxAnimateAnimation> {
|
||||||
{
|
|
||||||
if(animateAtlas != null)
|
|
||||||
return animateAtlas.anim.getByName(name);
|
|
||||||
return animation.getByName(name);
|
return animation.getByName(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,40 +299,26 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
return FlxPoint.weak(0, 0);
|
return FlxPoint.weak(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline function hasAnim(AnimName:String):Bool @:privateAccess
|
public inline function hasAnim(AnimName:String):Bool
|
||||||
return animateAtlas != null ? (animateAtlas.anim.animsMap.exists(AnimName)
|
return animation.exists(AnimName);
|
||||||
|| animateAtlas.anim.symbolDictionary.exists(AnimName)) : animation.exists(AnimName);
|
|
||||||
|
|
||||||
public inline function getAnimName() {
|
public inline function getAnimName()
|
||||||
return (animateAtlas != null) ? atlasPlayingAnim : animation.name;
|
return animation.name;
|
||||||
}
|
|
||||||
|
|
||||||
public inline function isAnimReversed():Bool {
|
public inline function isAnimReversed():Bool
|
||||||
return animateAtlas != null ? animateAtlas.anim.reversed : animation.curAnim != null ? animation.curAnim.reversed : false;
|
return animation.curAnim?.reversed ?? false;
|
||||||
}
|
|
||||||
|
|
||||||
public inline function getNameList():Array<String> {
|
public inline function getNameList():Array<String>
|
||||||
if (animateAtlas != null)
|
return animation.getNameList();
|
||||||
return [for (name in @:privateAccess animateAtlas.anim.animsMap.keys()) name];
|
|
||||||
else
|
|
||||||
return animation.getNameList();
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function stopAnim()
|
public inline function stopAnim()
|
||||||
{
|
animation.stop();
|
||||||
if (animateAtlas != null)
|
|
||||||
animateAtlas.anim.pause();
|
|
||||||
else
|
|
||||||
animation.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function isAnimFinished() {
|
public inline function isAnimFinished()
|
||||||
return animateAtlas != null ? animateAtlas.anim.finished : (animation.curAnim != null ? animation.curAnim.finished : true);
|
return animation.curAnim?.finished ?? true;
|
||||||
}
|
|
||||||
|
|
||||||
public inline function isAnimAtEnd() {
|
public inline function isAnimAtEnd()
|
||||||
return animateAtlas != null ? animateAtlas.anim.isAtEnd : (animation.curAnim != null ? animation.curAnim.isAtEnd : false);
|
return animation.curAnim?.isAtEnd ?? false;
|
||||||
}
|
|
||||||
|
|
||||||
override function updateAnimation(elapsed:Float) {
|
override function updateAnimation(elapsed:Float) {
|
||||||
if (animEnabled)
|
if (animEnabled)
|
||||||
@@ -447,10 +340,59 @@ class FunkinSprite extends FlxSkewedSprite implements IBeatReceiver implements I
|
|||||||
return beatInterval = v;
|
return beatInterval = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
@:noCompletion private inline function get_globalCurFrame() {
|
@:noCompletion
|
||||||
return animateAtlas != null ? (animateAtlas.anim.curFrame) : (animation.curAnim != null ? animation.curAnim.curFrame : 0);
|
@:deprecated("`FunkinSprite.animateAtlas` is deprecated, just use `FunkinSprite` instead")
|
||||||
}
|
public function get_animateAtlas():FunkinSprite
|
||||||
|
return isAnimate ? this : null;
|
||||||
|
|
||||||
|
@:noCompletion private inline function get_globalCurFrame()
|
||||||
|
return animation.curAnim?.curFrame ?? 0;
|
||||||
|
|
||||||
@:noCompletion private inline function set_globalCurFrame(val:Int) {
|
@:noCompletion private inline function set_globalCurFrame(val:Int) {
|
||||||
return animateAtlas != null ? (animateAtlas.anim.curFrame = val) : (animation.curAnim != null ? animation.curAnim.curFrame = val : val);
|
if (animation.curAnim != null)
|
||||||
|
animation.curAnim.curFrame = val;
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
override function prepareDrawMatrix(matrix:FlxMatrix, camera:FlxCamera):Void {
|
||||||
|
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.translate(origin.x, origin.y);
|
||||||
|
|
||||||
|
super.prepareDrawMatrix(matrix, camera);
|
||||||
|
|
||||||
|
applyZoomFactor(matrix, camera);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyZoomFactor(matrix:FlxMatrix, camera:FlxCamera) {
|
||||||
|
if(__shouldDoZoomFactor()) {
|
||||||
|
__prepareZoomFactor(_rect2, camera);
|
||||||
|
matrix.setTo(
|
||||||
|
matrix.a * _rect2.width, matrix.b * _rect2.height,
|
||||||
|
matrix.c * _rect2.width, matrix.d * _rect2.height,
|
||||||
|
(matrix.tx - _rect2.x) * _rect2.width + _rect2.x,
|
||||||
|
(matrix.ty - _rect2.y) * _rect2.height + _rect2.y,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override function checkFlipX() {
|
||||||
|
return super.checkFlipX() != camera.flipX;
|
||||||
|
}
|
||||||
|
override function checkFlipY() {
|
||||||
|
return super.checkFlipY() != camera.flipY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -114,12 +114,8 @@ class MusicBeatTransition extends MusicBeatSubstate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (transitionSprite != null) {
|
if (transitionSprite != null) {
|
||||||
if (transitionSprite.animateAtlas == null) {
|
transitionSprite.setGraphicSize(transitionCamera.width, transitionCamera.height);
|
||||||
transitionSprite.setGraphicSize(transitionCamera.width, transitionCamera.height);
|
transitionSprite.updateHitbox();
|
||||||
transitionSprite.updateHitbox();
|
|
||||||
} else {
|
|
||||||
transitionSprite.screenCenter();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import funkin.backend.assets.TranslatedAssetLibrary;
|
|||||||
#end
|
#end
|
||||||
import funkin.backend.assets.IModsAssetLibrary;
|
import funkin.backend.assets.IModsAssetLibrary;
|
||||||
import lime.utils.AssetLibrary;
|
import lime.utils.AssetLibrary;
|
||||||
|
import haxe.ds.Map;
|
||||||
|
|
||||||
class AssetsLibraryList extends AssetLibrary {
|
class AssetsLibraryList extends AssetLibrary {
|
||||||
public var libraries:Array<AssetLibrary> = [];
|
public var libraries:Array<AssetLibrary> = [];
|
||||||
@@ -141,6 +142,16 @@ class AssetsLibraryList extends AssetLibrary {
|
|||||||
public override inline function getAsset(id:String, type:String):Dynamic
|
public override inline function getAsset(id:String, type:String):Dynamic
|
||||||
return getSpecificAsset(id, type, BOTH);
|
return getSpecificAsset(id, type, BOTH);
|
||||||
|
|
||||||
|
public override function list(type:String):Array<String> {
|
||||||
|
// idk if there's a more efficient way tbh, correct if u find better
|
||||||
|
var files:Map<String, Bool> = [];
|
||||||
|
for(k=>l in libraries) {
|
||||||
|
for(f in l.list(type))
|
||||||
|
files.set(f, false);
|
||||||
|
}
|
||||||
|
return [for(k=>e in files) k];
|
||||||
|
}
|
||||||
|
|
||||||
public override function isLocal(id:String, type:String) {
|
public override function isLocal(id:String, type:String) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -149,6 +149,22 @@ class ModsFolderLibrary extends AssetLibrary implements IModsAssetLibrary {
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override function list(type:String):Array<String> {
|
||||||
|
var result = [];
|
||||||
|
__listAppend(result, '');
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function __listAppend(arr:Array<String>, folder:String) {
|
||||||
|
for(file in FileSystem.readDirectory('$basePath/$folder')) {
|
||||||
|
var fullPath = '$basePath/$folder/$file';
|
||||||
|
if (FileSystem.isDirectory(fullPath))
|
||||||
|
__listAppend(arr, '$folder$file/');
|
||||||
|
else
|
||||||
|
arr.push('$prefix$folder$file');
|
||||||
|
}
|
||||||
|
}
|
||||||
#end
|
#end
|
||||||
|
|
||||||
// Backwards compat
|
// Backwards compat
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import funkin.backend.scripting.Script;
|
|||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
import lime.utils.AssetLibrary;
|
import lime.utils.AssetLibrary;
|
||||||
import openfl.utils.Assets as OpenFlAssets;
|
import openfl.utils.Assets as OpenFlAssets;
|
||||||
|
import animate.FlxAnimateFrames;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
@@ -174,6 +175,9 @@ class Paths
|
|||||||
inline static public function getSparrowAtlas(key:String, ?library:String, ?ext:String)
|
inline static public function getSparrowAtlas(key:String, ?library:String, ?ext:String)
|
||||||
return FlxAtlasFrames.fromSparrow(image(key, library, ext), file('images/$key.xml', library));
|
return FlxAtlasFrames.fromSparrow(image(key, library, ext), file('images/$key.xml', library));
|
||||||
|
|
||||||
|
inline static public function getAnimateAtlasAlt(key:String, ?settings:FlxAnimateSettings)
|
||||||
|
return FlxAnimateFrames.fromAnimate(key, null, null, null, false, settings);
|
||||||
|
|
||||||
inline static public function getSparrowAtlasAlt(key:String, ?ext:String)
|
inline static public function getSparrowAtlasAlt(key:String, ?ext:String)
|
||||||
return FlxAtlasFrames.fromSparrow('$key.${ext != null ? ext : Flags.IMAGE_EXT}', '$key.xml');
|
return FlxAtlasFrames.fromSparrow('$key.${ext != null ? ext : Flags.IMAGE_EXT}', '$key.xml');
|
||||||
|
|
||||||
@@ -197,7 +201,7 @@ class Paths
|
|||||||
* @param key Path to the frames
|
* @param key Path to the frames
|
||||||
* @param library (Additional) library to load the frames from.
|
* @param library (Additional) library to load the frames from.
|
||||||
*/
|
*/
|
||||||
public static function getFrames(key:String, assetsPath:Bool = false, ?library:String, ?ext:String = null) {
|
public static function getFrames(key:String, assetsPath:Bool = false, ?library:String, ?ext:String = null, ?animateSettings:FlxAnimateSettings) {
|
||||||
if (tempFramesCache.exists(key)) {
|
if (tempFramesCache.exists(key)) {
|
||||||
var frames = tempFramesCache[key];
|
var frames = tempFramesCache[key];
|
||||||
if (frames != null && frames.parent != null && frames.parent.bitmap != null && frames.parent.bitmap.readable)
|
if (frames != null && frames.parent != null && frames.parent.bitmap != null && frames.parent.bitmap.readable)
|
||||||
@@ -205,7 +209,7 @@ class Paths
|
|||||||
else
|
else
|
||||||
tempFramesCache.remove(key);
|
tempFramesCache.remove(key);
|
||||||
}
|
}
|
||||||
return tempFramesCache[key] = loadFrames(assetsPath ? key : Paths.image(key, library, true, ext), false, null, false, ext);
|
return tempFramesCache[key] = loadFrames(assetsPath ? key : Paths.image(key, library, true, ext), false, null, false, ext, animateSettings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -242,7 +246,7 @@ class Paths
|
|||||||
* @param Ext Extension of the image.
|
* @param Ext Extension of the image.
|
||||||
* @return FlxFramesCollection Frames
|
* @return FlxFramesCollection Frames
|
||||||
*/
|
*/
|
||||||
static function loadFrames(path:String, Unique:Bool = false, Key:String = null, SkipAtlasCheck:Bool = false, SkipMultiCheck:Bool = false, ?Ext:String = null):FlxFramesCollection {
|
static function loadFrames(path:String, Unique:Bool = false, Key:String = null, SkipAtlasCheck:Bool = false, SkipMultiCheck:Bool = false, ?Ext:String = null, ?animateSettings:FlxAnimateSettings):FlxFramesCollection {
|
||||||
var noExt = Path.withoutExtension(path);
|
var noExt = Path.withoutExtension(path);
|
||||||
var ext = Ext != null ? Ext : Flags.IMAGE_EXT;
|
var ext = Ext != null ? Ext : Flags.IMAGE_EXT;
|
||||||
|
|
||||||
@@ -263,6 +267,8 @@ class Paths
|
|||||||
cur++;
|
cur++;
|
||||||
}
|
}
|
||||||
return finalFrames;
|
return finalFrames;
|
||||||
|
} else if (Assets.exists('$noExt/Animation.json')) {
|
||||||
|
return Paths.getAnimateAtlasAlt(noExt, animateSettings);
|
||||||
} else if (Assets.exists('$noExt.xml')) {
|
} else if (Assets.exists('$noExt.xml')) {
|
||||||
return Paths.getSparrowAtlasAlt(noExt, ext);
|
return Paths.getSparrowAtlasAlt(noExt, ext);
|
||||||
} else if (Assets.exists('$noExt.txt')) {
|
} else if (Assets.exists('$noExt.txt')) {
|
||||||
|
|||||||
@@ -108,6 +108,8 @@ class TranslatedAssetLibrary extends AssetLibrary implements IModsAssetLibrary {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: list support for TranslatedAssetLibrary (idk how it works)
|
||||||
|
|
||||||
#if MOD_SUPPORT
|
#if MOD_SUPPORT
|
||||||
public var _parsedAsset:String = null; // Theres no need to actually make this work - Nex
|
public var _parsedAsset:String = null; // Theres no need to actually make this work - Nex
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary {
|
|||||||
zip = SysZip.openFromFile(basePath);
|
zip = SysZip.openFromFile(basePath);
|
||||||
zip.read();
|
zip.read();
|
||||||
for(entry in zip.entries) {
|
for(entry in zip.entries) {
|
||||||
|
if (entry.fileName.length < 0 || entry.fileName.endsWith("/"))
|
||||||
|
continue;
|
||||||
|
|
||||||
lowerCaseAssets[entry.fileName.toLowerCase()] = assets[entry.fileName.toLowerCase()] = assets[entry.fileName] = entry;
|
lowerCaseAssets[entry.fileName.toLowerCase()] = assets[entry.fileName.toLowerCase()] = assets[entry.fileName] = entry;
|
||||||
nameMap.set(entry.fileName.toLowerCase(), entry.fileName);
|
nameMap.set(entry.fileName.toLowerCase(), entry.fileName);
|
||||||
}
|
}
|
||||||
@@ -154,6 +157,10 @@ class ZipFolderLibrary extends AssetLibrary implements IModsAssetLibrary {
|
|||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override function list(type:String):Array<String> {
|
||||||
|
return[for(k=>e in nameMap) '$prefix$e'];
|
||||||
|
}
|
||||||
|
|
||||||
// Backwards compat
|
// Backwards compat
|
||||||
|
|
||||||
@:noCompletion public var zipPath(get, set):String;
|
@:noCompletion public var zipPath(get, set):String;
|
||||||
|
|||||||
@@ -97,41 +97,6 @@ class Chart {
|
|||||||
data.setFieldDefault("vocalsSuffix", "");
|
data.setFieldDefault("vocalsSuffix", "");
|
||||||
data.setFieldDefault("needsVoices", true);
|
data.setFieldDefault("needsVoices", true);
|
||||||
data.setFieldDefault("difficulties", []);
|
data.setFieldDefault("difficulties", []);
|
||||||
|
|
||||||
var songNameLower = songName.toLowerCase();
|
|
||||||
var metaPath = Paths.file('songs/${songNameLower}/meta.json');
|
|
||||||
var metaDiffPath = Paths.file('songs/${songNameLower}/meta-${difficulty.toLowerCase()}.json');
|
|
||||||
|
|
||||||
var blacklist:Array<String> = [];
|
|
||||||
var data:ChartMetaData = null;
|
|
||||||
var fromMods:Bool = fromMods;
|
|
||||||
for (path in [metaDiffPath, metaPath]) {
|
|
||||||
if (Assets.exists(path)) {
|
|
||||||
fromMods = Paths.assetsTree.existsSpecific(path, "TEXT", MODS);
|
|
||||||
try {
|
|
||||||
var temp = CoolUtil.parseJson(path);
|
|
||||||
|
|
||||||
// Backwards compatibility (they both can be null so != true) - Nex
|
|
||||||
var coopExlc = false;
|
|
||||||
if (Reflect.hasField(temp, "coopAllowed") && Reflect.field(temp, "coopAllowed") != true) {
|
|
||||||
blacklist = blacklist.concat(["codename.coop", "codename.coop-opponent"]);
|
|
||||||
Reflect.deleteField(temp, "coopAllowed");
|
|
||||||
coopExlc = true;
|
|
||||||
}
|
|
||||||
if (Reflect.hasField(temp, "opponentModeAllowed") && Reflect.field(temp, "opponentModeAllowed") != true) {
|
|
||||||
if (!coopExlc) blacklist.push("codename.coop-opponent");
|
|
||||||
blacklist.push("codename.opponent");
|
|
||||||
Reflect.deleteField(temp, "opponentModeAllowed");
|
|
||||||
}
|
|
||||||
|
|
||||||
data = temp;
|
|
||||||
} catch(e) {
|
|
||||||
Logs.trace('Failed to load song metadata for ${songName} ($path): ${Std.string(e)}', ERROR);
|
|
||||||
}
|
|
||||||
if (data != null) break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data.setFieldDefault("excludedGameModes", blacklist);
|
|
||||||
data.setFieldDefault("variants", []);
|
data.setFieldDefault("variants", []);
|
||||||
data.setFieldDefault("metas", []);
|
data.setFieldDefault("metas", []);
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,8 @@ typedef ChartMetaData = {
|
|||||||
public var ?icon:String;
|
public var ?icon:String;
|
||||||
public var ?color:FlxColor;
|
public var ?color:FlxColor;
|
||||||
|
|
||||||
public var ?excludedGameModes:Array<String>;
|
public var ?coopAllowed:Bool;
|
||||||
|
public var ?opponentModeAllowed:Bool;
|
||||||
|
|
||||||
public var ?metas:Map<String, ChartMetaData>;
|
public var ?metas:Map<String, ChartMetaData>;
|
||||||
public var ?instSuffix:String;
|
public var ?instSuffix:String;
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ class Script extends FlxBasic implements IFlxDestroyable {
|
|||||||
"FunkinShader" => funkin.backend.shaders.FunkinShader,
|
"FunkinShader" => funkin.backend.shaders.FunkinShader,
|
||||||
"CustomShader" => funkin.backend.shaders.CustomShader,
|
"CustomShader" => funkin.backend.shaders.CustomShader,
|
||||||
"FunkinText" => funkin.backend.FunkinText,
|
"FunkinText" => funkin.backend.FunkinText,
|
||||||
"FlxAnimate" => funkin.backend.FlxAnimate,
|
"FlxAnimate" => animate.FlxAnimate,
|
||||||
"FunkinSprite" => funkin.backend.FunkinSprite,
|
"FunkinSprite" => funkin.backend.FunkinSprite,
|
||||||
"Alphabet" => funkin.menus.ui.Alphabet,
|
"Alphabet" => funkin.menus.ui.Alphabet,
|
||||||
"Flags" => funkin.backend.system.Flags,
|
"Flags" => funkin.backend.system.Flags,
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
package funkin.backend.scripting.events.menu.freeplay;
|
package funkin.backend.scripting.events.menu.freeplay;
|
||||||
|
|
||||||
import funkin.menus.FreeplayState.FreeplayGameMode;
|
|
||||||
|
|
||||||
final class FreeplaySongSelectEvent extends CancellableEvent {
|
final class FreeplaySongSelectEvent extends CancellableEvent {
|
||||||
/**
|
/**
|
||||||
* Song name that is about to be played
|
* Song name that is about to be played
|
||||||
@@ -16,26 +14,11 @@ final class FreeplaySongSelectEvent extends CancellableEvent {
|
|||||||
*/
|
*/
|
||||||
public var variant:String;
|
public var variant:String;
|
||||||
/**
|
/**
|
||||||
* Used game mode's data.
|
* Whenever opponent mode is enabled or not.
|
||||||
*/
|
*/
|
||||||
public var gameMode:FreeplayGameMode;
|
public var opponentMode:Bool;
|
||||||
|
/**
|
||||||
|
* Whenever coop mode is enabled.
|
||||||
// Backwards compat
|
*/
|
||||||
@:noCompletion public var opponentMode(get, set):Bool;
|
public var coopMode:Bool;
|
||||||
@:noCompletion private function get_opponentMode() return gameMode.modeID == "codename.opponent" || gameMode.modeID == "codename.coop-opponent";
|
|
||||||
@:noCompletion private function set_opponentMode(val:Bool) {
|
|
||||||
gameMode = coopMode ?
|
|
||||||
(val ? new FreeplayGameMode("Co-Op Mode (Switched)", "codename.coop-opponent", ["coop-switched", "opponent", "coop"]) : new FreeplayGameMode("Opponent Mode", "codename.opponent", ["opponent"])) :
|
|
||||||
(val ? new FreeplayGameMode("Opponent Mode", "codename.opponent", ["opponent"]) : null);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
@:noCompletion public var coopMode(get, set):Bool;
|
|
||||||
@:noCompletion private function get_coopMode() return gameMode.modeID == "codename.coop" || gameMode.modeID == "codename.coop-opponent";
|
|
||||||
@:noCompletion private function set_coopMode(val:Bool) {
|
|
||||||
gameMode = opponentMode ?
|
|
||||||
(val ? new FreeplayGameMode("Co-Op Mode (Switched)", "codename.coop-opponent", ["coop-switched", "opponent", "coop"]) : new FreeplayGameMode("Co-Op Mode", "codename.coop", ["coop"])) :
|
|
||||||
(val ? new FreeplayGameMode("Co-Op Mode", "codename.coop", ["coop"]) : null);
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -13,7 +13,7 @@ import lime.utils.AssetType;
|
|||||||
/**
|
/**
|
||||||
* A class that reads the `flags.ini` file, allowing to read settable Flags (customs too).
|
* A class that reads the `flags.ini` file, allowing to read settable Flags (customs too).
|
||||||
*/
|
*/
|
||||||
@:build(funkin.backend.system.macros.FlagMacro.build("onReset"))
|
@:build(funkin.backend.system.macros.FlagMacro.build())
|
||||||
class Flags {
|
class Flags {
|
||||||
public static var overridenFlags:Map<String, Bool> = [];
|
public static var overridenFlags:Map<String, Bool> = [];
|
||||||
|
|
||||||
@@ -312,11 +312,6 @@ class Flags {
|
|||||||
if (SUSTAINS_AS_ONE_NOTE == null) SUSTAINS_AS_ONE_NOTE = MOD_API_VERSION >= 2;
|
if (SUSTAINS_AS_ONE_NOTE == null) SUSTAINS_AS_ONE_NOTE = MOD_API_VERSION >= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static function onReset() {
|
|
||||||
var currentModFolder = ModsFolder.currentModFolder;
|
|
||||||
if (currentModFolder != null) SAVE_NAME = currentModFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function loadFromDatas(datas:Array<String>):Map<String, String> {
|
public static function loadFromDatas(datas:Array<String>):Map<String, String> {
|
||||||
var flags:Map<String, String> = [];
|
var flags:Map<String, String> = [];
|
||||||
for (data in datas) {
|
for (data in datas) {
|
||||||
@@ -337,8 +332,9 @@ class Flags {
|
|||||||
if (!(parsed = parse(name, value))) customFlags.set(name, value);
|
if (!(parsed = parse(name, value))) customFlags.set(name, value);
|
||||||
if (!overridenFlags.exists(name)) overridenFlags.set(name, parsed);
|
if (!overridenFlags.exists(name)) overridenFlags.set(name, parsed);
|
||||||
}
|
}
|
||||||
|
#if MODCHARTING_FEATURES
|
||||||
Options.modchartingHoldSubdivisions = DEFAULT_MODCHART_HOLD_SUBDIVISIONS;
|
Options.modchartingHoldSubdivisions = DEFAULT_MODCHART_HOLD_SUBDIVISIONS;
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -0,0 +1,134 @@
|
|||||||
|
package funkin.backend.system.macros;
|
||||||
|
|
||||||
|
#if macro
|
||||||
|
import sys.io.File;
|
||||||
|
import haxe.macro.ComplexTypeTools;
|
||||||
|
import haxe.macro.Printer;
|
||||||
|
import haxe.macro.Expr.Position;
|
||||||
|
import haxe.macro.Context;
|
||||||
|
import haxe.macro.Expr.Field;
|
||||||
|
import haxe.macro.Expr;
|
||||||
|
|
||||||
|
class AliasMacro {
|
||||||
|
public static var aliasMetadata:Metadata = [{
|
||||||
|
name: ":keep",
|
||||||
|
pos: Context.currentPos()
|
||||||
|
},{
|
||||||
|
name: ":dox",
|
||||||
|
pos: Context.currentPos(),
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
expr: EConst(CIdent("hide")),
|
||||||
|
pos: Context.currentPos()
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}];
|
||||||
|
|
||||||
|
public static function build():Array<Field> {
|
||||||
|
#if LIME_DISPLAY
|
||||||
|
return Context.getBuildFields();
|
||||||
|
#end
|
||||||
|
|
||||||
|
var fields = Context.getBuildFields();
|
||||||
|
var ogFieldCount = fields.length;
|
||||||
|
|
||||||
|
for(i in 0...ogFieldCount) {
|
||||||
|
var field = fields[i];
|
||||||
|
if (field.meta == null) continue;
|
||||||
|
|
||||||
|
var previousAliases:Array<{name:String, pos:Position}> = [];
|
||||||
|
for(meta in field.meta) {
|
||||||
|
if (meta.name == ":alias" && meta.params != null) {
|
||||||
|
for(p in meta.params) {
|
||||||
|
switch(p.expr) {
|
||||||
|
case EConst(CString(s, kind)):
|
||||||
|
previousAliases.push({
|
||||||
|
name: s,
|
||||||
|
pos: p.pos
|
||||||
|
});
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousAliases.length == 0) continue;
|
||||||
|
|
||||||
|
var ghostAccess = field.access.copy();
|
||||||
|
ghostAccess.remove(AOverride);
|
||||||
|
ghostAccess.remove(APublic);
|
||||||
|
|
||||||
|
for(alias in previousAliases) {
|
||||||
|
var ghostField:Field = {
|
||||||
|
name: alias.name,
|
||||||
|
pos: alias.pos,
|
||||||
|
kind: null,
|
||||||
|
access: ghostAccess,
|
||||||
|
meta: aliasMetadata
|
||||||
|
};
|
||||||
|
|
||||||
|
switch(field.kind) {
|
||||||
|
case FFun(f):
|
||||||
|
var args:Array<Expr> = [for(a in f.args) {
|
||||||
|
expr: EConst(CIdent(a.name)),
|
||||||
|
pos: Context.currentPos()
|
||||||
|
}];
|
||||||
|
|
||||||
|
ghostField.kind = FFun({
|
||||||
|
args: f.args,
|
||||||
|
params: f.params,
|
||||||
|
ret: f.ret,
|
||||||
|
expr: macro return $i{field.name}($a{args})
|
||||||
|
});
|
||||||
|
|
||||||
|
default:
|
||||||
|
var type = null;
|
||||||
|
switch(field.kind) {
|
||||||
|
case FVar(t, e):
|
||||||
|
type = t;
|
||||||
|
case FProp(get, set, t, e):
|
||||||
|
type = t;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
ghostField.kind = FProp("get", "set", type, null);
|
||||||
|
|
||||||
|
fields.push({
|
||||||
|
name: 'get_${alias.name}',
|
||||||
|
kind: FFun({
|
||||||
|
args: [],
|
||||||
|
expr: macro return $i{field.name},
|
||||||
|
ret: type
|
||||||
|
}),
|
||||||
|
pos: alias.pos,
|
||||||
|
meta: aliasMetadata
|
||||||
|
});
|
||||||
|
fields.push({
|
||||||
|
name: 'set_${alias.name}',
|
||||||
|
kind: FFun({
|
||||||
|
args: [{
|
||||||
|
name: '_${field.name}',
|
||||||
|
type: type
|
||||||
|
}],
|
||||||
|
expr: macro return ($i{field.name} = $i{'_${field.name}'}),
|
||||||
|
ret: type
|
||||||
|
}),
|
||||||
|
pos: alias.pos,
|
||||||
|
meta: aliasMetadata
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fields.push(ghostField);
|
||||||
|
}
|
||||||
|
|
||||||
|
var docFooter = '_Aliases: ${[for(alias in previousAliases) '`${alias.name}`'].join(", ")}_';
|
||||||
|
if (field.doc != null)
|
||||||
|
field.doc += '\n\n$docFooter';
|
||||||
|
else
|
||||||
|
field.doc = docFooter;
|
||||||
|
}
|
||||||
|
trace(fields);
|
||||||
|
|
||||||
|
return fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#end
|
||||||
@@ -19,9 +19,9 @@ class DefinesMacro {
|
|||||||
|
|
||||||
// INTERNAL MACROS
|
// INTERNAL MACROS
|
||||||
#if REGION
|
#if REGION
|
||||||
private static macro function __getDefines() {
|
private static macro function __getDefines():Expr {
|
||||||
#if display
|
#if display
|
||||||
return macro $v{[]};
|
return macro $v{([]:Map<String, Dynamic>)};
|
||||||
#else
|
#else
|
||||||
return macro $v{Context.getDefines()};
|
return macro $v{Context.getDefines()};
|
||||||
#end
|
#end
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ class FlagMacro {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function build(resetCallback:String):Array<Field> {
|
public static function build():Array<Field> {
|
||||||
var fields = Context.getBuildFields();
|
var fields = Context.getBuildFields();
|
||||||
|
|
||||||
var clRef = Context.getLocalClass();
|
var clRef = Context.getLocalClass();
|
||||||
@@ -248,10 +248,7 @@ class FlagMacro {
|
|||||||
access: [APublic, AStatic],
|
access: [APublic, AStatic],
|
||||||
kind: FFun({
|
kind: FFun({
|
||||||
args: [],
|
args: [],
|
||||||
expr: macro {
|
expr: macro $b{resetExprs},
|
||||||
$b{resetExprs};
|
|
||||||
$i{resetCallback}();
|
|
||||||
},
|
|
||||||
ret: macro: Void
|
ret: macro: Void
|
||||||
}),
|
}),
|
||||||
pos: Context.currentPos(),
|
pos: Context.currentPos(),
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class GitCommitMacro {
|
|||||||
// INTERNAL MACROS
|
// INTERNAL MACROS
|
||||||
#if REGION
|
#if REGION
|
||||||
private static macro function __getCommitHash() {
|
private static macro function __getCommitHash() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{"-"};
|
return macro $v{"-"};
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
@@ -78,7 +78,7 @@ class GitCommitMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static macro function __getCommitNumber() {
|
private static macro function __getCommitNumber() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{0};
|
return macro $v{0};
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
@@ -92,7 +92,7 @@ class GitCommitMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static macro function __getCommitHashLong() {
|
private static macro function __getCommitHashLong() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{"-"};
|
return macro $v{"-"};
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
@@ -106,7 +106,7 @@ class GitCommitMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static macro function __getCommitMessage() {
|
private static macro function __getCommitMessage() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{"-"};
|
return macro $v{"-"};
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
@@ -124,7 +124,7 @@ class GitCommitMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static macro function __getCommitAuthor() {
|
private static macro function __getCommitAuthor() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{"-"};
|
return macro $v{"-"};
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
@@ -138,8 +138,8 @@ class GitCommitMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static macro function __getCommitDate() {
|
private static macro function __getCommitDate() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{Date.now()};
|
return macro Date.now();
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
// get the time in UTC format
|
// get the time in UTC format
|
||||||
@@ -164,7 +164,7 @@ class GitCommitMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static macro function __getCurrentBranch() {
|
private static macro function __getCurrentBranch() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{"-"};
|
return macro $v{"-"};
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
@@ -179,7 +179,7 @@ class GitCommitMacro {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static macro function __getHasUncommittedChanges() {
|
private static macro function __getHasUncommittedChanges() {
|
||||||
#if display
|
#if LIME_DISPLAY
|
||||||
return macro $v{false};
|
return macro $v{false};
|
||||||
#else
|
#else
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ class Macros {
|
|||||||
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
|
#if VIDEO_CUTSCENES "hxvlc.flixel", "hxvlc.openfl", #end
|
||||||
#if NAPE_ENABLED "nape", "flixel.addons.nape", #end
|
#if NAPE_ENABLED "nape", "flixel.addons.nape", #end
|
||||||
// BASE HAXE
|
// BASE HAXE
|
||||||
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting"
|
"DateTools", "EReg", "Lambda", "StringBuf", "haxe.crypto", "haxe.display", "haxe.exceptions", "haxe.extern", "scripting", "animate"
|
||||||
])
|
])
|
||||||
Compiler.include(inc);
|
Compiler.include(inc);
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import flixel.util.FlxAxes;
|
|||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
import flixel.util.typeLimit.OneOfThree;
|
import flixel.util.typeLimit.OneOfThree;
|
||||||
import flixel.util.typeLimit.OneOfTwo;
|
import flixel.util.typeLimit.OneOfTwo;
|
||||||
import flxanimate.data.AnimationData.AnimAtlas;
|
|
||||||
import funkin.backend.system.Conductor;
|
import funkin.backend.system.Conductor;
|
||||||
import funkin.backend.utils.XMLUtil.TextFormat;
|
import funkin.backend.utils.XMLUtil.TextFormat;
|
||||||
import haxe.CallStack;
|
import haxe.CallStack;
|
||||||
@@ -34,6 +33,8 @@ import haxe.xml.Access;
|
|||||||
import lime.utils.Assets;
|
import lime.utils.Assets;
|
||||||
import openfl.display.BitmapData;
|
import openfl.display.BitmapData;
|
||||||
import openfl.geom.ColorTransform;
|
import openfl.geom.ColorTransform;
|
||||||
|
import animate.FlxAnimateJson;
|
||||||
|
import flixel.animation.FlxAnimationController;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
@@ -574,6 +575,29 @@ final class CoolUtil
|
|||||||
anim2.frames = old;
|
anim2.frames = old;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Swaps two animations on an animation controller.
|
||||||
|
* @param animation Animation controller
|
||||||
|
* @param anim1 First animation
|
||||||
|
* @param anim2 Second animation
|
||||||
|
*/
|
||||||
|
public static function swapAnims(animation:FlxAnimationController, anim1:String, anim2:String) @:privateAccess {
|
||||||
|
var flxAnim1 = animation.getByName(anim1);
|
||||||
|
animation._animations.remove(anim1);
|
||||||
|
|
||||||
|
var flxAnim2 = animation.getByName(anim2);
|
||||||
|
animation._animations.remove(anim2);
|
||||||
|
|
||||||
|
if (flxAnim1 != null) {
|
||||||
|
flxAnim1.name = anim2;
|
||||||
|
animation._animations.set(anim2, flxAnim1);
|
||||||
|
}
|
||||||
|
if (flxAnim2 != null) {
|
||||||
|
flxAnim2.name = anim1;
|
||||||
|
animation._animations.set(anim1, flxAnim2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows you to set a graphic size (ex: 150x150), with proper hitbox without a stretched sprite.
|
* Allows you to set a graphic size (ex: 150x150), with proper hitbox without a stretched sprite.
|
||||||
* @param sprite Sprite to apply the new graphic size to
|
* @param sprite Sprite to apply the new graphic size to
|
||||||
@@ -1252,23 +1276,20 @@ final class CoolUtil
|
|||||||
return animsList;
|
return animsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAnimsListFromAtlas(atlas:AnimAtlas):Array<String> {
|
public static function getAnimsListFromAtlas(atlas:AnimationJson):Array<String> {
|
||||||
if (atlas == null) return [];
|
if (atlas == null) return [];
|
||||||
|
|
||||||
var animsList:Array<String> = [];
|
var animsList:Array<String> = [];
|
||||||
if (atlas.AN.SN != null) animsList.push(atlas.AN.SN);
|
if (atlas.AN.SN != null) animsList.push(atlas.AN.SN);
|
||||||
if (atlas.SD != null)
|
if (atlas.SD != null)
|
||||||
for (symbol in atlas.SD.S)
|
for (symbol in atlas.SD)
|
||||||
if (symbol.SN != null) animsList.push(symbol.SN);
|
if (symbol.SN != null) animsList.push(symbol.SN);
|
||||||
|
|
||||||
return animsList;
|
return animsList;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function getAnimsListFromSprite(spr:FunkinSprite):Array<String> {
|
public static function getAnimsListFromSprite(spr:FunkinSprite):Array<String> {
|
||||||
if (spr.animateAtlas != null) {
|
return getAnimsListFromFrames(spr.frames);
|
||||||
return [for (symbol => timeline in spr.animateAtlas.anim.symbolDictionary) symbol];
|
|
||||||
} else
|
|
||||||
return getAnimsListFromFrames(spr.frames);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check this for bugs
|
// TODO: check this for bugs
|
||||||
|
|||||||
@@ -34,151 +34,23 @@ final class MatrixUtil {
|
|||||||
//if(_height == -1) _height = sprite.height;
|
//if(_height == -1) _height = sprite.height;
|
||||||
if(camera == null) camera = sprite.camera;
|
if(camera == null) camera = sprite.camera;
|
||||||
if(points is FlxBasePoint) points = [points];
|
if(points is FlxBasePoint) points = [points];
|
||||||
var isFunkinSprite = sprite is FunkinSprite;
|
|
||||||
var funkinSprite:FunkinSprite = null;
|
|
||||||
if(isFunkinSprite) funkinSprite = cast sprite;
|
|
||||||
var isAnimateAtlas = isFunkinSprite && funkinSprite.animateAtlas != null;
|
|
||||||
|
|
||||||
var nc:FakeCamera = isAnimateAtlas ? FakeCallCamera.instance : FakeCamera.instance;
|
var nc:FakeCamera = FakeCamera.instance;
|
||||||
nc.zoom = camera.zoom;
|
nc.zoom = camera.zoom;
|
||||||
nc.scroll.set(camera.scroll.x, camera.scroll.y);
|
nc.scroll.set(camera.scroll.x, camera.scroll.y);
|
||||||
nc.pixelPerfectRender = camera.pixelPerfectRender;
|
nc.pixelPerfectRender = camera.pixelPerfectRender;
|
||||||
|
|
||||||
var points:Array<FlxPoint> = cast points;
|
var points:Array<FlxPoint> = cast points;
|
||||||
|
|
||||||
if(isAnimateAtlas) {
|
if(sprite is IPrePostDraw) {
|
||||||
var cnc = FakeCallCamera.instance;
|
var postDraw = cast(sprite, IPrePostDraw);
|
||||||
var sprite = funkinSprite;
|
postDraw.preDraw();
|
||||||
var oldOnDraw = cnc.onDraw;
|
sprite.drawComplex(nc);
|
||||||
|
postDraw.postDraw();
|
||||||
// TODO: fix rotation
|
|
||||||
// TODO: fix skew
|
|
||||||
|
|
||||||
var boundsTopLeft = new FlxPoint(Math.POSITIVE_INFINITY, Math.POSITIVE_INFINITY);
|
|
||||||
var boundsTopRight = new FlxPoint(Math.NEGATIVE_INFINITY, Math.POSITIVE_INFINITY);
|
|
||||||
var boundsBottomLeft = new FlxPoint(Math.POSITIVE_INFINITY, Math.NEGATIVE_INFINITY);
|
|
||||||
var boundsBottomRight = new FlxPoint(Math.NEGATIVE_INFINITY, Math.NEGATIVE_INFINITY);
|
|
||||||
|
|
||||||
cnc.onDraw = function(?frame:FlxFrame, ?pixels:BitmapData, matrix:FlxMatrix, ?transform:ColorTransform, ?blend:BlendMode, ?smoothing:Bool = false, ?shader:FlxShader) {
|
|
||||||
// cnc is already perfect rn
|
|
||||||
// so we need to manually process the limb
|
|
||||||
var points = [
|
|
||||||
// corners
|
|
||||||
FlxPoint.get(0, 0),
|
|
||||||
FlxPoint.get(1, 0),
|
|
||||||
FlxPoint.get(0, 1),
|
|
||||||
FlxPoint.get(1, 1)
|
|
||||||
];
|
|
||||||
|
|
||||||
rawTransformPoints(points, matrix, frame.sourceSize.x, frame.sourceSize.y);
|
|
||||||
|
|
||||||
// sort the points, incase like they were transformed with a scale -1 matrix
|
|
||||||
|
|
||||||
var topLeft:FlxPoint = points[0];
|
|
||||||
var topRight:FlxPoint = points[1];
|
|
||||||
var bottomLeft:FlxPoint = points[2];
|
|
||||||
var bottomRight:FlxPoint = points[3];
|
|
||||||
|
|
||||||
if (points[0].y > points[1].y) {
|
|
||||||
topLeft = points[1];
|
|
||||||
topRight = points[0];
|
|
||||||
}
|
|
||||||
if (points[2].y > points[3].y) {
|
|
||||||
bottomLeft = points[3];
|
|
||||||
bottomRight = points[2];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (topLeft.x > topRight.x) {
|
|
||||||
var temp = topLeft;
|
|
||||||
topLeft = topRight;
|
|
||||||
topRight = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bottomLeft.x > bottomRight.x) {
|
|
||||||
var temp = bottomLeft;
|
|
||||||
bottomLeft = bottomRight;
|
|
||||||
bottomRight = temp;
|
|
||||||
}
|
|
||||||
|
|
||||||
// points should now contain the corners of the limb
|
|
||||||
|
|
||||||
// trace("Corners of limb: " + points);
|
|
||||||
|
|
||||||
// set the max bounds of each corner of the limb
|
|
||||||
if(topLeft.x < boundsTopLeft.x) boundsTopLeft.x = topLeft.x;
|
|
||||||
if(topLeft.y < boundsTopLeft.y) boundsTopLeft.y = topLeft.y;
|
|
||||||
if(topRight.x > boundsTopRight.x) boundsTopRight.x = topRight.x;
|
|
||||||
if(topRight.y < boundsTopRight.y) boundsTopRight.y = topRight.y;
|
|
||||||
if(bottomLeft.x < boundsBottomLeft.x) boundsBottomLeft.x = bottomLeft.x;
|
|
||||||
if(bottomLeft.y > boundsBottomLeft.y) boundsBottomLeft.y = bottomLeft.y;
|
|
||||||
if(bottomRight.x > boundsBottomRight.x) boundsBottomRight.x = bottomRight.x;
|
|
||||||
if(bottomRight.y > boundsBottomRight.y) boundsBottomRight.y = bottomRight.y;
|
|
||||||
|
|
||||||
// recycle the points
|
|
||||||
for(point in points) point.put();
|
|
||||||
}
|
|
||||||
var cameras = sprite._cameras;
|
|
||||||
var oldVisible = cnc.visible;
|
|
||||||
cnc.visible = true;
|
|
||||||
sprite._cameras = [cnc];
|
|
||||||
sprite.draw();
|
|
||||||
sprite._cameras = cameras;
|
|
||||||
cnc.visible = oldVisible;
|
|
||||||
cnc.onDraw = oldOnDraw;
|
|
||||||
|
|
||||||
// fake transform
|
|
||||||
|
|
||||||
//trace("");
|
|
||||||
//trace("topLeft: " + boundsTopLeft);
|
|
||||||
//trace("topRight: " + boundsTopRight);
|
|
||||||
//trace("bottomLeft: " + boundsBottomLeft);
|
|
||||||
//trace("bottomRight: " + boundsBottomRight);
|
|
||||||
//trace("Before transform");
|
|
||||||
//trace(points);
|
|
||||||
|
|
||||||
for(point in points) {
|
|
||||||
//var x = matrix.__transformX(point.x * _width, point.y * _height);
|
|
||||||
//var y = matrix.__transformY(point.x * _width, point.y * _height);
|
|
||||||
// apply using boundsTopLeft, boundsTopRight, boundsBottomLeft, boundsBottomRight
|
|
||||||
// matrix doesnt work for this
|
|
||||||
var x = FlxMath.lerp(
|
|
||||||
FlxMath.lerp(boundsTopLeft.x, boundsTopRight.x, point.x),
|
|
||||||
FlxMath.lerp(boundsBottomLeft.x, boundsBottomRight.x, point.x),
|
|
||||||
point.y
|
|
||||||
);
|
|
||||||
var y = FlxMath.lerp(
|
|
||||||
FlxMath.lerp(boundsTopLeft.y, boundsTopRight.y, point.x),
|
|
||||||
FlxMath.lerp(boundsBottomLeft.y, boundsBottomRight.y, point.x),
|
|
||||||
point.y
|
|
||||||
);
|
|
||||||
|
|
||||||
//trace("(" + point.x + ", " + point.y + ") -> (" + x + ", " + y + ")");
|
|
||||||
|
|
||||||
// reset to ingame coords
|
|
||||||
x += camera.scroll.x;
|
|
||||||
y += camera.scroll.y;
|
|
||||||
|
|
||||||
if(isFunkinSprite) {
|
|
||||||
var ratio = 1 - FlxMath.lerp(1 / camera.zoom, 1, funkinSprite.zoomFactor);
|
|
||||||
x += camera.width / 2 * ratio;
|
|
||||||
y += camera.height / 2 * ratio;
|
|
||||||
}
|
|
||||||
point.set(x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
//trace("After transform");
|
|
||||||
//trace(points);
|
|
||||||
} else {
|
} else {
|
||||||
if(sprite is IPrePostDraw) {
|
sprite.drawComplex(nc);
|
||||||
var postDraw = cast(sprite, IPrePostDraw);
|
|
||||||
postDraw.preDraw();
|
|
||||||
sprite.drawComplex(nc);
|
|
||||||
postDraw.postDraw();
|
|
||||||
} else {
|
|
||||||
sprite.drawComplex(nc);
|
|
||||||
}
|
|
||||||
transformPoints(sprite, points, sprite._matrix, camera, _width, _height);
|
|
||||||
}
|
}
|
||||||
|
transformPoints(sprite, points, sprite._matrix, camera, _width, _height);
|
||||||
|
|
||||||
return points;
|
return points;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import funkin.backend.scripting.ScriptPack;
|
|||||||
import flixel.util.typeLimit.OneOfTwo;
|
import flixel.util.typeLimit.OneOfTwo;
|
||||||
import funkin.backend.system.interfaces.IOffsetCompatible;
|
import funkin.backend.system.interfaces.IOffsetCompatible;
|
||||||
import haxe.xml.Access;
|
import haxe.xml.Access;
|
||||||
|
import animate.FlxAnimateFrames;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
@@ -127,6 +128,9 @@ final class XMLUtil {
|
|||||||
spr.spriteAnimType = XMLAnimType.fromString(node.att.type, spr.spriteAnimType);
|
spr.spriteAnimType = XMLAnimType.fromString(node.att.type, spr.spriteAnimType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.has.applyStageMatrix) spr.applyStageMatrix = node.att.applyStageMatrix == "true";
|
||||||
|
if (node.has.useRenderTexture) spr.useRenderTexture = node.att.useRenderTexture == "true";
|
||||||
|
|
||||||
if(node.has.x) {
|
if(node.has.x) {
|
||||||
var x:Null<Float> = Std.parseFloat(node.att.x);
|
var x:Null<Float> = Std.parseFloat(node.att.x);
|
||||||
if (x.isNotNull()) spr.x = x;
|
if (x.isNotNull()) spr.x = x;
|
||||||
@@ -225,7 +229,8 @@ final class XMLUtil {
|
|||||||
animType: spr.spriteAnimType,
|
animType: spr.spriteAnimType,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
indices: [for(i in 0...spr.frames.frames.length) i]
|
indices: [for(i in 0...spr.frames.frames.length) i],
|
||||||
|
label: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +266,8 @@ final class XMLUtil {
|
|||||||
animType: animType,
|
animType: animType,
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 0,
|
||||||
indices: []
|
indices: [],
|
||||||
|
label: false
|
||||||
};
|
};
|
||||||
|
|
||||||
if (anim.has.name) animData.name = anim.att.name;
|
if (anim.has.name) animData.name = anim.att.name;
|
||||||
@@ -273,6 +279,7 @@ final class XMLUtil {
|
|||||||
if (anim.has.loop) animData.loop = anim.att.loop == "true";
|
if (anim.has.loop) animData.loop = anim.att.loop == "true";
|
||||||
if (anim.has.forced) animData.forced = anim.att.forced == "true";
|
if (anim.has.forced) animData.forced = anim.att.forced == "true";
|
||||||
if (anim.has.indices) animData.indices = CoolUtil.parseNumberRange(anim.att.indices);
|
if (anim.has.indices) animData.indices = CoolUtil.parseNumberRange(anim.att.indices);
|
||||||
|
if (anim.has.label) animData.label = anim.att.label == "true";
|
||||||
|
|
||||||
return animData;
|
return animData;
|
||||||
}
|
}
|
||||||
@@ -299,15 +306,23 @@ final class XMLUtil {
|
|||||||
if (animData.name != null) {
|
if (animData.name != null) {
|
||||||
if (animData.fps <= 0 #if web || animData.fps == null #end) animData.fps = 24;
|
if (animData.fps <= 0 #if web || animData.fps == null #end) animData.fps = 24;
|
||||||
|
|
||||||
if (sprite is FunkinSprite && cast(sprite, FunkinSprite).animateAtlas != null) {
|
if (sprite.frames is FlxAnimateFrames) {
|
||||||
var animateAnim = cast(sprite, FunkinSprite).animateAtlas.anim;
|
|
||||||
if(animData.anim == null)
|
if(animData.anim == null)
|
||||||
return MISSING_PROPERTY;
|
return MISSING_PROPERTY;
|
||||||
|
|
||||||
if (animData.indices != null && animData.indices.length > 0)
|
var animateAnim = cast(sprite, FunkinSprite).anim;
|
||||||
animateAnim.addBySymbolIndices(animData.name, animData.anim, animData.indices, animData.fps, animData.loop);
|
|
||||||
else
|
if (animData.label) {
|
||||||
animateAnim.addBySymbol(animData.name, animData.anim, animData.fps, animData.loop);
|
if (animData.indices != null && animData.indices.length > 0)
|
||||||
|
animateAnim.addByFrameLabelIndices(animData.name, animData.anim, animData.indices, animData.fps, animData.loop);
|
||||||
|
else
|
||||||
|
animateAnim.addByFrameLabel(animData.name, animData.anim, animData.fps, animData.loop);
|
||||||
|
} else {
|
||||||
|
if (animData.indices != null && animData.indices.length > 0)
|
||||||
|
animateAnim.addBySymbolIndices(animData.name, animData.anim, animData.indices, animData.fps, animData.loop);
|
||||||
|
else
|
||||||
|
animateAnim.addBySymbol(animData.name, animData.anim, animData.fps, animData.loop);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (animData.indices != null && animData.indices.length > 0) {
|
if (animData.indices != null && animData.indices.length > 0) {
|
||||||
if (animData.anim == null)
|
if (animData.anim == null)
|
||||||
@@ -463,6 +478,7 @@ typedef AnimData = {
|
|||||||
var y:Float;
|
var y:Float;
|
||||||
var indices:Array<Int>;
|
var indices:Array<Int>;
|
||||||
var animType:XMLAnimType;
|
var animType:XMLAnimType;
|
||||||
|
var label:Bool;
|
||||||
var ?forced:Bool;
|
var ?forced:Bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,18 +2,13 @@ package funkin.editors.character;
|
|||||||
|
|
||||||
import flixel.text.FlxText.FlxTextFormat;
|
import flixel.text.FlxText.FlxTextFormat;
|
||||||
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||||
import flxanimate.animate.FlxAnim.FlxSymbolAnimation;
|
|
||||||
import flxanimate.animate.FlxSymbol;
|
|
||||||
import flxanimate.animate.FlxElement;
|
|
||||||
import flxanimate.animate.SymbolParameters;
|
|
||||||
import flxanimate.animate.FlxKeyFrame;
|
|
||||||
import flxanimate.animate.FlxTimeline;
|
|
||||||
import flixel.graphics.frames.FlxFrame;
|
import flixel.graphics.frames.FlxFrame;
|
||||||
import flixel.animation.FlxAnimation;
|
import flixel.animation.FlxAnimation;
|
||||||
import openfl.geom.Rectangle;
|
import openfl.geom.Rectangle;
|
||||||
import funkin.backend.utils.XMLUtil.AnimData;
|
import funkin.backend.utils.XMLUtil.AnimData;
|
||||||
import flixel.math.FlxPoint;
|
import flixel.math.FlxPoint;
|
||||||
import flixel.util.FlxColor;
|
import flixel.util.FlxColor;
|
||||||
|
import funkin.editors.character.CharacterAnimsWindow;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
@@ -26,6 +21,7 @@ class CharacterAnimButton extends UIButton {
|
|||||||
public var animationDisplayBG:UISliceSprite;
|
public var animationDisplayBG:UISliceSprite;
|
||||||
public var nameTextBox:UITextBox;
|
public var nameTextBox:UITextBox;
|
||||||
public var animTextBox:UIAutoCompleteTextBox;
|
public var animTextBox:UIAutoCompleteTextBox;
|
||||||
|
public var animLabelCheckbox:UICheckbox;
|
||||||
public var positionXStepper:UINumericStepper;
|
public var positionXStepper:UINumericStepper;
|
||||||
public var positionYStepper:UINumericStepper;
|
public var positionYStepper:UINumericStepper;
|
||||||
public var fpsStepper:UINumericStepper;
|
public var fpsStepper:UINumericStepper;
|
||||||
@@ -116,13 +112,20 @@ class CharacterAnimButton extends UIButton {
|
|||||||
foldableButtons.push(fpsStepper);
|
foldableButtons.push(fpsStepper);
|
||||||
addLabelOn(fpsStepper, translate("fps"), 12);
|
addLabelOn(fpsStepper, translate("fps"), 12);
|
||||||
|
|
||||||
loopedCheckbox = new UICheckbox(fpsStepper.x + 82 - 32 + 26, fpsStepper.y, "Looping?", animData.loop, 0, true);
|
loopedCheckbox = new UICheckbox(fpsStepper.x + 82 - 32 + 26, fpsStepper.y, translate("looping"), animData.loop, 0, true);
|
||||||
loopedCheckbox.onChecked = (newLooping:Bool) -> {this.changeLooping(newLooping);};
|
loopedCheckbox.onChecked = (newLooping:Bool) -> {this.changeLooping(newLooping);};
|
||||||
members.push(loopedCheckbox);
|
members.push(loopedCheckbox);
|
||||||
foldableButtons.push(loopedCheckbox);
|
foldableButtons.push(loopedCheckbox);
|
||||||
|
|
||||||
loopedCheckbox.x += 8; loopedCheckbox.y += 6;
|
loopedCheckbox.x += 8; loopedCheckbox.y += 6;
|
||||||
|
|
||||||
|
if (parent.character.isAnimate) {
|
||||||
|
animLabelCheckbox = new UICheckbox(loopedCheckbox.x, animTextBox.y + 26, translate("label"), animData.label, 0, true);
|
||||||
|
animLabelCheckbox.onChecked = (newLabel:Bool) -> {this.changeLabel(newLabel);};
|
||||||
|
members.push(animLabelCheckbox);
|
||||||
|
foldableButtons.push(animLabelCheckbox);
|
||||||
|
}
|
||||||
|
|
||||||
indicesTextBox = new UITextBox(nameTextBox.x, nameTextBox.y, CoolUtil.formatNumberRange(animData.indices.getDefault([]), ", "), 278, 22, false, true);
|
indicesTextBox = new UITextBox(nameTextBox.x, nameTextBox.y, CoolUtil.formatNumberRange(animData.indices.getDefault([]), ", "), 278, 22, false, true);
|
||||||
indicesTextBox.onChange = (text:String) -> {
|
indicesTextBox.onChange = (text:String) -> {
|
||||||
this.changeIndicies(CoolUtil.parseNumberRange(text));
|
this.changeIndicies(CoolUtil.parseNumberRange(text));
|
||||||
@@ -204,6 +207,7 @@ class CharacterAnimButton extends UIButton {
|
|||||||
|
|
||||||
fpsStepper.follow(this, 282, 118);
|
fpsStepper.follow(this, 282, 118);
|
||||||
loopedCheckbox.follow(this, 336, 122);
|
loopedCheckbox.follow(this, 336, 122);
|
||||||
|
animLabelCheckbox?.follow(this, 336, 98);
|
||||||
|
|
||||||
indicesTextBox.follow(this, 158, 164);
|
indicesTextBox.follow(this, 158, 164);
|
||||||
|
|
||||||
@@ -231,18 +235,12 @@ class CharacterAnimButton extends UIButton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var oldName:String = anim;
|
var oldName:String = anim;
|
||||||
if (parent.character.animateAtlas != null) {
|
|
||||||
var animSymbol:FlxSymbolAnimation = __getAnimationSymbol();
|
|
||||||
|
|
||||||
parent.character.animateAtlas.anim.animsMap.remove(anim);
|
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
||||||
parent.character.animateAtlas.anim.animsMap.set(newName, animSymbol);
|
flxAnimation.name = newName;
|
||||||
} else {
|
|
||||||
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
|
||||||
flxAnimation.name = newName;
|
|
||||||
|
|
||||||
parent.character.animation._animations.remove(anim);
|
parent.character.animation._animations.remove(anim);
|
||||||
parent.character.animation._animations.set(newName, flxAnimation);
|
parent.character.animation._animations.set(newName, flxAnimation);
|
||||||
}
|
|
||||||
|
|
||||||
var animData:AnimData = parent.character.animDatas[anim];
|
var animData:AnimData = parent.character.animDatas[anim];
|
||||||
animData.name = newName;
|
animData.name = newName;
|
||||||
@@ -254,7 +252,7 @@ class CharacterAnimButton extends UIButton {
|
|||||||
parent.character.animOffsets.remove(anim);
|
parent.character.animOffsets.remove(anim);
|
||||||
parent.character.animOffsets.set(newName, animOffset);
|
parent.character.animOffsets.set(newName, animOffset);
|
||||||
|
|
||||||
var displayFrame:{scale:Float, animBounds:Rectangle, frame:Int} = parent.displayAnimsFramesList[anim];
|
var displayFrame:DisplayAnimFrameEntry = parent.displayAnimsFramesList[anim];
|
||||||
parent.displayAnimsFramesList.remove(anim);
|
parent.displayAnimsFramesList.remove(anim);
|
||||||
parent.displayAnimsFramesList.set(newName, displayFrame);
|
parent.displayAnimsFramesList.set(newName, displayFrame);
|
||||||
|
|
||||||
@@ -276,23 +274,20 @@ class CharacterAnimButton extends UIButton {
|
|||||||
var oldAnim:String = animData.anim;
|
var oldAnim:String = animData.anim;
|
||||||
animData.anim = newAnim;
|
animData.anim = newAnim;
|
||||||
|
|
||||||
if (parent.character.animateAtlas != null)
|
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
||||||
__refreshAnimation();
|
flxAnimation.prefix = newAnim;
|
||||||
else {
|
|
||||||
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
|
||||||
flxAnimation.prefix = newAnim;
|
|
||||||
|
|
||||||
refreshFlxAnimationFrames(flxAnimation, animData);
|
refreshAnimation(__getFlxAnimation(), data);
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
parent.buildAnimDisplay(anim, data);
|
parent.buildAnimDisplay(anim, data);
|
||||||
animationDisplayBG.alpha = 1;
|
animationDisplayBG.alpha = 1;
|
||||||
} else {
|
} else {
|
||||||
parent.removeAnimDisplay(anim);
|
parent.removeAnimDisplay(anim);
|
||||||
animationDisplayBG.alpha = 0.4;
|
animationDisplayBG.alpha = 0.4;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (parent.character.getAnimName() == anim)
|
if (parent.character.getAnimName() == anim)
|
||||||
CharacterEditor.instance.playAnimation(anim);
|
CharacterEditor.instance.playAnimation(anim);
|
||||||
|
|
||||||
@@ -330,13 +325,8 @@ class CharacterAnimButton extends UIButton {
|
|||||||
var oldFPS:Float = animData.fps;
|
var oldFPS:Float = animData.fps;
|
||||||
animData.fps = newFPS;
|
animData.fps = newFPS;
|
||||||
|
|
||||||
if (parent.character.animateAtlas != null) {
|
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
||||||
var animSymbol:FlxSymbolAnimation = __getAnimationSymbol();
|
flxAnimation.frameRate = newFPS;
|
||||||
animSymbol.frameRate = newFPS;
|
|
||||||
} else {
|
|
||||||
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
|
||||||
flxAnimation.frameRate = newFPS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent.character.getAnimName() == anim)
|
if (parent.character.getAnimName() == anim)
|
||||||
CharacterEditor.instance.playAnimation(anim);
|
CharacterEditor.instance.playAnimation(anim);
|
||||||
@@ -351,13 +341,8 @@ class CharacterAnimButton extends UIButton {
|
|||||||
|
|
||||||
animData.loop = newLooping;
|
animData.loop = newLooping;
|
||||||
|
|
||||||
if (parent.character.animateAtlas != null) {
|
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
||||||
var animSymbol:FlxSymbolAnimation = __getAnimationSymbol();
|
flxAnimation.looped = animData.loop;
|
||||||
animSymbol.instance.symbol.loop = animData.loop ? Loop : PlayOnce;
|
|
||||||
} else {
|
|
||||||
var flxAnimation:FlxAnimation = __getFlxAnimation();
|
|
||||||
flxAnimation.looped = animData.loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent.character.getAnimName() == anim)
|
if (parent.character.getAnimName() == anim)
|
||||||
CharacterEditor.instance.playAnimation(anim);
|
CharacterEditor.instance.playAnimation(anim);
|
||||||
@@ -367,6 +352,19 @@ class CharacterAnimButton extends UIButton {
|
|||||||
if (addToUndo) CharacterEditor.undos.addToUndo(CAnimEditLooping(ID, newLooping));
|
if (addToUndo) CharacterEditor.undos.addToUndo(CAnimEditLooping(ID, newLooping));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function changeLabel(newLabel:Bool, addToUndo:Bool = true) @:privateAccess {
|
||||||
|
var animData:AnimData = parent.character.animDatas[anim];
|
||||||
|
|
||||||
|
animData.label = newLabel;
|
||||||
|
|
||||||
|
if (animLabelCheckbox != null)
|
||||||
|
animLabelCheckbox.checked = newLabel;
|
||||||
|
|
||||||
|
__refreshAnimation();
|
||||||
|
|
||||||
|
if (addToUndo) CharacterEditor.undos.addToUndo(CAnimEditLabel(ID, newLabel));
|
||||||
|
}
|
||||||
|
|
||||||
public function changeIndicies(indicies:Array<Int>, addToUndo:Bool = true) @:privateAccess {
|
public function changeIndicies(indicies:Array<Int>, addToUndo:Bool = true) @:privateAccess {
|
||||||
var animData:AnimData = parent.character.animDatas[anim];
|
var animData:AnimData = parent.character.animDatas[anim];
|
||||||
var oldIndices:Array<Int> = animData.indices.copy();
|
var oldIndices:Array<Int> = animData.indices.copy();
|
||||||
@@ -403,50 +401,6 @@ class CharacterAnimButton extends UIButton {
|
|||||||
CharacterEditor.undos.addToUndo(CAnimEditIndices(ID, oldIndices, indicies));
|
CharacterEditor.undos.addToUndo(CAnimEditIndices(ID, oldIndices, indicies));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public inline function refreshFlxAnimationFrames(flxAnimation:FlxAnimation, animData:AnimData) @:privateAccess {
|
|
||||||
try {
|
|
||||||
if (animData.indices.length > 0) {
|
|
||||||
var frameIndices:Array<Int> = new Array<Int>();
|
|
||||||
parent.character.animation.byIndicesHelper(frameIndices, flxAnimation.prefix, animData.indices, "");
|
|
||||||
|
|
||||||
flxAnimation.frames = frameIndices;
|
|
||||||
} else {
|
|
||||||
final animFrames:Array<FlxFrame> = new Array<FlxFrame>();
|
|
||||||
parent.character.animation.findByPrefix(animFrames, flxAnimation.prefix);
|
|
||||||
|
|
||||||
final frameIndices:Array<Int> = [];
|
|
||||||
parent.character.animation.byPrefixHelper(frameIndices, animFrames, flxAnimation.prefix);
|
|
||||||
|
|
||||||
flxAnimation.frames = frameIndices;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flxAnimation.frames.length <= 0) invalidate();
|
|
||||||
else validate();
|
|
||||||
} catch (e) {
|
|
||||||
trace('ERROR REFRESHING FLXANIMATION FRAMES: $e');
|
|
||||||
invalidate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public inline function refreshSymbolKeyFrames(symbol:FlxSymbolAnimation, animData:AnimData) @:privateAccess {
|
|
||||||
var wasRefreshed:Bool = false;
|
|
||||||
|
|
||||||
try {
|
|
||||||
parent.character.animateAtlas.anim.animsMap.remove(animData.name);
|
|
||||||
if (animData.indices.length > 0)
|
|
||||||
parent.character.animateAtlas.anim.addBySymbolIndices(animData.name, animData.anim, animData.indices, animData.fps, animData.loop);
|
|
||||||
else
|
|
||||||
parent.character.animateAtlas.anim.addBySymbol(animData.name, animData.anim, animData.fps, animData.loop);
|
|
||||||
wasRefreshed = parent.character.animateAtlas.anim.animsMap.exists(animData.name);
|
|
||||||
if (!wasRefreshed) __getAnimationSymbol();
|
|
||||||
} catch (e) {
|
|
||||||
trace('ERROR REFRESHING SYMBOL FRAMES: $e');
|
|
||||||
}
|
|
||||||
|
|
||||||
validate(wasRefreshed);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toggleGhost() {
|
public function toggleGhost() {
|
||||||
if (valid && parent.ghosts.indexOf(anim) == -1) {
|
if (valid && parent.ghosts.indexOf(anim) == -1) {
|
||||||
FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARACTER_GHOSTENABLE_SOUND));
|
FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARACTER_GHOSTENABLE_SOUND));
|
||||||
@@ -466,8 +420,8 @@ class CharacterAnimButton extends UIButton {
|
|||||||
super.draw();
|
super.draw();
|
||||||
|
|
||||||
if (!closed && parent.displayAnimsFramesList.exists(anim)) {
|
if (!closed && parent.displayAnimsFramesList.exists(anim)) {
|
||||||
var displayData:{frame:Int, scale:Float, animBounds:Rectangle} = parent.displayAnimsFramesList.get(anim);
|
var displayData:DisplayAnimFrameEntry = parent.displayAnimsFramesList.get(anim);
|
||||||
parent.displayWindowSprite.frame = parent.displayWindowSprite.frames.frames[displayData.frame];
|
parent.displayWindowSprite.frame = displayData.frame;
|
||||||
|
|
||||||
parent.displayWindowSprite.scale.x = parent.displayWindowSprite.scale.y = displayData.scale;
|
parent.displayWindowSprite.scale.x = parent.displayWindowSprite.scale.y = displayData.scale;
|
||||||
parent.displayWindowSprite.updateHitbox();
|
parent.displayWindowSprite.updateHitbox();
|
||||||
@@ -521,16 +475,26 @@ class CharacterAnimButton extends UIButton {
|
|||||||
return parent.character.animation._animations[anim];
|
return parent.character.animation._animations[anim];
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline function __getAnimationSymbol():Null<FlxSymbolAnimation> @:privateAccess {
|
public inline function refreshAnimation(anim:FlxAnimation, animData:AnimData) @:privateAccess {
|
||||||
if (!parent.character.animateAtlas.anim.animsMap.exists(anim))
|
var refreshed:Bool = false;
|
||||||
XMLUtil.addAnimToSprite(parent.character, data);
|
|
||||||
return parent.character.animateAtlas.anim.animsMap[anim];
|
parent.character.animation.remove(animData.name);
|
||||||
|
parent.character.animation._curAnim = null;
|
||||||
|
|
||||||
|
XMLUtil.addAnimToSprite(parent.character, animData);
|
||||||
|
|
||||||
|
var anim = parent.character.animation.getByName(animData.name);
|
||||||
|
|
||||||
|
if (anim != null && anim.frames.length > 0) {
|
||||||
|
validate();
|
||||||
|
parent.character.animation.play(animData.name);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@:noCompletion function __refreshAnimation() @:privateAccess {
|
@:noCompletion function __refreshAnimation() @:privateAccess {
|
||||||
if (parent.character.animateAtlas != null) refreshSymbolKeyFrames(__getAnimationSymbol(), data);
|
refreshAnimation(__getFlxAnimation(), data);
|
||||||
else refreshFlxAnimationFrames(__getFlxAnimation(), data);
|
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
parent.buildAnimDisplay(anim, data);
|
parent.buildAnimDisplay(anim, data);
|
||||||
|
|||||||
@@ -8,15 +8,24 @@ import openfl.geom.Rectangle;
|
|||||||
import flixel.graphics.frames.FlxFrame;
|
import flixel.graphics.frames.FlxFrame;
|
||||||
import funkin.game.Character;
|
import funkin.game.Character;
|
||||||
import flixel.animation.FlxPrerotatedAnimation;
|
import flixel.animation.FlxPrerotatedAnimation;
|
||||||
|
import animate.internal.RenderTexture;
|
||||||
|
import flixel.graphics.frames.FlxFrame;
|
||||||
|
import funkin.backend.system.Logs;
|
||||||
|
|
||||||
using funkin.backend.utils.BitmapUtil;
|
using funkin.backend.utils.BitmapUtil;
|
||||||
|
|
||||||
|
typedef DisplayAnimFrameEntry = {
|
||||||
|
scale:Float,
|
||||||
|
frame:FlxFrame,
|
||||||
|
renderTexture:RenderTexture
|
||||||
|
}
|
||||||
|
|
||||||
class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
|
class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
|
||||||
public var character:CharacterGhost;
|
public var character:CharacterGhost;
|
||||||
|
|
||||||
public var displayWindowSprite:FlxSprite;
|
public var displayWindowSprite:FlxSprite;
|
||||||
public var displayWindowGraphic:FlxGraphic;
|
public var displayWindowGraphic:FlxGraphic;
|
||||||
public var displayAnimsFramesList:Map<String, {scale:Float, animBounds:Rectangle, frame:OneOfTwo<Int, String>}> = [];
|
public var displayAnimsFramesList:Map<String, DisplayAnimFrameEntry> = [];
|
||||||
|
|
||||||
public var animButtons:Map<String, CharacterAnimButton> = [];
|
public var animButtons:Map<String, CharacterAnimButton> = [];
|
||||||
public var animsList:Array<String> = [];
|
public var animsList:Array<String> = [];
|
||||||
@@ -30,7 +39,7 @@ class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
|
|||||||
|
|
||||||
buttonCameras.pixelPerfectRender = true;
|
buttonCameras.pixelPerfectRender = true;
|
||||||
|
|
||||||
if (Assets.exists(Paths.image('characters/${character.sprite}')) && character.animateAtlas == null)
|
if (Assets.exists(Paths.image('characters/${character.sprite}')))
|
||||||
displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false));
|
displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false));
|
||||||
|
|
||||||
displayWindowSprite = new FlxSprite();
|
displayWindowSprite = new FlxSprite();
|
||||||
@@ -69,34 +78,45 @@ class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public function buildAnimDisplay(name:String, anim:AnimData) @:privateAccess {
|
public function buildAnimDisplay(name:String, anim:AnimData) @:privateAccess {
|
||||||
if (character.animateAtlas == null) {
|
var anim:FlxAnimation = character.animation._animations[anim.name];
|
||||||
var anim:FlxAnimation = character.animation._animations[anim.name];
|
if (anim == null) return;
|
||||||
if (anim == null || anim.frames.length <= 0) return;
|
|
||||||
|
|
||||||
|
if (character.isAnimate) {
|
||||||
|
var renderTex = character.generateRenderTextureForAnim(name);
|
||||||
|
var frame = renderTex.graphic.imageFrame.frame;
|
||||||
|
|
||||||
|
displayAnimsFramesList.set(name, {
|
||||||
|
frame: frame,
|
||||||
|
scale: 104/Math.max(frame.frame.width, frame.frame.height),
|
||||||
|
renderTexture: renderTex
|
||||||
|
});
|
||||||
|
} else {
|
||||||
var frameIndex:Int = anim.frames.getDefault([0])[0];
|
var frameIndex:Int = anim.frames.getDefault([0])[0];
|
||||||
var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex];
|
var frame:FlxFrame = displayWindowSprite.frames.frames[frameIndex];
|
||||||
|
|
||||||
var frameRect:Rectangle = new Rectangle(frame.offset.x, frame.offset.y, frame.sourceSize.x, frame.sourceSize.y);
|
var frameRect:Rectangle = new Rectangle(frame.offset.x, frame.offset.y, frame.sourceSize.x, frame.sourceSize.y);
|
||||||
var animBounds:Rectangle = displayWindowGraphic != null ? displayWindowGraphic.bitmap.bounds(frameRect) : frameRect;
|
var animBounds:Rectangle = displayWindowGraphic != null ? displayWindowGraphic.bitmap.bounds(frameRect) : frameRect;
|
||||||
|
|
||||||
displayAnimsFramesList.set(name, {frame: anim.frames.getDefault([0])[0], scale: 104/Math.max(animBounds.width, animBounds.height), animBounds: animBounds});
|
displayAnimsFramesList.set(name, {
|
||||||
} else {
|
frame: character.frames.frames[anim.frames.getDefault([0])[0]],
|
||||||
character.storeAtlasState();
|
scale: 104/Math.max(animBounds.width, animBounds.height),
|
||||||
|
renderTexture: null
|
||||||
/*
|
});
|
||||||
character.animateAtlas.anim.play(anim.name, true, false, 0);
|
|
||||||
character.animateAtlas.anim.stop();
|
|
||||||
|
|
||||||
var animBounds:Rectangle = MatrixUtil.getBounds(character).copyToFlash();
|
|
||||||
displayAnimsFramesList.set(name, {frame: anim.anim, scale: 104/animBounds.height, animBounds: animBounds});
|
|
||||||
*/
|
|
||||||
|
|
||||||
character.restoreAtlasState();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function removeAnimDisplay(name:String)
|
public function removeAnimDisplay(name:String) {
|
||||||
|
if (displayAnimsFramesList.exists(name))
|
||||||
|
displayAnimsFramesList[name].renderTexture?.destroy();
|
||||||
displayAnimsFramesList.remove(name);
|
displayAnimsFramesList.remove(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function clearDisplayAnims() {
|
||||||
|
for(k=>e in displayAnimsFramesList)
|
||||||
|
e.renderTexture?.destroy();
|
||||||
|
displayAnimsFramesList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
public function deleteAnimation(button:CharacterAnimButton, addToUndo:Bool = true) {
|
public function deleteAnimation(button:CharacterAnimButton, addToUndo:Bool = true) {
|
||||||
FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_DELETE_SOUND));
|
FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_DELETE_SOUND));
|
||||||
@@ -134,6 +154,7 @@ class CharacterAnimsWindow extends UIButtonList<CharacterAnimButton> {
|
|||||||
x: 0, y: 0,
|
x: 0, y: 0,
|
||||||
indices: [],
|
indices: [],
|
||||||
animType: NONE,
|
animType: NONE,
|
||||||
|
label: false
|
||||||
};
|
};
|
||||||
addAnimation(animData);
|
addAnimation(animData);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -554,6 +554,9 @@ class CharacterEditor extends UIState {
|
|||||||
case CAnimEditLooping(animID, newLooping):
|
case CAnimEditLooping(animID, newLooping):
|
||||||
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
||||||
button.changeLooping(!newLooping, false);
|
button.changeLooping(!newLooping, false);
|
||||||
|
case CAnimEditLabel(animID, newLabel):
|
||||||
|
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
||||||
|
button.changeLabel(!newLabel, false);
|
||||||
case CAnimEditIndices(animID, oldIndicies, newIndicies):
|
case CAnimEditIndices(animID, oldIndicies, newIndicies):
|
||||||
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
||||||
button.changeIndicies(oldIndicies, false);
|
button.changeIndicies(oldIndicies, false);
|
||||||
@@ -625,6 +628,9 @@ class CharacterEditor extends UIState {
|
|||||||
case CAnimEditLooping(animID, newLooping):
|
case CAnimEditLooping(animID, newLooping):
|
||||||
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
||||||
button.changeLooping(newLooping, false);
|
button.changeLooping(newLooping, false);
|
||||||
|
case CAnimEditLabel(animID, newLabel):
|
||||||
|
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
||||||
|
button.changeLabel(newLabel, false);
|
||||||
case CAnimEditIndices(animID, oldIndicies, newIndicies):
|
case CAnimEditIndices(animID, oldIndicies, newIndicies):
|
||||||
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
var button:CharacterAnimButton = characterAnimsWindow.buttons.members[animID];
|
||||||
button.changeIndicies(newIndicies, false);
|
button.changeIndicies(newIndicies, false);
|
||||||
@@ -936,6 +942,7 @@ enum CharacterEditorChange {
|
|||||||
CAnimEditFPS(animID:Int, oldFPS:Float, newFPS:Float);
|
CAnimEditFPS(animID:Int, oldFPS:Float, newFPS:Float);
|
||||||
CAnimEditLooping(animID:Int, newLooping:Bool);
|
CAnimEditLooping(animID:Int, newLooping:Bool);
|
||||||
CAnimEditIndices(animID:Int, oldIndicies:Array<Int>, newIndicies:Array<Int>);
|
CAnimEditIndices(animID:Int, oldIndicies:Array<Int>, newIndicies:Array<Int>);
|
||||||
|
CAnimEditLabel(animID:Int, newLabel:Bool);
|
||||||
|
|
||||||
CCharClearOffsets(oldOffsets:Map<String, FlxPoint>);
|
CCharClearOffsets(oldOffsets:Map<String, FlxPoint>);
|
||||||
}
|
}
|
||||||
@@ -4,6 +4,8 @@ import funkin.backend.system.FakeCamera.FakeCallCamera;
|
|||||||
import openfl.geom.ColorTransform;
|
import openfl.geom.ColorTransform;
|
||||||
import flixel.animation.FlxAnimation;
|
import flixel.animation.FlxAnimation;
|
||||||
import funkin.game.Character;
|
import funkin.game.Character;
|
||||||
|
import haxe.xml.Access;
|
||||||
|
import animate.internal.RenderTexture;
|
||||||
|
|
||||||
typedef AtlasState = {
|
typedef AtlasState = {
|
||||||
var oldAnim:String;
|
var oldAnim:String;
|
||||||
@@ -14,39 +16,35 @@ typedef AtlasState = {
|
|||||||
|
|
||||||
class CharacterGhost extends Character {
|
class CharacterGhost extends Character {
|
||||||
public var ghosts:Array<String> = [];
|
public var ghosts:Array<String> = [];
|
||||||
|
|
||||||
|
|
||||||
|
public override function buildCharacter(xml:Access) {
|
||||||
|
useRenderTexture = true; // per request from maru heh, still overridable
|
||||||
|
super.buildCharacter(xml);
|
||||||
|
}
|
||||||
|
|
||||||
public override function draw() @:privateAccess {
|
public override function draw() @:privateAccess {
|
||||||
ghostDraw = FakeCallCamera.instance.ignoreDraws = true;
|
ghostDraw = FakeCallCamera.instance.ignoreDraws = true;
|
||||||
|
|
||||||
var wasInvalidFrame:Bool = !colorTransform.__isDefault(false);
|
var wasInvalidFrame:Bool = !colorTransform.__isDefault(false);
|
||||||
colorTransform.__identity();
|
colorTransform.__identity();
|
||||||
|
|
||||||
if (animateAtlas != null) {
|
var animName = animation.curAnim?.name ?? null;
|
||||||
storeAtlasState();
|
var animFrame = animation.curAnim?.curFrame ?? 0;
|
||||||
for (anim in ghosts) {
|
var animFrameTimer = animation.curAnim?._frameTimer ?? 0;
|
||||||
animateAtlas.anim.play(anim, true, false, 0);
|
|
||||||
setAnimOffset(anim);
|
|
||||||
|
|
||||||
alpha = 0.4; color = 0xFFAEAEAE;
|
for (anim in ghosts) @:privateAccess {
|
||||||
super.draw();
|
alpha = 0.4; color = 0xFFAEAEAE;
|
||||||
}
|
|
||||||
|
|
||||||
if (ghosts.length > 0) restoreAtlasState();
|
var flxanim:FlxAnimation = animation._animations.get(anim);
|
||||||
|
animation.play(anim, true, false, flxanim.frames.length - 1);
|
||||||
|
|
||||||
|
setAnimOffset(anim);
|
||||||
|
super.draw();
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
for (anim in ghosts) @:privateAccess {
|
|
||||||
alpha = 0.4; color = 0xFFAEAEAE;
|
|
||||||
|
|
||||||
var flxanim:FlxAnimation = animation._animations.get(anim);
|
if (ghosts.length > 0)
|
||||||
var frameIndex:Int = flxanim.frames.getDefault([0])[flxanim.frames.length - 1];
|
frame = frames.frames[animation.frameIndex];
|
||||||
frame = frames.frames[frameIndex];
|
|
||||||
|
|
||||||
setAnimOffset(anim);
|
|
||||||
super.draw();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ghosts.length > 0)
|
|
||||||
frame = frames.frames[animation.frameIndex];
|
|
||||||
}
|
|
||||||
ghostDraw = FakeCallCamera.instance.ignoreDraws = false;
|
ghostDraw = FakeCallCamera.instance.ignoreDraws = false;
|
||||||
|
|
||||||
alpha = 1; color = 0xFFFFFFFF;
|
alpha = 1; color = 0xFFFFFFFF;
|
||||||
@@ -54,8 +52,12 @@ class CharacterGhost extends Character {
|
|||||||
frameOffset.set(0, 0);
|
frameOffset.set(0, 0);
|
||||||
offset.set(globalOffset.x * (isPlayer != playerOffsets ? 1 : -1), -globalOffset.y);
|
offset.set(globalOffset.x * (isPlayer != playerOffsets ? 1 : -1), -globalOffset.y);
|
||||||
colorTransform.color = 0xFFEF0202;
|
colorTransform.color = 0xFFEF0202;
|
||||||
} else
|
} else {
|
||||||
setAnimOffset(animateAtlas != null ? atlasPlayingAnim : animation.name);
|
animation.play(animName, true, false, animFrame);
|
||||||
|
setAnimOffset(animName);
|
||||||
|
if (animation.curAnim != null)
|
||||||
|
animation.curAnim._frameTimer = animFrameTimer;
|
||||||
|
}
|
||||||
|
|
||||||
super.draw();
|
super.draw();
|
||||||
}
|
}
|
||||||
@@ -70,22 +72,45 @@ class CharacterGhost extends Character {
|
|||||||
offset.set(globalOffset.x * (isPlayer != playerOffsets ? 1 : -1), -globalOffset.y);
|
offset.set(globalOffset.x * (isPlayer != playerOffsets ? 1 : -1), -globalOffset.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function generateRenderTextureForAnim(anim:String):RenderTexture @:privateAccess {
|
||||||
|
if (!isAnimate) return null;
|
||||||
|
|
||||||
|
var wasInvalidFrame:Bool = !colorTransform.__isDefault(false);
|
||||||
|
colorTransform.__identity();
|
||||||
|
|
||||||
|
var animName = animation.curAnim?.name ?? null;
|
||||||
|
var animFrame = animation.curAnim?.curFrame ?? 0;
|
||||||
|
var animFrameTimer = animation.curAnim?._frameTimer ?? 0;
|
||||||
|
|
||||||
|
var oldRenderTexture:RenderTexture = this._renderTexture;
|
||||||
|
var oldRenderTextureDirty = _renderTextureDirty;
|
||||||
|
var oldAlpha = alpha;
|
||||||
|
|
||||||
|
this._renderTexture = null;
|
||||||
|
this._renderTextureDirty = true;
|
||||||
|
this.alpha = 256.0/257.0;
|
||||||
|
|
||||||
|
animation.play(anim, true, false, 0);
|
||||||
|
|
||||||
|
drawAnimate(FakeCallCamera.instance);
|
||||||
|
|
||||||
|
var renderTex = this._renderTexture;
|
||||||
|
|
||||||
|
this._renderTexture = oldRenderTexture;
|
||||||
|
this._renderTextureDirty = oldRenderTextureDirty;
|
||||||
|
this.alpha = oldAlpha;
|
||||||
|
|
||||||
|
if (wasInvalidFrame) {
|
||||||
|
colorTransform.color = 0xFFEF0202;
|
||||||
|
} else {
|
||||||
|
animation.play(animName, true, false, animFrame);
|
||||||
|
if (animation.curAnim != null)
|
||||||
|
animation.curAnim._frameTimer = animFrameTimer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return renderTex;
|
||||||
|
}
|
||||||
|
|
||||||
// This gets annoying lmao -lunar
|
// This gets annoying lmao -lunar
|
||||||
private var atlasState:AtlasState = null;
|
// it's gone now <3 -yosh
|
||||||
public function storeAtlasState():AtlasState @:privateAccess {
|
|
||||||
return atlasState = {
|
|
||||||
oldAnim: atlasPlayingAnim,
|
|
||||||
oldFrame: animateAtlas.anim.curFrame,
|
|
||||||
oldTick: animateAtlas.anim._tick,
|
|
||||||
oldPlaying: animateAtlas.anim.isPlaying,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public function restoreAtlasState(state:AtlasState = null) @:privateAccess {
|
|
||||||
if (state == null) state = atlasState;
|
|
||||||
|
|
||||||
animateAtlas.anim.play(state.oldAnim, true, false, state.oldFrame);
|
|
||||||
animateAtlas.anim._tick = state.oldTick;
|
|
||||||
animateAtlas.anim.isPlaying = state.oldPlaying;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
|
|
||||||
package funkin.editors.character;
|
package funkin.editors.character;
|
||||||
|
|
||||||
import funkin.backend.FlxAnimate;
|
|
||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
import funkin.editors.character.CharacterInfoScreen.CharacterExtraInfo;
|
import funkin.editors.character.CharacterInfoScreen.CharacterExtraInfo;
|
||||||
import funkin.game.Character;
|
import funkin.game.Character;
|
||||||
@@ -184,31 +183,15 @@ class CharacterPropertiesWindow extends UISliceSprite {
|
|||||||
character.sprite = sprite;
|
character.sprite = sprite;
|
||||||
|
|
||||||
animsWindow.displayWindowSprite.animation.reset();
|
animsWindow.displayWindowSprite.animation.reset();
|
||||||
animsWindow.displayAnimsFramesList.clear();
|
animsWindow.clearDisplayAnims();
|
||||||
if (animsWindow.displayWindowGraphic != null)
|
if (animsWindow.displayWindowGraphic != null)
|
||||||
animsWindow.displayWindowGraphic.destroy();
|
animsWindow.displayWindowGraphic.destroy();
|
||||||
|
|
||||||
if (Assets.exists('$noExt/Animation.json')) {
|
character.frames = Paths.getFrames(path, true);
|
||||||
if (character.animateAtlas == null) {
|
|
||||||
character.animation.reset();
|
|
||||||
character.animateAtlas = new FlxAnimate(character.x, character.y);
|
|
||||||
} else
|
|
||||||
character.animateAtlas.anim.stop();
|
|
||||||
|
|
||||||
character.atlasPath = noExt;
|
animsWindow.displayWindowSprite.loadGraphicFromSprite(character);
|
||||||
character.animateAtlas.loadAtlas(noExt);
|
if (Assets.exists(Paths.image('characters/${character.sprite}')))
|
||||||
} else {
|
animsWindow.displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false));
|
||||||
if (character.animateAtlas != null) {
|
|
||||||
character.animateAtlas.destroy();
|
|
||||||
character.animateAtlas = null;
|
|
||||||
character.atlasPlayingAnim = character.atlasPath = null;
|
|
||||||
}
|
|
||||||
character.frames = Paths.getFrames(path, true);
|
|
||||||
|
|
||||||
animsWindow.displayWindowSprite.loadGraphicFromSprite(character);
|
|
||||||
if (Assets.exists(Paths.image('characters/${character.sprite}')))
|
|
||||||
animsWindow.displayWindowGraphic = FlxG.bitmap.add(Assets.getBitmapData(Paths.image('characters/${character.sprite}'), true, false));
|
|
||||||
}
|
|
||||||
|
|
||||||
character.animDatas.clear();
|
character.animDatas.clear();
|
||||||
for (anim in animsWindow.buttons) anim.checkValid(); // Re-add all animations
|
for (anim in animsWindow.buttons) anim.checkValid(); // Re-add all animations
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package funkin.editors.charter;
|
package funkin.editors.charter;
|
||||||
|
|
||||||
import funkin.game.HealthIcon;
|
|
||||||
import flixel.math.FlxPoint;
|
import flixel.math.FlxPoint;
|
||||||
import funkin.backend.chart.ChartData.ChartMetaData;
|
import funkin.backend.chart.ChartData.ChartMetaData;
|
||||||
import funkin.editors.extra.PropertyButton;
|
import funkin.editors.extra.PropertyButton;
|
||||||
@@ -22,7 +21,8 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
public var displayNameTextBox:UITextBox;
|
public var displayNameTextBox:UITextBox;
|
||||||
public var iconTextBox:UITextBox;
|
public var iconTextBox:UITextBox;
|
||||||
public var iconSprite:HealthIcon;
|
public var iconSprite:HealthIcon;
|
||||||
public var excludedGameModesList:UIAutoCompleteButtonList;
|
public var opponentModeCheckbox:UICheckbox;
|
||||||
|
public var coopAllowedCheckbox:UICheckbox;
|
||||||
public var needsVoicesCheckbox:UICheckbox;
|
public var needsVoicesCheckbox:UICheckbox;
|
||||||
public var colorWheel:UIColorwheel;
|
public var colorWheel:UIColorwheel;
|
||||||
public var difficultiesTextBox:UITextBox;
|
public var difficultiesTextBox:UITextBox;
|
||||||
@@ -78,29 +78,25 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
add(displayNameTextBox);
|
add(displayNameTextBox);
|
||||||
addLabelOn(displayNameTextBox, translate("displayName"));
|
addLabelOn(displayNameTextBox, translate("displayName"));
|
||||||
|
|
||||||
add(iconSprite = new HealthIcon(metadata.icon));
|
|
||||||
iconSprite.scale.set(0.5, 0.5);
|
|
||||||
iconSprite.updateHitbox();
|
|
||||||
|
|
||||||
iconTextBox = new UITextBox(displayNameTextBox.x + 320 + 26, displayNameTextBox.y, metadata.icon, 150);
|
iconTextBox = new UITextBox(displayNameTextBox.x + 320 + 26, displayNameTextBox.y, metadata.icon, 150);
|
||||||
iconTextBox.onChange = (newIcon:String) -> iconSprite.setIcon(newIcon);
|
iconTextBox.onChange = (newIcon:String) -> {updateIcon(newIcon);}
|
||||||
add(iconTextBox);
|
add(iconTextBox);
|
||||||
addLabelOn(iconTextBox, translate("icon"));
|
addLabelOn(iconTextBox, translate("icon"));
|
||||||
|
|
||||||
updateIcon(metadata.icon);
|
updateIcon(metadata.icon);
|
||||||
|
|
||||||
add(excludedGameModesList = new UIAutoCompleteButtonList(displayNameTextBox.x, iconTextBox.y + 62, Std.int(displayNameTextBox.bWidth), 100, "", [for (mode in funkin.menus.FreeplayState.FreeplayGameMode.get()) mode.modeID]));
|
opponentModeCheckbox = new UICheckbox(displayNameTextBox.x, iconTextBox.y + 10 + 32 + 26, translate("opponentMode"), metadata.opponentModeAllowed);
|
||||||
excludedGameModesList.frames = Paths.getFrames('editors/ui/inputbox');
|
add(opponentModeCheckbox);
|
||||||
excludedGameModesList.cameraSpacing = 0;
|
addLabelOn(opponentModeCheckbox, translate("modesAllowed"));
|
||||||
addLabelOn(excludedGameModesList, "Excluded Game Modes (IDs)");
|
|
||||||
for (mode in metadata.excludedGameModes)
|
coopAllowedCheckbox = new UICheckbox(opponentModeCheckbox.x + 150 + 26, opponentModeCheckbox.y, translate("coopAllowed"), metadata.coopAllowed);
|
||||||
excludedGameModesList.add(new UIAutoCompleteButtonList.UIAutoCompleteButton(0, 0, excludedGameModesList, excludedGameModesList.suggestItems, mode));
|
add(coopAllowedCheckbox);
|
||||||
|
|
||||||
colorWheel = new UIColorwheel(iconTextBox.x, coopAllowedCheckbox.y, metadata.color);
|
colorWheel = new UIColorwheel(iconTextBox.x, coopAllowedCheckbox.y, metadata.color);
|
||||||
add(colorWheel);
|
add(colorWheel);
|
||||||
addLabelOn(colorWheel, translate("color"));
|
addLabelOn(colorWheel, translate("color"));
|
||||||
|
|
||||||
difficultiesTextBox = new UITextBox(excludedGameModesList.x, excludedGameModesList.y + excludedGameModesList.bHeight + 32, metadata.difficulties.join(", "));
|
difficultiesTextBox = new UITextBox(opponentModeCheckbox.x, opponentModeCheckbox.y + 6 + 32 + 26, metadata.difficulties.join(", "));
|
||||||
add(difficultiesTextBox);
|
add(difficultiesTextBox);
|
||||||
addLabelOn(difficultiesTextBox, translate("difficulties"));
|
addLabelOn(difficultiesTextBox, translate("difficulties"));
|
||||||
|
|
||||||
@@ -115,6 +111,9 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
add(customPropertiesButtonList);
|
add(customPropertiesButtonList);
|
||||||
addLabelOn(customPropertiesButtonList, translate("customValues"));
|
addLabelOn(customPropertiesButtonList, translate("customValues"));
|
||||||
|
|
||||||
|
for (checkbox in [opponentModeCheckbox, coopAllowedCheckbox])
|
||||||
|
{checkbox.y += 6; checkbox.x += 4;}
|
||||||
|
|
||||||
saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, windowSpr.y + windowSpr.bHeight - 20, TU.translate("editor.saveClose"), function() {
|
saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, windowSpr.y + windowSpr.bHeight - 20, TU.translate("editor.saveClose"), function() {
|
||||||
saveMeta();
|
saveMeta();
|
||||||
close();
|
close();
|
||||||
@@ -162,7 +161,8 @@ class CharterMetaDataScreen extends UISubstateWindow {
|
|||||||
meta.displayName = displayNameTextBox.label.text;
|
meta.displayName = displayNameTextBox.label.text;
|
||||||
meta.icon = iconTextBox.label.text;
|
meta.icon = iconTextBox.label.text;
|
||||||
meta.color = colorWheel.curColor;
|
meta.color = colorWheel.curColor;
|
||||||
meta.excludedGameModes = [for (button in excludedGameModesList.buttons.members) button.textBox.label.text.trim()],
|
meta.opponentModeAllowed = opponentModeCheckbox.checked;
|
||||||
|
meta.coopAllowed = coopAllowedCheckbox.checked;
|
||||||
meta.difficulties = [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()];
|
meta.difficulties = [for (diff in difficultiesTextBox.label.text.split(",")) diff.trim()];
|
||||||
meta.customValues = customVals;
|
meta.customValues = customVals;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package funkin.editors.charter;
|
package funkin.editors.charter;
|
||||||
|
|
||||||
import funkin.game.HealthIcon;
|
|
||||||
import flixel.group.FlxGroup;
|
import flixel.group.FlxGroup;
|
||||||
import flixel.text.FlxText.FlxTextFormat;
|
import flixel.text.FlxText.FlxTextFormat;
|
||||||
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||||
@@ -38,7 +37,8 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
public var displayNameTextBox:UITextBox;
|
public var displayNameTextBox:UITextBox;
|
||||||
public var iconTextBox:UITextBox;
|
public var iconTextBox:UITextBox;
|
||||||
public var iconSprite:HealthIcon;
|
public var iconSprite:HealthIcon;
|
||||||
public var excludedGameModesList:UIAutoCompleteButtonList;
|
public var opponentModeCheckbox:UICheckbox;
|
||||||
|
public var coopAllowedCheckbox:UICheckbox;
|
||||||
public var colorWheel:UIColorwheel;
|
public var colorWheel:UIColorwheel;
|
||||||
public var difficultiesTextBox:UITextBox;
|
public var difficultiesTextBox:UITextBox;
|
||||||
|
|
||||||
@@ -166,19 +166,24 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
|
|
||||||
updateIcon("face");
|
updateIcon("face");
|
||||||
|
|
||||||
menuDataGroup.add(excludedGameModesList = new UIAutoCompleteButtonList(displayNameTextBox.x, iconTextBox.y + 62, Std.int(displayNameTextBox.bWidth), 100, "", [for (mode in funkin.menus.FreeplayState.FreeplayGameMode.get()) mode.modeID]));
|
opponentModeCheckbox = new UICheckbox(displayNameTextBox.x, iconTextBox.y + 10 + 32 + 26, translateMeta("opponentMode"), true);
|
||||||
excludedGameModesList.frames = Paths.getFrames('editors/ui/inputbox');
|
menuDataGroup.add(opponentModeCheckbox);
|
||||||
excludedGameModesList.cameraSpacing = 0;
|
addLabelOn(opponentModeCheckbox, translateMeta("modesAllowed"));
|
||||||
addLabelOn(excludedGameModesList, "Excluded Game Modes (IDs)");
|
|
||||||
|
|
||||||
colorWheel = new UIColorwheel(iconTextBox.x, excludedGameModesList.y, 0xFFFFFF);
|
coopAllowedCheckbox = new UICheckbox(opponentModeCheckbox.x + 150 + 26, opponentModeCheckbox.y, translateMeta("coopAllowed"), true);
|
||||||
|
menuDataGroup.add(coopAllowedCheckbox);
|
||||||
|
|
||||||
|
colorWheel = new UIColorwheel(iconTextBox.x, coopAllowedCheckbox.y, 0xFFFFFF);
|
||||||
menuDataGroup.add(colorWheel);
|
menuDataGroup.add(colorWheel);
|
||||||
addLabelOn(colorWheel, translateMeta("color"));
|
addLabelOn(colorWheel, translateMeta("color"));
|
||||||
|
|
||||||
difficultiesTextBox = new UITextBox(excludedGameModesList.x, excludedGameModesList.y + excludedGameModesList.bHeight + 32, "");
|
difficultiesTextBox = new UITextBox(opponentModeCheckbox.x, opponentModeCheckbox.y + 6 + 32 + 26, "");
|
||||||
menuDataGroup.add(difficultiesTextBox);
|
menuDataGroup.add(difficultiesTextBox);
|
||||||
addLabelOn(difficultiesTextBox, translateMeta("difficulties"));
|
addLabelOn(difficultiesTextBox, translateMeta("difficulties"));
|
||||||
|
|
||||||
|
for (checkbox in [opponentModeCheckbox, coopAllowedCheckbox])
|
||||||
|
{checkbox.y += 6; checkbox.x += 4;}
|
||||||
|
|
||||||
var menuTitle:UIText;
|
var menuTitle:UIText;
|
||||||
selectFormatGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, translate("importSource"), 28));
|
selectFormatGroup.add(menuTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, translate("importSource"), 28));
|
||||||
|
|
||||||
@@ -428,7 +433,8 @@ class SongCreationScreen extends UISubstateWindow {
|
|||||||
displayName: displayNameTextBox.label.text,
|
displayName: displayNameTextBox.label.text,
|
||||||
icon: iconTextBox.label.text,
|
icon: iconTextBox.label.text,
|
||||||
color: colorWheel.curColor,
|
color: colorWheel.curColor,
|
||||||
excludedGameModes: [for (button in excludedGameModesList.buttons.members) button.textBox.label.text.trim()],
|
opponentModeAllowed: opponentModeCheckbox.checked,
|
||||||
|
coopAllowed: coopAllowedCheckbox.checked,
|
||||||
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) if (diff.length > 0) diff.trim()]
|
difficulties: [for (diff in difficultiesTextBox.label.text.split(",")) if (diff.length > 0) diff.trim()]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -377,9 +377,7 @@ class StageEditor extends UIState {
|
|||||||
// Play first anim, and make it the last frame
|
// Play first anim, and make it the last frame
|
||||||
var animToPlay = char.getAnimOrder()[0];
|
var animToPlay = char.getAnimOrder()[0];
|
||||||
char.playAnim(animToPlay, true, NONE);
|
char.playAnim(animToPlay, true, NONE);
|
||||||
var lastIndx = (char.animateAtlas != null) ?
|
var lastIndx = char.animation.curAnim.numFrames - 1;
|
||||||
char.animateAtlas.anim.length - 1 :
|
|
||||||
char.animation.curAnim.numFrames - 1;
|
|
||||||
char.playAnim(animToPlay, true, NONE, false, lastIndx);
|
char.playAnim(animToPlay, true, NONE, false, lastIndx);
|
||||||
char.stopAnimation();
|
char.stopAnimation();
|
||||||
|
|
||||||
@@ -565,9 +563,7 @@ class StageEditor extends UIState {
|
|||||||
// Play first anim, and make it the last frame
|
// Play first anim, and make it the last frame
|
||||||
var animToPlay = char.getAnimOrder()[0];
|
var animToPlay = char.getAnimOrder()[0];
|
||||||
char.playAnim(animToPlay, true, NONE);
|
char.playAnim(animToPlay, true, NONE);
|
||||||
var lastIndx = (char.animateAtlas != null) ?
|
var lastIndx = char.animation.curAnim.numFrames - 1;
|
||||||
char.animateAtlas.anim.length - 1 :
|
|
||||||
char.animation.curAnim.numFrames - 1;
|
|
||||||
char.playAnim(animToPlay, true, NONE, false, lastIndx);
|
char.playAnim(animToPlay, true, NONE, false, lastIndx);
|
||||||
char.stopAnimation();
|
char.stopAnimation();
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
package funkin.editors.ui;
|
|
||||||
|
|
||||||
typedef UIAutoCompleteButtonList = UITypedAutoCompleteButtonList<UIAutoCompleteButton>;
|
|
||||||
|
|
||||||
class UITypedAutoCompleteButtonList<T:UIAutoCompleteButton> extends UIButtonList<T> {
|
|
||||||
public var suggestItems(default, set):Array<String> = [];
|
|
||||||
|
|
||||||
private function set_suggestItems(value:Array<String>) {
|
|
||||||
buttons.forEachAlive((button) -> button.textBox.suggestItems = value);
|
|
||||||
return suggestItems = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function new(x:Float, y:Float, width:Int, height:Int, windowName:String, ?suggestItems:Array<String>, ?buttonSize:FlxPoint, ?buttonOffset:FlxPoint, buttonSpacing:Float = 0) {
|
|
||||||
super(x, y, width, height, windowName, buttonSize == null ? FlxPoint.get(width, width * 0.15) : buttonSize, buttonOffset, buttonSpacing);
|
|
||||||
if (suggestItems != null && suggestItems.length > 0) this.suggestItems = suggestItems;
|
|
||||||
addButton.callback = () -> add(cast new UIAutoCompleteButton(0, 0, cast this, this.suggestItems));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class UIAutoCompleteButton extends UIButton {
|
|
||||||
public var textBox:UIAutoCompleteTextBox;
|
|
||||||
public var deleteButton:UIButton;
|
|
||||||
public var deleteIcon:FlxSprite;
|
|
||||||
|
|
||||||
public function new (x:Float, y:Float, parent:UIAutoCompleteButtonList, ?suggestItems:Array<String>, text:String = "", ?w:Int, ?h:Int, multiline:Bool = false) {
|
|
||||||
super(x, y, "", null, w == null ? Std.int(parent.buttonSize.x) : w, h == null ? Std.int(parent.buttonSize.y) : h);
|
|
||||||
|
|
||||||
members.push(textBox = new UIAutoCompleteTextBox(16, bHeight/2 - (32/2), text, Std.int(bWidth - 32 - 36), 32, multiline));
|
|
||||||
if (suggestItems != null && suggestItems.length > 0) textBox.suggestItems = suggestItems;
|
|
||||||
textBox.antialiasing = false;
|
|
||||||
|
|
||||||
members.push(deleteButton = new UIButton(textBox.x + textBox.bWidth + 10, textBox.y, "", () -> { parent.remove(this); destroy(); }, 32));
|
|
||||||
deleteButton.color = 0xFFFF0000;
|
|
||||||
deleteButton.autoAlpha = false;
|
|
||||||
|
|
||||||
members.push(deleteIcon = new FlxSprite(deleteButton.x + (15/2), deleteButton.y + 8).loadGraphic(Paths.image('editors/delete-button')));
|
|
||||||
deleteIcon.antialiasing = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
override function update(elapsed) {
|
|
||||||
deleteButton.y = y + bHeight / 2 - deleteButton.bHeight / 2;
|
|
||||||
textBox.y = y + bHeight/2 - 16;
|
|
||||||
deleteIcon.x = deleteButton.x + (15/2); deleteIcon.y = deleteButton.y + 8;
|
|
||||||
|
|
||||||
textBox.selectable = deleteButton.selectable = selectable;
|
|
||||||
deleteButton.shouldPress = shouldPress;
|
|
||||||
|
|
||||||
super.update(elapsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -3,7 +3,6 @@ package funkin.editors.ui;
|
|||||||
import flixel.util.typeLimit.OneOfTwo;
|
import flixel.util.typeLimit.OneOfTwo;
|
||||||
import flixel.text.FlxText.FlxTextFormat;
|
import flixel.text.FlxText.FlxTextFormat;
|
||||||
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
||||||
import flxanimate.data.SpriteMapData.AnimateAtlas;
|
|
||||||
import flixel.graphics.frames.FlxFramesCollection;
|
import flixel.graphics.frames.FlxFramesCollection;
|
||||||
import haxe.Json;
|
import haxe.Json;
|
||||||
import haxe.io.Bytes;
|
import haxe.io.Bytes;
|
||||||
@@ -11,6 +10,7 @@ import haxe.io.Path;
|
|||||||
import openfl.display.BitmapData;
|
import openfl.display.BitmapData;
|
||||||
import sys.FileSystem;
|
import sys.FileSystem;
|
||||||
import sys.io.File;
|
import sys.io.File;
|
||||||
|
import animate.FlxAnimateJson;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
using funkin.backend.utils.BitmapUtil;
|
using funkin.backend.utils.BitmapUtil;
|
||||||
@@ -122,7 +122,7 @@ class UIImageExplorer extends UIFileExplorer {
|
|||||||
for(file in files) {
|
for(file in files) {
|
||||||
if(SPRITEMAP_JSON_REGEX.match(file)) {
|
if(SPRITEMAP_JSON_REGEX.match(file)) {
|
||||||
var content:String = CoolUtil.removeBOM(File.getContent(Path.join([directoryPath, file])));
|
var content:String = CoolUtil.removeBOM(File.getContent(Path.join([directoryPath, file])));
|
||||||
var json:AnimateAtlas = Json.parse(content);
|
var json:SpritemapJson = Json.parse(content);
|
||||||
if(json.meta.image.toLowerCase() == fileName.toLowerCase())
|
if(json.meta.image.toLowerCase() == fileName.toLowerCase())
|
||||||
foundSpritemapJson = true;
|
foundSpritemapJson = true;
|
||||||
} else if(file == "Animation.json")
|
} else if(file == "Animation.json")
|
||||||
@@ -147,7 +147,7 @@ class UIImageExplorer extends UIFileExplorer {
|
|||||||
spritemaps.sort(Reflect.compare);
|
spritemaps.sort(Reflect.compare);
|
||||||
for(spritemap in spritemaps) {
|
for(spritemap in spritemaps) {
|
||||||
var content:String = CoolUtil.removeBOM(File.getContent(Path.join([directoryPath, spritemap])));
|
var content:String = CoolUtil.removeBOM(File.getContent(Path.join([directoryPath, spritemap])));
|
||||||
var json:AnimateAtlas = Json.parse(content);
|
var json:SpritemapJson = Json.parse(content);
|
||||||
var imageToFind:String = json.meta.image.toLowerCase();
|
var imageToFind:String = json.meta.image.toLowerCase();
|
||||||
for(file in files) {
|
for(file in files) {
|
||||||
// lowercase since windows does case insensitive stuff, so we use lowercase to match behavior on mac and linux
|
// lowercase since windows does case insensitive stuff, so we use lowercase to match behavior on mac and linux
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package funkin.game;
|
package funkin.game;
|
||||||
|
|
||||||
import sys.FileSystem;
|
|
||||||
import flixel.util.FlxSpriteUtil;
|
import flixel.util.FlxSpriteUtil;
|
||||||
import openfl.display.Graphics;
|
import openfl.display.Graphics;
|
||||||
import flixel.util.typeLimit.OneOfTwo;
|
import flixel.util.typeLimit.OneOfTwo;
|
||||||
@@ -26,6 +25,7 @@ import haxe.Exception;
|
|||||||
import haxe.io.Path;
|
import haxe.io.Path;
|
||||||
import haxe.xml.Access;
|
import haxe.xml.Access;
|
||||||
import openfl.geom.ColorTransform;
|
import openfl.geom.ColorTransform;
|
||||||
|
import animate.FlxAnimateFrames;
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
@@ -89,6 +89,8 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
scripts.call("create");
|
scripts.call("create");
|
||||||
buildCharacter(xml);
|
buildCharacter(xml);
|
||||||
scripts.call("postCreate");
|
scripts.call("postCreate");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@:noCompletion var __swappedLeftRightAnims:Bool = false;
|
@:noCompletion var __swappedLeftRightAnims:Bool = false;
|
||||||
@@ -118,7 +120,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (i in variants) {
|
for (i in variants) {
|
||||||
CoolUtil.switchAnimFrames(animation.getByName('singRIGHT$i'), animation.getByName('singLEFT$i'));
|
CoolUtil.swapAnims(animation, 'singLEFT$i', 'singRIGHT$i');
|
||||||
switchOffset('singLEFT$i', 'singRIGHT$i');
|
switchOffset('singLEFT$i', 'singRIGHT$i');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,9 +159,9 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
if (event.cancelled) return;
|
if (event.cancelled) return;
|
||||||
|
|
||||||
if (isDanceLeftDanceRight)
|
if (isDanceLeftDanceRight)
|
||||||
playAnim(((danced = !danced) ? 'danceLeft' : 'danceRight') + idleSuffix, DANCE);
|
playAnim(((danced = !danced) ? 'danceLeft' : 'danceRight') + idleSuffix, false, DANCE);
|
||||||
else
|
else
|
||||||
playAnim('idle' + idleSuffix, DANCE);
|
playAnim('idle' + idleSuffix, false, DANCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tryDance() {
|
public function tryDance() {
|
||||||
@@ -203,9 +205,11 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
|
|
||||||
@:noCompletion var __reverseDrawProcedure:Bool = false;
|
@:noCompletion var __reverseDrawProcedure:Bool = false;
|
||||||
public override function getScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect {
|
public override function getScreenBounds(?newRect:FlxRect, ?camera:FlxCamera):FlxRect {
|
||||||
if (__reverseDrawProcedure) {
|
if (isFlippedOffsets()) {
|
||||||
|
flipX = !flipX;
|
||||||
scale.x *= -1;
|
scale.x *= -1;
|
||||||
var bounds:FlxRect = super.getScreenBounds(newRect, camera);
|
var bounds:FlxRect = super.getScreenBounds(newRect, camera);
|
||||||
|
flipX = !flipX;
|
||||||
scale.x *= -1;
|
scale.x *= -1;
|
||||||
return bounds;
|
return bounds;
|
||||||
}
|
}
|
||||||
@@ -291,7 +295,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
|
|
||||||
super.playAnim(event.animName, event.force, event.context, event.reverse, event.startingFrame);
|
super.playAnim(event.animName, event.force, event.context, event.reverse, event.startingFrame);
|
||||||
|
|
||||||
offset.set(globalOffset.x * (isPlayer != playerOffsets ? 1 : -1), -globalOffset.y);
|
offset.set((isPlayer != playerOffsets) ? globalOffset.x : -globalOffset.x, -globalOffset.y);
|
||||||
if (event.context == SING || event.context == MISS)
|
if (event.context == SING || event.context == MISS)
|
||||||
lastHit = Conductor.songPosition;
|
lastHit = Conductor.songPosition;
|
||||||
}
|
}
|
||||||
@@ -352,7 +356,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
buildCharacter(xml);
|
buildCharacter(xml);
|
||||||
}
|
}
|
||||||
|
|
||||||
public inline function buildCharacter(xml:Access) {
|
public function buildCharacter(xml:Access) {
|
||||||
for(node in xml.elements)
|
for(node in xml.elements)
|
||||||
switch(node.name) {
|
switch(node.name) {
|
||||||
case "use-extension" | "extension" | "ext":
|
case "use-extension" | "extension" | "ext":
|
||||||
@@ -382,7 +386,22 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
updateHitbox();
|
updateHitbox();
|
||||||
}
|
}
|
||||||
if (xml.x.exists("antialiasing")) antialiasing = (xml.x.get("antialiasing") == "true");
|
if (xml.x.exists("antialiasing")) antialiasing = (xml.x.get("antialiasing") == "true");
|
||||||
|
if (xml.x.exists("applyStageMatrix")) applyStageMatrix = (xml.x.get("applyStageMatrix") == "true");
|
||||||
if (xml.x.exists("sprite")) sprite = xml.x.get("sprite");
|
if (xml.x.exists("sprite")) sprite = xml.x.get("sprite");
|
||||||
|
if (xml.x.exists("swfMode")) animateSettings.swfMode = (xml.x.get("swfMode") == "true");
|
||||||
|
if (xml.x.exists("cacheOnLoad")) animateSettings.cacheOnLoad = (xml.x.get("cacheOnLoad") == "true");
|
||||||
|
if (xml.x.exists("filterQuality")) {
|
||||||
|
var val = xml.x.get("filterQuality");
|
||||||
|
var qualityInt = Std.parseInt(val);
|
||||||
|
if (qualityInt != null) {
|
||||||
|
animateSettings.filterQuality = cast(qualityInt, FilterQuality);
|
||||||
|
} else {
|
||||||
|
var values = ["high", "medium", "low", "rudy"];
|
||||||
|
var index = values.indexOf(val.toLowerCase());
|
||||||
|
if (index > -1)
|
||||||
|
animateSettings.filterQuality = cast(index, FilterQuality);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var hasInterval:Bool = xml.x.exists("interval");
|
var hasInterval:Bool = xml.x.exists("interval");
|
||||||
if (hasInterval) beatInterval = Std.parseInt(xml.x.get("interval"));
|
if (hasInterval) beatInterval = Std.parseInt(xml.x.get("interval"));
|
||||||
@@ -421,10 +440,10 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
public static var characterProperties:Array<String> = [
|
public static var characterProperties:Array<String> = [
|
||||||
"x", "y", "sprite", "scale", "antialiasing",
|
"x", "y", "sprite", "scale", "antialiasing",
|
||||||
"flipX", "camx", "camy", "isPlayer", "icon",
|
"flipX", "camx", "camy", "isPlayer", "icon",
|
||||||
"color", "gameOverChar", "holdTime"
|
"color", "gameOverChar", "holdTime", "applyStageMatrix"
|
||||||
];
|
];
|
||||||
public static var characterAnimProperties:Array<String> = [
|
public static var characterAnimProperties:Array<String> = [
|
||||||
"name", "anim", "x", "y", "fps", "loop", "indices"
|
"name", "anim", "label", "x", "y", "fps", "loop", "indices"
|
||||||
];
|
];
|
||||||
|
|
||||||
public inline function buildXML(?animsOrder:Array<String>):Xml {
|
public inline function buildXML(?animsOrder:Array<String>):Xml {
|
||||||
@@ -451,6 +470,7 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
if (!antialiasing) xml.set("antialiasing", antialiasing == true ? "true" : "false");
|
if (!antialiasing) xml.set("antialiasing", antialiasing == true ? "true" : "false");
|
||||||
|
|
||||||
if (isPlayer) xml.set("isPlayer", isPlayer == true ? "true" : "false");
|
if (isPlayer) xml.set("isPlayer", isPlayer == true ? "true" : "false");
|
||||||
|
if (isAnimate) xml.set("applyStageMatrix", applyStageMatrix ? "true" : "false");
|
||||||
|
|
||||||
var anims:Array<AnimData> = [];
|
var anims:Array<AnimData> = [];
|
||||||
if (animsOrder != null) {
|
if (animsOrder != null) {
|
||||||
@@ -476,6 +496,9 @@ class Character extends FunkinSprite implements IBeatReceiver implements IOffset
|
|||||||
if (anim.indices.length > 0)
|
if (anim.indices.length > 0)
|
||||||
animXml.set("indices", CoolUtil.formatNumberRange(anim.indices));
|
animXml.set("indices", CoolUtil.formatNumberRange(anim.indices));
|
||||||
|
|
||||||
|
if (anim.label)
|
||||||
|
animXml.set("label", "true");
|
||||||
|
|
||||||
xml.addChild(animXml);
|
xml.addChild(animXml);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,6 @@ class HealthIcon extends FunkinSprite
|
|||||||
var iconSize:Int = 0;
|
var iconSize:Int = 0;
|
||||||
var iconIsPlayer = xmlValid ? xmlData.get("facing").getDefault("right").toLowerCase() == "left" : false;
|
var iconIsPlayer = xmlValid ? xmlData.get("facing").getDefault("right").toLowerCase() == "left" : false;
|
||||||
|
|
||||||
animateAtlas = null; // reset
|
|
||||||
if (this.animated)
|
if (this.animated)
|
||||||
loadSprite(Paths.image(newIconPath));
|
loadSprite(Paths.image(newIconPath));
|
||||||
else {
|
else {
|
||||||
@@ -184,8 +183,6 @@ class HealthIcon extends FunkinSprite
|
|||||||
|
|
||||||
if(!animation.onFinishEnd.has(animFinishCallback))
|
if(!animation.onFinishEnd.has(animFinishCallback))
|
||||||
animation.onFinishEnd.add(animFinishCallback);
|
animation.onFinishEnd.add(animFinishCallback);
|
||||||
if(animateAtlas != null && !animateAtlas.anim.onFinishEnd.has(animFinishCallback))
|
|
||||||
animateAtlas.anim.onFinishEnd.add(animFinishCallback);
|
|
||||||
|
|
||||||
var parsedSteps:Map<Int, String> = [];
|
var parsedSteps:Map<Int, String> = [];
|
||||||
|
|
||||||
@@ -233,10 +230,10 @@ class HealthIcon extends FunkinSprite
|
|||||||
offsetY = Std.parseFloat(node.get("offsety")).getDefault(0);
|
offsetY = Std.parseFloat(node.get("offsety")).getDefault(0);
|
||||||
|
|
||||||
addAnim(animName, node.get("anim"), Std.parseInt(node.get("fps")).getDefault(24), false, null, null, offsetX, offsetY); // don't allow looping for transitions
|
addAnim(animName, node.get("anim"), Std.parseInt(node.get("fps")).getDefault(24), false, null, null, offsetX, offsetY); // don't allow looping for transitions
|
||||||
if (animateAtlas == null && animation.exists(animName))
|
if (animation.exists(animName))
|
||||||
animation.getByName(animName).flipX = isPlayer != iconIsPlayer;
|
animation.getByName(animName).flipX = isPlayer != iconIsPlayer;
|
||||||
case "anim":
|
case "anim":
|
||||||
if (this.animated == false) {
|
if (!this.animated) {
|
||||||
Logs.trace('Icon ${char} data <anim> is not allowed when not animated', WARNING);
|
Logs.trace('Icon ${char} data <anim> is not allowed when not animated', WARNING);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -270,7 +267,7 @@ class HealthIcon extends FunkinSprite
|
|||||||
looped = node.get("loop").toLowerCase() == "true";
|
looped = node.get("loop").toLowerCase() == "true";
|
||||||
|
|
||||||
addAnim(animName, node.get("anim"), Std.parseInt(node.get("fps")).getDefault(24), looped, null, null, offsetX, offsetY);
|
addAnim(animName, node.get("anim"), Std.parseInt(node.get("fps")).getDefault(24), looped, null, null, offsetX, offsetY);
|
||||||
if (animateAtlas == null && animation.exists(animName))
|
if (animation.exists(animName))
|
||||||
animation.getByName(animName).flipX = isPlayer != iconIsPlayer;
|
animation.getByName(animName).flipX = isPlayer != iconIsPlayer;
|
||||||
case "step":
|
case "step":
|
||||||
if (!node.exists("percent")) {
|
if (!node.exists("percent")) {
|
||||||
@@ -314,18 +311,8 @@ class HealthIcon extends FunkinSprite
|
|||||||
curAnimState = data.animState;
|
curAnimState = data.animState;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (animateAtlas != null) {
|
setGraphicSize(150);
|
||||||
@:bypassAccessor
|
updateHitbox();
|
||||||
frameWidth = 150;
|
|
||||||
@:bypassAccessor
|
|
||||||
frameHeight = 150;
|
|
||||||
extraOffsets.x -= frameWidth / 2;
|
|
||||||
extraOffsets.y -= frameHeight / 2;
|
|
||||||
updateHitbox();
|
|
||||||
} else {
|
|
||||||
setGraphicSize(150);
|
|
||||||
updateHitbox();
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultScale = (xmlValid && xmlData.exists("scale")) ? Std.parseFloat(xmlData.get("scale")).getDefault(scale.x) : scale.x;
|
defaultScale = (xmlValid && xmlData.exists("scale")) ? Std.parseFloat(xmlData.get("scale")).getDefault(scale.x) : scale.x;
|
||||||
scale.set(defaultScale, defaultScale);
|
scale.set(defaultScale, defaultScale);
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ class Splash extends FunkinSprite
|
|||||||
@:privateAccess {
|
@:privateAccess {
|
||||||
spr.setPosition(source.x, source.y);
|
spr.setPosition(source.x, source.y);
|
||||||
spr.frames = source.frames;
|
spr.frames = source.frames;
|
||||||
if (source.animateAtlas != null && source.atlasPath != null)
|
|
||||||
spr.loadSprite(source.atlasPath);
|
|
||||||
spr.animation.copyFrom(source.animation);
|
spr.animation.copyFrom(source.animation);
|
||||||
spr.visible = source.visible;
|
spr.visible = source.visible;
|
||||||
spr.alpha = source.alpha;
|
spr.alpha = source.alpha;
|
||||||
@@ -29,8 +27,6 @@ class Splash extends FunkinSprite
|
|||||||
spr.scale.set(source.scale.x, source.scale.y);
|
spr.scale.set(source.scale.x, source.scale.y);
|
||||||
spr.scrollFactor.set(source.scrollFactor.x, source.scrollFactor.y);
|
spr.scrollFactor.set(source.scrollFactor.x, source.scrollFactor.y);
|
||||||
spr.skew.set(source.skew.x, source.skew.y);
|
spr.skew.set(source.skew.x, source.skew.y);
|
||||||
spr.transformMatrix = source.transformMatrix;
|
|
||||||
spr.matrixExposed = source.matrixExposed;
|
|
||||||
spr.zoomFactor = source.zoomFactor;
|
spr.zoomFactor = source.zoomFactor;
|
||||||
spr.animOffsets = source.animOffsets.copy();
|
spr.animOffsets = source.animOffsets.copy();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -174,8 +174,9 @@ class Strum extends FlxSprite {
|
|||||||
if (daNote.isSustainNote) offset.y -= height * 0.5;
|
if (daNote.isSustainNote) offset.y -= height * 0.5;
|
||||||
|
|
||||||
if (Std.int(daNote.__noteAngle % 360) != 0) {
|
if (Std.int(daNote.__noteAngle % 360) != 0) {
|
||||||
var noteAngleCos = FlxMath.fastCos(daNote.__noteAngle / PIX180);
|
var noteAngle = FlxMath.fastSinCos(daNote.__noteAngle / PIX180);
|
||||||
var noteAngleSin = FlxMath.fastSin(daNote.__noteAngle / PIX180);
|
var noteAngleCos = noteAngle.cos;
|
||||||
|
var noteAngleSin = noteAngle.sin;
|
||||||
|
|
||||||
var aOffset:FlxPoint = FlxPoint.get(
|
var aOffset:FlxPoint = FlxPoint.get(
|
||||||
(daNote.origin.x / daNote.scale.x) - daNote.offset.x,
|
(daNote.origin.x / daNote.scale.x) - daNote.offset.x,
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import funkin.backend.scripting.events.menu.freeplay.*;
|
|||||||
import funkin.backend.system.Conductor;
|
import funkin.backend.system.Conductor;
|
||||||
import funkin.game.HealthIcon;
|
import funkin.game.HealthIcon;
|
||||||
import funkin.savedata.FunkinSave;
|
import funkin.savedata.FunkinSave;
|
||||||
import haxe.io.Path;
|
|
||||||
|
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
@@ -35,11 +34,6 @@ class FreeplayState extends MusicBeatState
|
|||||||
*/
|
*/
|
||||||
public var curDiffMetaKeys:Array<String> = [];
|
public var curDiffMetaKeys:Array<String> = [];
|
||||||
|
|
||||||
/*
|
|
||||||
* Array containing all labels for game modes.
|
|
||||||
*/
|
|
||||||
public var gameModeLabels:Array<FreeplayGameMode> = [];
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently selected song
|
* Currently selected song
|
||||||
*/
|
*/
|
||||||
@@ -49,9 +43,9 @@ class FreeplayState extends MusicBeatState
|
|||||||
*/
|
*/
|
||||||
public var curDifficulty:Int = 1;
|
public var curDifficulty:Int = 1;
|
||||||
/**
|
/**
|
||||||
* Currently selected game mode
|
* Currently selected coop/opponent mode
|
||||||
*/
|
*/
|
||||||
public var curGameMode:Int = 0;
|
public var curCoopMode:Int = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text containing the score info (PERSONAL BEST: 0)
|
* Text containing the score info (PERSONAL BEST: 0)
|
||||||
@@ -64,9 +58,9 @@ class FreeplayState extends MusicBeatState
|
|||||||
public var diffText:FlxText;
|
public var diffText:FlxText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Text containing the current game mode, for example: ([KEYBINDS] Co-Op mode)
|
* Text containing the current coop/opponent mode ([KEYBINDS] Co-Op mode)
|
||||||
*/
|
*/
|
||||||
public var gameModeText:FlxText;
|
public var coopText:FlxText;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently lerped score. Is updated to go towards `intendedScore`.
|
* Currently lerped score. Is updated to go towards `intendedScore`.
|
||||||
@@ -136,7 +130,6 @@ class FreeplayState extends MusicBeatState
|
|||||||
}
|
}
|
||||||
|
|
||||||
updateCurSong();
|
updateCurSong();
|
||||||
gameModeLabels = FreeplayGameMode.get();
|
|
||||||
|
|
||||||
DiscordUtil.call("onMenuLoaded", ["Freeplay"]);
|
DiscordUtil.call("onMenuLoaded", ["Freeplay"]);
|
||||||
|
|
||||||
@@ -184,15 +177,14 @@ class FreeplayState extends MusicBeatState
|
|||||||
diffText.font = scoreText.font;
|
diffText.font = scoreText.font;
|
||||||
add(diffText);
|
add(diffText);
|
||||||
|
|
||||||
gameModeText = new FlxText(diffText.x, diffText.y + diffText.height + 2, 0, "", 24);
|
coopText = new FlxText(diffText.x, diffText.y + diffText.height + 2, 0, "", 24);
|
||||||
gameModeText.font = scoreText.font;
|
coopText.font = scoreText.font;
|
||||||
add(gameModeText);
|
add(coopText);
|
||||||
|
|
||||||
add(scoreText);
|
add(scoreText);
|
||||||
|
|
||||||
changeSelection(0, true);
|
changeSelection(0, true);
|
||||||
changeDiff(0, true);
|
changeCoopMode(0, true);
|
||||||
changeGameMode(0, true);
|
|
||||||
|
|
||||||
interpColor = new FlxInterpolateColor(bg.color);
|
interpColor = new FlxInterpolateColor(bg.color);
|
||||||
}
|
}
|
||||||
@@ -247,17 +239,17 @@ class FreeplayState extends MusicBeatState
|
|||||||
if (canSelect) {
|
if (canSelect) {
|
||||||
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
|
changeSelection((controls.UP_P ? -1 : 0) + (controls.DOWN_P ? 1 : 0) - FlxG.mouse.wheel);
|
||||||
changeDiff((controls.LEFT_P ? -1 : 0) + (controls.RIGHT_P ? 1 : 0));
|
changeDiff((controls.LEFT_P ? -1 : 0) + (controls.RIGHT_P ? 1 : 0));
|
||||||
changeGameMode((controls.CHANGE_MODE ? 1 : 0));
|
changeCoopMode((controls.CHANGE_MODE ? 1 : 0)); // TODO: make this configurable
|
||||||
// putting it before so that its actually smooth
|
// putting it before so that its actually smooth
|
||||||
updateOptionsAlpha();
|
updateOptionsAlpha();
|
||||||
}
|
}
|
||||||
|
|
||||||
scoreText.text = TEXT_FREEPLAY_SCORE.format([Math.round(lerpScore)]);
|
scoreText.text = TEXT_FREEPLAY_SCORE.format([Math.round(lerpScore)]);
|
||||||
scoreBG.scale.set(MathUtil.maxSmart(diffText.width, scoreText.width, gameModeText.width) + 8, (gameModeText.visible ? gameModeText.y + gameModeText.height : 66));
|
scoreBG.scale.set(MathUtil.maxSmart(diffText.width, scoreText.width, coopText.width) + 8, (coopText.visible ? coopText.y + coopText.height : 66));
|
||||||
scoreBG.updateHitbox();
|
scoreBG.updateHitbox();
|
||||||
scoreBG.x = FlxG.width - scoreBG.width;
|
scoreBG.x = FlxG.width - scoreBG.width;
|
||||||
|
|
||||||
scoreText.x = gameModeText.x = scoreBG.x + 4;
|
scoreText.x = coopText.x = scoreBG.x + 4;
|
||||||
diffText.x = Std.int(scoreBG.x + ((scoreBG.width - diffText.width) / 2));
|
diffText.x = Std.int(scoreBG.x + ((scoreBG.width - diffText.width) / 2));
|
||||||
|
|
||||||
interpColor.fpsLerpTo(curSong.color, 0.0625);
|
interpColor.fpsLerpTo(curSong.color, 0.0625);
|
||||||
@@ -318,13 +310,31 @@ class FreeplayState extends MusicBeatState
|
|||||||
select();
|
select();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var __opponentMode:Bool = false;
|
||||||
|
var __coopMode:Bool = false;
|
||||||
|
|
||||||
|
function updateCoopModes() {
|
||||||
|
__opponentMode = false;
|
||||||
|
__coopMode = false;
|
||||||
|
if (curSong.coopAllowed && curSong.opponentModeAllowed) {
|
||||||
|
__opponentMode = curCoopMode % 2 == 1;
|
||||||
|
__coopMode = curCoopMode >= 2;
|
||||||
|
} else if (curSong.coopAllowed) {
|
||||||
|
__coopMode = curCoopMode == 1;
|
||||||
|
} else if (curSong.opponentModeAllowed) {
|
||||||
|
__opponentMode = curCoopMode == 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Selects the current song.
|
* Selects the current song.
|
||||||
*/
|
*/
|
||||||
public function select() {
|
public function select() {
|
||||||
|
updateCoopModes();
|
||||||
|
|
||||||
if (curDifficulties.length == 0) return;
|
if (curDifficulties.length == 0) return;
|
||||||
|
|
||||||
var event = event("onSelect", EventManager.get(FreeplaySongSelectEvent).recycle(curSong.name, curDifficulties[curDifficulty], curSong.variant, gameModeLabels[curGameMode]));
|
var event = event("onSelect", EventManager.get(FreeplaySongSelectEvent).recycle(curSong.name, curDifficulties[curDifficulty], curSong.variant, __opponentMode, __coopMode));
|
||||||
|
|
||||||
if (event.cancelled) return;
|
if (event.cancelled) return;
|
||||||
|
|
||||||
@@ -383,7 +393,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
intendedScore = 0;
|
intendedScore = 0;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
updateCoopModes();
|
||||||
var changes:Array<HighscoreChange> = [];
|
var changes:Array<HighscoreChange> = [];
|
||||||
if (__coopMode) changes.push(CCoopMode);
|
if (__coopMode) changes.push(CCoopMode);
|
||||||
if (__opponentMode) changes.push(COpponentMode);
|
if (__opponentMode) changes.push(COpponentMode);
|
||||||
@@ -391,37 +401,45 @@ class FreeplayState extends MusicBeatState
|
|||||||
intendedScore = saveData.score;
|
intendedScore = saveData.score;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Array containing all labels for Co-Op / Opponent modes.
|
||||||
|
*/
|
||||||
|
public var coopLabels:Array<String> = [
|
||||||
|
TU.translate("freeplay.solo"),
|
||||||
|
TU.translate("freeplay.opponentMode"),
|
||||||
|
TU.translate("freeplay.coopMode"),
|
||||||
|
TU.translate("freeplay.coopModeSwitched")
|
||||||
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the current coop mode context.
|
* Change the current coop mode context.
|
||||||
* @param change How much to change
|
* @param change How much to change
|
||||||
* @param force Force the change, even if `change` is equal to 0.
|
* @param force Force the change, even if `change` is equal to 0.
|
||||||
*/
|
*/
|
||||||
public function changeGameMode(change:Int = 0, force:Bool = false) {
|
public function changeCoopMode(change:Int = 0, force:Bool = false) {
|
||||||
if (change == 0 && !force) return;
|
if (change == 0 && !force) return;
|
||||||
|
if (!curSong.coopAllowed && !curSong.opponentModeAllowed) return;
|
||||||
|
|
||||||
var i = 0;
|
var bothEnabled = curSong.coopAllowed && curSong.opponentModeAllowed;
|
||||||
var allowed = getAllowedGameModesID();
|
var event = event("onChangeCoopMode", EventManager.get(MenuChangeEvent).recycle(curCoopMode, FlxMath.wrap(curCoopMode + change, 0, bothEnabled ? 3 : 1), change));
|
||||||
var wrapped = FlxMath.wrap(curGameMode + change, 0, gameModeLabels.length - 1);
|
|
||||||
while (!allowed.contains(gameModeLabels[wrapped].modeID)) { // Skipping the blacklisted ones - Nex
|
|
||||||
wrapped = FlxMath.wrap(wrapped + change, 0, gameModeLabels.length - 1);
|
|
||||||
if (i++ > allowed.length) {
|
|
||||||
curGameMode = 0; // Idk honestly if I should modify the other event's variables - Nex
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var e = EventManager.get(MenuChangeEvent).recycle(curGameMode, wrapped, change);
|
if (event.cancelled) return;
|
||||||
event("onChangeCoopMode", e); // Backwards compat - Nex
|
|
||||||
if (event("onChangeGameMode", e).cancelled) return;
|
curCoopMode = event.value;
|
||||||
|
|
||||||
// Getting from scratch the allowed game modes just in case they changed when the event got called - Nex
|
|
||||||
if (gameModeText.visible = getAllowedGameModesID().length > 0) gameModeText.text = "[TAB] " + gameModeLabels[curGameMode = e.value].modeName;
|
|
||||||
updateScore();
|
updateScore();
|
||||||
}
|
|
||||||
|
|
||||||
public inline function getAllowedGameModesID() {
|
var coopBinds = [CoolUtil.keyToString(Options.P1_CHANGE_MODE[0]), CoolUtil.keyToString(Options.P2_CHANGE_MODE[0])].filter(x -> x != "---");
|
||||||
var excluded = songs[curSelected].excludedGameModes;
|
if (coopBinds.length == 2 && coopBinds[1] == coopBinds[0]) coopBinds.pop();
|
||||||
return [for (mode in gameModeLabels) if (!excluded.contains(mode.modeID)) mode.modeID];
|
else if (coopBinds.length == 0) coopBinds.push("---");
|
||||||
|
|
||||||
|
var key = '[${coopBinds.join(" / ")}] ';
|
||||||
|
|
||||||
|
if (bothEnabled) {
|
||||||
|
coopText.text = key + coopLabels[curCoopMode];
|
||||||
|
} else {
|
||||||
|
coopText.text = key + coopLabels[curCoopMode * (curSong.coopAllowed ? 2 : 1)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -447,12 +465,13 @@ class FreeplayState extends MusicBeatState
|
|||||||
}
|
}
|
||||||
|
|
||||||
changeDiff(0, true);
|
changeDiff(0, true);
|
||||||
changeGameMode(0, true);
|
|
||||||
|
|
||||||
#if PRELOAD_ALL
|
#if PRELOAD_ALL
|
||||||
autoplayElapsed = 0;
|
autoplayElapsed = 0;
|
||||||
songInstPlaying = false;
|
songInstPlaying = false;
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
coopText.visible = curSong.coopAllowed || curSong.opponentModeAllowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateOptionsAlpha() {
|
function updateOptionsAlpha() {
|
||||||
@@ -467,7 +486,7 @@ class FreeplayState extends MusicBeatState
|
|||||||
|
|
||||||
iconArray[curSelected].alpha = selectedAlpha;
|
iconArray[curSelected].alpha = selectedAlpha;
|
||||||
|
|
||||||
for (i => item in grpSongs.members)
|
for (i=>item in grpSongs.members)
|
||||||
{
|
{
|
||||||
item.targetY = i - curSelected;
|
item.targetY = i - curSelected;
|
||||||
|
|
||||||
@@ -498,118 +517,6 @@ class FreeplayState extends MusicBeatState
|
|||||||
else if ((curSong = song.metas.get(curDiffMetaKeys[curDifficulty])) == null)
|
else if ((curSong = song.metas.get(curDiffMetaKeys[curDifficulty])) == null)
|
||||||
curSong = song;
|
curSong = song;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Backwards compat
|
|
||||||
@:noCompletion public function changeCoopMode(change:Int = 0, force:Bool = false) return changeGameMode(change, force);
|
|
||||||
|
|
||||||
@:noCompletion public var coopText(get, set):FlxText;
|
|
||||||
@:noCompletion private function get_coopText() return gameModeText;
|
|
||||||
@:noCompletion private function set_coopText(val:FlxText) return gameModeText = val;
|
|
||||||
|
|
||||||
@:noCompletion function updateCoopModes() {}
|
|
||||||
@:noCompletion var __opponentMode(get, default):Bool = false; // God this is so cursed - Nex
|
|
||||||
@:noCompletion private function get___opponentMode() return getAllowedGameModesID().contains("codename.opponent");
|
|
||||||
@:noCompletion var __coopMode(get, default):Bool = false;
|
|
||||||
@:noCompletion private function get___coopMode() return getAllowedGameModesID().contains("codename.coop");
|
|
||||||
|
|
||||||
@:noCompletion var curCoopMode(get, set):Int;
|
|
||||||
@:noCompletion private function get_curCoopMode() return curGameMode;
|
|
||||||
@:noCompletion private function set_curCoopMode(val:Int) return curGameMode = val;
|
|
||||||
|
|
||||||
@:noCompletion var coopLabels(get, set):Array<String>;
|
|
||||||
@:noCompletion private function get_coopLabels() return [for(mode in gameModeLabels) mode.modeName];
|
|
||||||
@:noCompletion private function set_coopLabels(names:Array<String>) {
|
|
||||||
gameModeLabels = [for(name in names) {
|
|
||||||
if (name.startsWith("[TAB] ")) name = name.substr("[TAB] ".length);
|
|
||||||
new FreeplayGameMode(name, switch(name) {
|
|
||||||
case "Solo": "codename.solo";
|
|
||||||
case "Opponent Mode": "codename.opponent";
|
|
||||||
case "Co-Op Mode": "codename.coop";
|
|
||||||
case "Co-Op Mode (Switched)": "codename.coop-opponent";
|
|
||||||
default: name.toLowerCase().replace(" ", "-");
|
|
||||||
}, switch(name) {
|
|
||||||
case "Solo": ["solo"];
|
|
||||||
case "Opponent Mode": ["opponent"];
|
|
||||||
case "Co-Op Mode": ["coop"];
|
|
||||||
case "Co-Op Mode (Switched)": ["coop-switched", "opponent", "coop"];
|
|
||||||
default: null;
|
|
||||||
});
|
|
||||||
}];
|
|
||||||
return names;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Class used for the Freeplay menu game modes.
|
|
||||||
*
|
|
||||||
* **NOTE**: `fields` is useable not just for boolean values!!
|
|
||||||
*/
|
|
||||||
class FreeplayGameMode {
|
|
||||||
public var modeName:String;
|
|
||||||
public var modeID:String;
|
|
||||||
public var scripts(default, set):Array<String>;
|
|
||||||
public var fields(default, set):Dynamic;
|
|
||||||
|
|
||||||
@:noCompletion function set_scripts(val:Array<String>) return scripts = (val == null ? [] : val);
|
|
||||||
@:noCompletion function set_fields(val:Dynamic) return fields = (val == null ? {} : val);
|
|
||||||
|
|
||||||
public function new(modeName:String, modeID:String, ?scripts:Array<String>, ?fields:Dynamic) {
|
|
||||||
this.modeName = modeName;
|
|
||||||
this.modeID = modeID;
|
|
||||||
this.scripts = scripts;
|
|
||||||
this.fields = fields;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function toModifiers():Array<Dynamic> {
|
|
||||||
var fields = this.fields;
|
|
||||||
var modifiers:Array<Dynamic> = [];
|
|
||||||
for (field in {var _ = Reflect.fields(fields); _.sort(Reflect.compare); _;}) {
|
|
||||||
var val:Dynamic = Reflect.field(fields, field);
|
|
||||||
if (val != null && val != false) { // allow true, and floats/ints
|
|
||||||
modifiers.push(field);
|
|
||||||
modifiers.push(val);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return modifiers;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static inline function generateDefault() return new FreeplayGameMode("Solo Mode", "solo");
|
|
||||||
|
|
||||||
public static inline function getGameModesFromSource(source:AssetSource = BOTH, useTxt:Bool = true):Array<FreeplayGameMode> {
|
|
||||||
var path = 'data/gamemodes';
|
|
||||||
var txt = Paths.txt('gamemodes/list');
|
|
||||||
var list = useTxt && Paths.assetsTree.existsSpecific(txt, "TEXT", source) ? CoolUtil.coolTextFile(txt) : Paths.getFolderContent(path, false, source);
|
|
||||||
|
|
||||||
return [for (file in list) {
|
|
||||||
if (useTxt) file += ".json";
|
|
||||||
else if (Path.extension(file) != "json") continue;
|
|
||||||
|
|
||||||
var meta:FreeplayGameMode = null;
|
|
||||||
try {
|
|
||||||
var data = CoolUtil.parseJson(Paths.file(path + "/" + file)); var id = data.modeID;
|
|
||||||
meta = new FreeplayGameMode(CoolUtil.getDefault(data.displayName, id), id, [Path.withoutExtension(file)].concat(CoolUtil.getDefault(data.scripts, [])), data.fields);
|
|
||||||
} catch(e) Logs.trace('Failed to load game mode metadata for $file ($path): ${Std.string(e)}', ERROR);
|
|
||||||
if (meta != null) meta;
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
public static function get(useTxt:Bool = true):Array<FreeplayGameMode> {
|
|
||||||
var list:Array<FreeplayGameMode>;
|
|
||||||
|
|
||||||
switch(Flags.GAME_MODES_LIST_MOD_MODE) {
|
|
||||||
case 'prepend':
|
|
||||||
list = getGameModesFromSource(MODS, useTxt).concat(getGameModesFromSource(SOURCE, useTxt));
|
|
||||||
case 'append':
|
|
||||||
list = getGameModesFromSource(SOURCE, useTxt).concat(getGameModesFromSource(MODS, useTxt));
|
|
||||||
case 'override':
|
|
||||||
list = getGameModesFromSource(BOTH, useTxt);
|
|
||||||
default /*case 'oneOFtwo'*/:
|
|
||||||
if ((list = getGameModesFromSource(MODS, useTxt)).length == 0)
|
|
||||||
list = getGameModesFromSource(SOURCE, useTxt);
|
|
||||||
}
|
|
||||||
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class FreeplaySonglist {
|
class FreeplaySonglist {
|
||||||
@@ -646,9 +553,7 @@ class FreeplaySonglist {
|
|||||||
case 'append':
|
case 'append':
|
||||||
songList.getSongsFromSource(SOURCE, useTxt);
|
songList.getSongsFromSource(SOURCE, useTxt);
|
||||||
songList.getSongsFromSource(MODS, useTxt);
|
songList.getSongsFromSource(MODS, useTxt);
|
||||||
case 'override':
|
default /*case 'override'*/:
|
||||||
songList.getSongsFromSource(BOTH, useTxt);
|
|
||||||
default /*case 'oneOFtwo'*/:
|
|
||||||
if (songList.getSongsFromSource(MODS, useTxt))
|
if (songList.getSongsFromSource(MODS, useTxt))
|
||||||
songList.getSongsFromSource(SOURCE, useTxt);
|
songList.getSongsFromSource(SOURCE, useTxt);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,17 +342,10 @@ class StoryWeeklist {
|
|||||||
public function new() {}
|
public function new() {}
|
||||||
|
|
||||||
public function getWeeksFromSource(source:funkin.backend.assets.AssetSource, useTxt:Bool = true, loadCharactersData:Bool = true) {
|
public function getWeeksFromSource(source:funkin.backend.assets.AssetSource, useTxt:Bool = true, loadCharactersData:Bool = true) {
|
||||||
var weeksFound:Array<String> = null;
|
var path:String = Paths.txt('weeks/weeks');
|
||||||
if (useTxt) {
|
var weeksFound:Array<String> = useTxt && Paths.assetsTree.existsSpecific(path, "TEXT", source) ? CoolUtil.coolTextFile(path) :
|
||||||
var oldPath:String = Paths.txt('weeks/weeks');
|
[for (c in Paths.getFolderContent('data/weeks/weeks/', false, source)) if (Path.extension(c).toLowerCase() == "xml") Path.withoutExtension(c)];
|
||||||
var newPath:String = Paths.txt('config/weeks');
|
|
||||||
if (Paths.assetsTree.existsSpecific(newPath, "TEXT", source)) weeksFound = CoolUtil.coolTextFile(newPath);
|
|
||||||
else if (Paths.assetsTree.existsSpecific(oldPath, "TEXT", source)) {
|
|
||||||
Logs.warn("data/weeks/weeks.txt is deprecated and will be removed in the future. Please move the file to data/config/", DARKYELLOW, "StoryWeeklist");
|
|
||||||
weeksFound = CoolUtil.coolTextFile(oldPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (weeksFound == null) weeksFound = [for (c in Paths.getFolderContent('data/weeks/weeks/', false, source)) if (Path.extension(c).toLowerCase() == "xml") Path.withoutExtension(c)];
|
|
||||||
if (weeksFound.length > 0) {
|
if (weeksFound.length > 0) {
|
||||||
for (w in weeksFound) {
|
for (w in weeksFound) {
|
||||||
var week = Week.loadWeek(w, loadCharactersData);
|
var week = Week.loadWeek(w, loadCharactersData);
|
||||||
|
|||||||