diff --git a/.github/workflows/Android Buildyml b/.github/workflows/Android Buildyml
new file mode 100644
index 00000000000..8d40311097a
--- /dev/null
+++ b/.github/workflows/Android Buildyml
@@ -0,0 +1,80 @@
+# This is a basic workflow to help you get started with Actions
+
+name: Android Build CI
+
+# Controls when the workflow will run
+on: [push, pull_request, workflow_dispatch]
+
+# A workflow run is made up of one or more jobs that can run sequentially or in parallel
+jobs:
+ # This workflow contains a single job called "build"
+ build:
+ # The type of runner that the job will run on
+ runs-on: ubuntu-latest
+
+ # Steps represent a sequence of tasks that will be executed as part of the job
+ steps:
+ # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
+ - uses: actions/checkout@v2
+ - uses: krdlab/setup-haxe@v1
+ with:
+ haxe-version: 4.2.3
+
+ - name: Cache haxelib path
+ uses: actions/cache@v2
+ with:
+ path: |
+ %HAXELIB_ROOT%
+ key: ${{ runner.os }}-android
+
+ - name: Setup Android SDK Tools
+ uses: android-actions/setup-android@v2.0.2
+
+ - name: Setup Java JDK
+ uses: actions/setup-java@v2.3.1
+ with:
+ distribution: 'zulu'
+ java-version: '11'
+
+ - uses: nttld/setup-ndk@v1
+ with:
+ ndk-version: r20b
+
+ # Runs a set of commands using the runners shell
+ - name: script run line haha
+ run: |
+ mkdir -p "%HAXELIB_ROOT%"
+ haxelib setup "%HAXELIB_ROOT%"
+ haxelib install lime 7.9.0 --quiet
+ haxelib install openfl --quiet
+ haxelib install flixel 4.9.0 --quiet
+ haxelib install hxcpp --quiet
+ haxelib run lime setup
+ haxelib run lime config ANDROID_SDK $ANDROID_SDK_ROOT
+ haxelib run lime config ANDROID_NDK_ROOT $ANDROID_NDK_ROOT
+ haxelib run lime config JAVA_HOME $JAVA_HOME
+ haxelib run lime config ANDROID_SETUP true
+ haxelib install flixel-tools --quiet
+ haxelib install flixel-ui --quiet
+ haxelib install flixel-addons 2.10.0 --quiet
+ haxelib install hscript --quiet
+ haxelib git faxe https://github.com/uhrobots/faxe --quiet
+ haxelib git polymod https://github.com/MasterEric/polymod.git --quiet
+ haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc --quiet
+ haxelib git extension-webm https://github.com/KlavierGayming/extension-webm --quiet
+ haxelib git linc_luajit https://github.com/Sirox228/linc_luajit
+ haxelib run lime config HXCPP_ARM64 true
+ haxelib run lime config HXCPP_x86 true
+ haxelib install actuate
+ haxelib run lime rebuild extension-webm android
+ haxelib list
+
+ - name: Build Log
+ run: |
+ haxelib run lime setup android
+ haxelib run lime build android -final
+
+ - uses: actions/upload-artifact@v2
+ with:
+ name: Android Build
+ path: export/release/android/bin/app/build/outputs/apk/debug
diff --git a/.github/workflows/html5.yml b/.github/workflows/html5.yml
deleted file mode 100644
index bf1844688bc..00000000000
--- a/.github/workflows/html5.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: HTML5 Build CI
-
-# Controls when the workflow will run
-on: [push, pull_request]
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
- runs-on: ubuntu-latest
-
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
- - uses: krdlab/setup-haxe@v1
- with:
- haxe-version: 4.1.5
- # Runs a set of commands using the runners shell
- - name: script run line haha
- run: |
- sudo add-apt-repository ppa:haxe/releases -y
- sudo apt-get update
- sudo apt-get install gcc-multilib g++-multilib haxe -y
- mkdir "%HAXELIB_ROOT%"
- haxelib setup "%HAXELIB_ROOT%"
- haxelib install lime 7.9.0
- haxelib install openfl
- haxelib install flixel
- haxelib run lime setup flixel
- haxelib run lime setup
- haxelib install flixel-tools
- haxelib install flixel-addons
- haxelib install flixel-ui
- haxelib install hscript
- haxelib install flixel-addons
- haxelib git faxe https://github.com/uhrobots/faxe
- haxelib git polymod https://github.com/MasterEric/polymod.git
- haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc
- haxelib git extension-webm https://github.com/KadeDev/extension-webm
- haxelib run lime rebuild extension-webm linux
- haxelib git linc_luajit https://github.com/MasterEric/linc_luajit.git
- haxelib git hxvm-luajit https://github.com/nebulazorua/hxvm-luajit.git
- haxelib install actuate
- haxelib list
- haxelib run lime build html5
-
- - uses: actions/upload-artifact@v2
- with:
- name: HTML5 Build
- path: export/release/html5/bin
diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml
deleted file mode 100644
index 924795d799a..00000000000
--- a/.github/workflows/linux.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: Linux Build CI
-
-# Controls when the workflow will run
-on: [push, pull_request]
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
- runs-on: ubuntu-latest
-
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
- - uses: krdlab/setup-haxe@v1
- with:
- haxe-version: 4.1.5
- # Runs a set of commands using the runners shell
- - name: script run line haha
- run: |
- sudo add-apt-repository ppa:haxe/releases -y
- sudo apt-get update
- sudo apt-get install gcc-multilib g++-multilib haxe -y
- mkdir "%HAXELIB_ROOT%"
- haxelib setup "%HAXELIB_ROOT%"
- haxelib install lime 7.9.0
- haxelib install openfl
- haxelib install flixel
- haxelib run lime setup flixel
- haxelib run lime setup
- haxelib install flixel-tools
- haxelib install flixel-addons
- haxelib install flixel-ui
- haxelib install hscript
- haxelib install flixel-addons
- haxelib git faxe https://github.com/uhrobots/faxe
- haxelib git polymod https://github.com/MasterEric/polymod.git
- haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc
- haxelib git extension-webm https://github.com/KadeDev/extension-webm
- haxelib run lime rebuild extension-webm linux
- haxelib git linc_luajit https://github.com/MasterEric/linc_luajit.git
- haxelib git hxvm-luajit https://github.com/nebulazorua/hxvm-luajit.git
- haxelib install actuate
- haxelib list
- haxelib run lime build linux
-
- - uses: actions/upload-artifact@v2
- with:
- name: Linux Build
- path: export/release/linux/bin
diff --git a/.github/workflows/staleIssue.yml b/.github/workflows/staleIssue.yml
deleted file mode 100644
index af2fcd50681..00000000000
--- a/.github/workflows/staleIssue.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Close inactive issues
-on: [workflow_dispatch]
-
-jobs:
- close-issues:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/stale@v3
- with:
- days-before-issue-stale: 7
- days-before-issue-close: 0
- stale-issue-label: "stale"
- stale-issue-message: "This issue is stale because it has been open for 7 days with no activity."
- close-issue-message: "This issue was closed because it has become stale"
- days-before-pr-stale: -1
- days-before-pr-close: -1
- repo-token: ${{ secrets.GITHUB_TOKEN }}
- exempt-issue-labels: false
diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml
deleted file mode 100644
index 93a69869998..00000000000
--- a/.github/workflows/windows.yml
+++ /dev/null
@@ -1,54 +0,0 @@
-# This is a basic workflow to help you get started with Actions
-
-name: Windows Build CI
-
-# Controls when the workflow will run
-on: [push, pull_request]
-
-# A workflow run is made up of one or more jobs that can run sequentially or in parallel
-jobs:
- # This workflow contains a single job called "build"
- build:
- # The type of runner that the job will run on
- runs-on: windows-latest
-
- # Steps represent a sequence of tasks that will be executed as part of the job
- steps:
- # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
- - uses: actions/checkout@v2
- - uses: krdlab/setup-haxe@v1
- with:
- haxe-version: 4.1.5
- # Runs a set of commands using the runners shell
- - name: script run line haha
- run: |
- cinst haxe --version 4.1.5 -y
- RefreshEnv
- mkdir "%HAXELIB_ROOT%"
- haxelib setup "%HAXELIB_ROOT%"
- haxelib install lime 7.9.0
- RefreshEnv
- haxelib install openfl
- haxelib install flixel
- haxelib run lime setup flixel
- haxelib run lime setup
- haxelib install flixel-tools
- haxelib install flixel-addons
- haxelib install flixel-ui
- haxelib install hscript
- haxelib install flixel-addons
- haxelib git faxe https://github.com/uhrobots/faxe
- haxelib git polymod https://github.com/MasterEric/polymod.git
- haxelib git discord_rpc https://github.com/Aidan63/linc_discord-rpc
- haxelib git extension-webm https://github.com/KadeDev/extension-webm
- haxelib run lime rebuild extension-webm windows
- haxelib git linc_luajit https://github.com/nebulazorua/linc_luajit.git
- haxelib git hxvm-luajit https://github.com/nebulazorua/hxvm-luajit
- haxelib install actuate
- haxelib list
- haxelib run lime build windows
-
- - uses: actions/upload-artifact@v2
- with:
- name: Windows Build
- path: export/release/windows/bin
diff --git a/Project.xml b/Project.xml
index 7b87057ddaa..20c7b213b3b 100644
--- a/Project.xml
+++ b/Project.xml
@@ -30,6 +30,9 @@
+
+
+
@@ -126,7 +129,7 @@
-
+
@@ -194,11 +197,11 @@
-
+
-
+
-
+
diff --git a/assets/preload/data/songs/tutorial/modchart.lua b/assets/preload/data/songs/tutorial/modchart.lua
index 71a33b8a3c3..badd1f73136 100644
--- a/assets/preload/data/songs/tutorial/modchart.lua
+++ b/assets/preload/data/songs/tutorial/modchart.lua
@@ -1,37 +1,23 @@
-function start(song) -- do nothing
- spinLength = 0
+function start (song)
+ print("Song: " .. song .. " @ " .. bpm .. " donwscroll: " .. downscroll)
end
-function update(elapsed)
- if difficulty == 2 and curStep > 400 then
- if spinLength < 32 then
- spinLength = spinLength + 0.2
+function update (elapsed)
+ local currentBeat = (songPos / 1000)*(bpm/60)
+ for i=0,7 do
+ setActorY(defaultStrum0Y + 10 * math.cos((currentBeat + i*0.25) * math.pi), i)
end
-
-
- local currentBeat = (songPos / 1000)*(bpm/60)
- for i=0,7,1 do
- local receptor = _G['receptor_'..i]
- receptor.angle = (spinLength / 7) * -math.sin((currentBeat + i*0.25) * math.pi)
- receptor.x = receptor.defaultX + spinLength * math.sin((currentBeat + i*0.25) * math.pi)
- receptor.y = receptor.defaultY + spinLength * math.cos((currentBeat + i*0.25) * math.pi)
- end
- end
-end
-
-function beatHit(beat) -- do nothing
-
end
-function stepHit(step) -- do nothing
-
-end
+function beatHit (beat)
-function playerTwoTurn()
- camGame.tweenZoom(camGame,1.3,(crochet * 4) / 1000)
end
-function playerOneTurn()
- camGame.tweenZoom(camGame,1,(crochet * 4) / 1000)
+function stepHit (step)
+ if curStep == 20 or curStep == 248 or curStep == 375 or curStep == 632 or curStep == 696 or curStep == 824 or curStep == 952 or curStep == 1208 then
+ for i = 0, 7 do
+ tweenPosXAngle(i, _G['defaultStrum'..i..'X'],getActorAngle(i) + 360, 0.6, 'setDefault')
+ end
+ end
end
\ No newline at end of file
diff --git a/assets/preload/images/key_shift.png b/assets/preload/images/key_shift.png
new file mode 100644
index 00000000000..bea725fbf2f
Binary files /dev/null and b/assets/preload/images/key_shift.png differ
diff --git a/assets/preload/images/key_space.png b/assets/preload/images/key_space.png
new file mode 100644
index 00000000000..3aa0a5ed0db
Binary files /dev/null and b/assets/preload/images/key_space.png differ
diff --git a/assets/preload/images/virtual-input.png b/assets/preload/images/virtual-input.png
new file mode 100644
index 00000000000..6199fbbf823
Binary files /dev/null and b/assets/preload/images/virtual-input.png differ
diff --git a/assets/preload/images/virtual-input.txt b/assets/preload/images/virtual-input.txt
new file mode 100644
index 00000000000..f2d38e28db8
--- /dev/null
+++ b/assets/preload/images/virtual-input.txt
@@ -0,0 +1,21 @@
+base = 798 138 252 252
+thumb = 798 393 156 156
+a = 0 0 396 135
+b = 0 138 396 135
+c = 0 276 396 135
+down = 0 414 396 135
+left = 399 0 396 135
+right = 399 138 396 135
+up = 399 276 396 135
+x = 798 0 396 135
+y = 399 414 396 135
+6 = 0 548 396 135
+1 = 0 685 396 135
+7 = 0 821 396 135
+in = 397 547 396 135
+out = 395 682 396 135
+save = 401 820 396 135
+l = 800 682 396 135
+r = 800 820 396 135
+r2 = 0 956 396 135
+stage = 1194 0 396 135
\ No newline at end of file
diff --git a/assets/shared/images/hitbox/hitbox.png b/assets/shared/images/hitbox/hitbox.png
new file mode 100644
index 00000000000..79d0b2278c3
Binary files /dev/null and b/assets/shared/images/hitbox/hitbox.png differ
diff --git a/assets/shared/images/hitbox/hitbox.xml b/assets/shared/images/hitbox/hitbox.xml
new file mode 100644
index 00000000000..183916bfb59
--- /dev/null
+++ b/assets/shared/images/hitbox/hitbox.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/shared/images/hitbox/hitbox_hint.png b/assets/shared/images/hitbox/hitbox_hint.png
new file mode 100644
index 00000000000..196c5c86c97
Binary files /dev/null and b/assets/shared/images/hitbox/hitbox_hint.png differ
diff --git a/assets/shared/images/hitbox/hitbox_hint_old.png b/assets/shared/images/hitbox/hitbox_hint_old.png
new file mode 100644
index 00000000000..98b2cd8a439
Binary files /dev/null and b/assets/shared/images/hitbox/hitbox_hint_old.png differ
diff --git a/dependencies/android/build.gradle b/dependencies/android/build.gradle
new file mode 100644
index 00000000000..a132abee26b
--- /dev/null
+++ b/dependencies/android/build.gradle
@@ -0,0 +1,21 @@
+buildscript {
+ repositories {
+ jcenter()
+ google()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:::ANDROID_GRADLE_PLUGIN::'
+ }
+}
+
+apply plugin: 'com.android.library'
+
+android {
+ compileSdkVersion Integer.parseInt(project.ANDROID_BUILD_SDK_VERSION)
+ buildToolsVersion project.ANDROID_BUILD_TOOLS_VERSION
+}
+
+dependencies {
+ api project(':deps:extension-api')
+}
diff --git a/dependencies/android/src/main/AndroidManifest.xml b/dependencies/android/src/main/AndroidManifest.xml
new file mode 100644
index 00000000000..785bf6187eb
--- /dev/null
+++ b/dependencies/android/src/main/AndroidManifest.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/dependencies/android/src/main/java/org/haxe/extension/Tools.java b/dependencies/android/src/main/java/org/haxe/extension/Tools.java
new file mode 100644
index 00000000000..bde9e4d61dc
--- /dev/null
+++ b/dependencies/android/src/main/java/org/haxe/extension/Tools.java
@@ -0,0 +1,155 @@
+package org.haxe.extension;
+
+
+import android.Manifest;
+import android.app.Activity;
+import android.content.res.AssetManager;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import org.haxe.lime.HaxeObject;
+
+
+/*
+ You can use the Android Extension class in order to hook
+ into the Android activity lifecycle. This is not required
+ for standard Java code, this is designed for when you need
+ deeper integration.
+
+ You can access additional references from the Extension class,
+ depending on your needs:
+
+ - Extension.assetManager (android.content.res.AssetManager)
+ - Extension.callbackHandler (android.os.Handler)
+ - Extension.mainActivity (android.app.Activity)
+ - Extension.mainContext (android.content.Context)
+ - Extension.mainView (android.view.View)
+
+ You can also make references to static or instance methods
+ and properties on Java classes. These classes can be included
+ as single files using within your
+ project, or use the full Android Library Project format (such
+ as this example) in order to include your own AndroidManifest
+ data, additional dependencies, etc.
+
+ These are also optional, though this example shows a static
+ function for performing a single task, like returning a value
+ back to Haxe from Java.
+*/
+public class Tools extends Extension {
+
+ public static int sampleMethod (int inputValue) {
+
+ // Extension.mainActivity.requestPermissions(new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
+ // 1);
+
+ // Extension.mainActivity.finish();
+
+ return inputValue * 102;
+ }
+
+ public static void requestPermissions (String p) {
+ Extension.mainActivity.requestPermissions(new String[]{p}, 1);
+ }
+
+
+ /**
+ * Called when an activity you launched exits, giving you the requestCode
+ * you started it with, the resultCode it returned, and any additional data
+ * from it.
+ */
+ public boolean onActivityResult (int requestCode, int resultCode, Intent data) {
+
+ return true;
+
+ }
+
+ /**
+ * Called when the activity receives th results for permission requests.
+ */
+ public boolean onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
+
+ return true;
+
+ }
+
+
+ /**
+ * Called when the activity is starting.
+ */
+ public void onCreate (Bundle savedInstanceState) {
+
+
+
+ }
+
+
+ /**
+ * Perform any final cleanup before an activity is destroyed.
+ */
+ public void onDestroy () {
+
+
+
+ }
+
+
+ /**
+ * Called as part of the activity lifecycle when an activity is going into
+ * the background, but has not (yet) been killed.
+ */
+ public void onPause () {
+
+
+
+ }
+
+
+ /**
+ * Called after {@link #onStop} when the current activity is being
+ * re-displayed to the user (the user has navigated back to it).
+ */
+ public void onRestart () {
+
+
+
+ }
+
+
+ /**
+ * Called after {@link #onRestart}, or {@link #onPause}, for your activity
+ * to start interacting with the user.
+ */
+ public void onResume () {
+
+
+
+ }
+
+
+ /**
+ * Called after {@link #onCreate} — or after {@link #onRestart} when
+ * the activity had been stopped, but is now again being displayed to the
+ * user.
+ */
+ public void onStart () {
+
+
+
+ }
+
+
+ /**
+ * Called when the activity is no longer visible to the user, because
+ * another activity has been resumed and is covering this one.
+ */
+ public void onStop () {
+
+
+
+ }
+
+
+}
\ No newline at end of file
diff --git a/source/AnimationDebug.hx b/source/AnimationDebug.hx
index 4d1bedfd8b4..10c4bc064b1 100644
--- a/source/AnimationDebug.hx
+++ b/source/AnimationDebug.hx
@@ -21,7 +21,7 @@ import flixel.addons.ui.FlxUIInputText;
import flixel.addons.ui.FlxUINumericStepper;
import flixel.addons.ui.FlxUITabMenu;
import flixel.addons.ui.FlxUITooltip.FlxUITooltipStyle;
-
+import ui.FlxVirtualPad;
/**
*DEBUG MODE
*/
@@ -52,6 +52,8 @@ class AnimationDebug extends MusicBeatState
var characters:Array;
+ var _pad:FlxVirtualPad;
+
public function new(daAnim:String = 'bf')
{
super();
@@ -143,6 +145,10 @@ class AnimationDebug extends MusicBeatState
FlxG.camera.follow(camFollow);
+ _pad = new FlxVirtualPad(ANIMATION, ANIMATION);
+ _pad.alpha = 0.75;
+ add(_pad);
+
super.create();
}
@@ -227,6 +233,8 @@ class AnimationDebug extends MusicBeatState
result += text + "\n";
}
+ openfl.system.System.setClipboard(result.trim());
+
if ((result != null) && (result.length > 0))
{
_file = new FileReference();
@@ -288,7 +296,7 @@ class AnimationDebug extends MusicBeatState
function addHelpText():Void
{
- var helpTextValue = "Help:\nQ/E : Zoom in and out\nF : Flip\nI/J/K/L : Pan Camera\nW/S : Cycle Animation\nArrows : Offset Animation\nShift-Arrows : Offset Animation x10\nSpace : Replay Animation\nCTRL-S : Save Offsets to File\nEnter/ESC : Exit\nPress F1 to hide/show this!\n";
+ var helpTextValue = "Help:\nIN/OUT : Zoom in and out\nUP/DOWN : Cycle Animation\nDrag : Offset Animation\nA : Replay Animation\nSAVE : Save Offsets to ClipBoard\nB : Exit";
helpText = new FlxText(940, 20, 0, helpTextValue, 15);
helpText.scrollFactor.set();
helpText.y = FlxG.height - helpText.height - 20;
@@ -336,32 +344,32 @@ class AnimationDebug extends MusicBeatState
// TO MOUSE MOVEMENT?????????
}
- if (FlxG.keys.justPressed.ESCAPE)
+ if (_pad.buttonB.justPressed)
{
FlxG.mouse.visible = false;
FlxG.switchState(new PlayState());
}
- if (FlxG.keys.justPressed.E)
+ if (_pad.buttonIn.justPressed)
FlxG.camera.zoom += 0.25;
- if (FlxG.keys.justPressed.Q)
+ if (_pad.buttonOut.justPressed)
FlxG.camera.zoom -= 0.25;
if (FlxG.keys.justPressed.F)
char.flipX = !char.flipX;
- if (FlxG.keys.pressed.I || FlxG.keys.pressed.J || FlxG.keys.pressed.K || FlxG.keys.pressed.L)
+ if (_pad.buttonUp.pressed || _pad.buttonDown.pressed || _pad.buttonLeft.pressed || _pad.buttonRight.pressed)
{
- if (FlxG.keys.pressed.I)
+ if (_pad.buttonUp.pressed)
camFollow.velocity.y = -90;
- else if (FlxG.keys.pressed.K)
+ else if (_pad.buttonDown.pressed)
camFollow.velocity.y = 90;
else
camFollow.velocity.y = 0;
- if (FlxG.keys.pressed.J)
+ if (_pad.buttonLeft.pressed)
camFollow.velocity.x = -90;
- else if (FlxG.keys.pressed.L)
+ else if (_pad.buttonRight.pressed)
camFollow.velocity.x = 90;
else
camFollow.velocity.x = 0;
@@ -369,14 +377,14 @@ class AnimationDebug extends MusicBeatState
else
{
camFollow.velocity.set();
- }
+ }
- if (FlxG.keys.justPressed.W)
+ if (_pad.buttonUp2.justPressed)
{
curAnim -= 1;
}
- if (FlxG.keys.justPressed.S)
+ if (_pad.buttonDown2.justPressed)
{
curAnim += 1;
}
@@ -387,7 +395,7 @@ class AnimationDebug extends MusicBeatState
if (curAnim >= animList.length)
curAnim = 0;
- if (FlxG.keys.justPressed.S || FlxG.keys.justPressed.W || FlxG.keys.justPressed.SPACE)
+ if (_pad.buttonDown2.justPressed || _pad.buttonUp2.justPressed || _pad.buttonA.justPressed)
{
char.playAnim(animList[curAnim]);
@@ -422,7 +430,7 @@ class AnimationDebug extends MusicBeatState
char.playAnim(animList[curAnim]);
}
- if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.S)
+ if (_pad.buttonSave.justPressed)
saveBoyOffsets();
if (FlxG.keys.justPressed.F1)
diff --git a/source/Asset2File.hx b/source/Asset2File.hx
new file mode 100644
index 00000000000..b0bfcabedd1
--- /dev/null
+++ b/source/Asset2File.hx
@@ -0,0 +1,32 @@
+package;
+
+import haxe.crypto.Md5;
+import openfl.utils.Assets;
+#if sys
+import sys.FileSystem;
+import sys.io.File;
+#end
+
+class Asset2File
+{
+ static var path:String = lime.system.System.applicationStorageDirectory;
+
+ public static function getPath(id:String, ?ext:String = "")
+ {
+ #if android
+ var file = Assets.getBytes(id);
+
+ var md5 = Md5.encode(Md5.make(file).toString());
+
+ if (FileSystem.exists(path + md5 + ext))
+ return path + md5 + ext;
+
+
+ File.saveBytes(path + md5 + ext, file);
+
+ return path + md5 + ext;
+ #else
+ return #if sys Sys.getCwd() + #end id;
+ #end
+ }
+}
diff --git a/source/ChartingState.hx b/source/ChartingState.hx
index e02c9bc3138..50823e321ce 100644
--- a/source/ChartingState.hx
+++ b/source/ChartingState.hx
@@ -3,7 +3,7 @@ package;
import Song.SongMeta;
import openfl.system.System;
import lime.app.Application;
-#if FEATURE_FILESYSTEM
+#if sys
import sys.io.File;
import sys.FileSystem;
#end
@@ -48,6 +48,7 @@ import openfl.utils.ByteArray;
#if FEATURE_DISCORD
import Discord.DiscordClient;
#end
+import ui.FlxVirtualPad;
using StringTools;
@@ -59,6 +60,12 @@ class ChartingState extends MusicBeatState
public var playClaps:Bool = false;
+ var _pad:FlxVirtualPad;
+ //add buttons
+ var key_space:FlxButton;
+ var key_shift:FlxButton;
+
+
public var snap:Int = 16;
public var deezNuts:Map = new Map(); // snap conversion map
@@ -446,6 +453,21 @@ class ChartingState extends MusicBeatState
Debug.logTrace("create");
+ _pad = new FlxVirtualPad(FULL, NONE);
+ _pad.alpha = 0.75;
+ add(_pad);
+
+ // add buttons
+ key_space = new FlxButton(60, 60, "");
+ key_space.loadGraphic(Paths.image("key_space")); //"assets/images/key_space.png"
+ key_space.alpha = 0.75;
+ add(key_space);
+
+ key_shift = new FlxButton(60, 200, "");
+ key_shift.loadGraphic(Paths.image("key_shift")); //"assets/images/key_shift.png"
+ key_shift.alpha = 0.75;
+ add(key_shift);
+
super.create();
}
@@ -2086,11 +2108,11 @@ class ChartingState extends MusicBeatState
}
}
- if (FlxG.keys.pressed.SHIFT)
+ if (FlxG.keys.pressed.SHIFT || key_shift.pressed)
{
- if (FlxG.keys.justPressed.RIGHT)
+ if (FlxG.keys.justPressed.RIGHT || FlxG.keys.justPressed.D || _pad.buttonRight.justPressed)
speed += 0.1;
- else if (FlxG.keys.justPressed.LEFT)
+ else if (FlxG.keys.justPressed.LEFT || FlxG.keys.justPressed.A || _pad.buttonLeft.justPressed)
speed -= 0.1;
if (speed > 3)
@@ -2613,8 +2635,14 @@ class ChartingState extends MusicBeatState
if (doInput)
{
- if (FlxG.keys.justPressed.ENTER)
+ #if android
+ var androidback = FlxG.android.justReleased.BACK;
+ #else
+ var androidback = false;
+ #end
+ if (FlxG.keys.justPressed.ENTER || androidback)
{
+ FlxG.mouse.visible = false;
lastSection = curSection;
PlayState.SONG = _song;
@@ -2717,7 +2745,7 @@ class ChartingState extends MusicBeatState
var shiftThing:Int = 1;
if (FlxG.keys.pressed.SHIFT)
shiftThing = 4;
- if (FlxG.keys.justPressed.SPACE)
+ if (FlxG.keys.justPressed.SPACE || key_space.justPressed)
{
if (FlxG.sound.music.playing)
{
@@ -2737,9 +2765,9 @@ class ChartingState extends MusicBeatState
if (FlxG.sound.music.time < 0 || curDecimalBeat < 0)
FlxG.sound.music.time = 0;
- if (!FlxG.keys.pressed.SHIFT)
+ if (!FlxG.keys.pressed.SHIFT || !key_shift.pressed)
{
- if (FlxG.keys.pressed.W || FlxG.keys.pressed.S)
+ if (FlxG.keys.pressed.W || FlxG.keys.pressed.S || _pad.buttonUp.pressed || _pad.buttonDown.pressed)
{
FlxG.sound.music.pause();
if (!PlayState.isSM)
@@ -2748,7 +2776,7 @@ class ChartingState extends MusicBeatState
var daTime:Float = 700 * FlxG.elapsed;
- if (FlxG.keys.pressed.W)
+ if (FlxG.keys.pressed.W || _pad.buttonUp.pressed)
{
FlxG.sound.music.time -= daTime;
}
@@ -2761,7 +2789,7 @@ class ChartingState extends MusicBeatState
}
else
{
- if (FlxG.keys.justPressed.W || FlxG.keys.justPressed.S)
+ if (FlxG.keys.justPressed.W || FlxG.keys.justPressed.S || _pad.buttonUp.pressed || _pad.buttonDown.pressed)
{
FlxG.sound.music.pause();
if (!PlayState.isSM)
@@ -2769,7 +2797,7 @@ class ChartingState extends MusicBeatState
var daTime:Float = Conductor.stepCrochet * 2;
- if (FlxG.keys.justPressed.W)
+ if (FlxG.keys.justPressed.W || _pad.buttonUp.justPressed)
{
FlxG.sound.music.time -= daTime;
}
@@ -3600,6 +3628,8 @@ class ChartingState extends MusicBeatState
var data:String = Json.stringify(json, null, " ");
+ openfl.system.System.setClipboard(data.trim());
+
if ((data != null) && (data.length > 0))
{
_file = new FileReference();
diff --git a/source/Config.hx b/source/Config.hx
new file mode 100644
index 00000000000..e15be60f3af
--- /dev/null
+++ b/source/Config.hx
@@ -0,0 +1,94 @@
+package;
+
+import ui.FlxVirtualPad;
+import flixel.FlxG;
+import flixel.util.FlxSave;
+import flixel.math.FlxPoint;
+
+class Config {
+ var save:FlxSave;
+
+ public function new()
+ {
+ save = new FlxSave();
+ save.bind("saveconrtol");
+ }
+
+ public function setdownscroll(?value:Bool):Bool {
+ if (save.data.isdownscroll == null) save.data.isdownscroll = false;
+
+ save.data.isdownscroll = !save.data.isdownscroll;
+ save.flush();
+ return save.data.isdownscroll;
+ }
+
+ public function getdownscroll():Bool {
+ if (save.data.isdownscroll != null) return save.data.isdownscroll;
+ return false;
+ }
+
+ public function getcontrolmode():Int {
+ // load control mode num from FlxSave
+ if (save.data.buttonsmode != null) return save.data.buttonsmode[0];
+ return 0;
+ }
+
+ public function setcontrolmode(mode:Int = 0):Int {
+ // save control mode num from FlxSave
+ if (save.data.buttonsmode == null) save.data.buttonsmode = new Array();
+ save.data.buttonsmode[0] = mode;
+ save.flush();
+
+ return save.data.buttonsmode[0];
+ }
+
+ public function savecustom(_pad:FlxVirtualPad) {
+ trace("saved");
+
+ if (save.data.buttons == null)
+ {
+ save.data.buttons = new Array();
+
+ for (buttons in _pad)
+ {
+ save.data.buttons.push(FlxPoint.get(buttons.x, buttons.y));
+ }
+ }else
+ {
+ var tempCount:Int = 0;
+ for (buttons in _pad)
+ {
+ save.data.buttons[tempCount] = FlxPoint.get(buttons.x, buttons.y);
+ tempCount++;
+ }
+ }
+ save.flush();
+ }
+
+ public function loadcustom(_pad:FlxVirtualPad):FlxVirtualPad {
+ //load pad
+ if (save.data.buttons == null) return _pad;
+ var tempCount:Int = 0;
+
+ for(buttons in _pad)
+ {
+ buttons.x = save.data.buttons[tempCount].x;
+ buttons.y = save.data.buttons[tempCount].y;
+ tempCount++;
+ }
+ return _pad;
+ }
+
+ public function setFrameRate(fps:Int = 60) {
+ if (fps < 10) return;
+
+ FlxG.stage.frameRate = fps;
+ save.data.framerate = fps;
+ save.flush();
+ }
+
+ public function getFrameRate():Int {
+ if (save.data.framerate != null) return save.data.framerate;
+ return 60;
+ }
+}
\ No newline at end of file
diff --git a/source/Controls.hx b/source/Controls.hx
index 28182212e57..5b8cd1350be 100644
--- a/source/Controls.hx
+++ b/source/Controls.hx
@@ -11,6 +11,9 @@ import flixel.input.actions.FlxActionSet;
import flixel.input.gamepad.FlxGamepadButton;
import flixel.input.gamepad.FlxGamepadInputID;
import flixel.input.keyboard.FlxKey;
+import ui.Hitbox;
+import ui.FlxVirtualPad;
+import flixel.ui.FlxButton;
#if (haxe >= "4.0.0")
enum abstract Action(String) to String from String
@@ -32,6 +35,9 @@ enum abstract Action(String) to String from String
var PAUSE = "pause";
var RESET = "reset";
var CHEAT = "cheat";
+ var SIX = "six";
+ var ONE = "one";
+ var SEVEN = "seven";
}
#else
@:enum
@@ -54,6 +60,9 @@ abstract Action(String) to String from String
var PAUSE = "pause";
var RESET = "reset";
var CHEAT = "cheat";
+ var SIX = "six";
+ var ONE = "one";
+ var SEVEN = "seven";
}
#end
@@ -79,6 +88,9 @@ enum Control
BACK;
PAUSE;
CHEAT;
+ SIX;
+ ONE;
+ SEVEN;
}
enum KeyboardScheme
@@ -112,6 +124,9 @@ class Controls extends FlxActionSet
var _pause = new FlxActionDigital(Action.PAUSE);
var _reset = new FlxActionDigital(Action.RESET);
var _cheat = new FlxActionDigital(Action.CHEAT);
+ var _six = new FlxActionDigital(Action.SIX);
+ var _one = new FlxActionDigital(Action.ONE);
+ var _seven = new FlxActionDigital(Action.SEVEN);
#if (haxe >= "4.0.0")
var byName:Map = [];
@@ -207,6 +222,23 @@ class Controls extends FlxActionSet
inline function get_CHEAT()
return _cheat.check();
+ public var SIX(get, never):Bool;
+
+ inline function get_SIX()
+ return _six.check();
+
+ public var ONE(get, never):Bool;
+
+ inline function get_ONE()
+ return _one.check();
+
+ public var SEVEN(get, never):Bool;
+
+ inline function get_SEVEN()
+ return _seven.check();
+
+
+
#if (haxe >= "4.0.0")
public function new(name, scheme = None)
{
@@ -229,6 +261,9 @@ class Controls extends FlxActionSet
add(_pause);
add(_reset);
add(_cheat);
+ add(_six);
+ add(_one);
+ add(_seven);
for (action in digitalActions)
byName[action.name] = action;
@@ -257,6 +292,9 @@ class Controls extends FlxActionSet
add(_pause);
add(_reset);
add(_cheat);
+ add(_six);
+ add(_one);
+ add(_seven);
for (action in digitalActions)
byName[action.name] = action;
@@ -267,6 +305,122 @@ class Controls extends FlxActionSet
}
#end
+ public var trackedinputs:Array = [];
+
+ public function addbutton(action:FlxActionDigital, button:FlxButton, state:FlxInputState) {
+ var input = new FlxActionInputDigitalIFlxInput(button, state);
+ trackedinputs.push(input);
+
+ action.add(input);
+ //action.addInput(button, state);
+ }
+
+ public function setHitBox(hitbox:Hitbox)
+ {
+ inline forEachBound(Control.UP, (action, state) -> addbutton(action, hitbox.buttonUp, state));
+ inline forEachBound(Control.DOWN, (action, state) -> addbutton(action, hitbox.buttonDown, state));
+ inline forEachBound(Control.LEFT, (action, state) -> addbutton(action, hitbox.buttonLeft, state));
+ inline forEachBound(Control.RIGHT, (action, state) -> addbutton(action, hitbox.buttonRight, state));
+ }
+
+
+ public function setVirtualPad(virtualPad:FlxVirtualPad, ?DPad:FlxDPadMode, ?Action:FlxActionMode) {
+ if (DPad == null)
+ DPad = NONE;
+ if (Action == null)
+ Action = NONE;
+
+ switch (DPad)
+ {
+ case UP_DOWN:
+ inline forEachBound(Control.UP, (action, state) -> addbutton(action, virtualPad.buttonUp, state));
+ inline forEachBound(Control.DOWN, (action, state) -> addbutton(action, virtualPad.buttonDown, state));
+ case LEFT_RIGHT:
+ inline forEachBound(Control.LEFT, (action, state) -> addbutton(action, virtualPad.buttonLeft, state));
+ inline forEachBound(Control.RIGHT, (action, state) -> addbutton(action, virtualPad.buttonRight, state));
+ case UP_LEFT_RIGHT:
+ inline forEachBound(Control.UP, (action, state) -> addbutton(action, virtualPad.buttonUp, state));
+ inline forEachBound(Control.LEFT, (action, state) -> addbutton(action, virtualPad.buttonLeft, state));
+ inline forEachBound(Control.RIGHT, (action, state) -> addbutton(action, virtualPad.buttonRight, state));
+ case FULL | RIGHT_FULL:
+ inline forEachBound(Control.UP, (action, state) -> addbutton(action, virtualPad.buttonUp, state));
+ inline forEachBound(Control.DOWN, (action, state) -> addbutton(action, virtualPad.buttonDown, state));
+ inline forEachBound(Control.LEFT, (action, state) -> addbutton(action, virtualPad.buttonLeft, state));
+ inline forEachBound(Control.RIGHT, (action, state) -> addbutton(action, virtualPad.buttonRight, state));
+ case ANIMATION:
+ case NONE:
+ }
+
+ switch (Action)
+ {
+ case A:
+ inline forEachBound(Control.ACCEPT, (action, state) -> addbutton(action, virtualPad.buttonA, state));
+ case A_B:
+ inline forEachBound(Control.ACCEPT, (action, state) -> addbutton(action, virtualPad.buttonA, state));
+ inline forEachBound(Control.BACK, (action, state) -> addbutton(action, virtualPad.buttonB, state));
+ case STAGE:
+ case SONGD:
+ case ANIMATION:
+ case A_B_6:
+ inline forEachBound(Control.ACCEPT, (action, state) -> addbutton(action, virtualPad.buttonA, state));
+ inline forEachBound(Control.BACK, (action, state) -> addbutton(action, virtualPad.buttonB, state));
+ inline forEachBound(Control.SIX, (action, state) -> addbutton(action, virtualPad.button6, state));
+ case A_B_6_1:
+ inline forEachBound(Control.ACCEPT, (action, state) -> addbutton(action, virtualPad.buttonA, state));
+ inline forEachBound(Control.BACK, (action, state) -> addbutton(action, virtualPad.buttonB, state));
+ inline forEachBound(Control.SIX, (action, state) -> addbutton(action, virtualPad.button6, state));
+ inline forEachBound(Control.ONE, (action, state) -> addbutton(action, virtualPad.button1, state));
+ case A_B_6_1_7:
+ inline forEachBound(Control.ACCEPT, (action, state) -> addbutton(action, virtualPad.buttonA, state));
+ inline forEachBound(Control.BACK, (action, state) -> addbutton(action, virtualPad.buttonB, state));
+ inline forEachBound(Control.SIX, (action, state) -> addbutton(action, virtualPad.button6, state));
+ inline forEachBound(Control.ONE, (action, state) -> addbutton(action, virtualPad.button1, state));
+ inline forEachBound(Control.SEVEN, (action, state) -> addbutton(action, virtualPad.button7, state));
+ case A_B_C:
+ inline forEachBound(Control.ACCEPT, (action, state) -> addbutton(action, virtualPad.buttonA, state));
+ inline forEachBound(Control.BACK, (action, state) -> addbutton(action, virtualPad.buttonB, state));
+ case A_B_X_Y:
+ inline forEachBound(Control.ACCEPT, (action, state) -> addbutton(action, virtualPad.buttonA, state));
+ inline forEachBound(Control.BACK, (action, state) -> addbutton(action, virtualPad.buttonB, state));
+ case NONE:
+ }
+ }
+
+
+ public function removeFlxInput(Tinputs) {
+ for (action in this.digitalActions)
+ {
+ var i = action.inputs.length;
+
+ while (i-- > 0)
+ {
+ var input = action.inputs[i];
+ /*if (input.device == IFLXINPUT_OBJECT)
+ action.remove(input);*/
+
+ var x = Tinputs.length;
+ while (x-- > 0)
+ if (Tinputs[x] == input)
+ action.remove(input);
+ }
+ }
+ }
+
+
+
+ #if android
+ public function addAndroidBack() {
+ // fix this later
+
+ /*
+ var BACK = #if (openfl >= "8.0.0") 0x4000010E #else 27 #end;
+ _back.addKey(BACK, JUST_RELEASED);
+ _back.addKey(BACK, JUST_PRESSED);
+ _back.addKey(BACK, PRESSED);
+ */
+ }
+ #end
+
override function update()
{
super.update();
@@ -311,6 +465,9 @@ class Controls extends FlxActionSet
case PAUSE: _pause;
case RESET: _reset;
case CHEAT: _cheat;
+ case SIX: _six;
+ case ONE: _one;
+ case SEVEN: _seven;
}
}
@@ -356,6 +513,12 @@ class Controls extends FlxActionSet
func(_reset, JUST_PRESSED);
case CHEAT:
func(_cheat, JUST_PRESSED);
+ case SIX:
+ func(_six, JUST_PRESSED);
+ case ONE:
+ func(_one, JUST_PRESSED);
+ case SEVEN:
+ func(_seven, JUST_PRESSED);
}
}
diff --git a/source/FreeplayState.hx b/source/FreeplayState.hx
index 6163487f431..e7a5146bcef 100644
--- a/source/FreeplayState.hx
+++ b/source/FreeplayState.hx
@@ -6,7 +6,7 @@ import flixel.system.FlxSound;
#if FEATURE_STEPMANIA
import smTools.SMFile;
#end
-#if FEATURE_FILESYSTEM
+#if sys
import sys.FileSystem;
import sys.io.File;
#end
@@ -85,7 +85,7 @@ class FreeplayState extends MusicBeatState
#if !FEATURE_STEPMANIA
trace("FEATURE_STEPMANIA was not specified during build, sm file loading is disabled.");
- #elseif FEATURE_STEPMANIA
+ #elseif windows
// TODO: Refactor this to use OpenFlAssets.
trace("tryin to load sm files");
for (i in FileSystem.readDirectory("assets/sm/"))
@@ -133,9 +133,9 @@ class FreeplayState extends MusicBeatState
var isDebug:Bool = false;
- #if debug
+ // #if debug
isDebug = true;
- #end
+ //#end
persistentUpdate = true;
@@ -209,6 +209,10 @@ class FreeplayState extends MusicBeatState
var swag:Alphabet = new Alphabet(1, 0, "swag");
+ #if mobileC
+ addVirtualPad(FULL, A_B_6_1_7);
+ #end
+
super.create();
}
@@ -318,12 +322,12 @@ class FreeplayState extends MusicBeatState
FlxG.sound.music.volume -= 0.5 * FlxG.elapsed;
}
- var upP = FlxG.keys.justPressed.UP;
- var downP = FlxG.keys.justPressed.DOWN;
- var accepted = FlxG.keys.justPressed.ENTER;
- var dadDebug = FlxG.keys.justPressed.SIX;
- var charting = FlxG.keys.justPressed.SEVEN;
- var bfDebug = FlxG.keys.justPressed.ZERO;
+ var upP = controls.UP_P;
+ var downP = controls.DOWN_P;
+ var accepted = controls.ACCEPT;
+ var dadDebug = controls.SIX;
+ var charting = controls.SEVEN;
+ var bfDebug = controls.ONE;
var gamepad:FlxGamepad = FlxG.gamepads.lastActive;
@@ -396,9 +400,9 @@ class FreeplayState extends MusicBeatState
}
else
{
- if (FlxG.keys.justPressed.LEFT)
+ if (controls.LEFT_P)
changeDiff(-1);
- if (FlxG.keys.justPressed.RIGHT)
+ if (controls.RIGHT_P)
changeDiff(1);
}
@@ -421,7 +425,7 @@ class FreeplayState extends MusicBeatState
loadSong(true);
// AnimationDebug and StageDebug are only enabled in debug builds.
- #if debug
+ // #if debug
if (dadDebug)
{
loadAnimDebug(true);
@@ -430,7 +434,7 @@ class FreeplayState extends MusicBeatState
{
loadAnimDebug(false);
}
- #end
+ // #end
}
function loadAnimDebug(dad:Bool = true)
@@ -594,7 +598,7 @@ class FreeplayState extends MusicBeatState
diffCalcText.text = 'RATING: ${DiffCalc.CalculateDiff(songData.get(songs[curSelected].songName)[curDifficulty])}';
diffText.text = CoolUtil.difficultyFromInt(curDifficulty).toUpperCase();
- #if PRELOAD_ALL
+ #if windows
if (songs[curSelected].songCharacter == "sm")
{
var data = songs[curSelected];
diff --git a/source/GameOverSubstate.hx b/source/GameOverSubstate.hx
index 6f1c2cfb806..a91b01bc546 100644
--- a/source/GameOverSubstate.hx
+++ b/source/GameOverSubstate.hx
@@ -6,6 +6,7 @@ import flixel.FlxSubState;
import flixel.math.FlxPoint;
import flixel.util.FlxColor;
import flixel.util.FlxTimer;
+import flixel.FlxCamera;
class GameOverSubstate extends MusicBeatSubstate
{
@@ -46,6 +47,15 @@ class GameOverSubstate extends MusicBeatSubstate
FlxG.camera.target = null;
bf.playAnim('firstDeath');
+
+ #if mobileC
+ addVirtualPad(NONE, A_B);
+ var camcontrol = new FlxCamera();
+ FlxG.cameras.add(camcontrol);
+ camcontrol.bgColor.alpha = 0;
+ _virtualpad.cameras = [camcontrol];
+ #end
+
}
var startVibin:Bool = false;
diff --git a/source/GitarooPause.hx b/source/GitarooPause.hx
index cce3c49ad1e..e65732392b1 100644
--- a/source/GitarooPause.hx
+++ b/source/GitarooPause.hx
@@ -51,6 +51,11 @@ class GitarooPause extends MusicBeatState
changeThing();
+ #if mobileC
+ addVirtualPad(LEFT_RIGHT, A_B);
+ #end
+
+
super.create();
}
diff --git a/source/LoadReplayState.hx b/source/LoadReplayState.hx
index 627f8e06d04..e710b4023bd 100644
--- a/source/LoadReplayState.hx
+++ b/source/LoadReplayState.hx
@@ -16,7 +16,7 @@ import flixel.input.keyboard.FlxKey;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.util.FlxColor;
-#if FEATURE_FILESYSTEM
+#if sys
import sys.FileSystem;
import sys.io.File;
#end
diff --git a/source/Main.hx b/source/Main.hx
index 4666b0806ee..28d2c5e1bdc 100644
--- a/source/Main.hx
+++ b/source/Main.hx
@@ -16,6 +16,7 @@ import openfl.Lib;
import openfl.display.FPS;
import openfl.display.Sprite;
import openfl.events.Event;
+import lime.system.System;
class Main extends Sprite
{
@@ -23,7 +24,7 @@ class Main extends Sprite
var gameHeight:Int = 720; // Height of the game in pixels (might be less / more in actual pixels depending on your zoom).
var initialState:Class = TitleState; // The FlxState the game starts with.
var zoom:Float = -1; // If -1, zoom is automatically calculated to fit the window dimensions.
- var framerate:Int = 120; // How many frames per second the game should run at.
+ var framerate:Int = 60; // How many frames per second the game should run at.
var skipSplash:Bool = true; // Whether to skip the flixel splash screen that appears in release mode.
var startFullscreen:Bool = false; // Whether to start the game in fullscreen on desktop targets
@@ -31,6 +32,8 @@ class Main extends Sprite
public static var instance:Main;
+ public static var path:String = System.applicationStorageDirectory;
+
public static var watermarks = true; // Whether to put Kade Engine literally anywhere
// You can pretty much ignore everything from here on - your code should go in your states.
@@ -84,6 +87,13 @@ class Main extends Sprite
gameHeight = Math.ceil(stageHeight / zoom);
}
+ #if mobile
+ gameWidth = 1280;
+ gameHeight = 720;
+ zoom = 1;
+ #end
+
+
#if !cpp
framerate = 60;
#end
@@ -94,19 +104,16 @@ class Main extends Sprite
// Gotta run this before any assets get loaded.
ModCore.initialize();
- #if !mobile
fpsCounter = new KadeEngineFPS(10, 3, 0xFFFFFF);
bitmapFPS = ImageOutline.renderImage(fpsCounter, 1, 0x000000, true);
bitmapFPS.smoothing = true;
- #end
game = new FlxGame(gameWidth, gameHeight, initialState, zoom, framerate, framerate, skipSplash, startFullscreen);
addChild(game);
- #if !mobile
+
addChild(fpsCounter);
toggleFPS(FlxG.save.data.fps);
- #end
// Finish up loading debug tools.
Debug.onGameStart();
diff --git a/source/MainMenuState.hx b/source/MainMenuState.hx
index 4bd5188e3d5..d06076483e2 100644
--- a/source/MainMenuState.hx
+++ b/source/MainMenuState.hx
@@ -136,6 +136,10 @@ class MainMenuState extends MusicBeatState
changeItem();
+ #if mobileC
+ addVirtualPad(UP_DOWN, A_B);
+ #end
+
super.create();
}
@@ -166,13 +170,13 @@ class MainMenuState extends MusicBeatState
}
}
- if (FlxG.keys.justPressed.UP)
+ if (controls.UP_P)
{
FlxG.sound.play(Paths.sound('scrollMenu'));
changeItem(-1);
}
- if (FlxG.keys.justPressed.DOWN)
+ if (controls.DOWN_P)
{
FlxG.sound.play(Paths.sound('scrollMenu'));
changeItem(1);
diff --git a/source/ModchartState.hx b/source/ModchartState.hx
index a54ca8b747c..99630d2fb9d 100644
--- a/source/ModchartState.hx
+++ b/source/ModchartState.hx
@@ -383,7 +383,7 @@ class ModchartState
}
#end
- new LuaSprite(sprite, toBeCalled).Register(lua);
+ // new LuaSprite(sprite, toBeCalled).Register(lua);
return toBeCalled;
}
diff --git a/source/MusicBeatState.hx b/source/MusicBeatState.hx
index 77e952149ef..c358d2f8ea6 100644
--- a/source/MusicBeatState.hx
+++ b/source/MusicBeatState.hx
@@ -13,6 +13,10 @@ import openfl.Lib;
import Conductor.BPMChangeEvent;
import flixel.FlxG;
import flixel.addons.ui.FlxUIState;
+#if mobileC
+import ui.FlxVirtualPad;
+import flixel.input.actions.FlxActionInput;
+#end
class MusicBeatState extends FlxUIState
{
@@ -27,12 +31,36 @@ class MusicBeatState extends FlxUIState
inline function get_controls():Controls
return PlayerSettings.player1.controls;
+ #if mobileC
+ var _virtualpad:FlxVirtualPad;
+
+ var trackedinputs:Array = [];
+
+ // adding virtualpad to state
+ public function addVirtualPad(?DPad:FlxDPadMode, ?Action:FlxActionMode) {
+ _virtualpad = new FlxVirtualPad(DPad, Action);
+ _virtualpad.alpha = 0.75;
+ add(_virtualpad);
+ controls.setVirtualPad(_virtualpad, DPad, Action);
+ trackedinputs = controls.trackedinputs;
+ controls.trackedinputs = [];
+
+ #if android
+ controls.addAndroidBack();
+ #end
+ }
+
+ #else
+ public function addVirtualPad(?DPad, ?Action){};
+ #end
+
public static var initSave:Bool = false;
private var assets:Array = [];
override function destroy()
{
+ controls.removeFlxInput(trackedinputs);
Application.current.window.onFocusIn.remove(onWindowFocusOut);
Application.current.window.onFocusIn.remove(onWindowFocusIn);
super.destroy();
diff --git a/source/MusicBeatSubstate.hx b/source/MusicBeatSubstate.hx
index 66c06af9fa4..14e09e587f6 100644
--- a/source/MusicBeatSubstate.hx
+++ b/source/MusicBeatSubstate.hx
@@ -7,6 +7,10 @@ import flixel.input.gamepad.FlxGamepad;
import Conductor.BPMChangeEvent;
import flixel.FlxG;
import flixel.FlxSubState;
+#if mobileC
+import ui.FlxVirtualPad;
+import flixel.input.actions.FlxActionInput;
+#end
class MusicBeatSubstate extends FlxSubState
{
@@ -17,6 +21,7 @@ class MusicBeatSubstate extends FlxSubState
override function destroy()
{
+ controls.removeFlxInput(trackedinputs);
Application.current.window.onFocusIn.remove(onWindowFocusOut);
Application.current.window.onFocusIn.remove(onWindowFocusIn);
super.destroy();
@@ -39,6 +44,29 @@ class MusicBeatSubstate extends FlxSubState
inline function get_controls():Controls
return PlayerSettings.player1.controls;
+ #if mobileC
+ var _virtualpad:FlxVirtualPad;
+
+ var trackedinputs:Array = [];
+
+ // adding virtualpad to state
+ public function addVirtualPad(?DPad:FlxDPadMode, ?Action:FlxActionMode) {
+ _virtualpad = new FlxVirtualPad(DPad, Action);
+ _virtualpad.alpha = 0.75;
+ add(_virtualpad);
+ controls.setVirtualPad(_virtualpad, DPad, Action);
+ trackedinputs = controls.trackedinputs;
+ controls.trackedinputs = [];
+
+ #if android
+ controls.addAndroidBack();
+ #end
+ }
+
+ #else
+ public function addVirtualPad(?DPad, ?Action){};
+ #end
+
override function update(elapsed:Float)
{
// everyStep();
diff --git a/source/Options.hx b/source/Options.hx
index 6f16fda1842..e7921f0a27a 100644
--- a/source/Options.hx
+++ b/source/Options.hx
@@ -1767,6 +1767,24 @@ class ResetScoreOption extends Option
}
}
+class MobileControls extends Option
+{
+ public function new(desc:String)
+ {
+ super();
+ description = desc;
+ }
+ public override function press():Bool
+ {
+ FlxG.switchState(new options.CustomControlsState());
+ return true;
+ }
+ private override function updateDisplay():String
+ {
+ return "Mobile Controls";
+ }
+
+}
class ResetSettings extends Option
{
var confirm:Bool = false;
diff --git a/source/OptionsMenu.hx b/source/OptionsMenu.hx
index cbb7108f155..8157dd7aeac 100644
--- a/source/OptionsMenu.hx
+++ b/source/OptionsMenu.hx
@@ -17,6 +17,7 @@ import flixel.input.keyboard.FlxKey;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.util.FlxColor;
+import ui.FlxVirtualPad;
class OptionCata extends FlxSprite
{
@@ -114,10 +115,13 @@ class OptionsMenu extends FlxSubState
public var descText:FlxText;
public var descBack:FlxSprite;
+ var _pad:FlxVirtualPad;
+
override function create()
{
options = [
new OptionCata(50, 40, "Gameplay", [
+ new MobileControls("edit a control"),
new ScrollSpeedOption("Change your scroll speed. (1 = Chart dependent)"),
new OffsetThing("Change the note audio offset (how many milliseconds a note is offset in a chart)"),
new AccuracyDOption("Change how accuracy is calculated. (Accurate = Simple, Complex = Milisecond Based)"),
@@ -237,6 +241,10 @@ class OptionsMenu extends FlxSubState
selectedOption = selectedCat.options[0];
+ _pad = new FlxVirtualPad(FULL, A_B);
+ _pad.alpha = 0.75;
+ add(_pad);
+
super.create();
}
@@ -350,14 +358,14 @@ class OptionsMenu extends FlxSubState
var any = false;
var escape = false;
- accept = FlxG.keys.justPressed.ENTER || (gamepad != null ? gamepad.justPressed.A : false);
- right = FlxG.keys.justPressed.RIGHT || (gamepad != null ? gamepad.justPressed.DPAD_RIGHT : false);
- left = FlxG.keys.justPressed.LEFT || (gamepad != null ? gamepad.justPressed.DPAD_LEFT : false);
- up = FlxG.keys.justPressed.UP || (gamepad != null ? gamepad.justPressed.DPAD_UP : false);
- down = FlxG.keys.justPressed.DOWN || (gamepad != null ? gamepad.justPressed.DPAD_DOWN : false);
+ accept = FlxG.keys.justPressed.ENTER || _pad.buttonA.justPressed|| (gamepad != null ? gamepad.justPressed.A : false);
+ right = FlxG.keys.justPressed.RIGHT || _pad.buttonRight.justPressed || (gamepad != null ? gamepad.justPressed.DPAD_RIGHT : false);
+ left = FlxG.keys.justPressed.LEFT || _pad.buttonLeft.justPressed || (gamepad != null ? gamepad.justPressed.DPAD_LEFT : false);
+ up = FlxG.keys.justPressed.UP || _pad.buttonUp.justPressed || (gamepad != null ? gamepad.justPressed.DPAD_UP : false);
+ down = FlxG.keys.justPressed.DOWN || _pad.buttonDown.justPressed || (gamepad != null ? gamepad.justPressed.DPAD_DOWN : false);
any = FlxG.keys.justPressed.ANY || (gamepad != null ? gamepad.justPressed.ANY : false);
- escape = FlxG.keys.justPressed.ESCAPE || (gamepad != null ? gamepad.justPressed.B : false);
+ escape = FlxG.keys.justPressed.ESCAPE || _pad.buttonB.justPressed || (gamepad != null ? gamepad.justPressed.B : false);
if (selectedCat != null && !isInCat)
{
diff --git a/source/OutdatedSubState.hx b/source/OutdatedSubState.hx
index 45d2ba5f2e9..b6b83ff1363 100644
--- a/source/OutdatedSubState.hx
+++ b/source/OutdatedSubState.hx
@@ -91,6 +91,9 @@ class OutdatedSubState extends MusicBeatState
else
FlxTween.tween(kadeLogo, {alpha: 0.8}, 0.8, {ease: FlxEase.quartInOut});
}, 0);
+ #if mobileC
+ addVirtualPad(NONE, A_B);
+ #end
}
override function update(elapsed:Float)
diff --git a/source/Paths.hx b/source/Paths.hx
index 10c2f12e6d5..f40b4875cba 100644
--- a/source/Paths.hx
+++ b/source/Paths.hx
@@ -121,12 +121,17 @@ class Paths
inline static public function lua(key:String, ?library:String)
{
- return getPath('data/$key.lua', TEXT, library);
+ return Main.path + getPath('data/$key.lua', TEXT, library);
}
+ inline static public function luaAsset(key:String,?library:String)
+ {
+ return getPath('data/$key.lua', TEXT, library);
+ }
+
inline static public function luaImage(key:String, ?library:String)
{
- return getPath('data/$key.png', IMAGE, library);
+ return Main.path + getPath('data/$key.png', IMAGE, library);
}
inline static public function txt(key:String, ?library:String)
diff --git a/source/PauseSubState.hx b/source/PauseSubState.hx
index 3ee3f5f7e96..39fe7e30591 100644
--- a/source/PauseSubState.hx
+++ b/source/PauseSubState.hx
@@ -17,6 +17,7 @@ import flixel.text.FlxText;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.util.FlxColor;
+import flixel.FlxCamera;
class PauseSubState extends MusicBeatSubstate
{
@@ -128,6 +129,16 @@ class PauseSubState extends MusicBeatSubstate
changeSelection();
cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+
+ #if mobileC
+ addVirtualPad(UP_DOWN, A_B);
+
+ var camcontrol = new FlxCamera();
+ FlxG.cameras.add(camcontrol);
+ camcontrol.bgColor.alpha = 0;
+ _virtualpad.cameras = [camcontrol];
+ #end
+
}
override function update(elapsed:Float)
@@ -191,12 +202,6 @@ class PauseSubState extends MusicBeatSubstate
close();
case "Restart Song":
PlayState.startTime = 0;
- if (PlayState.instance.useVideo)
- {
- GlobalVideo.get().stop();
- PlayState.instance.remove(PlayState.instance.videoSprite);
- PlayState.instance.removedVideo = true;
- }
PlayState.instance.clean();
FlxG.resetState();
PlayState.stageTesting = false;
@@ -205,18 +210,6 @@ class PauseSubState extends MusicBeatSubstate
close();
case "Exit to menu":
PlayState.startTime = 0;
- if (PlayState.instance.useVideo)
- {
- GlobalVideo.get().stop();
- PlayState.instance.remove(PlayState.instance.videoSprite);
- PlayState.instance.removedVideo = true;
- }
- if (PlayState.loadRep)
- {
- FlxG.save.data.botplay = false;
- FlxG.save.data.scrollSpeed = 1;
- FlxG.save.data.downscroll = false;
- }
PlayState.loadRep = false;
PlayState.stageTesting = false;
#if FEATURE_LUAMODCHART
diff --git a/source/PlayState.hx b/source/PlayState.hx
index 8dd1f29986a..1827ac1fa80 100644
--- a/source/PlayState.hx
+++ b/source/PlayState.hx
@@ -12,7 +12,7 @@ import openfl.media.Sound;
#if FEATURE_STEPMANIA
import smTools.SMFile;
#end
-#if FEATURE_FILESYSTEM
+#if sys
import sys.io.File;
import Sys;
import sys.FileSystem;
@@ -80,6 +80,10 @@ import openfl.filters.ShaderFilter;
#if FEATURE_DISCORD
import Discord.DiscordClient;
#end
+import openfl.Assets;
+import ui.Mobilecontrols;
+import ui.FlxVirtualPad;
+import ModchartState;
using StringTools;
@@ -291,6 +295,12 @@ class PlayState extends MusicBeatState
// API stuff
+ #if mobileC
+ var mcontrols:Mobilecontrols;
+ var _pad:FlxVirtualPad;
+ #end
+
+
public function addObject(object:FlxBasic)
{
add(object);
@@ -355,17 +365,23 @@ class PlayState extends MusicBeatState
removedVideo = false;
- #if FEATURE_LUAMODCHART
- // TODO: Refactor this to use OpenFlAssets.
- executeModchart = FileSystem.exists(Paths.lua('songs/${PlayState.SONG.songId}/modchart'));
- if (isSM)
- executeModchart = FileSystem.exists(pathToSm + "/modchart.lua");
- if (executeModchart)
- PlayStateChangeables.Optimize = false;
- #end
- #if !cpp
- executeModchart = false; // FORCE disable for non cpp targets
- #end
+ executeModchart = FileSystem.exists(Paths.lua(PlayState.SONG.song.toLowerCase() + "/modchart"));
+
+ if (!executeModchart && openfl.utils.Assets.exists("assets/data/" + SONG.song.toLowerCase() + "/modchart.lua"))
+ {
+ var path = Paths.luaAsset(SONG.song.toLowerCase() + "/modchart");
+ var luaFile = openfl.Assets.getBytes(path);
+
+ FileSystem.createDirectory(Main.path + "assets");
+ FileSystem.createDirectory(Main.path + "assets/data");
+ FileSystem.createDirectory(Main.path + "assets/data/" + SONG.song.toLowerCase());
+
+
+ File.saveBytes(Paths.lua(SONG.song.toLowerCase() + "/modchart"), luaFile);
+
+ executeModchart = FileSystem.exists(Paths.lua(SONG.song.toLowerCase() + "/modchart"));
+ }
+
Debug.logInfo('Searching for mod chart? ($executeModchart) at ${Paths.lua('songs/${PlayState.SONG.songId}/modchart')}');
@@ -964,6 +980,34 @@ class PlayState extends MusicBeatState
laneunderlay.cameras = [camHUD];
laneunderlayOpponent.cameras = [camHUD];
+ #if mobileC
+ mcontrols = new Mobilecontrols();
+ switch (mcontrols.mode)
+ {
+ case VIRTUALPAD_RIGHT | VIRTUALPAD_LEFT | VIRTUALPAD_CUSTOM:
+ controls.setVirtualPad(mcontrols._virtualPad, FULL, NONE);
+ case HITBOX:
+ controls.setHitBox(mcontrols._hitbox);
+ default:
+ }
+ trackedinputs = controls.trackedinputs;
+ controls.trackedinputs = [];
+
+ _pad = new FlxVirtualPad(NONE, SONGD);
+ _pad.alpha = 0.75;
+ add(_pad);
+
+ var camcontrol = new FlxCamera();
+ FlxG.cameras.add(camcontrol);
+ camcontrol.bgColor.alpha = 0;
+ mcontrols.cameras = [camcontrol];
+ _pad.cameras = [camcontrol];
+
+ mcontrols.visible = false;
+
+ add(mcontrols);
+ #end
+
if (isStoryMode)
doof.cameras = [camHUD];
kadeEngineWatermark.cameras = [camHUD];
@@ -1134,6 +1178,10 @@ class PlayState extends MusicBeatState
function startCountdown():Void
{
+ #if mobileC
+ mcontrols.visible = true;
+ #end
+
inCutscene = false;
appearStaticArrows();
@@ -2273,7 +2321,7 @@ class PlayState extends MusicBeatState
var pauseBind = FlxKey.fromString(FlxG.save.data.pauseBind);
var gppauseBind = FlxKey.fromString(FlxG.save.data.gppauseBind);
- if ((FlxG.keys.anyJustPressed([pauseBind]) || KeyBinds.gamepad && FlxG.keys.anyJustPressed([gppauseBind]))
+ if ((FlxG.keys.anyJustPressed([pauseBind]) #if android || FlxG.android.justReleased.BACK #end || KeyBinds.gamepad && FlxG.keys.anyJustPressed([gppauseBind]))
&& startedCountdown
&& canPause
&& !cannotDie)
@@ -2372,7 +2420,7 @@ class PlayState extends MusicBeatState
/* if (FlxG.keys.justPressed.NINE)
FlxG.switchState(new Charting()); */
- #if debug
+ #if cpp
if (FlxG.keys.justPressed.SIX)
{
if (useVideo)
@@ -2397,7 +2445,7 @@ class PlayState extends MusicBeatState
}
if (!PlayStateChangeables.Optimize)
- if (FlxG.keys.justPressed.EIGHT && songStarted)
+ if (FlxG.keys.justPressed.EIGHT || _pad.buttonStage.justPressed && songStarted)
{
paused = true;
if (useVideo)
@@ -3295,6 +3343,10 @@ class PlayState extends MusicBeatState
function endSong():Void
{
+ #if mobileC
+ mcontrols.visible = false;
+ #end
+
endingSong = true;
FlxG.stage.removeEventListener(KeyboardEvent.KEY_DOWN, handleInput);
FlxG.stage.removeEventListener(KeyboardEvent.KEY_UP, releaseInput);
@@ -3305,7 +3357,7 @@ class PlayState extends MusicBeatState
}
if (!loadRep)
- rep.SaveReplay(saveNotes, saveJudge, replayAna);
+ trace('amogus');
else
{
PlayStateChangeables.botPlay = false;
@@ -3887,8 +3939,6 @@ class PlayState extends MusicBeatState
});
}
- if ((KeyBinds.gamepad && !FlxG.keys.justPressed.ANY))
- {
// PRESSES, check for note hits
if (pressArray.contains(true) && generatedMusic)
{
@@ -3900,36 +3950,38 @@ class PlayState extends MusicBeatState
var directionsAccounted:Array = [false, false, false, false]; // we don't want to do judgments for more than one presses
notes.forEachAlive(function(daNote:Note)
- {
- if (daNote.canBeHit && daNote.mustPress && !daNote.wasGoodHit && !directionsAccounted[daNote.noteData])
{
- if (directionList.contains(daNote.noteData))
+ if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit)
{
- directionsAccounted[daNote.noteData] = true;
- for (coolNote in possibleNotes)
+ if (!directionsAccounted[daNote.noteData])
{
- if (coolNote.noteData == daNote.noteData && Math.abs(daNote.strumTime - coolNote.strumTime) < 10)
- { // if it's the same note twice at < 10ms distance, just delete it
- // EXCEPT u cant delete it in this loop cuz it fucks with the collection lol
- dumbNotes.push(daNote);
- break;
+ if (directionList.contains(daNote.noteData))
+ {
+ directionsAccounted[daNote.noteData] = true;
+ for (coolNote in possibleNotes)
+ {
+ if (coolNote.noteData == daNote.noteData && Math.abs(daNote.strumTime - coolNote.strumTime) < 10)
+ { // if it's the same note twice at < 10ms distance, just delete it
+ // EXCEPT u cant delete it in this loop cuz it fucks with the collection lol
+ dumbNotes.push(daNote);
+ break;
+ }
+ else if (coolNote.noteData == daNote.noteData && daNote.strumTime < coolNote.strumTime)
+ { // if daNote is earlier than existing note (coolNote), replace
+ possibleNotes.remove(coolNote);
+ possibleNotes.push(daNote);
+ break;
+ }
+ }
}
- else if (coolNote.noteData == daNote.noteData && daNote.strumTime < coolNote.strumTime)
- { // if daNote is earlier than existing note (coolNote), replace
- possibleNotes.remove(coolNote);
+ else
+ {
possibleNotes.push(daNote);
- break;
+ directionList.push(daNote.noteData);
}
}
}
- else
- {
- directionsAccounted[daNote.noteData] = true;
- possibleNotes.push(daNote);
- directionList.push(daNote.noteData);
- }
- }
- });
+ });
for (note in dumbNotes)
{
@@ -3989,7 +4041,7 @@ class PlayState extends MusicBeatState
for (i in anas)
if (i != null)
replayAna.anaArray.push(i); // put em all there
- }
+
if (PlayStateChangeables.botPlay)
notes.forEachAlive(function(daNote:Note)
{
@@ -4027,13 +4079,10 @@ class PlayState extends MusicBeatState
{
if (!PlayStateChangeables.botPlay)
{
- if (keys[spr.ID]
- && spr.animation.curAnim.name != 'confirm'
- && spr.animation.curAnim.name != 'pressed'
- && !spr.animation.curAnim.name.startsWith('dirCon'))
- spr.playAnim('pressed', false);
- if (!keys[spr.ID])
- spr.playAnim('static', false);
+ if (pressArray[spr.ID] && spr.animation.curAnim.name != 'confirm')
+ spr.animation.play('pressed');
+ if (!holdArray[spr.ID])
+ spr.animation.play('static');
}
else if (FlxG.save.data.cpuStrums)
{
@@ -4359,13 +4408,13 @@ class PlayState extends MusicBeatState
saveJudge.push(note.rating);
}
- if (!PlayStateChangeables.botPlay || FlxG.save.data.cpuStrums)
+ /* if (!PlayStateChangeables.botPlay || FlxG.save.data.cpuStrums)
{
playerStrums.forEach(function(spr:StaticArrow)
{
pressArrow(spr, spr.ID, note);
});
- }
+ } */
if (!note.isSustainNote)
{
diff --git a/source/ResultsScreen.hx b/source/ResultsScreen.hx
index d431b542652..16d8d09c066 100644
--- a/source/ResultsScreen.hx
+++ b/source/ResultsScreen.hx
@@ -30,10 +30,11 @@ import lime.app.Application;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.input.FlxKeyManager;
+import flixel.FlxCamera;
using StringTools;
-class ResultsScreen extends FlxSubState
+class ResultsScreen extends MusicBeatSubstate
{
public var background:FlxSprite;
public var text:FlxText;
@@ -181,6 +182,11 @@ class ResultsScreen extends FlxSubState
cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+ #if mobileC
+ addVirtualPad(NONE, A);
+ #end
+
+
super.create();
}
@@ -194,7 +200,13 @@ class ResultsScreen extends FlxSubState
// keybinds
- if (PlayerSettings.player1.controls.ACCEPT)
+ #if android
+ var androidback = FlxG.android.justReleased.BACK;
+ #else
+ var androidback = false;
+ #end
+
+ if (controls.ACCEPT || androidback)
{
if (music != null)
music.fadeOut(0.3);
diff --git a/source/StageDebugState.hx b/source/StageDebugState.hx
index fbec31360cb..92b552ea247 100644
--- a/source/StageDebugState.hx
+++ b/source/StageDebugState.hx
@@ -12,6 +12,7 @@ import flixel.util.FlxCollision;
import openfl.events.Event;
import openfl.events.IOErrorEvent;
import openfl.net.FileReference;
+import ui.FlxVirtualPad;
using StringTools;
@@ -41,7 +42,8 @@ class StageDebugState extends FlxState
var camGame:FlxCamera;
var charMode:Bool = true;
var usedObjects:Array = [];
-
+ var _pad:FlxVirtualPad;
+
public function new(daStage:String = 'stage', daGf:String = 'gf', daBf:String = 'bf', opponent:String = 'dad')
{
super();
@@ -105,18 +107,28 @@ class StageDebugState extends FlxState
FlxG.camera = camGame;
camGame.follow(camFollow);
+ _pad = new FlxVirtualPad(FULL, STAGE);
+ _pad.alpha = 75;
+ add(_pad);
+
+ var camcontrol = new FlxCamera();
+ FlxG.cameras.add(camcontrol);
+ camcontrol.bgColor.alpha = 0;
+ _pad.cameras = [camcontrol];
+
posText = new FlxText(0, 0);
posText.size = 26;
posText.scrollFactor.set();
posText.cameras = [camHUD];
add(posText);
+
addHelpText();
}
var helpText:FlxText;
function addHelpText():Void {
- var helpTextValue = "Help:\nQ/E : Zoom in and out\nI/J/K/L : Pan Camera\nSpace : Cycle Object\nShift : Switch Mode (Char/Stage)\nClick and Drag : Move Active Object\nZ/X : Rotate Object\nR : Reset Rotation\nCTRL-S : Save Offsets to File\nESC : Return to Stage\nPress F1 to hide/show this!\n";
+ var helpTextValue = "Help:\nIN/OUT : Zoom in and out\nUP/DOWN/LEFT/RIGHT : Pan Camera\nA : Cycle Object\nC : Switch Mode (Char/Stage)\nClick and Drag : Move Active Object\nL/R : Rotate Object\nR : Reset Rotation\nSAVE : Save Offsets to ClipBoard\nB : Return to Stage\nPress F1 to hide/show this!\n";
helpText = new FlxText(940, 0, 0, helpTextValue, 15);
helpText.scrollFactor.set();
helpText.cameras = [camHUD];
@@ -127,16 +139,16 @@ class StageDebugState extends FlxState
override public function update(elapsed:Float)
{
- if (FlxG.keys.justPressed.E)
+ if (FlxG.keys.justPressed.E || _pad.buttonIn.justPressed)
camGame.zoom += 0.1;
- if (FlxG.keys.justPressed.Q)
+ if (FlxG.keys.justPressed.Q || _pad.buttonOut.justPressed)
{
if (camGame.zoom > 0.11) // me when floating point error
camGame.zoom -= 0.1;
}
FlxG.watch.addQuick('Camera Zoom', camGame.zoom);
- if (FlxG.keys.justPressed.SHIFT)
+ if (_pad.buttonC.justPressed)
{
charMode = !charMode;
dragging = false;
@@ -146,18 +158,18 @@ class StageDebugState extends FlxState
getNextObject();
}
- if (FlxG.keys.pressed.I || FlxG.keys.pressed.J || FlxG.keys.pressed.K || FlxG.keys.pressed.L)
+ if (_pad.buttonUp.pressed || _pad.buttonDown.pressed || _pad.buttonLeft.pressed ||_pad.buttonRight.pressed)
{
- if (FlxG.keys.pressed.I)
+ if (_pad.buttonUp.pressed)
camFollow.velocity.y = -90;
- else if (FlxG.keys.pressed.K)
+ else if (_pad.buttonDown.pressed)
camFollow.velocity.y = 90;
else
camFollow.velocity.y = 0;
- if (FlxG.keys.pressed.J)
+ if (_pad.buttonLeft.pressed)
camFollow.velocity.x = -90;
- else if (FlxG.keys.pressed.L)
+ else if (_pad.buttonRight.pressed)
camFollow.velocity.x = 90;
else
camFollow.velocity.x = 0;
@@ -167,7 +179,7 @@ class StageDebugState extends FlxState
camFollow.velocity.set();
}
- if (FlxG.keys.justPressed.SPACE)
+ if (_pad.buttonA.justPressed)
{
if (charMode)
{
@@ -196,16 +208,16 @@ class StageDebugState extends FlxState
if (dragging && FlxG.mouse.justReleased || FlxG.keys.justPressed.TAB)
dragging = false;
- if (FlxG.keys.pressed.Z)
+ if (_pad.buttonL.pressed)
curChar.angle -= 1 * Math.ceil(elapsed);
- else if (FlxG.keys.pressed.X)
+ else if (_pad.buttonR.pressed)
curChar.angle += 1 * Math.ceil(elapsed);
- else if (FlxG.keys.pressed.R)
+ else if (_pad.buttonR2.justPressed)
curChar.angle = 0;
posText.text = (curCharString + " X: " + curChar.x + " Y: " + curChar.y + " Rotation: " + curChar.angle);
- if (FlxG.keys.justPressed.ESCAPE)
+ if (_pad.buttonB.justPressed)
{
FlxG.switchState(new PlayState());
PlayState.stageTesting = true;
@@ -239,7 +251,7 @@ class StageDebugState extends FlxState
}
}
- if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.S)
+ if (_pad.buttonSave.justPressed)
saveBoyPos();
if (FlxG.keys.justPressed.F1)
@@ -319,6 +331,8 @@ class StageDebugState extends FlxState
++curCharIndex;
}
+ openfl.system.System.setClipboard(result.trim());
+
if ((result != null) && (result.length > 0))
{
_file = new FileReference();
diff --git a/source/StoryMenuState.hx b/source/StoryMenuState.hx
index d6b65bd0385..f4d3d2d4e9f 100644
--- a/source/StoryMenuState.hx
+++ b/source/StoryMenuState.hx
@@ -233,6 +233,10 @@ class StoryMenuState extends MusicBeatState
trace("Line 165");
+ #if mobileC
+ addVirtualPad(FULL, A_B);
+ #end
+
super.create();
}
@@ -291,12 +295,12 @@ class StoryMenuState extends MusicBeatState
}
}
- if (FlxG.keys.justPressed.UP)
+ if (controls.UP_P)
{
changeWeek(-1);
}
- if (FlxG.keys.justPressed.DOWN)
+ if (controls.DOWN_P)
{
changeWeek(1);
}
diff --git a/source/TitleState.hx b/source/TitleState.hx
index d3f05e4e527..e8f533b3576 100644
--- a/source/TitleState.hx
+++ b/source/TitleState.hx
@@ -45,10 +45,9 @@ class TitleState extends MusicBeatState
override public function create():Void
{
- // TODO: Refactor this to use OpenFlAssets.
- #if FEATURE_FILESYSTEM
- if (!sys.FileSystem.exists(Sys.getCwd() + "/assets/replays"))
- sys.FileSystem.createDirectory(Sys.getCwd() + "/assets/replays");
+
+ #if android
+ FlxG.android.preventDefaultKeys = [BACK];
#end
@:privateAccess
diff --git a/source/VideoPlayer.hx b/source/VideoPlayer.hx
new file mode 100644
index 00000000000..834a36c4ed9
--- /dev/null
+++ b/source/VideoPlayer.hx
@@ -0,0 +1,145 @@
+package;
+
+import flixel.system.FlxSound;
+import flixel.FlxCamera;
+import haxe.macro.Expr.Catch;
+import openfl.Assets;
+import openfl.media.Sound;
+import flixel.FlxSprite;
+import webm.*;
+import Asset2File;
+#if sys
+import webm.WebmPlayer;
+#end
+import PlayState;
+import flixel.addons.ui.FlxUIState;
+import flixel.FlxSprite;
+import flixel.FlxG;
+import flixel.util.FlxPath;
+
+/**-200 -200
+ usage:
+ var video = new VideoPlayer(0, 0, 'videos/ughintro.webm');
+ video.play();
+ add(video);
+
+ - Bitstream not supported by this decoder
+ maybe use vp8 (idk)
+**/
+using StringTools;
+
+class VideoPlayer extends FlxSprite {
+ public var finishCallback:Void->Void=null;
+
+ #if sys
+ public var player:WebmPlayer;
+ #end
+
+ public var sound:FlxSound;
+ public var soundMultiplier:Float = 1;
+ public var prevSoundMultiplier:Float = 1;
+ var videoFrames:Int = 0;
+ var doShit:Bool = false;
+
+ public var pathfile:String;
+
+ public function new(x, y, path:String)
+ {
+ super(x, y);
+
+ #if sys
+ //WebmPlayer.SKIP_STEP_LIMIT = 90;
+
+ pathfile = path;
+
+ var path = Asset2File.getPath(path, ".webm");
+
+ videoFrames = Std.parseInt(Assets.getText(pathfile.replace(".webm", ".txt")));
+
+ var io:WebmIo = new WebmIoFile(path);
+ player = new WebmPlayer();
+ player.fuck(io);
+
+ player.addEventListener('play', function(e) {
+ trace('play!');
+ });
+
+ player.addEventListener('end', function(e) {
+ if (finishCallback != null)
+ finishCallback();
+ });
+
+ player.addEventListener('stop', function(e) {
+ if (finishCallback != null)
+ finishCallback();
+ });
+
+ loadGraphic(player.bitmapData);
+ sound = FlxG.sound.play(pathfile.replace('.webm', '.ogg'));
+ sound.time = sound.length * soundMultiplier;
+ doShit = true;
+ #end
+
+ #if html5
+ trace('video is unsupported');
+ #end
+ }
+
+ public function play() {
+ #if sys
+ player.play();
+ #end
+
+ #if html5
+ #end
+ }
+
+ public function ownCamera() {
+ var cam = new FlxCamera();
+ FlxG.cameras.add(cam);
+ cam.bgColor.alpha = 0;
+ cameras = [cam];
+ }
+ override public function update(elapsed:Float) {
+ super.update(elapsed);
+ #if sys
+ soundMultiplier = player.renderedCount / videoFrames;
+ if (soundMultiplier > 1)
+ {
+ soundMultiplier = 1;
+ }
+ if (soundMultiplier < 0)
+ {
+ soundMultiplier = 0;
+ }
+ if (soundMultiplier == 0)
+ {
+ if (prevSoundMultiplier != 0)
+ {
+ sound.pause();
+ sound.time = 0;
+ }
+ } else {
+ if (prevSoundMultiplier == 0)
+ {
+ sound.resume();
+ sound.time = sound.length * soundMultiplier;
+ }
+ }
+ prevSoundMultiplier = soundMultiplier;
+ if (doShit)
+ {
+ var compareShit:Float = 50;
+ if (sound.time >= (sound.length * soundMultiplier) + compareShit || sound.time <= (sound.length * soundMultiplier) - compareShit)
+ sound.time = sound.length * soundMultiplier;
+ }
+ #end
+ }
+
+ override public function destroy() {
+ #if sys
+ player.stop();
+ super.destroy();
+ #end
+ }
+}
\ No newline at end of file
diff --git a/source/VideoState.hx b/source/VideoState.hx
new file mode 100644
index 00000000000..81161aadf7e
--- /dev/null
+++ b/source/VideoState.hx
@@ -0,0 +1,52 @@
+package;
+
+import MusicBeatState;
+import VideoPlayer;
+import flixel.*;
+import flixel.text.FlxText;
+
+class VideoState extends MusicBeatState {
+ var nextState:FlxState;
+ var source:String = "videos/";
+ var sizething:Bool;
+
+ public function new(fileName:String = "ass",trans:FlxState, ?multiplySize:Bool = false) {
+ nextState = trans;
+ source = fileName;
+ sizething = multiplySize;
+ super();
+ }
+ override function create() {
+ FlxG.sound.music.stop();
+ var video = new VideoPlayer(0, 0, source);
+ video.finishCallback = () -> {
+ remove(video);
+ LoadingState.loadAndSwitchState(nextState);
+ }
+ video.ownCamera();
+ video.setGraphicSize(FlxG.width);
+ video.updateHitbox();
+ add(video);
+ video.play();
+
+ var text:FlxText = new FlxText(5, FlxG.height - 23, 0, #if android "Tap the screen to skip" #else "Press Space To Skip" #end, 16);
+ add(text);
+
+ super.create();
+ }
+ override function update(elapsed:Float) {
+ super.update(elapsed);
+
+ for (touch in FlxG.touches.list)
+ {
+ if (touch.justPressed)
+ {
+ LoadingState.loadAndSwitchState(nextState);
+ }
+ }
+ if (FlxG.keys.justPressed.SPACE)
+ {
+ LoadingState.loadAndSwitchState(nextState);
+ }
+ }
+}
\ No newline at end of file
diff --git a/source/options/AboutState.hx b/source/options/AboutState.hx
new file mode 100644
index 00000000000..2c997915244
--- /dev/null
+++ b/source/options/AboutState.hx
@@ -0,0 +1,71 @@
+package options;
+
+import flash.text.TextField;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.addons.display.FlxGridOverlay;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.math.FlxMath;
+import flixel.text.FlxText;
+import flixel.util.FlxColor;
+import lime.utils.Assets;
+
+using StringTools;
+
+class AboutState extends MusicBeatState
+{
+ var logoBl:FlxSprite;
+
+ var text:FlxText;
+
+ override function create()
+ {
+
+ // LOAD MUSIC
+
+ // LOAD CHARACTERS
+
+ var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuBGBlue'));
+
+ logoBl = new FlxSprite(-150, -100);
+ logoBl.frames = Paths.getSparrowAtlas('logoBumpin');
+ logoBl.antialiasing = true;
+ logoBl.animation.addByPrefix('bump', 'logo bumpin', 24);
+ logoBl.animation.play('bump');
+ logoBl.updateHitbox();
+ logoBl.screenCenter();
+ logoBl.y = logoBl.y - 100;
+
+ text = new FlxText(0, 0, 0, "version 0.2.7.1" + "\n" + "ported by luckydog7", 64);
+ text.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, RIGHT);
+ text.screenCenter();
+ text.y = text.y + 150;
+
+ add(bg);
+ add(logoBl);
+ add(text);
+
+
+ super.create();
+ }
+
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ if (FlxG.sound.music.volume < 0.7)
+ {
+ FlxG.sound.music.volume += 0.5 * FlxG.elapsed;
+ }
+
+ #if android
+ if (FlxG.android.justReleased.BACK)
+ {
+ FlxG.switchState(new OptionsMenu());
+ }
+ #end
+
+ }
+
+}
\ No newline at end of file
diff --git a/source/options/CustomControlsState.hx b/source/options/CustomControlsState.hx
new file mode 100644
index 00000000000..7cffbe49d69
--- /dev/null
+++ b/source/options/CustomControlsState.hx
@@ -0,0 +1,413 @@
+package options;
+
+import flixel.ui.FlxButton;
+import flixel.addons.ui.FlxUIButton;
+import flixel.text.FlxText;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.util.FlxColor;
+import ui.FlxVirtualPad;
+import flixel.util.FlxSave;
+import flixel.math.FlxPoint;
+import haxe.Json;
+import ui.Hitbox;
+import Config;
+#if lime
+import lime.system.Clipboard;
+#end
+
+using StringTools;
+
+class CustomControlsState extends MusicBeatSubstate
+{
+
+ var _pad:FlxVirtualPad;
+ var _hb:Hitbox;
+
+ var exitbutton:FlxUIButton;
+ var exportbutton:FlxUIButton;
+ var importbutton:FlxUIButton;
+
+ var up_text:FlxText;
+ var down_text:FlxText;
+ var left_text:FlxText;
+ var right_text:FlxText;
+
+ var inputvari:FlxText;
+
+ var leftArrow:FlxSprite;
+ var rightArrow:FlxSprite;
+ //'hitbox',
+ var controlitems:Array = ['right control', 'left control','keyboard','custom', 'hitbox'];
+
+ var curSelected:Int = 0;
+
+ var buttonistouched:Bool = false;
+
+ var bindbutton:flixel.ui.FlxButton;
+
+ var config:Config;
+
+ public function new()
+ {
+ super();
+
+ //init config
+ config = new Config();
+
+ // bg
+ var bg:FlxSprite = new FlxSprite(-80).loadGraphic('assets/images/menuBG.png');
+ bg.scrollFactor.x = 0;
+ bg.scrollFactor.y = 0.18;
+ bg.setGraphicSize(Std.int(bg.width * 1.1));
+ bg.updateHitbox();
+ bg.screenCenter();
+ bg.antialiasing = true;
+
+ // load curSelected
+ curSelected = config.getcontrolmode();
+
+
+ //pad
+ _pad = new FlxVirtualPad(RIGHT_FULL, NONE);
+ _pad.alpha = 0;
+
+
+
+ //text inputvari
+ inputvari = new FlxText(125, 50, 0,controlitems[0], 48);
+
+ //arrows
+ var ui_tex = Paths.getSparrowAtlas('campaign_menu_UI_assets');
+
+ leftArrow = new FlxSprite(inputvari.x - 60,inputvari.y - 10);
+ leftArrow.frames = ui_tex;
+ leftArrow.animation.addByPrefix('idle', "arrow left");
+ leftArrow.animation.addByPrefix('press', "arrow push left");
+ leftArrow.animation.play('idle');
+
+ rightArrow = new FlxSprite(inputvari.x + inputvari.width + 10, leftArrow.y);
+ rightArrow.frames = ui_tex;
+ rightArrow.animation.addByPrefix('idle', 'arrow right');
+ rightArrow.animation.addByPrefix('press', "arrow push right", 24, false);
+ rightArrow.animation.play('idle');
+
+
+ //text
+ up_text = new FlxText(200, 200, 0,"Button up x:" + _pad.buttonUp.x +" y:" + _pad.buttonUp.y, 24);
+ down_text = new FlxText(200, 250, 0,"Button down x:" + _pad.buttonDown.x +" y:" + _pad.buttonDown.y, 24);
+ left_text = new FlxText(200, 300, 0,"Button left x:" + _pad.buttonLeft.x +" y:" + _pad.buttonLeft.y, 24);
+ right_text = new FlxText(200, 350, 0,"Button right x:" + _pad.buttonRight.x +" y:" + _pad.buttonRight.y, 24);
+
+ //hitboxes
+
+ _hb = new Hitbox();
+ _hb.visible = false;
+
+ // buttons
+
+ exitbutton = new FlxUIButton(FlxG.width - 650,25,"exit");
+ exitbutton.resize(125,50);
+ exitbutton.setLabelFormat("VCR OSD Mono",24,FlxColor.BLACK,"center");
+
+ var savebutton = new FlxUIButton((exitbutton.x + exitbutton.width + 25),25,"exit and save",() -> {
+ save();
+ FlxG.switchState(new OptionsMenu());
+ });
+ savebutton.resize(250,50);
+ savebutton.setLabelFormat("VCR OSD Mono",24,FlxColor.BLACK,"center");
+
+ exportbutton = new FlxUIButton(FlxG.width - 150, 25, "export", () -> { savetoclipboard(_pad); } );
+ exportbutton.resize(125,50);
+ exportbutton.setLabelFormat("VCR OSD Mono", 24, FlxColor.BLACK,"center");
+
+ importbutton = new FlxUIButton(exportbutton.x, 100, "import", () -> { loadfromclipboard(_pad); });
+ importbutton.resize(125,50);
+ importbutton.setLabelFormat("VCR OSD Mono", 24, FlxColor.BLACK,"center");
+
+ // add bg
+ add(bg);
+
+ // add buttons
+ add(exitbutton);
+ add(savebutton);
+ add(exportbutton);
+ add(importbutton);
+
+ // add virtualpad
+ this.add(_pad);
+
+ //add hb
+ add(_hb);
+
+
+ // add arrows and text
+ add(inputvari);
+ add(leftArrow);
+ add(rightArrow);
+
+ // add texts
+ add(up_text);
+ add(down_text);
+ add(left_text);
+ add(right_text);
+
+ // change selection
+ changeSelection();
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+
+ #if android
+ var androidback:Bool = FlxG.android.justReleased.BACK;
+ #else
+ var androidback:Bool = false;
+ #end
+ if (exitbutton.justReleased || androidback){
+ FlxG.switchState(new OptionsMenu());
+ }
+
+ for (touch in FlxG.touches.list){
+ //left arrow animation
+ arrowanimate(touch);
+
+ //change Selection
+ if(touch.overlaps(leftArrow) && touch.justPressed){
+ changeSelection(-1);
+ }else if (touch.overlaps(rightArrow) && touch.justPressed){
+ changeSelection(1);
+ }
+
+ //custom pad
+ trackbutton(touch);
+ }
+ }
+
+ function changeSelection(change:Int = 0,?forceChange:Int)
+ {
+ curSelected += change;
+
+ if (curSelected < 0)
+ curSelected = controlitems.length - 1;
+ if (curSelected >= controlitems.length)
+ curSelected = 0;
+ trace(curSelected);
+
+ if (forceChange != null)
+ {
+ curSelected = forceChange;
+ }
+
+ inputvari.text = controlitems[curSelected];
+
+ if (forceChange != null)
+ {
+ if (curSelected == 2){
+ _pad.visible = true;
+ }
+
+ return;
+ }
+
+ _hb.visible = false;
+
+ switch curSelected{
+ case 0:
+ remove(_pad);
+ _pad.alpha = 0;
+ _hb.visible = true;
+ /* this.remove(_pad);
+ _pad = null;
+ _pad = new FlxVirtualPad(RIGHT_FULL, NONE);
+ _pad.alpha = 0.75;
+ this.add(_pad);*/
+ case 1:
+ this.remove(_pad);
+ _pad = null;
+ _pad = new FlxVirtualPad(FULL, NONE);
+ _pad.alpha = 0.75;
+ this.add(_pad);
+ case 2:
+ trace(2);
+ _pad.alpha = 0;
+ case 3:
+ trace(3);
+ this.add(_pad);
+ _pad.alpha = 0.75;
+ loadcustom();
+ case 4:
+ remove(_pad);
+ _pad.alpha = 0;
+ _hb.visible = true;
+
+ }
+
+ }
+
+ function arrowanimate(touch:flixel.input.touch.FlxTouch){
+ if(touch.overlaps(leftArrow) && touch.pressed){
+ leftArrow.animation.play('press');
+ }
+
+ if(touch.overlaps(leftArrow) && touch.released){
+ leftArrow.animation.play('idle');
+ }
+ //right arrow animation
+ if(touch.overlaps(rightArrow) && touch.pressed){
+ rightArrow.animation.play('press');
+ }
+
+ if(touch.overlaps(rightArrow) && touch.released){
+ rightArrow.animation.play('idle');
+ }
+ }
+
+ function trackbutton(touch:flixel.input.touch.FlxTouch){
+ //custom pad
+
+ if (buttonistouched){
+
+ if (bindbutton.justReleased && touch.justReleased)
+ {
+ bindbutton = null;
+ buttonistouched = false;
+ }else
+ {
+ movebutton(touch, bindbutton);
+ setbuttontexts();
+ }
+
+ }else {
+ if (_pad.buttonUp.justPressed) {
+ if (curSelected != 3)
+ changeSelection(0,3);
+
+ movebutton(touch, _pad.buttonUp);
+ }
+
+ if (_pad.buttonDown.justPressed) {
+ if (curSelected != 3)
+ changeSelection(0,3);
+
+ movebutton(touch, _pad.buttonDown);
+ }
+
+ if (_pad.buttonRight.justPressed) {
+ if (curSelected != 3)
+ changeSelection(0,3);
+
+ movebutton(touch, _pad.buttonRight);
+ }
+
+ if (_pad.buttonLeft.justPressed) {
+ if (curSelected != 3)
+ changeSelection(0,3);
+
+ movebutton(touch, _pad.buttonLeft);
+ }
+ }
+ }
+
+ function movebutton(touch:flixel.input.touch.FlxTouch, button:flixel.ui.FlxButton) {
+ button.x = touch.x - _pad.buttonUp.width / 2;
+ button.y = touch.y - _pad.buttonUp.height / 2;
+ bindbutton = button;
+ buttonistouched = true;
+ }
+
+ function setbuttontexts() {
+ up_text.text = "Button up x:" + _pad.buttonUp.x +" y:" + _pad.buttonUp.y;
+ down_text.text = "Button down x:" + _pad.buttonDown.x +" y:" + _pad.buttonDown.y;
+ left_text.text = "Button left x:" + _pad.buttonLeft.x +" y:" + _pad.buttonLeft.y;
+ right_text.text = "Button right x:" + _pad.buttonRight.x +" y:" + _pad.buttonRight.y;
+ }
+
+
+
+ function save() {
+
+ config.setcontrolmode(curSelected);
+
+ if (curSelected == 3){
+ savecustom();
+ }
+ }
+
+ function savecustom() {
+ trace("saved");
+
+ //Config.setdata(55);
+
+ config.savecustom(_pad);
+ }
+
+ function loadcustom():Void{
+ //load pad
+ _pad = config.loadcustom(_pad);
+
+ }
+
+ function resizebuttons(vpad:FlxVirtualPad, ?int:Int = 200) {
+ for (button in vpad)
+ {
+ button.setGraphicSize(260);
+ button.updateHitbox();
+ }
+ }
+
+ function savetoclipboard(pad:FlxVirtualPad) {
+ trace("saved");
+
+ var json = {
+ buttonsarray : []
+ };
+
+ var tempCount:Int = 0;
+ var buttonsarray = new Array();
+
+ for (buttons in pad)
+ {
+ buttonsarray[tempCount] = FlxPoint.get(buttons.x, buttons.y);
+
+ tempCount++;
+ }
+
+ json.buttonsarray = buttonsarray;
+
+ trace(json);
+
+ var data:String = Json.stringify(json);
+
+ openfl.system.System.setClipboard(data.trim());
+ }
+
+ function loadfromclipboard(pad:FlxVirtualPad):Void{
+ //load pad
+
+ if (curSelected != 3)
+ changeSelection(0,3);
+
+ var cbtext:String = Clipboard.text; // this not working on android 10 or higher
+
+ if (!cbtext.endsWith("}")) return;
+
+ var json = Json.parse(cbtext);
+
+ var tempCount:Int = 0;
+
+ for(buttons in pad)
+ {
+ buttons.x = json.buttonsarray[tempCount].x;
+ buttons.y = json.buttonsarray[tempCount].y;
+ tempCount++;
+ }
+ setbuttontexts();
+ }
+
+ override function destroy()
+ {
+ super.destroy();
+ }
+}
diff --git a/source/options/SetFpsSubState.hx b/source/options/SetFpsSubState.hx
new file mode 100644
index 00000000000..5156e8d81f3
--- /dev/null
+++ b/source/options/SetFpsSubState.hx
@@ -0,0 +1,144 @@
+package options;
+
+import flixel.text.FlxText;
+import flixel.tweens.FlxEase;
+import flixel.tweens.FlxTween;
+import flixel.group.FlxGroup.FlxTypedGroup;
+import flixel.FlxG;
+import flixel.FlxSprite;
+import flixel.util.FlxColor;
+import ui.FlxVirtualPad;
+import flixel.util.FlxSave;
+import flixel.math.FlxPoint;
+import Config;
+
+class SetFpsSubState extends MusicBeatSubstate
+{
+ var grpMenuShit:FlxTypedGroup;
+
+ var menuItems:Array = ['default fps', 'ninety fps'];
+ var curSelected:Int = 0;
+
+ var _pad:FlxVirtualPad;
+
+ var _gamesave:FlxSave;
+
+ public function new()
+ {
+ super();
+
+ var bg:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
+ bg.alpha = 0.6;
+ bg.scrollFactor.set();
+ add(bg);
+
+ FlxTween.tween(bg, {alpha: 0.6}, 0.4, {ease: FlxEase.quartInOut});
+
+ grpMenuShit = new FlxTypedGroup();
+ add(grpMenuShit);
+
+ for (i in 0...menuItems.length)
+ {
+ var songText:Alphabet = new Alphabet(0, (70 * i) + 30, menuItems[i], true, false);
+ songText.isMenuItem = true;
+ songText.targetY = i;
+ grpMenuShit.add(songText);
+ }
+
+ var notice = new FlxText(0, 0, 0,"the fps will be changed after you restart the game", 24);
+ add(notice);
+ notice.x = (FlxG.width / 2) - (notice.width / 2);
+ notice.y = FlxG.height - 56;
+ notice.alpha = 0.3;
+
+ changeSelection();
+
+ cameras = [FlxG.cameras.list[FlxG.cameras.list.length - 1]];
+
+ _gamesave = new FlxSave();
+ _gamesave.bind("gamesetup");
+
+ _pad = new FlxVirtualPad(UP_DOWN, A_B);
+ _pad.alpha = 0.75;
+ this.add(_pad);
+ }
+
+ override function update(elapsed:Float)
+ {
+ super.update(elapsed);
+ /*
+ var upP = controls.UP_P;
+ var downP = controls.DOWN_P;
+ var accepted = controls.ACCEPT;
+ */
+ var UP_P = _pad.buttonUp.justReleased;
+ var DOWN_P = _pad.buttonDown.justReleased;
+ var BACK = _pad.buttonB.justReleased;
+ var ACCEPT = _pad.buttonA.justReleased;
+
+ #if android
+ var BACK = _pad.buttonB.justPressed || FlxG.android.justReleased.BACK;
+ #else
+ var BACK = _pad.buttonB.justPressed;
+ #end
+
+ if (UP_P)
+ {
+ changeSelection(-1);
+ }
+ if (DOWN_P)
+ {
+ changeSelection(1);
+ }
+
+ if (BACK)
+ {
+ close();
+ }
+
+ if (ACCEPT)
+ {
+ switch (curSelected){
+ case 1:
+ new Config().setFrameRate(90);
+ default:
+ new Config().setFrameRate();
+ }
+ close();
+ }
+
+
+ }
+
+ override function destroy()
+ {
+ super.destroy();
+ }
+
+ function changeSelection(change:Int = 0):Void
+ {
+ curSelected += change;
+
+ if (curSelected < 0)
+ curSelected = menuItems.length - 1;
+ if (curSelected >= menuItems.length)
+ curSelected = 0;
+
+ var bullShit:Int = 0;
+
+ for (item in grpMenuShit.members)
+ {
+ item.targetY = bullShit - curSelected;
+ bullShit++;
+
+ item.alpha = 0.6;
+ // item.setGraphicSize(Std.int(item.width * 0.8));
+
+ if (item.targetY == 0)
+ {
+ item.alpha = 1;
+ // item.setGraphicSize(Std.int(item.width));
+ }
+ }
+ }
+}
diff --git a/source/ui/FlxVirtualPad.hx b/source/ui/FlxVirtualPad.hx
new file mode 100644
index 00000000000..f57e79e44ff
--- /dev/null
+++ b/source/ui/FlxVirtualPad.hx
@@ -0,0 +1,281 @@
+package ui;
+
+import flixel.FlxG;
+import flixel.graphics.frames.FlxTileFrames;
+import flixel.group.FlxSpriteGroup;
+import flixel.math.FlxPoint;
+import flixel.system.FlxAssets;
+import flixel.util.FlxDestroyUtil;
+import flixel.ui.FlxButton;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flash.display.BitmapData;
+import flixel.graphics.FlxGraphic;
+import openfl.utils.ByteArray;
+
+/**
+ * A gamepad which contains 4 directional buttons and 4 action buttons.
+ * It's easy to set the callbacks and to customize the layout.
+ *
+ * @author Ka Wing Chin
+ */
+@:keep @:bitmap("assets/preload/images/virtual-input.png")
+class GraphicVirtualInput extends BitmapData {}
+
+@:file("assets/preload/images/virtual-input.txt")
+class VirtualInputData extends #if (lime_legacy || nme) ByteArray #else ByteArrayData #end {}
+
+class FlxVirtualPad extends FlxSpriteGroup
+{
+ public var buttonA:FlxButton;
+ public var buttonB:FlxButton;
+ public var buttonC:FlxButton;
+ public var buttonY:FlxButton;
+ public var buttonX:FlxButton;
+ public var buttonLeft:FlxButton;
+ public var buttonUp:FlxButton;
+ public var buttonRight:FlxButton;
+ public var buttonDown:FlxButton;
+
+ public var button6:FlxButton;
+ public var button1:FlxButton;
+ public var button7:FlxButton;
+ public var buttonIn:FlxButton;
+ public var buttonOut:FlxButton;
+ public var buttonSave:FlxButton;
+ public var buttonL:FlxButton;
+ public var buttonR:FlxButton;
+ public var buttonR2:FlxButton;
+ public var buttonStage:FlxButton;
+
+ public var buttonUp2:FlxButton;
+ public var buttonDown2:FlxButton;
+
+
+ /**
+ * Group of directions buttons.
+ */
+ public var dPad:FlxSpriteGroup;
+
+ /**
+ * Group of action buttons.
+ */
+ public var actions:FlxSpriteGroup;
+
+ /**
+ * Create a gamepad which contains 4 directional buttons and 4 action buttons.
+ *
+ * @param DPadMode The D-Pad mode. `FULL` for example.
+ * @param ActionMode The action buttons mode. `A_B_C` for example.
+ */
+ public function new(?DPad:FlxDPadMode, ?Action:FlxActionMode)
+ {
+ super();
+ scrollFactor.set();
+
+ if (DPad == null)
+ DPad = FULL;
+ if (Action == null)
+ Action = A_B_C;
+
+ dPad = new FlxSpriteGroup();
+ dPad.scrollFactor.set();
+
+ actions = new FlxSpriteGroup();
+ actions.scrollFactor.set();
+
+ switch (DPad)
+ {
+ case UP_DOWN:
+ dPad.add(add(buttonUp = createButton(0, FlxG.height - 85 * 3, 44 * 3, 45 * 3, "up")));
+ dPad.add(add(buttonDown = createButton(0, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "down")));
+ case LEFT_RIGHT:
+ dPad.add(add(buttonLeft = createButton(0, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "left")));
+ dPad.add(add(buttonRight = createButton(42 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "right")));
+ case UP_LEFT_RIGHT:
+ dPad.add(add(buttonUp = createButton(35 * 3, FlxG.height - 81 * 3, 44 * 3, 45 * 3, "up")));
+ dPad.add(add(buttonLeft = createButton(0, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "left")));
+ dPad.add(add(buttonRight = createButton(69 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "right")));
+ case FULL:
+ dPad.add(add(buttonUp = createButton(35 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "up")));
+ dPad.add(add(buttonLeft = createButton(0, FlxG.height - 81 * 3, 44 * 3, 45 * 3, "left")));
+ dPad.add(add(buttonRight = createButton(69 * 3, FlxG.height - 81 * 3, 44 * 3, 45 * 3, "right")));
+ dPad.add(add(buttonDown = createButton(35 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "down")));
+ case RIGHT_FULL:
+ dPad.add(add(buttonUp = createButton(FlxG.width - 86 * 3, FlxG.height - 66 - 116 * 3, 44 * 3, 45 * 3, "up")));
+ dPad.add(add(buttonLeft = createButton(FlxG.width - 130 * 3, FlxG.height - 66 - 81 * 3, 44 * 3, 45 * 3, "left")));
+ dPad.add(add(buttonRight = createButton(FlxG.width - 44 * 3, FlxG.height - 66 - 81 * 3, 44 * 3, 45 * 3, "right")));
+ dPad.add(add(buttonDown = createButton(FlxG.width - 86 * 3, FlxG.height - 66 - 45 * 3, 44 * 3, 45 * 3, "down")));
+ case ANIMATION:
+ dPad.add(add(buttonUp2 = createButton(0, FlxG.height - 85 * 3, 44 * 3, 45 * 3, "up")));
+ dPad.add(add(buttonDown2 = createButton(0, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "down")));
+
+ dPad.add(add(buttonUp = createButton(75 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "up")));
+ dPad.add(add(buttonLeft = createButton(40 * 3, FlxG.height - 81 * 3, 44 * 3, 45 * 3, "left")));
+ dPad.add(add(buttonRight = createButton(109 * 3, FlxG.height - 81 * 3, 44 * 3, 45 * 3, "right")));
+ dPad.add(add(buttonDown = createButton(75 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "down")));
+ case NONE: // do nothing
+ }
+
+ switch (Action)
+ {
+ case A:
+ actions.add(add(buttonA = createButton(FlxG.width - 44 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "a")));
+ case A_B:
+ actions.add(add(buttonA = createButton(FlxG.width - 44 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "a")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "b")));
+ case STAGE:
+ actions.add(add(buttonA = createButton(FlxG.width - 44 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "a")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "b")));
+ actions.add(add(buttonC = createButton(FlxG.width - 128 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "c")));
+ actions.add(add(buttonIn = createButton(FlxG.width - 44 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "in")));
+ actions.add(add(buttonOut = createButton(FlxG.width - 86 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "out")));
+ actions.add(add(buttonSave = createButton(FlxG.width - 86 * 3, FlxG.height - 160 * 3, 44 * 3, 45 * 3, "save")));
+ actions.add(add(buttonL = createButton(0, FlxG.height - 160 * 3, 44 * 3, 45 * 3, "l")));
+ actions.add(add(buttonR = createButton(42 * 3, FlxG.height - 160 * 3, 44 * 3, 45 * 3, "r")));
+ actions.add(add(buttonR2 = createButton(84 * 3, FlxG.height - 160 * 3, 44 * 3, 45 * 3, "r2")));
+ case ANIMATION:
+ actions.add(add(buttonA = createButton(FlxG.width - 44 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "a")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "b")));
+ actions.add(add(buttonIn = createButton(FlxG.width - 44 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "in")));
+ actions.add(add(buttonOut = createButton(FlxG.width - 86 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "out")));
+ actions.add(add(buttonSave = createButton(FlxG.width - 86 * 3, FlxG.height - 160 * 3, 44 * 3, 45 * 3, "save")));
+ case SONGD:
+ actions.add(add(buttonStage = createButton(0, FlxG.height - 240 * 3, 44 * 3, 45 * 3, "stage")));
+ case A_B_6:
+ actions.add(add(buttonA = createButton(FlxG.width - 44 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "a")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "b")));
+ actions.add(add(button6 = createButton(FlxG.width - 44 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "6")));
+ case A_B_6_1:
+ actions.add(add(buttonA = createButton(FlxG.width - 44 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "a")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "b")));
+ actions.add(add(button6 = createButton(FlxG.width - 44 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "6")));
+ actions.add(add(button1 = createButton(FlxG.width - 86 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "1")));
+ case A_B_6_1_7:
+ actions.add(add(buttonA = createButton(FlxG.width - 44 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "a")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86 * 3, FlxG.height - 45 * 3, 44 * 3, 45 * 3, "b")));
+ actions.add(add(button6 = createButton(FlxG.width - 44 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "6")));
+ actions.add(add(button1 = createButton(FlxG.width - 44 * 3, FlxG.height - 160 * 3, 44 * 3, 45 * 3, "1")));
+ actions.add(add(button7 = createButton(FlxG.width - 86 * 3, FlxG.height - 116 * 3, 44 * 3, 45 * 3, "7")));
+ case A_B_C:
+ actions.add(add(buttonA = createButton(FlxG.width - 128, FlxG.height - 45, 44, 45, "a")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86, FlxG.height - 45, 44, 45, "b")));
+ actions.add(add(buttonC = createButton(FlxG.width - 44, FlxG.height - 45, 44, 45, "c")));
+ case A_B_X_Y:
+ actions.add(add(buttonY = createButton(FlxG.width - 86, FlxG.height - 85, 44, 45, "y")));
+ actions.add(add(buttonX = createButton(FlxG.width - 44, FlxG.height - 85, 44, 45, "x")));
+ actions.add(add(buttonB = createButton(FlxG.width - 86, FlxG.height - 45, 44, 45, "b")));
+ actions.add(add(buttonA = createButton(FlxG.width - 44, FlxG.height - 45, 44, 45, "a")));
+ case NONE: // do nothing
+ }
+ }
+
+ override public function destroy():Void
+ {
+ super.destroy();
+
+ dPad = FlxDestroyUtil.destroy(dPad);
+ actions = FlxDestroyUtil.destroy(actions);
+
+ dPad = null;
+ actions = null;
+ buttonA = null;
+ buttonB = null;
+ buttonC = null;
+ buttonY = null;
+ buttonX = null;
+ buttonLeft = null;
+ buttonUp = null;
+ buttonDown = null;
+ buttonRight = null;
+
+ button1 = null;
+ button6 = null;
+ button7 = null;
+ buttonIn = null;
+ buttonOut = null;
+ buttonSave = null;
+ buttonL = null;
+ buttonR = null;
+ buttonR2 = null;
+ buttonStage = null;
+ buttonUp2 = null;
+ buttonDown2 = null;
+ }
+
+ /**
+ * @param X The x-position of the button.
+ * @param Y The y-position of the button.
+ * @param Width The width of the button.
+ * @param Height The height of the button.
+ * @param Graphic The image of the button. It must contains 3 frames (`NORMAL`, `HIGHLIGHT`, `PRESSED`).
+ * @param Callback The callback for the button.
+ * @return The button
+ */
+ public function createButton(X:Float, Y:Float, Width:Int, Height:Int, Graphic:String, ?OnClick:Void->Void):FlxButton
+ {
+ var button = new FlxButton(X, Y);
+ var frame = getVirtualInputFrames().getByName(Graphic);
+ button.frames = FlxTileFrames.fromFrame(frame, FlxPoint.get(Width, Height));
+ button.resetSizeFromFrame();
+ button.solid = false;
+ button.immovable = true;
+ button.scrollFactor.set();
+
+ #if FLX_DEBUG
+ button.ignoreDrawDebug = true;
+ #end
+
+ if (OnClick != null)
+ button.onDown.callback = OnClick;
+
+ return button;
+ }
+
+ public static function getVirtualInputFrames():FlxAtlasFrames
+ {
+ #if !web
+ var bitmapData = new GraphicVirtualInput(0, 0);
+ #end
+
+ /*
+ #if html5 // dirty hack for openfl/openfl#682
+ Reflect.setProperty(bitmapData, "width", 399);
+ Reflect.setProperty(bitmapData, "height", 183);
+ #end
+ */
+
+ #if !web
+ var graphic:FlxGraphic = FlxGraphic.fromBitmapData(bitmapData);
+ return FlxAtlasFrames.fromSpriteSheetPacker(graphic, Std.string(new VirtualInputData()));
+ #else
+ var graphic:FlxGraphic = FlxGraphic.fromAssetKey(Paths.image('virtual-input'));
+ return FlxAtlasFrames.fromSpriteSheetPacker(graphic, Std.string(new VirtualInputData()));
+ #end
+ }
+}
+
+enum FlxDPadMode
+{
+ NONE;
+ UP_DOWN;
+ ANIMATION;
+ LEFT_RIGHT;
+ UP_LEFT_RIGHT;
+ RIGHT_FULL;
+ FULL;
+}
+
+enum FlxActionMode
+{
+ NONE;
+ A;
+ A_B;
+ ANIMATION;
+ SONGD;
+ STAGE;
+ A_B_6;
+ A_B_6_1;
+ A_B_6_1_7;
+ A_B_C;
+ A_B_X_Y;
+}
diff --git a/source/ui/Hitbox.hx b/source/ui/Hitbox.hx
new file mode 100644
index 00000000000..77b983b7469
--- /dev/null
+++ b/source/ui/Hitbox.hx
@@ -0,0 +1,98 @@
+package ui;
+
+import flixel.graphics.FlxGraphic;
+import flixel.addons.ui.FlxButtonPlus;
+import flixel.FlxSprite;
+import flixel.FlxG;
+import flixel.graphics.frames.FlxTileFrames;
+import flixel.group.FlxSpriteGroup;
+import flixel.math.FlxPoint;
+import flixel.system.FlxAssets;
+import flixel.util.FlxDestroyUtil;
+import flixel.ui.FlxButton;
+import flixel.graphics.frames.FlxAtlasFrames;
+import flixel.graphics.frames.FlxFrame;
+import flixel.ui.FlxVirtualPad;
+import flixel.tweens.FlxTween;
+import flixel.tweens.FlxEase;
+
+// copyed from flxvirtualpad
+class Hitbox extends FlxSpriteGroup
+{
+ public var hitbox:FlxSpriteGroup;
+
+ var sizex:Int = 320;
+
+ var screensizey:Int = 720;
+
+ public var buttonLeft:FlxButton;
+ public var buttonDown:FlxButton;
+ public var buttonUp:FlxButton;
+ public var buttonRight:FlxButton;
+
+ public function new(?widghtScreen:Int)
+ {
+ super();
+
+ /*if (widghtScreen == null)
+ widghtScreen = FlxG.width;*/
+
+ sizex = widghtScreen != null ? Std.int(widghtScreen / 4) : 320;
+
+
+ //add graphic
+ hitbox = new FlxSpriteGroup();
+ hitbox.scrollFactor.set();
+
+ var hitbox_hint:FlxSprite = new FlxSprite(0, 0).loadGraphic('assets/shared/images/hitbox/hitbox_hint.png');
+
+ hitbox_hint.alpha = 0.2;
+
+ add(hitbox_hint);
+
+
+ hitbox.add(add(buttonLeft = createhitbox(0, "left")));
+
+ hitbox.add(add(buttonDown = createhitbox(sizex, "down")));
+
+ hitbox.add(add(buttonUp = createhitbox(sizex * 2, "up")));
+
+ hitbox.add(add(buttonRight = createhitbox(sizex * 3, "right")));
+ }
+
+ public function createhitbox(X:Float, framestring:String) {
+ var button = new FlxButton(X, 0);
+ var frames = FlxAtlasFrames.fromSparrow('assets/shared/images/hitbox/hitbox.png', 'assets/shared/images/hitbox/hitbox.xml');
+
+ var graphic:FlxGraphic = FlxGraphic.fromFrame(frames.getByName(framestring));
+
+ button.loadGraphic(graphic);
+
+ button.alpha = 0;
+
+
+ button.onDown.callback = function (){
+ FlxTween.num(0, 0.75, .075, {ease: FlxEase.circInOut}, function (a:Float) { button.alpha = a; });
+ };
+
+ button.onUp.callback = function (){
+ FlxTween.num(0.75, 0, .1, {ease: FlxEase.circInOut}, function (a:Float) { button.alpha = a; });
+ }
+
+ button.onOut.callback = function (){
+ FlxTween.num(button.alpha, 0, .2, {ease: FlxEase.circInOut}, function (a:Float) { button.alpha = a; });
+ }
+
+ return button;
+ }
+
+ override public function destroy():Void
+ {
+ super.destroy();
+
+ buttonLeft = null;
+ buttonDown = null;
+ buttonUp = null;
+ buttonRight = null;
+ }
+}
\ No newline at end of file
diff --git a/source/ui/Mobilecontrols.hx b/source/ui/Mobilecontrols.hx
new file mode 100644
index 00000000000..7ee82621040
--- /dev/null
+++ b/source/ui/Mobilecontrols.hx
@@ -0,0 +1,84 @@
+package ui;
+
+import flixel.FlxG;
+import flixel.group.FlxSpriteGroup;
+
+import ui.FlxVirtualPad;
+import ui.Hitbox;
+
+import Config;
+
+class Mobilecontrols extends FlxSpriteGroup
+{
+ public var mode:ControlsGroup = HITBOX;
+
+ public var _hitbox:Hitbox;
+ public var _virtualPad:FlxVirtualPad;
+
+ var config:Config;
+
+ public function new()
+ {
+ super();
+
+ config = new Config();
+
+ // load control mode num from Config.hx
+ mode = getModeFromNumber(config.getcontrolmode());
+ trace(config.getcontrolmode());
+
+ switch (mode)
+ {
+ case VIRTUALPAD_RIGHT:
+ initVirtualPad(0);
+ case VIRTUALPAD_LEFT:
+ initVirtualPad(1);
+ case VIRTUALPAD_CUSTOM:
+ initVirtualPad(2);
+ case HITBOX:
+ _hitbox = new Hitbox();
+ add(_hitbox);
+ case KEYBOARD:
+ }
+ }
+
+ function initVirtualPad(vpadMode:Int)
+ {
+ switch (vpadMode)
+ {
+ case 1:
+ _virtualPad = new FlxVirtualPad(FULL, NONE);
+ case 2:
+ _virtualPad = new FlxVirtualPad(FULL, NONE);
+ _virtualPad = config.loadcustom(_virtualPad);
+ default: // 0
+ _virtualPad = new FlxVirtualPad(RIGHT_FULL, NONE);
+ }
+
+ _virtualPad.alpha = 0.75;
+ add(_virtualPad);
+ }
+
+
+ public static function getModeFromNumber(modeNum:Int):ControlsGroup {
+ return switch (modeNum)
+ {
+ case 0: VIRTUALPAD_RIGHT;
+ case 1: VIRTUALPAD_LEFT;
+ case 2: KEYBOARD;
+ case 3: VIRTUALPAD_CUSTOM;
+ case 4: HITBOX;
+
+ default: VIRTUALPAD_RIGHT;
+
+ }
+ }
+}
+
+enum ControlsGroup {
+ VIRTUALPAD_RIGHT;
+ VIRTUALPAD_LEFT;
+ KEYBOARD;
+ VIRTUALPAD_CUSTOM;
+ HITBOX;
+}
\ No newline at end of file
diff --git a/source/vscode-project.hxml b/source/vscode-project.hxml
new file mode 100644
index 00000000000..1524649b69d
--- /dev/null
+++ b/source/vscode-project.hxml
@@ -0,0 +1,3 @@
+#automatically generated do not edit
+#@date Tue Dec 14 2021 18:35:32 GMT-0300 (Horário Padrão de Brasília)
+-cp c:\temp\b03daa7c25a5885336d573e7becc42cc56c88e43
\ No newline at end of file