Edit Metadata WIP Menu
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
#pragma header
|
||||
|
||||
vec3 hsvToRgb(vec3 hsv){ //hsv.x = hue, hsv.y = saturation, hsv.z = value
|
||||
vec3 col = vec3(hsv.x, hsv.x + 2.0/3.0, hsv.x + 4.0/3.0); //inputs for r, g, and b
|
||||
col = clamp(abs(mod(col*2.0, 2.0)-1.0)*3.0 - 1.0, 0.0, 1.0)*hsv.z*hsv.y + hsv.z - hsv.z*hsv.y; //hue function (graph it on desmos)
|
||||
return col;
|
||||
}
|
||||
|
||||
uniform float hue;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec2 uv = openfl_TextureCoordv.xy;
|
||||
vec4 col = texture2D(bitmap, uv);
|
||||
|
||||
if (col.a > 0.0)
|
||||
col = vec4(hsvToRgb(vec3(hue, uv.x, 1.0-uv.y)), 0.0);
|
||||
|
||||
gl_FragColor = col;
|
||||
}
|
||||
@@ -46,13 +46,14 @@ class MainState extends FlxState {
|
||||
EventsData.reloadEvents();
|
||||
TitleState.initialized = false;
|
||||
|
||||
|
||||
/*
|
||||
if (betaWarningShown)
|
||||
FlxG.switchState(new TitleState());
|
||||
else {
|
||||
FlxG.switchState(new BetaWarningState());
|
||||
betaWarningShown = true;
|
||||
}
|
||||
}*/
|
||||
FlxG.switchState(new funkin.editors.charter.Charter("gamebreaker", "normal"));
|
||||
|
||||
#if sys
|
||||
sys.FileSystem.createDirectory('./.temp/');
|
||||
|
||||
@@ -187,7 +187,8 @@ class Charter extends UIState {
|
||||
},
|
||||
null,
|
||||
{
|
||||
label: "Edit metadata information"
|
||||
label: "Edit metadata information",
|
||||
onSelect: chart_edit_metadata
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -928,6 +929,8 @@ class Charter extends UIState {
|
||||
function _chart_enablescripts(t) {
|
||||
t.icon = (Options.charterEnablePlaytestScripts = !Options.charterEnablePlaytestScripts) ? 1 : 0;
|
||||
}
|
||||
function chart_edit_metadata(_)
|
||||
FlxG.state.openSubState(new MetaDataScreen(PlayState.SONG.meta));
|
||||
|
||||
function _playback_metronome(t) {
|
||||
t.icon = (Options.charterMetronomeEnabled = !Options.charterMetronomeEnabled) ? 1 : 0;
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package funkin.editors.charter;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.backend.chart.ChartData.ChartMetaData;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class MetaDataScreen extends UISubstateWindow {
|
||||
public var metadata:ChartMetaData;
|
||||
public var saveButton:UIButton;
|
||||
|
||||
public var songNameTextBox:UITextBox;
|
||||
public var bpmStepper:UINumericStepper;
|
||||
public var stepsPerBeatStepper:UINumericStepper;
|
||||
public var beatsPerMesureStepper:UINumericStepper;
|
||||
public var needsVoicesCheckbox:UICheckbox;
|
||||
|
||||
public var displayNameTextBox:UITextBox;
|
||||
public var iconTextBox:UITextBox;
|
||||
public var iconSprite:FlxSprite;
|
||||
public var opponentModeCheckbox:UICheckbox;
|
||||
public var coopAllowedCheckbox:UICheckbox;
|
||||
public var colorWheel:UIColorwheel;
|
||||
public var difficulitesTextBox:UITextBox;
|
||||
|
||||
public function new(metadata:ChartMetaData) {
|
||||
super();
|
||||
this.metadata = metadata;
|
||||
trace(metadata);
|
||||
}
|
||||
|
||||
public override function create() {
|
||||
winTitle = "Edit Metadata";
|
||||
winWidth = 748 - 32 + 40;
|
||||
|
||||
super.create();
|
||||
FlxG.sound.music.pause();
|
||||
|
||||
function addLabelOn(ui:UISprite, text:String)
|
||||
add(new UIText(ui.x, ui.y - 24, 0, text));
|
||||
|
||||
var title:UIText;
|
||||
add(title = new UIText(windowSpr.x + 20, windowSpr.y + 30 + 16, 0, "Song Data", 28));
|
||||
|
||||
songNameTextBox = new UITextBox(title.x, title.y + title.height + 36, metadata.name);
|
||||
add(songNameTextBox);
|
||||
addLabelOn(songNameTextBox, "Song Name");
|
||||
|
||||
bpmStepper = new UINumericStepper(songNameTextBox.x + 320 + 26, songNameTextBox.y, metadata.bpm, 1, 2, 1, null, 90);
|
||||
add(bpmStepper);
|
||||
addLabelOn(bpmStepper, "BPM");
|
||||
|
||||
stepsPerBeatStepper = new UINumericStepper(bpmStepper.x + 60 + 26, bpmStepper.y, metadata.stepsPerBeat, 1, 0, 1, null, 54);
|
||||
add(stepsPerBeatStepper);
|
||||
addLabelOn(stepsPerBeatStepper, "Time Signature");
|
||||
|
||||
add(new UIText(stepsPerBeatStepper.x + 30, stepsPerBeatStepper.y + 3, 0, "/", 22));
|
||||
|
||||
beatsPerMesureStepper = new UINumericStepper(stepsPerBeatStepper.x + 30 + 24, stepsPerBeatStepper.y, metadata.beatsPerMesure, 1, 0, 1, null, 54);
|
||||
add(beatsPerMesureStepper);
|
||||
|
||||
needsVoicesCheckbox = new UICheckbox(beatsPerMesureStepper.x + 80 + 26, beatsPerMesureStepper.y, "Voices", metadata.needsVoices);
|
||||
add(needsVoicesCheckbox);
|
||||
addLabelOn(needsVoicesCheckbox, "Needs Voices");
|
||||
needsVoicesCheckbox.y += 6; needsVoicesCheckbox.x += 4;
|
||||
|
||||
add(title = new UIText(songNameTextBox.x, songNameTextBox.y + 10 + 46, 0, "Menus Data (Freeplay/Story)", 28));
|
||||
|
||||
displayNameTextBox = new UITextBox(title.x, title.y + title.height + 36, metadata.displayName);
|
||||
add(displayNameTextBox);
|
||||
addLabelOn(displayNameTextBox, "Display Name");
|
||||
|
||||
iconTextBox = new UITextBox(displayNameTextBox.x + 320 + 26, displayNameTextBox.y, metadata.icon, 150);
|
||||
iconTextBox.onChange = (newIcon:String) -> {updateIcon(newIcon);}
|
||||
add(iconTextBox);
|
||||
addLabelOn(iconTextBox, "Icon");
|
||||
|
||||
updateIcon(metadata.icon);
|
||||
|
||||
opponentModeCheckbox = new UICheckbox(displayNameTextBox.x, iconTextBox.y + 10 + 32 + 26, "Opponent Mode", metadata.opponentModeAllowed);
|
||||
add(opponentModeCheckbox);
|
||||
addLabelOn(opponentModeCheckbox, "Modes Allowed");
|
||||
|
||||
coopAllowedCheckbox = new UICheckbox(opponentModeCheckbox.x + 150 + 26, opponentModeCheckbox.y, "Co-op Mode", metadata.coopAllowed);
|
||||
add(coopAllowedCheckbox);
|
||||
|
||||
colorWheel = new UIColorwheel(iconTextBox.x, coopAllowedCheckbox.y, metadata.parsedColor);
|
||||
add(colorWheel);
|
||||
addLabelOn(colorWheel, "Color");
|
||||
|
||||
difficulitesTextBox = new UITextBox(opponentModeCheckbox.x, opponentModeCheckbox.y + 6 + 32 + 26, metadata.difficulties.join(", "));
|
||||
add(difficulitesTextBox);
|
||||
addLabelOn(difficulitesTextBox, "Difficulties");
|
||||
|
||||
for (checkbox in [opponentModeCheckbox, coopAllowedCheckbox])
|
||||
{checkbox.y += 6; checkbox.x += 4;}
|
||||
|
||||
saveButton = new UIButton(windowSpr.x + windowSpr.bWidth - 20, colorWheel.y + 32 + 197 + 26, "Save & Close", function() {
|
||||
saveMeta();
|
||||
close();
|
||||
}, 125);
|
||||
saveButton.x -= saveButton.bWidth;
|
||||
saveButton.y -= saveButton.bHeight;
|
||||
add(saveButton);
|
||||
}
|
||||
|
||||
function updateIcon(icon:String) {
|
||||
if (iconSprite == null) add(iconSprite = new FlxSprite());
|
||||
|
||||
if (iconSprite.animation.exists(icon)) return;
|
||||
@:privateAccess iconSprite.animation.clearAnimations();
|
||||
|
||||
var path:String = Paths.image('icons/$icon');
|
||||
if (!Assets.exists(path)) path = Paths.image('icons/face');
|
||||
|
||||
iconSprite.loadGraphic(path, true, 150, 150);
|
||||
iconSprite.animation.add(icon, [0], 0, false);
|
||||
iconSprite.antialiasing = true;
|
||||
iconSprite.animation.play(icon);
|
||||
|
||||
iconSprite.scale.set(0.5, 0.5);
|
||||
iconSprite.updateHitbox();
|
||||
iconSprite.setPosition(iconTextBox.x + 150 + 8, (iconTextBox.y + 16) - (iconSprite.height/2));
|
||||
}
|
||||
|
||||
public function saveMeta() {
|
||||
PlayState.SONG.meta = {
|
||||
name: songNameTextBox.label.text,
|
||||
bpm: bpmStepper.value,
|
||||
stepsPerBeat: Std.int(stepsPerBeatStepper.value),
|
||||
beatsPerMesure: Std.int(beatsPerMesureStepper.value),
|
||||
needsVoices: needsVoicesCheckbox.checked,
|
||||
displayName: displayNameTextBox.label.text,
|
||||
icon: iconTextBox.label.text,
|
||||
color: colorWheel.curColorString,
|
||||
parsedColor: colorWheel.curColor,
|
||||
opponentModeAllowed: opponentModeCheckbox.checked,
|
||||
coopAllowed: coopAllowedCheckbox.checked,
|
||||
difficulties: [for (diff in difficulitesTextBox.label.text.split(",")) diff.trim()],
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,173 @@
|
||||
package funkin.editors.ui;
|
||||
|
||||
import flixel.math.FlxPoint;
|
||||
import funkin.backend.shaders.CustomShader;
|
||||
import flixel.util.FlxColor;
|
||||
|
||||
using flixel.util.FlxSpriteUtil;
|
||||
|
||||
class UIColorwheel extends UISliceSprite {
|
||||
var colorPicker:FlxSprite;
|
||||
var colorPickerShader:CustomShader;
|
||||
var colorPickerSelector:UIColorWheelSelector;
|
||||
|
||||
var colorSlider:FlxSprite;
|
||||
var colorSliderSelector:UIColorWheelSelector;
|
||||
|
||||
var colorHexTextBox:UITextBox;
|
||||
var rgbNumSteppers:Array<UINumericStepper> = []; // r,g,b
|
||||
|
||||
public var curColor:Null<FlxColor> = FlxColor.WHITE;
|
||||
public var curColorString:String = "#FFFFFF";
|
||||
|
||||
public var saturation:Float;
|
||||
public var brightness:Float;
|
||||
public var hue:Float;
|
||||
|
||||
public function new (x:Float, y:Float, ?color:Int) {
|
||||
super(x, y, 299, 125, 'editors/ui/inputbox');
|
||||
|
||||
curColor = cast color;
|
||||
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
||||
|
||||
colorPickerShader = new CustomShader("engine/colorPicker");
|
||||
colorPickerShader.hset("hue", hue);
|
||||
|
||||
colorPicker = new FlxSprite(x + 12.5, (y + 125/2) - (100/2)).makeGraphic(100, 100, FlxColor.TRANSPARENT);
|
||||
colorPicker.drawRoundRect(0, 0, 100, 100, 10, 10, FlxColor.WHITE);
|
||||
colorPicker.shader = colorPickerShader;
|
||||
|
||||
colorPickerSelector = new UIColorWheelSelector(colorPicker.x + 100 - 16, colorPicker.y);
|
||||
|
||||
colorSlider = new FlxSprite(colorPicker.x + 100 + 12.5, colorPicker.y).makeGraphic(16, 100, FlxColor.TRANSPARENT);
|
||||
colorSlider.drawRoundRect(0, 0, 16, 100, 10, 10, FlxColor.WHITE);
|
||||
|
||||
// Im too lazy to use a shader for this if its not even gonna change
|
||||
colorSlider.pixels.lock();
|
||||
for (pixely in 0...Std.int(colorSlider.height)) {
|
||||
var color:Int = FlxColor.fromHSB(pixely / (colorSlider.height-1) * 360, 1, 1);
|
||||
for (pixelx in 0...Std.int(colorSlider.width))
|
||||
if (colorSlider.pixels.getPixel32(pixelx, pixely) != FlxColor.TRANSPARENT) colorSlider.pixels.setPixel32(pixelx, pixely, color);
|
||||
}
|
||||
colorSlider.pixels.unlock();
|
||||
|
||||
colorSliderSelector = new UIColorWheelSelector(colorSlider.x, colorSlider.y);
|
||||
|
||||
colorHexTextBox = new UITextBox(colorSlider.x + 16 + 12.5, colorSlider.y + 16, "", 100, 28);
|
||||
colorHexTextBox.onChange = (colorString:String) -> {
|
||||
curColor = FlxColor.fromString(colorString);
|
||||
if (curColor == null) curColor = FlxColor.WHITE;
|
||||
|
||||
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
||||
updateWheel();
|
||||
}
|
||||
|
||||
var hexLabel:UIText = new UIText(colorHexTextBox.x - 2, colorHexTextBox.y - 18, 0, "Hex (#FFFFFF)", 13);
|
||||
|
||||
for (i in 0...3) {
|
||||
var numStepper:UINumericStepper = new UINumericStepper(colorSlider.x + 18 + 12.5 + (i * 44), colorHexTextBox.y + 28 + 6 + 13 + 6 + .5, 0, 1, 0, 0, 255, 40 + 28, 28);
|
||||
numStepper.antialiasing = true; numStepper.ID = i;
|
||||
numStepper.onChange = (text:String) -> {
|
||||
@:privateAccess numStepper.__onChange(text);
|
||||
switch (numStepper.ID) {
|
||||
default: curColor.red = Std.int(numStepper.value);
|
||||
case 1: curColor.green = Std.int(numStepper.value);
|
||||
case 2: curColor.blue = Std.int(numStepper.value);
|
||||
}
|
||||
hue = curColor.hue; saturation = curColor.saturation; brightness = curColor.brightness;
|
||||
updateWheel();
|
||||
};
|
||||
members.push(numStepper); rgbNumSteppers.push(numStepper);
|
||||
}
|
||||
|
||||
var rgbLabel:UIText = new UIText(rgbNumSteppers[0].x - 2, rgbNumSteppers[0].y - 18, 0, "RGB (255,255,255)", 13);
|
||||
|
||||
colorPicker.antialiasing = colorSlider.antialiasing = colorHexTextBox.antialiasing = true;
|
||||
|
||||
for (item in [colorPicker, colorPickerSelector, colorSlider, colorSliderSelector, colorHexTextBox, hexLabel, rgbLabel])
|
||||
members.push(item);
|
||||
|
||||
updateWheel();
|
||||
}
|
||||
|
||||
inline function updateColorPickerSelector()
|
||||
colorPickerSelector.selector.setPosition(colorPicker.x + (colorPicker.width *saturation) - 8, colorPicker.y + (colorPicker.height + (colorPicker.height * -brightness))- 8);
|
||||
|
||||
inline function updateColorPickerMouse(mousePos:FlxPoint) {
|
||||
saturation = mousePos.x/colorPicker.width; brightness = 1 + -(mousePos.y/colorPicker.height);
|
||||
}
|
||||
|
||||
inline function updateColorSliderPickerSelector()
|
||||
colorSliderSelector.selector.setPosition(colorSlider.x, colorSlider.y + (hue / 360 * (colorSlider.height-1)) - 8);
|
||||
|
||||
inline function updateColorSliderMouse(mousePos:FlxPoint)
|
||||
hue = (mousePos.y / colorSlider.height) * 360;
|
||||
|
||||
public function updateWheel() {
|
||||
colorPickerShader.hset("hue", hue / 360);
|
||||
colorPickerSelector.curColor = color = curColor = FlxColor.fromHSB(hue, saturation, brightness); colorSliderSelector.curColor = FlxColor.fromHSB(hue, 1, 1);
|
||||
|
||||
updateColorPickerSelector(); updateColorSliderPickerSelector();
|
||||
colorHexTextBox.label.text = curColorString = curColor.toHexString(false).replace("0x", "#");
|
||||
for (numStepper in rgbNumSteppers) {
|
||||
numStepper.label.text = Std.string(switch (numStepper.ID) {
|
||||
default: curColor.red;
|
||||
case 1: curColor.green;
|
||||
case 2: curColor.blue;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Make the colorwhell feel better
|
||||
static inline var hitBoxExtenstion:Float = 8;
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
if (hovered && FlxG.mouse.pressed) {
|
||||
var mousePos = FlxG.mouse.getScreenPosition(__lastDrawCameras[0], FlxPoint.get());
|
||||
|
||||
for (sprite in [colorPicker, colorSlider]) {
|
||||
var spritePos:FlxPoint = sprite.getScreenPosition(FlxPoint.get(), __lastDrawCameras[0]);
|
||||
|
||||
if (((mousePos.x > (spritePos.x - (hitBoxExtenstion/2))) && (mousePos.x < spritePos.x - (hitBoxExtenstion/2) + (sprite.width + hitBoxExtenstion))) && ((mousePos.y > (spritePos.y - (hitBoxExtenstion/2))) && (mousePos.y < spritePos.y - (hitBoxExtenstion/2) + (sprite.height + hitBoxExtenstion)))) {
|
||||
mousePos -= FlxPoint.weak(spritePos.x, spritePos.y);
|
||||
mousePos.set(FlxMath.bound(mousePos.x, 0, sprite.width), FlxMath.bound(mousePos.y, 0, sprite.height));
|
||||
|
||||
if (sprite == colorSlider) updateColorSliderMouse(mousePos);
|
||||
if (sprite == colorPicker) updateColorPickerMouse(mousePos);
|
||||
updateWheel();
|
||||
|
||||
spritePos.put();
|
||||
break;
|
||||
}
|
||||
}
|
||||
mousePos.put();
|
||||
}
|
||||
|
||||
super.update(elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
class UIColorWheelSelector extends FlxTypedGroup<FlxSprite> {
|
||||
public var curColor:FlxColor = FlxColor.WHITE;
|
||||
|
||||
public var selector:FlxSprite;
|
||||
public var colorCircle:FlxSprite;
|
||||
|
||||
public function new(x:Float, y:Float, ?color:Null<Int>) {
|
||||
super();
|
||||
if (color != null) curColor = cast color;
|
||||
|
||||
add(selector = new FlxSprite(x, y).loadGraphic(Paths.image("editors/ui/slider")));
|
||||
add(colorCircle = new FlxSprite(x + 2, y + 2).makeGraphic(12,12, FlxColor.TRANSPARENT).drawCircle());
|
||||
|
||||
selector.antialiasing = colorCircle.antialiasing = true;
|
||||
colorCircle.colorTransform.color = curColor;
|
||||
}
|
||||
|
||||
public override function update(elapsed:Float) {
|
||||
super.update(elapsed);
|
||||
|
||||
colorCircle.setPosition(selector.x + 2, selector.y + 2);
|
||||
colorCircle.colorTransform.color = curColor;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user