mirror of
https://github.com/ninjamuffin99/Funkin.git
synced 2025-04-01 15:25:25 +00:00
Merge branch 'master' into bugfix-squashed/macos-file-browse
This commit is contained in:
commit
446dc30277
|
@ -4,9 +4,34 @@ import openfl.utils.Assets;
|
||||||
import lime.app.Future;
|
import lime.app.Future;
|
||||||
import openfl.display.BitmapData;
|
import openfl.display.BitmapData;
|
||||||
|
|
||||||
|
@:nullSafety
|
||||||
class Cursor
|
class Cursor
|
||||||
{
|
{
|
||||||
public static var cursorMode(default, set):CursorMode;
|
/**
|
||||||
|
* The current cursor mode.
|
||||||
|
* Set this value to change the cursor graphic.
|
||||||
|
*/
|
||||||
|
public static var cursorMode(default, set):Null<CursorMode> = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the cursor.
|
||||||
|
*/
|
||||||
|
public static inline function show():Void
|
||||||
|
{
|
||||||
|
FlxG.mouse.visible = true;
|
||||||
|
// Reset the cursor mode.
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hide the cursor.
|
||||||
|
*/
|
||||||
|
public static inline function hide():Void
|
||||||
|
{
|
||||||
|
FlxG.mouse.visible = false;
|
||||||
|
// Reset the cursor mode.
|
||||||
|
Cursor.cursorMode = null;
|
||||||
|
}
|
||||||
|
|
||||||
static final CURSOR_DEFAULT_PARAMS:CursorParams =
|
static final CURSOR_DEFAULT_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
|
@ -15,7 +40,7 @@ class Cursor
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorDefault:BitmapData = null;
|
static var assetCursorDefault:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_CROSS_PARAMS:CursorParams =
|
static final CURSOR_CROSS_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
|
@ -24,7 +49,7 @@ class Cursor
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorCross:BitmapData = null;
|
static var assetCursorCross:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_ERASER_PARAMS:CursorParams =
|
static final CURSOR_ERASER_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
|
@ -33,16 +58,16 @@ class Cursor
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorEraser:BitmapData = null;
|
static var assetCursorEraser:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_GRABBING_PARAMS:CursorParams =
|
static final CURSOR_GRABBING_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
graphic: "assets/images/cursor/cursor-grabbing.png",
|
graphic: "assets/images/cursor/cursor-grabbing.png",
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
offsetX: 32,
|
offsetX: -8,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorGrabbing:BitmapData = null;
|
static var assetCursorGrabbing:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_HOURGLASS_PARAMS:CursorParams =
|
static final CURSOR_HOURGLASS_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
|
@ -51,25 +76,34 @@ class Cursor
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorHourglass:BitmapData = null;
|
static var assetCursorHourglass:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_POINTER_PARAMS:CursorParams =
|
static final CURSOR_POINTER_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
graphic: "assets/images/cursor/cursor-pointer.png",
|
graphic: "assets/images/cursor/cursor-pointer.png",
|
||||||
scale: 1.0,
|
scale: 1.0,
|
||||||
offsetX: 8,
|
offsetX: -8,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorPointer:BitmapData = null;
|
static var assetCursorPointer:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_TEXT_PARAMS:CursorParams =
|
static final CURSOR_TEXT_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
graphic: "assets/images/cursor/cursor-text.png",
|
graphic: "assets/images/cursor/cursor-text.png",
|
||||||
scale: 1.0,
|
scale: 0.2,
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorText:BitmapData = null;
|
static var assetCursorText:Null<BitmapData> = null;
|
||||||
|
|
||||||
|
static final CURSOR_TEXT_VERTICAL_PARAMS:CursorParams =
|
||||||
|
{
|
||||||
|
graphic: "assets/images/cursor/cursor-text-vertical.png",
|
||||||
|
scale: 0.2,
|
||||||
|
offsetX: 0,
|
||||||
|
offsetY: 0,
|
||||||
|
};
|
||||||
|
static var assetCursorTextVertical:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_ZOOM_IN_PARAMS:CursorParams =
|
static final CURSOR_ZOOM_IN_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
|
@ -78,7 +112,7 @@ class Cursor
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorZoomIn:BitmapData = null;
|
static var assetCursorZoomIn:Null<BitmapData> = null;
|
||||||
|
|
||||||
static final CURSOR_ZOOM_OUT_PARAMS:CursorParams =
|
static final CURSOR_ZOOM_OUT_PARAMS:CursorParams =
|
||||||
{
|
{
|
||||||
|
@ -87,11 +121,36 @@ class Cursor
|
||||||
offsetX: 0,
|
offsetX: 0,
|
||||||
offsetY: 0,
|
offsetY: 0,
|
||||||
};
|
};
|
||||||
static var assetCursorZoomOut:BitmapData = null;
|
static var assetCursorZoomOut:Null<BitmapData> = null;
|
||||||
|
|
||||||
static function set_cursorMode(value:CursorMode):CursorMode
|
static final CURSOR_CROSSHAIR_PARAMS:CursorParams =
|
||||||
|
{
|
||||||
|
graphic: "assets/images/cursor/cursor-crosshair.png",
|
||||||
|
scale: 1.0,
|
||||||
|
offsetX: -16,
|
||||||
|
offsetY: -16,
|
||||||
|
};
|
||||||
|
static var assetCursorCrosshair:Null<BitmapData> = null;
|
||||||
|
|
||||||
|
static final CURSOR_CELL_PARAMS:CursorParams =
|
||||||
|
{
|
||||||
|
graphic: "assets/images/cursor/cursor-cell.png",
|
||||||
|
scale: 1.0,
|
||||||
|
offsetX: -16,
|
||||||
|
offsetY: -16,
|
||||||
|
};
|
||||||
|
static var assetCursorCell:Null<BitmapData> = null;
|
||||||
|
|
||||||
|
// DESIRED CURSOR: Resize NS (vertical)
|
||||||
|
// DESIRED CURSOR: Resize EW (horizontal)
|
||||||
|
// DESIRED CURSOR: Resize NESW (diagonal)
|
||||||
|
// DESIRED CURSOR: Resize NWSE (diagonal)
|
||||||
|
// DESIRED CURSOR: Help (Cursor with question mark)
|
||||||
|
// DESIRED CURSOR: Menu (Cursor with menu icon)
|
||||||
|
|
||||||
|
static function set_cursorMode(value:Null<CursorMode>):Null<CursorMode>
|
||||||
{
|
{
|
||||||
if (cursorMode != value)
|
if (value != null && cursorMode != value)
|
||||||
{
|
{
|
||||||
cursorMode = value;
|
cursorMode = value;
|
||||||
setCursorGraphic(cursorMode);
|
setCursorGraphic(cursorMode);
|
||||||
|
@ -99,16 +158,9 @@ class Cursor
|
||||||
return cursorMode;
|
return cursorMode;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static inline function show():Void
|
/**
|
||||||
{
|
* Synchronous.
|
||||||
FlxG.mouse.visible = true;
|
*/
|
||||||
}
|
|
||||||
|
|
||||||
public static inline function hide():Void
|
|
||||||
{
|
|
||||||
FlxG.mouse.visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static function setCursorGraphic(?value:CursorMode = null):Void
|
static function setCursorGraphic(?value:CursorMode = null):Void
|
||||||
{
|
{
|
||||||
if (value == null)
|
if (value == null)
|
||||||
|
@ -117,6 +169,156 @@ class Cursor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
case Default:
|
||||||
|
if (assetCursorDefault == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_DEFAULT_PARAMS.graphic);
|
||||||
|
assetCursorDefault = bitmapData;
|
||||||
|
applyCursorParams(assetCursorDefault, CURSOR_DEFAULT_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorDefault, CURSOR_DEFAULT_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Cross:
|
||||||
|
if (assetCursorCross == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_CROSS_PARAMS.graphic);
|
||||||
|
assetCursorCross = bitmapData;
|
||||||
|
applyCursorParams(assetCursorCross, CURSOR_CROSS_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorCross, CURSOR_CROSS_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Eraser:
|
||||||
|
if (assetCursorEraser == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_ERASER_PARAMS.graphic);
|
||||||
|
assetCursorEraser = bitmapData;
|
||||||
|
applyCursorParams(assetCursorEraser, CURSOR_ERASER_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorEraser, CURSOR_ERASER_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Grabbing:
|
||||||
|
if (assetCursorGrabbing == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_GRABBING_PARAMS.graphic);
|
||||||
|
assetCursorGrabbing = bitmapData;
|
||||||
|
applyCursorParams(assetCursorGrabbing, CURSOR_GRABBING_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorGrabbing, CURSOR_GRABBING_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Hourglass:
|
||||||
|
if (assetCursorHourglass == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_HOURGLASS_PARAMS.graphic);
|
||||||
|
assetCursorHourglass = bitmapData;
|
||||||
|
applyCursorParams(assetCursorHourglass, CURSOR_HOURGLASS_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorHourglass, CURSOR_HOURGLASS_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Pointer:
|
||||||
|
if (assetCursorPointer == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_POINTER_PARAMS.graphic);
|
||||||
|
assetCursorPointer = bitmapData;
|
||||||
|
applyCursorParams(assetCursorPointer, CURSOR_POINTER_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorPointer, CURSOR_POINTER_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Text:
|
||||||
|
if (assetCursorText == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_TEXT_PARAMS.graphic);
|
||||||
|
assetCursorText = bitmapData;
|
||||||
|
applyCursorParams(assetCursorText, CURSOR_TEXT_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorText, CURSOR_TEXT_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case ZoomIn:
|
||||||
|
if (assetCursorZoomIn == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_ZOOM_IN_PARAMS.graphic);
|
||||||
|
assetCursorZoomIn = bitmapData;
|
||||||
|
applyCursorParams(assetCursorZoomIn, CURSOR_ZOOM_IN_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorZoomIn, CURSOR_ZOOM_IN_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case ZoomOut:
|
||||||
|
if (assetCursorZoomOut == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_ZOOM_OUT_PARAMS.graphic);
|
||||||
|
assetCursorZoomOut = bitmapData;
|
||||||
|
applyCursorParams(assetCursorZoomOut, CURSOR_ZOOM_OUT_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorZoomOut, CURSOR_ZOOM_OUT_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Crosshair:
|
||||||
|
if (assetCursorCrosshair == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_CROSSHAIR_PARAMS.graphic);
|
||||||
|
assetCursorCrosshair = bitmapData;
|
||||||
|
applyCursorParams(assetCursorCrosshair, CURSOR_CROSSHAIR_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorCrosshair, CURSOR_CROSSHAIR_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Cell:
|
||||||
|
if (assetCursorCell == null)
|
||||||
|
{
|
||||||
|
var bitmapData:BitmapData = Assets.getBitmapData(CURSOR_CELL_PARAMS.graphic);
|
||||||
|
assetCursorCell = bitmapData;
|
||||||
|
applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
setCursorGraphic(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asynchronous.
|
||||||
|
*/
|
||||||
|
static function loadCursorGraphic(?value:CursorMode = null):Void
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
FlxG.mouse.unload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
switch (value)
|
switch (value)
|
||||||
{
|
{
|
||||||
case Default:
|
case Default:
|
||||||
|
@ -127,6 +329,7 @@ class Cursor
|
||||||
assetCursorDefault = bitmapData;
|
assetCursorDefault = bitmapData;
|
||||||
applyCursorParams(assetCursorDefault, CURSOR_DEFAULT_PARAMS);
|
applyCursorParams(assetCursorDefault, CURSOR_DEFAULT_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(Default));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -141,6 +344,7 @@ class Cursor
|
||||||
assetCursorCross = bitmapData;
|
assetCursorCross = bitmapData;
|
||||||
applyCursorParams(assetCursorCross, CURSOR_CROSS_PARAMS);
|
applyCursorParams(assetCursorCross, CURSOR_CROSS_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(Cross));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -155,6 +359,7 @@ class Cursor
|
||||||
assetCursorEraser = bitmapData;
|
assetCursorEraser = bitmapData;
|
||||||
applyCursorParams(assetCursorEraser, CURSOR_ERASER_PARAMS);
|
applyCursorParams(assetCursorEraser, CURSOR_ERASER_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(Eraser));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -169,6 +374,7 @@ class Cursor
|
||||||
assetCursorGrabbing = bitmapData;
|
assetCursorGrabbing = bitmapData;
|
||||||
applyCursorParams(assetCursorGrabbing, CURSOR_GRABBING_PARAMS);
|
applyCursorParams(assetCursorGrabbing, CURSOR_GRABBING_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(Grabbing));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -183,6 +389,7 @@ class Cursor
|
||||||
assetCursorHourglass = bitmapData;
|
assetCursorHourglass = bitmapData;
|
||||||
applyCursorParams(assetCursorHourglass, CURSOR_HOURGLASS_PARAMS);
|
applyCursorParams(assetCursorHourglass, CURSOR_HOURGLASS_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(Hourglass));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -197,6 +404,7 @@ class Cursor
|
||||||
assetCursorPointer = bitmapData;
|
assetCursorPointer = bitmapData;
|
||||||
applyCursorParams(assetCursorPointer, CURSOR_POINTER_PARAMS);
|
applyCursorParams(assetCursorPointer, CURSOR_POINTER_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(Pointer));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -211,6 +419,7 @@ class Cursor
|
||||||
assetCursorText = bitmapData;
|
assetCursorText = bitmapData;
|
||||||
applyCursorParams(assetCursorText, CURSOR_TEXT_PARAMS);
|
applyCursorParams(assetCursorText, CURSOR_TEXT_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(Text));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -225,6 +434,7 @@ class Cursor
|
||||||
assetCursorZoomIn = bitmapData;
|
assetCursorZoomIn = bitmapData;
|
||||||
applyCursorParams(assetCursorZoomIn, CURSOR_ZOOM_IN_PARAMS);
|
applyCursorParams(assetCursorZoomIn, CURSOR_ZOOM_IN_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(ZoomIn));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -239,14 +449,45 @@ class Cursor
|
||||||
assetCursorZoomOut = bitmapData;
|
assetCursorZoomOut = bitmapData;
|
||||||
applyCursorParams(assetCursorZoomOut, CURSOR_ZOOM_OUT_PARAMS);
|
applyCursorParams(assetCursorZoomOut, CURSOR_ZOOM_OUT_PARAMS);
|
||||||
});
|
});
|
||||||
|
future.onError(onCursorError.bind(ZoomOut));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
applyCursorParams(assetCursorZoomOut, CURSOR_ZOOM_OUT_PARAMS);
|
applyCursorParams(assetCursorZoomOut, CURSOR_ZOOM_OUT_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Crosshair:
|
||||||
|
if (assetCursorCrosshair == null)
|
||||||
|
{
|
||||||
|
var future:Future<BitmapData> = Assets.loadBitmapData(CURSOR_CROSSHAIR_PARAMS.graphic);
|
||||||
|
future.onComplete(function(bitmapData:BitmapData) {
|
||||||
|
assetCursorCrosshair = bitmapData;
|
||||||
|
applyCursorParams(assetCursorCrosshair, CURSOR_CROSSHAIR_PARAMS);
|
||||||
|
});
|
||||||
|
future.onError(onCursorError.bind(Crosshair));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorCrosshair, CURSOR_CROSSHAIR_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
case Cell:
|
||||||
|
if (assetCursorCell == null)
|
||||||
|
{
|
||||||
|
var future:Future<BitmapData> = Assets.loadBitmapData(CURSOR_CELL_PARAMS.graphic);
|
||||||
|
future.onComplete(function(bitmapData:BitmapData) {
|
||||||
|
assetCursorCell = bitmapData;
|
||||||
|
applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS);
|
||||||
|
});
|
||||||
|
future.onError(onCursorError.bind(Cell));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
applyCursorParams(assetCursorCell, CURSOR_CELL_PARAMS);
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
setCursorGraphic(null);
|
loadCursorGraphic(null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +495,11 @@ class Cursor
|
||||||
{
|
{
|
||||||
FlxG.mouse.load(graphic, params.scale, params.offsetX, params.offsetY);
|
FlxG.mouse.load(graphic, params.scale, params.offsetX, params.offsetY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static function onCursorError(cursorMode:CursorMode, error:String):Void
|
||||||
|
{
|
||||||
|
trace("Failed to load cursor graphic for cursor mode " + cursorMode + ": " + error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
|
// https://developer.mozilla.org/en-US/docs/Web/CSS/cursor
|
||||||
|
@ -268,6 +514,8 @@ enum CursorMode
|
||||||
Text;
|
Text;
|
||||||
ZoomIn;
|
ZoomIn;
|
||||||
ZoomOut;
|
ZoomOut;
|
||||||
|
Crosshair;
|
||||||
|
Cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -179,7 +179,7 @@ class SongMigrator
|
||||||
songMetadata.playData.playableChars = {};
|
songMetadata.playData.playableChars = {};
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Reflect.setField(songMetadata.playData.playableChars, songData.song.player1, new SongPlayableChar('', songData.song.player2));
|
songMetadata.playData.playableChars.set(songData.song.player1, new SongPlayableChar('', songData.song.player2));
|
||||||
}
|
}
|
||||||
catch (e)
|
catch (e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,6 +6,7 @@ import funkin.util.SerializerUtil;
|
||||||
import funkin.play.song.SongData.SongChartData;
|
import funkin.play.song.SongData.SongChartData;
|
||||||
import funkin.play.song.SongData.SongMetadata;
|
import funkin.play.song.SongData.SongMetadata;
|
||||||
import flixel.util.FlxTimer;
|
import flixel.util.FlxTimer;
|
||||||
|
import funkin.ui.haxeui.components.FunkinLink;
|
||||||
import funkin.util.SortUtil;
|
import funkin.util.SortUtil;
|
||||||
import funkin.input.Cursor;
|
import funkin.input.Cursor;
|
||||||
import funkin.play.character.BaseCharacter;
|
import funkin.play.character.BaseCharacter;
|
||||||
|
@ -122,7 +123,7 @@ class ChartEditorDialogHandler
|
||||||
trace('[WARN] Could not fetch song name for ${targetSongId}');
|
trace('[WARN] Could not fetch song name for ${targetSongId}');
|
||||||
}
|
}
|
||||||
|
|
||||||
var linkTemplateSong:Link = new Link();
|
var linkTemplateSong:Link = new FunkinLink();
|
||||||
linkTemplateSong.text = songName;
|
linkTemplateSong.text = songName;
|
||||||
linkTemplateSong.onClick = function(_event) {
|
linkTemplateSong.onClick = function(_event) {
|
||||||
dialog.hideDialog(DialogButton.CANCEL);
|
dialog.hideDialog(DialogButton.CANCEL);
|
||||||
|
@ -290,6 +291,7 @@ class ChartEditorDialogHandler
|
||||||
if (state.loadInstrumentalFromBytes(selectedFile.bytes))
|
if (state.loadInstrumentalFromBytes(selectedFile.bytes))
|
||||||
{
|
{
|
||||||
trace('Selected file: ' + selectedFile.fullPath);
|
trace('Selected file: ' + selectedFile.fullPath);
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -297,6 +299,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
removeDropHandler(onDropFile);
|
removeDropHandler(onDropFile);
|
||||||
|
@ -305,6 +308,7 @@ class ChartEditorDialogHandler
|
||||||
{
|
{
|
||||||
trace('Failed to load instrumental (${selectedFile.fullPath})');
|
trace('Failed to load instrumental (${selectedFile.fullPath})');
|
||||||
|
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Failure',
|
title: 'Failure',
|
||||||
|
@ -312,6 +316,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Error,
|
type: NotificationType.Error,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -323,6 +328,7 @@ class ChartEditorDialogHandler
|
||||||
if (state.loadInstrumentalFromPath(path))
|
if (state.loadInstrumentalFromPath(path))
|
||||||
{
|
{
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -330,6 +336,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
removeDropHandler(onDropFile);
|
removeDropHandler(onDropFile);
|
||||||
|
@ -346,6 +353,7 @@ class ChartEditorDialogHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Failure',
|
title: 'Failure',
|
||||||
|
@ -353,6 +361,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Error,
|
type: NotificationType.Error,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -635,6 +644,7 @@ class ChartEditorDialogHandler
|
||||||
if (state.loadVocalsFromPath(path, charKey))
|
if (state.loadVocalsFromPath(path, charKey))
|
||||||
{
|
{
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -642,7 +652,9 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
|
|
||||||
vocalsEntryLabel.text = 'Vocals for $charName (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
vocalsEntryLabel.text = 'Vocals for $charName (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
||||||
#else
|
#else
|
||||||
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${path.file}.${path.ext}';
|
vocalsEntryLabel.text = 'Vocals for $charName (click to browse)\n${path.file}.${path.ext}';
|
||||||
|
@ -663,6 +675,7 @@ class ChartEditorDialogHandler
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vocals failed to load.
|
// Vocals failed to load.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Failure',
|
title: 'Failure',
|
||||||
|
@ -670,6 +683,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Error,
|
type: NotificationType.Error,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
vocalsEntryLabel.text = 'Drag and drop vocals for $charName here, or click to browse.';
|
||||||
|
@ -778,6 +792,14 @@ class ChartEditorDialogHandler
|
||||||
songVariationMetadataEntryLabel.text = 'Click to browse for <song>-metadata-${variation}.json file.';
|
songVariationMetadataEntryLabel.text = 'Click to browse for <song>-metadata-${variation}.json file.';
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
songVariationMetadataEntry.onMouseOver = function(_event) {
|
||||||
|
songVariationMetadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
songVariationMetadataEntry.onMouseOut = function(_event) {
|
||||||
|
songVariationMetadataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
songVariationMetadataEntry.onClick = onClickMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel);
|
songVariationMetadataEntry.onClick = onClickMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel);
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
addDropHandler(songVariationMetadataEntry, onDropFileMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel));
|
addDropHandler(songVariationMetadataEntry, onDropFileMetadataVariation.bind(variation).bind(songVariationMetadataEntryLabel));
|
||||||
|
@ -793,6 +815,14 @@ class ChartEditorDialogHandler
|
||||||
songVariationChartDataEntryLabel.text = 'Click to browse for <song>-chart-${variation}.json file.';
|
songVariationChartDataEntryLabel.text = 'Click to browse for <song>-chart-${variation}.json file.';
|
||||||
#end
|
#end
|
||||||
|
|
||||||
|
songVariationChartDataEntry.onMouseOver = function(_event) {
|
||||||
|
songVariationChartDataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
songVariationChartDataEntry.onMouseOut = function(_event) {
|
||||||
|
songVariationChartDataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
songVariationChartDataEntry.onClick = onClickChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel);
|
songVariationChartDataEntry.onClick = onClickChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel);
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
addDropHandler(songVariationChartDataEntry, onDropFileChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel));
|
addDropHandler(songVariationChartDataEntry, onDropFileChartDataVariation.bind(variation).bind(songVariationChartDataEntryLabel));
|
||||||
|
@ -812,6 +842,7 @@ class ChartEditorDialogHandler
|
||||||
if (songMetadataVariation == null)
|
if (songMetadataVariation == null)
|
||||||
{
|
{
|
||||||
// Tell the user the load was not successful.
|
// Tell the user the load was not successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Failure',
|
title: 'Failure',
|
||||||
|
@ -819,12 +850,14 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Error,
|
type: NotificationType.Error,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
songMetadata.set(variation, songMetadataVariation);
|
songMetadata.set(variation, songMetadataVariation);
|
||||||
|
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -832,6 +865,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
||||||
|
@ -857,6 +891,7 @@ class ChartEditorDialogHandler
|
||||||
songMetadata.set(variation, songMetadataVariation);
|
songMetadata.set(variation, songMetadataVariation);
|
||||||
|
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -864,6 +899,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
label.text = 'Metadata file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
||||||
|
@ -890,6 +926,7 @@ class ChartEditorDialogHandler
|
||||||
state.noteDisplayDirty = true;
|
state.noteDisplayDirty = true;
|
||||||
|
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -897,6 +934,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${path.file}.${path.ext}';
|
||||||
|
@ -922,6 +960,7 @@ class ChartEditorDialogHandler
|
||||||
state.noteDisplayDirty = true;
|
state.noteDisplayDirty = true;
|
||||||
|
|
||||||
// Tell the user the load was successful.
|
// Tell the user the load was successful.
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -929,6 +968,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
|
|
||||||
#if FILE_DROP_SUPPORTED
|
#if FILE_DROP_SUPPORTED
|
||||||
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
label.text = 'Chart data file (drag and drop, or click to browse)\nSelected file: ${selectedFile.name}';
|
||||||
|
@ -955,6 +995,14 @@ class ChartEditorDialogHandler
|
||||||
|
|
||||||
metadataEntry.onClick = onClickMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel);
|
metadataEntry.onClick = onClickMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel);
|
||||||
addDropHandler(metadataEntry, onDropFileMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel));
|
addDropHandler(metadataEntry, onDropFileMetadataVariation.bind(Constants.DEFAULT_VARIATION).bind(metadataEntryLabel));
|
||||||
|
metadataEntry.onMouseOver = function(_event) {
|
||||||
|
metadataEntry.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
metadataEntry.onMouseOut = function(_event) {
|
||||||
|
metadataEntry.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
|
||||||
chartContainerA.addComponent(metadataEntry);
|
chartContainerA.addComponent(metadataEntry);
|
||||||
|
|
||||||
|
@ -998,7 +1046,6 @@ class ChartEditorDialogHandler
|
||||||
importBox.swapClass('upload-bg', 'upload-bg-hover');
|
importBox.swapClass('upload-bg', 'upload-bg-hover');
|
||||||
Cursor.cursorMode = Pointer;
|
Cursor.cursorMode = Pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
importBox.onMouseOut = function(_event) {
|
importBox.onMouseOut = function(_event) {
|
||||||
importBox.swapClass('upload-bg-hover', 'upload-bg');
|
importBox.swapClass('upload-bg-hover', 'upload-bg');
|
||||||
Cursor.cursorMode = Default;
|
Cursor.cursorMode = Default;
|
||||||
|
@ -1018,6 +1065,7 @@ class ChartEditorDialogHandler
|
||||||
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -1025,6 +1073,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1038,6 +1087,7 @@ class ChartEditorDialogHandler
|
||||||
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
state.loadSong([Constants.DEFAULT_VARIATION => songMetadata], [Constants.DEFAULT_VARIATION => songChartData]);
|
||||||
|
|
||||||
dialog.hideDialog(DialogButton.APPLY);
|
dialog.hideDialog(DialogButton.APPLY);
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -1045,6 +1095,7 @@ class ChartEditorDialogHandler
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
};
|
};
|
||||||
|
|
||||||
addDropHandler(importBox, onDropFile);
|
addDropHandler(importBox, onDropFile);
|
||||||
|
|
|
@ -130,7 +130,7 @@ class ChartEditorNoteSprite extends FlxSprite
|
||||||
return this.noteData;
|
return this.noteData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function updateNotePosition(?origin:FlxObject)
|
public function updateNotePosition(?origin:FlxObject):Void
|
||||||
{
|
{
|
||||||
if (this.noteData == null) return;
|
if (this.noteData == null) return;
|
||||||
|
|
||||||
|
@ -160,9 +160,7 @@ class ChartEditorNoteSprite extends FlxSprite
|
||||||
if (this.noteData.stepTime >= 0)
|
if (this.noteData.stepTime >= 0)
|
||||||
{
|
{
|
||||||
// noteData.stepTime is a calculated value which accounts for BPM changes
|
// noteData.stepTime is a calculated value which accounts for BPM changes
|
||||||
var stepTime:Float = this.noteData.stepTime;
|
this.y = this.noteData.stepTime * ChartEditorState.GRID_SIZE;
|
||||||
var roundedStepTime:Float = Math.floor(stepTime + 0.01); // Add epsilon to fix rounding issues
|
|
||||||
this.y = roundedStepTime * ChartEditorState.GRID_SIZE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (origin != null)
|
if (origin != null)
|
||||||
|
|
|
@ -179,14 +179,24 @@ class ChartEditorState extends HaxeUIState
|
||||||
*/
|
*/
|
||||||
static final SNAP_QUANTS:Array<Int> = [4, 8, 12, 16, 20, 24, 32, 48, 64, 96, 192];
|
static final SNAP_QUANTS:Array<Int> = [4, 8, 12, 16, 20, 24, 32, 48, 64, 96, 192];
|
||||||
|
|
||||||
|
static final BASE_QUANT:Int = 16;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* INSTANCE DATA
|
* INSTANCE DATA
|
||||||
*/
|
*/
|
||||||
// ==============================
|
// ==============================
|
||||||
public var currentZoomLevel:Float = 1.0;
|
public var currentZoomLevel:Float = 1.0;
|
||||||
|
|
||||||
var noteSnapQuantIndex:Int = 3;
|
/**
|
||||||
|
* The internal index of what note snapping value is in use.
|
||||||
|
* Increment to make placement more preceise and decrement to make placement less precise.
|
||||||
|
*/
|
||||||
|
var noteSnapQuantIndex:Int = 3; // default is 16
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The current note snapping value.
|
||||||
|
* For example, `32` when snapping to 32nd notes.
|
||||||
|
*/
|
||||||
public var noteSnapQuant(get, never):Int;
|
public var noteSnapQuant(get, never):Int;
|
||||||
|
|
||||||
function get_noteSnapQuant():Int
|
function get_noteSnapQuant():Int
|
||||||
|
@ -194,6 +204,17 @@ class ChartEditorState extends HaxeUIState
|
||||||
return SNAP_QUANTS[noteSnapQuantIndex];
|
return SNAP_QUANTS[noteSnapQuantIndex];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ratio of the current note snapping value to the default.
|
||||||
|
* For example, `32` becomes `0.5` when snapping to 16th notes.
|
||||||
|
*/
|
||||||
|
public var noteSnapRatio(get, never):Float;
|
||||||
|
|
||||||
|
function get_noteSnapRatio():Float
|
||||||
|
{
|
||||||
|
return BASE_QUANT / noteSnapQuant;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* scrollPosition is the current position in the song, in pixels.
|
* scrollPosition is the current position in the song, in pixels.
|
||||||
* One pixel is 1/40 of 1 step, and 1/160 of 1 beat.
|
* One pixel is 1/40 of 1 step, and 1/160 of 1 beat.
|
||||||
|
@ -1195,6 +1216,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
// Set the z-index of the HaxeUI.
|
// Set the z-index of the HaxeUI.
|
||||||
this.component.zIndex = 100;
|
this.component.zIndex = 100;
|
||||||
|
|
||||||
|
// Show the mouse cursor.
|
||||||
|
Cursor.show();
|
||||||
|
|
||||||
fixCamera();
|
fixCamera();
|
||||||
|
|
||||||
// Get rid of any music from the previous state.
|
// Get rid of any music from the previous state.
|
||||||
|
@ -1282,9 +1306,13 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
buildNoteGroup();
|
buildNoteGroup();
|
||||||
|
|
||||||
gridPlayheadScrollArea = new FlxSprite(gridTiledSprite.x - PLAYHEAD_SCROLL_AREA_WIDTH,
|
gridPlayheadScrollArea = new FlxSprite(0, 0);
|
||||||
MENU_BAR_HEIGHT).makeGraphic(PLAYHEAD_SCROLL_AREA_WIDTH, FlxG.height - MENU_BAR_HEIGHT, PLAYHEAD_SCROLL_AREA_COLOR);
|
gridPlayheadScrollArea.makeGraphic(10, 10, PLAYHEAD_SCROLL_AREA_COLOR); // Make it 10x10px and then scale it as needed.
|
||||||
add(gridPlayheadScrollArea);
|
add(gridPlayheadScrollArea);
|
||||||
|
gridPlayheadScrollArea.setGraphicSize(PLAYHEAD_SCROLL_AREA_WIDTH, 3000);
|
||||||
|
gridPlayheadScrollArea.updateHitbox();
|
||||||
|
gridPlayheadScrollArea.x = gridTiledSprite.x - PLAYHEAD_SCROLL_AREA_WIDTH;
|
||||||
|
gridPlayheadScrollArea.y = MENU_BAR_HEIGHT + GRID_TOP_PAD;
|
||||||
gridPlayheadScrollArea.zIndex = 25;
|
gridPlayheadScrollArea.zIndex = 25;
|
||||||
|
|
||||||
// The playhead that show the current position in the song.
|
// The playhead that show the current position in the song.
|
||||||
|
@ -1769,7 +1797,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
// These ones only happen if the modal dialog is not open.
|
// These ones only happen if the modal dialog is not open.
|
||||||
handleScrollKeybinds();
|
handleScrollKeybinds();
|
||||||
// handleZoom();
|
// handleZoom();
|
||||||
// handleSnap();
|
handleSnap();
|
||||||
handleCursor();
|
handleCursor();
|
||||||
|
|
||||||
handleMenubar();
|
handleMenubar();
|
||||||
|
@ -1845,14 +1873,21 @@ class ChartEditorState extends HaxeUIState
|
||||||
**/
|
**/
|
||||||
function handleScrollKeybinds():Void
|
function handleScrollKeybinds():Void
|
||||||
{
|
{
|
||||||
// Don't scroll when the cursor is over the UI.
|
// Don't scroll when the cursor is over the UI, unless a playbar button (the << >> ones) is pressed.
|
||||||
if (isCursorOverHaxeUI) return;
|
if (isCursorOverHaxeUI && playbarButtonPressed == null) return;
|
||||||
|
|
||||||
var scrollAmount:Float = 0; // Amount to scroll the grid.
|
var scrollAmount:Float = 0; // Amount to scroll the grid.
|
||||||
var playheadAmount:Float = 0; // Amount to scroll the playhead relative to the grid.
|
var playheadAmount:Float = 0; // Amount to scroll the playhead relative to the grid.
|
||||||
var shouldPause:Bool = false; // Whether to pause the song when scrolling.
|
var shouldPause:Bool = false; // Whether to pause the song when scrolling.
|
||||||
var shouldEase:Bool = false; // Whether to ease the scroll.
|
var shouldEase:Bool = false; // Whether to ease the scroll.
|
||||||
|
|
||||||
|
// Mouse Wheel = Scroll
|
||||||
|
if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL)
|
||||||
|
{
|
||||||
|
scrollAmount = -10 * FlxG.mouse.wheel;
|
||||||
|
shouldPause = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Up Arrow = Scroll Up
|
// Up Arrow = Scroll Up
|
||||||
if (upKeyHandler.activated && currentLiveInputStyle != LiveInputStyle.WASD)
|
if (upKeyHandler.activated && currentLiveInputStyle != LiveInputStyle.WASD)
|
||||||
{
|
{
|
||||||
|
@ -1870,13 +1905,15 @@ class ChartEditorState extends HaxeUIState
|
||||||
if (pageUpKeyHandler.activated)
|
if (pageUpKeyHandler.activated)
|
||||||
{
|
{
|
||||||
var measureHeight:Float = GRID_SIZE * 4 * Conductor.beatsPerMeasure;
|
var measureHeight:Float = GRID_SIZE * 4 * Conductor.beatsPerMeasure;
|
||||||
var targetScrollPosition:Float = Math.floor(scrollPositionInPixels / measureHeight) * measureHeight;
|
var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels;
|
||||||
|
var targetScrollPosition:Float = Math.floor(playheadPos / measureHeight) * measureHeight;
|
||||||
// If we would move less than one grid, instead move to the top of the previous measure.
|
// If we would move less than one grid, instead move to the top of the previous measure.
|
||||||
if (Math.abs(targetScrollPosition - scrollPositionInPixels) < GRID_SIZE)
|
var targetScrollAmount = Math.abs(targetScrollPosition - playheadPos);
|
||||||
|
if (targetScrollAmount < GRID_SIZE)
|
||||||
{
|
{
|
||||||
targetScrollPosition -= GRID_SIZE * 4 * Conductor.beatsPerMeasure;
|
targetScrollPosition -= GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.beatsPerMeasure;
|
||||||
}
|
}
|
||||||
scrollAmount = targetScrollPosition - scrollPositionInPixels;
|
scrollAmount = targetScrollPosition - playheadPos;
|
||||||
|
|
||||||
shouldPause = true;
|
shouldPause = true;
|
||||||
}
|
}
|
||||||
|
@ -1891,13 +1928,15 @@ class ChartEditorState extends HaxeUIState
|
||||||
if (pageDownKeyHandler.activated)
|
if (pageDownKeyHandler.activated)
|
||||||
{
|
{
|
||||||
var measureHeight:Float = GRID_SIZE * 4 * Conductor.beatsPerMeasure;
|
var measureHeight:Float = GRID_SIZE * 4 * Conductor.beatsPerMeasure;
|
||||||
var targetScrollPosition:Float = Math.ceil(scrollPositionInPixels / measureHeight) * measureHeight;
|
var playheadPos:Float = scrollPositionInPixels + playheadPositionInPixels;
|
||||||
|
var targetScrollPosition:Float = Math.ceil(playheadPos / measureHeight) * measureHeight;
|
||||||
// If we would move less than one grid, instead move to the top of the next measure.
|
// If we would move less than one grid, instead move to the top of the next measure.
|
||||||
if (Math.abs(targetScrollPosition - scrollPositionInPixels) < GRID_SIZE)
|
var targetScrollAmount = Math.abs(targetScrollPosition - playheadPos);
|
||||||
|
if (targetScrollAmount < GRID_SIZE)
|
||||||
{
|
{
|
||||||
targetScrollPosition += GRID_SIZE * 4 * Conductor.beatsPerMeasure;
|
targetScrollPosition += GRID_SIZE * Constants.STEPS_PER_BEAT * Conductor.beatsPerMeasure;
|
||||||
}
|
}
|
||||||
scrollAmount = targetScrollPosition - scrollPositionInPixels;
|
scrollAmount = targetScrollPosition - playheadPos;
|
||||||
|
|
||||||
shouldPause = true;
|
shouldPause = true;
|
||||||
}
|
}
|
||||||
|
@ -1908,13 +1947,6 @@ class ChartEditorState extends HaxeUIState
|
||||||
shouldPause = true;
|
shouldPause = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mouse Wheel = Scroll
|
|
||||||
if (FlxG.mouse.wheel != 0 && !FlxG.keys.pressed.CONTROL)
|
|
||||||
{
|
|
||||||
scrollAmount = -10 * FlxG.mouse.wheel;
|
|
||||||
shouldPause = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Middle Mouse + Drag = Scroll but move the playhead the same amount.
|
// Middle Mouse + Drag = Scroll but move the playhead the same amount.
|
||||||
if (FlxG.mouse.pressedMiddle)
|
if (FlxG.mouse.pressedMiddle)
|
||||||
{
|
{
|
||||||
|
@ -2046,6 +2078,11 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
if (shouldHandleCursor)
|
if (shouldHandleCursor)
|
||||||
{
|
{
|
||||||
|
// Over the course of this big conditional block,
|
||||||
|
// we determine what the cursor should look like,
|
||||||
|
// and fall back to the default cursor if none of the conditions are met.
|
||||||
|
var targetCursorMode:Null<CursorMode> = null;
|
||||||
|
|
||||||
if (gridTiledSprite == null) throw "ERROR: Tried to handle cursor, but gridTiledSprite is null! Check ChartEditorState.buildGrid()";
|
if (gridTiledSprite == null) throw "ERROR: Tried to handle cursor, but gridTiledSprite is null! Check ChartEditorState.buildGrid()";
|
||||||
|
|
||||||
var overlapsGrid:Bool = FlxG.mouse.overlaps(gridTiledSprite);
|
var overlapsGrid:Bool = FlxG.mouse.overlaps(gridTiledSprite);
|
||||||
|
@ -2055,9 +2092,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
var cursorY:Float = FlxG.mouse.screenY - gridTiledSprite.y;
|
var cursorY:Float = FlxG.mouse.screenY - gridTiledSprite.y;
|
||||||
|
|
||||||
var overlapsSelectionBorder:Bool = overlapsGrid
|
var overlapsSelectionBorder:Bool = overlapsGrid
|
||||||
&& (cursorX % 40) < (GRID_SELECTION_BORDER_WIDTH / 2)
|
&& ((cursorX % 40) < (GRID_SELECTION_BORDER_WIDTH / 2)
|
||||||
|| (cursorX % 40) > (40 - (GRID_SELECTION_BORDER_WIDTH / 2))
|
|| (cursorX % 40) > (40 - (GRID_SELECTION_BORDER_WIDTH / 2))
|
||||||
|| (cursorY % 40) < (GRID_SELECTION_BORDER_WIDTH / 2) || (cursorY % 40) > (40 - (GRID_SELECTION_BORDER_WIDTH / 2));
|
|| (cursorY % 40) < (GRID_SELECTION_BORDER_WIDTH / 2) || (cursorY % 40) > (40 - (GRID_SELECTION_BORDER_WIDTH / 2)));
|
||||||
|
|
||||||
if (FlxG.mouse.justPressed)
|
if (FlxG.mouse.justPressed)
|
||||||
{
|
{
|
||||||
|
@ -2073,6 +2110,8 @@ class ChartEditorState extends HaxeUIState
|
||||||
else if (!overlapsGrid || overlapsSelectionBorder)
|
else if (!overlapsGrid || overlapsSelectionBorder)
|
||||||
{
|
{
|
||||||
selectionBoxStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
|
selectionBoxStartPos = new FlxPoint(FlxG.mouse.screenX, FlxG.mouse.screenY);
|
||||||
|
// Drawing selection box.
|
||||||
|
targetCursorMode = Crosshair;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2083,23 +2122,6 @@ class ChartEditorState extends HaxeUIState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gridPlayheadScrollAreaPressed)
|
|
||||||
{
|
|
||||||
Cursor.cursorMode = Grabbing;
|
|
||||||
}
|
|
||||||
else if (notePreviewScrollAreaStartPos != null)
|
|
||||||
{
|
|
||||||
Cursor.cursorMode = Pointer;
|
|
||||||
}
|
|
||||||
else if (gridPlayheadScrollArea != null && FlxG.mouse.overlaps(gridPlayheadScrollArea))
|
|
||||||
{
|
|
||||||
Cursor.cursorMode = Pointer;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Cursor.cursorMode = Default;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (gridPlayheadScrollAreaPressed && FlxG.mouse.released)
|
if (gridPlayheadScrollAreaPressed && FlxG.mouse.released)
|
||||||
{
|
{
|
||||||
gridPlayheadScrollAreaPressed = false;
|
gridPlayheadScrollAreaPressed = false;
|
||||||
|
@ -2116,11 +2138,18 @@ class ChartEditorState extends HaxeUIState
|
||||||
// Move the playhead to the cursor position.
|
// Move the playhead to the cursor position.
|
||||||
this.playheadPositionInPixels = FlxG.mouse.screenY - MENU_BAR_HEIGHT - GRID_TOP_PAD;
|
this.playheadPositionInPixels = FlxG.mouse.screenY - MENU_BAR_HEIGHT - GRID_TOP_PAD;
|
||||||
moveSongToScrollPosition();
|
moveSongToScrollPosition();
|
||||||
|
|
||||||
|
// Cursor should be a grabby hand.
|
||||||
|
if (targetCursorMode == null) targetCursorMode = Grabbing;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The song position of the cursor, in steps.
|
// The song position of the cursor, in steps.
|
||||||
var cursorFractionalStep:Float = cursorY / GRID_SIZE / (16 / noteSnapQuant);
|
var cursorFractionalStep:Float = cursorY / GRID_SIZE;
|
||||||
var cursorMs:Float = Conductor.getStepTimeInMs(cursorFractionalStep);
|
var cursorMs:Float = Conductor.getStepTimeInMs(cursorFractionalStep);
|
||||||
|
// Round the cursor step to the nearest snap quant.
|
||||||
|
var cursorSnappedStep:Float = Math.floor(cursorFractionalStep / noteSnapRatio) * noteSnapRatio;
|
||||||
|
var cursorSnappedMs:Float = Conductor.getStepTimeInMs(cursorSnappedStep);
|
||||||
|
|
||||||
// The direction value for the column at the cursor.
|
// The direction value for the column at the cursor.
|
||||||
var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE);
|
var cursorColumn:Int = Math.floor(cursorX / GRID_SIZE);
|
||||||
if (cursorColumn < 0) cursorColumn = 0;
|
if (cursorColumn < 0) cursorColumn = 0;
|
||||||
|
@ -2268,6 +2297,8 @@ class ChartEditorState extends HaxeUIState
|
||||||
selectionRect.width = Math.abs(FlxG.mouse.screenX - selectionBoxStartPos.x);
|
selectionRect.width = Math.abs(FlxG.mouse.screenX - selectionBoxStartPos.x);
|
||||||
selectionRect.height = Math.abs(FlxG.mouse.screenY - selectionBoxStartPos.y);
|
selectionRect.height = Math.abs(FlxG.mouse.screenY - selectionBoxStartPos.y);
|
||||||
setSelectionBoxBounds(selectionRect);
|
setSelectionBoxBounds(selectionRect);
|
||||||
|
|
||||||
|
targetCursorMode = Crosshair;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (FlxG.mouse.justReleased)
|
else if (FlxG.mouse.justReleased)
|
||||||
|
@ -2359,7 +2390,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
}
|
}
|
||||||
else if (notePreviewScrollAreaStartPos != null)
|
else if (notePreviewScrollAreaStartPos != null)
|
||||||
{
|
{
|
||||||
trace('Updating current song time while clicking and holding...');
|
// Player is clicking and holding on note preview to scrub around.
|
||||||
|
targetCursorMode = Grabbing;
|
||||||
|
|
||||||
var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.screenY, (notePreview?.y ?? 0.0),
|
var clickedPosInPixels:Float = FlxMath.remapToRange(FlxG.mouse.screenY, (notePreview?.y ?? 0.0),
|
||||||
(notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0), 0, songLengthInPixels);
|
(notePreview?.y ?? 0.0) + (notePreview?.height ?? 0.0), 0, songLengthInPixels);
|
||||||
|
|
||||||
|
@ -2371,7 +2404,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
// Handle extending the note as you drag.
|
// Handle extending the note as you drag.
|
||||||
|
|
||||||
// TODO: This should be beat snapped?
|
// TODO: This should be beat snapped?
|
||||||
var dragLengthSteps:Float = Conductor.getTimeInSteps(cursorMs) - currentPlaceNoteData.stepTime;
|
var dragLengthSteps:Float = Conductor.getTimeInSteps(cursorSnappedMs) - currentPlaceNoteData.stepTime;
|
||||||
|
|
||||||
// Without this, the newly placed note feels too short compared to the user's input.
|
// Without this, the newly placed note feels too short compared to the user's input.
|
||||||
var INCREMENT:Float = 1.0;
|
var INCREMENT:Float = 1.0;
|
||||||
|
@ -2465,14 +2498,14 @@ class ChartEditorState extends HaxeUIState
|
||||||
{
|
{
|
||||||
// Create an event and place it in the chart.
|
// Create an event and place it in the chart.
|
||||||
// TODO: Figure out configuring event data.
|
// TODO: Figure out configuring event data.
|
||||||
var newEventData:SongEventData = new SongEventData(cursorMs, selectedEventKind, selectedEventData);
|
var newEventData:SongEventData = new SongEventData(cursorSnappedMs, selectedEventKind, selectedEventData);
|
||||||
|
|
||||||
performCommand(new AddEventsCommand([newEventData], FlxG.keys.pressed.CONTROL));
|
performCommand(new AddEventsCommand([newEventData], FlxG.keys.pressed.CONTROL));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create a note and place it in the chart.
|
// Create a note and place it in the chart.
|
||||||
var newNoteData:SongNoteData = new SongNoteData(cursorMs, cursorColumn, 0, selectedNoteKind);
|
var newNoteData:SongNoteData = new SongNoteData(cursorSnappedMs, cursorColumn, 0, selectedNoteKind);
|
||||||
|
|
||||||
performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL));
|
performCommand(new AddNotesCommand([newNoteData], FlxG.keys.pressed.CONTROL));
|
||||||
|
|
||||||
|
@ -2527,8 +2560,6 @@ class ChartEditorState extends HaxeUIState
|
||||||
// Handle grid cursor.
|
// Handle grid cursor.
|
||||||
if (overlapsGrid && !overlapsSelectionBorder && !gridPlayheadScrollAreaPressed)
|
if (overlapsGrid && !overlapsSelectionBorder && !gridPlayheadScrollAreaPressed)
|
||||||
{
|
{
|
||||||
Cursor.cursorMode = Pointer;
|
|
||||||
|
|
||||||
// Indicate that we can place a note here.
|
// Indicate that we can place a note here.
|
||||||
|
|
||||||
if (cursorColumn == eventColumn)
|
if (cursorColumn == eventColumn)
|
||||||
|
@ -2543,11 +2574,13 @@ class ChartEditorState extends HaxeUIState
|
||||||
{
|
{
|
||||||
eventData.event = selectedEventKind;
|
eventData.event = selectedEventKind;
|
||||||
}
|
}
|
||||||
eventData.time = cursorMs;
|
eventData.time = cursorSnappedMs;
|
||||||
|
|
||||||
gridGhostEvent.visible = true;
|
gridGhostEvent.visible = true;
|
||||||
gridGhostEvent.eventData = eventData;
|
gridGhostEvent.eventData = eventData;
|
||||||
gridGhostEvent.updateEventPosition(renderedEvents);
|
gridGhostEvent.updateEventPosition(renderedEvents);
|
||||||
|
|
||||||
|
targetCursorMode = Cell;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2563,35 +2596,61 @@ class ChartEditorState extends HaxeUIState
|
||||||
noteData.data = cursorColumn;
|
noteData.data = cursorColumn;
|
||||||
gridGhostNote.playNoteAnimation();
|
gridGhostNote.playNoteAnimation();
|
||||||
}
|
}
|
||||||
noteData.time = cursorMs;
|
noteData.time = cursorSnappedMs;
|
||||||
|
|
||||||
gridGhostNote.visible = true;
|
gridGhostNote.visible = true;
|
||||||
gridGhostNote.noteData = noteData;
|
gridGhostNote.noteData = noteData;
|
||||||
gridGhostNote.updateNotePosition(renderedNotes);
|
gridGhostNote.updateNotePosition(renderedNotes);
|
||||||
}
|
|
||||||
|
|
||||||
// gridCursor.visible = true;
|
targetCursorMode = Cell;
|
||||||
// // X and Y are the cursor position relative to the grid, snapped to the top left of the grid square.
|
}
|
||||||
// gridCursor.x = Math.floor(cursorX / GRID_SIZE) * GRID_SIZE + gridTiledSprite.x + (GRID_SELECTION_BORDER_WIDTH / 2);
|
|
||||||
// gridCursor.y = cursorStep * GRID_SIZE + gridTiledSprite.y + (GRID_SELECTION_BORDER_WIDTH / 2);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (gridGhostNote != null) gridGhostNote.visible = false;
|
if (gridGhostNote != null) gridGhostNote.visible = false;
|
||||||
if (gridGhostEvent != null) gridGhostEvent.visible = false;
|
if (gridGhostEvent != null) gridGhostEvent.visible = false;
|
||||||
Cursor.cursorMode = Default;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (targetCursorMode == null)
|
||||||
|
{
|
||||||
|
if (FlxG.mouse.pressed)
|
||||||
|
{
|
||||||
|
if (overlapsSelectionBorder)
|
||||||
|
{
|
||||||
|
targetCursorMode = Crosshair;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (FlxG.mouse.overlaps(notePreview))
|
||||||
|
{
|
||||||
|
targetCursorMode = Pointer;
|
||||||
|
}
|
||||||
|
else if (FlxG.mouse.overlaps(gridPlayheadScrollArea))
|
||||||
|
{
|
||||||
|
targetCursorMode = Pointer;
|
||||||
|
}
|
||||||
|
else if (overlapsSelectionBorder)
|
||||||
|
{
|
||||||
|
targetCursorMode = Crosshair;
|
||||||
|
}
|
||||||
|
else if (overlapsGrid)
|
||||||
|
{
|
||||||
|
targetCursorMode = Cell;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actually set the cursor mode to the one we specified earlier.
|
||||||
|
Cursor.cursorMode = targetCursorMode ?? Default;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (gridGhostNote != null) gridGhostNote.visible = false;
|
if (gridGhostNote != null) gridGhostNote.visible = false;
|
||||||
if (gridGhostEvent != null) gridGhostEvent.visible = false;
|
if (gridGhostEvent != null) gridGhostEvent.visible = false;
|
||||||
}
|
|
||||||
|
|
||||||
if (isCursorOverHaxeUIButton && Cursor.cursorMode == Default)
|
// Do not set Cursor.cursorMode here, because it will be set by the HaxeUI.
|
||||||
{
|
|
||||||
Cursor.cursorMode = Pointer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2838,10 +2897,10 @@ class ChartEditorState extends HaxeUIState
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort the notes DESCENDING. This keeps the sustain behind the associated note.
|
// Sort the notes DESCENDING. This keeps the sustain behind the associated note.
|
||||||
renderedNotes.sort(FlxSort.byY, FlxSort.DESCENDING);
|
renderedNotes.sort(FlxSort.byY, FlxSort.DESCENDING); // TODO: .group.insertionSort()
|
||||||
|
|
||||||
// Sort the events DESCENDING. This keeps the sustain behind the associated note.
|
// Sort the events DESCENDING. This keeps the sustain behind the associated note.
|
||||||
renderedEvents.sort(FlxSort.byY, FlxSort.DESCENDING);
|
renderedEvents.sort(FlxSort.byY, FlxSort.DESCENDING); // TODO: .group.insertionSort()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a debug value which displays the current size of the note pool.
|
// Add a debug value which displays the current size of the note pool.
|
||||||
|
@ -2899,6 +2958,18 @@ class ChartEditorState extends HaxeUIState
|
||||||
*/
|
*/
|
||||||
function handleFileKeybinds():Void
|
function handleFileKeybinds():Void
|
||||||
{
|
{
|
||||||
|
// CTRL + N = New Chart
|
||||||
|
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.N)
|
||||||
|
{
|
||||||
|
ChartEditorDialogHandler.openWelcomeDialog(this, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CTRL + O = Open Chart
|
||||||
|
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.O)
|
||||||
|
{
|
||||||
|
ChartEditorDialogHandler.openBrowseWizard(this, true);
|
||||||
|
}
|
||||||
|
|
||||||
// CTRL + Q = Quit to Menu
|
// CTRL + Q = Quit to Menu
|
||||||
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.Q)
|
if (FlxG.keys.pressed.CONTROL && FlxG.keys.justPressed.Q)
|
||||||
{
|
{
|
||||||
|
@ -3685,25 +3756,29 @@ class ChartEditorState extends HaxeUIState
|
||||||
this.scrollPositionInPixels = value;
|
this.scrollPositionInPixels = value;
|
||||||
|
|
||||||
// Move the grid sprite to the correct position.
|
// Move the grid sprite to the correct position.
|
||||||
if (isViewDownscroll)
|
if (gridTiledSprite != null)
|
||||||
{
|
{
|
||||||
if (gridTiledSprite != null) gridTiledSprite.y = -scrollPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
if (isViewDownscroll)
|
||||||
}
|
{
|
||||||
else
|
gridTiledSprite.y = -scrollPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||||
{
|
gridPlayheadScrollArea.y = gridTiledSprite.y;
|
||||||
if (gridTiledSprite != null) gridTiledSprite.y = -scrollPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gridTiledSprite.y = -scrollPositionInPixels + (MENU_BAR_HEIGHT + GRID_TOP_PAD);
|
||||||
|
gridPlayheadScrollArea.y = gridTiledSprite.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move the rendered notes to the correct position.
|
// Move the rendered notes to the correct position.
|
||||||
renderedNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
renderedNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
||||||
renderedHoldNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
renderedHoldNotes.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
||||||
renderedEvents.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
renderedEvents.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
||||||
renderedSelectionSquares.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
renderedSelectionSquares.setPosition(gridTiledSprite?.x ?? 0.0, gridTiledSprite?.y ?? 0.0);
|
||||||
|
|
||||||
// Offset the selection box start position, if we are dragging.
|
// Offset the selection box start position, if we are dragging.
|
||||||
if (selectionBoxStartPos != null) selectionBoxStartPos.y -= diff;
|
if (selectionBoxStartPos != null) selectionBoxStartPos.y -= diff;
|
||||||
// Update the note preview viewport box.
|
// Update the note preview viewport box.
|
||||||
setNotePreviewViewportBounds(calculateNotePreviewViewportBounds());
|
setNotePreviewViewportBounds(calculateNotePreviewViewportBounds());
|
||||||
|
|
||||||
return this.scrollPositionInPixels;
|
return this.scrollPositionInPixels;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3862,6 +3937,11 @@ class ChartEditorState extends HaxeUIState
|
||||||
songLengthInMs = audioInstTrack.length;
|
songLengthInMs = audioInstTrack.length;
|
||||||
|
|
||||||
if (gridTiledSprite != null) gridTiledSprite.height = songLengthInPixels;
|
if (gridTiledSprite != null) gridTiledSprite.height = songLengthInPixels;
|
||||||
|
if (gridPlayheadScrollArea != null)
|
||||||
|
{
|
||||||
|
gridPlayheadScrollArea.setGraphicSize(Std.int(gridPlayheadScrollArea.width), songLengthInPixels);
|
||||||
|
gridPlayheadScrollArea.updateHitbox();
|
||||||
|
}
|
||||||
|
|
||||||
buildSpectrogram(audioInstTrack);
|
buildSpectrogram(audioInstTrack);
|
||||||
}
|
}
|
||||||
|
@ -4003,6 +4083,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if !mac
|
||||||
NotificationManager.instance.addNotification(
|
NotificationManager.instance.addNotification(
|
||||||
{
|
{
|
||||||
title: 'Success',
|
title: 'Success',
|
||||||
|
@ -4010,6 +4091,7 @@ class ChartEditorState extends HaxeUIState
|
||||||
type: NotificationType.Success,
|
type: NotificationType.Success,
|
||||||
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
expiryMs: ChartEditorState.NOTIFICATION_DISMISS_TIME
|
||||||
});
|
});
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4146,10 +4228,12 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
function sortChartData():Void
|
function sortChartData():Void
|
||||||
{
|
{
|
||||||
|
// TODO: .insertionSort()
|
||||||
currentSongChartNoteData.sort(function(a:SongNoteData, b:SongNoteData):Int {
|
currentSongChartNoteData.sort(function(a:SongNoteData, b:SongNoteData):Int {
|
||||||
return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time);
|
return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// TODO: .insertionSort()
|
||||||
currentSongChartEventData.sort(function(a:SongEventData, b:SongEventData):Int {
|
currentSongChartEventData.sort(function(a:SongEventData, b:SongEventData):Int {
|
||||||
return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time);
|
return FlxSort.byValues(FlxSort.ASCENDING, a.time, b.time);
|
||||||
});
|
});
|
||||||
|
@ -4197,6 +4281,9 @@ class ChartEditorState extends HaxeUIState
|
||||||
|
|
||||||
cleanupAutoSave();
|
cleanupAutoSave();
|
||||||
|
|
||||||
|
// Hide the mouse cursor on other states.
|
||||||
|
Cursor.hide();
|
||||||
|
|
||||||
@:privateAccess
|
@:privateAccess
|
||||||
ChartEditorNoteSprite.noteFrameCollection = null;
|
ChartEditorNoteSprite.noteFrameCollection = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,11 @@ class ChartEditorThemeHandler
|
||||||
static final GRID_MEASURE_DIVIDER_COLOR_DARK:FlxColor = 0xFFC4C4C4;
|
static final GRID_MEASURE_DIVIDER_COLOR_DARK:FlxColor = 0xFFC4C4C4;
|
||||||
static final GRID_MEASURE_DIVIDER_WIDTH:Float = ChartEditorState.GRID_SELECTION_BORDER_WIDTH;
|
static final GRID_MEASURE_DIVIDER_WIDTH:Float = ChartEditorState.GRID_SELECTION_BORDER_WIDTH;
|
||||||
|
|
||||||
|
// Horizontal divider between beats.
|
||||||
|
static final GRID_BEAT_DIVIDER_COLOR_LIGHT:FlxColor = 0xFFC1C1C1;
|
||||||
|
static final GRID_BEAT_DIVIDER_COLOR_DARK:FlxColor = 0xFF848484;
|
||||||
|
static final GRID_BEAT_DIVIDER_WIDTH:Float = ChartEditorState.GRID_SELECTION_BORDER_WIDTH;
|
||||||
|
|
||||||
// Border on the square highlighting selected notes.
|
// Border on the square highlighting selected notes.
|
||||||
static final SELECTION_SQUARE_BORDER_COLOR_LIGHT:FlxColor = 0xFF339933;
|
static final SELECTION_SQUARE_BORDER_COLOR_LIGHT:FlxColor = 0xFF339933;
|
||||||
static final SELECTION_SQUARE_BORDER_COLOR_DARK:FlxColor = 0xFF339933;
|
static final SELECTION_SQUARE_BORDER_COLOR_DARK:FlxColor = 0xFF339933;
|
||||||
|
@ -141,7 +146,7 @@ class ChartEditorThemeHandler
|
||||||
ChartEditorState.GRID_SELECTION_BORDER_WIDTH),
|
ChartEditorState.GRID_SELECTION_BORDER_WIDTH),
|
||||||
selectionBorderColor);
|
selectionBorderColor);
|
||||||
|
|
||||||
// Selection borders in the middle.
|
// Selection borders horizontally along the middle.
|
||||||
for (i in 1...(Conductor.stepsPerMeasure))
|
for (i in 1...(Conductor.stepsPerMeasure))
|
||||||
{
|
{
|
||||||
state.gridBitmap.fillRect(new Rectangle(0, (ChartEditorState.GRID_SIZE * i) - (ChartEditorState.GRID_SELECTION_BORDER_WIDTH / 2),
|
state.gridBitmap.fillRect(new Rectangle(0, (ChartEditorState.GRID_SIZE * i) - (ChartEditorState.GRID_SELECTION_BORDER_WIDTH / 2),
|
||||||
|
@ -159,7 +164,7 @@ class ChartEditorThemeHandler
|
||||||
state.gridBitmap.height),
|
state.gridBitmap.height),
|
||||||
selectionBorderColor);
|
selectionBorderColor);
|
||||||
|
|
||||||
// Selection borders across the middle.
|
// Selection borders vertically along the middle.
|
||||||
for (i in 1...TOTAL_COLUMN_COUNT)
|
for (i in 1...TOTAL_COLUMN_COUNT)
|
||||||
{
|
{
|
||||||
state.gridBitmap.fillRect(new Rectangle((ChartEditorState.GRID_SIZE * i) - (ChartEditorState.GRID_SELECTION_BORDER_WIDTH / 2), 0,
|
state.gridBitmap.fillRect(new Rectangle((ChartEditorState.GRID_SIZE * i) - (ChartEditorState.GRID_SELECTION_BORDER_WIDTH / 2), 0,
|
||||||
|
@ -172,7 +177,7 @@ class ChartEditorThemeHandler
|
||||||
ChartEditorState.GRID_SELECTION_BORDER_WIDTH, state.gridBitmap.height),
|
ChartEditorState.GRID_SELECTION_BORDER_WIDTH, state.gridBitmap.height),
|
||||||
selectionBorderColor);
|
selectionBorderColor);
|
||||||
|
|
||||||
// Draw dividers between the measures.
|
// Draw horizontal dividers between the measures.
|
||||||
|
|
||||||
var gridMeasureDividerColor:FlxColor = switch (state.currentTheme)
|
var gridMeasureDividerColor:FlxColor = switch (state.currentTheme)
|
||||||
{
|
{
|
||||||
|
@ -187,7 +192,30 @@ class ChartEditorThemeHandler
|
||||||
var dividerLineBY:Float = state.gridBitmap.height - (GRID_MEASURE_DIVIDER_WIDTH / 2);
|
var dividerLineBY:Float = state.gridBitmap.height - (GRID_MEASURE_DIVIDER_WIDTH / 2);
|
||||||
state.gridBitmap.fillRect(new Rectangle(0, dividerLineBY, state.gridBitmap.width, GRID_MEASURE_DIVIDER_WIDTH / 2), gridMeasureDividerColor);
|
state.gridBitmap.fillRect(new Rectangle(0, dividerLineBY, state.gridBitmap.width, GRID_MEASURE_DIVIDER_WIDTH / 2), gridMeasureDividerColor);
|
||||||
|
|
||||||
// Draw dividers between the strumlines.
|
// Draw horizontal dividers between the beats.
|
||||||
|
|
||||||
|
var gridBeatDividerColor:FlxColor = switch (state.currentTheme)
|
||||||
|
{
|
||||||
|
case Light: GRID_BEAT_DIVIDER_COLOR_LIGHT;
|
||||||
|
case Dark: GRID_BEAT_DIVIDER_COLOR_DARK;
|
||||||
|
default: GRID_BEAT_DIVIDER_COLOR_LIGHT;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Selection borders horizontally in the middle.
|
||||||
|
for (i in 1...(Conductor.stepsPerMeasure))
|
||||||
|
{
|
||||||
|
if ((i % Conductor.beatsPerMeasure) == 0)
|
||||||
|
{
|
||||||
|
state.gridBitmap.fillRect(new Rectangle(0, (ChartEditorState.GRID_SIZE * i) - (GRID_BEAT_DIVIDER_WIDTH / 2), state.gridBitmap.width,
|
||||||
|
GRID_BEAT_DIVIDER_WIDTH),
|
||||||
|
gridBeatDividerColor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Divider at top
|
||||||
|
state.gridBitmap.fillRect(new Rectangle(0, 0, state.gridBitmap.width, GRID_MEASURE_DIVIDER_WIDTH / 2), gridMeasureDividerColor);
|
||||||
|
|
||||||
|
// Draw vertical dividers between the strumlines.
|
||||||
|
|
||||||
var gridStrumlineDividerColor:FlxColor = switch (state.currentTheme)
|
var gridStrumlineDividerColor:FlxColor = switch (state.currentTheme)
|
||||||
{
|
{
|
||||||
|
|
|
@ -30,7 +30,7 @@ typedef AnimationInfo =
|
||||||
@:composite(Layout)
|
@:composite(Layout)
|
||||||
class CharacterPlayer extends Box
|
class CharacterPlayer extends Box
|
||||||
{
|
{
|
||||||
var character:BaseCharacter;
|
var character:Null<BaseCharacter>;
|
||||||
|
|
||||||
public function new(defaultToBf:Bool = true)
|
public function new(defaultToBf:Bool = true)
|
||||||
{
|
{
|
||||||
|
@ -47,7 +47,7 @@ class CharacterPlayer extends Box
|
||||||
|
|
||||||
function get_charId():String
|
function get_charId():String
|
||||||
{
|
{
|
||||||
return character.characterId;
|
return character?.characterId ?? '';
|
||||||
}
|
}
|
||||||
|
|
||||||
function set_charId(value:String):String
|
function set_charId(value:String):String
|
||||||
|
@ -60,7 +60,7 @@ class CharacterPlayer extends Box
|
||||||
|
|
||||||
function get_charName():String
|
function get_charName():String
|
||||||
{
|
{
|
||||||
return character.characterName;
|
return character?.characterName ?? "Unknown";
|
||||||
}
|
}
|
||||||
|
|
||||||
// possible haxeui bug: if listener is added after event is dispatched, event is "lost"... is it smart to "collect and redispatch"? Not sure
|
// possible haxeui bug: if listener is added after event is dispatched, event is "lost"... is it smart to "collect and redispatch"? Not sure
|
||||||
|
@ -86,7 +86,11 @@ class CharacterPlayer extends Box
|
||||||
|
|
||||||
// Prevent script issues by fetching with debug=true.
|
// Prevent script issues by fetching with debug=true.
|
||||||
var newCharacter:BaseCharacter = CharacterDataParser.fetchCharacter(id, true);
|
var newCharacter:BaseCharacter = CharacterDataParser.fetchCharacter(id, true);
|
||||||
if (newCharacter == null) return; // Fail if character doesn't exist.
|
if (newCharacter == null)
|
||||||
|
{
|
||||||
|
character = null;
|
||||||
|
return; // Fail if character doesn't exist.
|
||||||
|
}
|
||||||
|
|
||||||
// Assign character.
|
// Assign character.
|
||||||
character = newCharacter;
|
character = newCharacter;
|
||||||
|
|
30
source/funkin/ui/haxeui/components/FunkinButton.hx
Normal file
30
source/funkin/ui/haxeui/components/FunkinButton.hx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package funkin.ui.haxeui.components;
|
||||||
|
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.events.MouseEvent;
|
||||||
|
import haxe.ui.components.Button;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HaxeUI button which:
|
||||||
|
* - Changes the current cursor when hovered over.
|
||||||
|
*/
|
||||||
|
class FunkinButton extends Button
|
||||||
|
{
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.onMouseOver = handleMouseOver;
|
||||||
|
this.onMouseOut = handleMouseOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOver(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOut(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
}
|
30
source/funkin/ui/haxeui/components/FunkinHorizontalSlider.hx
Normal file
30
source/funkin/ui/haxeui/components/FunkinHorizontalSlider.hx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package funkin.ui.haxeui.components;
|
||||||
|
|
||||||
|
import haxe.ui.components.HorizontalSlider;
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.events.MouseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HaxeUI horizontal slider which:
|
||||||
|
* - Changes the current cursor when hovered over.
|
||||||
|
*/
|
||||||
|
class FunkinHorizontalSlider extends HorizontalSlider
|
||||||
|
{
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.onMouseOver = handleMouseOver;
|
||||||
|
this.onMouseOut = handleMouseOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOver(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOut(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
}
|
30
source/funkin/ui/haxeui/components/FunkinLink.hx
Normal file
30
source/funkin/ui/haxeui/components/FunkinLink.hx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package funkin.ui.haxeui.components;
|
||||||
|
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.events.MouseEvent;
|
||||||
|
import haxe.ui.components.Link;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HaxeUI link which:
|
||||||
|
* - Changes the current cursor when hovered over.
|
||||||
|
*/
|
||||||
|
class FunkinLink extends Link
|
||||||
|
{
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.onMouseOver = handleMouseOver;
|
||||||
|
this.onMouseOut = handleMouseOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOver(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOut(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
}
|
32
source/funkin/ui/haxeui/components/FunkinMenuBar.hx
Normal file
32
source/funkin/ui/haxeui/components/FunkinMenuBar.hx
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package funkin.ui.haxeui.components;
|
||||||
|
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.events.MouseEvent;
|
||||||
|
import haxe.ui.containers.menus.MenuBar;
|
||||||
|
import haxe.ui.core.CompositeBuilder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HaxeUI menu bar which:
|
||||||
|
* - Changes the current cursor when each button is hovered over.
|
||||||
|
*/
|
||||||
|
class FunkinMenuBar extends MenuBar
|
||||||
|
{
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
registerListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function registerListeners():Void {}
|
||||||
|
|
||||||
|
private function handleMouseOver(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOut(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
}
|
30
source/funkin/ui/haxeui/components/FunkinMenuCheckBox.hx
Normal file
30
source/funkin/ui/haxeui/components/FunkinMenuCheckBox.hx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package funkin.ui.haxeui.components;
|
||||||
|
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.events.MouseEvent;
|
||||||
|
import haxe.ui.containers.menus.MenuCheckBox;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HaxeUI menu checkbox which:
|
||||||
|
* - Changes the current cursor when hovered over.
|
||||||
|
*/
|
||||||
|
class FunkinMenuCheckBox extends MenuCheckBox
|
||||||
|
{
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.onMouseOver = handleMouseOver;
|
||||||
|
this.onMouseOut = handleMouseOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOver(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOut(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
}
|
30
source/funkin/ui/haxeui/components/FunkinMenuItem.hx
Normal file
30
source/funkin/ui/haxeui/components/FunkinMenuItem.hx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package funkin.ui.haxeui.components;
|
||||||
|
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.events.MouseEvent;
|
||||||
|
import haxe.ui.containers.menus.MenuItem;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HaxeUI menu item which:
|
||||||
|
* - Changes the current cursor when hovered over.
|
||||||
|
*/
|
||||||
|
class FunkinMenuItem extends MenuItem
|
||||||
|
{
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.onMouseOver = handleMouseOver;
|
||||||
|
this.onMouseOut = handleMouseOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOver(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOut(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
}
|
30
source/funkin/ui/haxeui/components/FunkinMenuOptionBox.hx
Normal file
30
source/funkin/ui/haxeui/components/FunkinMenuOptionBox.hx
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
package funkin.ui.haxeui.components;
|
||||||
|
|
||||||
|
import haxe.ui.containers.menus.MenuOptionBox;
|
||||||
|
import funkin.input.Cursor;
|
||||||
|
import haxe.ui.events.MouseEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A HaxeUI menu option box which:
|
||||||
|
* - Changes the current cursor when hovered over.
|
||||||
|
*/
|
||||||
|
class FunkinMenuOptionBox extends MenuOptionBox
|
||||||
|
{
|
||||||
|
public function new()
|
||||||
|
{
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.onMouseOver = handleMouseOver;
|
||||||
|
this.onMouseOut = handleMouseOut;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOver(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function handleMouseOut(event:MouseEvent)
|
||||||
|
{
|
||||||
|
Cursor.cursorMode = Default;
|
||||||
|
}
|
||||||
|
}
|
|
@ -98,19 +98,40 @@ class Level implements IRegistryEntry<LevelData>
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Build a sprite for the background of the level.
|
||||||
|
* Can be overriden by ScriptedLevel. Not used if `isBackgroundSimple` returns true.
|
||||||
|
*/
|
||||||
public function buildBackground():FlxSprite
|
public function buildBackground():FlxSprite
|
||||||
{
|
{
|
||||||
if (_data.background.startsWith('#'))
|
if (!_data.background.startsWith('#'))
|
||||||
{
|
|
||||||
// Color specified
|
|
||||||
var color:FlxColor = FlxColor.fromString(_data.background);
|
|
||||||
return new FlxSprite().makeGraphic(FlxG.width, 400, color);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// Image specified
|
// Image specified
|
||||||
return new FlxSprite().loadGraphic(Paths.image(_data.background));
|
return new FlxSprite().loadGraphic(Paths.image(_data.background));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Color specified
|
||||||
|
var result:FlxSprite = new FlxSprite().makeGraphic(FlxG.width, 400, FlxColor.WHITE);
|
||||||
|
result.color = getBackgroundColor();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the background is a solid color.
|
||||||
|
* If you have a ScriptedLevel with a fancy background, you may want to override this to false.
|
||||||
|
*/
|
||||||
|
public function isBackgroundSimple():Bool
|
||||||
|
{
|
||||||
|
return _data.background.startsWith('#');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if the background is a solid color.
|
||||||
|
* If you have a ScriptedLevel with a fancy background, you may want to override this to false.
|
||||||
|
*/
|
||||||
|
public function getBackgroundColor():FlxColor
|
||||||
|
{
|
||||||
|
return FlxColor.fromString(_data.background);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDifficulties():Array<String>
|
public function getDifficulties():Array<String>
|
||||||
|
|
|
@ -135,10 +135,15 @@ class StoryMenuState extends MusicBeatState
|
||||||
this.bgColor = FlxColor.BLACK;
|
this.bgColor = FlxColor.BLACK;
|
||||||
|
|
||||||
levelTitles = new FlxTypedGroup<LevelTitle>();
|
levelTitles = new FlxTypedGroup<LevelTitle>();
|
||||||
|
levelTitles.zIndex = 15;
|
||||||
add(levelTitles);
|
add(levelTitles);
|
||||||
|
|
||||||
updateBackground();
|
updateBackground();
|
||||||
|
|
||||||
|
var black:FlxSprite = new FlxSprite(levelBackground.x, 0).makeGraphic(FlxG.width, Std.int(400 + levelBackground.y), FlxColor.BLACK);
|
||||||
|
black.zIndex = levelBackground.zIndex - 1;
|
||||||
|
add(black);
|
||||||
|
|
||||||
levelProps = new FlxTypedGroup<LevelProp>();
|
levelProps = new FlxTypedGroup<LevelProp>();
|
||||||
levelProps.zIndex = 1000;
|
levelProps.zIndex = 1000;
|
||||||
add(levelProps);
|
add(levelProps);
|
||||||
|
@ -153,17 +158,20 @@ class StoryMenuState extends MusicBeatState
|
||||||
|
|
||||||
scoreText = new FlxText(10, 10, 0, 'HIGH SCORE: 42069420');
|
scoreText = new FlxText(10, 10, 0, 'HIGH SCORE: 42069420');
|
||||||
scoreText.setFormat("VCR OSD Mono", 32);
|
scoreText.setFormat("VCR OSD Mono", 32);
|
||||||
|
scoreText.zIndex = 1000;
|
||||||
add(scoreText);
|
add(scoreText);
|
||||||
|
|
||||||
modeText = new FlxText(10, 10, 0, 'Base Game Levels [TAB to switch]');
|
modeText = new FlxText(10, 10, 0, 'Base Game Levels [TAB to switch]');
|
||||||
modeText.setFormat("VCR OSD Mono", 32);
|
modeText.setFormat("VCR OSD Mono", 32);
|
||||||
modeText.screenCenter(X);
|
modeText.screenCenter(X);
|
||||||
modeText.visible = hasModdedLevels();
|
modeText.visible = hasModdedLevels();
|
||||||
|
modeText.zIndex = 1000;
|
||||||
add(modeText);
|
add(modeText);
|
||||||
|
|
||||||
levelTitleText = new FlxText(FlxG.width * 0.7, 10, 0, 'LEVEL 1');
|
levelTitleText = new FlxText(FlxG.width * 0.7, 10, 0, 'LEVEL 1');
|
||||||
levelTitleText.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT);
|
levelTitleText.setFormat("VCR OSD Mono", 32, FlxColor.WHITE, RIGHT);
|
||||||
levelTitleText.alpha = 0.7;
|
levelTitleText.alpha = 0.7;
|
||||||
|
levelTitleText.zIndex = 1000;
|
||||||
add(levelTitleText);
|
add(levelTitleText);
|
||||||
|
|
||||||
buildLevelTitles();
|
buildLevelTitles();
|
||||||
|
@ -384,6 +392,7 @@ class StoryMenuState extends MusicBeatState
|
||||||
if (currentIndex < 0) currentIndex = levelList.length - 1;
|
if (currentIndex < 0) currentIndex = levelList.length - 1;
|
||||||
if (currentIndex >= levelList.length) currentIndex = 0;
|
if (currentIndex >= levelList.length) currentIndex = 0;
|
||||||
|
|
||||||
|
var previousLevelId:String = currentLevelId;
|
||||||
currentLevelId = levelList[currentIndex];
|
currentLevelId = levelList[currentIndex];
|
||||||
|
|
||||||
updateData();
|
updateData();
|
||||||
|
@ -399,18 +408,14 @@ class StoryMenuState extends MusicBeatState
|
||||||
currentLevelTitle = item;
|
currentLevelTitle = item;
|
||||||
item.alpha = 1.0;
|
item.alpha = 1.0;
|
||||||
}
|
}
|
||||||
else if (index > currentIndex)
|
|
||||||
{
|
|
||||||
item.alpha = 0.6;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
item.alpha = 0.0;
|
item.alpha = 0.6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
updateText();
|
updateText();
|
||||||
updateBackground();
|
updateBackground(previousLevelId);
|
||||||
updateProps();
|
updateProps();
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
@ -533,32 +538,66 @@ class StoryMenuState extends MusicBeatState
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateBackground():Void
|
function updateBackground(?previousLevelId:String = ''):Void
|
||||||
{
|
{
|
||||||
if (levelBackground != null)
|
if (levelBackground == null || previousLevelId == '')
|
||||||
{
|
{
|
||||||
var oldBackground:FlxSprite = levelBackground;
|
// Build a new background and display it immediately.
|
||||||
|
levelBackground = currentLevel.buildBackground();
|
||||||
FlxTween.tween(oldBackground, {alpha: 0.0}, 0.6,
|
levelBackground.x = 0;
|
||||||
{
|
levelBackground.y = 56;
|
||||||
ease: FlxEase.linear,
|
levelBackground.zIndex = 100;
|
||||||
onComplete: function(_) {
|
levelBackground.alpha = 1.0; // Not hidden.
|
||||||
remove(oldBackground);
|
add(levelBackground);
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var previousLevel = LevelRegistry.instance.fetchEntry(previousLevelId);
|
||||||
|
|
||||||
levelBackground = currentLevel.buildBackground();
|
if (currentLevel.isBackgroundSimple() && previousLevel.isBackgroundSimple())
|
||||||
levelBackground.x = 0;
|
|
||||||
levelBackground.y = 56;
|
|
||||||
levelBackground.alpha = 0.0;
|
|
||||||
levelBackground.zIndex = 100;
|
|
||||||
add(levelBackground);
|
|
||||||
|
|
||||||
FlxTween.tween(levelBackground, {alpha: 1.0}, 0.6,
|
|
||||||
{
|
{
|
||||||
ease: FlxEase.linear
|
var previousColor:FlxColor = previousLevel.getBackgroundColor();
|
||||||
});
|
var currentColor:FlxColor = currentLevel.getBackgroundColor();
|
||||||
|
if (previousColor != currentColor)
|
||||||
|
{
|
||||||
|
// Both the previous and current level were simple backgrounds.
|
||||||
|
// Fade between colors directly, rather than fading one background out and another in.
|
||||||
|
FlxTween.color(levelBackground, 0.4, previousColor, currentColor);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Do no fade at all if the colors aren't different.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Either the previous or current level has a complex background.
|
||||||
|
// We need to fade the old background out and the new one in.
|
||||||
|
|
||||||
|
// Reference the old background and fade it out.
|
||||||
|
var oldBackground:FlxSprite = levelBackground;
|
||||||
|
FlxTween.tween(oldBackground, {alpha: 0.0}, 0.6,
|
||||||
|
{
|
||||||
|
ease: FlxEase.linear,
|
||||||
|
onComplete: function(_) {
|
||||||
|
remove(oldBackground);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Build a new background and fade it in.
|
||||||
|
levelBackground = currentLevel.buildBackground();
|
||||||
|
levelBackground.x = 0;
|
||||||
|
levelBackground.y = 56;
|
||||||
|
levelBackground.alpha = 0.0; // Hidden to start.
|
||||||
|
levelBackground.zIndex = 100;
|
||||||
|
add(levelBackground);
|
||||||
|
|
||||||
|
FlxTween.tween(levelBackground, {alpha: 1.0}, 0.6,
|
||||||
|
{
|
||||||
|
ease: FlxEase.linear
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateProps():Void
|
function updateProps():Void
|
||||||
|
|
Loading…
Reference in a new issue