diff --git a/assets/shaders/engine/editorWaveforms.frag b/assets/shaders/engine/editorWaveforms.frag index 28734524..9a8b8be7 100644 --- a/assets/shaders/engine/editorWaveforms.frag +++ b/assets/shaders/engine/editorWaveforms.frag @@ -5,6 +5,7 @@ uniform vec2 textureRes; uniform float pixelOffset; +uniform float waveAlpha; uniform sampler2D waveformTexture; uniform ivec2 waveformSize; @@ -58,6 +59,6 @@ void main() gradientColor = mix(gradientColor, gradientColor * vec3(1.8), map(hightlightAmount, 0., 1., .4, 1.)); } - gl_FragColor = vec4(vec3(gradientColor * mix(0.5, .8, amplitude)), 1.); + gl_FragColor = vec4(vec3(gradientColor * mix(0.5, .8, amplitude))*openfl_Alphav, openfl_Alphav); } } \ No newline at end of file diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index ba203022..afa94443 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -551,70 +551,21 @@ class Charter extends UIState { __relinkUndos(); __applyPlaytestInfo(); - var analyzer:AudioAnalyzer = new AudioAnalyzer(FlxG.sound.music); + /* + var charterWaveHandler:CharterWaveformHandler = new CharterWaveformHandler(); + var waveShader:CustomShader = charterWaveHandler.generateShader("Inst.ogg", FlxG.sound.music); - var pixelsToAnalyze:Float = __endStep*40; - - var pixelsNeeded:Int = Math.floor(pixelsToAnalyze/3); - if ((pixelsToAnalyze/3) % 1 > 0) pixelsNeeded += 1; - - var WRAP_WIDTH:Int = 500; // just to test if it works - lunar - - var waveData:BitmapData = new BitmapData(WRAP_WIDTH, 1+Math.floor(pixelsNeeded/WRAP_WIDTH), true, 0xFF000000); - - for (y in 0...waveData.height) - for (x in 0...waveData.width) { - var amplitudes:Array = [0., 0., 0.]; - for (color in 0...3) { - var gridY:Float = (y * (waveData.width * 3)) + (x * 3) + color; - - var startTime:Float = Conductor.getTimeForStep(gridY/40); - if (startTime > FlxG.sound.music.length) - if (color == 0) break; else continue; - - var endTime:Float = Conductor.getTimeForStep((gridY+1)/40); - if (endTime > FlxG.sound.music.length) - if (color == 0) break; else continue; - - var amplitude:Float = analyzer.analyze(startTime, endTime); - amplitudes[color] = amplitude; - } - waveData.setPixel(x, y, FlxColor.fromRGBFloat(amplitudes[0], amplitudes[1], amplitudes[2])); - } - - var sprite:FlxSprite = new FlxSprite().loadGraphic(waveData); - sprite.cameras = [charterCamera]; - add(sprite); - - var testWaveform:FlxSprite = new FlxSprite().makeSolid(160, 16*Std.int(40 * Conductor.getMeasureLength()), 0xFF000000); - testWaveform.cameras = [charterCamera]; - // add(testWaveform); - - wshader = new CustomShader("engine/editorWaveforms"); - // wshader.data.textureRes.value = [testWaveform.width, testWaveform.height]; - wshader.data.waveformSize.value = [waveData.width, waveData.height]; - wshader.data.waveformTexture.input = waveData; - wshader.data.pixelOffset.value = [0]; - - testSpriteCool = new FlxSprite().makeSolid(1, 1, 0xFFFF0000); - testSpriteCool.scale.set(160, FlxG.height); - testSpriteCool.cameras = [charterCamera]; - testSpriteCool.updateHitbox(); - testSpriteCool.setPosition(0,0); - testSpriteCool.shader = wshader; - add(testSpriteCool); + for (grid in gridBackdrops) grid.waveformSprite.shader = waveShader; + */ } - var testSpriteCool:FlxSprite; - var wshader:CustomShader; - public var __endStep:Float = 0; public function refreshBPMSensitive() { // refreshes everything dependant on BPM, and BPM changes var length = FlxG.sound.music.getDefault(vocals).length; scrollBar.length = __endStep = Conductor.getStepForTime(length); - gridBackdrops.bottomLimitY = Conductor.getStepForTime(length) * 40; + gridBackdrops.bottomLimitY = __endStep * 40; eventsBackdrop.bottomSeparator.y = gridBackdrops.bottomLimitY-2; } @@ -1067,21 +1018,6 @@ class Charter extends UIState { gridBackdrops.conductorSprY - (FlxG.height * 0.5) ); - testSpriteCool.scale.set(160, FlxG.height * (1/charterCamera.zoom)); - testSpriteCool.updateHitbox(); - - testSpriteCool.y = (charterCamera.scroll.y+FlxG.height/2)-(testSpriteCool.height/2); - - if (testSpriteCool.y < 0) {testSpriteCool.scale.y += testSpriteCool.y; testSpriteCool.y = 0;} - if (testSpriteCool.y + testSpriteCool.height > __endStep*40) { - testSpriteCool.scale.y -= (testSpriteCool.y + testSpriteCool.height)-(__endStep*40); - testSpriteCool.y = (__endStep*40) - testSpriteCool.scale.y; - } - testSpriteCool.updateHitbox(); - - wshader.data.textureRes.value = [testSpriteCool.width, testSpriteCool.height]; - wshader.data.pixelOffset.value = [Math.max(gridBackdrops.conductorSprY - ((FlxG.height * (1/charterCamera.zoom)) * 0.5), 0)]; - if (topMenuSpr.members[playbackIndex] != null) { var playBackButton:UITopMenuButton = cast topMenuSpr.members[playbackIndex]; playBackButton.x = playBackSlider.x-playBackSlider.startText.width-10-playBackSlider.valueStepper.bWidth-playBackButton.bWidth-10; diff --git a/source/funkin/editors/charter/CharterBackdropGroup.hx b/source/funkin/editors/charter/CharterBackdropGroup.hx index 851df461..7a5c379a 100644 --- a/source/funkin/editors/charter/CharterBackdropGroup.hx +++ b/source/funkin/editors/charter/CharterBackdropGroup.hx @@ -114,6 +114,8 @@ class CharterBackdrop extends FlxTypedGroup { public var bottomLimit:FlxSprite; public var bottomSeparator:FlxSprite; + public var waveformSprite:FlxSprite; + public var conductorFollowerSpr:FlxSprite; public var beatSeparator:FlxBackdrop; public var sectionSeparator:FlxBackdrop; @@ -127,6 +129,11 @@ class CharterBackdrop extends FlxTypedGroup { gridBackDrop = new FlxBackdrop(gridGraphic, Y, 0, 0); add(gridBackDrop); + 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; @@ -191,8 +198,9 @@ class CharterBackdrop extends FlxTypedGroup { alpha = strumLine.strumLine.visible ? 0.9 : 0.4; } else alpha = 0.9; - for (spr in [gridBackDrop, sectionSeparator, beatSeparator, topLimit, bottomLimit, topSeparator, bottomSeparator, conductorFollowerSpr]) { - spr.x = x; spr.alpha = alpha; + 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; } @@ -205,6 +213,24 @@ class CharterBackdrop extends FlxTypedGroup { bottomLimit.scale.set(4 * 40, Math.ceil(FlxG.height / cameras[0].zoom)); bottomLimit.updateHitbox(); + + waveformSprite.visible = waveformSprite.shader != null; + if (waveformSprite.shader == null) return; + + waveformSprite.scale.set(160, 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]; } } diff --git a/source/funkin/editors/charter/CharterWaveformHandler.hx b/source/funkin/editors/charter/CharterWaveformHandler.hx index 14be299c..24e8a763 100644 --- a/source/funkin/editors/charter/CharterWaveformHandler.hx +++ b/source/funkin/editors/charter/CharterWaveformHandler.hx @@ -1 +1,90 @@ package funkin.editors.charter; + +import flixel.util.FlxColor; +import funkin.backend.system.Conductor; +import flixel.sound.FlxSound; +import funkin.backend.shaders.CustomShader; +import openfl.display.BitmapData; + +class CharterWaveformHandler extends FlxBasic { + public var ampsNeeded:Float = 0; + public var ampSqrt(get, never):Int; + public function get_ampSqrt():Int { + var sqrt:Float = Math.sqrt(ampsNeeded); + var ampRet:Int = Math.floor(sqrt); + if (sqrt % 1 > 0) ampRet += 1; + return ampRet; + } + + public var waveDatas:Map = []; + public var waveShaders:Map = []; + + public var sounds:Map = []; + public var analyzers:Map = []; + + public function new() {super(); exists = false;} + + public function generateData(name:String, sound:FlxSound):BitmapData { + if (!sounds.exists(name)) sounds.set(name, sound); + if (!analyzers.exists(name)) + analyzers.set(name, new AudioAnalyzer(sound)); + + var analyzer:AudioAnalyzer = analyzers.get(name); + + var pixelsNeeded:Int = Math.floor(ampsNeeded/3); + if ((ampsNeeded/3) % 1 > 0) pixelsNeeded += 1; + + var WRAP:Int = 500; // should be ampSqrt + + var waveData:BitmapData = new BitmapData( + WRAP, 1+Math.floor(pixelsNeeded/WRAP), true, 0xFF000000 + ); + + for (y in 0...waveData.height) + for (x in 0...waveData.width) { + var amplitudes:Array = [0., 0., 0.]; + for (color in 0...3) { + var gridY:Float = (y * (waveData.width * 3)) + (x * 3) + color; + + var startTime:Float = Conductor.getTimeForStep(gridY/40); + if (startTime > sound.length) if (color == 0) break; else continue; + + var endTime:Float = Conductor.getTimeForStep((gridY+1)/40); + if (endTime > sound.length) if (color == 0) break; else continue; + + var amplitude:Float = analyzer.analyze(startTime, endTime); + amplitudes[color] = amplitude; + } + waveData.setPixel(x, y, FlxColor.fromRGBFloat(amplitudes[0], amplitudes[1], amplitudes[2])); + } + + waveDatas.set(name, waveData); + return waveData; + } + + public function generateShader(name:String, sound:FlxSound):CustomShader { + if (!waveDatas.exists(name)) generateData(name, sound); + + var waveData:BitmapData = waveDatas.get(name); + + var waveShader:CustomShader = new CustomShader("engine/editorWaveforms"); + waveShader.data.waveformSize.value = [waveData.width, waveData.height]; + waveShader.data.waveformTexture.input = waveData; + waveShader.data.textureRes.value = [0, 0]; + waveShader.data.pixelOffset.value = [0]; + + waveShaders.set(name, waveShader); + return waveShader; + } + + public override function destroy() { + for (data in waveDatas) data.dispose(); + for (shader in waveShaders) shader = null; + for (analyzer in analyzers) analyzer = null; + + waveDatas.clear(); waveShaders.clear(); + analyzers.clear(); sounds.clear(); + + super.destroy(); + } +} \ No newline at end of file