Add new Offsets window, work in progress

This commit is contained in:
EliteMasterEric 2024-01-20 14:07:31 -05:00
parent 583eb81de5
commit 608d9b6968
9 changed files with 223 additions and 42 deletions

View file

@ -243,6 +243,8 @@ class InitState extends FlxState
FlxG.switchState(new FreeplayState());
#elseif ANIMATE // -DANIMATE
FlxG.switchState(new funkin.ui.debug.anim.FlxAnimateTest());
#elseif WAVEFORM // -DWAVEFORM
FlxG.switchState(new funkin.ui.debug.WaveformTestState());
#elseif CHARTING // -DCHARTING
FlxG.switchState(new funkin.ui.debug.charting.ChartEditorState());
#elseif STAGEBUILD // -DSTAGEBUILD

View file

@ -63,6 +63,19 @@ class FunkinSound extends FlxSound
}
}
public function togglePlayback():FunkinSound
{
if (playing)
{
pause();
}
else
{
resume();
}
return this;
}
public override function play(forceRestart:Bool = false, startTime:Float = 0, ?endTime:Float):FunkinSound
{
if (!exists) return this;

View file

@ -102,7 +102,7 @@ class PolygonSpectogram extends MeshRender
coolPoint.x = (curAud.balanced * waveAmplitude);
coolPoint.y = (i / funnyPixels * daHeight);
add_quad(prevPoint.x, prevPoint.y, prevPoint.x
build_quad(prevPoint.x, prevPoint.y, prevPoint.x
+ thickness, prevPoint.y, coolPoint.x, coolPoint.y, coolPoint.x
+ thickness, coolPoint.y
+ thickness);

View file

@ -12,22 +12,19 @@ class MeshRender extends FlxStrip
public var vertex_count(default, null):Int = 0;
public var index_count(default, null):Int = 0;
var tri_offset:Int = 0;
public function new(x, y, ?col:FlxColor = FlxColor.WHITE)
{
super(x, y);
makeGraphic(1, 1, col);
}
public inline function start()
/**
* Add a vertex.
*/
public inline function build_vertex(x:Float, y:Float, u:Float = 0, v:Float = 0):Int
{
tri_offset = vertex_count;
}
public inline function add_vertex(x:Float, y:Float, u:Float = 0, v:Float = 0)
{
final pos = vertex_count << 1;
final index = vertex_count;
final pos = index << 1;
vertices[pos] = x;
vertices[pos + 1] = y;
@ -36,42 +33,64 @@ class MeshRender extends FlxStrip
uvtData[pos + 1] = v;
vertex_count++;
return index;
}
public function add_tri(a:Int, b:Int, c:Int)
/**
* Build a triangle from three vertex indexes.
* @param a
* @param b
* @param c
*/
public function add_tri(a:Int, b:Int, c:Int):Void
{
indices[index_count] = a + tri_offset;
indices[index_count + 1] = b + tri_offset;
indices[index_count + 2] = c + tri_offset;
indices[index_count] = a;
indices[index_count + 1] = b;
indices[index_count + 2] = c;
index_count += 3;
}
/**
*
* top left - a
*
* top right - b
*
* bottom left - c
*
* bottom right - d
*/
public function add_quad(ax:Float, ay:Float, bx:Float, by:Float, cx:Float, cy:Float, dx:Float, dy:Float, au:Float = 0, av:Float = 0, bu:Float = 0,
bv:Float = 0, cu:Float = 0, cv:Float = 0, du:Float = 0, dv:Float = 0)
public function build_tri(ax:Float, ay:Float, bx:Float, by:Float, cx:Float, cy:Float, au:Float = 0, av:Float = 0, bu:Float = 0, bv:Float = 0, cu:Float = 0,
cv:Float = 0):Void
{
start();
// top left
add_vertex(bx, by, bu, bv);
// top right
add_vertex(ax, ay, au, av);
// bottom left
add_vertex(cx, cy, cu, cv);
// bottom right
add_vertex(dx, dy, du, dv);
add_tri(build_vertex(ax, ay, au, av), build_vertex(bx, by, bu, bv), build_vertex(cx, cy, cu, cv));
}
add_tri(0, 1, 2);
add_tri(0, 2, 3);
/**
* @param a top left vertex
* @param b top right vertex
* @param c bottom right vertex
* @param d bottom left vertex
*/
public function add_quad(a:Int, b:Int, c:Int, d:Int):Void
{
add_tri(a, b, c);
add_tri(a, c, d);
}
/**
* Build a quad from four points.
*
* top right - a
* top left - b
* bottom right - c
* bottom left - d
*/
public function build_quad(ax:Float, ay:Float, bx:Float, by:Float, cx:Float, cy:Float, dx:Float, dy:Float, au:Float = 0, av:Float = 0, bu:Float = 0,
bv:Float = 0, cu:Float = 0, cv:Float = 0, du:Float = 0, dv:Float = 0):Void
{
// top left
var b = build_vertex(bx, by, bu, bv);
// top right
var a = build_vertex(ax, ay, au, av);
// bottom left
var c = build_vertex(cx, cy, cu, cv);
// bottom right
var d = build_vertex(dx, dy, du, dv);
add_tri(a, b, c);
add_tri(a, c, d);
}
public function clear()

View file

@ -159,6 +159,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
public static final CHART_EDITOR_TOOLBOX_EVENT_DATA_LAYOUT:String = Paths.ui('chart-editor/toolbox/eventdata');
public static final CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT:String = Paths.ui('chart-editor/toolbox/playtest-properties');
public static final CHART_EDITOR_TOOLBOX_METADATA_LAYOUT:String = Paths.ui('chart-editor/toolbox/metadata');
public static final CHART_EDITOR_TOOLBOX_OFFSETS_LAYOUT:String = Paths.ui('chart-editor/toolbox/offsets');
public static final CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT:String = Paths.ui('chart-editor/toolbox/difficulty');
public static final CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT:String = Paths.ui('chart-editor/toolbox/player-preview');
public static final CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT:String = Paths.ui('chart-editor/toolbox/opponent-preview');
@ -1820,11 +1821,16 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
*/
var notePreviewViewportBitmap:Null<BitmapData> = null;
/**r
/**
* The IMAGE used for the measure ticks. Updated by ChartEditorThemeHandler.
*/
var measureTickBitmap:Null<BitmapData> = null;
/**
* The IMAGE used for the offset ticks. Updated by ChartEditorThemeHandler.
*/
var offsetTickBitmap:Null<BitmapData> = null;
/**
* The tiled sprite used to display the grid.
* The height is the length of the song, and scrolling is done by simply the sprite.
@ -2893,6 +2899,7 @@ class ChartEditorState extends UIState // UIState derives from MusicBeatState
menubarItemToggleToolboxDifficulty.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_DIFFICULTY_LAYOUT, event.value);
menubarItemToggleToolboxMetadata.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_METADATA_LAYOUT, event.value);
menubarItemToggleToolboxOffsets.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_OFFSETS_LAYOUT, event.value);
menubarItemToggleToolboxNotes.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_NOTEDATA_LAYOUT, event.value);
menubarItemToggleToolboxEventData.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_EVENT_DATA_LAYOUT, event.value);
menubarItemToggleToolboxPlaytestProperties.onChange = event -> this.setToolboxState(CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT, event.value);

View file

@ -82,6 +82,7 @@ class ChartEditorThemeHandler
updateBackground(state);
updateGridBitmap(state);
updateMeasureTicks(state);
updateOffsetTicks(state);
updateSelectionSquare(state);
updateNotePreview(state);
}
@ -231,6 +232,9 @@ class ChartEditorThemeHandler
// Else, gridTiledSprite will be built later.
}
/**
* Vertical measure ticks.
*/
static function updateMeasureTicks(state:ChartEditorState):Void
{
var measureTickWidth:Int = 6;
@ -286,6 +290,57 @@ class ChartEditorThemeHandler
state.measureTickBitmap.fillRect(new Rectangle(0, stepTick16Y, stepTickLength, stepTickWidth), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
}
/**
* Horizontal offset ticks.
*/
static function updateOffsetTicks(state:ChartEditorState):Void
{
var majorTickWidth:Int = 6;
var minorTickWidth:Int = 3;
var ticksWidth:Int = Std.int(ChartEditorState.GRID_SIZE * Conductor.instance.stepsPerMeasure); // 10 minor ticks wide.
var ticksHeight:Int = Std.int(ChartEditorState.GRID_SIZE); // 1 grid squares tall.
state.offsetTickBitmap = new BitmapData(ticksWidth, ticksHeight, true);
state.offsetTickBitmap.fillRect(new Rectangle(0, 0, ticksWidth, ticksHeight), GRID_BEAT_DIVIDER_COLOR_DARK);
// Draw the major ticks.
var leftTickX:Float = 0;
var middleTickX:Float = state.offsetTickBitmap.width / 2 - (majorTickWidth / 2);
var rightTickX:Float = state.offsetTickBitmap.width - majorTickWidth;
state.offsetTickBitmap.fillRect(new Rectangle(leftTickX, 0, majorTickWidth / 2, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(middleTickX, 0, majorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(rightTickX, 0, majorTickWidth / 2, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
// Draw the minor ticks.
var minorTick2X:Float = state.offsetTickBitmap.width * 1 / 10 - (minorTickWidth / 2);
var minorTick3X:Float = state.offsetTickBitmap.width * 2 / 10 - (minorTickWidth / 2);
var minorTick4X:Float = state.offsetTickBitmap.width * 3 / 10 - (minorTickWidth / 2);
var minorTick5X:Float = state.offsetTickBitmap.width * 4 / 10 - (minorTickWidth / 2);
var minorTick7X:Float = state.offsetTickBitmap.width * 6 / 10 - (minorTickWidth / 2);
var minorTick8X:Float = state.offsetTickBitmap.width * 7 / 10 - (minorTickWidth / 2);
var minorTick9X:Float = state.offsetTickBitmap.width * 8 / 10 - (minorTickWidth / 2);
var minorTick10X:Float = state.offsetTickBitmap.width * 9 / 10 - (minorTickWidth / 2);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick2X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick3X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick4X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick5X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick7X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick8X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick9X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
state.offsetTickBitmap.fillRect(new Rectangle(minorTick10X, 0, minorTickWidth, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
// Draw the offset ticks.
// var ticksWidth:Int = Std.int(ChartEditorState.GRID_SIZE * TOTAL_COLUMN_COUNT); // 1 grid squares wide.
// var ticksHeight:Int = Std.int(ChartEditorState.GRID_SIZE); // 1 measure tall.
// state.offsetTickBitmap = new BitmapData(ticksWidth, ticksHeight, true);
// state.offsetTickBitmap.fillRect(new Rectangle(0, 0, ticksWidth, ticksHeight), GRID_BEAT_DIVIDER_COLOR_DARK);
//
//// Draw the offset ticks.
// state.offsetTickBitmap.fillRect(new Rectangle(0, 0, offsetTickWidth / 2, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
// var rightTickX:Float = state.offsetTickBitmap.width - (offsetTickWidth / 2);
// state.offsetTickBitmap.fillRect(new Rectangle(rightTickX, 0, offsetTickWidth / 2, state.offsetTickBitmap.height), GRID_MEASURE_DIVIDER_COLOR_LIGHT);
}
static function updateSelectionSquare(state:ChartEditorState):Void
{
var selectionSquareBorderColor:FlxColor = switch (state.currentTheme)

View file

@ -35,6 +35,7 @@ import haxe.ui.containers.dialogs.Dialog.DialogButton;
import haxe.ui.containers.dialogs.Dialog.DialogEvent;
import funkin.ui.debug.charting.toolboxes.ChartEditorBaseToolbox;
import funkin.ui.debug.charting.toolboxes.ChartEditorMetadataToolbox;
import funkin.ui.debug.charting.toolboxes.ChartEditorOffsetsToolbox;
import funkin.ui.debug.charting.toolboxes.ChartEditorEventDataToolbox;
import funkin.ui.debug.charting.toolboxes.ChartEditorDifficultyToolbox;
import haxe.ui.containers.Frame;
@ -89,6 +90,8 @@ class ChartEditorToolboxHandler
case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT:
// TODO: Fix this.
cast(toolbox, ChartEditorBaseToolbox).refresh();
case ChartEditorState.CHART_EDITOR_TOOLBOX_OFFSETS_LAYOUT:
cast(toolbox, ChartEditorBaseToolbox).refresh();
case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT:
onShowToolboxPlayerPreview(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT:
@ -124,8 +127,6 @@ class ChartEditorToolboxHandler
onHideToolboxEventData(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYTEST_PROPERTIES_LAYOUT:
onHideToolboxPlaytestProperties(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT:
onHideToolboxMetadata(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT:
onHideToolboxPlayerPreview(state, toolbox);
case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT:
@ -202,6 +203,8 @@ class ChartEditorToolboxHandler
toolbox = buildToolboxDifficultyLayout(state);
case ChartEditorState.CHART_EDITOR_TOOLBOX_METADATA_LAYOUT:
toolbox = buildToolboxMetadataLayout(state);
case ChartEditorState.CHART_EDITOR_TOOLBOX_OFFSETS_LAYOUT:
toolbox = buildToolboxOffsetsLayout(state);
case ChartEditorState.CHART_EDITOR_TOOLBOX_PLAYER_PREVIEW_LAYOUT:
toolbox = buildToolboxPlayerPreviewLayout(state);
case ChartEditorState.CHART_EDITOR_TOOLBOX_OPPONENT_PREVIEW_LAYOUT:
@ -304,8 +307,6 @@ class ChartEditorToolboxHandler
static function onHideToolboxNoteData(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onHideToolboxMetadata(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onHideToolboxEventData(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
static function onShowToolboxPlaytestProperties(state:ChartEditorState, toolbox:CollapsibleDialog):Void {}
@ -373,6 +374,15 @@ class ChartEditorToolboxHandler
return toolbox;
}
static function buildToolboxOffsetsLayout(state:ChartEditorState):Null<ChartEditorBaseToolbox>
{
var toolbox:ChartEditorBaseToolbox = ChartEditorOffsetsToolbox.build(state);
if (toolbox == null) return null;
return toolbox;
}
static function buildToolboxEventDataLayout(state:ChartEditorState):Null<ChartEditorBaseToolbox>
{
var toolbox:ChartEditorBaseToolbox = ChartEditorEventDataToolbox.build(state);

View file

@ -0,0 +1,63 @@
package funkin.ui.debug.charting.toolboxes;
import funkin.play.character.BaseCharacter.CharacterType;
import funkin.play.character.CharacterData;
import funkin.data.stage.StageData;
import funkin.data.stage.StageRegistry;
import funkin.ui.debug.charting.commands.ChangeStartingBPMCommand;
import funkin.ui.debug.charting.util.ChartEditorDropdowns;
import haxe.ui.components.Button;
import haxe.ui.components.CheckBox;
import haxe.ui.components.DropDown;
import haxe.ui.components.HorizontalSlider;
import haxe.ui.components.Label;
import haxe.ui.components.NumberStepper;
import haxe.ui.components.Slider;
import haxe.ui.components.TextField;
import funkin.play.stage.Stage;
import haxe.ui.containers.Box;
import haxe.ui.containers.Frame;
import haxe.ui.events.UIEvent;
/**
* The toolbox which allows modifying information like Song Title, Scroll Speed, Characters/Stages, and starting BPM.
*/
// @:nullSafety // TODO: Fix null safety when used with HaxeUI build macros.
@:access(funkin.ui.debug.charting.ChartEditorState)
@:build(haxe.ui.ComponentBuilder.build("assets/exclude/data/ui/chart-editor/toolboxes/offsets.xml"))
class ChartEditorOffsetsToolbox extends ChartEditorBaseToolbox
{
public function new(chartEditorState2:ChartEditorState)
{
super(chartEditorState2);
initialize();
this.onDialogClosed = onClose;
}
function onClose(event:UIEvent)
{
chartEditorState.menubarItemToggleToolboxOffsets.selected = false;
}
function initialize():Void
{
// Starting position.
// TODO: Save and load this.
this.x = 150;
this.y = 250;
refresh();
}
public override function refresh():Void
{
super.refresh();
}
public static function build(chartEditorState:ChartEditorState):ChartEditorOffsetsToolbox
{
return new ChartEditorOffsetsToolbox(chartEditorState);
}
}

View file

@ -3,6 +3,7 @@ package funkin.util.logging;
import openfl.Lib;
import openfl.events.UncaughtErrorEvent;
import flixel.util.FlxSignal.FlxTypedSignal;
import flixel.FlxG.FlxRenderMethod;
/**
* A custom crash handler that writes to a log file and displays a message box.
@ -118,6 +119,7 @@ class CrashHandler
var driverInfo = FlxG?.stage?.context3D?.driverInfo ?? 'N/A';
fullContents += 'Driver info: ${driverInfo}\n';
fullContents += 'Platform: ${Sys.systemName()}\n';
fullContents += 'Render method: ${renderMethod()}\n';
fullContents += '\n';
@ -196,4 +198,14 @@ class CrashHandler
{
throw "This is an example of an uncaught exception.";
}
static function renderMethod():String
{
return switch (FlxG.renderMethod)
{
case FlxRenderMethod.DRAW_TILES: 'DRAW_TILES';
case FlxRenderMethod.BLITTING: 'BLITTING';
default: 'UNKNOWN';
}
}
}