Merge remote-tracking branch 'upstream/main' into better-templates

This commit is contained in:
tposejank 2024-07-10 20:37:31 -04:00
commit a27e743c5f
10 changed files with 343 additions and 176 deletions

51
.github/ISSUE_TEMPLATE/bug.md vendored Normal file
View file

@ -0,0 +1,51 @@
---
name: Bug Report
about: Report a bug or critical performance issue
title: 'Bug Report: [DESCRIBE YOUR BUG IN DETAIL HERE]'
labels: 'status: pending triage'
---
<!-- FILL THIS ISSUE THING OUT AS MUCH AS POSSIBLE
OR ELSE YOUR ISSUE WILL BE LESS LIKELY TO BE SOLVED!
Do not post about issues from other FNF mod engines!
We cannot and probably won't solve those!
You can hopefully go to their respective GitHub issues pages and report them there, thank you :)
Please check for duplicates or similar issues, as well as performing simple troubleshooting steps (such as clearing cookies, clearing AppData, trying another browser) before submitting an issue.
From Joel On Software:
"Its pretty easy to remember the rule for a good bug report. Every good bug report needs exactly three things.
1. Steps to reproduce,
2. What you expected to see, and
3. What you saw instead."
-->
## Describe the Bug
<!-- A clear and concise description of what the bug is. -->
## To Reproduce
<!-- Describe IN DETAIL how to reproduce the bug/issue you are running into. -->
## Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
## Screenshots/Video
<!-- If applicable, add screenshots/video to help explain your problem.
Remember to mark the area in the application that's impacted. -->
## Desktop
- OS:
<!-- [e.g. Windows 10, 11, Mac, Linux Mint, Ubuntu, Arch (btw)] -->
- Browser:
<!-- [e.g. Chrome, Safari, Firefox, Edge, OperaGX, or None if you're playing the downloaded version!] -->
- Version:
<!-- [e.g. 0.4.0, 0.3.3, this can be found in the bottom left corner of the main menu!] -->
## Additional Context
<!-- Add any other context about the problem here. -->
<!-- If your game is FROZEN and you're playing a web version, press F12 to open up the browser dev window, go to the "Console" tab, and copy-paste whatever red error you're getting below -->

8
.github/ISSUE_TEMPLATE/enhancement.md vendored Normal file
View file

@ -0,0 +1,8 @@
---
name: Enhancement
about: Suggest a new feature
title: 'Enhancement: '
labels: 'status: pending triage'
---
#### Please check for duplicates or similar issues before submitting this suggestion.
## What is your suggestion, and why should it be implemented?

10
.github/PULL_REQUEST_TEMPLATE/bug.md vendored Normal file
View file

@ -0,0 +1,10 @@
---
name: Bug Fix
about: Fix a bug or critical performance issue
title: 'Bug Fix: '
labels: 'status: pending triage'
---
#### Please check for duplicates or similar PRs before submitting this PR.
## Does this PR close any issues? If so, link them below.
## Briefly describe the issue(s) fixed.

View file

@ -0,0 +1,10 @@
---
name: Enhancement
about: Add a new feature
title: 'Enhancement: '
labels: 'status: pending triage'
---
#### Please check for duplicates or similar PRs before submitting this PR.
## Does this PR close any issues? If so, link them below.
## What do your changes add, and why should they be implemented?

12
.github/changed-lines-count-labeler.yml vendored Normal file
View file

@ -0,0 +1,12 @@
# Add 'small' to any changes below 10 lines
small:
max: 9
# Add 'medium' to any changes between 10 and 100 lines
medium:
min: 10
max: 99
# Add 'large' to any changes for more than 100 lines
large:
min: 100

View file

@ -9,6 +9,19 @@ jobs:
pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/labeler@v5
- name: Set basic labels
uses: actions/labeler@v5
with:
sync-labels: true
changed-lines-count-labeler:
permissions:
contents: read
pull-requests: write
runs-on: ubuntu-latest
name: An action for automatically labelling pull requests based on the changed lines count
steps:
- name: Set change count labels
uses: vkirilichev/changed-lines-count-labeler@v0.2
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
configuration-path: .github/changed-lines-count-labeler.yml

View file

@ -81,19 +81,9 @@ which would remove their rank if they had a lower one.
- Fixed a crash on Linux caused by an old version of hxCodec (thanks Noobz4Life!)
- Optimized animation handling for characters (thanks richTrash21!)
- Made improvements to compiling documentation (thanks gedehari!)
- Fixed a bug where pressing the volume keys would stop the Toy commercial (thanks gamerbross!)
- Fixed a bug where the Chart Editor Playtest would crash when losing (thanks gamerbross!)
- Removed a large number of unused imports to optimize builds (thanks Ethan-makes-music!)
- Fixed a bug where hold notes would be positioned wrong on downscroll (thanks MaybeMaru!)
- Additional fixes to the Loading bar on HTML5 (thanks lemz1!)
- Fixed a crash in Freeplay caused by a level referencing an invalid song (thanks gamerbross!)
- Improved debug logging for unscripted stages (thanks gamerbross!)
- Fixed a bug where changing difficulties in Story mode wouldn't update the score (thanks sectorA!)
- Fixed an issue where the Chart Editor would use an incorrect instrumental on imported Legacy songs (thanks gamerbross!)
- Fixed a camera bug in the Main Menu (thanks richTrash21!)
- Fixed several bugs with the TitleState, including missing music when returning from the Main Menu (thanks gamerbross!)
- Fixed a bug where opening the game from the command line would crash the preloader (thanks NotHyper474!)
- Fixed a bug where hold notes would display improperly in the Chart Editor when downscroll was enabled for gameplay (thanks gamerbross!)
- Fixed a bug where characters would sometimes use the wrong scale value (thanks PurSnake!)
- Additional bug fixes and optimizations.

View file

@ -2,14 +2,19 @@
0. Setup
- Download Haxe from [Haxe.org](https://haxe.org)
1. Cloning the Repository: Make sure when you clone, you clone the submodules to get the assets repo:
- `git clone --recurse-submodules https://github.com/FunkinCrew/funkin.git`
- If you accidentally cloned without the `assets` submodule (aka didn't follow the step above), you can run `git submodule update --init --recursive` to get the assets in a foolproof way.
2. Install `hmm` (run `haxelib --global install hmm` and then `haxelib --global run hmm setup`)
3. Download Git from [git-scm.com](https://www.git-scm.com)
4. Install all haxelibs of the current branch by running `hmm install`
5. Setup lime: `haxelib run lime setup`
6. Platform setup
- Download Git from [git-scm.com](https://www.git-scm.com)
- Do NOT download the repository using the Download ZIP button on GitHub or you may run into errors!
- Instead, open a command prompt and do the following steps...
1. Run `cd the\directory\you\want\the\source\code\in` to specify which folder the command prompt is working in.
- For example, `cd C:\Users\YOURNAME\Documents` would instruct the command prompt to perform the next steps in your Documents folder.
2. Run `git clone https://github.com/FunkinCrew/funkin.git` to clone the base repository.
3. Run `cd funkin` to enter the cloned repository's directory.
4. Run `git submodule update --init --recursive` to download the game's assets.
- NOTE: By performing this operation, you are downloading Content which is proprietary and protected by national and international copyright and trademark laws. See [the LICENSE.md file for the Funkin.assets](https://github.com/FunkinCrew/funkin.assets/blob/main/LICENSE.md) repo for more information.
5. Run `haxelib --global install hmm` and then `haxelib --global run hmm setup` to install hmm.json
6. Run `hmm install` to install all haxelibs of the current branch
7. Run `haxelib run lime setup` to set up lime
8. Platform setup
- For Windows, download the [Visual Studio Build Tools](https://aka.ms/vs/17/release/vs_BuildTools.exe)
- When prompted, select "Individual Components" and make sure to download the following:
- MSVC v143 VS 2022 C++ x64/x86 build tools
@ -17,10 +22,12 @@
- Mac: [`lime setup mac` Documentation](https://lime.openfl.org/docs/advanced-setup/macos/)
- Linux: [`lime setup linux` Documentation](https://lime.openfl.org/docs/advanced-setup/linux/)
- HTML5: Compiles without any extra setup
7. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug`
8. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State).
9. If you are targeting for native, you may need to run `lime rebuild PLATFORM` and `lime rebuild PLATFORM -debug`
10. `lime test PLATFORM` ! Add `-debug` to enable several debug features such as time travel (`PgUp`/`PgDn` in Play State).
# Troubleshooting
# Troubleshooting - GO THROUGH THESE STEPS BEFORE OPENING ISSUES ON GITHUB!
- During the cloning process, you may experience an error along the lines of `error: RPC failed; curl 92 HTTP/2 stream 0 was not closed cleanly: PROTOCOL_ERROR (err 1)` due to poor connectivity. A common fix is to run ` git config --global http.postBuffer 4096M`.
- Make sure your game directory has an `assets` folder! If it's missing, copy the path to your `funkin` folder and run `cd the\path\you\copied`. Then follow the guide starting from **Step 4**.
- Check that your `assets` folder is not empty! If it is, go back to **Step 4** and follow the guide from there.
- The compilation process often fails due to having the wrong versions of the required libraries. Many errors can be resolved by deleting the `.haxelib` folder and following the guide starting from **Step 5**.

View file

@ -31,6 +31,7 @@ class Controls extends FlxActionSet
* Uses FlxActions to funnel various inputs to a single action.
*/
var _ui_up = new FunkinAction(Action.UI_UP);
var _ui_left = new FunkinAction(Action.UI_LEFT);
var _ui_right = new FunkinAction(Action.UI_RIGHT);
var _ui_down = new FunkinAction(Action.UI_DOWN);
@ -325,19 +326,18 @@ class Controls extends FlxActionSet
add(_volume_down);
add(_volume_mute);
for (action in digitalActions) {
if (Std.isOfType(action, FunkinAction)) {
for (action in digitalActions)
{
if (Std.isOfType(action, FunkinAction))
{
var funkinAction:FunkinAction = cast action;
byName[funkinAction.name] = funkinAction;
if (funkinAction.namePressed != null)
byName[funkinAction.namePressed] = funkinAction;
if (funkinAction.nameReleased != null)
byName[funkinAction.nameReleased] = funkinAction;
if (funkinAction.namePressed != null) byName[funkinAction.namePressed] = funkinAction;
if (funkinAction.nameReleased != null) byName[funkinAction.nameReleased] = funkinAction;
}
}
if (scheme == null)
scheme = None;
if (scheme == null) scheme = None;
setKeyboardScheme(scheme, false);
}
@ -350,38 +350,38 @@ class Controls extends FlxActionSet
public function check(name:Action, trigger:FlxInputState = JUST_PRESSED, gamepadOnly:Bool = false):Bool
{
#if debug
if (!byName.exists(name))
throw 'Invalid name: $name';
if (!byName.exists(name)) throw 'Invalid name: $name';
#end
var action = byName[name];
if (gamepadOnly)
return action.checkFiltered(trigger, GAMEPAD);
if (gamepadOnly) return action.checkFiltered(trigger, GAMEPAD);
else
return action.checkFiltered(trigger);
}
public function getKeysForAction(name:Action):Array<FlxKey> {
public function getKeysForAction(name:Action):Array<FlxKey>
{
#if debug
if (!byName.exists(name))
throw 'Invalid name: $name';
if (!byName.exists(name)) throw 'Invalid name: $name';
#end
// TODO: Revert to `.map().filter()` once HashLink doesn't complain anymore.
var result:Array<FlxKey> = [];
for (input in byName[name].inputs) {
for (input in byName[name].inputs)
{
if (input.device == KEYBOARD) result.push(input.inputID);
}
return result;
}
public function getButtonsForAction(name:Action):Array<FlxGamepadInputID> {
public function getButtonsForAction(name:Action):Array<FlxGamepadInputID>
{
#if debug
if (!byName.exists(name))
throw 'Invalid name: $name';
if (!byName.exists(name)) throw 'Invalid name: $name';
#end
var result:Array<FlxGamepadInputID> = [];
for (input in byName[name].inputs) {
for (input in byName[name].inputs)
{
if (input.device == GAMEPAD) result.push(input.inputID);
}
return result;
@ -405,7 +405,7 @@ class Controls extends FlxActionSet
function getActionFromControl(control:Control):FlxActionDigital
{
return switch(control)
return switch (control)
{
case UI_UP: _ui_up;
case UI_DOWN: _ui_down;
@ -448,7 +448,7 @@ class Controls extends FlxActionSet
*/
function forEachBound(control:Control, func:FlxActionDigital->FlxInputState->Void)
{
switch(control)
switch (control)
{
case UI_UP:
func(_ui_up, PRESSED);
@ -519,10 +519,9 @@ class Controls extends FlxActionSet
public function replaceBinding(control:Control, device:Device, toAdd:Int, toRemove:Int)
{
if (toAdd == toRemove)
return;
if (toAdd == toRemove) return;
switch(device)
switch (device)
{
case Keys:
forEachBound(control, function(action, state) replaceKey(action, toAdd, toRemove, state));
@ -534,7 +533,8 @@ class Controls extends FlxActionSet
function replaceKey(action:FlxActionDigital, toAdd:FlxKey, toRemove:FlxKey, state:FlxInputState)
{
if (action.inputs.length == 0) {
if (action.inputs.length == 0)
{
// Add the keybind, don't replace.
addKeys(action, [toAdd], state);
return;
@ -548,34 +548,44 @@ class Controls extends FlxActionSet
if (input.device == KEYBOARD && input.inputID == toRemove)
{
if (toAdd == FlxKey.NONE) {
if (toAdd == FlxKey.NONE)
{
// Remove the keybind, don't replace.
action.inputs.remove(input);
} else {
}
else
{
// Replace the keybind.
@:privateAccess
action.inputs[i].inputID = toAdd;
}
hasReplaced = true;
} else if (input.device == KEYBOARD && input.inputID == toAdd) {
}
else if (input.device == KEYBOARD && input.inputID == toAdd)
{
// This key is already bound!
if (hasReplaced) {
if (hasReplaced)
{
// Remove the duplicate keybind, don't replace.
action.inputs.remove(input);
} else {
}
else
{
hasReplaced = true;
}
}
}
if (!hasReplaced) {
if (!hasReplaced)
{
addKeys(action, [toAdd], state);
}
}
function replaceButton(action:FlxActionDigital, deviceID:Int, toAdd:FlxGamepadInputID, toRemove:FlxGamepadInputID, state:FlxInputState)
{
if (action.inputs.length == 0) {
if (action.inputs.length == 0)
{
addButtons(action, [toAdd], state, deviceID);
return;
}
@ -594,7 +604,8 @@ class Controls extends FlxActionSet
}
}
if (!hasReplaced) {
if (!hasReplaced)
{
addButtons(action, [toAdd], state, deviceID);
}
}
@ -606,18 +617,16 @@ class Controls extends FlxActionSet
var action = controls.byName[name];
for (input in action.inputs)
{
if (device == null || isDevice(input, device))
byName[name].add(cast input);
if (device == null || isDevice(input, device)) byName[name].add(cast input);
}
}
switch(device)
switch (device)
{
case null:
// add all
for (gamepad in controls.gamepadsAdded)
if (gamepadsAdded.indexOf(gamepad) == -1)
gamepadsAdded.push(gamepad);
if (gamepadsAdded.indexOf(gamepad) == -1) gamepadsAdded.push(gamepad);
mergeKeyboardScheme(controls.keyboardScheme);
@ -637,7 +646,7 @@ class Controls extends FlxActionSet
{
if (scheme != None)
{
switch(keyboardScheme)
switch (keyboardScheme)
{
case None:
keyboardScheme = scheme;
@ -672,7 +681,8 @@ class Controls extends FlxActionSet
static function addKeys(action:FlxActionDigital, keys:Array<FlxKey>, state:FlxInputState)
{
for (key in keys) {
for (key in keys)
{
if (key == FlxKey.NONE) continue; // Ignore unbound keys.
action.addKey(key, state);
}
@ -684,15 +694,13 @@ class Controls extends FlxActionSet
while (i-- > 0)
{
var input = action.inputs[i];
if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1)
action.remove(input);
if (input.device == KEYBOARD && keys.indexOf(cast input.inputID) != -1) action.remove(input);
}
}
public function setKeyboardScheme(scheme:KeyboardScheme, reset = true)
{
if (reset)
removeKeyboard();
if (reset) removeKeyboard();
keyboardScheme = scheme;
@ -724,10 +732,13 @@ class Controls extends FlxActionSet
bindMobileLol();
}
function getDefaultKeybinds(scheme:KeyboardScheme, control:Control):Array<FlxKey> {
switch (scheme) {
function getDefaultKeybinds(scheme:KeyboardScheme, control:Control):Array<FlxKey>
{
switch (scheme)
{
case Solo:
switch (control) {
switch (control)
{
case Control.UI_UP: return [W, FlxKey.UP];
case Control.UI_DOWN: return [S, FlxKey.DOWN];
case Control.UI_LEFT: return [A, FlxKey.LEFT];
@ -754,7 +765,8 @@ class Controls extends FlxActionSet
case Control.VOLUME_MUTE: return [ZERO, NUMPADZERO];
}
case Duo(true):
switch (control) {
switch (control)
{
case Control.UI_UP: return [W];
case Control.UI_DOWN: return [S];
case Control.UI_LEFT: return [A];
@ -779,10 +791,10 @@ class Controls extends FlxActionSet
case Control.VOLUME_UP: return [PLUS];
case Control.VOLUME_DOWN: return [MINUS];
case Control.VOLUME_MUTE: return [ZERO];
}
case Duo(false):
switch (control) {
switch (control)
{
case Control.UI_UP: return [FlxKey.UP];
case Control.UI_DOWN: return [FlxKey.DOWN];
case Control.UI_LEFT: return [FlxKey.LEFT];
@ -807,7 +819,6 @@ class Controls extends FlxActionSet
case Control.VOLUME_UP: return [NUMPADPLUS];
case Control.VOLUME_DOWN: return [NUMPADMINUS];
case Control.VOLUME_MUTE: return [NUMPADZERO];
}
default:
// Fallthrough.
@ -834,8 +845,7 @@ class Controls extends FlxActionSet
#end
#if android
forEachBound(Control.BACK, function(action, pres)
{
forEachBound(Control.BACK, function(action, pres) {
action.add(new FlxActionInputDigitalAndroid(FlxAndroidKey.BACK, JUST_PRESSED));
});
#end
@ -849,8 +859,7 @@ class Controls extends FlxActionSet
while (i-- > 0)
{
var input = action.inputs[i];
if (input.device == KEYBOARD)
action.remove(input);
if (input.device == KEYBOARD) action.remove(input);
}
}
}
@ -862,11 +871,13 @@ class Controls extends FlxActionSet
fromSaveData(padData, Gamepad(id));
}
public function getGamepadIds():Array<Int> {
public function getGamepadIds():Array<Int>
{
return gamepadsAdded;
}
public function getGamepads():Array<FlxGamepad> {
public function getGamepads():Array<FlxGamepad>
{
return [for (id in gamepadsAdded) FlxG.gamepads.getByID(id)];
}
@ -886,8 +897,7 @@ class Controls extends FlxActionSet
while (i-- > 0)
{
var input = action.inputs[i];
if (isGamepad(input, deviceID))
action.remove(input);
if (isGamepad(input, deviceID)) action.remove(input);
}
}
@ -924,32 +934,58 @@ class Controls extends FlxActionSet
]);
}
function getDefaultGamepadBinds(control:Control):Array<FlxGamepadInputID> {
switch(control) {
case Control.ACCEPT: return [#if switch B #else A #end];
case Control.BACK: return [#if switch A #else B #end];
case Control.UI_UP: return [DPAD_UP, LEFT_STICK_DIGITAL_UP];
case Control.UI_DOWN: return [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN];
case Control.UI_LEFT: return [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT];
case Control.UI_RIGHT: return [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT];
case Control.NOTE_UP: return [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP];
case Control.NOTE_DOWN: return [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN];
case Control.NOTE_LEFT: return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT];
case Control.NOTE_RIGHT: return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT];
case Control.PAUSE: return [START];
case Control.RESET: return [FlxGamepadInputID.BACK]; // Back (i.e. Select)
case Control.WINDOW_FULLSCREEN: [];
case Control.WINDOW_SCREENSHOT: [];
case Control.CUTSCENE_ADVANCE: return [A];
case Control.FREEPLAY_FAVORITE: [FlxGamepadInputID.BACK]; // Back (i.e. Select)
case Control.FREEPLAY_LEFT: [LEFT_SHOULDER];
case Control.FREEPLAY_RIGHT: [RIGHT_SHOULDER];
case Control.VOLUME_UP: [];
case Control.VOLUME_DOWN: [];
case Control.VOLUME_MUTE: [];
case Control.DEBUG_MENU: [];
case Control.DEBUG_CHART: [];
case Control.DEBUG_STAGE: [];
function getDefaultGamepadBinds(control:Control):Array<FlxGamepadInputID>
{
switch (control)
{
case Control.ACCEPT:
return [#if switch B #else A #end];
case Control.BACK:
return [#if switch A #else B #end];
case Control.UI_UP:
return [DPAD_UP, LEFT_STICK_DIGITAL_UP];
case Control.UI_DOWN:
return [DPAD_DOWN, LEFT_STICK_DIGITAL_DOWN];
case Control.UI_LEFT:
return [DPAD_LEFT, LEFT_STICK_DIGITAL_LEFT];
case Control.UI_RIGHT:
return [DPAD_RIGHT, LEFT_STICK_DIGITAL_RIGHT];
case Control.NOTE_UP:
return [DPAD_UP, Y, LEFT_STICK_DIGITAL_UP, RIGHT_STICK_DIGITAL_UP];
case Control.NOTE_DOWN:
return [DPAD_DOWN, A, LEFT_STICK_DIGITAL_DOWN, RIGHT_STICK_DIGITAL_DOWN];
case Control.NOTE_LEFT:
return [DPAD_LEFT, X, LEFT_STICK_DIGITAL_LEFT, RIGHT_STICK_DIGITAL_LEFT];
case Control.NOTE_RIGHT:
return [DPAD_RIGHT, B, LEFT_STICK_DIGITAL_RIGHT, RIGHT_STICK_DIGITAL_RIGHT];
case Control.PAUSE:
return [START];
case Control.RESET:
return [FlxGamepadInputID.BACK]; // Back (i.e. Select)
case Control.WINDOW_FULLSCREEN:
[];
case Control.WINDOW_SCREENSHOT:
[];
case Control.CUTSCENE_ADVANCE:
return [A];
case Control.FREEPLAY_FAVORITE:
[FlxGamepadInputID.BACK]; // Back (i.e. Select)
case Control.FREEPLAY_LEFT:
[LEFT_SHOULDER];
case Control.FREEPLAY_RIGHT:
[RIGHT_SHOULDER];
case Control.VOLUME_UP:
[];
case Control.VOLUME_DOWN:
[];
case Control.VOLUME_MUTE:
[];
case Control.DEBUG_MENU:
[];
case Control.DEBUG_CHART:
[];
case Control.DEBUG_STAGE:
[];
default:
// Fallthrough.
}
@ -967,8 +1003,7 @@ class Controls extends FlxActionSet
public function touchShit(control:Control, id)
{
forEachBound(control, function(action, state)
{
forEachBound(control, function(action, state) {
// action
});
}
@ -984,7 +1019,8 @@ class Controls extends FlxActionSet
inline static function addButtons(action:FlxActionDigital, buttons:Array<FlxGamepadInputID>, state, id)
{
for (button in buttons) {
for (button in buttons)
{
if (button == FlxGamepadInputID.NONE) continue; // Ignore unbound keys.
action.addGamepad(button, state, id);
}
@ -996,29 +1032,25 @@ class Controls extends FlxActionSet
while (i-- > 0)
{
var input = action.inputs[i];
if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1)
action.remove(input);
if (isGamepad(input, gamepadID) && buttons.indexOf(cast input.inputID) != -1) action.remove(input);
}
}
public function getInputsFor(control:Control, device:Device, ?list:Array<Int>):Array<Int>
{
if (list == null)
list = [];
if (list == null) list = [];
switch(device)
switch (device)
{
case Keys:
for (input in getActionFromControl(control).inputs)
{
if (input.device == KEYBOARD)
list.push(input.inputID);
if (input.device == KEYBOARD) list.push(input.inputID);
}
case Gamepad(id):
for (input in getActionFromControl(control).inputs)
{
if (isGamepad(input, id))
list.push(input.inputID);
if (isGamepad(input, id)) list.push(input.inputID);
}
}
return list;
@ -1026,7 +1058,7 @@ class Controls extends FlxActionSet
public function removeDevice(device:Device)
{
switch(device)
switch (device)
{
case Keys:
setKeyboardScheme(None);
@ -1040,27 +1072,32 @@ class Controls extends FlxActionSet
* An EMPTY array means the control is uninitialized and needs to be reset to default.
* An array with a single FlxKey.NONE means the control was intentionally unbound by the user.
*/
public function fromSaveData(data:Dynamic, device:Device)
public function fromSaveData(data:Dynamic, device:Device):Void
{
for (control in Control.createAll())
{
var inputs:Array<Int> = Reflect.field(data, control.getName());
inputs = inputs.distinct();
inputs = inputs?.distinct();
if (inputs != null)
{
if (inputs.length == 0) {
if (inputs.length == 0)
{
trace('Control ${control} is missing bindings, resetting to default.');
switch(device)
switch (device)
{
case Keys:
bindKeys(control, getDefaultKeybinds(Solo, control));
case Gamepad(id):
bindButtons(control, id, getDefaultGamepadBinds(control));
}
} else if (inputs == [FlxKey.NONE]) {
}
else if (inputs == [FlxKey.NONE])
{
trace('Control ${control} is unbound, leaving it be.');
} else {
switch(device)
}
else
{
switch (device)
{
case Keys:
bindKeys(control, inputs.copy());
@ -1068,9 +1105,11 @@ class Controls extends FlxActionSet
bindButtons(control, id, inputs.copy());
}
}
} else {
}
else
{
trace('Control ${control} is missing bindings, resetting to default.');
switch(device)
switch (device)
{
case Keys:
bindKeys(control, getDefaultKeybinds(Solo, control));
@ -1095,9 +1134,12 @@ class Controls extends FlxActionSet
var inputs = getInputsFor(control, device);
isEmpty = isEmpty && inputs.length == 0;
if (inputs.length == 0) {
if (inputs.length == 0)
{
inputs = [FlxKey.NONE];
} else {
}
else
{
inputs = inputs.distinct();
}
@ -1109,7 +1151,7 @@ class Controls extends FlxActionSet
static function isDevice(input:FlxActionInput, device:Device)
{
return switch(device)
return switch (device)
{
case Keys: input.device == KEYBOARD;
case Gamepad(id): isGamepad(input, id);
@ -1141,7 +1183,8 @@ typedef Swipes =
* - Combining `pressed` and `released` inputs into one action.
* - Filtering by input method (`KEYBOARD`, `MOUSE`, `GAMEPAD`, etc).
*/
class FunkinAction extends FlxActionDigital {
class FunkinAction extends FlxActionDigital
{
public var namePressed(default, null):Null<String>;
public var nameReleased(default, null):Null<String>;
@ -1158,83 +1201,102 @@ class FunkinAction extends FlxActionDigital {
/**
* Input checks default to whether the input was just pressed, on any input device.
*/
public override function check():Bool {
public override function check():Bool
{
return checkFiltered(JUST_PRESSED);
}
/**
* Check whether the input is currently being held.
*/
public function checkPressed():Bool {
public function checkPressed():Bool
{
return checkFiltered(PRESSED);
}
/**
* Check whether the input is currently being held, and was not held last frame.
*/
public function checkJustPressed():Bool {
public function checkJustPressed():Bool
{
return checkFiltered(JUST_PRESSED);
}
/**
* Check whether the input is not currently being held.
*/
public function checkReleased():Bool {
public function checkReleased():Bool
{
return checkFiltered(RELEASED);
}
/**
* Check whether the input is not currently being held, and was held last frame.
*/
public function checkJustReleased():Bool {
public function checkJustReleased():Bool
{
return checkFiltered(JUST_RELEASED);
}
/**
* Check whether the input is currently being held by a gamepad device.
*/
public function checkPressedGamepad():Bool {
public function checkPressedGamepad():Bool
{
return checkFiltered(PRESSED, GAMEPAD);
}
/**
* Check whether the input is currently being held by a gamepad device, and was not held last frame.
*/
public function checkJustPressedGamepad():Bool {
public function checkJustPressedGamepad():Bool
{
return checkFiltered(JUST_PRESSED, GAMEPAD);
}
/**
* Check whether the input is not currently being held by a gamepad device.
*/
public function checkReleasedGamepad():Bool {
public function checkReleasedGamepad():Bool
{
return checkFiltered(RELEASED, GAMEPAD);
}
/**
* Check whether the input is not currently being held by a gamepad device, and was held last frame.
*/
public function checkJustReleasedGamepad():Bool {
public function checkJustReleasedGamepad():Bool
{
return checkFiltered(JUST_RELEASED, GAMEPAD);
}
public function checkMultiFiltered(?filterTriggers:Array<FlxInputState>, ?filterDevices:Array<FlxInputDevice>):Bool {
if (filterTriggers == null) {
public function checkMultiFiltered(?filterTriggers:Array<FlxInputState>, ?filterDevices:Array<FlxInputDevice>):Bool
{
if (filterTriggers == null)
{
filterTriggers = [PRESSED, JUST_PRESSED];
}
if (filterDevices == null) {
if (filterDevices == null)
{
filterDevices = [];
}
// Perform checkFiltered for each combination.
for (i in filterTriggers) {
if (filterDevices.length == 0) {
if (checkFiltered(i)) {
for (i in filterTriggers)
{
if (filterDevices.length == 0)
{
if (checkFiltered(i))
{
return true;
}
} else {
for (j in filterDevices) {
if (checkFiltered(i, j)) {
}
else
{
for (j in filterDevices)
{
if (checkFiltered(i, j))
{
return true;
}
}
@ -1249,52 +1311,56 @@ class FunkinAction extends FlxActionDigital {
* @param filterTrigger Optionally filter by trigger condition (`JUST_PRESSED`, `PRESSED`, `JUST_RELEASED`, `RELEASED`).
* @param filterDevice Optionally filter by device (`KEYBOARD`, `MOUSE`, `GAMEPAD`, `OTHER`).
*/
public function checkFiltered(?filterTrigger:FlxInputState, ?filterDevice:FlxInputDevice):Bool {
public function checkFiltered(?filterTrigger:FlxInputState, ?filterDevice:FlxInputDevice):Bool
{
// The normal
// Make sure we only update the inputs once per frame.
var key = '${filterTrigger}:${filterDevice}';
var cacheEntry = cache.get(key);
if (cacheEntry != null && cacheEntry.timestamp == FlxG.game.ticks) {
if (cacheEntry != null && cacheEntry.timestamp == FlxG.game.ticks)
{
return cacheEntry.value;
}
// Use a for loop instead so we can remove inputs while iterating.
// We don't return early because we need to call check() on ALL inputs.
var result = false;
var len = inputs != null ? inputs.length : 0;
for (i in 0...len)
{
var j = len - i - 1;
var input = inputs[j];
var len = inputs != null ? inputs.length : 0;
for (i in 0...len)
{
var j = len - i - 1;
var input = inputs[j];
// Filter out dead inputs.
if (input.destroyed)
{
inputs.splice(j, 1);
continue;
}
if (input.destroyed)
{
inputs.splice(j, 1);
continue;
}
// Update the input.
input.update();
// Check whether the input is the right trigger.
if (filterTrigger != null && input.trigger != filterTrigger) {
if (filterTrigger != null && input.trigger != filterTrigger)
{
continue;
}
// Check whether the input is the right device.
if (filterDevice != null && input.device != filterDevice) {
if (filterDevice != null && input.device != filterDevice)
{
continue;
}
// Check whether the input has triggered.
if (input.check(this))
{
result = true;
}
}
if (input.check(this))
{
result = true;
}
}
// We need to cache this result.
cache.set(key, {timestamp: FlxG.game.ticks, value: result});
@ -1391,12 +1457,12 @@ class FlxActionInputDigitalMobileSwipeGameplay extends FlxActionInputDigital
{
var degAngle = FlxAngle.asDegrees(swp.touchAngle);
switch(trigger)
switch (trigger)
{
case JUST_PRESSED:
if (swp.touchLength >= activateLength)
{
switch(inputID)
switch (inputID)
{
case FlxDirectionFlags.UP:
if (degAngle >= 45 && degAngle <= 90 + 45) return properTouch(swp);
@ -1440,7 +1506,7 @@ class FlxActionInputDigitalAndroid extends FlxActionInputDigital
override public function check(Action:FlxAction):Bool
{
return switch(trigger)
return switch (trigger)
{
#if android
case PRESSED: FlxG.android.checkStatus(inputID, PRESSED) || FlxG.android.checkStatus(inputID, PRESSED);

View file

@ -51,7 +51,7 @@ class AnsiTrace
public static function traceBF()
{
#if sys
#if (sys && debug)
if (colorSupported)
{
for (line in ansiBF)