366 lines
14 KiB
Haxe
366 lines
14 KiB
Haxe
package funkin.editors.charter;
|
|
|
|
import flixel.text.FlxText.FlxTextFormat;
|
|
import flixel.text.FlxText.FlxTextFormatMarkerPair;
|
|
import funkin.backend.shaders.CustomShader;
|
|
import flixel.math.FlxRect;
|
|
import funkin.game.Character;
|
|
import funkin.game.Stage;
|
|
import funkin.game.HealthIcon;
|
|
import funkin.backend.chart.ChartData;
|
|
import haxe.io.Bytes;
|
|
|
|
class ChartCreationScreen extends UISubstateWindow {
|
|
private var onSave:(String, ChartData) -> Void = null;
|
|
public var charFileList:Array<String> = [];
|
|
|
|
public var difficultyNameTextBox:UITextBox;
|
|
public var scrollSpeedTextBox:UINumericStepper;
|
|
public var stageTextBox:UIAutoCompleteTextBox;
|
|
public var strumLineList:UIButtonList<StrumLineButton>;
|
|
|
|
public var saveButton:UIButton;
|
|
public var closeButton:UIButton;
|
|
|
|
public function new(?onSave:(String, ChartData)->Void) {
|
|
super();
|
|
if (onSave != null) this.onSave = onSave;
|
|
}
|
|
|
|
public override function create() {
|
|
winTitle = "Creating New Chart";
|
|
|
|
winWidth = 652;
|
|
winHeight = 600;
|
|
|
|
super.create();
|
|
|
|
function addLabelOn(ui:UISprite, text:String):UIText {
|
|
var text:UIText = new UIText(ui.x, ui.y - 24, 0, text);
|
|
ui.members.push(text);
|
|
return text;
|
|
}
|
|
|
|
charFileList = Character.getList(true);
|
|
if (charFileList.length == 0) charFileList = Character.getList(false);
|
|
|
|
var chartTitle:UIText;
|
|
add(chartTitle = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Chart Info", 28));
|
|
|
|
difficultyNameTextBox = new UITextBox(chartTitle.x, chartTitle.y + chartTitle.height + 36, "difficulty", 200);
|
|
add(difficultyNameTextBox);
|
|
addLabelOn(difficultyNameTextBox, "Difficulty Name");
|
|
|
|
var stageFileList = Stage.getList(true);
|
|
if (stageFileList.length == 0) stageFileList = Stage.getList(false);
|
|
|
|
stageTextBox = new UIAutoCompleteTextBox(difficultyNameTextBox.x + 200 + 26, difficultyNameTextBox.y, "stage", 180);
|
|
stageTextBox.suggestItems = stageFileList;
|
|
add(stageTextBox);
|
|
addLabelOn(stageTextBox, "Stage");
|
|
|
|
scrollSpeedTextBox = new UINumericStepper(stageTextBox.x + 180 + 26, difficultyNameTextBox.y, 1.0, 0.1, 2, null, null, 90);
|
|
scrollSpeedTextBox.onChange = function (text:String) {
|
|
@:privateAccess scrollSpeedTextBox.__onChange(text);
|
|
for (button in strumLineList.buttons.members)
|
|
if (button.usesChartscrollSpeed.checked)
|
|
button.scrollSpeedStepper.value = scrollSpeedTextBox.value;
|
|
}
|
|
add(scrollSpeedTextBox);
|
|
addLabelOn(scrollSpeedTextBox, "Scroll Speed");
|
|
|
|
strumLineList = new UIButtonList<StrumLineButton>(difficultyNameTextBox.x, difficultyNameTextBox.y+difficultyNameTextBox.bHeight+36, 620, (552-179)-16, "", FlxPoint.get(620, 246), null, 6);
|
|
strumLineList.frames = Paths.getFrames('editors/ui/inputbox');
|
|
strumLineList.cameraSpacing = 0;
|
|
|
|
strumLineList.addButton.callback = function() {
|
|
strumLineList.add(new StrumLineButton(strumLineList.buttons.length, {
|
|
characters: ["dad"],
|
|
type: 0,
|
|
notes: null,
|
|
position: "DAD",
|
|
strumPos: [0, 50],
|
|
strumLinePos: 0.25,
|
|
}, strumLineList));
|
|
}
|
|
|
|
// DEFAULTS
|
|
strumLineList.add(new StrumLineButton(0, {
|
|
characters: ["dad"],
|
|
type: 0,
|
|
notes: null,
|
|
position: "DAD",
|
|
strumPos: [0, 50],
|
|
strumLinePos: 0.25,
|
|
scrollSpeed: 1,
|
|
}, strumLineList));
|
|
strumLineList.add(new StrumLineButton(1, {
|
|
characters: ["bf"],
|
|
type: 1,
|
|
notes: null,
|
|
position: "BOYFRIEND",
|
|
strumPos: [0, 50],
|
|
strumLinePos: 0.75,
|
|
scrollSpeed: 1,
|
|
}, strumLineList));
|
|
strumLineList.add(new StrumLineButton(2, {
|
|
characters: ["gf"],
|
|
type: 2,
|
|
notes: null,
|
|
position: "GIRLFRIEND",
|
|
strumPos: [0, 50],
|
|
strumLinePos: 0.50,
|
|
scrollSpeed: 1,
|
|
visible: false,
|
|
}, strumLineList));
|
|
|
|
add(strumLineList);
|
|
addLabelOn(strumLineList, "Strumlines").applyMarkup(
|
|
"Strumlines $* Atleast 1 Strumline Required$",
|
|
[new FlxTextFormatMarkerPair(new FlxTextFormat(0xFFAD1212), "$")]);
|
|
|
|
strumLineList.dragCallback = (object:StrumLineButton, oldIndex:Int, newIndex:Int) -> {object.idText.text = 'Strumline - #${newIndex}';};
|
|
scrollSpeedTextBox.onChange(scrollSpeedTextBox.label.text);
|
|
|
|
saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20 - 125, windowSpr.y + windowSpr.bHeight - 16 - 32, "Save & Close", function() {
|
|
createChart();
|
|
close();
|
|
}, 125);
|
|
add(saveButton);
|
|
|
|
closeButton = new UIButton(saveButton.x - 20 - saveButton.bWidth, saveButton.y, "Cancel", function() {
|
|
close();
|
|
}, 125);
|
|
add(closeButton);
|
|
closeButton.color = 0xFFFF0000;
|
|
}
|
|
|
|
public override function update(elapsed:Float) {
|
|
saveButton.selectable = strumLineList.buttons.members.length != 0;
|
|
saveButton.alpha = saveButton.field.alpha = saveButton.selectable ? 1 : 0.4;
|
|
super.update(elapsed);
|
|
}
|
|
|
|
public function createChart() {
|
|
scrollSpeedTextBox.onChange(scrollSpeedTextBox.label.text);
|
|
|
|
var strumLines:Array<ChartStrumLine> = [];
|
|
for (strline in strumLineList.buttons.members) {
|
|
for (stepper in [strline.hudXStepper, strline.hudYStepper, strline.hudScaleStepper])
|
|
@:privateAccess stepper.__onChange(stepper.label.text);
|
|
|
|
strumLines.push({
|
|
characters: [for (charb in strline.charactersList.buttons.members) charb.textBox.label.text],
|
|
type: strline.typeDropdown.index,
|
|
notes: [],
|
|
position: strline.stagePositionDropdown.label.text.toLowerCase(),
|
|
visible: strline.visibleCheckbox.checked,
|
|
strumPos: [0, strline.hudYStepper.value],
|
|
strumLinePos: strline.hudXStepper.value,
|
|
strumScale: strline.hudScaleStepper.value,
|
|
scrollSpeed: strline.usesChartscrollSpeed.checked ? strline.scrollSpeedStepper.value : null
|
|
});
|
|
}
|
|
|
|
var chartData:ChartData = {
|
|
codenameChart: true,
|
|
strumLines: strumLines,
|
|
stage: stageTextBox.label.text,
|
|
scrollSpeed: scrollSpeedTextBox.value,
|
|
events: [],
|
|
noteTypes: [],
|
|
meta: null
|
|
}
|
|
|
|
if (onSave != null) onSave(difficultyNameTextBox.label.text, chartData);
|
|
}
|
|
}
|
|
|
|
class StrumLineButton extends UIButton {
|
|
public var idText:UIText;
|
|
|
|
public var charactersList:UIButtonList<CompactCharacterButton>;
|
|
public var typeDropdown:UIDropDown;
|
|
public var stagePositionDropdown:UIDropDown;
|
|
public var hudScaleStepper:UINumericStepper;
|
|
public var hudXStepper:UINumericStepper;
|
|
public var hudYStepper:UINumericStepper;
|
|
public var visibleCheckbox:UICheckbox;
|
|
public var scrollSpeedStepper:UINumericStepper;
|
|
public var usesChartscrollSpeed:UICheckbox;
|
|
|
|
public var deleteButton:UIButton;
|
|
public var deleteIcon:FlxSprite;
|
|
|
|
public var labels:Map<UISprite, UIText> = [];
|
|
public var XYComma:UIText;
|
|
|
|
public var cameraClipShader:CustomShader;
|
|
|
|
public function new(id:Int, strumLine:ChartStrumLine, parent:UIButtonList<StrumLineButton>) {
|
|
super(0, 0, '', function () {}, 620, 246);
|
|
|
|
var subState:ChartCreationScreen = cast FlxG.state.subState;
|
|
autoAlpha = false; frames = Paths.getFrames('editors/ui/inputbox');
|
|
|
|
function addLabelOn(ui:UISprite, text:String, ?size:Int):UIText {
|
|
var uiText:UIText = new UIText(ui.x, ui.y - 24, 0, text, size);
|
|
members.push(uiText); labels.set(ui, uiText);
|
|
return uiText;
|
|
}
|
|
|
|
charactersList = new UIButtonList<CompactCharacterButton>(16, 8+26, 210, 160, "", FlxPoint.get(200, 40), null, 5);
|
|
charactersList.frames = Paths.getFrames('editors/ui/inputbox');
|
|
charactersList.cameraSpacing = 0;
|
|
|
|
charactersList.addButton.callback = function()
|
|
charactersList.add(new CompactCharacterButton("New Char", subState.charFileList, charactersList));
|
|
for (character in strumLine.characters)
|
|
charactersList.add(new CompactCharacterButton(character, subState.charFileList, charactersList));
|
|
|
|
members.push(charactersList);
|
|
idText = addLabelOn(charactersList, 'Strumline - #$id');
|
|
|
|
cameraClipShader = new CustomShader("engine/cameraClip");
|
|
cameraClipShader.hset("clipRect", [0, 0, 100, 100]);
|
|
charactersList.buttonCameras.addShader(cameraClipShader);
|
|
|
|
typeDropdown = new UIDropDown(charactersList.x + charactersList.bWidth + 16, 8+26, 200, 32, ["OPPONENT", "PLAYER", "ADDITIONAL"], strumLine.type);
|
|
members.push(typeDropdown);
|
|
addLabelOn(typeDropdown, "Type");
|
|
|
|
var stagePositionI = strumLine.position == null ? strumLine.type : ["DAD", "BOYFRIEND", "GIRLFRIEND"].indexOf(strumLine.position.toUpperCase());
|
|
|
|
stagePositionDropdown = new UIDropDown(typeDropdown.x + 200 - 32 + 26, typeDropdown.y, 200, 32, ["DAD", "BOYFRIEND", "GIRLFRIEND"], stagePositionI);
|
|
members.push(stagePositionDropdown);
|
|
addLabelOn(stagePositionDropdown, "Stage Position");
|
|
|
|
hudScaleStepper = new UINumericStepper(typeDropdown.x, typeDropdown.y + 64, strumLine.strumScale == null ? 1 : strumLine.strumScale, 0.001, 2, null, null, 74);
|
|
members.push(hudScaleStepper);
|
|
addLabelOn(hudScaleStepper, "Scale");
|
|
|
|
var strOffset:Float = strumLine.strumLinePos == null ? (strumLine.type == 1 ? 0.75 : 0.25) : strumLine.strumLinePos;
|
|
|
|
var startingPos:FlxPoint = strumLine.strumLinePos == null ?
|
|
FlxPoint.get(strOffset, 50) :
|
|
FlxPoint.get(strOffset, strumLine.strumPos[1]);
|
|
|
|
hudXStepper = new UINumericStepper(hudScaleStepper.x + 80 - 32 + 26, hudScaleStepper.y, startingPos.x, 0.01, 2, 0, 2, 84);
|
|
members.push(hudXStepper);
|
|
addLabelOn(hudXStepper, "Hud Position (X [Ratio 0-1],Y)");
|
|
|
|
members.push(XYComma = new UIText(hudXStepper.x + 84 - 32 + 0, hudXStepper.y + 9, 0, ",", 22));
|
|
|
|
hudYStepper = new UINumericStepper(hudXStepper.x + 84 - 32 + 26, hudXStepper.y, startingPos.y, 0.001, 2, null, null, 84);
|
|
members.push(hudYStepper);
|
|
|
|
visibleCheckbox = new UICheckbox(hudYStepper.x + hudYStepper.bWidth + 42, hudYStepper.y + 9, "Visible?", strumLine.visible == null ? true : strumLine.visible);
|
|
members.push(visibleCheckbox);
|
|
|
|
scrollSpeedStepper = new UINumericStepper(typeDropdown.x, typeDropdown.y + 128, strumLine.scrollSpeed, 0.1, 2, 0, 10, 82);
|
|
scrollSpeedStepper.selectable = strumLine.scrollSpeed != null;
|
|
members.push(scrollSpeedStepper);
|
|
addLabelOn(scrollSpeedStepper, "Scroll Speed");
|
|
|
|
usesChartscrollSpeed = new UICheckbox(scrollSpeedStepper.x + 104, typeDropdown.y + 135, "Uses charts scroll speed?", strumLine.scrollSpeed == null);
|
|
usesChartscrollSpeed.onChecked = function(b) {
|
|
if(b) {
|
|
scrollSpeedStepper.value = subState.scrollSpeedTextBox.value;
|
|
scrollSpeedStepper.selectable = false;
|
|
} else
|
|
scrollSpeedStepper.selectable = true;
|
|
}
|
|
members.push(usesChartscrollSpeed);
|
|
|
|
deleteButton = new UIButton(16, 246-32-11, "", function () {
|
|
parent.remove(this);
|
|
}, 620-32);
|
|
deleteButton.color = 0xFFFF0000;
|
|
deleteButton.autoAlpha = false;
|
|
members.push(deleteButton);
|
|
|
|
deleteIcon = new FlxSprite(deleteButton.x + ((deleteButton.bWidth/2)-(15/2)), deleteButton.y + ((deleteButton.bHeight/2)-(16/2))).loadGraphic(Paths.image('editors/delete-button'));
|
|
deleteIcon.antialiasing = false;
|
|
members.push(deleteIcon);
|
|
}
|
|
|
|
public override function update(elapsed:Float) {
|
|
super.update(elapsed);
|
|
|
|
charactersList.follow(this, 16, 8+26);
|
|
typeDropdown.follow(this, charactersList.x + charactersList.bWidth + 16, 8+26);
|
|
stagePositionDropdown.follow(this, typeDropdown.x + 200 - 32 + 26, 8+26);
|
|
hudScaleStepper.follow(this, typeDropdown.x, 8+26 + 64);
|
|
hudXStepper.follow(this, hudScaleStepper.x + 80 - 32 + 26, 8+26 + 64);
|
|
hudYStepper.follow(this, hudXStepper.x + 84 - 32 + 26, 8+26 + 64);
|
|
visibleCheckbox.follow(this, hudYStepper.x + hudYStepper.bWidth + 42, 8+26 + 64 + 9);
|
|
scrollSpeedStepper.follow(this, typeDropdown.x, 8+26 + 128);
|
|
usesChartscrollSpeed.follow(this, scrollSpeedStepper.x + 104, 8+26 + 135);
|
|
|
|
deleteButton.follow(this, 16, 246-32-11);
|
|
deleteIcon.follow(this, 16 + ((deleteButton.bWidth/2)-(15/2)), (246-32-11) + ((deleteButton.bHeight/2)-(16/2)));
|
|
|
|
XYComma.follow(hudXStepper, 84 - 32, 9);
|
|
for (ui => text in labels)
|
|
text.follow(ui, 0, -24);
|
|
|
|
var subState:ChartCreationScreen = cast FlxG.state.subState;
|
|
var strumLineList:UIButtonList<StrumLineButton> = subState.strumLineList;
|
|
cameraClipShader.hset("clipRect", [0, (-y-(8+26))+cameras[0].scroll.y, strumLineList.bWidth, strumLineList.bHeight]);
|
|
}
|
|
}
|
|
|
|
class CompactCharacterButton extends UIButton {
|
|
public var charIcon:HealthIcon;
|
|
public var textBox:UIAutoCompleteTextBox;
|
|
public var deleteButton:UIButton;
|
|
public var deleteIcon:FlxSprite;
|
|
|
|
public function new(char:String, charsList:Array<String>, parent:UIButtonList<CompactCharacterButton>) {
|
|
super(0, 0, "", null, 200, 40);
|
|
autoAlpha = false;
|
|
|
|
charIcon = new HealthIcon(funkin.game.Character.getIconFromCharName(char));
|
|
charIcon.scale.set(0.2, 0.2);
|
|
charIcon.updateHitbox();
|
|
charIcon.setPosition(10, bHeight/2 - charIcon.height / 2);
|
|
charIcon.scrollFactor.set(1,1);
|
|
|
|
members.push(charIcon);
|
|
|
|
members.push(textBox = new UIAutoCompleteTextBox(charIcon.x + charIcon.width + 16, bHeight/2 - (32/2), char, 115));
|
|
textBox.suggestItems = charsList;
|
|
textBox.antialiasing = true;
|
|
textBox.onChange = function(char:String) {
|
|
char = funkin.game.Character.getIconFromCharName(char);
|
|
var image = Paths.image("icons/" + char);
|
|
if(!Assets.exists(image))
|
|
image = Paths.image("icons/face");
|
|
charIcon.loadGraphic(image, true, 150, 150);
|
|
charIcon.updateHitbox();
|
|
}
|
|
|
|
deleteButton = new UIButton(textBox.x + 115 + 16, bHeight/2 - (32/2), "", function () {
|
|
parent.remove(this);
|
|
}, 32);
|
|
deleteButton.color = 0xFFFF0000;
|
|
deleteButton.autoAlpha = false;
|
|
members.push(deleteButton);
|
|
|
|
deleteIcon = new FlxSprite(deleteButton.x + (15/2), deleteButton.y + 8).loadGraphic(Paths.image('editors/delete-button'));
|
|
deleteIcon.antialiasing = false;
|
|
members.push(deleteIcon);
|
|
}
|
|
|
|
override function update(elapsed) {
|
|
charIcon.follow(this, 6, bHeight / 2 - charIcon.height / 2);
|
|
textBox.follow(charIcon, charIcon.width + 6, 0);
|
|
deleteButton.follow(textBox, 115 + 6, 0);
|
|
deleteIcon.follow(deleteButton, 15 / 2, 8);
|
|
|
|
deleteButton.selectable = selectable;
|
|
deleteButton.shouldPress = shouldPress;
|
|
|
|
super.update(elapsed);
|
|
}
|
|
} |