Merge pull request #1798 from FunkinCrew/pr-5118/anysad/funkin-ui-null-safety

This commit is contained in:
Abnormal
2025-10-07 03:49:36 -05:00
committed by GitHub
10 changed files with 84 additions and 77 deletions
+1
View File
@@ -2,6 +2,7 @@ package funkin.ui.charSelect;
import flixel.FlxSprite;
@:nullSafety
class CharIcon extends FlxSprite
{
public var locked:Bool = false;
@@ -5,9 +5,10 @@ import openfl.filters.DropShadowFilter;
import openfl.filters.ConvolutionFilter;
import funkin.graphics.shaders.StrokeShader;
@:nullSafety
class CharIconCharacter extends CharIcon
{
public var dropShadowFilter:DropShadowFilter;
// public var dropShadowFilter:DropShadowFilter;
var matrixFilter:Array<Float> = [
1, 1, 1,
@@ -17,12 +18,12 @@ class CharIconCharacter extends CharIcon
var divisor:Int = 1;
var bias:Int = 0;
var convolutionFilter:ConvolutionFilter;
// var convolutionFilter:ConvolutionFilter;
public var noDropShadow:BitmapData;
public var withDropShadow:BitmapData;
// public var noDropShadow:BitmapData;
// public var withDropShadow:BitmapData;
var strokeShader:StrokeShader;
// var strokeShader:StrokeShader;
public function new(path:String)
{
@@ -33,7 +34,7 @@ class CharIconCharacter extends CharIcon
updateHitbox();
antialiasing = false;
strokeShader = new StrokeShader();
// strokeShader = new StrokeShader();
// shader = strokeShader;
// noDropShadow = pixels.clone();
@@ -1,3 +1,4 @@
package funkin.ui.charSelect;
@:nullSafety
class CharIconLocked extends CharIcon {}
+9 -7
View File
@@ -10,6 +10,7 @@ import funkin.modding.events.ScriptEvent;
import funkin.vis.dsp.SpectralAnalyzer;
import funkin.data.freeplay.player.PlayerRegistry;
@:nullSafety
class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
{
var fadeTimer:Float = 0;
@@ -21,9 +22,9 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
var intendedYPos:Float = 0;
var intendedAlpha:Float = 0;
var list:Array<String> = [];
var list:Array<Null<String>> = [];
var analyzer:SpectralAnalyzer;
var analyzer:Null<SpectralAnalyzer>;
var analyzerLevelsCache:Array<Bar> = new Array<Bar>();
var currentGFPath:Null<String>;
@@ -35,7 +36,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
list = anim.curSymbol.getFrameLabelNames();
switchGF("bf");
switchGF(Constants.DEFAULT_CHARACTER);
}
override public function update(elapsed:Float):Void
@@ -50,9 +51,9 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
// maybe reset timers?
resetFadeAnimParams();
case FADE_OUT:
doFade(animOutInfo);
if (animOutInfo != null) doFade(animOutInfo);
case FADE_IN:
doFade(animInInfo);
if (animInInfo != null) doFade(animInInfo);
default:
}
}
@@ -83,10 +84,11 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
function drawFFT()
{
if (enableVisualizer)
if (enableVisualizer && analyzer != null)
{
analyzerLevelsCache = analyzer.getLevels(analyzerLevelsCache);
var frame = anim.curSymbol.timeline.get("VIZ_bars").get(anim.curFrame);
if (frame == null) return;
var elements = frame.getList();
var len:Int = cast Math.min(elements.length, 7);
@@ -167,7 +169,7 @@ class CharSelectGF extends FlxAtlasSprite implements IBPMSyncedScriptedClass
var bfObj = PlayerRegistry.instance.fetchEntry(bf);
var gfData = bfObj?.getCharSelectData()?.gf;
currentGFPath = gfData?.assetPath != null ? Paths.animateAtlas(gfData?.assetPath) : null;
if (gfData != null && gfData.assetPath != null) currentGFPath = Paths.animateAtlas(gfData.assetPath);
// We don't need to update any anims if we didn't change GF
trace('currentGFPath(${currentGFPath})');
@@ -4,6 +4,7 @@ import funkin.graphics.adobeanimate.FlxAtlasSprite;
import funkin.modding.IScriptedClass.IBPMSyncedScriptedClass;
import funkin.modding.events.ScriptEvent;
@:nullSafety
class CharSelectPlayer extends FlxAtlasSprite implements IBPMSyncedScriptedClass
{
var initialX:Float = 0;
@@ -39,18 +39,19 @@ import funkin.util.TouchUtil;
import funkin.util.SwipeUtil;
import funkin.util.HapticUtil;
@:nullSafety
class CharSelectSubState extends MusicBeatSubState
{
// what the actual hell
// having a hard time trying to make my changes work so i chose to be less stubborn and just remove them for now. - Zack
// Left this here so somebody can remind me
var cursor:FlxSprite;
var cursor:FlxSprite = new FlxSprite(0, 0);
var cursorBlue:FlxSprite;
var cursorDarkBlue:FlxSprite;
var grpCursors:FlxTypedGroup<FlxSprite>;
var cursorConfirmed:FlxSprite;
var cursorDenied:FlxSprite;
var cursorBlue:FlxSprite = new FlxSprite(0, 0);
var cursorDarkBlue:FlxSprite = new FlxSprite(0, 0);
var grpCursors:FlxTypedGroup<FlxSprite> = new FlxTypedGroup<FlxSprite>();
var cursorConfirmed:FlxSprite = new FlxSprite(0, 0);
var cursorDenied:FlxSprite = new FlxSprite(0, 0);
var cursorX:Int = 0;
var cursorY:Int = 0;
var cursorFactor:Float = 110;
@@ -58,50 +59,50 @@ class CharSelectSubState extends MusicBeatSubState
var cursorOffsetY:Float = -48;
var cursorLocIntended:FlxPoint = new FlxPoint(0, 0);
var tmrFrames:Int = 60;
var currentStage:Stage;
var playerChill:CharSelectPlayer;
var playerChillOut:CharSelectPlayer;
var gfChill:CharSelectGF;
var gfChillOut:CharSelectGF;
var barthing:FlxAtlasSprite;
var dipshitBacking:FlxSprite;
var chooseDipshit:FlxSprite;
var dipshitBlur:FlxSprite;
var transitionGradient:FlxSprite;
// var currentStage:Stage;
var playerChill:CharSelectPlayer = new CharSelectPlayer(0, 0);
var playerChillOut:CharSelectPlayer = new CharSelectPlayer(0, 0);
var gfChill:CharSelectGF = new CharSelectGF();
// var gfChillOut:CharSelectGF;
var barthing:FlxAtlasSprite = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/barThing"));
var dipshitBacking:FlxSprite = new FlxSprite(423, -17);
var chooseDipshit:FlxSprite = new FlxSprite(426, -13);
var dipshitBlur:FlxSprite = new FlxSprite(419, -65);
var transitionGradient:FlxSprite = new FlxSprite(0, 0);
var curChar(default, set):String = Constants.DEFAULT_CHARACTER;
var rememberedChar:String;
var nametag:Nametag;
var camFollow:FlxObject;
var nametag:Nametag = new Nametag(Constants.DEFAULT_CHARACTER);
var camFollow:FlxObject = new FlxObject(0, 0, 1, 1);
var autoFollow:Bool = false;
var availableChars:Map<Int, String> = new Map<Int, String>();
var pressedSelect:Bool = false;
var selectTimer:FlxTimer = new FlxTimer();
var allowInput:Bool = false;
var selectSound:FunkinSound;
var unlockSound:FunkinSound;
var lockedSound:FunkinSound;
var introSound:FunkinSound;
var staticSound:FunkinSound;
var selectSound:FunkinSound = new FunkinSound();
var unlockSound:FunkinSound = new FunkinSound();
var lockedSound:FunkinSound = new FunkinSound();
var introSound:FunkinSound = new FunkinSound();
var staticSound:FunkinSound = new FunkinSound();
var charSelectCam:FunkinCamera;
// var charSelectCam:FunkinCamera;
var selectedBizz:Array<BitmapFilter> = [
new DropShadowFilter(0, 0, 0xFFFFFF, 1, 2, 2, 19, 1, false, false, false),
new DropShadowFilter(5, 45, 0x000000, 1, 2, 2, 1, 1, false, false, false)
];
var bopInfo:Null<FramesJSFLInfo>;
var blackScreen:FunkinSprite;
var bopInfo:Null<Null<FramesJSFLInfo>>;
// var blackScreen:FunkinSprite;
var charHitbox:FlxObject;
var charHitbox:FlxObject = new FlxObject();
var cutoutSize:Float = 0;
public function new(?params:CharSelectSubStateParams)
{
super();
rememberedChar = params?.character;
rememberedChar = params?.character ?? Constants.DEFAULT_CHARACTER;
loadAvailableCharacters();
}
@@ -166,7 +167,6 @@ class CharSelectSubState extends MusicBeatSubState
curtains.scrollFactor.set(1.4, 1.4);
add(curtains);
barthing = new FlxAtlasSprite(0, 0, Paths.animateAtlas("charSelect/barThing"));
barthing.anim.play("");
barthing.anim.onComplete.add(function() {
barthing.anim.play("");
@@ -297,34 +297,28 @@ class CharSelectSubState extends MusicBeatSubState
// FlxG.debugger.track(charLightGF, "charLight");
// FlxG.debugger.track(gfChill, "gfChill");
grpCursors = new FlxTypedGroup<FlxSprite>();
add(grpCursors);
cursor = new FlxSprite(0, 0);
cursor.loadGraphic(Paths.image('charSelect/charSelector'));
cursor.color = 0xFFFFFF00;
// FFCC00
cursorBlue = new FlxSprite(0, 0);
cursorBlue.loadGraphic(Paths.image('charSelect/charSelector'));
cursorBlue.color = 0xFF3EBBFF;
cursorDarkBlue = new FlxSprite(0, 0);
cursorDarkBlue.loadGraphic(Paths.image('charSelect/charSelector'));
cursorDarkBlue.color = 0xFF3C74F7;
cursorBlue.blend = BlendMode.SCREEN;
cursorDarkBlue.blend = BlendMode.SCREEN;
cursorConfirmed = new FlxSprite(0, 0);
cursorConfirmed.scrollFactor.set();
cursorConfirmed.frames = Paths.getSparrowAtlas("charSelect/charSelectorConfirm");
cursorConfirmed.animation.addByPrefix("idle", "cursor ACCEPTED instance 1", 24, true);
cursorConfirmed.visible = false;
add(cursorConfirmed);
cursorDenied = new FlxSprite(0, 0);
cursorDenied.scrollFactor.set();
cursorDenied.frames = Paths.getSparrowAtlas("charSelect/charSelectorDenied");
cursorDenied.animation.addByPrefix("idle", "cursor DENIED instance 1", 24, false);
@@ -339,7 +333,6 @@ class CharSelectSubState extends MusicBeatSubState
charHitbox.active = false;
charHitbox.scrollFactor.set();
selectSound = new FunkinSound();
selectSound.loadEmbedded(Paths.sound('CS_select'));
selectSound.pitch = 1;
selectSound.volume = 0.7;
@@ -347,7 +340,6 @@ class CharSelectSubState extends MusicBeatSubState
FlxG.sound.defaultSoundGroup.add(selectSound);
FlxG.sound.list.add(selectSound);
unlockSound = new FunkinSound();
unlockSound.loadEmbedded(Paths.sound('CS_unlock'));
unlockSound.pitch = 1;
@@ -357,7 +349,6 @@ class CharSelectSubState extends MusicBeatSubState
FlxG.sound.defaultSoundGroup.add(unlockSound);
FlxG.sound.list.add(unlockSound);
lockedSound = new FunkinSound();
lockedSound.loadEmbedded(Paths.sound('CS_locked'));
lockedSound.pitch = 1;
@@ -366,7 +357,6 @@ class CharSelectSubState extends MusicBeatSubState
FlxG.sound.defaultSoundGroup.add(lockedSound);
FlxG.sound.list.add(lockedSound);
staticSound = new FunkinSound();
staticSound.loadEmbedded(Paths.sound('static loop'));
staticSound.pitch = 1;
@@ -405,7 +395,6 @@ class CharSelectSubState extends MusicBeatSubState
FlxG.debugger.addTrackerProfile(new TrackerProfile(CharSelectSubState, ["curChar", "grpXSpread", "grpYSpread"]));
FlxG.debugger.track(this);
camFollow = new FlxObject(0, 0, 1, 1);
add(camFollow);
camFollow.screenCenter();
@@ -423,7 +412,7 @@ class CharSelectSubState extends MusicBeatSubState
Conductor.stepHit.add(spamOnStep);
// FlxG.debugger.track(temp, "tempBG");
transitionGradient = new FlxSprite(0, 0).loadGraphic(Paths.image('freeplay/transitionGradient'));
transitionGradient.loadGraphic(Paths.image('freeplay/transitionGradient'));
transitionGradient.scale.set(1280, 1);
transitionGradient.flipY = true;
transitionGradient.updateHitbox();
@@ -504,26 +493,24 @@ class CharSelectSubState extends MusicBeatSubState
}
}
var grpIcons:FlxSpriteGroup;
var grpHitboxes:FlxTypedGroup<FlxObject>;
var grpIcons:FlxSpriteGroup = new FlxSpriteGroup();
var grpHitboxes:FlxTypedGroup<FlxObject> = new FlxTypedGroup<FlxObject>();
var grpXSpread(default, set):Float = 107;
var grpYSpread(default, set):Float = 127;
var nonLocks = [];
function initLocks():Void
{
grpIcons = new FlxSpriteGroup();
add(grpIcons);
grpHitboxes = new FlxTypedGroup<FlxObject>();
FlxG.debugger.addTrackerProfile(new TrackerProfile(FlxSpriteGroup, ["x", "y"]));
// FlxG.debugger.track(grpIcons, "iconGrp");
for (i in 0...9)
{
if (availableChars.exists(i) && PlayerRegistry.instance.isCharacterSeen(availableChars.get(i)))
if (availableChars.exists(i) && PlayerRegistry.instance.isCharacterSeen(availableChars.get(i) ?? Constants.DEFAULT_CHARACTER))
{
var path:String = availableChars.get(i);
var path:Null<String> = availableChars.get(i) ?? Constants.DEFAULT_CHARACTER;
var temp:PixelatedIcon = new PixelatedIcon(0, 0);
temp.setCharacter(path);
temp.setGraphicSize(128, 128);
@@ -533,7 +520,7 @@ class CharSelectSubState extends MusicBeatSubState
}
else
{
var playableCharacterId:String = availableChars.get(i);
var playableCharacterId:Null<String> = availableChars.get(i) ?? Constants.DEFAULT_CHARACTER;
var player:Null<PlayableCharacter> = PlayerRegistry.instance.fetchEntry(playableCharacterId);
var isPlayerUnlocked:Bool = player?.isUnlocked() ?? false;
if (availableChars.exists(i) && isPlayerUnlocked) nonLocks.push(i);
@@ -605,7 +592,7 @@ class CharSelectSubState extends MusicBeatSubState
lock.onAnimationComplete.addOnce(function(_) {
// syncLock = null;
var char = availableChars.get(index);
var char:Null<String> = availableChars.get(index) ?? Constants.DEFAULT_CHARACTER;
camera.flash(0xFFFFFFFF, 0.1);
playerChill.playAnimation("unlock");
playerChill.visible = true;
@@ -671,7 +658,7 @@ class CharSelectSubState extends MusicBeatSubState
});
playerChill.visible = false;
playerChill.switchChar(availableChars[index]);
playerChill.switchChar(availableChars[index] ?? Constants.DEFAULT_CHARACTER);
playerChillOut.visible = true;
});
@@ -707,7 +694,7 @@ class CharSelectSubState extends MusicBeatSubState
}
var sync:Bool = false;
var syncLock:Lock = null;
var syncLock:Null<Lock>;
var audioBizz:Float = 0;
function syncAudio(elapsed:Float):Void
@@ -933,9 +920,11 @@ class CharSelectSubState extends MusicBeatSubState
cursorY = -1;
}
if (availableChars.exists(getCurrentSelected()) && PlayerRegistry.instance.isCharacterSeen(availableChars[getCurrentSelected()]))
if (availableChars.exists(getCurrentSelected())
&& PlayerRegistry.instance.isCharacterSeen(availableChars[getCurrentSelected()] ?? Constants.DEFAULT_CHARACTER))
{
curChar = availableChars.get(getCurrentSelected());
var charId = availableChars.get(getCurrentSelected());
if (charId != null) curChar = charId;
if (allowInput && pressedSelect && (controls.BACK #if FEATURE_TOUCH_CONTROLS || (mobileDeny && TouchUtil.justReleased) #end))
{
@@ -1181,6 +1170,7 @@ class CharSelectSubState extends MusicBeatSubState
if (autoFollow && !pressedSelect && memb.animation.curAnim?.name != 'idle')
{
memb.animation.play("confirm", false, true);
@:nullSafety(Off)
var onFinish:String->Void = null;
onFinish = (_) -> {
member.animation.play('idle');
@@ -1192,6 +1182,7 @@ class CharSelectSubState extends MusicBeatSubState
else
{
// memb.pixels = memb.noDropShadow.clone();
@:nullSafety(Off)
memb.filters = null;
memb.scale.set(2, 2);
}
@@ -24,6 +24,7 @@ using flixel.util.FlxSpriteUtil;
* When you want the player to unlock a character, call `CharacterUnlockState.unlock(characterName)`.
* It handles both the act of unlocking the character and displaying the dialog.
*/
@:nullSafety
class CharacterUnlockState extends MusicBeatState
{
public var targetCharacterId:String = "";
@@ -78,11 +79,11 @@ class CharacterUnlockState extends MusicBeatState
// HealthIcon handles getting the right frames for us,
// but it has a bunch of overhead in it that makes it gross to work with outside the health bar.
var healthIconCharacterId = targetCharacterData.getOwnedCharacterIds()[0];
var baseCharacter = CharacterDataParser.fetchCharacter(healthIconCharacterId);
var healthIconCharacterId = targetCharacterData?.getOwnedCharacterIds()[0];
var baseCharacter = CharacterDataParser.fetchCharacter(healthIconCharacterId ?? Constants.DEFAULT_CHARACTER);
var healthIcon:HealthIcon = new HealthIcon(healthIconCharacterId);
@:privateAccess
healthIcon.configure(baseCharacter._data.healthIcon);
healthIcon.configure(baseCharacter?._data.healthIcon);
healthIcon.autoUpdate = false;
healthIcon.bopEvery = 0; // You can increase this number later once the animation is done.
healthIcon.size.set(0.5, 0.5);
+9 -6
View File
@@ -12,6 +12,7 @@ import funkin.save.Save;
/**
* When you first enter the character select state, it will play an introductory video opening up the lights
*/
@:nullSafety
class IntroSubState extends MusicBeatSubState
{
#if html5
@@ -33,6 +34,7 @@ class IntroSubState extends MusicBeatSubState
if (FlxG.sound.music != null)
{
FlxG.sound.music.destroy();
@:nullSafety(Off)
FlxG.sound.music = null;
}
@@ -77,7 +79,7 @@ class IntroSubState extends MusicBeatSubState
#end
#if hxvlc
var vid:FunkinVideoSprite;
var vid:Null<FunkinVideoSprite>;
function playVideoNative(filePath:String):Void
{
@@ -90,15 +92,15 @@ class IntroSubState extends MusicBeatSubState
{
vid.zIndex = 0;
vid.active = false;
vid.bitmap.onEncounteredError.add(function(msg:String):Void {
vid.bitmap?.onEncounteredError.add(function(msg:String):Void {
trace('[VLC] Encountered an error: $msg');
onLightsEnd();
});
vid.bitmap.onEndReached.add(onLightsEnd);
vid.bitmap.onFormatSetup.add(() -> {
vid.setGraphicSize(FlxG.initialWidth, FlxG.initialHeight);
vid.updateHitbox();
vid.bitmap?.onEndReached.add(onLightsEnd);
vid.bitmap?.onFormatSetup.add(() -> {
vid?.setGraphicSize(FlxG.initialWidth, FlxG.initialHeight);
vid?.updateHitbox();
vid.screenCenter();
});
@@ -140,6 +142,7 @@ class IntroSubState extends MusicBeatSubState
#end
remove(vid);
vid.destroy();
@:nullSafety(Off)
vid = null;
}
#end
+5 -1
View File
@@ -4,6 +4,7 @@ import flixel.util.FlxColor;
import flxanimate.effects.FlxTint;
import funkin.graphics.adobeanimate.FlxAtlasSprite;
@:nullSafety
class Lock extends FlxAtlasSprite
{
var colors:Array<FlxColor> = [
@@ -22,7 +23,10 @@ class Lock extends FlxAtlasSprite
var func = function(name) {
var symbol = anim.symbolDictionary[name];
if (symbol != null && symbol.timeline.get("color") != null) symbol.timeline.get("color").get(0).colorEffect = tint;
if (symbol != null && symbol.timeline.get("color") != null) {
var color = symbol.timeline.get("color").get(0);
if (color != null) color.colorEffect = tint;
}
}
for (symbol in arr)
{
+3 -1
View File
@@ -5,6 +5,7 @@ import funkin.graphics.shaders.MosaicEffect;
import flixel.util.FlxTimer;
import funkin.util.TimerUtil;
@:nullSafety
class Nametag extends FlxSprite
{
@:allow(funkin.ui.charSelect.CharSelectSubState)
@@ -13,7 +14,7 @@ class Nametag extends FlxSprite
var midpointY(default, set):Float = 100;
var mosaicShader:MosaicEffect;
var currentMosaicSequence:Sequence;
var currentMosaicSequence:Null<Sequence>;
public function new(?x:Float = 0, ?y:Float = 0, character:String)
{
@@ -67,6 +68,7 @@ class Nametag extends FlxSprite
// Forcibly reset the shader to prevent overlapping blur sequences
mosaicShader.setBlockSize(1, 1);
currentMosaicSequence.destroy();
@:nullSafety(Off)
currentMosaicSequence = null;
}