Merge branch 'rewrite/master' into mob-96/week3-train-haptics
This commit is contained in:
@@ -767,6 +767,10 @@ class Project extends HXProject
|
||||
// Enable OpenFL's error handler. Required for the crash logger.
|
||||
setHaxedef("openfl-enable-handle-error");
|
||||
|
||||
// Disable a macro in Lime that generates a random number for Assets.cache.version every build.
|
||||
// This doesn't seem to be of any use and it causes lime.utils.AssetCache to be re-compiled on every build.
|
||||
setHaxedef("lime_disable_assets_version");
|
||||
|
||||
// Enable stack trace tracking. Good for debugging but has a (minor) performance impact.
|
||||
setHaxedef("HXCPP_CHECK_POINTER");
|
||||
setHaxedef("HXCPP_STACK_LINE");
|
||||
|
||||
@@ -5,6 +5,7 @@ import funkin.mobile.ui.FunkinHitbox;
|
||||
#end
|
||||
import funkin.save.Save;
|
||||
import funkin.util.WindowUtil;
|
||||
import funkin.util.HapticUtil.HapticsMode;
|
||||
|
||||
/**
|
||||
* A core class which provides a store of user-configurable, globally relevant values.
|
||||
@@ -147,20 +148,42 @@ class Preferences
|
||||
}
|
||||
|
||||
/**
|
||||
* If enabled, vibration will be enabled.
|
||||
* @default `true`
|
||||
* If enabled, haptic feedback will be enabled.
|
||||
* @default `All`
|
||||
*/
|
||||
public static var vibration(get, set):Bool;
|
||||
public static var hapticsMode(get, set):HapticsMode;
|
||||
|
||||
static function get_vibration():Bool
|
||||
static function get_hapticsMode():HapticsMode
|
||||
{
|
||||
return Save?.instance?.options?.vibration ?? true;
|
||||
var value = Save?.instance?.options?.hapticsMode ?? "All";
|
||||
|
||||
return switch (value)
|
||||
{
|
||||
case "None":
|
||||
HapticsMode.NONE;
|
||||
case "Notes Only":
|
||||
HapticsMode.NOTES_ONLY;
|
||||
default:
|
||||
HapticsMode.ALL;
|
||||
};
|
||||
}
|
||||
|
||||
static function set_vibration(value:Bool):Bool
|
||||
static function set_hapticsMode(value:HapticsMode):HapticsMode
|
||||
{
|
||||
var string;
|
||||
|
||||
switch (value)
|
||||
{
|
||||
case HapticsMode.NONE:
|
||||
string = "None";
|
||||
case HapticsMode.NOTES_ONLY:
|
||||
string = "Notes Only";
|
||||
default:
|
||||
string = "All";
|
||||
};
|
||||
|
||||
var save:Save = Save.instance;
|
||||
save.options.vibration = value;
|
||||
save.options.hapticsMode = string;
|
||||
save.flush();
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ class HoldNoteScriptEvent extends NoteScriptEvent
|
||||
*/
|
||||
public var doesNotesplash:Bool = false;
|
||||
|
||||
public function new(type:ScriptEventType, holdNote:SustainTrail, healthChange:Float, score:Int, isComboBreak:Bool, cancelable:Bool = false):Void
|
||||
public function new(type:ScriptEventType, holdNote:SustainTrail, healthChange:Float, score:Int, isComboBreak:Bool, comboCount:Int = 0, cancelable:Bool = false):Void
|
||||
{
|
||||
super(type, null, healthChange, comboCount, true);
|
||||
this.holdNote = holdNote;
|
||||
|
||||
@@ -213,7 +213,7 @@ class PauseSubState extends MusicBeatSubState
|
||||
#if FEATURE_MOBILE_ADVERTISEMENTS
|
||||
extension.admob.Admob.onEvent.add(onBannerEvent);
|
||||
|
||||
funkin.mobile.util.AdMobUtil.addBanner(extension.admob.AdmobBannerSize.BANNER, extension.admob.AdmobBannerAlign.TOP_LEFT);
|
||||
funkin.mobile.util.AdMobUtil.addBanner(extension.admob.AdmobBannerSize.BANNER, extension.admob.AdmobBannerAlign.TOP_CENTER);
|
||||
#end
|
||||
|
||||
super.create();
|
||||
@@ -279,6 +279,7 @@ class PauseSubState extends MusicBeatSubState
|
||||
failedAdPlaceHolder = new FunkinSprite(0, 0);
|
||||
failedAdPlaceHolder.makeSolidColor(Math.floor(320 * scale), Math.floor(50 * scale), FlxColor.RED);
|
||||
failedAdPlaceHolder.updateHitbox();
|
||||
failedAdPlaceHolder.screenCenter(X);
|
||||
failedAdPlaceHolder.scrollFactor.set(0, 0);
|
||||
add(failedAdPlaceHolder);
|
||||
}
|
||||
|
||||
@@ -2517,7 +2517,7 @@ class PlayState extends MusicBeatSubState
|
||||
{
|
||||
// Call an event to allow canceling the note miss.
|
||||
// NOTE: This is what handles the character animations!
|
||||
var event:NoteScriptEvent = new NoteScriptEvent(NOTE_MISS, note, Constants.HEALTH_MISS_PENALTY, 0, true);
|
||||
var event:NoteScriptEvent = new NoteScriptEvent(NOTE_MISS, note, Constants.HEALTH_MISS_PENALTY, Highscore.tallies.combo, true);
|
||||
dispatchEvent(event);
|
||||
|
||||
// Calling event.cancelEvent() skips all the other logic! Neat!
|
||||
@@ -2584,7 +2584,7 @@ class PlayState extends MusicBeatSubState
|
||||
var healthChange = healthChangeUncapped.clamp(healthChangeMax, 0);
|
||||
var scoreChange = Std.int(Constants.SCORE_HOLD_DROP_PENALTY_PER_SECOND * remainingLengthSec);
|
||||
|
||||
var event:HoldNoteScriptEvent = new HoldNoteScriptEvent(NOTE_HOLD_DROP, holdNote, healthChange, scoreChange, true);
|
||||
var event:HoldNoteScriptEvent = new HoldNoteScriptEvent(NOTE_HOLD_DROP, holdNote, healthChange, scoreChange, true, Highscore.tallies.combo);
|
||||
dispatchEvent(event);
|
||||
|
||||
trace('Penalizing score by ${event.score} and health by ${event.healthChange} for dropping hold note (is combo break: ${event.isComboBreak})!');
|
||||
|
||||
@@ -218,9 +218,21 @@ class FocusCameraSongEvent extends SongEvent
|
||||
'Smooth Step In' => 'smoothStepIn',
|
||||
'Smooth Step Out' => 'smoothStepOut',
|
||||
'Smooth Step In/Out' => 'smoothStepInOut',
|
||||
'Smoother Step In' => 'smootherStepIn',
|
||||
'Smoother Step Out' => 'smootherStepOut',
|
||||
'Smoother Step In/Out' => 'smootherStepInOut',
|
||||
'Elastic In' => 'elasticIn',
|
||||
'Elastic Out' => 'elasticOut',
|
||||
'Elastic In/Out' => 'elasticInOut',
|
||||
'Back In' => 'backIn',
|
||||
'Back Out' => 'backOut',
|
||||
'Back In/Out' => 'backInOut',
|
||||
'Bounce In' => 'bounceIn',
|
||||
'Bounce Out' => 'bounceOut',
|
||||
'Bounce In/Out' => 'bounceInOut',
|
||||
'Circ In' => 'circIn',
|
||||
'Circ Out' => 'circOut',
|
||||
'Circ In/Out' => 'circInOut',
|
||||
'Instant (Ignores duration)' => 'INSTANT',
|
||||
'Classic (Ignores duration)' => 'CLASSIC'
|
||||
]
|
||||
|
||||
@@ -149,9 +149,21 @@ class ScrollSpeedEvent extends SongEvent
|
||||
'Smooth Step In' => 'smoothStepIn',
|
||||
'Smooth Step Out' => 'smoothStepOut',
|
||||
'Smooth Step In/Out' => 'smoothStepInOut',
|
||||
'Smoother Step In' => 'smootherStepIn',
|
||||
'Smoother Step Out' => 'smootherStepOut',
|
||||
'Smoother Step In/Out' => 'smootherStepInOut',
|
||||
'Elastic In' => 'elasticIn',
|
||||
'Elastic Out' => 'elasticOut',
|
||||
'Elastic In/Out' => 'elasticInOut'
|
||||
'Elastic In/Out' => 'elasticInOut',
|
||||
'Back In' => 'backIn',
|
||||
'Back Out' => 'backOut',
|
||||
'Back In/Out' => 'backInOut',
|
||||
'Bounce In' => 'bounceIn',
|
||||
'Bounce Out' => 'bounceOut',
|
||||
'Bounce In/Out' => 'bounceInOut',
|
||||
'Circ In' => 'circIn',
|
||||
'Circ Out' => 'circOut',
|
||||
'Circ In/Out' => 'circInOut'
|
||||
]
|
||||
},
|
||||
{
|
||||
|
||||
@@ -158,9 +158,21 @@ class ZoomCameraSongEvent extends SongEvent
|
||||
'Smooth Step In' => 'smoothStepIn',
|
||||
'Smooth Step Out' => 'smoothStepOut',
|
||||
'Smooth Step In/Out' => 'smoothStepInOut',
|
||||
'Smoother Step In' => 'smootherStepIn',
|
||||
'Smoother Step Out' => 'smootherStepOut',
|
||||
'Smoother Step In/Out' => 'smootherStepInOut',
|
||||
'Elastic In' => 'elasticIn',
|
||||
'Elastic Out' => 'elasticOut',
|
||||
'Elastic In/Out' => 'elasticInOut'
|
||||
'Elastic In/Out' => 'elasticInOut',
|
||||
'Back In' => 'backIn',
|
||||
'Back Out' => 'backOut',
|
||||
'Back In/Out' => 'backInOut',
|
||||
'Bounce In' => 'bounceIn',
|
||||
'Bounce Out' => 'bounceOut',
|
||||
'Bounce In/Out' => 'bounceInOut',
|
||||
'Circ In' => 'circIn',
|
||||
'Circ Out' => 'circOut',
|
||||
'Circ In/Out' => 'circInOut'
|
||||
]
|
||||
}
|
||||
]);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package funkin.play.notes;
|
||||
|
||||
import funkin.util.HapticUtil;
|
||||
import funkin.util.HapticUtil.HapticsMode;
|
||||
|
||||
/**
|
||||
* Handles vibrations on note presses.
|
||||
@@ -60,7 +61,7 @@ class NoteVibrationsHandler
|
||||
|
||||
if (stackingAmplitude > Constants.MAX_VIBRATION_AMPLITUDE) stackingAmplitude = Constants.MAX_VIBRATION_AMPLITUDE;
|
||||
|
||||
if (stackingAmplitude > 0) HapticUtil.vibrate(0, 0.01, stackingAmplitude);
|
||||
if (stackingAmplitude > 0) HapticUtil.vibrate(0, 0.01, stackingAmplitude, [HapticsMode.ALL, HapticsMode.NOTES_ONLY]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +84,7 @@ class NoteVibrationsHandler
|
||||
|
||||
if (stackingAmplitude > Constants.MAX_VIBRATION_AMPLITUDE) stackingAmplitude = Constants.MAX_VIBRATION_AMPLITUDE;
|
||||
|
||||
if (stackingAmplitude > 0) HapticUtil.vibrate(0, 0.01, stackingAmplitude);
|
||||
if (stackingAmplitude > 0) HapticUtil.vibrate(0, 0.01, stackingAmplitude, [HapticsMode.ALL, HapticsMode.NOTES_ONLY]);
|
||||
|
||||
for (currentNoteStatus in noteStatuses)
|
||||
{
|
||||
|
||||
@@ -121,7 +121,7 @@ class Save
|
||||
flashingLights: true,
|
||||
zoomCamera: true,
|
||||
debugDisplay: false,
|
||||
vibration: true,
|
||||
hapticsMode: 'All',
|
||||
autoPause: true,
|
||||
vsyncMode: 'Off',
|
||||
strumlineBackgroundOpacity: 0,
|
||||
@@ -1435,10 +1435,10 @@ typedef SaveDataOptions =
|
||||
var debugDisplay:Bool;
|
||||
|
||||
/**
|
||||
* If enabled, vibration will be enabled.
|
||||
* @default `true`
|
||||
* If enabled, haptic feedback will be enabled.
|
||||
* @default `All`
|
||||
*/
|
||||
var vibration:Bool;
|
||||
var hapticsMode:String;
|
||||
|
||||
/**
|
||||
* If enabled, the game will automatically pause when tabbing out.
|
||||
|
||||
@@ -22,7 +22,8 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
|
||||
public var charSelectScroll:ScrollView;
|
||||
public var charIconName:Label;
|
||||
|
||||
var currentCharButton:Button;
|
||||
var currentCharButton:Null<Button> = null;
|
||||
var currentCharId:String = '';
|
||||
|
||||
public function new(chartEditorState2:ChartEditorState, charType:CharacterType, lockPosition:Bool = false)
|
||||
{
|
||||
@@ -36,14 +37,16 @@ class ChartEditorCharacterIconSelectorMenu extends ChartEditorBaseMenu
|
||||
ease: FlxEase.quartOut,
|
||||
onComplete: function(_) {
|
||||
// Just focus the button FFS. Idk why, but the scrollbar doesn't update until after the tween finishes with this????
|
||||
currentCharButton.focus = true;
|
||||
if (currentCharButton != null) currentCharButton.focus = true;
|
||||
else
|
||||
chartEditorState.error('Failure', 'Could not find character of ${currentCharId} in registry (Is the character in the registry?)');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function initialize(charType:CharacterType, lockPosition:Bool)
|
||||
{
|
||||
var currentCharId:String = switch (charType)
|
||||
currentCharId = switch (charType)
|
||||
{
|
||||
case BF: chartEditorState.currentSongMetadata.playData.characters.player;
|
||||
case GF: chartEditorState.currentSongMetadata.playData.characters.girlfriend;
|
||||
|
||||
@@ -833,10 +833,6 @@ class FreeplayState extends MusicBeatSubState
|
||||
currentFilteredSongs = tempSongs;
|
||||
curSelected = 0;
|
||||
|
||||
// If curSelected is 0, the result will be null and fall back to the rememberedSongId.
|
||||
// We set this so if we change the filter, we'd remain on the same song if it's still in the list.
|
||||
rememberedSongId = grpCapsules.members[curSelected]?.freeplayData?.data.id ?? rememberedSongId;
|
||||
|
||||
grpCapsules.killMembers();
|
||||
|
||||
// Initialize the random capsule, with empty/blank info (which we display once bf/pico does his hand)
|
||||
@@ -963,6 +959,9 @@ class FreeplayState extends MusicBeatSubState
|
||||
|
||||
rememberedSongId = fromResults.songId;
|
||||
rememberedDifficulty = fromResults.difficultyId;
|
||||
capsuleToRank.fakeRanking.visible = true;
|
||||
capsuleToRank.fakeRanking.alpha = 0; // If this isn't done, you'd see a tiny E being replaced for the first rank
|
||||
|
||||
changeSelection();
|
||||
changeDiff();
|
||||
|
||||
@@ -1003,6 +1002,7 @@ class FreeplayState extends MusicBeatSubState
|
||||
sparksADD.cameras = [rankCamera];
|
||||
sparksADD.color = fromResults.oldRank.getRankingFreeplayColor();
|
||||
// sparksADD.color = sparks.color;
|
||||
capsuleToRank.fakeRanking.alpha = 1.0;
|
||||
}
|
||||
|
||||
capsuleToRank.doLerp = false;
|
||||
@@ -1015,7 +1015,6 @@ class FreeplayState extends MusicBeatSubState
|
||||
trace(originalPos);
|
||||
|
||||
capsuleToRank.ranking.visible = false;
|
||||
capsuleToRank.fakeRanking.visible = false;
|
||||
|
||||
// Rank animation vibrations.
|
||||
HapticUtil.increasingVibrate(Constants.MIN_VIBRATION_AMPLITUDE, Constants.MAX_VIBRATION_AMPLITUDE, 0.6);
|
||||
@@ -2290,16 +2289,22 @@ class FreeplayState extends MusicBeatSubState
|
||||
var altInstrumentalIds:Array<String> = targetSong.listAltInstrumentalIds(targetDifficultyId,
|
||||
targetDifficulty?.variation ?? Constants.DEFAULT_VARIATION) ?? [];
|
||||
|
||||
#if !mobile
|
||||
if (altInstrumentalIds.length > 0)
|
||||
{
|
||||
var instrumentalIds = [baseInstrumentalId].concat(altInstrumentalIds);
|
||||
openInstrumentalList(cap, instrumentalIds);
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace('NO ALTS');
|
||||
capsuleOnConfirmDefault(cap);
|
||||
}
|
||||
#end
|
||||
|
||||
#if mobile
|
||||
trace('ALTS ARE DISABLED');
|
||||
#else
|
||||
trace('NO ALTS');
|
||||
#end
|
||||
capsuleOnConfirmDefault(cap);
|
||||
}
|
||||
|
||||
public function getControls():Controls
|
||||
|
||||
@@ -300,7 +300,7 @@ class SongMenuItem extends FlxSpriteGroup
|
||||
var clipSize:Int = 290;
|
||||
var clipType:Int = 0;
|
||||
|
||||
if (ranking.visible)
|
||||
if (ranking.visible || fakeRanking.visible)
|
||||
{
|
||||
favIconBlurred.x = this.x + 370;
|
||||
favIcon.x = favIconBlurred.x;
|
||||
|
||||
@@ -22,6 +22,7 @@ import funkin.mobile.ui.FunkinHitbox.FunkinHitboxControlSchemes;
|
||||
import funkin.util.TouchUtil;
|
||||
import funkin.util.SwipeUtil;
|
||||
#end
|
||||
import funkin.util.HapticUtil;
|
||||
import lime.ui.WindowVSyncMode;
|
||||
|
||||
class PreferencesMenu extends Page<OptionsState.OptionsMenuPageName>
|
||||
@@ -124,6 +125,20 @@ class PreferencesMenu extends Page<OptionsState.OptionsMenuPageName>
|
||||
createPrefItemCheckbox('Camera Zooms', 'If disabled, camera stops bouncing to the song.', function(value:Bool):Void {
|
||||
Preferences.zoomCamera = value;
|
||||
}, Preferences.zoomCamera);
|
||||
#if FEATURE_HAPTICS
|
||||
createPrefItemEnum('Haptics', 'If enabled, game will use haptic feedback effects.', [
|
||||
"All" => HapticsMode.ALL,
|
||||
"Notes Only" => HapticsMode.NOTES_ONLY,
|
||||
"None" => HapticsMode.NONE,
|
||||
], function(key:String, value:HapticsMode):Void {
|
||||
Preferences.hapticsMode = value;
|
||||
}, switch (Preferences.hapticsMode)
|
||||
{
|
||||
case HapticsMode.NOTES_ONLY: "Notes Only";
|
||||
case HapticsMode.NONE: "None";
|
||||
default: "All";
|
||||
});
|
||||
#end
|
||||
createPrefItemCheckbox('Debug Display', 'If enabled, FPS and other debug stats will be displayed.', function(value:Bool):Void {
|
||||
Preferences.debugDisplay = value;
|
||||
}, Preferences.debugDisplay);
|
||||
|
||||
@@ -35,11 +35,15 @@ class HapticUtil
|
||||
* @param sharpness Controls the feel of vibration.
|
||||
*/
|
||||
public static function vibrate(period:Float = Constants.DEFAULT_VIBRATION_PERIOD, duration:Float = Constants.DEFAULT_VIBRATION_DURATION,
|
||||
amplitude:Float = Constants.DEFAULT_VIBRATION_AMPLITUDE, sharpness:Float = Constants.DEFAULT_VIBRATION_SHARPNESS):Void
|
||||
amplitude:Float = Constants.DEFAULT_VIBRATION_AMPLITUDE, sharpness:Float = Constants.DEFAULT_VIBRATION_SHARPNESS,
|
||||
?targetHapticsModes:Array<HapticsMode>):Void
|
||||
{
|
||||
#if FEATURE_HAPTICS
|
||||
if (!HapticUtil.hapticsAvailable) return;
|
||||
|
||||
final hapticsModes:Array<HapticsMode> = targetHapticsModes ?? [HapticsMode.ALL];
|
||||
if (!hapticsModes.contains(Preferences.hapticsMode)) return;
|
||||
|
||||
#if ios
|
||||
final amplitudeValue = FlxMath.bound(amplitude * 2.5, 0, Constants.MAX_VIBRATION_AMPLITUDE);
|
||||
#else
|
||||
@@ -122,7 +126,7 @@ class HapticUtil
|
||||
static function get_hapticsAvailable():Bool
|
||||
{
|
||||
#if FEATURE_HAPTICS
|
||||
if (Preferences.vibration) return true;
|
||||
if (Preferences.hapticsMode != HapticsMode.NONE) return true;
|
||||
#end
|
||||
|
||||
return false;
|
||||
@@ -154,3 +158,24 @@ typedef VibrationPreset =
|
||||
*/
|
||||
var sharpness:Float;
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract for vibrations preference.
|
||||
*/
|
||||
enum abstract HapticsMode(Int) from Int to Int
|
||||
{
|
||||
/**
|
||||
* Haptics are completely disabled.
|
||||
*/
|
||||
var NONE:Int = 0;
|
||||
|
||||
/**
|
||||
* Only note haptics are enabled.
|
||||
*/
|
||||
var NOTES_ONLY:Int = 1;
|
||||
|
||||
/**
|
||||
* All the haptics are enabled.
|
||||
*/
|
||||
var ALL:Int = 2;
|
||||
}
|
||||
|
||||
@@ -85,12 +85,6 @@ class WindowUtil
|
||||
*/
|
||||
public static function initTracy():Void
|
||||
{
|
||||
// Apply a marker to indicate frame end for the Tracy profiler.
|
||||
// Do this only if Tracy is configured to prevent lag.
|
||||
openfl.Lib.current.stage.addEventListener(openfl.events.Event.EXIT_FRAME, (e:openfl.events.Event) -> {
|
||||
cpp.vm.tracy.TracyProfiler.frameMark();
|
||||
});
|
||||
|
||||
var appInfoMessage = funkin.util.logging.CrashHandler.buildSystemInfo();
|
||||
|
||||
trace("Friday Night Funkin': Connection to Tracy profiler successful.");
|
||||
|
||||
Reference in New Issue
Block a user