Continuous bpm change event, lots of other reworks and fixes
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextureAtlas imagePath="arrow-down.png">
|
||||
<SubTexture name="tail" x="0" y="0" width="8" height="3"/>
|
||||
<SubTexture name="segment" x="0" y="3" width="8" height="1"/>
|
||||
<SubTexture name="arrow" x="0" y="6" width="8" height="6"/>
|
||||
</TextureAtlas>
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.8 KiB |
@@ -10,7 +10,7 @@ import funkin.backend.assets.Paths;
|
||||
using StringTools;
|
||||
|
||||
class EventsData {
|
||||
public static var defaultEventsList:Array<String> = ["HScript Call", "Camera Movement", "Add Camera Zoom", "Camera Modulo Change", "Camera Flash", "BPM Change", "Scroll Speed Change", "Alt Animation Toggle", "Play Animation", "Time Signature Change"];
|
||||
public static var defaultEventsList:Array<String> = ["HScript Call", "Camera Movement", "Add Camera Zoom", "Camera Modulo Change", "Camera Flash", "BPM Change", "Continuous BPM Change", "Time Signature Change", "Scroll Speed Change", "Alt Animation Toggle", "Play Animation"];
|
||||
public static var defaultEventsParams:Map<String, Array<EventParamInfo>> = [
|
||||
"HScript Call" => [
|
||||
{name: "Function Name", type: TString, defValue: "myFunc"},
|
||||
@@ -31,7 +31,9 @@ class EventsData {
|
||||
{name: "Time (Steps)", type: TFloat(0.25, 9999, 0.25, 2), defValue: 4},
|
||||
{name: "Camera", type: TDropDown(['camGame', 'camHUD']), defValue: "camHUD"}
|
||||
],
|
||||
"BPM Change" => [{name: "Target BPM", type: TFloat(1.00, null, 0.001, 3), defValue: 100}],
|
||||
"BPM Change" => [{name: "Target BPM", type: TFloat(1.00, 9999, 0.001, 3), defValue: 100}],
|
||||
"Continuous BPM Change" => [{name: "Target BPM", type: TFloat(1.00, 9999, 0.001, 3), defValue: 100}, {name: "Time (steps)", type: TFloat(0.25, 9999, 0.25, 2), defValue: 4}],
|
||||
"Time Signature Change" => [{name: "Target Beat Count", type: TFloat(1), defValue: 4}, {name: "Target Step Count", type: TFloat(1), defValue: 4}],
|
||||
"Scroll Speed Change" => [
|
||||
{name: "Tween Speed?", type: TBool, defValue: true},
|
||||
{name: "New Speed", type: TFloat(0.01, 99, 0.01, 2), defValue: 1.},
|
||||
@@ -48,8 +50,7 @@ class EventsData {
|
||||
}
|
||||
],
|
||||
"Alt Animation Toggle" => [{name: "Enable On Sing Poses", type: TBool, defValue: true}, {name: "Enable On Idle", type: TBool, defValue: true}, {name: "Strumline", type: TStrumLine, defValue: 0}],
|
||||
"Play Animation" => [{name: "Character", type: TStrumLine, defValue: 0}, {name: "Animation", type: TString, defValue: "animation"}, {name: "Is forced?", type: TBool, defValue: true}],
|
||||
"Time Signature Change" => [{name: "Target Beat Count", type: TFloat(1), defValue: 4}, {name: "Target Step Count", type: TFloat(1), defValue: 4}],
|
||||
"Play Animation" => [{name: "Character", type: TStrumLine, defValue: 0}, {name: "Animation", type: TString, defValue: "animation"}, {name: "Is forced?", type: TBool, defValue: true}]
|
||||
];
|
||||
|
||||
public static var eventsList:Array<String> = defaultEventsList.copy();
|
||||
|
||||
@@ -4,6 +4,7 @@ import flixel.FlxState;
|
||||
import flixel.util.FlxSignal.FlxTypedSignal;
|
||||
import funkin.backend.chart.ChartData;
|
||||
import funkin.backend.system.interfaces.IBeatReceiver;
|
||||
import funkin.editors.charter.Charter;
|
||||
|
||||
@:structInit
|
||||
class BPMChangeEvent
|
||||
@@ -14,6 +15,7 @@ class BPMChangeEvent
|
||||
public var stepsPerBeat:Int = 4;
|
||||
|
||||
public var endSongTime:Float = 0;
|
||||
public var endStepTime:Float = 0;
|
||||
public var continuous:Bool = false;
|
||||
|
||||
public var stepTime:Float;
|
||||
@@ -139,6 +141,11 @@ final class Conductor
|
||||
*/
|
||||
public static var bpmChangeMap:Array<BPMChangeEvent>;
|
||||
|
||||
/**
|
||||
* Array of all events that have been rejected by the Conductor.
|
||||
*/
|
||||
public static var invalidEvents:Array<ChartEvent> = [];
|
||||
|
||||
@:dox(hide) public function new() {}
|
||||
|
||||
public static function reset() {
|
||||
@@ -154,13 +161,9 @@ final class Conductor
|
||||
mapBPMChanges(SONG);
|
||||
}
|
||||
|
||||
private static function mapBPMChange(curChange:BPMChangeEvent, time:Float, bpm:Float, ?endTime:Float, ?prevChange:BPMChangeEvent):BPMChangeEvent {
|
||||
private static function mapBPMChange(curChange:BPMChangeEvent, time:Float, bpm:Float):BPMChangeEvent {
|
||||
var beatTime:Float, measureTime:Float, stepTime:Float;
|
||||
if (curChange.continuous)
|
||||
stepTime = curChange.stepTime + (((curChange.endSongTime - curChange.songTime) * (curChange.bpm - prevChange.bpm))
|
||||
/ Math.log(curChange.bpm / prevChange.bpm) + (time - curChange.endSongTime) * curChange.bpm) / 15000;
|
||||
else
|
||||
stepTime = curChange.stepTime + (time - curChange.songTime) / (15000 / curChange.bpm);
|
||||
stepTime = (curChange.continuous ? curChange.endStepTime : curChange.stepTime) + (time - (curChange.continuous ? curChange.endSongTime : curChange.songTime)) / (15000 / curChange.bpm);
|
||||
|
||||
beatTime = curChange.beatTime + (stepTime - curChange.stepTime) / curChange.stepsPerBeat;
|
||||
measureTime = curChange.measureTime + (beatTime - curChange.beatTime) / curChange.beatsPerMeasure;
|
||||
@@ -174,7 +177,6 @@ final class Conductor
|
||||
beatsPerMeasure: curChange.beatsPerMeasure,
|
||||
stepsPerBeat: curChange.stepsPerBeat
|
||||
});
|
||||
if (curChange.continuous = (endTime is Float && endTime != 0)) curChange.endSongTime = endTime;
|
||||
return curChange;
|
||||
}
|
||||
|
||||
@@ -194,32 +196,97 @@ final class Conductor
|
||||
};
|
||||
curChangeIndex = 0;
|
||||
bpmChangeMap = [curChange];
|
||||
invalidEvents = [];
|
||||
if (song.events == null) return;
|
||||
|
||||
// fix the sort first...
|
||||
var events:Array<ChartEvent> = [];
|
||||
for (e in song.events) if (e.params != null && (e.name == "BPM Change" || e.name == "Time Signature Change")) events.push(e);
|
||||
events.sort(function(a, b) return Std.int(a.time - b.time));
|
||||
for (e in song.events) if (e.params != null && (e.name == "BPM Change" || e.name == "Time Signature Change" || e.name == "Continuous BPM Change")) events.push(e);
|
||||
events.sort(function(a, b) {
|
||||
if (a.time == b.time) {
|
||||
if (a.name == "Continuous BPM Change") return 1;
|
||||
if (b.name == "Continuous BPM Change") return -1;
|
||||
}
|
||||
return Std.int(a.time - b.time);
|
||||
});
|
||||
|
||||
var prevChange:BPMChangeEvent = null;
|
||||
for (e in events) {
|
||||
if (bpmChangeMap.length > 3) prevChange = bpmChangeMap[bpmChangeMap.length - 2];
|
||||
var name = e.name, params = e.params, time = e.time;
|
||||
if (name == "BPM Change" && params[0] is Float && curChange.bpm != params[0])
|
||||
curChange = mapBPMChange(curChange, time, params[0], params[1], prevChange);
|
||||
else if (name == "Time Signature Change") {
|
||||
//if (beatsPerMeasure == curChange.beatsPerMeasure && stepsPerBeat == curChange.stepsPerBeat) continue;
|
||||
/* TODO: make so time sigs doesnt stop the bpm change if its in the duration of bpm change */
|
||||
curChange = mapEvent(e, curChange);
|
||||
}
|
||||
}
|
||||
|
||||
if (curChange.songTime != time) curChange = mapBPMChange(curChange, time, curChange.bpm, null, prevChange);
|
||||
curChange.beatsPerMeasure = params[0];
|
||||
curChange.stepsPerBeat = params[1];
|
||||
private static function mapEvent(e:ChartEvent, curChange:BPMChangeEvent) {
|
||||
var name = e.name, params = e.params, time = e.time;
|
||||
if (curChange.continuous && time < curChange.endSongTime) { //ensure that you cannot place any conductor events during a continuous change
|
||||
invalidEvents.push(e);
|
||||
Logs.trace('Invalid Conductor event "${e.name}" at ${e.time} (Intersecting continuous change!)', WARNING);
|
||||
return curChange;
|
||||
}
|
||||
|
||||
if (name == "BPM Change" && params[0] is Float && curChange.bpm != params[0])
|
||||
curChange = mapBPMChange(curChange, time, params[0]);
|
||||
else if (name == "Time Signature Change") {
|
||||
//if (beatsPerMeasure == curChange.beatsPerMeasure && stepsPerBeat == curChange.stepsPerBeat) continue;
|
||||
/* TODO: make so time sigs doesnt stop the bpm change if its in the duration of bpm change */
|
||||
|
||||
if (curChange.songTime != time) curChange = mapBPMChange(curChange, time, curChange.bpm);
|
||||
curChange.beatsPerMeasure = params[0];
|
||||
curChange.stepsPerBeat = params[1];
|
||||
|
||||
curChange.stepTime = CoolUtil.floorInt(curChange.stepTime + .99998);
|
||||
curChange.beatTime = CoolUtil.floorInt(curChange.beatTime + .99998);
|
||||
curChange.measureTime = CoolUtil.floorInt(curChange.measureTime + .99998);
|
||||
} else if (name == "Continuous BPM Change") {
|
||||
|
||||
var prevBPM = curChange.bpm;
|
||||
if (curChange.bpm == params[0]) {
|
||||
invalidEvents.push(e);
|
||||
return curChange; //DO NOT!!!!
|
||||
}
|
||||
curChange = mapBPMChange(curChange, time, params[0]);
|
||||
var endTime = time + (params[1]) / (curChange.bpm - prevBPM) * Math.log(curChange.bpm / prevBPM) * 15000;
|
||||
curChange.endStepTime = curChange.stepTime + params[1];
|
||||
curChange.continuous = true;
|
||||
curChange.endSongTime = endTime;
|
||||
}
|
||||
return curChange;
|
||||
}
|
||||
|
||||
public static function mapCharterBPMChanges(song:ChartData) {
|
||||
var curChange:BPMChangeEvent = {
|
||||
songTime: 0,
|
||||
stepTime: 0,
|
||||
beatTime: 0,
|
||||
measureTime: 0,
|
||||
bpm: song.meta.bpm,
|
||||
beatsPerMeasure: song.meta.beatsPerMeasure.getDefault(4),
|
||||
stepsPerBeat: CoolUtil.floorInt(song.meta.stepsPerBeat.getDefault(4))
|
||||
};
|
||||
curChangeIndex = 0;
|
||||
bpmChangeMap = [curChange];
|
||||
invalidEvents = [];
|
||||
|
||||
for(event in Charter.instance.eventsGroup.members) {
|
||||
event.events.sort(function(a, b) {
|
||||
if (a.time == b.time) {
|
||||
if (a.name == "Continuous BPM Change") return 1;
|
||||
if (b.name == "Continuous BPM Change") return -1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
|
||||
var eventTime = Conductor.getTimeForStep(event.step);
|
||||
for (e in event.events) {
|
||||
e.time = eventTime;
|
||||
|
||||
curChange.stepTime = CoolUtil.floorInt(curChange.stepTime + .99998);
|
||||
curChange.beatTime = CoolUtil.floorInt(curChange.beatTime + .99998);
|
||||
curChange.measureTime = CoolUtil.floorInt(curChange.measureTime + .99998);
|
||||
if ((e.name == "BPM Change" || e.name == "Time Signature Change" || e.name == "Continuous BPM Change")) {
|
||||
curChange = mapEvent(e, curChange);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static var elapsed:Float;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user