diff --git a/art/flashFiles/RECOVER_NOTE_assets.fla b/art/flashFiles/RECOVER_NOTE_assets.fla new file mode 100644 index 00000000..32a9b700 Binary files /dev/null and b/art/flashFiles/RECOVER_NOTE_assets.fla differ diff --git a/assets/images/editors/charter/note.png b/assets/images/editors/charter/note.png new file mode 100644 index 00000000..703ec056 Binary files /dev/null and b/assets/images/editors/charter/note.png differ diff --git a/assets/shaders/engine/README.txt b/assets/shaders/engine/README.txt new file mode 100644 index 00000000..d5534429 --- /dev/null +++ b/assets/shaders/engine/README.txt @@ -0,0 +1,3 @@ +THOSE SHADERS ARE USED INTERNALLY BY THE ENGINE + +MODIFY THEM AT YOUR OWN RISK!! IF IT CRASHES IT AINT MY FAULT \ No newline at end of file diff --git a/assets/shaders/engine/charterNote.frag b/assets/shaders/engine/charterNote.frag new file mode 100644 index 00000000..8e0c60f0 --- /dev/null +++ b/assets/shaders/engine/charterNote.frag @@ -0,0 +1,9 @@ +#pragma header + +uniform vec3 noteColor; + +void main() { + vec4 finalColor = flixel_texture2D(bitmap, openfl_TextureCoordv); + float diff = finalColor.r - ((finalColor.g + finalColor.b) / 2.0); + gl_FragColor = vec4(((finalColor.g + finalColor.b) / 2.0) + (noteColor.r * diff), finalColor.g + (noteColor.g * diff), finalColor.b + (noteColor.b * diff), finalColor.a); +} \ No newline at end of file diff --git a/assets/shaders/circleProfilePicture.frag b/assets/shaders/engine/circleProfilePicture.frag similarity index 100% rename from assets/shaders/circleProfilePicture.frag rename to assets/shaders/engine/circleProfilePicture.frag diff --git a/assets/shaders/editorBlur.frag b/assets/shaders/engine/editorBlur.frag similarity index 100% rename from assets/shaders/editorBlur.frag rename to assets/shaders/engine/editorBlur.frag diff --git a/assets/shaders/updaterShader.frag b/assets/shaders/engine/updaterShader.frag similarity index 100% rename from assets/shaders/updaterShader.frag rename to assets/shaders/engine/updaterShader.frag diff --git a/buildnumber.txt b/buildnumber.txt index f1488c48..917c81e5 100644 --- a/buildnumber.txt +++ b/buildnumber.txt @@ -1 +1 @@ -2651 \ No newline at end of file +2663 \ No newline at end of file diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 6920486b..97ee2f96 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1,5 +1,8 @@ package funkin.editors.charter; +import funkin.system.Conductor; +import funkin.chart.*; +import funkin.chart.ChartData; import openfl.display.BitmapData; import flixel.util.FlxColor; import flixel.addons.display.FlxBackdrop; @@ -10,11 +13,16 @@ class Charter extends UIState { var __song:String; var __diff:String; + var chart(get, null):ChartData; + private function get_chart() + return PlayState.SONG; + /** - * CONFIG (might make this customizable later) + * CONFIG & UI (might make this customizable later) */ - private var gridColor1:FlxColor = 0xFF404040; // white - private var gridColor2:FlxColor = 0xFF212121; // gray + public var uiGroup:FlxTypedGroup = new FlxTypedGroup(); + private var gridColor1:FlxColor = 0xFF272727; // white + private var gridColor2:FlxColor = 0xFF545454; // gray public var topMenu:Array = [ { @@ -101,7 +109,21 @@ class Charter extends UIState { ]; public var topMenuSpr:UITopMenu; - public var gridBackdrop:FlxBackdrop; + public var gridBackdrop:CharterBackdrop; + + /** + * ACTUAL CHART DATA + */ + public var strumLines:Array = []; + public var notesGroup:FlxTypedGroup = new FlxTypedGroup(); + + /** + * CAMERAS + */ + // camera for the chart itself so that it can be unzoomed/zoomed in again + public var charterCamera:FlxCamera; + // camera for the ui + public var uiCamera:FlxCamera; public function new(song:String, diff:String) { super(); @@ -112,29 +134,52 @@ class Charter extends UIState { public override function create() { super.create(); trace('Entering Charter for song $__song with difficulty $__diff.'); + + + charterCamera = FlxG.camera; + uiCamera = new FlxCamera(); + uiCamera.bgColor = 0; + FlxG.cameras.add(uiCamera); + + + gridBackdrop = new CharterBackdrop(); + gridBackdrop.setPosition(0, 0); + notesGroup.cameras = gridBackdrop.cameras = [charterCamera]; + + + topMenuSpr = new UITopMenu(topMenu); + topMenuSpr.cameras = uiGroup.cameras = [uiCamera]; + + + // adds grid and notes so that they're ALWAYS behind the UI + add(gridBackdrop); + add(notesGroup); + // add the ui group + add(uiGroup); + // add the top menu last OUT of the ui group so that it stays on top + add(topMenuSpr); + + loadSong(); + } + + public function loadSong() { CoolUtil.loadSong(__song, __diff, false, false); - gridBackdrop = new FlxBackdrop(null, 1, 1, true, true); - gridBackdrop.makeGraphic(4, 4, gridColor1, true); - gridBackdrop.pixels.lock(); - for(y in 0...4) - for(x in 0...2) - gridBackdrop.pixels.setPixel32((x*2)+(y%2), y, gridColor2); - gridBackdrop.pixels.unlock(); - gridBackdrop.scale.set(40, 40); - gridBackdrop.updateHitbox(); - gridBackdrop.loadFrame(gridBackdrop.frame); - gridBackdrop.cameras = cameras; - add(gridBackdrop); - - - // ALWAYS ADD LAST - topMenuSpr = new UITopMenu(topMenu); - add(topMenuSpr); + Conductor.setupSong(PlayState.SONG); + + for(strID=>strL in PlayState.SONG.strumLines) { + for(note in strL.notes) { + var n = new CharterNote(); + n.updatePos(Conductor.getStepForTime(note.time), (strID * 4) + note.id, note.sLen, note.type); + notesGroup.add(n); + } + } } public override function update(elapsed:Float) { super.update(elapsed); + + gridBackdrop.strumlinesAmount = 3; // TODO: remove this bs!! if (controls.BACK) FlxG.switchState(new funkin.menus.MainMenuState()); diff --git a/source/funkin/editors/charter/CharterBackdrop.hx b/source/funkin/editors/charter/CharterBackdrop.hx new file mode 100644 index 00000000..a6e750af --- /dev/null +++ b/source/funkin/editors/charter/CharterBackdrop.hx @@ -0,0 +1,30 @@ +package funkin.editors.charter; + +import flixel.addons.display.FlxBackdrop; + +class CharterBackdrop extends FlxBackdrop { + public var strumlinesAmount:Int = 1; + + public function new() { + super(null, 1, 1, false, true); + + makeGraphic(4, 4, 0xFF272727, true); + pixels.lock(); + for(y in 0...4) + for(x in 0...2) + pixels.setPixel32((x*2)+(y%2), y, 0xFF545454); + pixels.unlock(); + scale.set(40, 40); + updateHitbox(); + loadFrame(frame); + } + + public override function draw() { + var ogX:Float = x; + for(_ in 0...strumlinesAmount) { + super.draw(); + x += width; + } + x = ogX; + } +} \ No newline at end of file diff --git a/source/funkin/editors/charter/CharterNote.hx b/source/funkin/editors/charter/CharterNote.hx new file mode 100644 index 00000000..a4a284dd --- /dev/null +++ b/source/funkin/editors/charter/CharterNote.hx @@ -0,0 +1,81 @@ +package funkin.editors.charter; + +import flixel.tweens.FlxTween; +import funkin.shaders.CustomShader; +import flixel.util.FlxColor; + +class CharterNote extends UISprite { + private static var colors:Array = [ + 0xFFC24B99, // purple + 0xFF00FFFF, // cyan + 0xFF12FA05, // green + 0xFFF9393F // red + ]; + private static var colorsRotation:Array; + + public static final noteScaleX:Float = 40 / 154; + public static final noteScaleY:Float = 40 / 157; + + public var charterNoteShader:CustomShader; + + var angleTween:FlxTween; + + public function new() { + super(); + antialiasing = true; + loadGraphic(Paths.image('editors/charter/note')); + scale.set(noteScaleX, noteScaleY); + updateHitbox(); + scale.set(noteScaleY, noteScaleY); + + shader = charterNoteShader = new CustomShader('engine/charterNote'); + + if (colorsRotation == null) colorsRotation = [ + colors[2], + colors[3], + colors[1], + colors[0] + ]; + + angle = 45; // green-red inbetween + } + + private override function set_angle(v:Float):Float { + if (charterNoteShader != null) { + var v2:Float = v; + var o:Int = 0; + + // make sure the note isnt negative + while(v2 < 0) { + v2 += 90; + o -= 1; + } + // make sure the note is under 90 degrees + while(v2 > 90) { + v2 -= 90; + o += 1; + } + var c:FlxColor = FlxColor.interpolate(colorsRotation[FlxMath.wrap(o, 0, 3)], colorsRotation[FlxMath.wrap(o+1, 0, 3)], v2 / 90); + + charterNoteShader.hset('noteColor', [c.redFloat, c.greenFloat, c.blueFloat]); + } + return super.set_angle(v); + } + + public function updatePos(step:Float, id:Int, susLength:Float = 0, type:Int = 0) { + x = id * 40; + y = step * 40; + + if (angleTween != null) angleTween.cancel(); + + angleTween = FlxTween.tween(this, {angle: switch(id % 4) { + case 0: -90; + case 1: 180; + case 2: 0; + case 3: 90; + default: 0; // how is that even possible + }}, 1, {ease: function(t) { + return ((Math.sin(t * Math.PI) * 0.35) * 3 * t * Math.sqrt(1 - t)) + t; + }}); + } +} \ No newline at end of file diff --git a/source/funkin/editors/ui/UIWarningSubstate.hx b/source/funkin/editors/ui/UIWarningSubstate.hx index 38365f4a..11fe9b8d 100644 --- a/source/funkin/editors/ui/UIWarningSubstate.hx +++ b/source/funkin/editors/ui/UIWarningSubstate.hx @@ -6,7 +6,7 @@ import funkin.shaders.CustomShader; class UIWarningSubstate extends MusicBeatSubstate { var camShaders:Array = []; - var blurShader:CustomShader = new CustomShader("editorBlur"); + var blurShader:CustomShader = new CustomShader("engine/editorBlur"); var title:String; var message:String; diff --git a/source/funkin/menus/credits/CreditsCodename.hx b/source/funkin/menus/credits/CreditsCodename.hx index d1728d56..611e3296 100644 --- a/source/funkin/menus/credits/CreditsCodename.hx +++ b/source/funkin/menus/credits/CreditsCodename.hx @@ -77,7 +77,7 @@ class CreditsCodename extends OptionsScreen { spr.antialiasing = true; spr.setUnstretchedGraphicSize(96, 96, false); spr.updateHitbox(); - spr.shader = new CustomShader('circleProfilePicture'); + spr.shader = new CustomShader('engine/circleProfilePicture'); contributorsSprites.push(spr); add(spr); } diff --git a/source/funkin/system/Conductor.hx b/source/funkin/system/Conductor.hx index 44705092..0d3c19d9 100644 --- a/source/funkin/system/Conductor.hx +++ b/source/funkin/system/Conductor.hx @@ -250,4 +250,32 @@ class Conductor onBPMChange.dispatch(bpm); } + + public static function getTimeForStep(step:Float) { + var bpmChange:BPMChangeEvent = { + stepTime: 0, + songTime: 0, + bpm: bpm + }; + + for(change in bpmChangeMap) + if (change.stepTime < step && change.stepTime >= bpmChange.stepTime) + bpmChange = change; + + return bpmChange.songTime + ((step - bpmChange.stepTime) * ((60 / bpmChange.bpm) * 250)); + } + + public static function getStepForTime(time:Float) { + var bpmChange:BPMChangeEvent = { + stepTime: 0, + songTime: 0, + bpm: bpm + }; + + for(change in bpmChangeMap) + if (change.songTime < time && change.songTime >= bpmChange.songTime) + bpmChange = change; + + return bpmChange.stepTime + ((time - bpmChange.songTime) / ((60 / bpmChange.bpm) * 250)); + } } diff --git a/source/funkin/updating/UpdateScreen.hx b/source/funkin/updating/UpdateScreen.hx index 1b6a3bb6..dfcc9b0c 100644 --- a/source/funkin/updating/UpdateScreen.hx +++ b/source/funkin/updating/UpdateScreen.hx @@ -61,7 +61,7 @@ class UpdateScreen extends MusicBeatState { updater.execute(); - FlxG.camera.addShader(rainbowShader = new CustomShader("updaterShader")); + FlxG.camera.addShader(rainbowShader = new CustomShader("engine/updaterShader")); }