Continuous bpm change event, lots of other reworks and fixes

This commit is contained in:
TheZoroForce240
2025-02-01 21:13:46 +00:00
parent 2f6207b11b
commit 3e13bf50c6
10 changed files with 277 additions and 59 deletions
+26 -13
View File
@@ -843,6 +843,7 @@ class Charter extends UIState {
if (s is CharterNote) cast(s, CharterNote).snappedToStrumline = true;
if (s is UISprite) cast(s, UISprite).cursor = BUTTON;
}
checkSelectionForBPMUpdates();
if (!(verticalChange == 0 && horizontalChange == 0)) {
notesGroup.sortNotes(); eventsGroup.sortEvents();
undos.addToUndo(CSelectionDrag(undoDrags));
@@ -1031,11 +1032,7 @@ class Charter extends UIState {
notesGroup.sortNotes();
notesGroup.autoSort = true;
for (s in selection)
if (s is CharterEvent) {
Charter.instance.updateBPMEvents();
break;
}
checkSelectionForBPMUpdates();
if (addToUndo)
undos.addToUndo(CCreateSelection(selection));
@@ -1059,11 +1056,7 @@ class Charter extends UIState {
notesGroup.sortNotes();
notesGroup.autoSort = true;
for (s in selection)
if (s is CharterEvent) {
Charter.instance.updateBPMEvents();
break;
}
checkSelectionForBPMUpdates();
if (addToUndo)
undos.addToUndo(CDeleteSelection(selection));
@@ -1432,6 +1425,8 @@ class Charter extends UIState {
selection = sObjects;
_edit_copy(_); // to fix stupid bugs
checkSelectionForBPMUpdates();
undos.addToUndo(CCreateSelection(sObjects.copy()));
}
@@ -1477,6 +1472,7 @@ class Charter extends UIState {
if (s.selectable.draggable) s.selectable.handleDrag(s.change * -1);
selection = [for (s in selectionDrags) s.selectable];
Charter.instance.updateBPMEvents();
case CEditSustains(changes):
for(n in changes)
n.note.updatePos(n.note.step, n.note.id, n.before, n.note.type);
@@ -1522,6 +1518,7 @@ class Charter extends UIState {
for (s in selectionDrags)
if (s.selectable.draggable) s.selectable.handleDrag(s.change);
//this.selection = selection;
Charter.instance.updateBPMEvents();
case CEditSustains(changes):
for(n in changes)
n.note.updatePos(n.note.step, n.note.id, n.after, n.note.type);
@@ -1836,14 +1833,30 @@ class Charter extends UIState {
}
public function updateBPMEvents() {
eventsGroup.sortEvents();
Conductor.mapCharterBPMChanges(PlayState.SONG);
buildEvents();
Conductor.changeBPM(PlayState.SONG.meta.bpm, cast PlayState.SONG.meta.beatsPerMeasure.getDefault(4), cast PlayState.SONG.meta.stepsPerBeat.getDefault(4));
Conductor.mapBPMChanges(PlayState.SONG);
for(e in eventsGroup.members) {
for(event in e.events) {
if (event.name == "BPM Change" || event.name == "Time Signature Change" || event.name == "Continuous BPM Change") {
e.refreshEventIcons();
break;
}
}
}
refreshBPMSensitive();
}
public inline function checkSelectionForBPMUpdates() {
for (s in selection)
if (s is CharterEvent) {
Charter.instance.updateBPMEvents();
break;
}
}
public inline function hitsoundsEnabled(id:Int)
return strumLines.members[id] != null && strumLines.members[id].hitsounds;
@@ -294,10 +294,10 @@ class CharterGridSeperatorBase extends FlxSprite {
for (i => change in Conductor.bpmChangeMap) {
if (change.stepTime >= minStep && change.stepTime <= maxStep) {
//get step while ignoring the current change
var index = CoolUtil.boundInt(i-1, 0, Conductor.bpmChangeMap.length - 1);
var step = Conductor.getTimeWithBPMInSteps(change.songTime, index, Conductor.getTimeWithIndexInBPM(change.songTime, index));
var index:Int = CoolUtil.boundInt(i-1, 0, Conductor.bpmChangeMap.length - 1);
var step:Float = Conductor.getTimeWithBPMInSteps(change.songTime, index, Conductor.getTimeWithIndexInBPM(change.songTime, index));
if (Math.ceil(step) - step > 0) { //mid step change
if (Math.ceil(step) - step > 0 && (step - Math.floor(step)) > FlxMath.EPSILON) { //mid step change
timeSignatureChangeGaps.push(step);
}
}
+126 -12
View File
@@ -1,5 +1,7 @@
package funkin.editors.charter;
import funkin.backend.shaders.CustomShader;
import funkin.backend.system.Conductor;
import flixel.group.FlxSpriteGroup;
import flixel.math.FlxPoint;
import flixel.system.FlxAssets.FlxGraphicAsset;
@@ -176,7 +178,7 @@ class CharterEvent extends UISliceSprite implements ICharterSelectable {
return healthIcon;
}
public static function generateEventIcon(event:ChartEvent):FlxSprite {
public static function generateEventIcon(event:ChartEvent, inMenu:Bool = true):FlxSprite {
var script = getUIScript(event, "event-icon");
if(script != null && !(script is DummyScript)) {
if(script.get("generateIcon") != null) {
@@ -201,8 +203,43 @@ class CharterEvent extends UISliceSprite implements ICharterSelectable {
num.active = false;
num;
});
if (Conductor.invalidEvents.contains(event)) generateEventIconWarning(group);
return group;
}
case "Continuous BPM Change":
if(event.params != null && event.params[1] != null) {
if (inMenu) {
var group = new EventIconGroup();
group.add(generateDefaultIcon("BPM Change Start"));
if (Conductor.invalidEvents.contains(event)) generateEventIconWarning(group);
return group;
}
var group = generateEventIconWithDuration(event.params[1], "BPM Change Start");
group.members[0].y -= 2;
generateEventIconNumbers(group, Std.int(event.params[0]), 15);
if (Conductor.invalidEvents.contains(event)) generateEventIconWarning(group);
return group;
} else {
return generateDefaultIcon("BPM Change Start");
}
case "BPM Change":
if(event.params != null && event.params[0] != null) {
if (inMenu) {
var group = new EventIconGroup();
group.add(generateDefaultIcon(event.name));
if (Conductor.invalidEvents.contains(event)) generateEventIconWarning(group);
return group;
}
var group = new EventIconGroup();
group.add(generateDefaultIcon(event.name));
group.members[0].y -= 2;
generateEventIconNumbers(group, Std.int(event.params[0]), 15);
if (Conductor.invalidEvents.contains(event)) generateEventIconWarning(group);
return group;
}
case "Camera Movement":
// camera movement, use health icon
if(event.params != null) {
@@ -213,6 +250,76 @@ class CharterEvent extends UISliceSprite implements ICharterSelectable {
return generateDefaultIcon(event.name);
}
private static function generateEventIconNumbers(group:EventIconGroup, number:Int, y:Float) {
var numString = Std.string(number);
var offset = (16 - (numString.length*5))/2;
for (num in 0...numString.length) {
group.add({
var num = new EventNumber(offset + num*5, y, Std.parseInt(numString.charAt(num)), EventNumber.ALIGN_CENTER);
num.active = false;
num;
});
}
}
private static function generateEventIconWithDuration(duration:Float, startIcon:String, endIcon:String = "") {
var group = new EventIconGroup();
group.add(generateDefaultIcon(startIcon));
var xOffset = 4;
var yGap = 24;
var endGap = 7;
if (endIcon == "") endGap = -2;
if (duration >= 0.65) { //min time for showing arrow
var tail = new FlxSprite(xOffset, yGap);
var arrow = new FlxSprite(xOffset, (duration * 40) + endGap);
var arrowSegment = new FlxSprite(xOffset, yGap);
tail.frames = arrow.frames = arrowSegment.frames = Paths.getSparrowAtlas("editors/charter/event-icons/components/arrow-down");
group.add({
tail.animation.addByPrefix("tail", "tail");
tail.animation.play("tail");
tail;
});
group.add({
arrowSegment.animation.addByPrefix("segment", "segment");
arrowSegment.animation.play("segment");
arrowSegment.scale.y = (duration * 40) - (tail.height + endGap + yGap);
arrowSegment.updateHitbox();
arrowSegment.y += tail.height;
arrowSegment;
});
group.add({
arrow.animation.addByPrefix("arrow", "arrow");
arrow.animation.play("arrow");
arrow;
});
}
if (endIcon != "") {
group.add({
var icon = generateDefaultIcon(endIcon);
icon.y = duration * 40;
icon;
});
}
return group;
}
private static function generateEventIconWarning(group:EventIconGroup) {
for (spr in group) {
spr.colorTransform.redMultiplier = spr.colorTransform.greenMultiplier = spr.colorTransform.blueMultiplier = 0.5;
spr.colorTransform.redOffset = 100;
}
group.add(getEventComponent("warning", 16, -8));
group.copyColorTransformToChildren = false;
}
public override function onHovered() {
super.onHovered();
/*
@@ -238,26 +345,22 @@ class CharterEvent extends UISliceSprite implements ICharterSelectable {
}
for(event in events) {
var spr = generateEventIcon(event);
var spr = generateEventIcon(event, false);
icons.push(spr);
members.push(spr);
}
draggable = true;
for (event in events)
if (event.name == "BPM Change" || event.name == "Time Signature Change") {
draggable = false;
break;
}
x = (snappedToGrid && eventsBackdrop != null ? eventsBackdrop.x : 0) - (bWidth = 37 + (icons.length * 22));
}
}
class EventIconGroup extends FlxSpriteGroup {
public var forceWidth:Float = 32;
public var forceHeight:Float = 32;
public var forceWidth:Float = 16;
public var forceHeight:Float = 16;
public var dontTransformChildren:Bool = true;
public var copyColorTransformToChildren:Bool = true;
public function new() {
super();
@@ -298,6 +401,12 @@ class EventIconGroup extends FlxSpriteGroup {
override function get_height() {
return forceHeight;
}
override public function draw() {
@:privateAccess
if (copyColorTransformToChildren && colorTransform != null) for (child in members) child.colorTransform.__copyFrom(colorTransform);
super.draw();
}
}
class EventNumber extends FlxSprite {
@@ -312,10 +421,15 @@ class EventNumber extends FlxSprite {
super(x, y);
this.digits = [];
this.align = align;
while (number > 0) {
this.digits.insert(0, number % 10);
number = Std.int(number / 10);
if (number == 0) {
this.digits.insert(0, 0);
} else {
while (number > 0) {
this.digits.insert(0, number % 10);
number = Std.int(number / 10);
}
}
loadGraphic(Paths.image('editors/charter/event-icons/components/eventNums'), true, 6, 7);
}
@@ -58,7 +58,7 @@ class CharterEventScreen extends UISubstateWindow {
});
eventsList.add(new EventButton(events[events.length-1], CharterEvent.generateEventIcon(events[events.length-1]), events.length-1, this, eventsList));
changeTab(events.length-1);
}));
}, chartEvent.step));
for (k=>i in events)
eventsList.add(new EventButton(i, CharterEvent.generateEventIcon(i), k, this, eventsList));
add(eventsList);
@@ -83,12 +83,12 @@ class CharterEventScreen extends UISubstateWindow {
else {
chartEvent.events = [for (i in eventsList.buttons.members) i.event];
chartEvent.refreshEventIcons();
Charter.instance.updateBPMEvents();
Charter.undos.addToUndo(CEditEvent(chartEvent, oldEvents, [for (event in events) Reflect.copy(event)]));
}
}
Charter.instance.updateBPMEvents();
close();
});
saveButton.x -= saveButton.bWidth;
@@ -1,9 +1,11 @@
package funkin.editors.charter;
import funkin.backend.system.Conductor;
import funkin.backend.chart.EventsData;
class CharterEventTypeSelection extends UISubstateWindow {
var callback:String->Void;
var eventStepTime:Float;
var buttons:Array<UIButton> = [];
@@ -13,9 +15,10 @@ class CharterEventTypeSelection extends UISubstateWindow {
var upIndicator:UIText;
var downIndicator:UIText;
public function new(callback:String->Void) {
public function new(callback:String->Void, eventStepTime:Float) {
super();
this.callback = callback;
this.eventStepTime = eventStepTime;
}
public override function create() {
@@ -32,6 +35,15 @@ class CharterEventTypeSelection extends UISubstateWindow {
buttonsBG.frames = Paths.getFrames('editors/ui/inputbox');
add(buttonsBG);
var disableConductorEvents:Bool = false;
var disableOnlyContinuousChanges:Bool = false;
for (change in Conductor.bpmChangeMap) {
if (change.continuous && eventStepTime >= change.stepTime && eventStepTime < change.endStepTime) {
disableOnlyContinuousChanges = eventStepTime == change.stepTime; //allow time sig and instant bpm changes on the same event
disableConductorEvents = !disableOnlyContinuousChanges;
}
}
for(k=>eventName in EventsData.eventsList) {
var button = new UIButton(0, (32 * k), eventName, function() {
close();
@@ -52,6 +64,11 @@ class CharterEventTypeSelection extends UISubstateWindow {
icon.x = button.x + 8;
icon.y = button.y + Math.abs(button.bHeight - icon.height) / 2;
add(icon);
if (disableConductorEvents && (eventName == "Time Signature Change" || eventName == "Continuous BPM Change" || eventName == "BPM Change") || (disableOnlyContinuousChanges && eventName == "Continuous BPM Change")) {
button.selectable = button.shouldPress = false;
button.autoAlpha = true;
}
}
windowSpr.bHeight = 61 + (32 * (17));
@@ -79,7 +96,7 @@ class CharterEventTypeSelection extends UISubstateWindow {
sinner += elapsed;
for (button in buttons)
button.selectable = buttonsBG.hovered;
if (button.shouldPress) button.selectable = buttonsBG.hovered;
buttonCameras.zoom = subCam.zoom;