init commit

This commit is contained in:
Return0ne 2021-11-05 17:34:27 -04:00
commit 322d1a0516
1054 changed files with 85998 additions and 0 deletions

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,779 @@
package editors;
#if desktop
import Discord.DiscordClient;
#end
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.addons.display.FlxGridOverlay;
import flixel.addons.transition.FlxTransitionableState;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.util.FlxColor;
import flixel.system.FlxSound;
import flixel.addons.ui.FlxInputText;
import flixel.addons.ui.FlxUI9SliceSprite;
import flixel.addons.ui.FlxUI;
import flixel.addons.ui.FlxUICheckBox;
import flixel.addons.ui.FlxUIInputText;
import flixel.addons.ui.FlxUINumericStepper;
import flixel.addons.ui.FlxUITabMenu;
import flixel.ui.FlxButton;
import openfl.net.FileReference;
import openfl.events.Event;
import openfl.events.IOErrorEvent;
import flash.net.FileFilter;
import haxe.Json;
import DialogueBoxPsych;
import flixel.FlxCamera;
import flixel.group.FlxSpriteGroup;
import lime.system.Clipboard;
#if sys
import sys.io.File;
#end
using StringTools;
class DialogueCharacterEditorState extends MusicBeatState
{
var box:FlxSprite;
var daText:Alphabet = null;
private static var TIP_TEXT_MAIN:String =
'JKLI - Move camera (Hold Shift to move 4x faster)
\nQ/E - Zoom out/in
\nR - Reset Camera
\nH - Toggle Speech Bubble
\nSpace - Reset text';
private static var TIP_TEXT_OFFSET:String =
'JKLI - Move camera (Hold Shift to move 4x faster)
\nQ/E - Zoom out/in
\nR - Reset Camera
\nH - Toggle Ghosts
\nWASD - Move Looping animation offset (Red)
\nArrow Keys - Move Idle/Finished animation offset (Blue)
\nHold Shift to move offsets 10x faster';
var tipText:FlxText;
var offsetLoopText:FlxText;
var offsetIdleText:FlxText;
var camGame:FlxCamera;
var camOther:FlxCamera;
var mainGroup:FlxSpriteGroup;
var hudGroup:FlxSpriteGroup;
var character:DialogueCharacter;
var ghostLoop:DialogueCharacter;
var ghostIdle:DialogueCharacter;
override function create() {
persistentUpdate = persistentDraw = true;
camGame = new FlxCamera();
camOther = new FlxCamera();
camGame.bgColor = FlxColor.fromHSL(0, 0, 0.5);
camOther.bgColor.alpha = 0;
FlxG.cameras.reset(camGame);
FlxG.cameras.add(camOther);
FlxCamera.defaultCameras = [camOther];
mainGroup = new FlxSpriteGroup();
mainGroup.cameras = [camGame];
hudGroup = new FlxSpriteGroup();
hudGroup.cameras = [camGame];
add(mainGroup);
add(hudGroup);
character = new DialogueCharacter();
character.scrollFactor.set();
mainGroup.add(character);
ghostLoop = new DialogueCharacter();
ghostLoop.alpha = 0;
ghostLoop.color = FlxColor.RED;
ghostLoop.isGhost = true;
ghostLoop.jsonFile = character.jsonFile;
ghostLoop.cameras = [camGame];
add(ghostLoop);
ghostIdle = new DialogueCharacter();
ghostIdle.alpha = 0;
ghostIdle.color = FlxColor.BLUE;
ghostIdle.isGhost = true;
ghostIdle.jsonFile = character.jsonFile;
ghostIdle.cameras = [camGame];
add(ghostIdle);
box = new FlxSprite(70, 370);
box.frames = Paths.getSparrowAtlas('speech_bubble');
box.scrollFactor.set();
box.antialiasing = ClientPrefs.globalAntialiasing;
box.animation.addByPrefix('normal', 'speech bubble normal', 24);
box.animation.addByPrefix('center', 'speech bubble middle', 24);
box.animation.play('normal', true);
box.setGraphicSize(Std.int(box.width * 0.9));
box.updateHitbox();
hudGroup.add(box);
tipText = new FlxText(10, 10, FlxG.width - 20, TIP_TEXT_MAIN, 8);
tipText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, RIGHT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
tipText.cameras = [camOther];
tipText.scrollFactor.set();
add(tipText);
offsetLoopText = new FlxText(10, 10, 0, '', 32);
offsetLoopText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
offsetLoopText.cameras = [camOther];
offsetLoopText.scrollFactor.set();
add(offsetLoopText);
offsetLoopText.visible = false;
offsetIdleText = new FlxText(10, 46, 0, '', 32);
offsetIdleText.setFormat(Paths.font("vcr.ttf"), 32, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
offsetIdleText.cameras = [camOther];
offsetIdleText.scrollFactor.set();
add(offsetIdleText);
offsetIdleText.visible = false;
reloadCharacter();
updateTextBox();
reloadText();
addEditorBox();
FlxG.mouse.visible = true;
updateCharTypeBox();
super.create();
}
var UI_typebox:FlxUITabMenu;
var UI_mainbox:FlxUITabMenu;
function addEditorBox() {
var tabs = [
{name: 'Character Type', label: 'Character Type'},
];
UI_typebox = new FlxUITabMenu(null, tabs, true);
UI_typebox.resize(120, 180);
UI_typebox.x = 900;
UI_typebox.y = FlxG.height - UI_typebox.height - 50;
UI_typebox.scrollFactor.set();
UI_typebox.camera = camGame;
addTypeUI();
add(UI_typebox);
var tabs = [
{name: 'Animations', label: 'Animations'},
{name: 'Character', label: 'Character'},
];
UI_mainbox = new FlxUITabMenu(null, tabs, true);
UI_mainbox.resize(200, 250);
UI_mainbox.x = UI_typebox.x + UI_typebox.width;
UI_mainbox.y = FlxG.height - UI_mainbox.height - 50;
UI_mainbox.scrollFactor.set();
UI_mainbox.camera = camGame;
addAnimationsUI();
addCharacterUI();
add(UI_mainbox);
UI_mainbox.selected_tab_id = 'Character';
lastTab = UI_mainbox.selected_tab_id;
}
var leftCheckbox:FlxUICheckBox;
var centerCheckbox:FlxUICheckBox;
var rightCheckbox:FlxUICheckBox;
function addTypeUI() {
var tab_group = new FlxUI(null, UI_typebox);
tab_group.name = "Character Type";
leftCheckbox = new FlxUICheckBox(10, 20, null, null, "Left", 100);
leftCheckbox.callback = function()
{
character.jsonFile.dialogue_pos = 'left';
updateCharTypeBox();
};
centerCheckbox = new FlxUICheckBox(leftCheckbox.x, leftCheckbox.y + 40, null, null, "Center", 100);
centerCheckbox.callback = function()
{
character.jsonFile.dialogue_pos = 'center';
updateCharTypeBox();
};
rightCheckbox = new FlxUICheckBox(centerCheckbox.x, centerCheckbox.y + 40, null, null, "Right", 100);
rightCheckbox.callback = function()
{
character.jsonFile.dialogue_pos = 'right';
updateCharTypeBox();
};
tab_group.add(leftCheckbox);
tab_group.add(centerCheckbox);
tab_group.add(rightCheckbox);
UI_typebox.addGroup(tab_group);
}
var curSelectedAnim:String;
var animationArray:Array<String> = [];
var animationDropDown:FlxUIDropDownMenuCustom;
var animationInputText:FlxUIInputText;
var loopInputText:FlxUIInputText;
var idleInputText:FlxUIInputText;
function addAnimationsUI() {
var tab_group = new FlxUI(null, UI_mainbox);
tab_group.name = "Animations";
animationDropDown = new FlxUIDropDownMenuCustom(10, 30, FlxUIDropDownMenuCustom.makeStrIdLabelArray([''], true), function(animation:String) {
var anim:String = animationArray[Std.parseInt(animation)];
if(character.dialogueAnimations.exists(anim)) {
ghostLoop.playAnim(anim);
ghostIdle.playAnim(anim, true);
curSelectedAnim = anim;
var animShit:DialogueAnimArray = character.dialogueAnimations.get(curSelectedAnim);
offsetLoopText.text = 'Loop: ' + animShit.loop_offsets;
offsetIdleText.text = 'Idle: ' + animShit.idle_offsets;
animationInputText.text = animShit.anim;
loopInputText.text = animShit.loop_name;
idleInputText.text = animShit.idle_name;
}
});
animationInputText = new FlxUIInputText(15, 85, 80, '', 8);
blockPressWhileTypingOn.push(animationInputText);
loopInputText = new FlxUIInputText(animationInputText.x, animationInputText.y + 35, 150, '', 8);
blockPressWhileTypingOn.push(loopInputText);
idleInputText = new FlxUIInputText(loopInputText.x, loopInputText.y + 40, 150, '', 8);
blockPressWhileTypingOn.push(idleInputText);
var addUpdateButton:FlxButton = new FlxButton(10, idleInputText.y + 30, "Add/Update", function() {
var theAnim:String = animationInputText.text.trim();
if(character.dialogueAnimations.exists(theAnim)) //Update
{
for (i in 0...character.jsonFile.animations.length) {
var animArray:DialogueAnimArray = character.jsonFile.animations[i];
if(animArray.anim.trim() == theAnim) {
animArray.loop_name = loopInputText.text;
animArray.idle_name = idleInputText.text;
break;
}
}
character.reloadAnimations();
ghostLoop.reloadAnimations();
ghostIdle.reloadAnimations();
if(curSelectedAnim == theAnim) {
ghostLoop.playAnim(theAnim);
ghostIdle.playAnim(theAnim, true);
}
}
else //Add
{
var newAnim:DialogueAnimArray = {
anim: theAnim,
loop_name: loopInputText.text,
loop_offsets: [0, 0],
idle_name: idleInputText.text,
idle_offsets: [0, 0]
}
character.jsonFile.animations.push(newAnim);
var lastSelected:String = animationDropDown.selectedLabel;
character.reloadAnimations();
ghostLoop.reloadAnimations();
ghostIdle.reloadAnimations();
reloadAnimationsDropDown();
animationDropDown.selectedLabel = lastSelected;
}
});
var removeUpdateButton:FlxButton = new FlxButton(100, addUpdateButton.y, "Remove", function() {
for (i in 0...character.jsonFile.animations.length) {
var animArray:DialogueAnimArray = character.jsonFile.animations[i];
if(animArray != null && animArray.anim.trim() == animationInputText.text.trim()) {
var lastSelected:String = animationDropDown.selectedLabel;
character.jsonFile.animations.remove(animArray);
character.reloadAnimations();
ghostLoop.reloadAnimations();
ghostIdle.reloadAnimations();
reloadAnimationsDropDown();
if(character.jsonFile.animations.length > 0 && lastSelected == animArray.anim.trim()) {
var animToPlay:String = character.jsonFile.animations[0].anim;
ghostLoop.playAnim(animToPlay);
ghostIdle.playAnim(animToPlay, true);
}
animationDropDown.selectedLabel = lastSelected;
animationInputText.text = '';
loopInputText.text = '';
idleInputText.text = '';
break;
}
}
});
tab_group.add(new FlxText(animationDropDown.x, animationDropDown.y - 18, 0, 'Animations:'));
tab_group.add(new FlxText(animationInputText.x, animationInputText.y - 18, 0, 'Animation name:'));
tab_group.add(new FlxText(loopInputText.x, loopInputText.y - 18, 0, 'Loop name on .XML file:'));
tab_group.add(new FlxText(idleInputText.x, idleInputText.y - 18, 0, 'Idle/Finished name on .XML file:'));
tab_group.add(animationInputText);
tab_group.add(loopInputText);
tab_group.add(idleInputText);
tab_group.add(addUpdateButton);
tab_group.add(removeUpdateButton);
tab_group.add(animationDropDown);
UI_mainbox.addGroup(tab_group);
reloadAnimationsDropDown();
}
function reloadAnimationsDropDown() {
animationArray = [];
for (anim in character.jsonFile.animations) {
animationArray.push(anim.anim);
}
if(animationArray.length < 1) animationArray = [''];
animationDropDown.setData(FlxUIDropDownMenuCustom.makeStrIdLabelArray(animationArray, true));
}
var imageInputText:FlxUIInputText;
var scaleStepper:FlxUINumericStepper;
var xStepper:FlxUINumericStepper;
var yStepper:FlxUINumericStepper;
var blockPressWhileTypingOn:Array<FlxUIInputText> = [];
function addCharacterUI() {
var tab_group = new FlxUI(null, UI_mainbox);
tab_group.name = "Character";
imageInputText = new FlxUIInputText(10, 30, 80, character.jsonFile.image, 8);
blockPressWhileTypingOn.push(imageInputText);
xStepper = new FlxUINumericStepper(imageInputText.x, imageInputText.y + 50, 10, character.jsonFile.position[0], -2000, 2000, 0);
yStepper = new FlxUINumericStepper(imageInputText.x + 80, xStepper.y, 10, character.jsonFile.position[1], -2000, 2000, 0);
scaleStepper = new FlxUINumericStepper(imageInputText.x, xStepper.y + 50, 0.05, character.jsonFile.scale, 0.1, 10, 2);
tab_group.add(new FlxText(10, imageInputText.y - 18, 0, 'Image file name:'));
tab_group.add(new FlxText(10, xStepper.y - 18, 0, 'Position Offset:'));
tab_group.add(new FlxText(10, scaleStepper.y - 18, 0, 'Scale:'));
tab_group.add(imageInputText);
tab_group.add(xStepper);
tab_group.add(yStepper);
tab_group.add(scaleStepper);
var reloadImageButton:FlxButton = new FlxButton(10, scaleStepper.y + 60, "Reload Image", function() {
reloadCharacter();
});
var loadButton:FlxButton = new FlxButton(reloadImageButton.x + 100, reloadImageButton.y, "Load Character", function() {
loadCharacter();
});
var saveButton:FlxButton = new FlxButton(loadButton.x, reloadImageButton.y - 30, "Save Character", function() {
saveCharacter();
});
tab_group.add(reloadImageButton);
tab_group.add(loadButton);
tab_group.add(saveButton);
UI_mainbox.addGroup(tab_group);
}
function updateCharTypeBox() {
leftCheckbox.checked = false;
centerCheckbox.checked = false;
rightCheckbox.checked = false;
switch(character.jsonFile.dialogue_pos) {
case 'left':
leftCheckbox.checked = true;
case 'center':
centerCheckbox.checked = true;
case 'right':
rightCheckbox.checked = true;
}
reloadCharacter();
updateTextBox();
}
private static var DEFAULT_TEXT:String = 'Lorem ipsum dolor sit amet';
function reloadText() {
if(daText != null) {
daText.killTheTimer();
daText.kill();
hudGroup.remove(daText);
daText.destroy();
}
daText = new Alphabet(0, 0, DEFAULT_TEXT, false, true, 0.05, 0.7);
daText.x = DialogueBoxPsych.DEFAULT_TEXT_X;
daText.y = DialogueBoxPsych.DEFAULT_TEXT_Y;
hudGroup.add(daText);
}
function reloadCharacter() {
var charsArray:Array<DialogueCharacter> = [character, ghostLoop, ghostIdle];
for (char in charsArray) {
char.frames = Paths.getSparrowAtlas('dialogue/' + character.jsonFile.image);
char.jsonFile = character.jsonFile;
char.reloadAnimations();
char.setGraphicSize(Std.int(char.width * DialogueCharacter.DEFAULT_SCALE * character.jsonFile.scale));
char.updateHitbox();
}
character.x = DialogueBoxPsych.LEFT_CHAR_X;
character.y = DialogueBoxPsych.DEFAULT_CHAR_Y;
switch(character.jsonFile.dialogue_pos) {
case 'right':
character.x = FlxG.width - character.width + DialogueBoxPsych.RIGHT_CHAR_X;
case 'center':
character.x = FlxG.width / 2;
character.x -= character.width / 2;
}
character.x += character.jsonFile.position[0] + mainGroup.x;
character.y += character.jsonFile.position[1] + mainGroup.y;
character.playAnim(); //Plays random animation
if(character.jsonFile.animations.length > 0) {
curSelectedAnim = character.jsonFile.animations[0].anim;
var animShit:DialogueAnimArray = character.dialogueAnimations.get(curSelectedAnim);
ghostLoop.playAnim(animShit.anim);
ghostIdle.playAnim(animShit.anim, true);
offsetLoopText.text = 'Loop: ' + animShit.loop_offsets;
offsetIdleText.text = 'Idle: ' + animShit.idle_offsets;
}
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("Dialogue Character Editor", "Editting: " + character.jsonFile.image);
#end
}
function updateTextBox() {
box.flipX = false;
var anim:String = 'normal';
switch(character.jsonFile.dialogue_pos) {
case 'left':
box.flipX = true;
case 'center':
anim = 'center';
}
box.animation.play(anim, true);
DialogueBoxPsych.updateBoxOffsets(box);
}
override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>) {
if(id == FlxUIInputText.CHANGE_EVENT && sender == imageInputText) {
character.jsonFile.image = imageInputText.text;
} else if(id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper)) {
if(sender == scaleStepper) {
character.jsonFile.scale = scaleStepper.value;
reloadCharacter();
} else if(sender == xStepper) {
character.jsonFile.position[0] = xStepper.value;
reloadCharacter();
} else if(sender == yStepper) {
character.jsonFile.position[1] = yStepper.value;
reloadCharacter();
}
}
}
var currentGhosts:Int = 0;
var lastTab:String = 'Character';
var transitioning:Bool = false;
override function update(elapsed:Float) {
if(transitioning) {
super.update(elapsed);
return;
}
if(character.animation.curAnim != null) {
if(daText.finishedText) {
if(character.animationIsLoop()) {
character.playAnim(character.animation.curAnim.name, true);
}
} else if(character.animation.curAnim.finished) {
character.animation.curAnim.restart();
}
}
var blockInput:Bool = false;
for (inputText in blockPressWhileTypingOn) {
if(inputText.hasFocus) {
FlxG.sound.muteKeys = [];
FlxG.sound.volumeDownKeys = [];
FlxG.sound.volumeUpKeys = [];
blockInput = true;
if(FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.V && Clipboard.text != null) { //Copy paste
inputText.text = ClipboardAdd(inputText.text);
inputText.caretIndex = inputText.text.length;
getEvent(FlxUIInputText.CHANGE_EVENT, inputText, null, []);
}
if(FlxG.keys.justPressed.ENTER) inputText.hasFocus = false;
break;
}
}
if(!blockInput && !animationDropDown.dropPanel.visible) {
FlxG.sound.muteKeys = TitleState.muteKeys;
FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys;
FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys;
if(FlxG.keys.justPressed.SPACE && UI_mainbox.selected_tab_id == 'Character') {
character.playAnim();
updateTextBox();
reloadText();
}
//lots of Ifs lol get trolled
var offsetAdd:Int = 1;
var speed:Float = 300;
if(FlxG.keys.pressed.SHIFT) {
speed = 1200;
offsetAdd = 10;
}
var negaMult:Array<Int> = [1, 1, -1, -1];
var controlArray:Array<Bool> = [FlxG.keys.pressed.J, FlxG.keys.pressed.I, FlxG.keys.pressed.L, FlxG.keys.pressed.K];
for (i in 0...controlArray.length) {
if(controlArray[i]) {
if(i % 2 == 1) {
mainGroup.y += speed * elapsed * negaMult[i];
} else {
mainGroup.x += speed * elapsed * negaMult[i];
}
}
}
if(UI_mainbox.selected_tab_id == 'Animations' && curSelectedAnim != null && character.dialogueAnimations.exists(curSelectedAnim)) {
var moved:Bool = false;
var animShit:DialogueAnimArray = character.dialogueAnimations.get(curSelectedAnim);
var controlArrayLoop:Array<Bool> = [FlxG.keys.justPressed.A, FlxG.keys.justPressed.W, FlxG.keys.justPressed.D, FlxG.keys.justPressed.S];
var controlArrayIdle:Array<Bool> = [FlxG.keys.justPressed.LEFT, FlxG.keys.justPressed.UP, FlxG.keys.justPressed.RIGHT, FlxG.keys.justPressed.DOWN];
for (i in 0...controlArrayLoop.length) {
if(controlArrayLoop[i]) {
if(i % 2 == 1) {
animShit.loop_offsets[1] += offsetAdd * negaMult[i];
} else {
animShit.loop_offsets[0] += offsetAdd * negaMult[i];
}
moved = true;
}
}
for (i in 0...controlArrayIdle.length) {
if(controlArrayIdle[i]) {
if(i % 2 == 1) {
animShit.idle_offsets[1] += offsetAdd * negaMult[i];
} else {
animShit.idle_offsets[0] += offsetAdd * negaMult[i];
}
moved = true;
}
}
if(moved) {
offsetLoopText.text = 'Loop: ' + animShit.loop_offsets;
offsetIdleText.text = 'Idle: ' + animShit.idle_offsets;
ghostLoop.offset.set(animShit.loop_offsets[0], animShit.loop_offsets[1]);
ghostIdle.offset.set(animShit.idle_offsets[0], animShit.idle_offsets[1]);
}
}
if (FlxG.keys.pressed.Q && camGame.zoom > 0.1) {
camGame.zoom -= elapsed * camGame.zoom;
if(camGame.zoom < 0.1) camGame.zoom = 0.1;
}
if (FlxG.keys.pressed.E && camGame.zoom < 1) {
camGame.zoom += elapsed * camGame.zoom;
if(camGame.zoom > 1) camGame.zoom = 1;
}
if(FlxG.keys.justPressed.H) {
if(UI_mainbox.selected_tab_id == 'Animations') {
currentGhosts++;
if(currentGhosts > 2) currentGhosts = 0;
ghostLoop.visible = (currentGhosts != 1);
ghostIdle.visible = (currentGhosts != 2);
ghostLoop.alpha = (currentGhosts == 2 ? 1 : 0.6);
ghostIdle.alpha = (currentGhosts == 1 ? 1 : 0.6);
} else {
hudGroup.visible = !hudGroup.visible;
}
}
if(FlxG.keys.justPressed.R) {
camGame.zoom = 1;
mainGroup.setPosition(0, 0);
hudGroup.visible = true;
}
if(UI_mainbox.selected_tab_id != lastTab) {
if(UI_mainbox.selected_tab_id == 'Animations') {
hudGroup.alpha = 0;
mainGroup.alpha = 0;
ghostLoop.alpha = 0.6;
ghostIdle.alpha = 0.6;
tipText.text = TIP_TEXT_OFFSET;
offsetLoopText.visible = true;
offsetIdleText.visible = true;
currentGhosts = 0;
} else {
hudGroup.alpha = 1;
mainGroup.alpha = 1;
ghostLoop.alpha = 0;
ghostIdle.alpha = 0;
tipText.text = TIP_TEXT_MAIN;
offsetLoopText.visible = false;
offsetIdleText.visible = false;
character.playAnim();
updateTextBox();
reloadText();
}
lastTab = UI_mainbox.selected_tab_id;
currentGhosts = 0;
}
if(FlxG.keys.justPressed.ESCAPE) {
MusicBeatState.switchState(new editors.MasterEditorMenu());
FlxG.sound.playMusic(Paths.music('freakyMenu'), 1);
transitioning = true;
}
ghostLoop.setPosition(character.x, character.y);
ghostIdle.setPosition(character.x, character.y);
hudGroup.x = mainGroup.x;
hudGroup.y = mainGroup.y;
}
super.update(elapsed);
}
var _file:FileReference = null;
function loadCharacter() {
var jsonFilter:FileFilter = new FileFilter('JSON', 'json');
_file = new FileReference();
_file.addEventListener(Event.SELECT, onLoadComplete);
_file.addEventListener(Event.CANCEL, onLoadCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file.browse([jsonFilter]);
}
function onLoadComplete(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
#if sys
var fullPath:String = null;
var jsonLoaded = cast Json.parse(Json.stringify(_file)); //Exploit(???) for accessing a private variable
if(jsonLoaded.__path != null) fullPath = jsonLoaded.__path; //I'm either a genious or dangerously dumb
if(fullPath != null) {
var rawJson:String = File.getContent(fullPath);
if(rawJson != null) {
var loadedChar:DialogueCharacterFile = cast Json.parse(rawJson);
if(loadedChar.dialogue_pos != null) //Make sure it's really a dialogue character
{
var cutName:String = _file.name.substr(0, _file.name.length - 5);
trace("Successfully loaded file: " + cutName);
character.jsonFile = loadedChar;
reloadCharacter();
reloadAnimationsDropDown();
updateCharTypeBox();
updateTextBox();
reloadText();
imageInputText.text = character.jsonFile.image;
scaleStepper.value = character.jsonFile.scale;
xStepper.value = character.jsonFile.position[0];
yStepper.value = character.jsonFile.position[1];
_file = null;
return;
}
}
}
_file = null;
#else
trace("File couldn't be loaded! You aren't on Desktop, are you?");
#end
}
/**
* Called when the save file dialog is cancelled.
*/
function onLoadCancel(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Cancelled file loading.");
}
/**
* Called if there is an error while saving the gameplay recording.
*/
function onLoadError(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Problem loading file");
}
function saveCharacter() {
var data:String = Json.stringify(character.jsonFile, "\t");
if (data.length > 0)
{
var splittedImage:Array<String> = imageInputText.text.trim().split('_');
var characterName:String = splittedImage[0].toLowerCase().replace(' ', '');
_file = new FileReference();
_file.addEventListener(Event.COMPLETE, onSaveComplete);
_file.addEventListener(Event.CANCEL, onSaveCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file.save(data, characterName + ".json");
}
}
function onSaveComplete(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.notice("Successfully saved file.");
}
/**
* Called when the save file dialog is cancelled.
*/
function onSaveCancel(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
}
/**
* Called if there is an error while saving the gameplay recording.
*/
function onSaveError(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.error("Problem saving file");
}
function ClipboardAdd(prefix:String = ''):String {
if(prefix.toLowerCase().endsWith('v')) //probably copy paste attempt
{
prefix = prefix.substring(0, prefix.length-1);
}
var text:String = prefix + Clipboard.text.replace('\n', '');
return text;
}
}

View file

@ -0,0 +1,546 @@
package editors;
#if desktop
import Discord.DiscordClient;
#end
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.addons.display.FlxGridOverlay;
import flixel.addons.transition.FlxTransitionableState;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.util.FlxColor;
import flixel.system.FlxSound;
import flixel.addons.ui.FlxInputText;
import flixel.addons.ui.FlxUI9SliceSprite;
import flixel.addons.ui.FlxUI;
import flixel.addons.ui.FlxUICheckBox;
import flixel.addons.ui.FlxUIInputText;
import flixel.addons.ui.FlxUINumericStepper;
import flixel.addons.ui.FlxUITabMenu;
import flixel.ui.FlxButton;
import openfl.net.FileReference;
import openfl.events.Event;
import openfl.events.IOErrorEvent;
import flash.net.FileFilter;
import haxe.Json;
import DialogueBoxPsych;
import lime.system.Clipboard;
#if sys
import sys.io.File;
#end
using StringTools;
class DialogueEditorState extends MusicBeatState
{
var character:DialogueCharacter;
var box:FlxSprite;
var daText:Alphabet;
var selectedText:FlxText;
var animText:FlxText;
var defaultLine:DialogueLine;
var dialogueFile:DialogueFile = null;
override function create() {
persistentUpdate = persistentDraw = true;
FlxG.camera.bgColor = FlxColor.fromHSL(0, 0, 0.5);
defaultLine = {
portrait: DialogueCharacter.DEFAULT_CHARACTER,
expression: 'talk',
text: DEFAULT_TEXT,
boxState: DEFAULT_BUBBLETYPE,
speed: 0.05
};
dialogueFile = {
dialogue: [
copyDefaultLine()
]
};
character = new DialogueCharacter();
character.scrollFactor.set();
add(character);
box = new FlxSprite(70, 370);
box.frames = Paths.getSparrowAtlas('speech_bubble');
box.scrollFactor.set();
box.antialiasing = ClientPrefs.globalAntialiasing;
box.animation.addByPrefix('normal', 'speech bubble normal', 24);
box.animation.addByPrefix('angry', 'AHH speech bubble', 24);
box.animation.addByPrefix('center', 'speech bubble middle', 24);
box.animation.addByPrefix('center-angry', 'AHH Speech Bubble middle', 24);
box.animation.play('normal', true);
box.setGraphicSize(Std.int(box.width * 0.9));
box.updateHitbox();
add(box);
addEditorBox();
FlxG.mouse.visible = true;
var addLineText:FlxText = new FlxText(10, 10, FlxG.width - 20, 'Press O to remove the current dialogue line, Press P to add another line after the current one.', 8);
addLineText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
addLineText.scrollFactor.set();
add(addLineText);
selectedText = new FlxText(10, 32, FlxG.width - 20, '', 8);
selectedText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
selectedText.scrollFactor.set();
add(selectedText);
animText = new FlxText(10, 62, FlxG.width - 20, '', 8);
animText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
animText.scrollFactor.set();
add(animText);
changeText();
super.create();
}
var UI_box:FlxUITabMenu;
function addEditorBox() {
var tabs = [
{name: 'Dialogue Line', label: 'Dialogue Line'},
];
UI_box = new FlxUITabMenu(null, tabs, true);
UI_box.resize(250, 190);
UI_box.x = FlxG.width - UI_box.width - 10;
UI_box.y = 10;
UI_box.scrollFactor.set();
UI_box.alpha = 0.8;
addDialogueLineUI();
add(UI_box);
}
var characterInputText:FlxUIInputText;
var lineInputText:FlxUIInputText;
var angryCheckbox:FlxUICheckBox;
var speedStepper:FlxUINumericStepper;
function addDialogueLineUI() {
var tab_group = new FlxUI(null, UI_box);
tab_group.name = "Dialogue Line";
characterInputText = new FlxUIInputText(10, 20, 80, DialogueCharacter.DEFAULT_CHARACTER, 8);
blockPressWhileTypingOn.push(characterInputText);
speedStepper = new FlxUINumericStepper(10, characterInputText.y + 40, 0.005, 0.05, 0, 0.5, 3);
angryCheckbox = new FlxUICheckBox(speedStepper.x + 120, speedStepper.y, null, null, "Angry Textbox", 200);
angryCheckbox.callback = function()
{
updateTextBox();
dialogueFile.dialogue[curSelected].boxState = (angryCheckbox.checked ? 'angry' : 'normal');
};
lineInputText = new FlxUIInputText(10, speedStepper.y + 45, 200, DEFAULT_TEXT, 8);
blockPressWhileTypingOn.push(lineInputText);
var loadButton:FlxButton = new FlxButton(20, lineInputText.y + 30, "Load Dialogue", function() {
loadDialogue();
});
var saveButton:FlxButton = new FlxButton(loadButton.x + 120, loadButton.y, "Save Dialogue", function() {
saveDialogue();
});
tab_group.add(new FlxText(10, speedStepper.y - 18, 0, 'Interval/Speed (ms):'));
tab_group.add(new FlxText(10, characterInputText.y - 18, 0, 'Character:'));
tab_group.add(new FlxText(10, lineInputText.y - 18, 0, 'Text:'));
tab_group.add(characterInputText);
tab_group.add(angryCheckbox);
tab_group.add(speedStepper);
tab_group.add(lineInputText);
tab_group.add(lineInputText);
tab_group.add(loadButton);
tab_group.add(saveButton);
UI_box.addGroup(tab_group);
}
function copyDefaultLine():DialogueLine {
var copyLine:DialogueLine = {
portrait: defaultLine.portrait,
expression: defaultLine.expression,
text: defaultLine.text,
boxState: defaultLine.boxState,
speed: defaultLine.speed
};
return copyLine;
}
function updateTextBox() {
box.flipX = false;
var isAngry:Bool = angryCheckbox.checked;
var anim:String = isAngry ? 'angry' : 'normal';
switch(character.jsonFile.dialogue_pos) {
case 'left':
box.flipX = true;
case 'center':
if(isAngry) {
anim = 'center-angry';
} else {
anim = 'center';
}
}
box.animation.play(anim, true);
DialogueBoxPsych.updateBoxOffsets(box);
}
function reloadCharacter() {
character.frames = Paths.getSparrowAtlas('dialogue/' + character.jsonFile.image);
character.jsonFile = character.jsonFile;
character.reloadAnimations();
character.setGraphicSize(Std.int(character.width * DialogueCharacter.DEFAULT_SCALE * character.jsonFile.scale));
character.updateHitbox();
character.x = DialogueBoxPsych.LEFT_CHAR_X;
character.y = DialogueBoxPsych.DEFAULT_CHAR_Y;
switch(character.jsonFile.dialogue_pos) {
case 'right':
character.x = FlxG.width - character.width + DialogueBoxPsych.RIGHT_CHAR_X;
case 'center':
character.x = FlxG.width / 2;
character.x -= character.width / 2;
}
character.x += character.jsonFile.position[0];
character.y += character.jsonFile.position[1];
character.playAnim(); //Plays random animation
characterAnimSpeed();
if(character.animation.curAnim != null) {
animText.text = 'Animation: ' + character.jsonFile.animations[curAnim].anim + ' (' + (curAnim + 1) +' / ' + character.jsonFile.animations.length + ') - Press W or S to scroll';
} else {
animText.text = 'ERROR! NO ANIMATIONS FOUND';
}
}
private static var DEFAULT_TEXT:String = "coolswag";
private static var DEFAULT_SPEED:Float = 0.05;
private static var DEFAULT_BUBBLETYPE:String = "normal";
function reloadText(speed:Float = 0.05) {
if(daText != null) {
daText.killTheTimer();
daText.kill();
remove(daText);
daText.destroy();
}
if(Math.isNaN(speed) || speed < 0.001) speed = 0.0;
var textToType:String = lineInputText.text;
if(textToType == null || textToType.length < 1) textToType = ' ';
daText = new Alphabet(DialogueBoxPsych.DEFAULT_TEXT_X, DialogueBoxPsych.DEFAULT_TEXT_Y, textToType, false, true, speed, 0.7);
add(daText);
if(speed > 0) {
if(character.jsonFile.animations.length > curAnim && character.jsonFile.animations[curAnim] != null) {
character.playAnim(character.jsonFile.animations[curAnim].anim);
}
characterAnimSpeed();
}
#if desktop
// Updating Discord Rich Presence
var rpcText:String = lineInputText.text;
if(rpcText == null || rpcText.length < 1) rpcText = '(Empty)';
if(rpcText.length < 3) rpcText += ' '; //Fixes a bug on RPC that triggers an error when the text is too short
DiscordClient.changePresence("Dialogue Editor", rpcText);
#end
}
override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>) {
if(id == FlxUIInputText.CHANGE_EVENT && (sender is FlxUIInputText)) {
if(sender == characterInputText) {
character.reloadCharacterJson(characterInputText.text);
reloadCharacter();
updateTextBox();
if(character.jsonFile.animations.length > 0) {
curAnim = 0;
if(character.jsonFile.animations.length > curAnim && character.jsonFile.animations[curAnim] != null) {
character.playAnim(character.jsonFile.animations[curAnim].anim, daText.finishedText);
animText.text = 'Animation: ' + character.jsonFile.animations[curAnim].anim + ' (' + (curAnim + 1) +' / ' + character.jsonFile.animations.length + ') - Press W or S to scroll';
} else {
animText.text = 'ERROR! NO ANIMATIONS FOUND';
}
characterAnimSpeed();
}
dialogueFile.dialogue[curSelected].portrait = characterInputText.text;
} else if(sender == lineInputText) {
reloadText(0);
dialogueFile.dialogue[curSelected].text = lineInputText.text;
}
} else if(id == FlxUINumericStepper.CHANGE_EVENT && (sender == speedStepper)) {
reloadText(speedStepper.value);
dialogueFile.dialogue[curSelected].speed = speedStepper.value;
if(Math.isNaN(dialogueFile.dialogue[curSelected].speed) || dialogueFile.dialogue[curSelected].speed == null || dialogueFile.dialogue[curSelected].speed < 0.001) {
dialogueFile.dialogue[curSelected].speed = 0.0;
}
}
}
var curSelected:Int = 0;
var curAnim:Int = 0;
var blockPressWhileTypingOn:Array<FlxUIInputText> = [];
var transitioning:Bool = false;
override function update(elapsed:Float) {
if(transitioning) {
super.update(elapsed);
return;
}
if(character.animation.curAnim != null) {
if(daText.finishedText) {
if(character.animationIsLoop() && character.animation.curAnim.finished) {
character.playAnim(character.animation.curAnim.name, true);
}
} else if(character.animation.curAnim.finished) {
character.animation.curAnim.restart();
}
}
var blockInput:Bool = false;
for (inputText in blockPressWhileTypingOn) {
if(inputText.hasFocus) {
FlxG.sound.muteKeys = [];
FlxG.sound.volumeDownKeys = [];
FlxG.sound.volumeUpKeys = [];
blockInput = true;
if(FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.V && Clipboard.text != null) { //Copy paste
inputText.text = ClipboardAdd(inputText.text);
inputText.caretIndex = inputText.text.length;
getEvent(FlxUIInputText.CHANGE_EVENT, inputText, null, []);
}
if(FlxG.keys.justPressed.ENTER) {
if(inputText == lineInputText) {
inputText.text += '\\n';
inputText.caretIndex += 2;
} else {
inputText.hasFocus = false;
}
}
break;
}
}
if(!blockInput) {
FlxG.sound.muteKeys = TitleState.muteKeys;
FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys;
FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys;
if(FlxG.keys.justPressed.SPACE) {
reloadText(speedStepper.value);
}
if(FlxG.keys.justPressed.ESCAPE) {
MusicBeatState.switchState(new editors.MasterEditorMenu());
FlxG.sound.playMusic(Paths.music('freakyMenu'), 1);
transitioning = true;
}
var negaMult:Array<Int> = [1, -1];
var controlAnim:Array<Bool> = [FlxG.keys.justPressed.W, FlxG.keys.justPressed.S];
var controlText:Array<Bool> = [FlxG.keys.justPressed.D, FlxG.keys.justPressed.A];
for (i in 0...controlAnim.length) {
if(controlAnim[i] && character.jsonFile.animations.length > 0) {
curAnim += negaMult[i];
if(curAnim < 0) curAnim = character.jsonFile.animations.length - 1;
else if(curAnim >= character.jsonFile.animations.length) curAnim = 0;
var animToPlay:String = character.jsonFile.animations[curAnim].anim;
if(character.dialogueAnimations.exists(animToPlay)) {
character.playAnim(animToPlay, daText.finishedText);
dialogueFile.dialogue[curSelected].expression = animToPlay;
}
animText.text = 'Animation: ' + animToPlay + ' (' + (curAnim + 1) +' / ' + character.jsonFile.animations.length + ') - Press W or S to scroll';
}
if(controlText[i]) {
changeText(negaMult[i]);
}
}
if(FlxG.keys.justPressed.O) {
dialogueFile.dialogue.remove(dialogueFile.dialogue[curSelected]);
if(dialogueFile.dialogue.length < 1) //You deleted everything, dumbo!
{
dialogueFile.dialogue = [
copyDefaultLine()
];
}
changeText();
} else if(FlxG.keys.justPressed.P) {
dialogueFile.dialogue.insert(curSelected + 1, copyDefaultLine());
changeText(1);
}
}
super.update(elapsed);
}
function changeText(add:Int = 0) {
curSelected += add;
if(curSelected < 0) curSelected = dialogueFile.dialogue.length - 1;
else if(curSelected >= dialogueFile.dialogue.length) curSelected = 0;
var curDialogue:DialogueLine = dialogueFile.dialogue[curSelected];
characterInputText.text = curDialogue.portrait;
lineInputText.text = curDialogue.text;
angryCheckbox.checked = (curDialogue.boxState == 'angry');
speedStepper.value = curDialogue.speed;
curAnim = 0;
character.reloadCharacterJson(characterInputText.text);
reloadCharacter();
updateTextBox();
reloadText(curDialogue.speed);
var leLength:Int = character.jsonFile.animations.length;
if(leLength > 0) {
for (i in 0...leLength) {
var leAnim:DialogueAnimArray = character.jsonFile.animations[i];
if(leAnim != null && leAnim.anim == curDialogue.expression) {
curAnim = i;
break;
}
}
character.playAnim(character.jsonFile.animations[curAnim].anim, daText.finishedText);
animText.text = 'Animation: ' + character.jsonFile.animations[curAnim].anim + ' (' + (curAnim + 1) +' / ' + leLength + ') - Press W or S to scroll';
} else {
animText.text = 'ERROR! NO ANIMATIONS FOUND';
}
characterAnimSpeed();
selectedText.text = 'Line: (' + (curSelected + 1) + ' / ' + dialogueFile.dialogue.length + ') - Press A or D to scroll';
}
function characterAnimSpeed() {
if(character.animation.curAnim != null) {
var speed:Float = speedStepper.value;
var rate:Float = 24 - (((speed - 0.05) / 5) * 480);
if(rate < 12) rate = 12;
else if(rate > 48) rate = 48;
character.animation.curAnim.frameRate = rate;
}
}
function ClipboardAdd(prefix:String = ''):String {
if(prefix.toLowerCase().endsWith('v')) //probably copy paste attempt
{
prefix = prefix.substring(0, prefix.length-1);
}
var text:String = prefix + Clipboard.text.replace('\n', '');
return text;
}
var _file:FileReference = null;
function loadDialogue() {
var jsonFilter:FileFilter = new FileFilter('JSON', 'json');
_file = new FileReference();
_file.addEventListener(Event.SELECT, onLoadComplete);
_file.addEventListener(Event.CANCEL, onLoadCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file.browse([jsonFilter]);
}
function onLoadComplete(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
#if sys
var fullPath:String = null;
var jsonLoaded = cast Json.parse(Json.stringify(_file)); //Exploit(???) for accessing a private variable
if(jsonLoaded.__path != null) fullPath = jsonLoaded.__path; //I'm either a genious or dangerously dumb
if(fullPath != null) {
var rawJson:String = File.getContent(fullPath);
if(rawJson != null) {
var loadedDialog:DialogueFile = cast Json.parse(rawJson);
if(loadedDialog.dialogue != null && loadedDialog.dialogue.length > 0) //Make sure it's really a dialogue file
{
var cutName:String = _file.name.substr(0, _file.name.length - 5);
trace("Successfully loaded file: " + cutName);
dialogueFile = loadedDialog;
changeText();
_file = null;
return;
}
}
}
_file = null;
#else
trace("File couldn't be loaded! You aren't on Desktop, are you?");
#end
}
/**
* Called when the save file dialog is cancelled.
*/
function onLoadCancel(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Cancelled file loading.");
}
/**
* Called if there is an error while saving the gameplay recording.
*/
function onLoadError(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Problem loading file");
}
function saveDialogue() {
var data:String = Json.stringify(dialogueFile, "\t");
if (data.length > 0)
{
_file = new FileReference();
_file.addEventListener(Event.COMPLETE, onSaveComplete);
_file.addEventListener(Event.CANCEL, onSaveCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file.save(data, "dialogue.json");
}
}
function onSaveComplete(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.notice("Successfully saved file.");
}
/**
* Called when the save file dialog is cancelled.
*/
function onSaveCancel(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
}
/**
* Called if there is an error while saving the gameplay recording.
*/
function onSaveError(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.error("Problem saving file");
}
}

267
source/editors/EditorLua.hx Normal file
View file

@ -0,0 +1,267 @@
package editors;
#if LUA_ALLOWED
import llua.Lua;
import llua.LuaL;
import llua.State;
import llua.Convert;
#end
import flixel.FlxG;
import flixel.tweens.FlxTween;
import flixel.tweens.FlxEase;
import flixel.text.FlxText;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxPoint;
import flixel.system.FlxSound;
import flixel.util.FlxTimer;
import flixel.FlxSprite;
import flixel.FlxCamera;
import flixel.util.FlxColor;
import flixel.FlxBasic;
#if sys
import sys.FileSystem;
import sys.io.File;
#end
import Type.ValueType;
import Controls;
import DialogueBoxPsych;
using StringTools;
class EditorLua {
public static var Function_Stop = 1;
public static var Function_Continue = 0;
#if LUA_ALLOWED
public var lua:State = null;
#end
var lePlayState:editors.EditorPlayState = null;
public function new(script:String) {
#if LUA_ALLOWED
lua = LuaL.newstate();
LuaL.openlibs(lua);
Lua.init_callbacks(lua);
//trace('Lua version: ' + Lua.version());
//trace("LuaJIT version: " + Lua.versionJIT());
var result:Dynamic = LuaL.dofile(lua, script);
var resultStr:String = Lua.tostring(lua, result);
if(resultStr != null && result != 0) {
lime.app.Application.current.window.alert(resultStr, 'Error on .LUA script!');
trace('Error on .LUA script! ' + resultStr);
lua = null;
return;
}
trace('Lua file loaded succesfully:' + script);
var curState:Dynamic = FlxG.state;
lePlayState = curState;
// Lua variables
set('Function_Stop', Function_Stop);
set('Function_Continue', Function_Continue);
set('inChartEditor', true);
set('curBpm', Conductor.bpm);
set('bpm', PlayState.SONG.bpm);
set('scrollSpeed', PlayState.SONG.speed);
set('crochet', Conductor.crochet);
set('stepCrochet', Conductor.stepCrochet);
set('songLength', FlxG.sound.music.length);
set('songName', PlayState.SONG.song);
set('screenWidth', FlxG.width);
set('screenHeight', FlxG.height);
for (i in 0...4) {
set('defaultPlayerStrumX' + i, 0);
set('defaultPlayerStrumY' + i, 0);
set('defaultOpponentStrumX' + i, 0);
set('defaultOpponentStrumY' + i, 0);
}
set('downscroll', ClientPrefs.downScroll);
set('middlescroll', ClientPrefs.middleScroll);
//stuff 4 noobz like you B)
Lua_helper.add_callback(lua, "getProperty", function(variable:String) {
var killMe:Array<String> = variable.split('.');
if(killMe.length > 1) {
var coverMeInPiss:Dynamic = Reflect.getProperty(lePlayState, killMe[0]);
for (i in 1...killMe.length-1) {
coverMeInPiss = Reflect.getProperty(coverMeInPiss, killMe[i]);
}
return Reflect.getProperty(coverMeInPiss, killMe[killMe.length-1]);
}
return Reflect.getProperty(lePlayState, variable);
});
Lua_helper.add_callback(lua, "setProperty", function(variable:String, value:Dynamic) {
var killMe:Array<String> = variable.split('.');
if(killMe.length > 1) {
var coverMeInPiss:Dynamic = Reflect.getProperty(lePlayState, killMe[0]);
for (i in 1...killMe.length-1) {
coverMeInPiss = Reflect.getProperty(coverMeInPiss, killMe[i]);
}
return Reflect.setProperty(coverMeInPiss, killMe[killMe.length-1], value);
}
return Reflect.setProperty(lePlayState, variable, value);
});
Lua_helper.add_callback(lua, "getPropertyFromGroup", function(obj:String, index:Int, variable:Dynamic) {
if(Std.isOfType(Reflect.getProperty(lePlayState, obj), FlxTypedGroup)) {
return Reflect.getProperty(Reflect.getProperty(lePlayState, obj).members[index], variable);
}
var leArray:Dynamic = Reflect.getProperty(lePlayState, obj)[index];
if(leArray != null) {
if(Type.typeof(variable) == ValueType.TInt) {
return leArray[variable];
}
return Reflect.getProperty(leArray, variable);
}
return null;
});
Lua_helper.add_callback(lua, "setPropertyFromGroup", function(obj:String, index:Int, variable:Dynamic, value:Dynamic) {
if(Std.isOfType(Reflect.getProperty(lePlayState, obj), FlxTypedGroup)) {
return Reflect.setProperty(Reflect.getProperty(lePlayState, obj).members[index], variable, value);
}
var leArray:Dynamic = Reflect.getProperty(lePlayState, obj)[index];
if(leArray != null) {
if(Type.typeof(variable) == ValueType.TInt) {
return leArray[variable] = value;
}
return Reflect.setProperty(leArray, variable, value);
}
});
Lua_helper.add_callback(lua, "removeFromGroup", function(obj:String, index:Int, dontDestroy:Bool = false) {
if(Std.isOfType(Reflect.getProperty(lePlayState, obj), FlxTypedGroup)) {
var sex = Reflect.getProperty(lePlayState, obj).members[index];
if(!dontDestroy)
sex.kill();
Reflect.getProperty(lePlayState, obj).remove(sex, true);
if(!dontDestroy)
sex.destroy();
return;
}
Reflect.getProperty(lePlayState, obj).remove(Reflect.getProperty(lePlayState, obj)[index]);
});
Lua_helper.add_callback(lua, "getColorFromHex", function(color:String) {
if(!color.startsWith('0x')) color = '0xff' + color;
return Std.parseInt(color);
});
Lua_helper.add_callback(lua, "setGraphicSize", function(obj:String, x:Int, y:Int = 0) {
var poop:FlxSprite = Reflect.getProperty(lePlayState, obj);
if(poop != null) {
poop.setGraphicSize(x, y);
poop.updateHitbox();
return;
}
});
Lua_helper.add_callback(lua, "scaleObject", function(obj:String, x:Float, y:Float) {
var poop:FlxSprite = Reflect.getProperty(lePlayState, obj);
if(poop != null) {
poop.scale.set(x, y);
poop.updateHitbox();
return;
}
});
Lua_helper.add_callback(lua, "updateHitbox", function(obj:String) {
var poop:FlxSprite = Reflect.getProperty(lePlayState, obj);
if(poop != null) {
poop.updateHitbox();
return;
}
});
call('onCreate', []);
#end
}
public function call(event:String, args:Array<Dynamic>):Dynamic {
#if LUA_ALLOWED
if(lua == null) {
return Function_Continue;
}
Lua.getglobal(lua, event);
for (arg in args) {
Convert.toLua(lua, arg);
}
var result:Null<Int> = Lua.pcall(lua, args.length, 1, 0);
if(result != null && resultIsAllowed(lua, result)) {
/*var resultStr:String = Lua.tostring(lua, result);
var error:String = Lua.tostring(lua, -1);
Lua.pop(lua, 1);*/
if(Lua.type(lua, -1) == Lua.LUA_TSTRING) {
var error:String = Lua.tostring(lua, -1);
Lua.pop(lua, 1);
if(error == 'attempt to call a nil value') { //Makes it ignore warnings and not break stuff if you didn't put the functions on your lua file
return Function_Continue;
}
}
var conv:Dynamic = Convert.fromLua(lua, result);
return conv;
}
#end
return Function_Continue;
}
#if LUA_ALLOWED
function resultIsAllowed(leLua:State, leResult:Null<Int>) { //Makes it ignore warnings
switch(Lua.type(leLua, leResult)) {
case Lua.LUA_TNIL | Lua.LUA_TBOOLEAN | Lua.LUA_TNUMBER | Lua.LUA_TSTRING | Lua.LUA_TTABLE:
return true;
}
return false;
}
#end
public function set(variable:String, data:Dynamic) {
#if LUA_ALLOWED
if(lua == null) {
return;
}
Convert.toLua(lua, data);
Lua.setglobal(lua, variable);
#end
}
#if LUA_ALLOWED
public function getBool(variable:String) {
var result:String = null;
Lua.getglobal(lua, variable);
result = Convert.fromLua(lua, -1);
Lua.pop(lua, 1);
if(result == null) {
return false;
}
// YES! FINALLY IT WORKS
//trace('variable: ' + variable + ', ' + result);
return (result == 'true');
}
#end
public function stop() {
#if LUA_ALLOWED
if(lua == null) {
return;
}
Lua.close(lua);
lua = null;
#end
}
}

View file

@ -0,0 +1,878 @@
package editors;
import Section.SwagSection;
import Song.SwagSong;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.addons.transition.FlxTransitionableState;
import flixel.util.FlxColor;
import flixel.FlxSprite;
import flixel.FlxG;
import flixel.text.FlxText;
import flixel.tweens.FlxEase;
import flixel.tweens.FlxTween;
import flixel.math.FlxMath;
import flixel.math.FlxPoint;
import flixel.math.FlxRect;
import flixel.system.FlxSound;
import flixel.util.FlxSort;
import flixel.util.FlxTimer;
import FunkinLua;
using StringTools;
class EditorPlayState extends MusicBeatState
{
// Yes, this is mostly a copy of PlayState, it's kinda dumb to make a direct copy of it but... ehhh
private var strumLine:FlxSprite;
private var comboGroup:FlxTypedGroup<FlxSprite>;
public var strumLineNotes:FlxTypedGroup<StrumNote>;
public var opponentStrums:FlxTypedGroup<StrumNote>;
public var playerStrums:FlxTypedGroup<StrumNote>;
public var grpNoteSplashes:FlxTypedGroup<NoteSplash>;
public var notes:FlxTypedGroup<Note>;
public var unspawnNotes:Array<Note> = [];
var generatedMusic:Bool = false;
var vocals:FlxSound;
var startOffset:Float = 0;
var startPos:Float = 0;
public function new(startPos:Float) {
this.startPos = startPos;
Conductor.songPosition = startPos - startOffset;
startOffset = Conductor.crochet;
timerToStart = startOffset;
super();
}
var scoreTxt:FlxText;
var timerToStart:Float = 0;
private var noteTypeMap:Map<String, Bool> = new Map<String, Bool>();
override function create()
{
var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
bg.scrollFactor.set();
bg.color = FlxColor.fromHSB(FlxG.random.int(0, 359), FlxG.random.float(0, 0.8), FlxG.random.float(0.3, 1));
add(bg);
strumLine = new FlxSprite(ClientPrefs.middleScroll ? PlayState.STRUM_X_MIDDLESCROLL : PlayState.STRUM_X, 50).makeGraphic(FlxG.width, 10);
if(ClientPrefs.downScroll) strumLine.y = FlxG.height - 150;
strumLine.scrollFactor.set();
comboGroup = new FlxTypedGroup<FlxSprite>();
add(comboGroup);
strumLineNotes = new FlxTypedGroup<StrumNote>();
opponentStrums = new FlxTypedGroup<StrumNote>();
playerStrums = new FlxTypedGroup<StrumNote>();
add(strumLineNotes);
generateStaticArrows(0);
generateStaticArrows(1);
if(ClientPrefs.middleScroll) {
opponentStrums.forEachAlive(function (note:StrumNote) {
note.visible = false;
});
}
grpNoteSplashes = new FlxTypedGroup<NoteSplash>();
add(grpNoteSplashes);
var splash:NoteSplash = new NoteSplash(100, 100, 0);
grpNoteSplashes.add(splash);
splash.alpha = 0.0;
if (PlayState.SONG.needsVoices)
vocals = new FlxSound().loadEmbedded(Paths.voices(PlayState.SONG.song));
else
vocals = new FlxSound();
generateSong(PlayState.SONG.song);
#if LUA_ALLOWED
for (notetype in noteTypeMap.keys()) {
var luaToLoad:String = Paths.modFolders('custom_notetypes/' + notetype + '.lua');
if(sys.FileSystem.exists(luaToLoad)) {
var lua:editors.EditorLua = new editors.EditorLua(luaToLoad);
new FlxTimer().start(0.1, function (tmr:FlxTimer) {
lua.stop();
lua = null;
});
}
}
#end
noteTypeMap.clear();
noteTypeMap = null;
scoreTxt = new FlxText(0, FlxG.height - 50, FlxG.width, "Hits: 0 | Misses: 0", 20);
scoreTxt.setFormat(Paths.font("vcr.ttf"), 20, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
scoreTxt.scrollFactor.set();
scoreTxt.borderSize = 1.25;
scoreTxt.visible = !ClientPrefs.hideHud;
add(scoreTxt);
var tipText:FlxText = new FlxText(10, FlxG.height - 24, 0, 'Press ESC to Go Back to Chart Editor', 16);
tipText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, LEFT, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
tipText.borderSize = 2;
tipText.scrollFactor.set();
add(tipText);
FlxG.mouse.visible = false;
//sayGo();
super.create();
}
function sayGo() {
var go:FlxSprite = new FlxSprite().loadGraphic(Paths.image('go'));
go.scrollFactor.set();
go.updateHitbox();
go.screenCenter();
go.antialiasing = ClientPrefs.globalAntialiasing;
add(go);
FlxTween.tween(go, {y: go.y += 100, alpha: 0}, Conductor.crochet / 1000, {
ease: FlxEase.cubeInOut,
onComplete: function(twn:FlxTween)
{
go.destroy();
}
});
FlxG.sound.play(Paths.sound('introGo'), 0.6);
}
//var songScore:Int = 0;
var songHits:Int = 0;
var songMisses:Int = 0;
var ghostMisses:Int = 0;
var startingSong:Bool = true;
private function generateSong(dataPath:String):Void
{
FlxG.sound.playMusic(Paths.inst(PlayState.SONG.song), 0, false);
FlxG.sound.music.pause();
FlxG.sound.music.onComplete = endSong;
vocals.pause();
vocals.volume = 0;
var songData = PlayState.SONG;
Conductor.changeBPM(songData.bpm);
notes = new FlxTypedGroup<Note>();
add(notes);
var noteData:Array<SwagSection>;
// NEW SHIT
noteData = songData.notes;
var playerCounter:Int = 0;
var daBeats:Int = 0; // Not exactly representative of 'daBeats' lol, just how much it has looped
for (section in noteData)
{
for (songNotes in section.sectionNotes)
{
if(songNotes[1] > -1) { //Real notes
var daStrumTime:Float = songNotes[0];
if(daStrumTime >= startPos) {
var daNoteData:Int = Std.int(songNotes[1] % 4);
var gottaHitNote:Bool = section.mustHitSection;
if (songNotes[1] > 3)
{
gottaHitNote = !section.mustHitSection;
}
var oldNote:Note;
if (unspawnNotes.length > 0)
oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)];
else
oldNote = null;
var swagNote:Note = new Note(daStrumTime, daNoteData, oldNote);
swagNote.mustPress = gottaHitNote;
swagNote.sustainLength = songNotes[2];
swagNote.noteType = songNotes[3];
if(!Std.isOfType(songNotes[3], String)) swagNote.noteType = editors.ChartingState.noteTypeList[songNotes[3]]; //Backward compatibility + compatibility with Week 7 charts
swagNote.scrollFactor.set();
var susLength:Float = swagNote.sustainLength;
susLength = susLength / Conductor.stepCrochet;
unspawnNotes.push(swagNote);
var floorSus:Int = Math.floor(susLength);
if(floorSus > 0) {
for (susNote in 0...floorSus+1)
{
oldNote = unspawnNotes[Std.int(unspawnNotes.length - 1)];
var sustainNote:Note = new Note(daStrumTime + (Conductor.stepCrochet * susNote) + (Conductor.stepCrochet / FlxMath.roundDecimal(PlayState.SONG.speed, 2)), daNoteData, oldNote, true);
sustainNote.mustPress = gottaHitNote;
sustainNote.noteType = swagNote.noteType;
sustainNote.scrollFactor.set();
unspawnNotes.push(sustainNote);
if (sustainNote.mustPress)
{
sustainNote.x += FlxG.width / 2; // general offset
}
}
}
if (swagNote.mustPress)
{
swagNote.x += FlxG.width / 2; // general offset
}
else {}
if(!noteTypeMap.exists(swagNote.noteType)) {
noteTypeMap.set(swagNote.noteType, true);
}
}
}
}
daBeats += 1;
}
unspawnNotes.sort(sortByShit);
generatedMusic = true;
}
function startSong():Void
{
startingSong = false;
FlxG.sound.music.time = startPos;
FlxG.sound.music.play();
FlxG.sound.music.volume = 1;
vocals.volume = 1;
vocals.time = startPos;
vocals.play();
}
function sortByShit(Obj1:Note, Obj2:Note):Int
{
return FlxSort.byValues(FlxSort.ASCENDING, Obj1.strumTime, Obj2.strumTime);
}
private function endSong() {
LoadingState.loadAndSwitchState(new editors.ChartingState());
}
override function update(elapsed:Float) {
if (FlxG.keys.justPressed.ESCAPE)
{
FlxG.sound.music.pause();
vocals.pause();
LoadingState.loadAndSwitchState(new editors.ChartingState());
}
if (startingSong) {
timerToStart -= elapsed * 1000;
Conductor.songPosition = startPos - timerToStart;
if(timerToStart < 0) {
startSong();
}
} else {
Conductor.songPosition += elapsed * 1000;
}
var roundedSpeed:Float = FlxMath.roundDecimal(PlayState.SONG.speed, 2);
if (unspawnNotes[0] != null)
{
var time:Float = 1500;
if(roundedSpeed < 1) time /= roundedSpeed;
while (unspawnNotes.length > 0 && unspawnNotes[0].strumTime - Conductor.songPosition < time)
{
var dunceNote:Note = unspawnNotes[0];
notes.add(dunceNote);
var index:Int = unspawnNotes.indexOf(dunceNote);
unspawnNotes.splice(index, 1);
}
}
if (generatedMusic)
{
var fakeCrochet:Float = (60 / PlayState.SONG.bpm) * 1000;
notes.forEachAlive(function(daNote:Note)
{
if(!daNote.mustPress && ClientPrefs.middleScroll)
{
daNote.active = true;
daNote.visible = false;
}
else if (daNote.y > FlxG.height)
{
daNote.active = false;
daNote.visible = false;
}
else
{
daNote.visible = true;
daNote.active = true;
}
// i am so fucking sorry for this if condition
var strumX:Float = 0;
var strumY:Float = 0;
if(daNote.mustPress) {
strumX = playerStrums.members[daNote.noteData].x;
strumY = playerStrums.members[daNote.noteData].y;
} else {
strumX = opponentStrums.members[daNote.noteData].x;
strumY = opponentStrums.members[daNote.noteData].y;
}
strumX += daNote.offsetX;
strumY += daNote.offsetY;
var center:Float = strumY + Note.swagWidth / 2;
if(daNote.copyX) {
daNote.x = strumX;
}
if(daNote.copyY) {
if (ClientPrefs.downScroll) {
daNote.y = (strumY + 0.45 * (Conductor.songPosition - daNote.strumTime) * roundedSpeed);
if (daNote.isSustainNote) {
//Jesus fuck this took me so much mother fucking time AAAAAAAAAA
if (daNote.animation.curAnim.name.endsWith('end')) {
daNote.y += 10.5 * (fakeCrochet / 400) * 1.5 * roundedSpeed + (46 * (roundedSpeed - 1));
daNote.y -= 46 * (1 - (fakeCrochet / 600)) * roundedSpeed;
if(PlayState.isPixelStage) {
daNote.y += 8;
} else {
daNote.y -= 19;
}
}
daNote.y += (Note.swagWidth / 2) - (60.5 * (roundedSpeed - 1));
daNote.y += 27.5 * ((PlayState.SONG.bpm / 100) - 1) * (roundedSpeed - 1);
if(daNote.mustPress || !daNote.ignoreNote)
{
if(daNote.y - daNote.offset.y * daNote.scale.y + daNote.height >= center
&& (!daNote.mustPress || (daNote.wasGoodHit || (daNote.prevNote.wasGoodHit && !daNote.canBeHit))))
{
var swagRect = new FlxRect(0, 0, daNote.frameWidth, daNote.frameHeight);
swagRect.height = (center - daNote.y) / daNote.scale.y;
swagRect.y = daNote.frameHeight - swagRect.height;
daNote.clipRect = swagRect;
}
}
}
} else {
daNote.y = (strumY - 0.45 * (Conductor.songPosition - daNote.strumTime) * roundedSpeed);
if(daNote.mustPress || !daNote.ignoreNote)
{
if (daNote.isSustainNote
&& daNote.y + daNote.offset.y * daNote.scale.y <= center
&& (!daNote.mustPress || (daNote.wasGoodHit || (daNote.prevNote.wasGoodHit && !daNote.canBeHit))))
{
var swagRect = new FlxRect(0, 0, daNote.width / daNote.scale.x, daNote.height / daNote.scale.y);
swagRect.y = (center - daNote.y) / daNote.scale.y;
swagRect.height -= swagRect.y;
daNote.clipRect = swagRect;
}
}
}
}
if (!daNote.mustPress && daNote.wasGoodHit && !daNote.hitByOpponent && !daNote.ignoreNote)
{
if (PlayState.SONG.needsVoices)
vocals.volume = 1;
var time:Float = 0.15;
if(daNote.isSustainNote && !daNote.animation.curAnim.name.endsWith('end')) {
time += 0.15;
}
StrumPlayAnim(true, Std.int(Math.abs(daNote.noteData)) % 4, time);
daNote.hitByOpponent = true;
if (!daNote.isSustainNote)
{
daNote.kill();
notes.remove(daNote, true);
daNote.destroy();
}
}
var doKill:Bool = daNote.y < -daNote.height;
if(ClientPrefs.downScroll) doKill = daNote.y > FlxG.height;
if (doKill)
{
if (daNote.mustPress)
{
if (daNote.tooLate || !daNote.wasGoodHit)
{
//Dupe note remove
notes.forEachAlive(function(note:Note) {
if (daNote != note && daNote.mustPress && daNote.noteData == note.noteData && daNote.isSustainNote == note.isSustainNote && Math.abs(daNote.strumTime - note.strumTime) < 10) {
note.kill();
notes.remove(note, true);
note.destroy();
}
});
if(!daNote.ignoreNote) {
songMisses++;
vocals.volume = 0;
}
}
}
daNote.active = false;
daNote.visible = false;
daNote.kill();
notes.remove(daNote, true);
daNote.destroy();
}
});
}
keyShit();
scoreTxt.text = 'Hits: ' + songHits + ' | Misses: ' + songMisses;
super.update(elapsed);
}
override function beatHit()
{
super.beatHit();
if (generatedMusic)
{
notes.sort(FlxSort.byY, ClientPrefs.downScroll ? FlxSort.ASCENDING : FlxSort.DESCENDING);
}
}
override function stepHit()
{
super.stepHit();
if (FlxG.sound.music.time > Conductor.songPosition + 20 || FlxG.sound.music.time < Conductor.songPosition - 20)
{
resyncVocals();
}
}
function resyncVocals():Void
{
vocals.pause();
FlxG.sound.music.play();
Conductor.songPosition = FlxG.sound.music.time;
vocals.time = Conductor.songPosition;
vocals.play();
}
function keyShit() {
// HOLDING
var up = controls.NOTE_UP;
var right = controls.NOTE_RIGHT;
var down = controls.NOTE_DOWN;
var left = controls.NOTE_LEFT;
var upP = controls.NOTE_UP_P;
var rightP = controls.NOTE_RIGHT_P;
var downP = controls.NOTE_DOWN_P;
var leftP = controls.NOTE_LEFT_P;
var upR = controls.NOTE_UP_R;
var rightR = controls.NOTE_RIGHT_R;
var downR = controls.NOTE_DOWN_R;
var leftR = controls.NOTE_LEFT_R;
var controlArray:Array<Bool> = [leftP, downP, upP, rightP];
var controlReleaseArray:Array<Bool> = [leftR, downR, upR, rightR];
var controlHoldArray:Array<Bool> = [left, down, up, right];
// FlxG.watch.addQuick('asdfa', upP);
if (generatedMusic)
{
// rewritten inputs???
notes.forEachAlive(function(daNote:Note)
{
// hold note functions
if (daNote.isSustainNote && controlHoldArray[daNote.noteData] && daNote.canBeHit
&& daNote.mustPress && !daNote.tooLate && !daNote.wasGoodHit) {
goodNoteHit(daNote);
}
});
if (controlHoldArray.contains(true) || controlArray.contains(true)) {
var canMiss:Bool = !ClientPrefs.ghostTapping;
if (controlArray.contains(true)) {
for (i in 0...controlArray.length) {
// heavily based on my own code LOL if it aint broke dont fix it
var pressNotes:Array<Note> = [];
var notesDatas:Array<Int> = [];
var notesStopped:Bool = false;
var sortedNotesList:Array<Note> = [];
notes.forEachAlive(function(daNote:Note)
{
if (daNote.canBeHit && daNote.mustPress && !daNote.tooLate
&& !daNote.wasGoodHit && daNote.noteData == i) {
sortedNotesList.push(daNote);
notesDatas.push(daNote.noteData);
canMiss = true;
}
});
sortedNotesList.sort((a, b) -> Std.int(a.strumTime - b.strumTime));
if (sortedNotesList.length > 0) {
for (epicNote in sortedNotesList)
{
for (doubleNote in pressNotes) {
if (Math.abs(doubleNote.strumTime - epicNote.strumTime) < 10) {
doubleNote.kill();
notes.remove(doubleNote, true);
doubleNote.destroy();
} else
notesStopped = true;
}
// eee jack detection before was not super good
if (controlArray[epicNote.noteData] && !notesStopped) {
goodNoteHit(epicNote);
pressNotes.push(epicNote);
}
}
}
else if (canMiss && controlArray[i])
noteMiss(i, true);
}
}
}
}
playerStrums.forEach(function(spr:StrumNote)
{
if(controlArray[spr.ID] && spr.animation.curAnim.name != 'confirm') {
spr.playAnim('pressed');
spr.resetAnim = 0;
}
if(controlReleaseArray[spr.ID]) {
spr.playAnim('static');
spr.resetAnim = 0;
}
});
}
var combo:Int = 0;
function goodNoteHit(note:Note):Void
{
if (!note.wasGoodHit)
{
switch(note.noteType) {
case 'Hurt Note': //Hurt note
noteMiss(note.noteData);
--songMisses;
if(!note.isSustainNote) {
if(!note.noteSplashDisabled) {
spawnNoteSplashOnNote(note);
}
}
note.wasGoodHit = true;
vocals.volume = 0;
if (!note.isSustainNote)
{
note.kill();
notes.remove(note, true);
note.destroy();
}
return;
}
if (!note.isSustainNote)
{
popUpScore(note);
combo += 1;
songHits++;
if(combo > 9999) combo = 9999;
}
playerStrums.forEach(function(spr:StrumNote)
{
if (Math.abs(note.noteData) == spr.ID)
{
spr.playAnim('confirm', true);
}
});
note.wasGoodHit = true;
vocals.volume = 1;
if (!note.isSustainNote)
{
note.kill();
notes.remove(note, true);
note.destroy();
}
}
}
function noteMiss(direction:Int = 1, ?ghostMiss:Bool = false):Void
{
combo = 0;
//songScore -= 10;
if(ghostMiss) ghostMisses++;
songMisses++;
FlxG.sound.play(Paths.soundRandom('missnote', 1, 3), FlxG.random.float(0.1, 0.2));
vocals.volume = 0;
}
var COMBO_X:Float = 400;
var COMBO_Y:Float = 340;
private function popUpScore(note:Note = null):Void
{
var noteDiff:Float = Math.abs(note.strumTime - Conductor.songPosition + 8);
vocals.volume = 1;
var placement:String = Std.string(combo);
var coolText:FlxText = new FlxText(0, 0, 0, placement, 32);
coolText.x = COMBO_X;
coolText.y = COMBO_Y;
//
var rating:FlxSprite = new FlxSprite();
//var score:Int = 350;
var daRating:String = "sick";
if (noteDiff > Conductor.safeZoneOffset * 0.75)
{
daRating = 'shit';
//score = 50;
}
else if (noteDiff > Conductor.safeZoneOffset * 0.5)
{
daRating = 'bad';
//score = 100;
}
else if (noteDiff > Conductor.safeZoneOffset * 0.25)
{
daRating = 'good';
//score = 200;
}
if(daRating == 'sick' && !note.noteSplashDisabled)
{
spawnNoteSplashOnNote(note);
}
//songScore += score;
/* if (combo > 60)
daRating = 'sick';
else if (combo > 12)
daRating = 'good'
else if (combo > 4)
daRating = 'bad';
*/
var pixelShitPart1:String = "";
var pixelShitPart2:String = '';
if (PlayState.isPixelStage)
{
pixelShitPart1 = 'pixelUI/';
pixelShitPart2 = '-pixel';
}
rating.loadGraphic(Paths.image(pixelShitPart1 + daRating + pixelShitPart2));
rating.screenCenter();
rating.x = coolText.x - 40;
rating.y -= 60;
rating.acceleration.y = 550;
rating.velocity.y -= FlxG.random.int(140, 175);
rating.velocity.x -= FlxG.random.int(0, 10);
rating.visible = !ClientPrefs.hideHud;
var comboSpr:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'combo' + pixelShitPart2));
comboSpr.screenCenter();
comboSpr.x = coolText.x;
comboSpr.acceleration.y = 600;
comboSpr.velocity.y -= 150;
comboSpr.visible = !ClientPrefs.hideHud;
comboSpr.velocity.x += FlxG.random.int(1, 10);
comboGroup.add(rating);
if (!PlayState.isPixelStage)
{
rating.setGraphicSize(Std.int(rating.width * 0.7));
rating.antialiasing = ClientPrefs.globalAntialiasing;
comboSpr.setGraphicSize(Std.int(comboSpr.width * 0.7));
comboSpr.antialiasing = ClientPrefs.globalAntialiasing;
}
else
{
rating.setGraphicSize(Std.int(rating.width * PlayState.daPixelZoom * 0.7));
comboSpr.setGraphicSize(Std.int(comboSpr.width * PlayState.daPixelZoom * 0.7));
}
comboSpr.updateHitbox();
rating.updateHitbox();
var seperatedScore:Array<Int> = [];
if(combo >= 1000) {
seperatedScore.push(Math.floor(combo / 1000) % 10);
}
seperatedScore.push(Math.floor(combo / 100) % 10);
seperatedScore.push(Math.floor(combo / 10) % 10);
seperatedScore.push(combo % 10);
var daLoop:Int = 0;
for (i in seperatedScore)
{
var numScore:FlxSprite = new FlxSprite().loadGraphic(Paths.image(pixelShitPart1 + 'num' + Std.int(i) + pixelShitPart2));
numScore.screenCenter();
numScore.x = coolText.x + (43 * daLoop) - 90;
numScore.y += 80;
if (!PlayState.isPixelStage)
{
numScore.antialiasing = ClientPrefs.globalAntialiasing;
numScore.setGraphicSize(Std.int(numScore.width * 0.5));
}
else
{
numScore.setGraphicSize(Std.int(numScore.width * PlayState.daPixelZoom));
}
numScore.updateHitbox();
numScore.acceleration.y = FlxG.random.int(200, 300);
numScore.velocity.y -= FlxG.random.int(140, 160);
numScore.velocity.x = FlxG.random.float(-5, 5);
numScore.visible = !ClientPrefs.hideHud;
if (combo >= 10 || combo == 0)
comboGroup.add(numScore);
FlxTween.tween(numScore, {alpha: 0}, 0.2, {
onComplete: function(tween:FlxTween)
{
numScore.destroy();
},
startDelay: Conductor.crochet * 0.002
});
daLoop++;
}
/*
trace(combo);
trace(seperatedScore);
*/
coolText.text = Std.string(seperatedScore);
// comboGroup.add(coolText);
FlxTween.tween(rating, {alpha: 0}, 0.2, {
startDelay: Conductor.crochet * 0.001
});
FlxTween.tween(comboSpr, {alpha: 0}, 0.2, {
onComplete: function(tween:FlxTween)
{
coolText.destroy();
comboSpr.destroy();
rating.destroy();
},
startDelay: Conductor.crochet * 0.001
});
}
private function generateStaticArrows(player:Int):Void
{
for (i in 0...4)
{
// FlxG.log.add(i);
var babyArrow:StrumNote = new StrumNote(ClientPrefs.middleScroll ? PlayState.STRUM_X_MIDDLESCROLL : PlayState.STRUM_X, strumLine.y, i, player);
babyArrow.alpha = 0;
FlxTween.tween(babyArrow, {alpha: 1}, 0.5, {ease: FlxEase.circOut});
if (player == 1)
{
playerStrums.add(babyArrow);
}
else
{
opponentStrums.add(babyArrow);
}
strumLineNotes.add(babyArrow);
babyArrow.postAddedToGroup();
}
}
// For Opponent's notes glow
function StrumPlayAnim(isDad:Bool, id:Int, time:Float) {
var spr:StrumNote = null;
if(isDad) {
spr = strumLineNotes.members[id];
} else {
spr = playerStrums.members[id];
}
if(spr != null) {
spr.playAnim('confirm', true);
spr.resetAnim = time;
}
}
// Note splash shit, duh
function spawnNoteSplashOnNote(note:Note) {
if(ClientPrefs.noteSplashes && note != null) {
var strum:StrumNote = playerStrums.members[note.noteData];
if(strum != null) {
spawnNoteSplash(strum.x, strum.y, note.noteData, note);
}
}
}
function spawnNoteSplash(x:Float, y:Float, data:Int, ?note:Note = null) {
var skin:String = 'noteSplashes';
if(PlayState.SONG.splashSkin != null && PlayState.SONG.splashSkin.length > 0) skin = PlayState.SONG.splashSkin;
var hue:Float = ClientPrefs.arrowHSV[data % 4][0] / 360;
var sat:Float = ClientPrefs.arrowHSV[data % 4][1] / 100;
var brt:Float = ClientPrefs.arrowHSV[data % 4][2] / 100;
if(note != null) {
skin = note.noteSplashTexture;
hue = note.noteSplashHue;
sat = note.noteSplashSat;
brt = note.noteSplashBrt;
}
var splash:NoteSplash = grpNoteSplashes.recycle(NoteSplash);
splash.setupNoteSplash(x, y, data, skin, hue, sat, brt);
grpNoteSplashes.add(splash);
}
override function destroy() {
FlxG.sound.music.stop();
vocals.stop();
vocals.destroy();
super.destroy();
}
}

View file

@ -0,0 +1,122 @@
package editors;
#if desktop
import Discord.DiscordClient;
#end
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.addons.display.FlxGridOverlay;
import flixel.addons.transition.FlxTransitionableState;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.util.FlxColor;
import flixel.system.FlxSound;
using StringTools;
class MasterEditorMenu extends MusicBeatState
{
var options:Array<String> = [
'Week Editor',
'Menu Character Editor',
'Dialogue Editor',
'Dialogue Portrait Editor',
'Character Editor'
];
private var grpTexts:FlxTypedGroup<Alphabet>;
private var curSelected = 0;
override function create()
{
FlxG.camera.bgColor = FlxColor.BLACK;
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("Editors Main Menu", null);
#end
var bg:FlxSprite = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
bg.scrollFactor.set();
bg.color = 0xFF353535;
add(bg);
grpTexts = new FlxTypedGroup<Alphabet>();
add(grpTexts);
for (i in 0...options.length)
{
var leText:Alphabet = new Alphabet(0, (70 * i) + 30, options[i], true, false);
leText.isMenuItem = true;
leText.targetY = i;
grpTexts.add(leText);
}
changeSelection();
super.create();
}
override function update(elapsed:Float)
{
if (controls.UI_UP_P)
{
changeSelection(-1);
}
if (controls.UI_DOWN_P)
{
changeSelection(1);
}
if (controls.BACK)
{
MusicBeatState.switchState(new MainMenuState());
}
if (controls.ACCEPT)
{
switch(options[curSelected]) {
case 'Character Editor':
LoadingState.loadAndSwitchState(new CharacterEditorState(Character.DEFAULT_CHARACTER, false));
case 'Week Editor':
MusicBeatState.switchState(new WeekEditorState());
case 'Menu Character Editor':
MusicBeatState.switchState(new MenuCharacterEditorState());
case 'Dialogue Portrait Editor':
LoadingState.loadAndSwitchState(new DialogueCharacterEditorState(), false);
case 'Dialogue Editor':
LoadingState.loadAndSwitchState(new DialogueEditorState(), false);
}
FlxG.sound.music.volume = 0;
FreeplayState.destroyFreeplayVocals();
}
var bullShit:Int = 0;
for (item in grpTexts.members)
{
item.targetY = bullShit - curSelected;
bullShit++;
item.alpha = 0.6;
// item.setGraphicSize(Std.int(item.width * 0.8));
if (item.targetY == 0)
{
item.alpha = 1;
// item.setGraphicSize(Std.int(item.width));
}
}
super.update(elapsed);
}
function changeSelection(change:Int = 0)
{
FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
curSelected += change;
if (curSelected < 0)
curSelected = options.length - 1;
if (curSelected >= options.length)
curSelected = 0;
}
}

View file

@ -0,0 +1,443 @@
package editors;
#if desktop
import Discord.DiscordClient;
#end
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.addons.display.FlxGridOverlay;
import flixel.addons.transition.FlxTransitionableState;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.util.FlxColor;
import flixel.system.FlxSound;
import flixel.addons.ui.FlxInputText;
import flixel.addons.ui.FlxUI9SliceSprite;
import flixel.addons.ui.FlxUI;
import flixel.addons.ui.FlxUICheckBox;
import flixel.addons.ui.FlxUIInputText;
import flixel.addons.ui.FlxUINumericStepper;
import flixel.addons.ui.FlxUITabMenu;
import flixel.ui.FlxButton;
import MenuCharacter;
import openfl.net.FileReference;
import openfl.events.Event;
import openfl.events.IOErrorEvent;
import flash.net.FileFilter;
import haxe.Json;
#if sys
import sys.io.File;
#end
using StringTools;
class MenuCharacterEditorState extends MusicBeatState
{
var grpWeekCharacters:FlxTypedGroup<MenuCharacter>;
var characterFile:MenuCharacterFile = null;
var txtOffsets:FlxText;
var defaultCharacters:Array<String> = ['dad', 'bf', 'gf'];
override function create() {
characterFile = {
image: 'Menu_Dad',
scale: 1,
position: [0, 0],
idle_anim: 'M Dad Idle',
confirm_anim: 'M Dad Idle'
};
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("Menu Character Editor", "Editting: " + characterFile.image);
#end
grpWeekCharacters = new FlxTypedGroup<MenuCharacter>();
for (char in 0...3)
{
var weekCharacterThing:MenuCharacter = new MenuCharacter((FlxG.width * 0.25) * (1 + char) - 150, defaultCharacters[char]);
weekCharacterThing.y += 70;
weekCharacterThing.alpha = 0.2;
grpWeekCharacters.add(weekCharacterThing);
}
add(new FlxSprite(0, 56).makeGraphic(FlxG.width, 386, 0xFFF9CF51));
add(grpWeekCharacters);
txtOffsets = new FlxText(20, 10, 0, "[0, 0]", 32);
txtOffsets.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, CENTER);
txtOffsets.alpha = 0.7;
add(txtOffsets);
var tipText:FlxText = new FlxText(0, 540, FlxG.width,
"Arrow Keys - Change Offset (Hold shift for 10x speed)
\nSpace - Play \"Start Press\" animation (Boyfriend Character Type)", 16);
tipText.setFormat(Paths.font("vcr.ttf"), 16, FlxColor.WHITE, CENTER);
tipText.scrollFactor.set();
add(tipText);
addEditorBox();
FlxG.mouse.visible = true;
updateCharTypeBox();
super.create();
}
var UI_typebox:FlxUITabMenu;
var UI_mainbox:FlxUITabMenu;
var blockPressWhileTypingOn:Array<FlxUIInputText> = [];
function addEditorBox() {
var tabs = [
{name: 'Character Type', label: 'Character Type'},
];
UI_typebox = new FlxUITabMenu(null, tabs, true);
UI_typebox.resize(120, 180);
UI_typebox.x = 100;
UI_typebox.y = FlxG.height - UI_typebox.height - 50;
UI_typebox.scrollFactor.set();
addTypeUI();
add(UI_typebox);
var tabs = [
{name: 'Character', label: 'Character'},
];
UI_mainbox = new FlxUITabMenu(null, tabs, true);
UI_mainbox.resize(240, 180);
UI_mainbox.x = FlxG.width - UI_mainbox.width - 100;
UI_mainbox.y = FlxG.height - UI_mainbox.height - 50;
UI_mainbox.scrollFactor.set();
addCharacterUI();
add(UI_mainbox);
var loadButton:FlxButton = new FlxButton(0, 480, "Load Character", function() {
loadCharacter();
});
loadButton.screenCenter(X);
loadButton.x -= 60;
add(loadButton);
var saveButton:FlxButton = new FlxButton(0, 480, "Save Character", function() {
saveCharacter();
});
saveButton.screenCenter(X);
saveButton.x += 60;
add(saveButton);
}
var opponentCheckbox:FlxUICheckBox;
var boyfriendCheckbox:FlxUICheckBox;
var girlfriendCheckbox:FlxUICheckBox;
var curTypeSelected:Int = 0; //0 = Dad, 1 = BF, 2 = GF
function addTypeUI() {
var tab_group = new FlxUI(null, UI_typebox);
tab_group.name = "Character Type";
opponentCheckbox = new FlxUICheckBox(10, 20, null, null, "Opponent", 100);
opponentCheckbox.callback = function()
{
curTypeSelected = 0;
updateCharTypeBox();
};
boyfriendCheckbox = new FlxUICheckBox(opponentCheckbox.x, opponentCheckbox.y + 40, null, null, "Boyfriend", 100);
boyfriendCheckbox.callback = function()
{
curTypeSelected = 1;
updateCharTypeBox();
};
girlfriendCheckbox = new FlxUICheckBox(boyfriendCheckbox.x, boyfriendCheckbox.y + 40, null, null, "Girlfriend", 100);
girlfriendCheckbox.callback = function()
{
curTypeSelected = 2;
updateCharTypeBox();
};
tab_group.add(opponentCheckbox);
tab_group.add(boyfriendCheckbox);
tab_group.add(girlfriendCheckbox);
UI_typebox.addGroup(tab_group);
}
var imageInputText:FlxUIInputText;
var idleInputText:FlxUIInputText;
var confirmInputText:FlxUIInputText;
var confirmDescText:FlxText;
var scaleStepper:FlxUINumericStepper;
function addCharacterUI() {
var tab_group = new FlxUI(null, UI_mainbox);
tab_group.name = "Character";
imageInputText = new FlxUIInputText(10, 20, 80, characterFile.image, 8);
blockPressWhileTypingOn.push(imageInputText);
idleInputText = new FlxUIInputText(10, imageInputText.y + 35, 100, characterFile.idle_anim, 8);
blockPressWhileTypingOn.push(idleInputText);
confirmInputText = new FlxUIInputText(10, idleInputText.y + 35, 100, characterFile.confirm_anim, 8);
blockPressWhileTypingOn.push(confirmInputText);
var reloadImageButton:FlxButton = new FlxButton(10, confirmInputText.y + 30, "Reload Char", function() {
reloadSelectedCharacter();
});
scaleStepper = new FlxUINumericStepper(140, imageInputText.y, 0.05, 1, 0.1, 30, 2);
confirmDescText = new FlxText(10, confirmInputText.y - 18, 0, 'Start Press animation on the .XML:');
tab_group.add(new FlxText(10, imageInputText.y - 18, 0, 'Image file name:'));
tab_group.add(new FlxText(10, idleInputText.y - 18, 0, 'Idle animation on the .XML:'));
tab_group.add(new FlxText(scaleStepper.x, scaleStepper.y - 18, 0, 'Scale:'));
tab_group.add(reloadImageButton);
tab_group.add(confirmDescText);
tab_group.add(imageInputText);
tab_group.add(idleInputText);
tab_group.add(confirmInputText);
tab_group.add(scaleStepper);
UI_mainbox.addGroup(tab_group);
}
function updateCharTypeBox() {
opponentCheckbox.checked = false;
boyfriendCheckbox.checked = false;
girlfriendCheckbox.checked = false;
switch(curTypeSelected) {
case 0:
opponentCheckbox.checked = true;
case 1:
boyfriendCheckbox.checked = true;
case 2:
girlfriendCheckbox.checked = true;
}
updateCharacters();
}
function updateCharacters() {
for (i in 0...3) {
var char:MenuCharacter = grpWeekCharacters.members[i];
char.alpha = 0.2;
char.character = '';
char.changeCharacter(defaultCharacters[i]);
}
reloadSelectedCharacter();
}
function reloadSelectedCharacter() {
var char:MenuCharacter = grpWeekCharacters.members[curTypeSelected];
char.alpha = 1;
char.frames = Paths.getSparrowAtlas('menucharacters/' + characterFile.image);
char.animation.addByPrefix('idle', characterFile.idle_anim, 24);
if(curTypeSelected == 1) char.animation.addByPrefix('confirm', characterFile.confirm_anim, 24, false);
char.scale.set(characterFile.scale, characterFile.scale);
char.updateHitbox();
char.animation.play('idle');
confirmDescText.visible = (curTypeSelected == 1);
confirmInputText.visible = (curTypeSelected == 1);
updateOffset();
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("Menu Character Editor", "Editting: " + characterFile.image);
#end
}
override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>) {
if(id == FlxUIInputText.CHANGE_EVENT && (sender is FlxUIInputText)) {
if(sender == imageInputText) {
characterFile.image = imageInputText.text;
} else if(sender == idleInputText) {
characterFile.idle_anim = idleInputText.text;
} else if(sender == confirmInputText) {
characterFile.confirm_anim = confirmInputText.text;
}
} else if(id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper)) {
if (sender == scaleStepper) {
characterFile.scale = scaleStepper.value;
reloadSelectedCharacter();
}
}
}
override function update(elapsed:Float) {
var blockInput:Bool = false;
for (inputText in blockPressWhileTypingOn) {
if(inputText.hasFocus) {
FlxG.sound.muteKeys = [];
FlxG.sound.volumeDownKeys = [];
FlxG.sound.volumeUpKeys = [];
blockInput = true;
if(FlxG.keys.justPressed.ENTER) inputText.hasFocus = false;
break;
}
}
if(!blockInput) {
FlxG.sound.muteKeys = TitleState.muteKeys;
FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys;
FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys;
if(FlxG.keys.justPressed.ESCAPE) {
FlxG.mouse.visible = false;
MusicBeatState.switchState(new editors.MasterEditorMenu());
FlxG.sound.playMusic(Paths.music('freakyMenu'));
}
var shiftMult:Int = 1;
if(FlxG.keys.pressed.SHIFT) shiftMult = 10;
if(FlxG.keys.justPressed.LEFT) {
characterFile.position[0] += shiftMult;
updateOffset();
}
if(FlxG.keys.justPressed.RIGHT) {
characterFile.position[0] -= shiftMult;
updateOffset();
}
if(FlxG.keys.justPressed.UP) {
characterFile.position[1] += shiftMult;
updateOffset();
}
if(FlxG.keys.justPressed.DOWN) {
characterFile.position[1] -= shiftMult;
updateOffset();
}
if(FlxG.keys.justPressed.SPACE && curTypeSelected == 1) {
grpWeekCharacters.members[curTypeSelected].animation.play('confirm', true);
}
}
var char:MenuCharacter = grpWeekCharacters.members[1];
if(char.animation.curAnim != null && char.animation.curAnim.name == 'confirm' && char.animation.curAnim.finished) {
char.animation.play('idle', true);
}
super.update(elapsed);
}
function updateOffset() {
var char:MenuCharacter = grpWeekCharacters.members[curTypeSelected];
char.offset.set(characterFile.position[0], characterFile.position[1]);
txtOffsets.text = '' + characterFile.position;
}
var _file:FileReference = null;
function loadCharacter() {
var jsonFilter:FileFilter = new FileFilter('JSON', 'json');
_file = new FileReference();
_file.addEventListener(Event.SELECT, onLoadComplete);
_file.addEventListener(Event.CANCEL, onLoadCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file.browse([jsonFilter]);
}
function onLoadComplete(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
#if sys
var fullPath:String = null;
var jsonLoaded = cast Json.parse(Json.stringify(_file)); //Exploit(???) for accessing a private variable
if(jsonLoaded.__path != null) fullPath = jsonLoaded.__path; //I'm either a genious or dangerously dumb
if(fullPath != null) {
var rawJson:String = File.getContent(fullPath);
if(rawJson != null) {
var loadedChar:MenuCharacterFile = cast Json.parse(rawJson);
if(loadedChar.idle_anim != null && loadedChar.confirm_anim != null) //Make sure it's really a character
{
var cutName:String = _file.name.substr(0, _file.name.length - 5);
trace("Successfully loaded file: " + cutName);
characterFile = loadedChar;
reloadSelectedCharacter();
imageInputText.text = characterFile.image;
idleInputText.text = characterFile.image;
confirmInputText.text = characterFile.image;
scaleStepper.value = characterFile.scale;
updateOffset();
_file = null;
return;
}
}
}
_file = null;
#else
trace("File couldn't be loaded! You aren't on Desktop, are you?");
#end
}
/**
* Called when the save file dialog is cancelled.
*/
function onLoadCancel(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Cancelled file loading.");
}
/**
* Called if there is an error while saving the gameplay recording.
*/
function onLoadError(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Problem loading file");
}
function saveCharacter() {
var data:String = Json.stringify(characterFile, "\t");
if (data.length > 0)
{
var splittedImage:Array<String> = imageInputText.text.trim().split('_');
var characterName:String = splittedImage[splittedImage.length-1].toLowerCase().replace(' ', '');
_file = new FileReference();
_file.addEventListener(Event.COMPLETE, onSaveComplete);
_file.addEventListener(Event.CANCEL, onSaveCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file.save(data, characterName + ".json");
}
}
function onSaveComplete(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.notice("Successfully saved file.");
}
/**
* Called when the save file dialog is cancelled.
*/
function onSaveCancel(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
}
/**
* Called if there is an error while saving the gameplay recording.
*/
function onSaveError(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.error("Problem saving file");
}
}

View file

@ -0,0 +1,796 @@
package editors;
#if desktop
import Discord.DiscordClient;
#end
import flixel.FlxG;
import flixel.FlxSprite;
import flixel.addons.display.FlxGridOverlay;
import flixel.addons.transition.FlxTransitionableState;
import flixel.group.FlxGroup.FlxTypedGroup;
import flixel.math.FlxMath;
import flixel.text.FlxText;
import flixel.util.FlxColor;
import flixel.system.FlxSound;
import openfl.utils.Assets;
import flixel.addons.ui.FlxInputText;
import flixel.addons.ui.FlxUI9SliceSprite;
import flixel.addons.ui.FlxUI;
import flixel.addons.ui.FlxUICheckBox;
import flixel.addons.ui.FlxUIInputText;
import flixel.addons.ui.FlxUINumericStepper;
import flixel.addons.ui.FlxUITabMenu;
import flixel.ui.FlxButton;
import openfl.net.FileReference;
import openfl.events.Event;
import openfl.events.IOErrorEvent;
import flash.net.FileFilter;
import lime.system.Clipboard;
import haxe.Json;
#if sys
import sys.io.File;
import sys.FileSystem;
#end
import WeekData;
using StringTools;
class WeekEditorState extends MusicBeatState
{
var txtWeekTitle:FlxText;
var bgSprite:FlxSprite;
var lock:FlxSprite;
var txtTracklist:FlxText;
var grpWeekCharacters:FlxTypedGroup<MenuCharacter>;
var weekThing:MenuItem;
var missingFileText:FlxText;
var weekFile:WeekFile = null;
public function new(weekFile:WeekFile = null)
{
super();
this.weekFile = WeekData.createWeekFile();
if(weekFile != null) this.weekFile = weekFile;
else weekFileName = 'week1';
}
override function create() {
txtWeekTitle = new FlxText(FlxG.width * 0.7, 10, 0, "", 32);
txtWeekTitle.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT);
txtWeekTitle.alpha = 0.7;
var ui_tex = Paths.getSparrowAtlas('campaign_menu_UI_assets');
var bgYellow:FlxSprite = new FlxSprite(0, 56).makeGraphic(FlxG.width, 386, 0xFFF9CF51);
bgSprite = new FlxSprite(0, 56);
bgSprite.antialiasing = ClientPrefs.globalAntialiasing;
weekThing = new MenuItem(0, bgSprite.y + 396, weekFileName);
weekThing.y += weekThing.height + 20;
weekThing.antialiasing = ClientPrefs.globalAntialiasing;
add(weekThing);
var blackBarThingie:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 56, FlxColor.BLACK);
add(blackBarThingie);
grpWeekCharacters = new FlxTypedGroup<MenuCharacter>();
lock = new FlxSprite();
lock.frames = ui_tex;
lock.animation.addByPrefix('lock', 'lock');
lock.animation.play('lock');
lock.antialiasing = ClientPrefs.globalAntialiasing;
add(lock);
missingFileText = new FlxText(0, 0, FlxG.width, "");
missingFileText.setFormat(Paths.font("vcr.ttf"), 24, FlxColor.WHITE, CENTER, FlxTextBorderStyle.OUTLINE, FlxColor.BLACK);
missingFileText.borderSize = 2;
missingFileText.visible = false;
add(missingFileText);
var charArray:Array<String> = weekFile.weekCharacters;
for (char in 0...3)
{
var weekCharacterThing:MenuCharacter = new MenuCharacter((FlxG.width * 0.25) * (1 + char) - 150, charArray[char]);
weekCharacterThing.y += 70;
grpWeekCharacters.add(weekCharacterThing);
}
add(bgYellow);
add(bgSprite);
add(grpWeekCharacters);
var tracksSprite:FlxSprite = new FlxSprite(FlxG.width * 0.07, bgSprite.y + 435).loadGraphic(Paths.image('Menu_Tracks'));
tracksSprite.antialiasing = ClientPrefs.globalAntialiasing;
add(tracksSprite);
txtTracklist = new FlxText(FlxG.width * 0.05, tracksSprite.y + 60, 0, "", 32);
txtTracklist.alignment = CENTER;
txtTracklist.font = Paths.font("vcr.ttf");
txtTracklist.color = 0xFFe55777;
add(txtTracklist);
add(txtWeekTitle);
addEditorBox();
reloadAllShit();
FlxG.mouse.visible = true;
super.create();
}
var UI_box:FlxUITabMenu;
var blockPressWhileTypingOn:Array<FlxUIInputText> = [];
function addEditorBox() {
var tabs = [
{name: 'Week', label: 'Week'},
{name: 'Lock', label: 'Lock'},
];
UI_box = new FlxUITabMenu(null, tabs, true);
UI_box.resize(250, 375);
UI_box.x = FlxG.width - UI_box.width;
UI_box.y = FlxG.height - UI_box.height;
UI_box.scrollFactor.set();
addWeekUI();
addLockUI();
UI_box.selected_tab_id = 'Week';
add(UI_box);
var loadWeekButton:FlxButton = new FlxButton(0, 650, "Load Week", function() {
loadWeek();
});
loadWeekButton.screenCenter(X);
loadWeekButton.x -= 120;
add(loadWeekButton);
var freeplayButton:FlxButton = new FlxButton(0, 650, "Freeplay", function() {
MusicBeatState.switchState(new WeekEditorFreeplayState(weekFile));
});
freeplayButton.screenCenter(X);
add(freeplayButton);
var saveWeekButton:FlxButton = new FlxButton(0, 650, "Save Week", function() {
saveWeek(weekFile);
});
saveWeekButton.screenCenter(X);
saveWeekButton.x += 120;
add(saveWeekButton);
}
var songsInputText:FlxUIInputText;
var backgroundInputText:FlxUIInputText;
var displayNameInputText:FlxUIInputText;
var weekNameInputText:FlxUIInputText;
var weekFileInputText:FlxUIInputText;
var opponentInputText:FlxUIInputText;
var boyfriendInputText:FlxUIInputText;
var girlfriendInputText:FlxUIInputText;
var hideCheckbox:FlxUICheckBox;
public static var weekFileName:String = 'week1';
function addWeekUI() {
var tab_group = new FlxUI(null, UI_box);
tab_group.name = "Week";
songsInputText = new FlxUIInputText(10, 30, 200, '', 8);
blockPressWhileTypingOn.push(songsInputText);
opponentInputText = new FlxUIInputText(10, songsInputText.y + 40, 70, '', 8);
blockPressWhileTypingOn.push(opponentInputText);
boyfriendInputText = new FlxUIInputText(opponentInputText.x + 75, opponentInputText.y, 70, '', 8);
blockPressWhileTypingOn.push(boyfriendInputText);
girlfriendInputText = new FlxUIInputText(boyfriendInputText.x + 75, opponentInputText.y, 70, '', 8);
blockPressWhileTypingOn.push(girlfriendInputText);
backgroundInputText = new FlxUIInputText(10, opponentInputText.y + 40, 120, '', 8);
blockPressWhileTypingOn.push(backgroundInputText);
displayNameInputText = new FlxUIInputText(10, backgroundInputText.y + 60, 200, '', 8);
blockPressWhileTypingOn.push(backgroundInputText);
weekNameInputText = new FlxUIInputText(10, displayNameInputText.y + 60, 150, '', 8);
blockPressWhileTypingOn.push(weekNameInputText);
weekFileInputText = new FlxUIInputText(10, weekNameInputText.y + 40, 100, '', 8);
blockPressWhileTypingOn.push(weekFileInputText);
reloadWeekThing();
hideCheckbox = new FlxUICheckBox(10, weekFileInputText.y + 40, null, null, "Hide Week from Story Mode?", 100);
hideCheckbox.callback = function()
{
weekFile.hideStoryMode = hideCheckbox.checked;
};
tab_group.add(new FlxText(songsInputText.x, songsInputText.y - 18, 0, 'Songs:'));
tab_group.add(new FlxText(opponentInputText.x, opponentInputText.y - 18, 0, 'Characters:'));
tab_group.add(new FlxText(backgroundInputText.x, backgroundInputText.y - 18, 0, 'Background Asset:'));
tab_group.add(new FlxText(displayNameInputText.x, displayNameInputText.y - 18, 0, 'Display Name:'));
tab_group.add(new FlxText(weekNameInputText.x, weekNameInputText.y - 18, 0, 'Week Name (for Reset Score Menu):'));
tab_group.add(new FlxText(weekFileInputText.x, weekFileInputText.y - 18, 0, 'Week File:'));
tab_group.add(songsInputText);
tab_group.add(opponentInputText);
tab_group.add(boyfriendInputText);
tab_group.add(girlfriendInputText);
tab_group.add(backgroundInputText);
tab_group.add(displayNameInputText);
tab_group.add(weekNameInputText);
tab_group.add(weekFileInputText);
tab_group.add(hideCheckbox);
UI_box.addGroup(tab_group);
}
var weekBeforeInputText:FlxUIInputText;
var lockedCheckbox:FlxUICheckBox;
function addLockUI() {
var tab_group = new FlxUI(null, UI_box);
tab_group.name = "Lock";
lockedCheckbox = new FlxUICheckBox(10, 30, null, null, "Week starts Locked", 100);
lockedCheckbox.callback = function()
{
weekFile.startUnlocked = !lockedCheckbox.checked;
lock.visible = lockedCheckbox.checked;
};
weekBeforeInputText = new FlxUIInputText(10, lockedCheckbox.y + 55, 100, '', 8);
blockPressWhileTypingOn.push(weekBeforeInputText);
tab_group.add(new FlxText(weekBeforeInputText.x, weekBeforeInputText.y - 28, 0, 'Week File name of the Week you have\nto finish for Unlocking:'));
tab_group.add(weekBeforeInputText);
tab_group.add(lockedCheckbox);
UI_box.addGroup(tab_group);
}
//Used on onCreate and when you load a week
function reloadAllShit() {
var weekString:String = weekFile.songs[0][0];
for (i in 1...weekFile.songs.length) {
weekString += ', ' + weekFile.songs[i][0];
}
songsInputText.text = weekString;
backgroundInputText.text = weekFile.weekBackground;
displayNameInputText.text = weekFile.storyName;
weekNameInputText.text = weekFile.weekName;
weekFileInputText.text = weekFileName;
opponentInputText.text = weekFile.weekCharacters[0];
boyfriendInputText.text = weekFile.weekCharacters[1];
girlfriendInputText.text = weekFile.weekCharacters[2];
hideCheckbox.checked = weekFile.hideStoryMode;
weekBeforeInputText.text = weekFile.weekBefore;
lockedCheckbox.checked = !weekFile.startUnlocked;
lock.visible = lockedCheckbox.checked;
reloadBG();
reloadWeekThing();
updateText();
}
function updateText()
{
for (i in 0...grpWeekCharacters.length) {
grpWeekCharacters.members[i].changeCharacter(weekFile.weekCharacters[i]);
}
var stringThing:Array<String> = [];
for (i in 0...weekFile.songs.length) {
stringThing.push(weekFile.songs[i][0]);
}
txtTracklist.text = '';
for (i in 0...stringThing.length)
{
txtTracklist.text += stringThing[i] + '\n';
}
txtTracklist.text = txtTracklist.text.toUpperCase();
txtTracklist.screenCenter(X);
txtTracklist.x -= FlxG.width * 0.35;
txtWeekTitle.text = weekFile.storyName.toUpperCase();
txtWeekTitle.x = FlxG.width - (txtWeekTitle.width + 10);
}
function reloadBG() {
bgSprite.visible = true;
var assetName:String = weekFile.weekBackground;
var isMissing:Bool = true;
if(assetName != null && assetName.length > 0) {
if( #if MODS_ALLOWED FileSystem.exists(Paths.modsImages('menubackgrounds/menu_' + assetName)) || #end
Assets.exists(Paths.image('menubackgrounds/menu_' + assetName), IMAGE)) {
bgSprite.loadGraphic(Paths.image('menubackgrounds/menu_' + assetName));
isMissing = false;
}
}
if(isMissing) {
bgSprite.visible = false;
}
}
function reloadWeekThing() {
weekThing.visible = true;
missingFileText.visible = false;
var assetName:String = weekFileInputText.text.trim();
var isMissing:Bool = true;
if(assetName != null && assetName.length > 0) {
if( #if MODS_ALLOWED FileSystem.exists(Paths.modsImages('storymenu/' + assetName)) || #end
Assets.exists(Paths.image('storymenu/' + assetName), IMAGE)) {
weekThing.loadGraphic(Paths.image('storymenu/' + assetName));
isMissing = false;
}
}
if(isMissing) {
weekThing.visible = false;
missingFileText.visible = true;
missingFileText.text = 'MISSING FILE: images/storymenu/' + assetName + '.png';
}
recalculateStuffPosition();
#if desktop
// Updating Discord Rich Presence
DiscordClient.changePresence("Week Editor", "Editting: " + weekFileName);
#end
}
override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>) {
if(id == FlxUIInputText.CHANGE_EVENT && (sender is FlxUIInputText)) {
if(sender == weekFileInputText) {
weekFileName = weekFileInputText.text.trim();
reloadWeekThing();
} else if(sender == opponentInputText || sender == boyfriendInputText || sender == girlfriendInputText) {
weekFile.weekCharacters[0] = opponentInputText.text.trim();
weekFile.weekCharacters[1] = boyfriendInputText.text.trim();
weekFile.weekCharacters[2] = girlfriendInputText.text.trim();
updateText();
} else if(sender == backgroundInputText) {
weekFile.weekBackground = backgroundInputText.text.trim();
reloadBG();
} else if(sender == displayNameInputText) {
weekFile.storyName = displayNameInputText.text.trim();
updateText();
} else if(sender == weekNameInputText) {
weekFile.weekName = weekNameInputText.text.trim();
} else if(sender == songsInputText) {
var splittedText:Array<String> = songsInputText.text.trim().split(',');
for (i in 0...splittedText.length) {
splittedText[i] = splittedText[i].trim();
}
while(splittedText.length < weekFile.songs.length) {
weekFile.songs.pop();
}
for (i in 0...splittedText.length) {
if(i >= weekFile.songs.length) { //Add new song
weekFile.songs.push([splittedText[i], 'dad', [146, 113, 253]]);
} else { //Edit song
weekFile.songs[i][0] = splittedText[i];
if(weekFile.songs[i][1] == null || weekFile.songs[i][1]) {
weekFile.songs[i][1] = 'dad';
weekFile.songs[i][2] = [146, 113, 253];
}
}
}
updateText();
} else if(sender == weekBeforeInputText) {
weekFile.weekBefore = weekBeforeInputText.text.trim();
}
}
}
override function update(elapsed:Float)
{
if(loadedWeek != null) {
weekFile = loadedWeek;
loadedWeek = null;
reloadAllShit();
}
var blockInput:Bool = false;
for (inputText in blockPressWhileTypingOn) {
if(inputText.hasFocus) {
FlxG.sound.muteKeys = [];
FlxG.sound.volumeDownKeys = [];
FlxG.sound.volumeUpKeys = [];
blockInput = true;
if(FlxG.keys.justPressed.ENTER) inputText.hasFocus = false;
break;
}
}
if(!blockInput) {
FlxG.sound.muteKeys = TitleState.muteKeys;
FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys;
FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys;
if(FlxG.keys.justPressed.ESCAPE) {
FlxG.mouse.visible = false;
MusicBeatState.switchState(new editors.MasterEditorMenu());
FlxG.sound.playMusic(Paths.music('freakyMenu'));
}
}
super.update(elapsed);
lock.y = weekThing.y;
missingFileText.y = weekThing.y + 36;
}
function recalculateStuffPosition() {
weekThing.screenCenter(X);
lock.x = weekThing.width + 10 + weekThing.x;
}
private static var _file:FileReference;
public static function loadWeek() {
var jsonFilter:FileFilter = new FileFilter('JSON', 'json');
_file = new FileReference();
_file.addEventListener(Event.SELECT, onLoadComplete);
_file.addEventListener(Event.CANCEL, onLoadCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file.browse([jsonFilter]);
}
public static var loadedWeek:WeekFile = null;
public static var loadError:Bool = false;
private static function onLoadComplete(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
#if sys
var fullPath:String = null;
var jsonLoaded = cast Json.parse(Json.stringify(_file)); //Exploit(???) for accessing a private variable
if(jsonLoaded.__path != null) fullPath = jsonLoaded.__path; //I'm either a genious or dangerously dumb
if(fullPath != null) {
var rawJson:String = File.getContent(fullPath);
if(rawJson != null) {
loadedWeek = cast Json.parse(rawJson);
if(loadedWeek.weekCharacters != null && loadedWeek.weekName != null) //Make sure it's really a week
{
var cutName:String = _file.name.substr(0, _file.name.length - 5);
trace("Successfully loaded file: " + cutName);
loadError = false;
weekFileName = cutName;
_file = null;
return;
}
}
}
loadError = true;
loadedWeek = null;
_file = null;
#else
trace("File couldn't be loaded! You aren't on Desktop, are you?");
#end
}
/**
* Called when the save file dialog is cancelled.
*/
private static function onLoadCancel(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Cancelled file loading.");
}
/**
* Called if there is an error while saving the gameplay recording.
*/
private static function onLoadError(_):Void
{
_file.removeEventListener(Event.SELECT, onLoadComplete);
_file.removeEventListener(Event.CANCEL, onLoadCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onLoadError);
_file = null;
trace("Problem loading file");
}
public static function saveWeek(weekFile:WeekFile) {
var data:String = Json.stringify(weekFile, "\t");
if (data.length > 0)
{
_file = new FileReference();
_file.addEventListener(Event.COMPLETE, onSaveComplete);
_file.addEventListener(Event.CANCEL, onSaveCancel);
_file.addEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file.save(data, weekFileName + ".json");
}
}
private static function onSaveComplete(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.notice("Successfully saved file.");
}
/**
* Called when the save file dialog is cancelled.
*/
private static function onSaveCancel(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
}
/**
* Called if there is an error while saving the gameplay recording.
*/
private static function onSaveError(_):Void
{
_file.removeEventListener(Event.COMPLETE, onSaveComplete);
_file.removeEventListener(Event.CANCEL, onSaveCancel);
_file.removeEventListener(IOErrorEvent.IO_ERROR, onSaveError);
_file = null;
FlxG.log.error("Problem saving file");
}
}
class WeekEditorFreeplayState extends MusicBeatState
{
var weekFile:WeekFile = null;
public function new(weekFile:WeekFile = null)
{
super();
this.weekFile = WeekData.createWeekFile();
if(weekFile != null) this.weekFile = weekFile;
}
var bg:FlxSprite;
private var grpSongs:FlxTypedGroup<Alphabet>;
private var iconArray:Array<HealthIcon> = [];
var curSelected = 0;
override function create() {
bg = new FlxSprite().loadGraphic(Paths.image('menuDesat'));
bg.antialiasing = ClientPrefs.globalAntialiasing;
bg.color = FlxColor.WHITE;
add(bg);
grpSongs = new FlxTypedGroup<Alphabet>();
add(grpSongs);
for (i in 0...weekFile.songs.length)
{
var songText:Alphabet = new Alphabet(0, (70 * i) + 30, weekFile.songs[i][0], true, false);
songText.isMenuItem = true;
songText.targetY = i;
grpSongs.add(songText);
var icon:HealthIcon = new HealthIcon(weekFile.songs[i][1]);
icon.sprTracker = songText;
// using a FlxGroup is too much fuss!
iconArray.push(icon);
add(icon);
// songText.x += 40;
// DONT PUT X IN THE FIRST PARAMETER OF new ALPHABET() !!
// songText.screenCenter(X);
}
addEditorBox();
changeSelection();
super.create();
}
var UI_box:FlxUITabMenu;
var blockPressWhileTypingOn:Array<FlxUIInputText> = [];
function addEditorBox() {
var tabs = [
{name: 'Freeplay', label: 'Freeplay'},
];
UI_box = new FlxUITabMenu(null, tabs, true);
UI_box.resize(250, 200);
UI_box.x = FlxG.width - UI_box.width - 100;
UI_box.y = FlxG.height - UI_box.height - 60;
UI_box.scrollFactor.set();
UI_box.selected_tab_id = 'Week';
addFreeplayUI();
add(UI_box);
var blackBlack:FlxSprite = new FlxSprite(0, 670).makeGraphic(FlxG.width, 50, FlxColor.BLACK);
blackBlack.alpha = 0.6;
add(blackBlack);
var loadWeekButton:FlxButton = new FlxButton(0, 685, "Load Week", function() {
WeekEditorState.loadWeek();
});
loadWeekButton.screenCenter(X);
loadWeekButton.x -= 120;
add(loadWeekButton);
var storyModeButton:FlxButton = new FlxButton(0, 685, "Story Mode", function() {
MusicBeatState.switchState(new WeekEditorState(weekFile));
});
storyModeButton.screenCenter(X);
add(storyModeButton);
var saveWeekButton:FlxButton = new FlxButton(0, 685, "Save Week", function() {
WeekEditorState.saveWeek(weekFile);
});
saveWeekButton.screenCenter(X);
saveWeekButton.x += 120;
add(saveWeekButton);
}
override function getEvent(id:String, sender:Dynamic, data:Dynamic, ?params:Array<Dynamic>) {
if(id == FlxUIInputText.CHANGE_EVENT && (sender is FlxUIInputText)) {
weekFile.songs[curSelected][1] = iconInputText.text;
iconArray[curSelected].changeIcon(iconInputText.text);
} else if(id == FlxUINumericStepper.CHANGE_EVENT && (sender is FlxUINumericStepper)) {
if(sender == bgColorStepperR || sender == bgColorStepperG || sender == bgColorStepperB) {
updateBG();
}
}
}
var bgColorStepperR:FlxUINumericStepper;
var bgColorStepperG:FlxUINumericStepper;
var bgColorStepperB:FlxUINumericStepper;
var iconInputText:FlxUIInputText;
function addFreeplayUI() {
var tab_group = new FlxUI(null, UI_box);
tab_group.name = "Freeplay";
bgColorStepperR = new FlxUINumericStepper(10, 40, 20, 255, 0, 255, 0);
bgColorStepperG = new FlxUINumericStepper(80, 40, 20, 255, 0, 255, 0);
bgColorStepperB = new FlxUINumericStepper(150, 40, 20, 255, 0, 255, 0);
var copyColor:FlxButton = new FlxButton(10, bgColorStepperR.y + 25, "Copy Color", function() {
Clipboard.text = bg.color.red + ',' + bg.color.green + ',' + bg.color.blue;
});
var pasteColor:FlxButton = new FlxButton(140, copyColor.y, "Paste Color", function() {
if(Clipboard.text != null) {
var leColor:Array<Int> = [];
var splitted:Array<String> = Clipboard.text.trim().split(',');
for (i in 0...splitted.length) {
var toPush:Int = Std.parseInt(splitted[i]);
if(!Math.isNaN(toPush)) {
if(toPush > 255) toPush = 255;
else if(toPush < 0) toPush *= -1;
leColor.push(toPush);
}
}
if(leColor.length > 2) {
bgColorStepperR.value = leColor[0];
bgColorStepperG.value = leColor[1];
bgColorStepperB.value = leColor[2];
updateBG();
}
}
});
iconInputText = new FlxUIInputText(10, bgColorStepperR.y + 70, 100, '', 8);
var hideFreeplayCheckbox:FlxUICheckBox = new FlxUICheckBox(10, iconInputText.y + 30, null, null, "Hide Week from Freeplay?", 100);
hideFreeplayCheckbox.checked = weekFile.hideFreeplay;
hideFreeplayCheckbox.callback = function()
{
weekFile.hideFreeplay = hideFreeplayCheckbox.checked;
};
tab_group.add(new FlxText(10, bgColorStepperR.y - 18, 0, 'Selected background Color R/G/B:'));
tab_group.add(new FlxText(10, iconInputText.y - 18, 0, 'Selected icon:'));
tab_group.add(bgColorStepperR);
tab_group.add(bgColorStepperG);
tab_group.add(bgColorStepperB);
tab_group.add(copyColor);
tab_group.add(pasteColor);
tab_group.add(iconInputText);
tab_group.add(hideFreeplayCheckbox);
UI_box.addGroup(tab_group);
}
function updateBG() {
weekFile.songs[curSelected][2][0] = Math.round(bgColorStepperR.value);
weekFile.songs[curSelected][2][1] = Math.round(bgColorStepperG.value);
weekFile.songs[curSelected][2][2] = Math.round(bgColorStepperB.value);
bg.color = FlxColor.fromRGB(weekFile.songs[curSelected][2][0], weekFile.songs[curSelected][2][1], weekFile.songs[curSelected][2][2]);
}
function changeSelection(change:Int = 0) {
FlxG.sound.play(Paths.sound('scrollMenu'), 0.4);
curSelected += change;
if (curSelected < 0)
curSelected = weekFile.songs.length - 1;
if (curSelected >= weekFile.songs.length)
curSelected = 0;
var bullShit:Int = 0;
for (i in 0...iconArray.length)
{
iconArray[i].alpha = 0.6;
}
iconArray[curSelected].alpha = 1;
for (item in grpSongs.members)
{
item.targetY = bullShit - curSelected;
bullShit++;
item.alpha = 0.6;
// item.setGraphicSize(Std.int(item.width * 0.8));
if (item.targetY == 0)
{
item.alpha = 1;
// item.setGraphicSize(Std.int(item.width));
}
}
trace(weekFile.songs[curSelected]);
iconInputText.text = weekFile.songs[curSelected][1];
bgColorStepperR.value = Math.round(weekFile.songs[curSelected][2][0]);
bgColorStepperG.value = Math.round(weekFile.songs[curSelected][2][1]);
bgColorStepperB.value = Math.round(weekFile.songs[curSelected][2][2]);
updateBG();
}
override function update(elapsed:Float) {
if(WeekEditorState.loadedWeek != null) {
super.update(elapsed);
FlxTransitionableState.skipNextTransIn = true;
FlxTransitionableState.skipNextTransOut = true;
MusicBeatState.switchState(new WeekEditorFreeplayState(WeekEditorState.loadedWeek));
WeekEditorState.loadedWeek = null;
return;
}
if(iconInputText.hasFocus) {
FlxG.sound.muteKeys = [];
FlxG.sound.volumeDownKeys = [];
FlxG.sound.volumeUpKeys = [];
if(FlxG.keys.justPressed.ENTER) {
iconInputText.hasFocus = false;
}
} else {
FlxG.sound.muteKeys = TitleState.muteKeys;
FlxG.sound.volumeDownKeys = TitleState.volumeDownKeys;
FlxG.sound.volumeUpKeys = TitleState.volumeUpKeys;
if(FlxG.keys.justPressed.ESCAPE) {
FlxG.mouse.visible = false;
MusicBeatState.switchState(new editors.MasterEditorMenu());
FlxG.sound.playMusic(Paths.music('freakyMenu'));
}
if(controls.UI_UP_P) changeSelection(-1);
if(controls.UI_DOWN_P) changeSelection(1);
}
super.update(elapsed);
}
}