512 lines
13 KiB
Haxe
512 lines
13 KiB
Haxe
package editors;
|
|
|
|
import Note;
|
|
import NoteSplash;
|
|
import StrumNote;
|
|
import flixel.addons.ui.FlxInputText;
|
|
import flixel.addons.ui.FlxUINumericStepper;
|
|
|
|
class NoteSplashDebugState extends MusicBeatState
|
|
{
|
|
var config:NoteSplash.NoteSplashConfig;
|
|
var forceFrame:Int = -1;
|
|
var curSelected:Int = 0;
|
|
var maxNotes:Int = 4;
|
|
|
|
var selection:FlxSprite;
|
|
var notes:FlxTypedGroup<StrumNote>;
|
|
var splashes:FlxTypedGroup<FlxSprite>;
|
|
|
|
var imageInputText:FlxInputText;
|
|
var nameInputText:FlxInputText;
|
|
var stepperMinFps:FlxUINumericStepper;
|
|
var stepperMaxFps:FlxUINumericStepper;
|
|
|
|
var offsetsText:FlxText;
|
|
var curFrameText:FlxText;
|
|
var curAnimText:FlxText;
|
|
var savedText:FlxText;
|
|
var selecArr:Array<Float> = null;
|
|
|
|
var missingTextBG:FlxSprite;
|
|
var missingText:FlxText;
|
|
|
|
public static final defaultTexture:String = 'noteSplashes';
|
|
|
|
override function create()
|
|
{
|
|
FlxG.camera.bgColor = FlxColor.fromHSL(0, 0, 0.5);
|
|
selection = new FlxSprite(0, 270).makeGraphic(150, 150, FlxColor.BLACK);
|
|
selection.alpha = 0.4;
|
|
add(selection);
|
|
|
|
notes = new FlxTypedGroup<StrumNote>();
|
|
add(notes);
|
|
|
|
splashes = new FlxTypedGroup<FlxSprite>();
|
|
add(splashes);
|
|
|
|
for (i in 0...maxNotes)
|
|
{
|
|
var x = i * 220 + 240;
|
|
var y = 290;
|
|
var note:StrumNote = new StrumNote(x, y, i, 0);
|
|
note.alpha = 0.75;
|
|
note.playAnim('static');
|
|
notes.add(note);
|
|
|
|
var splash:FlxSprite = new FlxSprite(x, y);
|
|
splash.setPosition(splash.x - Note.swagWidth * 0.95, splash.y - Note.swagWidth);
|
|
splash.shader = note.rgbShader.parent.shader;
|
|
splash.antialiasing = ClientPrefs.globalAntialiasing;
|
|
splashes.add(splash);
|
|
}
|
|
|
|
//
|
|
var txtx = 60;
|
|
var txty = 640;
|
|
|
|
var imageName:FlxText = new FlxText(txtx, txty - 120, 'Image Name:', 16);
|
|
add(imageName);
|
|
|
|
imageInputText = new FlxInputText(txtx, txty - 100, 360, defaultTexture, 16);
|
|
imageInputText.callback = function(text:String, action:String)
|
|
{
|
|
switch (action)
|
|
{
|
|
case 'enter':
|
|
imageInputText.hasFocus = false;
|
|
textureName = text;
|
|
try
|
|
{
|
|
loadFrames();
|
|
}
|
|
catch (e:Dynamic)
|
|
{
|
|
trace('ERROR! $e');
|
|
textureName = defaultTexture;
|
|
loadFrames();
|
|
|
|
missingText.text = 'ERROR WHILE LOADING IMAGE:\n$text';
|
|
missingText.screenCenter(Y);
|
|
missingText.visible = true;
|
|
missingTextBG.visible = true;
|
|
FlxG.sound.play(Paths.sound('cancelMenu'));
|
|
|
|
new FlxTimer().start(2.5, function(tmr:FlxTimer)
|
|
{
|
|
missingText.visible = false;
|
|
missingTextBG.visible = false;
|
|
});
|
|
}
|
|
|
|
default:
|
|
trace('changed image to $text');
|
|
}
|
|
};
|
|
add(imageInputText);
|
|
|
|
var animName:FlxText = new FlxText(txtx, txty, 'Animation Name:', 16);
|
|
add(animName);
|
|
|
|
nameInputText = new FlxInputText(txtx, txty + 20, 360, '', 16);
|
|
nameInputText.callback = function(text:String, action:String)
|
|
{
|
|
switch (action)
|
|
{
|
|
case 'enter':
|
|
nameInputText.hasFocus = false;
|
|
|
|
default:
|
|
trace('changed anim name to $text');
|
|
config.anim = text;
|
|
curAnim = 1;
|
|
reloadAnims();
|
|
}
|
|
};
|
|
add(nameInputText);
|
|
|
|
add(new FlxText(txtx, txty - 50, 0, 'Min/Max Framerate:', 16));
|
|
stepperMinFps = new FlxUINumericStepper(txtx, txty - 30, 1, 22, 1, 60, 0);
|
|
stepperMinFps.name = 'min_fps';
|
|
add(stepperMinFps);
|
|
|
|
stepperMaxFps = new FlxUINumericStepper(txtx + 60, txty - 30, 1, 26, 1, 60, 0);
|
|
stepperMaxFps.name = 'max_fps';
|
|
add(stepperMaxFps);
|
|
|
|
//
|
|
offsetsText = new FlxText(300, 150, 680, '', 16);
|
|
offsetsText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
|
offsetsText.scrollFactor.set();
|
|
add(offsetsText);
|
|
|
|
curFrameText = new FlxText(300, 100, 680, '', 16);
|
|
curFrameText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
|
curFrameText.scrollFactor.set();
|
|
add(curFrameText);
|
|
|
|
curAnimText = new FlxText(300, 50, 680, '', 16);
|
|
curAnimText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
|
curAnimText.scrollFactor.set();
|
|
add(curAnimText);
|
|
|
|
var text:FlxText = new FlxText(0, 520, FlxG.width, "Press SPACE to Reset animation\n
|
|
Press ENTER twice to save to the loaded Note Splash PNG's folder\n
|
|
A/D change selected note - Arrow Keys to change offset (Hold shift for 10x)\n
|
|
Ctrl + C/V - Copy & Paste", 16);
|
|
text.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
|
text.scrollFactor.set();
|
|
add(text);
|
|
|
|
savedText = new FlxText(0, 340, FlxG.width, '', 24);
|
|
savedText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
|
savedText.scrollFactor.set();
|
|
add(savedText);
|
|
|
|
missingTextBG = new FlxSprite().makeGraphic(FlxG.width, FlxG.height, FlxColor.BLACK);
|
|
missingTextBG.alpha = 0.6;
|
|
missingTextBG.visible = false;
|
|
add(missingTextBG);
|
|
|
|
missingText = new FlxText(50, 0, FlxG.width - 100, '', 24);
|
|
missingText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
|
|
missingText.scrollFactor.set();
|
|
missingText.visible = false;
|
|
add(missingText);
|
|
|
|
loadFrames();
|
|
changeSelection();
|
|
super.create();
|
|
FlxG.mouse.visible = true;
|
|
}
|
|
|
|
var curAnim:Int = 1;
|
|
var visibleTime:Float = 0;
|
|
var pressEnterToSave:Float = 0;
|
|
|
|
override function update(elapsed:Float)
|
|
{
|
|
@:privateAccess
|
|
cast(stepperMinFps.text_field, FlxInputText).hasFocus = cast(stepperMaxFps.text_field, FlxInputText).hasFocus = false;
|
|
|
|
var notTyping:Bool = !nameInputText.hasFocus && !imageInputText.hasFocus;
|
|
if (controls.BACK && notTyping)
|
|
{
|
|
FlxG.switchState(new MasterEditorMenu());
|
|
FlxG.sound.playMusic(Paths.music('freakyMenu-' + ClientPrefs.daMenuMusic));
|
|
FlxG.mouse.visible = false;
|
|
}
|
|
super.update(elapsed);
|
|
|
|
if (!notTyping)
|
|
return;
|
|
|
|
if (FlxG.keys.justPressed.A)
|
|
changeSelection(-1);
|
|
else if (FlxG.keys.justPressed.D)
|
|
changeSelection(1);
|
|
|
|
if (maxAnims < 1)
|
|
return;
|
|
|
|
if (selecArr != null)
|
|
{
|
|
var movex = 0;
|
|
var movey = 0;
|
|
if (FlxG.keys.justPressed.LEFT)
|
|
movex = -1;
|
|
else if (FlxG.keys.justPressed.RIGHT)
|
|
movex = 1;
|
|
|
|
if (FlxG.keys.justPressed.UP)
|
|
movey = 1;
|
|
else if (FlxG.keys.justPressed.DOWN)
|
|
movey = -1;
|
|
|
|
if (FlxG.keys.pressed.SHIFT)
|
|
{
|
|
movex *= 10;
|
|
movey *= 10;
|
|
}
|
|
|
|
if (movex != 0 || movey != 0)
|
|
{
|
|
selecArr[0] -= movex;
|
|
selecArr[1] += movey;
|
|
updateOffsetText();
|
|
splashes.members[curSelected].offset.set(10 + selecArr[0], 10 + selecArr[1]);
|
|
}
|
|
}
|
|
|
|
// Copy & Paste
|
|
if (FlxG.keys.pressed.CONTROL)
|
|
{
|
|
if (FlxG.keys.justPressed.C)
|
|
{
|
|
var arr:Array<Float> = selectedArray();
|
|
if (copiedArray == null)
|
|
copiedArray = [0, 0];
|
|
copiedArray[0] = arr[0];
|
|
copiedArray[1] = arr[1];
|
|
}
|
|
else if (FlxG.keys.justPressed.V && copiedArray != null)
|
|
{
|
|
var offs:Array<Float> = selectedArray();
|
|
offs[0] = copiedArray[0];
|
|
offs[1] = copiedArray[1];
|
|
splashes.members[curSelected].offset.set(10 + offs[0], 10 + offs[1]);
|
|
updateOffsetText();
|
|
}
|
|
}
|
|
|
|
// Saving
|
|
pressEnterToSave -= elapsed;
|
|
if (visibleTime >= 0)
|
|
{
|
|
visibleTime -= elapsed;
|
|
if (visibleTime <= 0)
|
|
savedText.visible = false;
|
|
}
|
|
|
|
if (FlxG.keys.justPressed.ENTER)
|
|
{
|
|
savedText.text = 'Press ENTER again to save.';
|
|
if (pressEnterToSave > 0) // save
|
|
{
|
|
saveFile();
|
|
FlxG.sound.play(Paths.sound('confirmMenu'), 0.4);
|
|
pressEnterToSave = 0;
|
|
visibleTime = 3;
|
|
}
|
|
else
|
|
{
|
|
pressEnterToSave = 0.5;
|
|
visibleTime = 0.5;
|
|
}
|
|
savedText.visible = true;
|
|
}
|
|
|
|
// Reset anim & change anim
|
|
if (FlxG.keys.justPressed.SPACE)
|
|
changeAnim();
|
|
else if (FlxG.keys.justPressed.S)
|
|
changeAnim(-1);
|
|
else if (FlxG.keys.justPressed.W)
|
|
changeAnim(1);
|
|
|
|
// Force frame
|
|
var updatedFrame:Bool = false;
|
|
if (updatedFrame = FlxG.keys.justPressed.Q)
|
|
forceFrame--;
|
|
else if (updatedFrame = FlxG.keys.justPressed.E)
|
|
forceFrame++;
|
|
|
|
if (updatedFrame)
|
|
{
|
|
if (forceFrame < 0)
|
|
forceFrame = 0;
|
|
else if (forceFrame >= maxFrame)
|
|
forceFrame = maxFrame - 1;
|
|
// trace('curFrame: $forceFrame');
|
|
|
|
curFrameText.text = 'Force Frame: ${forceFrame + 1} / $maxFrame\n(Press Q/E to change)';
|
|
splashes.forEachAlive(function(spr:FlxSprite)
|
|
{
|
|
spr.animation.curAnim.paused = true;
|
|
spr.animation.curAnim.curFrame = forceFrame;
|
|
});
|
|
}
|
|
}
|
|
|
|
function updateOffsetText()
|
|
{
|
|
selecArr = selectedArray();
|
|
offsetsText.text = selecArr.toString();
|
|
}
|
|
|
|
var textureName:String = defaultTexture;
|
|
var texturePath:String = '';
|
|
var copiedArray:Array<Float> = null;
|
|
|
|
function loadFrames()
|
|
{
|
|
texturePath = 'noteSplashes/' + textureName;
|
|
splashes.forEachAlive(function(spr:FlxSprite)
|
|
{
|
|
spr.frames = Paths.getSparrowAtlas(texturePath);
|
|
});
|
|
|
|
// Initialize config
|
|
Paths.splashConfigs.clear();
|
|
if (!Paths.splashConfigs.exists(textureName))
|
|
Paths.initSplashConfig(textureName);
|
|
config = Paths.splashConfigs.get(textureName);
|
|
trace(config);
|
|
if (config == null)
|
|
config = Paths.initSplashConfig('noteSplashes');
|
|
nameInputText.text = (config.anim.length > 0 && config.anim != null ? config.anim : 'note splash');
|
|
stepperMinFps.value = (!Math.isNaN(config.minFps) ? config.minFps : 22);
|
|
stepperMaxFps.value = !Math.isNaN(config.maxFps) ? config.maxFps : 26;
|
|
//
|
|
|
|
reloadAnims();
|
|
}
|
|
|
|
function saveFile()
|
|
{
|
|
#if sys
|
|
var maxLen:Int = maxAnims * Note.colArray.length;
|
|
var curLen:Int = config.offsets.length;
|
|
while (curLen > maxLen)
|
|
{
|
|
config.offsets.pop();
|
|
curLen = config.offsets.length;
|
|
}
|
|
|
|
var strToSave = config.anim + '\n' + config.minFps + ' ' + config.maxFps;
|
|
for (offGroup in config.offsets)
|
|
strToSave += '\n' + offGroup[0] + ' ' + offGroup[1];
|
|
|
|
var pathSplit:Array<String> = (Paths.getPath('images/$texturePath.png', IMAGE, null, true).split('.png')[0] + '.txt').split(':');
|
|
var path:String = pathSplit[pathSplit.length - 1];
|
|
savedText.text = 'Saved to: $path';
|
|
trace('$path');
|
|
File.saveContent(path, strToSave);
|
|
|
|
// trace(strToSave);
|
|
#else
|
|
savedText.text = 'Can\'t save on this platform, too bad.';
|
|
#end
|
|
}
|
|
|
|
override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>)
|
|
{
|
|
if (id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper))
|
|
{
|
|
var nums:FlxUINumericStepper = cast sender;
|
|
var wname = nums.name;
|
|
switch (wname)
|
|
{
|
|
case 'min_fps':
|
|
if (nums.value > stepperMaxFps.value)
|
|
stepperMaxFps.value = nums.value;
|
|
case 'max_fps':
|
|
if (nums.value < stepperMinFps.value)
|
|
stepperMinFps.value = nums.value;
|
|
}
|
|
config.minFps = Std.int(stepperMinFps.value);
|
|
config.maxFps = Std.int(stepperMaxFps.value);
|
|
}
|
|
}
|
|
|
|
var maxAnims:Int = 0;
|
|
|
|
function reloadAnims()
|
|
{
|
|
var loopContinue:Bool = true;
|
|
splashes.forEachAlive(function(spr:FlxSprite)
|
|
{
|
|
spr.animation.destroyAnimations();
|
|
});
|
|
|
|
maxAnims = 0;
|
|
while (loopContinue)
|
|
{
|
|
var animID:Int = maxAnims + 1;
|
|
splashes.forEachAlive(function(spr:FlxSprite)
|
|
{
|
|
for (i in 0...Note.colArray.length)
|
|
{
|
|
var animName = 'note$i-$animID';
|
|
if (!addAnimAndCheck(spr, animName, '${config.anim} ${Note.colArray[i]} $animID', 24, false))
|
|
{
|
|
loopContinue = false;
|
|
return;
|
|
}
|
|
spr.animation.play(animName, true);
|
|
}
|
|
});
|
|
if (loopContinue)
|
|
maxAnims++;
|
|
}
|
|
trace('maxAnims: $maxAnims');
|
|
changeAnim();
|
|
}
|
|
|
|
var maxFrame:Int = 0;
|
|
|
|
function changeAnim(change:Int = 0)
|
|
{
|
|
maxFrame = 0;
|
|
forceFrame = -1;
|
|
if (maxAnims > 0)
|
|
{
|
|
curAnim += change;
|
|
if (curAnim > maxAnims)
|
|
curAnim = 1;
|
|
else if (curAnim < 1)
|
|
curAnim = maxAnims;
|
|
|
|
curAnimText.text = 'Current Animation: $curAnim / $maxAnims\n(Press W/S to change)';
|
|
curFrameText.text = 'Force Frame Disabled\n(Press Q/E to change)';
|
|
|
|
for (i in 0...maxNotes)
|
|
{
|
|
var spr:FlxSprite = splashes.members[i];
|
|
spr.animation.play('note$i-$curAnim', true);
|
|
|
|
if (maxFrame < spr.animation.curAnim.numFrames)
|
|
maxFrame = spr.animation.curAnim.numFrames;
|
|
|
|
spr.animation.curAnim.frameRate = FlxG.random.int(config.minFps, config.maxFps);
|
|
var offs:Array<Float> = selectedArray(i);
|
|
spr.offset.set(10 + offs[0], 10 + offs[1]);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
curAnimText.text = 'INVALID ANIMATION NAME';
|
|
curFrameText.text = '';
|
|
}
|
|
updateOffsetText();
|
|
}
|
|
|
|
function changeSelection(change:Int = 0)
|
|
{
|
|
var max:Int = Note.colArray.length;
|
|
curSelected += change;
|
|
if (curSelected < 0)
|
|
curSelected = max - 1;
|
|
else if (curSelected >= max)
|
|
curSelected = 0;
|
|
|
|
selection.x = curSelected * 220 + 220;
|
|
updateOffsetText();
|
|
}
|
|
|
|
function selectedArray(sel:Int = -1)
|
|
{
|
|
if (sel < 0)
|
|
sel = curSelected;
|
|
var animID:Int = sel + ((curAnim - 1) * Note.colArray.length);
|
|
if (config.offsets[animID] == null)
|
|
{
|
|
while (config.offsets[animID] == null)
|
|
config.offsets.push(config.offsets[FlxMath.wrap(animID, 0, config.offsets.length - 1)].copy());
|
|
}
|
|
return config.offsets[FlxMath.wrap(animID, 0, config.offsets.length - 1)];
|
|
}
|
|
|
|
function addAnimAndCheck(spr:FlxSprite, name:String, anim:String, ?framerate:Int = 24, ?loop:Bool = false)
|
|
{
|
|
spr.animation.addByPrefix(name, anim, framerate, loop);
|
|
return spr.animation.getByName(name) != null;
|
|
}
|
|
|
|
override function destroy()
|
|
{
|
|
super.destroy();
|
|
}
|
|
}
|