mirror of
https://github.com/FunkinCrew/Funkin.git
synced 2024-11-14 19:25:16 -05:00
Merge remote-tracking branch 'upstream/main' into better-templates
This commit is contained in:
commit
a27e743c5f
10 changed files with 343 additions and 176 deletions
51
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal file
51
.github/ISSUE_TEMPLATE/bug.md
vendored
Normal 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:
|
||||
|
||||
"It’s 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
8
.github/ISSUE_TEMPLATE/enhancement.md
vendored
Normal 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
10
.github/PULL_REQUEST_TEMPLATE/bug.md
vendored
Normal 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.
|
10
.github/PULL_REQUEST_TEMPLATE/enhancement.md
vendored
Normal file
10
.github/PULL_REQUEST_TEMPLATE/enhancement.md
vendored
Normal 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
12
.github/changed-lines-count-labeler.yml
vendored
Normal 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
|
15
.github/workflows/labeler.yml
vendored
15
.github/workflows/labeler.yml
vendored
|
@ -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
|
||||
|
|
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -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.
|
||||
|
||||
|
|
|
@ -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**.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -51,7 +51,7 @@ class AnsiTrace
|
|||
|
||||
public static function traceBF()
|
||||
{
|
||||
#if sys
|
||||
#if (sys && debug)
|
||||
if (colorSupported)
|
||||
{
|
||||
for (line in ansiBF)
|
||||
|
|
Loading…
Reference in a new issue