Files
CodenameEngine/source/funkin/editors/charter/CharterBackdropGroup.hx
T
2024-11-11 15:16:16 -07:00

352 lines
10 KiB
Haxe

package funkin.editors.charter;
import flixel.addons.display.FlxBackdrop;
import flixel.graphics.FlxGraphic;
import funkin.backend.system.Conductor;
import openfl.geom.Rectangle;
import funkin.backend.shaders.CustomShader;
class FlxFastTypedGroup<T:FlxBasic> extends FlxTypedGroup<T> {
public function new(?maxSize:Int = 0) {
super(maxSize);
}
override public function add(Object:T):T
{
if (Object == null)
{
FlxG.log.warn("Cannot add a `null` object to a FlxGroup.");
return null;
}
// removed the check for multiple
// removed the check for null reuse
// If the group is full, return the Object
if (maxSize > 0 && length >= maxSize)
return Object;
// If we made it this far, we need to add the object to the group.
members.push(Object);
length++;
if (_memberAdded != null)
_memberAdded.dispatch(Object);
return Object;
}
}
class CharterBackdropGroup extends FlxTypedGroup<CharterBackdrop> {
public var strumLineGroup:CharterStrumLineGroup;
public var notesGroup:CharterNoteGroup;
public var conductorSprY:Float = 0;
public var bottomLimitY:Float = 0;
public var sectionsVisible:Bool = true;
public var beatsVisible:Bool = true;
// Just here so you can update display sprites all dat and above
public var strumlinesAmount:Int = 0;
public function new(strumLineGroup:CharterStrumLineGroup) {
super();
this.strumLineGroup = strumLineGroup;
}
public function createGrids(amount:Int = 0) {
for (i in 0...amount) {
var grid = new CharterBackdrop();
grid.active = grid.visible = false;
add(grid);
}
}
public override function update(elapsed:Float) {
for (grid in members)
grid.active = grid.visible = false;
super.update(elapsed);
for (i => strumLine in strumLineGroup.members) {
if (strumLine == null) continue;
if (members[i] == null)
members[i] = recycle(CharterBackdrop, () -> {return new CharterBackdrop();});
var grid = members[i];
grid.cameras = this.cameras;
grid.strumLine = strumLine;
grid.conductorFollowerSpr.y = conductorSprY;
grid.bottomSeparator.y = (grid.bottomLimit.y = bottomLimitY)-2;
grid.sectionSeparator.visible = sectionsVisible;
grid.beatSeparator.visible = beatsVisible;
grid.waveformSprite.shader = strumLine.waveformShader;
grid.notesGroup.clear();
notesGroup.forEach((n) -> {
if(n.exists && n.visible) {
var onStr:Bool = (n.snappedToGrid ? n.strumLineID : CoolUtil.boundInt(Std.int((n.x+n.width)/(40*strumLine.keyCount)), 0, strumLineGroup.members.length-1)) == i;
if(onStr)
grid.notesGroup.add(n);
}
});
grid.active = grid.visible = true;
grid.updateSprites();
}
}
public var draggingObj:CharterBackdrop = null;
override function draw() @:privateAccess {
var i:Int = 0;
var basic:FlxBasic = null;
for (grid in members) {
if (strumLineGroup.draggingObj == null) break;
if (grid.strumLine == null) continue;
if (strumLineGroup.draggingObj.strumLine == grid.strumLine.strumLine) {
draggingObj = grid;
break;
}
}
var oldDefaultCameras = FlxCamera._defaultCameras;
if (cameras != null)
FlxCamera._defaultCameras = cameras;
while (i < length)
{
basic = members[i++];
if (basic != null && basic != draggingObj && basic.exists && basic.visible)
basic.draw();
}
if (draggingObj != null) draggingObj.draw();
FlxCamera._defaultCameras = oldDefaultCameras;
}
}
class CharterBackdrop extends FlxTypedGroup<FlxBasic> {
public var gridBackDrop:FlxBackdrop;
public var topLimit:FlxSprite;
public var topSeparator:FlxSprite;
public var bottomLimit:FlxSprite;
public var bottomSeparator:FlxSprite;
public var waveformSprite:FlxSprite;
public var conductorFollowerSpr:FlxSprite;
public var beatSeparator:FlxBackdrop;
public var sectionSeparator:FlxBackdrop;
public var notesGroup:FlxFastTypedGroup<CharterNote> = new FlxFastTypedGroup<CharterNote>();
public var strumLine:CharterStrumline;
public var gridShader:CustomShader = new CustomShader("engine/charterGrid");
var __lastKeyCount:Int = 4;
public function new() {
super();
gridBackDrop = new FlxBackdrop(null, Y, 0, 0);
gridBackDrop.makeSolid(1, 1, -1);
gridBackDrop.shader = gridShader;
add(gridBackDrop);
gridShader.hset("segments", 4);
waveformSprite = new FlxSprite().makeSolid(1, 1, 0xFF000000);
waveformSprite.scale.set(160, 1);
waveformSprite.updateHitbox();
add(waveformSprite);
sectionSeparator = new FlxBackdrop(null, Y, 0, 0);
sectionSeparator.y = -2;
sectionSeparator.visible = Options.charterShowSections;
beatSeparator = new FlxBackdrop(null, Y, 0, 0);
beatSeparator.y = -1;
beatSeparator.visible = Options.charterShowBeats;
for(sep in [sectionSeparator, beatSeparator]) {
sep.makeSolid(1, 1, -1);
sep.alpha = 0.5;
sep.scrollFactor.set(1, 1);
sep.scale.set((4 * 40), sep == sectionSeparator ? 4 : 2);
sep.updateHitbox();
}
add(beatSeparator);
add(sectionSeparator);
add(notesGroup);
bottomSeparator = new FlxSprite(0,-2);
bottomSeparator.makeSolid(1, 1, -1);
bottomSeparator.alpha = 0.5;
bottomSeparator.scrollFactor.set(1, 1);
bottomSeparator.scale.set(4 * 40, 4);
bottomSeparator.updateHitbox();
add(bottomSeparator);
topSeparator = new FlxSprite(0, -2);
topSeparator.makeSolid(1, 1, -1);
topSeparator.alpha = 0.5;
topSeparator.scrollFactor.set(1, 1);
topSeparator.scale.set(4 * 40, 4);
topSeparator.updateHitbox();
add(topSeparator);
// Limits
topLimit = new FlxSprite();
topLimit.makeSolid(1, 1, -1);
topLimit.color = 0xFF888888;
topLimit.blend = MULTIPLY;
add(topLimit);
bottomLimit = new FlxSprite();
bottomLimit.makeSolid(1, 1, -1);
bottomLimit.color = 0xFF888888;
bottomLimit.blend = MULTIPLY;
add(bottomLimit);
// Follower
conductorFollowerSpr = new FlxSprite(0, 0).makeSolid(1, 1, -1);
conductorFollowerSpr.scale.set(4 * 40, 4);
conductorFollowerSpr.updateHitbox();
add(conductorFollowerSpr);
}
public function updateSprites() {
var x:Float = 0; // fuck you
var alpha:Float = 0.9;
var keyCount:Int = 4;
if (strumLine != null) {
x = strumLine.x;
alpha = strumLine.strumLine.visible ? 0.9 : 0.4;
keyCount = strumLine.keyCount;
} else alpha = 0.9;
for (spr in [gridBackDrop, sectionSeparator, beatSeparator, topLimit, bottomLimit,
topSeparator, bottomSeparator, conductorFollowerSpr, waveformSprite]) {
spr.x = x; if (spr != waveformSprite) spr.alpha = alpha;
spr.cameras = this.cameras;
}
gridBackDrop.setGraphicSize(40*keyCount, 160);
gridBackDrop.updateHitbox();
if (__lastKeyCount != keyCount) gridShader.hset("segments", keyCount);
__lastKeyCount = keyCount;
sectionSeparator.spacing.y = (10 * Conductor.beatsPerMeasure * Conductor.stepsPerBeat) - 1;
beatSeparator.spacing.y = (20 * Conductor.stepsPerBeat) - 1;
topLimit.scale.set(keyCount * 40, Math.ceil(FlxG.height / cameras[0].zoom));
topLimit.updateHitbox();
topLimit.y = -topLimit.height;
bottomLimit.scale.set(keyCount * 40, Math.ceil(FlxG.height / cameras[0].zoom));
bottomLimit.updateHitbox();
for (spr in [conductorFollowerSpr, sectionSeparator, beatSeparator, topSeparator, bottomSeparator]) {
spr.scale.x = keyCount * 40;
spr.updateHitbox();
}
waveformSprite.visible = waveformSprite.shader != null;
if (waveformSprite.shader == null) return;
waveformSprite.scale.set(keyCount * 40, FlxG.height * (1/cameras[0].zoom));
waveformSprite.updateHitbox();
waveformSprite.y = (cameras[0].scroll.y+FlxG.height/2)-(waveformSprite.height/2);
if (waveformSprite.y < 0) {waveformSprite.scale.y += waveformSprite.y; waveformSprite.y = 0;}
if (waveformSprite.y + waveformSprite.height > bottomLimit.y) {
waveformSprite.scale.y -= (waveformSprite.y + waveformSprite.height)-(bottomLimit.y);
waveformSprite.y = (bottomLimit.y) - waveformSprite.scale.y;
}
waveformSprite.updateHitbox();
waveformSprite.shader.data.pixelOffset.value = [Math.max(conductorFollowerSpr.y - ((FlxG.height * (1/cameras[0].zoom)) * 0.5), 0)];
waveformSprite.shader.data.textureRes.value = [waveformSprite.width, waveformSprite.height];
waveformSprite.shader.data.playerPosition.value = [conductorFollowerSpr.y];
}
}
class EventBackdrop extends FlxBackdrop {
public var eventBeatSeparator:FlxBackdrop;
public var eventSecSeparator:FlxBackdrop;
public var topSeparator:FlxSprite;
public var bottomSeparator:FlxSprite;
public var global:Bool = false;
public function new(global:Bool) {
super(Paths.image('editors/charter/events-grid'), Y, 0, 0);
this.global = flipX = flipY = global;
alpha = 0.9;
// Separators
eventSecSeparator = new FlxBackdrop(null, Y, 0, 0);
eventSecSeparator.y = -2;
eventSecSeparator.visible = Options.charterShowSections;
eventBeatSeparator = new FlxBackdrop(null, Y, 0, 0);
eventBeatSeparator.y = -1;
eventBeatSeparator.visible = Options.charterShowBeats;
for(sep in [eventSecSeparator, eventBeatSeparator]) {
sep.makeSolid(1, 1, -1);
sep.alpha = 0.5;
sep.scrollFactor.set(1, 1);
}
eventSecSeparator.scale.set(20, 4);
eventSecSeparator.updateHitbox();
eventBeatSeparator.scale.set(10, 2);
eventBeatSeparator.updateHitbox();
bottomSeparator = new FlxSprite(0,-2);
bottomSeparator.makeSolid(1, 1, -1);
bottomSeparator.alpha = 0.5;
bottomSeparator.scrollFactor.set(1, 1);
bottomSeparator.scale.set(20, 4);
bottomSeparator.updateHitbox();
topSeparator = new FlxSprite(0, -2);
topSeparator.makeSolid(1, 1, -1);
topSeparator.alpha = 0.5;
topSeparator.scrollFactor.set(1, 1);
topSeparator.scale.set(20, 4);
topSeparator.updateHitbox();
}
public override function draw() {
super.draw();
eventSecSeparator.spacing.y = (10 * Conductor.beatsPerMeasure * Conductor.stepsPerBeat) - 1;
eventBeatSeparator.spacing.y = (20 * Conductor.stepsPerBeat) - 1;
eventSecSeparator.cameras = cameras;
eventSecSeparator.x = this.global ? x : ((x+width) - 20);
if (eventSecSeparator.visible) eventSecSeparator.draw();
eventBeatSeparator.cameras = cameras;
eventBeatSeparator.x = this.global ? x : ((x+width) - 10);
if (eventBeatSeparator.visible) eventBeatSeparator.draw();
topSeparator.x = this.global ? x : ((x+width) - 20);
topSeparator.cameras = this.cameras;
if (!eventSecSeparator.visible) topSeparator.draw();
bottomSeparator.x = this.global ? x : ((x+width) - 20);
bottomSeparator.cameras = this.cameras;
bottomSeparator.draw();
}
}