From 5a1fc57fd1eb77d41555872caa0827345a5147a7 Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Fri, 15 Aug 2025 16:35:52 +0100 Subject: [PATCH 01/10] camera highlights again --- source/funkin/editors/charter/Charter.hx | 53 +++++++++++++++ .../editors/charter/CharterBackdropGroup.hx | 67 ++++++++++++++++++- .../editors/charter/CharterStrumLineGroup.hx | 1 + .../editors/charter/CharterStrumline.hx | 11 +++ source/funkin/options/Options.hx | 1 + 5 files changed, 132 insertions(+), 1 deletion(-) diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index facf00351..874247421 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -94,6 +94,7 @@ class Charter extends UIState { public var rightEventRowText:UIText; public var leftEventsGroup:CharterEventGroup = new CharterEventGroup(); public var rightEventsGroup:CharterEventGroup = new CharterEventGroup(); + public var cameraMovementChanges:Array = []; public var charterCamera:FlxCamera; public var uiCamera:FlxCamera; @@ -306,6 +307,11 @@ class Charter extends UIState { onSelect: _view_showeventBeatSeparator, icon: Options.charterShowBeats ? 1 : 0 }, + { + label: 'Show Camera Highlights', + onSelect: _view_showeventCameraHighlights, + icon: Options.charterShowCameraHighlights ? 1 : 0 + }, null, { label: translate("view.rainbowWaveforms"), @@ -680,6 +686,7 @@ class Charter extends UIState { CharterGridSeperatorBase.lastConductorSprY = Math.NEGATIVE_INFINITY; updateWaveforms(); + updateCameraChanges(); } public function getWavesToGenerate():Array<{name:String, sound:FlxSound}> { @@ -735,6 +742,40 @@ class Charter extends UIState { } } + public function updateCameraChanges() { + if (!Options.charterShowCameraHighlights) return; + + trace("updating cam changes"); + + cameraMovementChanges = []; + for (grp in [leftEventsGroup, rightEventsGroup]) { + grp.filterEvents(); + grp.sortEvents(); + for(e in grp.members) { + for(event in e.events) { + if (event.name == "Camera Movement") { + cameraMovementChanges.push({ + strumLineID: event.params[0], + step: e.step, + endStep: __endStep + }); + } + } + } + } + + //need to sort again for both local and global events to be used + cameraMovementChanges.sort(function(e1, e2) { + return FlxSort.byValues(FlxSort.ASCENDING, e1.step, e2.step); + }); + //update previous change + if (cameraMovementChanges.length > 0) { + for (i in 1...cameraMovementChanges.length) { + cameraMovementChanges[i-1].endStep = cameraMovementChanges[i].step; + } + } + } + public override function beatHit(curBeat:Int) { super.beatHit(curBeat); if (FlxG.sound.music.playing) { @@ -1863,6 +1904,7 @@ class Charter extends UIState { __event.global = true; rightEventsGroup.add(__event); undos.addToUndo(CEditEvent(__event, [], __event.events)); + updateCameraChanges(); } function _player_camera_add(_) { @@ -1876,6 +1918,7 @@ class Charter extends UIState { __event.refreshEventIcons(); rightEventsGroup.add(__event); undos.addToUndo(CEditEvent(__event, [], __event.events)); + updateCameraChanges(); } @@ -2063,6 +2106,10 @@ class Charter extends UIState { function _view_showeventBeatSeparator(t) { t.icon = (Options.charterShowBeats = !Options.charterShowBeats) ? 1 : 0; } + function _view_showeventCameraHighlights(t) { + t.icon = (Options.charterShowCameraHighlights = !Options.charterShowCameraHighlights) ? 1 : 0; + updateCameraChanges(); + } function _view_switchWaveformRainbow(t) { t.icon = (Options.charterRainbowWaveforms = !Options.charterRainbowWaveforms) ? 1 : 0; @@ -2521,4 +2568,10 @@ typedef PlaytestInfo = { var hitSounds:Array; var mutedVocals:Array; var waveforms:Array; +} + +typedef CameraChange = { + var strumLineID:Int; + var step:Float; + var endStep:Float; } \ No newline at end of file diff --git a/source/funkin/editors/charter/CharterBackdropGroup.hx b/source/funkin/editors/charter/CharterBackdropGroup.hx index a4e35ce64..5c668789c 100644 --- a/source/funkin/editors/charter/CharterBackdropGroup.hx +++ b/source/funkin/editors/charter/CharterBackdropGroup.hx @@ -178,6 +178,8 @@ class CharterBackdrop extends FlxTypedGroup { public var gridShader:CustomShader = new CustomShader("engine/charterGrid"); var __lastKeyCount:Int = 4; + public var cameraHighlight:CameraHighlight; + public function new() { super(); @@ -187,6 +189,10 @@ class CharterBackdrop extends FlxTypedGroup { add(gridBackDrop); gridShader.hset("segments", 4); + cameraHighlight = new CameraHighlight(this); + cameraHighlight.makeSolid(1, 1, 0xFFFFFFFF); + add(cameraHighlight); + waveformSprite = new FlxSprite().makeSolid(1, 1, 0xFF000000); waveformSprite.scale.set(160, 1); waveformSprite.updateHitbox(); @@ -247,10 +253,11 @@ class CharterBackdrop extends FlxTypedGroup { x = strumLine.x; alpha = strumLine.strumLine.visible ? 0.9 : 0.4; keyCount = strumLine.keyCount; + cameraHighlight.color = strumLine.highlightColor; } else alpha = 0.9; for (spr in [gridBackDrop, beatSeparator, topLimit, bottomLimit, - topSeparator, bottomSeparator, conductorFollowerSpr, waveformSprite]) { + topSeparator, bottomSeparator, conductorFollowerSpr, waveformSprite, cameraHighlight]) { spr.x = x; if (spr != waveformSprite) spr.alpha = alpha; spr.cameras = this.cameras; } @@ -272,6 +279,9 @@ class CharterBackdrop extends FlxTypedGroup { spr.updateHitbox(); } + cameraHighlight.scale.x = (keyCount * 40)-2; + cameraHighlight.x += 1; + waveformSprite.visible = waveformSprite.shader != null; if (waveformSprite.shader == null) return; @@ -446,6 +456,61 @@ class CharterGridSeperator extends CharterGridSeperatorBase { } } +class CameraHighlight extends FlxSprite { + + private var grid:CharterBackdrop; + public function new(grid:CharterBackdrop) { + this.grid = grid; + super(); + } + + override public function draw() { + if (!Options.charterShowCameraHighlights || grid.strumLine == null) return; + + @:privateAccess + var minStep = CharterGridSeperatorBase.minStep; + @:privateAccess + var maxStep = CharterGridSeperatorBase.maxStep; + @:privateAccess + var strumLineID = Charter.instance.strumLines.isDragging ? Charter.instance.strumLines.__pastStrumlines.indexOf(grid.strumLine) : Charter.instance.gridBackdrops.members.indexOf(grid); + + //first default camera change + if ((Charter.instance.cameraMovementChanges[0] == null || Charter.instance.cameraMovementChanges[0].step != 0) && strumLineID == 0) { + var endStep = Charter.instance.cameraMovementChanges[0] != null ? Charter.instance.cameraMovementChanges[0].step : Charter.instance.__endStep; + + if (endStep >= minStep) { + setupHighlight(0, endStep); super.draw(); + setupLine(endStep); super.draw(); + } + } + + for (change in Charter.instance.cameraMovementChanges) { + if (change.endStep >= minStep) { + if (change.strumLineID == strumLineID) { + setupHighlight(change.step, change.endStep); super.draw(); + setupLine(change.step); super.draw(); + setupLine(change.endStep); super.draw(); + } + } + if (change.endStep > maxStep) break; + } + } + + private inline function setupHighlight(step:Float, endStep:Float) { + y = step * 40; + alpha = 0.15; + scale.y = (endStep -step) * 40; + updateHitbox(); + } + + private inline function setupLine(step:Float) { + y = (step * 40)-1; + alpha = 0.8; + scale.y = 2; + updateHitbox(); + } +} + class EventBackdrop extends FlxBackdrop { public var eventBeatSeparator:CharterEventGridSeperator; diff --git a/source/funkin/editors/charter/CharterStrumLineGroup.hx b/source/funkin/editors/charter/CharterStrumLineGroup.hx index 5b1633a65..2a0f42b61 100644 --- a/source/funkin/editors/charter/CharterStrumLineGroup.hx +++ b/source/funkin/editors/charter/CharterStrumLineGroup.hx @@ -105,6 +105,7 @@ class CharterStrumLineGroup extends FlxTypedGroup { draggingObj = null; fixEvents(); refreshStrumlineIDs(); + Charter.instance.updateCameraChanges(); } public inline function fixEvents() { diff --git a/source/funkin/editors/charter/CharterStrumline.hx b/source/funkin/editors/charter/CharterStrumline.hx index aea5b6790..2d37e0a52 100644 --- a/source/funkin/editors/charter/CharterStrumline.hx +++ b/source/funkin/editors/charter/CharterStrumline.hx @@ -1,5 +1,6 @@ package funkin.editors.charter; +import flixel.util.FlxColor; import flixel.group.FlxSpriteGroup; import flixel.sound.FlxSound; import funkin.backend.chart.ChartData.ChartStrumLine; @@ -15,6 +16,7 @@ class CharterStrumline extends UISprite { public var draggingSprite:UISprite; public var healthIcons:FlxSpriteGroup; public var button:CharterStrumlineOptions; + public var highlightColor:FlxColor; public var draggable:Bool = false; public var dragging:Bool = false; @@ -146,6 +148,15 @@ class CharterStrumline extends UISprite { vocals.destroy(); } vocals.group = FlxG.sound.defaultMusicGroup; + + highlightColor = 0xFFFFFFFF; + if (icons[0] != null) { + var characterXML = Character.getXMLFromCharName(icons[0]); + if (characterXML != null && characterXML.x.exists("color")) highlightColor = FlxColor.fromString(characterXML.x.get("color")); + + //make darker colors more visible for the highlight + highlightColor.brightness = Math.max(highlightColor.brightness, 0.65); + } } } diff --git a/source/funkin/options/Options.hx b/source/funkin/options/Options.hx index ac5c87acd..38993d328 100644 --- a/source/funkin/options/Options.hx +++ b/source/funkin/options/Options.hx @@ -84,6 +84,7 @@ class Options public static var charterMetronomeEnabled:Bool = false; public static var charterShowSections:Bool = true; public static var charterShowBeats:Bool = true; + public static var charterShowCameraHighlights:Bool = true; public static var charterEnablePlaytestScripts:Bool = true; public static var charterRainbowWaveforms:Bool = false; public static var charterLowDetailWaveforms:Bool = false; From 5ac0c8b2d3352a9df97e60cddaea74302e0e80dc Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Mon, 6 Oct 2025 20:59:07 +0100 Subject: [PATCH 02/10] option to mute all hitsounds --- assets/languages/en/Editors.xml | 2 ++ source/funkin/editors/charter/Charter.hx | 15 ++++++++++++--- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/assets/languages/en/Editors.xml b/assets/languages/en/Editors.xml index ae4c27e16..95497e254 100644 --- a/assets/languages/en/Editors.xml +++ b/assets/languages/en/Editors.xml @@ -223,6 +223,7 @@ Reset Zoom Show Sections Separator Show Beats Separator + Show Camera Highlights Rainbow Waveforms Low Detail Waveforms Scroll Left @@ -238,6 +239,7 @@ Add camera on Player Mute instrumental Mute voices + Mute hitsounds diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 45398ed78..98f3fe14c 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -309,7 +309,7 @@ class Charter extends UIState { icon: Options.charterShowBeats ? 1 : 0 }, { - label: 'Show Camera Highlights', + label: translate("view.showCameraHighlights"), onSelect: _view_showeventCameraHighlights, icon: Options.charterShowCameraHighlights ? 1 : 0 }, @@ -749,8 +749,6 @@ class Charter extends UIState { public function updateCameraChanges() { if (!Options.charterShowCameraHighlights) return; - trace("updating cam changes"); - cameraMovementChanges = []; for (grp in [leftEventsGroup, rightEventsGroup]) { grp.filterEvents(); @@ -1857,6 +1855,12 @@ class Charter extends UIState { for (strumLine in strumLines.members) strumLine.vocals.volume = strumLine.vocals.volume > 0 ? 0 : 1; t.icon = 1 - Std.int(Math.ceil(vocals.volume)); } + var _hitsoundsEnabled = true; + function _song_mutehitsounds(t) { + _hitsoundsEnabled = !_hitsoundsEnabled; + for (strumLine in strumLines.members) strumLine.hitsounds = !strumLine.hitsounds; + t.icon = _hitsoundsEnabled ? 0 : 1; + } function _playback_back(_) { if (FlxG.sound.music.playing) return; Conductor.songPosition -= (Conductor.beatsPerMeasure * __crochet); @@ -2074,6 +2078,11 @@ class Charter extends UIState { onSelect: _song_mutevoices }); + newChilds.push({ + label: translate("song.muteHitsounds"), + onSelect: _song_mutehitsounds + }); + if (songTopButton != null) songTopButton.contextMenu = newChilds; return newChilds; } From b4af2dad1b2a233226a33ab6d68229453c1a6ae2 Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Tue, 7 Oct 2025 21:47:36 +0100 Subject: [PATCH 03/10] context menus inside context menus and wip sliders in context menu --- assets/languages/en/Editors.xml | 6 +- source/funkin/editors/charter/Charter.hx | 31 +++++-- source/funkin/editors/ui/UIContextMenu.hx | 107 ++++++++++++++++++++-- 3 files changed, 129 insertions(+), 15 deletions(-) diff --git a/assets/languages/en/Editors.xml b/assets/languages/en/Editors.xml index 95497e254..4ceddbd10 100644 --- a/assets/languages/en/Editors.xml +++ b/assets/languages/en/Editors.xml @@ -237,9 +237,9 @@ Go forward to the end Add camera on Opponent Add camera on Player - Mute instrumental - Mute voices - Mute hitsounds + Instrumental volume + Voices volume + Hitsounds volume diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 98f3fe14c..babf11561 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1861,6 +1861,9 @@ class Charter extends UIState { for (strumLine in strumLines.members) strumLine.hitsounds = !strumLine.hitsounds; t.icon = _hitsoundsEnabled ? 0 : 1; } + function _song_hitsoundvolume(t) { + hitsound.volume = t.slider.value; + } function _playback_back(_) { if (FlxG.sound.music.playing) return; Conductor.songPosition -= (Conductor.beatsPerMeasure * __crochet); @@ -2069,18 +2072,34 @@ class Charter extends UIState { newChilds.push({ - label: translate("song.muteInst"), - onSelect: _song_muteinst + label: translate("song.instVolume"), + onSelect: _song_muteinst, + slider: { + min: 0, + max: 1, + value: 1 + } }); newChilds.push({ - label: translate("song.muteVoices"), - onSelect: _song_mutevoices + label: translate("song.voicesVolume"), + onSelect: _song_mutevoices, + slider: { + min: 0, + max: 1, + value: 1 + } }); newChilds.push({ - label: translate("song.muteHitsounds"), - onSelect: _song_mutehitsounds + label: translate("song.hitsoundsVolume"), + onSelect: _song_mutehitsounds, + slider: { + min: 0, + max: 1, + value: 1, + onChange: _song_hitsoundvolume + } }); if (songTopButton != null) songTopButton.contextMenu = newChilds; diff --git a/source/funkin/editors/ui/UIContextMenu.hx b/source/funkin/editors/ui/UIContextMenu.hx index dcd8d0af3..31a7f71a9 100644 --- a/source/funkin/editors/ui/UIContextMenu.hx +++ b/source/funkin/editors/ui/UIContextMenu.hx @@ -16,6 +16,12 @@ class UIContextMenu extends MusicBeatSubstate { public var contextMenuOptions:Array = []; public var separators:Array = []; + public var childContextMenu:UIContextMenu = null; + public var parentContextMenu:UIContextMenu = null; + private var childContextMenuOptionIndex:Int = -1; + @:allow(funkin.editors.ui.UIContextMenu) + private var lastHoveredOptionIndex:Int = -1; + var scroll:Float = 0.0; var flipped:Bool = false; @@ -105,12 +111,12 @@ class UIContextMenu extends MusicBeatSubstate { if (callback != null) callback(this, index, option); if (option.closeOnSelect == null ? true : option.closeOnSelect) - close(); + closeWithParents(); } public override function update(elapsed:Float) { - if (__oobDeletion && FlxG.mouse.justPressed && !bg.hoveredByChild) - close(); + if (__oobDeletion && FlxG.mouse.justPressed && !bg.hoveredByChild && !hoveringAnyChildren()) + closeWithParents(); __oobDeletion = true; @@ -121,6 +127,14 @@ class UIContextMenu extends MusicBeatSubstate { contextCam.scroll.y = CoolUtil.fpsLerp(contextCam.scroll.y, scroll, 0.5); contextCam.alpha = CoolUtil.fpsLerp(contextCam.alpha, 1, 0.25); + + if (parentContextMenu != null) { + if (hoveringAnyParents() && parentContextMenu.lastHoveredOptionIndex != parentContextMenu.childContextMenuOptionIndex) { + closeWithChildren(); + parentContextMenu.childContextMenuOptionIndex = -1; + } + } + } public override function destroy() { @@ -129,6 +143,51 @@ class UIContextMenu extends MusicBeatSubstate { if (UIState.state.curContextMenu == this) UIState.state.curContextMenu = null; } + + public function openChildContextMenu(optionSpr:UIContextMenuOptionSpr) { + var index = contextMenuOptions.indexOf(optionSpr); + if (index != childContextMenuOptionIndex) { + childContextMenuOptionIndex = index; + var child = new UIContextMenu(optionSpr.option.childs, null, optionSpr.x + optionSpr.bWidth, optionSpr.y); + persistentDraw = true; + persistentUpdate = true; + child.parentContextMenu = this; + childContextMenu = child; + openSubState(child); + } + } + public function closeWithParents() { + close(); + if (parentContextMenu != null) { + parentContextMenu.closeWithParents(); + } + } + public function closeWithChildren() { + if (childContextMenu != null) { + childContextMenu.closeWithChildren(); + } + close(); + } + public function hoveringAnyParents() { + if (parentContextMenu != null) { + return parentContextMenu.bg.hoveredByChild || parentContextMenu.hoveringAnyParents(); + } + return false; + } + public function hoveringAnyChildren() { + if (childContextMenu != null) { + return childContextMenu.bg.hoveredByChild || childContextMenu.hoveringAnyChildren(); + } + return false; + } +} + +typedef UIContextMenuSliderOptionData = { + var min:Float; + var max:Float; + var value:Float; + var ?width:Float; + var ?onChange:UIContextMenuOption->Void; } typedef UIContextMenuCallback = UIContextMenu->Int->UIContextMenuOption->Void; @@ -144,6 +203,7 @@ typedef UIContextMenuOption = { var ?button:UIContextMenuOptionSpr; var ?onCreate:UIContextMenuOptionSpr->Void; var ?childs:Array; + var ?slider:UIContextMenuSliderOptionData; } class UIContextMenuOptionSpr extends UISliceSprite { @@ -151,6 +211,7 @@ class UIContextMenuOptionSpr extends UISliceSprite { public var labelKeybind:UIText; public var icon:FlxSprite; public var option:UIContextMenuOption; + public var slider:UISlider = null; var parent:UIContextMenu; @@ -188,12 +249,33 @@ class UIContextMenuOptionSpr extends UISliceSprite { labelKeybind.alpha = 0.75; } - super(x, y, labelKeybind != null ? Std.int(labelKeybind.x + labelKeybind.frameWidth + 10) : (label.frameWidth + 22), label.frameHeight, 'editors/ui/menu-item'); + if (option.childs != null) { + labelKeybind = new UIText(label.x + label.frameWidth + 10, 2, 0, ">"); + } + + if (option.slider != null) { + slider = new UISlider(0, 0, option.slider.width != null ? Std.int(option.slider.width) : 120, option.slider.value, + [{start: option.slider.min, end: option.slider.max, size: option.slider.max-option.slider.min}], false); + + slider.onChange = function(v) { + option.slider.value = v; + }; + slider.value = option.slider.value; + } + + var w:Int = labelKeybind != null ? Std.int(labelKeybind.x + labelKeybind.frameWidth + 10) : (label.frameWidth + 22); + if (slider != null) { + w += 120 + slider.barWidth; + } + + super(x, y, w, label.frameHeight, 'editors/ui/menu-item'); members.push(label); if (icon != null) members.push(icon); if (labelKeybind != null) members.push(labelKeybind); + if (slider != null) + members.push(slider); } public override function draw() { @@ -205,12 +287,25 @@ class UIContextMenuOptionSpr extends UISliceSprite { icon.follow(this, 0, 0); if (labelKeybind != null) labelKeybind.follow(this, bWidth - 10 - labelKeybind.frameWidth, 2); + if (slider != null) + slider.follow(this, bWidth - 18 - slider.barWidth - slider.endText.width, 5); super.draw(); } public override function onHovered() { super.onHovered(); - if (FlxG.mouse.justReleased) - parent.select(option); + + parent.lastHoveredOptionIndex = parent.contextMenuOptions.indexOf(this); + + if (option.slider == null) { //TODO fix this logic cuz its stupid + if (option.childs != null) { + parent.openChildContextMenu(this); + } else { + if (FlxG.mouse.justReleased) + parent.select(option); + } + } else { + + } } } \ No newline at end of file From e25d706453a0255bff319655c3e0f938fec246ff Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Sun, 12 Oct 2025 08:48:19 +0100 Subject: [PATCH 04/10] wip volume slider stuff --- assets/images/editors/ui/context-icons.png | Bin 804 -> 1038 bytes assets/languages/en/Editors.xml | 9 +- source/funkin/editors/charter/Charter.hx | 44 +++-- .../editors/charter/CharterStrumline.hx | 61 ++++-- source/funkin/editors/ui/UIContextMenu.hx | 177 +++++++++++++----- 5 files changed, 202 insertions(+), 89 deletions(-) diff --git a/assets/images/editors/ui/context-icons.png b/assets/images/editors/ui/context-icons.png index b7411d02d04d6ab4e33560a393a918b0aab7dcc7..68f8976e517a08656d5a4b8dfb35dc6238e1bff7 100644 GIT binary patch delta 943 zcmV;g15o^=295|UiBL{Q4GJ0x0000DNk~Le0002A0000K2m=5B022@A?f?J)#!yUD zMF0Q*kugk>Km~sQ000000OscA$;ru~2#unqA^!jX|HQ=q|Nm+L0G0ov|WfLUiW48<^5l3?j<1wfpM_y`f*RJ!>Rhz08!AvVascG{I=IpudLVa zK%UnQ*a&^^B>|La*N**}J7JGlQBVYF%53zKj=C`SqYPY*JU>cwaa00n%6xWqHm!qh z)Pb66FIkzjM1P4SFCMV5UK90g-fG38A@lwHeF2&#_-O&H;OKPe=Btm(IOL|OCItyHJDWpiTUOo@+i)k1=>>c{9KTjU}oVu zhJ}PZ_`=4`k6&&_T7`xOXhRKV6_FP5l2A%F1!XkMe0lk7bw>nd(e&T{NVVfB+yy!n zY7v>zzJI=(kvEKerJ136=qhtPbhYE^!k55t4!8g`JV0lAyuhpmM3c!Hc_+QV!rq13dz8eOyDc0B10MHwRV0U92lm0>1O$0Ug+?_<*KNS>h<=&g@DfhP0ZfQUh9 zq*o*5c3fv2AY{NXS!j5O%$Y$QCX%T0J`E$^JH)jDz3t^9&~|S?qw*Wk>9{I)P)YKm~sQ000000HUTL($^fJ2#o;781M3lmH(r+0s;&S3g4H_C65)u*w1O(t-UKbY^F)=X?4h{kW0=F0#78Vu-1qBrq6%-T{ z6B833@0b7p0013yQchC<0RjUA1qKHQ2?`4g4Gs?w5fYOQ0TF)!NklA!vM;?avoG)eUUOVcB?ZV5n%0~PEBY_;NyrJ&X`{2)B&khI9Q~(h zLpPIT0CH>o1t4Bf3>#=^J|V2g^p_2G!*a-wW{Zk=g}A(-?s~nR2jRW}l85Hb5e^5U z^5||hNCVx)VxfOvQl}W-w82-(#75e3NpvpoX0?Jm#Klf9bzvA!FrHclZkfe0X6zuRfU*f9_{y=dAsQ7H<;Vo-0b=ZpZC7(>E^N0dl3?D+O?SHP0@z@w?G4qw%g+m+l;P4>M=gQT%oFT(lhwArX<}&5J z+%WW4z6?Xg@l|zM6;|A#uf+jw(BPM|E34AwsWclcN3UDZ_zSTkko=`$slxyO002ov JPDHLkV1gkDF@pdA diff --git a/assets/languages/en/Editors.xml b/assets/languages/en/Editors.xml index 4ceddbd10..d2a168784 100644 --- a/assets/languages/en/Editors.xml +++ b/assets/languages/en/Editors.xml @@ -237,9 +237,9 @@ Go forward to the end Add camera on Opponent Add camera on Player - Instrumental volume - Voices volume - Hitsounds volume + Instrumental + Voices + Hitsounds @@ -310,8 +310,9 @@ Options ↓ + Waveforms Hitsounds - Mute Vocals + Vocals Edit Delete diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index babf11561..da955521b 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1846,6 +1846,7 @@ class Charter extends UIState { function _playback_metronome(t) { t.icon = (Options.charterMetronomeEnabled = !Options.charterMetronomeEnabled) ? 1 : 0; } + /* function _song_muteinst(t) { FlxG.sound.music.volume = FlxG.sound.music.volume > 0 ? 0 : 1; t.icon = 1 - Std.int(Math.ceil(FlxG.sound.music.volume)); @@ -1861,8 +1862,20 @@ class Charter extends UIState { for (strumLine in strumLines.members) strumLine.hitsounds = !strumLine.hitsounds; t.icon = _hitsoundsEnabled ? 0 : 1; } + */ + + function _song_instvolume(t) { + FlxG.sound.music.volume = t.slider.value; + t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); + } + function _song_voicesvolume(t) { + vocals.volume = t.slider.value; + for (strumLine in strumLines.members) strumLine.vocals.volume = t.slider.value; //TODO: fix to multiply with other strumline specific volume + t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); + } function _song_hitsoundvolume(t) { hitsound.volume = t.slider.value; + t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); } function _playback_back(_) { if (FlxG.sound.music.playing) return; @@ -2070,36 +2083,37 @@ class Charter extends UIState { newChilds.push(null); } - newChilds.push({ - label: translate("song.instVolume"), - onSelect: _song_muteinst, + label: translate("song.inst"), slider: { min: 0, max: 1, - value: 1 - } + value: 1, + onChange: _song_instvolume + }, + icon: 7 }); newChilds.push({ - label: translate("song.voicesVolume"), - onSelect: _song_mutevoices, + label: translate("song.voices"), slider: { min: 0, max: 1, - value: 1 - } + value: 1, + onChange: _song_voicesvolume + }, + icon: 7 }); newChilds.push({ - label: translate("song.hitsoundsVolume"), - onSelect: _song_mutehitsounds, + label: translate("song.hitsounds"), slider: { min: 0, max: 1, value: 1, onChange: _song_hitsoundvolume - } + }, + icon: 7 }); if (songTopButton != null) songTopButton.contextMenu = newChilds; @@ -2388,7 +2402,7 @@ class Charter extends UIState { } public inline function hitsoundsEnabled(id:Int) - return strumLines.members[id] != null && strumLines.members[id].hitsounds; + return strumLines.members[id] != null && strumLines.members[id].hitsoundVolume > 0; public inline function __fixSelection(selection:Selection):Selection { var newSelection:Selection = new Selection(); @@ -2479,7 +2493,7 @@ class Charter extends UIState { quantSelected: quant, noteTypeSelected: noteType, strumlinesDraggable: strumLines.draggable, - hitSounds: [for (strumLine in strumLines.members) strumLine.hitsounds], + hitSounds: [for (strumLine in strumLines.members) strumLine.hitsoundVolume > 0], mutedVocals: [for (strumLine in strumLines.members) !(strumLine.vocals.volume > 0)], waveforms: [for (strumLine in strumLines.members) strumLine.selectedWaveform] } @@ -2495,7 +2509,7 @@ class Charter extends UIState { strumLines.draggable = playtestInfo.strumlinesDraggable; for (i => strumLine in strumLines.members) - strumLine.hitsounds = playtestInfo.hitSounds[i]; + strumLine.hitsoundVolume = playtestInfo.hitSounds[i] ? 1 : 0; for (i => strumLine in strumLines.members) strumLine.vocals.volume = playtestInfo.mutedVocals[i] ? 0 : 1; for (i => strumLine in strumLines.members) diff --git a/source/funkin/editors/charter/CharterStrumline.hx b/source/funkin/editors/charter/CharterStrumline.hx index 2d37e0a52..ea914cd2d 100644 --- a/source/funkin/editors/charter/CharterStrumline.hx +++ b/source/funkin/editors/charter/CharterStrumline.hx @@ -1,5 +1,6 @@ package funkin.editors.charter; +import funkin.editors.ui.UIContextMenu.UIContextMenuOption; import flixel.util.FlxColor; import flixel.group.FlxSpriteGroup; import flixel.sound.FlxSound; @@ -11,7 +12,7 @@ import funkin.game.HealthIcon; class CharterStrumline extends UISprite { public var strumLine:ChartStrumLine; - public var hitsounds:Bool = true; + public var hitsoundVolume:Float = 1; public var draggingSprite:UISprite; public var healthIcons:FlxSpriteGroup; @@ -24,6 +25,7 @@ class CharterStrumline extends UISprite { public var curMenu:UIContextMenu = null; public var vocals:FlxSound; + public var hasVocals:Bool = false; public var keyCount:Int = 4; public var startingID(get, null):Int; @@ -143,9 +145,11 @@ class CharterStrumline extends UISprite { if (asset != null) { vocals.reset(); vocals.loadEmbedded(asset); + hasVocals = true; } else { vocals.destroy(); + hasVocals = false; } vocals.group = FlxG.sound.defaultMusicGroup; @@ -179,17 +183,16 @@ class CharterStrumlineOptions extends UITopMenuButton { contextMenu = [ { label: TU.translate("charter.strumLine.hitsounds"), - onSelect: function(_) { - strLine.hitsounds = !strLine.hitsounds; + slider: { + min: 0, + max: 1, + value: strLine.hitsoundVolume, + onChange: function(t) { + strLine.hitsoundVolume = t.slider.value; + t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); + } }, - icon: strLine.hitsounds ? 1 : 0 - }, - { - label: TU.translate("charter.strumLine.muteVocals"), - onSelect: function(_) { - strLine.vocals.volume = strLine.vocals.volume > 0 ? 0 : 1; - }, - icon: strLine.vocals.volume > 0 ? 0 : 1 + icon: 7 }, null, { @@ -210,20 +213,42 @@ class CharterStrumlineOptions extends UITopMenuButton { } ]; - contextMenu.insert(0, { - label: TU.translate("charter.strumLine.noWaveform"), - onSelect: function(_) {strLine.selectedWaveform = -1;}, - icon: strLine.selectedWaveform == -1 ? 1 : 0 - }); + if (strLine.hasVocals) { + contextMenu.insert(1, { + label: TU.translate("charter.strumLine.vocals"), + slider: { + min: 0, + max: 1, + value: strLine.vocals.volume, + onChange: function(t) { + strLine.vocals.volume = t.slider.value; + t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); + } + }, + icon: 7 + }); + } + + var waveformOptions:Array = [ + { + label: TU.translate("charter.strumLine.noWaveform"), + onSelect: function(_) {strLine.selectedWaveform = -1;}, + icon: strLine.selectedWaveform == -1 ? 1 : 0 + } + ]; for (i => name in Charter.waveformHandler.waveformList) - contextMenu.insert(1+i, { + waveformOptions.push({ label: name, onSelect: function(_) {strLine.selectedWaveform = i;}, icon: strLine.selectedWaveform == i ? 6 : 5 }); - contextMenu.insert(1+Charter.waveformHandler.waveformList.length, null); + contextMenu.insert(0, { + label: TU.translate("charter.strumLine.waveforms"), + childs: waveformOptions + }); + contextMenu.insert(1, null); var cam = Charter.instance.charterCamera; var point = CoolUtil.worldToScreenPosition(this, cam); diff --git a/source/funkin/editors/ui/UIContextMenu.hx b/source/funkin/editors/ui/UIContextMenu.hx index 31a7f71a9..ade327c3d 100644 --- a/source/funkin/editors/ui/UIContextMenu.hx +++ b/source/funkin/editors/ui/UIContextMenu.hx @@ -102,6 +102,10 @@ class UIContextMenu extends MusicBeatSubstate { for(o in separators) o.x -= bg.bWidth; } + + for(o in contextMenuOptions) { + o.postCreate(); + } } public function select(option:UIContextMenuOption) { @@ -188,6 +192,8 @@ typedef UIContextMenuSliderOptionData = { var value:Float; var ?width:Float; var ?onChange:UIContextMenuOption->Void; + var ?showValues:Bool; + var ?sameLine:Bool; } typedef UIContextMenuCallback = UIContextMenu->Int->UIContextMenuOption->Void; @@ -206,76 +212,121 @@ typedef UIContextMenuOption = { var ?slider:UIContextMenuSliderOptionData; } +enum abstract UIContextMenuOptionType(Int) from Int { + var DEFAULT = 0; + var SUBMENU = 1; + var SLIDER = 2; +} + class UIContextMenuOptionSpr extends UISliceSprite { public var label:UIText; public var labelKeybind:UIText; public var icon:FlxSprite; public var option:UIContextMenuOption; + public var optionType:UIContextMenuOptionType = DEFAULT; + public var slider:UISlider = null; var parent:UIContextMenu; + private var _lastIcon:Int = 0; + public function new(x:Float, y:Float, option:UIContextMenuOption, parent:UIContextMenu) { label = new UIText(20, 2, 0, option.label); this.option = option; this.parent = parent; this.color = option.color; - if (option.icon != null && option.icon > 0) { - icon = new FlxSprite(0, 0).loadGraphic(Paths.image('editors/ui/context-icons'), true, 20, 20); - icon.animation.add('icon', [option.icon-1], 0, true); - icon.animation.play('icon'); - } + var w:Int = label.frameWidth + 22; + var h:Int = label.frameHeight; - if (option.keybinds == null) { - if (option.keybind != null) { - option.keybinds = [option.keybind]; - } - } + if (option.childs != null) optionType = SUBMENU; + if (option.slider != null) optionType = SLIDER; - if (option.keybinds != null || option.keybindText != null) { - var text = if(option.keybindText == null) { - var textKeys:Array = []; - for (o in option.keybinds[0]) { - if (Std.int(o) > 0) { - textKeys.push(o.toUIString()); + switch(optionType) { + + case SUBMENU: + labelKeybind = new UIText(label.x + label.frameWidth + 10, 2, 0, ">"); + case SLIDER: + labelKeybind = new UIText(label.x + label.frameWidth + 10, 2, 0, ""); + //slider needs to be created after so that it can match the menu width (when not on the same line) + if (option.slider.sameLine != null && option.slider.sameLine) { + var sliderWidth = option.slider.width != null ? Std.int(option.slider.width) : 120; + w += 120 + slider.barWidth; + } else { + h *= 2; + } + + default: + if (option.keybinds == null) { + if (option.keybind != null) { + option.keybinds = [option.keybind]; } } - textKeys.join("+"); - } else { - option.keybindText; - } - labelKeybind = new UIText(label.x + label.frameWidth + 10, 2, 0, text); - labelKeybind.alpha = 0.75; - } - - if (option.childs != null) { - labelKeybind = new UIText(label.x + label.frameWidth + 10, 2, 0, ">"); - } - if (option.slider != null) { - slider = new UISlider(0, 0, option.slider.width != null ? Std.int(option.slider.width) : 120, option.slider.value, - [{start: option.slider.min, end: option.slider.max, size: option.slider.max-option.slider.min}], false); + if (option.keybinds != null || option.keybindText != null) { + var text = if(option.keybindText == null) { + var textKeys:Array = []; + for (o in option.keybinds[0]) { + if (Std.int(o) > 0) { + textKeys.push(o.toUIString()); + } + } + textKeys.join("+"); + } else { + option.keybindText; + } + labelKeybind = new UIText(label.x + label.frameWidth + 10, 2, 0, text); + labelKeybind.alpha = 0.75; - slider.onChange = function(v) { - option.slider.value = v; - }; - slider.value = option.slider.value; - } - - var w:Int = labelKeybind != null ? Std.int(labelKeybind.x + labelKeybind.frameWidth + 10) : (label.frameWidth + 22); - if (slider != null) { - w += 120 + slider.barWidth; + w = Std.int(labelKeybind.x + labelKeybind.frameWidth + 10); + } } - super(x, y, w, label.frameHeight, 'editors/ui/menu-item'); + super(x, y, w, h, 'editors/ui/menu-item'); + members.push(label); - if (icon != null) - members.push(icon); + updateIcon(); + if (labelKeybind != null) - members.push(labelKeybind); - if (slider != null) - members.push(slider); + members.push(labelKeybind); + } + + //Called after all options are created and the context menu width/height is final + public function postCreate() { + switch(optionType) { + case SLIDER: + + var sliderWidth = bWidth-50; + if (option.slider.sameLine != null && option.slider.sameLine) { + option.slider.width != null ? Std.int(option.slider.width) : 120; + } + + slider = new UISlider(0, 0, sliderWidth, option.slider.value, + [{start: option.slider.min, end: option.slider.max, size: option.slider.max-option.slider.min}], false); + + slider.onChange = function(v) { + option.slider.value = v; + if (option.slider.onChange != null) option.slider.onChange(option); + updateIcon(); //check if icon has changed + @:privateAccess + labelKeybind.text = '${CoolUtil.quantize(slider.__barProgress * 100, 1)}%'; + }; + slider.value = option.slider.value; + + if (option.slider.showValues == null || !option.slider.showValues) { + slider.startText.visible = false; + slider.endText.visible = false; + slider.valueStepper.visible = false; + slider.valueStepper.selectable = false; + } + + members.push(slider); + case SUBMENU: + + default: + + } } public override function draw() { @@ -287,8 +338,13 @@ class UIContextMenuOptionSpr extends UISliceSprite { icon.follow(this, 0, 0); if (labelKeybind != null) labelKeybind.follow(this, bWidth - 10 - labelKeybind.frameWidth, 2); - if (slider != null) - slider.follow(this, bWidth - 18 - slider.barWidth - slider.endText.width, 5); + if (slider != null) { + if (option.slider.sameLine != null && option.slider.sameLine) { + slider.follow(this, bWidth - 18 - slider.barWidth - (slider.endText.visible ? slider.endText.width : 0), 5); + } else { + slider.follow(this, 20, 5 + label.frameHeight); + } + } super.draw(); } @@ -297,15 +353,32 @@ class UIContextMenuOptionSpr extends UISliceSprite { parent.lastHoveredOptionIndex = parent.contextMenuOptions.indexOf(this); - if (option.slider == null) { //TODO fix this logic cuz its stupid - if (option.childs != null) { + switch(optionType) { + case SUBMENU: parent.openChildContextMenu(this); - } else { + case SLIDER: + + default: if (FlxG.mouse.justReleased) parent.select(option); + } + } + + public function updateIcon() { + var currentIcon = option.icon != null ? option.icon : 0; + + if (_lastIcon != currentIcon) { + _lastIcon = currentIcon; + if (icon == null) { + icon = new FlxSprite(0, 0).loadGraphic(Paths.image('editors/ui/context-icons'), true, 20, 20); + members.push(icon); + } + icon.visible = currentIcon > 0; + + if (currentIcon > 0) { + icon.animation.add('icon', [currentIcon-1], 0, true); + icon.animation.play('icon'); } - } else { - } } } \ No newline at end of file From fffc404f8cca45e64b1d92e372ede8cabbe5f945 Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Tue, 14 Oct 2025 19:40:55 +0100 Subject: [PATCH 05/10] strumline preview fix with resizable editors --- .../charter/CharterPreviewStrumLine.hx | 4 +- .../editors/charter/CharterStrumlineScreen.hx | 42 ++++++++++++++++--- source/funkin/game/StrumLine.hx | 3 ++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/source/funkin/editors/charter/CharterPreviewStrumLine.hx b/source/funkin/editors/charter/CharterPreviewStrumLine.hx index 91aa5ccad..22e104683 100644 --- a/source/funkin/editors/charter/CharterPreviewStrumLine.hx +++ b/source/funkin/editors/charter/CharterPreviewStrumLine.hx @@ -41,7 +41,7 @@ class CharterPreviewStrumLine extends FlxTypedGroup add(note); } - var noteTime:Float = FlxG.height; + var noteTime:Float = FlxG.initialHeight; var scroll:Float = 1.0; public function updatePos(x:Float, y:Float, scale:Float, spacing:Float, keyCount:Int, scrollSpeed:Float){ @@ -61,7 +61,7 @@ class CharterPreviewStrumLine extends FlxTypedGroup scroll = CoolUtil.fpsLerp(scroll, scrollSpeed, 0.2); noteTime -= FlxG.elapsed * scroll * 1000 * 0.45; if (noteTime <= 0.0) - noteTime = FlxG.height; + noteTime = FlxG.initialHeight; note.x = members[0].x; note.y = members[0].y + noteTime; diff --git a/source/funkin/editors/charter/CharterStrumlineScreen.hx b/source/funkin/editors/charter/CharterStrumlineScreen.hx index a6beb4ad7..501317c64 100644 --- a/source/funkin/editors/charter/CharterStrumlineScreen.hx +++ b/source/funkin/editors/charter/CharterStrumlineScreen.hx @@ -33,6 +33,8 @@ class CharterStrumlineScreen extends UISubstateWindow { public var strumLineCam:HudCamera; public var previewStrumLine:CharterPreviewStrumLine; + public var previewBorder:Array = []; + private final borderGap:Int = 5; private var onSave:ChartStrumLine -> Void = null; @@ -176,20 +178,30 @@ class CharterStrumlineScreen extends UISubstateWindow { addLabelOn(vocalsSuffixDropDown, TU.translate("charterStrumLine.vocalSuffix")); keyCountStepper = new UINumericStepper(stagePositionDropdown.x, vocalsSuffixDropDown.y, strumLine.keyCount != null ? strumLine.keyCount : 4, 1, 0, 1, 1000, 84); - // if (Flags.CHARTER_ADVANCED_SETTINGS) { - add(keyCountStepper); - addLabelOn(keyCountStepper, TU.translate("charterStrumLine.keyCount")); - // } + add(keyCountStepper); + addLabelOn(keyCountStepper, TU.translate("charterStrumLine.keyCount")); strumLineCam = new HudCamera(); strumLineCam.downscroll = Options.downscroll; strumLineCam.bgColor = 0; strumLineCam.alpha = 0; FlxG.cameras.add(strumLineCam, false); + updateStrumlineCam(FlxG.width, FlxG.height); + previewStrumLine = new CharterPreviewStrumLine(0, 0, 0, 1, 4, 0); previewStrumLine.camera = strumLineCam; add(previewStrumLine); FlxTween.tween(strumLineCam, {alpha: 1}, 0.25, {ease: FlxEase.cubeOut}); + + //preview border + previewBorder.push(new FlxSprite(-borderGap, -borderGap).makeSolid(FlxG.initialWidth + (borderGap*2), borderGap, 0x88FFFFFF)); + previewBorder.push(new FlxSprite(-borderGap, 0).makeSolid(borderGap, FlxG.initialHeight, 0x88FFFFFF)); + previewBorder.push(new FlxSprite(FlxG.initialWidth, 0).makeSolid(borderGap, FlxG.initialHeight, 0x88FFFFFF)); + previewBorder.push(new FlxSprite(-borderGap, FlxG.initialHeight).makeSolid(FlxG.initialWidth + (borderGap*2), borderGap, 0x88FFFFFF)); + for (border in previewBorder) { + border.camera = strumLineCam; + add(border); + } } function saveStrumline() { @@ -222,7 +234,7 @@ class CharterStrumlineScreen extends UISubstateWindow { previewStrumLine.visible = visibleCheckbox.checked; - var xOffset:Float = StrumLine.calculateStartingXPos(hudXStepper.value, hudScaleStepper.value, hudSpacingStepper.value, Std.int(keyCountStepper.value)); + var xOffset:Float = StrumLine.calculateStartingXPosFromInitialWidth(hudXStepper.value, hudScaleStepper.value, hudSpacingStepper.value, Std.int(keyCountStepper.value)); previewStrumLine.updatePos(xOffset, hudYStepper.value, hudScaleStepper.value, hudSpacingStepper.value, Std.int(keyCountStepper.value), scrollSpeed); super.update(elapsed); @@ -233,6 +245,26 @@ class CharterStrumlineScreen extends UISubstateWindow { FlxTween.cancelTweensOf(strumLineCam); FlxG.cameras.remove(strumLineCam); } + + public override function onResize(width:Int, height:Int) { + super.onResize(width, height); + if (!UIState.resolutionAware) return; + + if ((width < FlxG.initialWidth || height < FlxG.initialHeight) && !Options.bypassEditorsResize) { + width = FlxG.initialWidth; height = FlxG.initialHeight; + } + + updateStrumlineCam(width, height); + } + + private function updateStrumlineCam(windowWidth:Int, windowHeight:Int) { + strumLineCam.width = FlxG.initialWidth + (borderGap*2); + strumLineCam.height = FlxG.initialHeight + (borderGap*2); + strumLineCam.x = (windowWidth/2) - (strumLineCam.width/2); + strumLineCam.y = (windowHeight/2) - (strumLineCam.height/2); + strumLineCam.scroll.x = -borderGap; + strumLineCam.scroll.y = -borderGap; + } } class CharacterButton extends UIButton { diff --git a/source/funkin/game/StrumLine.hx b/source/funkin/game/StrumLine.hx index ae5303b8c..f814cdec3 100644 --- a/source/funkin/game/StrumLine.hx +++ b/source/funkin/game/StrumLine.hx @@ -420,6 +420,9 @@ class StrumLine extends FlxTypedGroup { public static inline function calculateStartingXPos(hudXRatio:Float, scale:Float, spacing:Float, keyCount:Int) { return (FlxG.width * hudXRatio) - ((Note.swagWidth * scale * ((keyCount/2)-0.5) * spacing) + Note.swagWidth * 0.5 * scale); } + public static inline function calculateStartingXPosFromInitialWidth(hudXRatio:Float, scale:Float, spacing:Float, keyCount:Int) { + return (FlxG.initialWidth * hudXRatio) - ((Note.swagWidth * scale * ((keyCount/2)-0.5) * spacing) + Note.swagWidth * 0.5 * scale); + } /** * SETTERS & GETTERS From d17de87d660cf5369db4713538473c16aa1ae171 Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Tue, 14 Oct 2025 20:41:14 +0100 Subject: [PATCH 06/10] more slider stuff --- source/funkin/editors/charter/Charter.hx | 34 +++++------ source/funkin/editors/charter/CharterNote.hx | 5 +- .../editors/charter/CharterStrumline.hx | 2 + source/funkin/editors/ui/UIContextMenu.hx | 58 ++++++++++++++----- 4 files changed, 62 insertions(+), 37 deletions(-) diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index da955521b..dbcbbe41a 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -77,6 +77,7 @@ class Charter extends UIState { public var strumlineLockButton:CharterStrumlineButton; public var hitsound:FlxSound; + public var hitsoundGlobalVolume:Float = 1.0; public var metronome:FlxSound; public var vocals:FlxSound; @@ -1846,23 +1847,11 @@ class Charter extends UIState { function _playback_metronome(t) { t.icon = (Options.charterMetronomeEnabled = !Options.charterMetronomeEnabled) ? 1 : 0; } - /* - function _song_muteinst(t) { - FlxG.sound.music.volume = FlxG.sound.music.volume > 0 ? 0 : 1; - t.icon = 1 - Std.int(Math.ceil(FlxG.sound.music.volume)); - } - function _song_mutevoices(t) { - vocals.volume = vocals.volume > 0 ? 0 : 1; - for (strumLine in strumLines.members) strumLine.vocals.volume = strumLine.vocals.volume > 0 ? 0 : 1; - t.icon = 1 - Std.int(Math.ceil(vocals.volume)); - } - var _hitsoundsEnabled = true; - function _song_mutehitsounds(t) { - _hitsoundsEnabled = !_hitsoundsEnabled; - for (strumLine in strumLines.members) strumLine.hitsounds = !strumLine.hitsounds; - t.icon = _hitsoundsEnabled ? 0 : 1; + + public function _slider_mutetoggle(t:UIContextMenuOption) { + if (t.slider == null) return; + t.button.slider.value = t.button.slider.value > 0 ? 0 : 1; } - */ function _song_instvolume(t) { FlxG.sound.music.volume = t.slider.value; @@ -1874,7 +1863,7 @@ class Charter extends UIState { t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); } function _song_hitsoundvolume(t) { - hitsound.volume = t.slider.value; + hitsoundGlobalVolume = t.slider.value; t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); } function _playback_back(_) { @@ -2091,6 +2080,7 @@ class Charter extends UIState { value: 1, onChange: _song_instvolume }, + onIconClick: _slider_mutetoggle, icon: 7 }); @@ -2102,6 +2092,7 @@ class Charter extends UIState { value: 1, onChange: _song_voicesvolume }, + onIconClick: _slider_mutetoggle, icon: 7 }); @@ -2113,6 +2104,7 @@ class Charter extends UIState { value: 1, onChange: _song_hitsoundvolume }, + onIconClick: _slider_mutetoggle, icon: 7 }); @@ -2401,8 +2393,12 @@ class Charter extends UIState { } } - public inline function hitsoundsEnabled(id:Int) - return strumLines.members[id] != null && strumLines.members[id].hitsoundVolume > 0; + public inline function playHitsound(id:Int) { + if (strumLines.members[id] != null && strumLines.members[id].hitsoundVolume > 0 && hitsoundGlobalVolume > 0) { + hitsound.volume = hitsoundGlobalVolume * strumLines.members[id].hitsoundVolume; + hitsound.replay(); + } + } public inline function __fixSelection(selection:Selection):Selection { var newSelection:Selection = new Selection(); diff --git a/source/funkin/editors/charter/CharterNote.hx b/source/funkin/editors/charter/CharterNote.hx index 2376392f9..8bece2b4a 100644 --- a/source/funkin/editors/charter/CharterNote.hx +++ b/source/funkin/editors/charter/CharterNote.hx @@ -161,8 +161,9 @@ class CharterNote extends UISprite implements ICharterSelectable { } if (__passed != (__passed = step < Conductor.curStepFloat + (Options.songOffsetAffectEditors ? (Conductor.songOffset / Conductor.stepCrochet) : 0))) { - if (__passed && FlxG.sound.music.playing && Charter.instance.hitsoundsEnabled(strumLineID)) - Charter.instance.hitsound.replay(); + if (__passed && FlxG.sound.music.playing) { + Charter.instance.playHitsound(strumLineID); + } } if (strumLine != null) { diff --git a/source/funkin/editors/charter/CharterStrumline.hx b/source/funkin/editors/charter/CharterStrumline.hx index ea914cd2d..38c93942d 100644 --- a/source/funkin/editors/charter/CharterStrumline.hx +++ b/source/funkin/editors/charter/CharterStrumline.hx @@ -192,6 +192,7 @@ class CharterStrumlineOptions extends UITopMenuButton { t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); } }, + onIconClick: Charter.instance._slider_mutetoggle, icon: 7 }, null, @@ -225,6 +226,7 @@ class CharterStrumlineOptions extends UITopMenuButton { t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); } }, + onIconClick: Charter.instance._slider_mutetoggle, icon: 7 }); } diff --git a/source/funkin/editors/ui/UIContextMenu.hx b/source/funkin/editors/ui/UIContextMenu.hx index ade327c3d..14b3db0bc 100644 --- a/source/funkin/editors/ui/UIContextMenu.hx +++ b/source/funkin/editors/ui/UIContextMenu.hx @@ -152,7 +152,7 @@ class UIContextMenu extends MusicBeatSubstate { var index = contextMenuOptions.indexOf(optionSpr); if (index != childContextMenuOptionIndex) { childContextMenuOptionIndex = index; - var child = new UIContextMenu(optionSpr.option.childs, null, optionSpr.x + optionSpr.bWidth, optionSpr.y); + var child = new UIContextMenu(optionSpr.option.childs, null, optionSpr.x + optionSpr.bWidth + 4, optionSpr.y - 4); persistentDraw = true; persistentUpdate = true; child.parentContextMenu = this; @@ -190,9 +190,12 @@ typedef UIContextMenuSliderOptionData = { var min:Float; var max:Float; var value:Float; - var ?width:Float; var ?onChange:UIContextMenuOption->Void; + //default = 120, ignored if sameLine = false + var ?width:Float; + //disables stepper and text if false, default = false var ?showValues:Bool; + //if true, the slider will be on the same line as the label text, otherwise it will be on the next line below the label var ?sameLine:Bool; } @@ -210,6 +213,7 @@ typedef UIContextMenuOption = { var ?onCreate:UIContextMenuOptionSpr->Void; var ?childs:Array; var ?slider:UIContextMenuSliderOptionData; + var ?onIconClick:UIContextMenuOption->Void; } enum abstract UIContextMenuOptionType(Int) from Int { @@ -221,7 +225,7 @@ enum abstract UIContextMenuOptionType(Int) from Int { class UIContextMenuOptionSpr extends UISliceSprite { public var label:UIText; public var labelKeybind:UIText; - public var icon:FlxSprite; + public var icon:UIContextMenuOptionIcon; public var option:UIContextMenuOption; public var optionType:UIContextMenuOptionType = DEFAULT; @@ -229,8 +233,6 @@ class UIContextMenuOptionSpr extends UISliceSprite { var parent:UIContextMenu; - private var _lastIcon:Int = 0; - public function new(x:Float, y:Float, option:UIContextMenuOption, parent:UIContextMenu) { label = new UIText(20, 2, 0, option.label); this.option = option; @@ -367,18 +369,42 @@ class UIContextMenuOptionSpr extends UISliceSprite { public function updateIcon() { var currentIcon = option.icon != null ? option.icon : 0; - if (_lastIcon != currentIcon) { - _lastIcon = currentIcon; - if (icon == null) { - icon = new FlxSprite(0, 0).loadGraphic(Paths.image('editors/ui/context-icons'), true, 20, 20); - members.push(icon); - } - icon.visible = currentIcon > 0; + if (icon == null && currentIcon > 0) { + members.push(icon = new UIContextMenuOptionIcon(option)); + } + if (icon != null) { + icon.updateIconState(currentIcon); + } + } +} - if (currentIcon > 0) { - icon.animation.add('icon', [currentIcon-1], 0, true); - icon.animation.play('icon'); - } +class UIContextMenuOptionIcon extends UISprite { + private var option:UIContextMenuOption; + private var _lastState:Int = 0; + override public function new(option:UIContextMenuOption) { + super(); + this.option = option; + loadGraphic(Paths.image('editors/ui/context-icons'), true, 20, 20); + selectable = option.onIconClick != null; + cursor = option.onIconClick != null ? CLICK : ARROW; + } + + public function updateIconState(state:Int) { + if (_lastState == state) return; + _lastState = state; + + visible = state > 0; + if (state > 0) { + animation.add('icon', [state-1], 0, true); + animation.play('icon'); + } + } + + public override function onHovered() { + super.onHovered(); + + if (FlxG.mouse.justReleased && option.onIconClick != null) { + option.onIconClick(option); } } } \ No newline at end of file From a67223938536758e9cba56e9f96990c4711ebc7f Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Wed, 15 Oct 2025 06:17:41 +0100 Subject: [PATCH 07/10] editor sfx option should now actually work for everything --- .../editors/character/CharacterAnimButton.hx | 4 +- .../editors/character/CharacterAnimsWindow.hx | 2 +- .../editors/character/CharacterEditor.hx | 8 +-- source/funkin/editors/charter/Charter.hx | 50 +++++++++---------- .../editors/charter/CharterAutoSaveUI.hx | 2 +- source/funkin/editors/stage/StageEditor.hx | 8 +-- source/funkin/editors/ui/UIButton.hx | 2 +- source/funkin/editors/ui/UIDropDown.hx | 2 +- source/funkin/editors/ui/UIState.hx | 11 ++-- source/funkin/editors/ui/UISubstateWindow.hx | 2 +- source/funkin/editors/ui/UITextBox.hx | 8 +-- source/funkin/editors/ui/UIWindow.hx | 2 +- .../options/categories/GameplayOptions.hx | 2 +- 13 files changed, 54 insertions(+), 49 deletions(-) diff --git a/source/funkin/editors/character/CharacterAnimButton.hx b/source/funkin/editors/character/CharacterAnimButton.hx index a9b184a9e..fd400fa99 100644 --- a/source/funkin/editors/character/CharacterAnimButton.hx +++ b/source/funkin/editors/character/CharacterAnimButton.hx @@ -449,12 +449,12 @@ class CharacterAnimButton extends UIButton { public function toggleGhost() { if (valid && parent.ghosts.indexOf(anim) == -1) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARACTER_GHOSTENABLE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_CHARACTER_GHOSTENABLE_SOUND); parent.ghosts.push(anim); ghostIcon.animation.play("alive", true); ghostIcon.color = 0xFFFFFFFF; } else { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARACTER_GHOSTDISABLE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_CHARACTER_GHOSTDISABLE_SOUND); parent.ghosts.remove(anim); ghostIcon.animation.play("dead", true); ghostIcon.color = 0xFFADADAD; diff --git a/source/funkin/editors/character/CharacterAnimsWindow.hx b/source/funkin/editors/character/CharacterAnimsWindow.hx index ae6822eac..6e9c5a015 100644 --- a/source/funkin/editors/character/CharacterAnimsWindow.hx +++ b/source/funkin/editors/character/CharacterAnimsWindow.hx @@ -99,7 +99,7 @@ class CharacterAnimsWindow extends UIButtonList { displayAnimsFramesList.remove(name); public function deleteAnimation(button:CharacterAnimButton, addToUndo:Bool = true) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_DELETE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_DELETE_SOUND); if (buttons.members.length <= 1) return; if (character.getAnimName() == button.anim) @:privateAccess CharacterEditor.instance._animation_down(null); diff --git a/source/funkin/editors/character/CharacterEditor.hx b/source/funkin/editors/character/CharacterEditor.hx index b040d9bd3..efdeb30d8 100644 --- a/source/funkin/editors/character/CharacterEditor.hx +++ b/source/funkin/editors/character/CharacterEditor.hx @@ -453,7 +453,7 @@ class CharacterEditor extends UIState { function _file_save(_) { #if sys - FlxG.sound.play(Paths.sound('editors/save')); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND); CoolUtil.safeSaveFile( '${Paths.getAssetsRoot()}/data/characters/${character.curCharacter}.xml', buildCharacter() @@ -465,7 +465,7 @@ class CharacterEditor extends UIState { } function _file_saveas(_) { - FlxG.sound.play(Paths.sound('editors/save')); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND); openSubState(new SaveSubstate(buildCharacter(), { defaultSaveFile: '${character.curCharacter}.xml' })); @@ -499,7 +499,7 @@ class CharacterEditor extends UIState { } function _undo(undo:CharacterEditorChange) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_UNDO_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_UNDO_SOUND); switch (undo) { case null: // do nothing case CCharEditPosition(oldPos, newPos): @@ -570,7 +570,7 @@ class CharacterEditor extends UIState { } function _redo(redo:CharacterEditorChange) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_REDO_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_REDO_SOUND); switch (redo) { case null: // do nothing case CCharEditPosition(oldPos, newPos): diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index dbcbbe41a..5806ad3ac 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -521,7 +521,7 @@ class Charter extends UIState { strumlineLockButton = new CharterStrumlineButton("editors/charter/lock-strumline", translate("lock-unlock")); strumlineLockButton.onClick = function () { - FlxG.sound.play(Paths.sound(!strumLines.draggable ? Flags.DEFAULT_CHARTER_STRUMUNLOCK_SOUND : Flags.DEFAULT_CHARTER_STRUMLOCK_SOUND)); + UIState.playEditorSound(!strumLines.draggable ? Flags.DEFAULT_CHARTER_STRUMUNLOCK_SOUND : Flags.DEFAULT_CHARTER_STRUMLOCK_SOUND); if (strumLines != null) { strumLines.draggable = !strumLines.draggable; strumlineLockButton.textTweenColor.color = strumLines.draggable ? 0xFF5C95CA : 0xFFE16565; @@ -841,7 +841,7 @@ class Charter extends UIState { else Chart.save(PlayState.SONG, __diff.toLowerCase(), __variant, {saveMetaInChart: true, saveLocalEvents: true, seperateGlobalEvents: true, prettyPrint: Options.editorCharterPrettyPrint}); - FlxG.sound.play(Paths.sound('editors/save')); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND); undos.save(); } autoSaveNotif.cancelled = false; @@ -1001,7 +1001,7 @@ class Charter extends UIState { notesGroup.add(note); selection = [note]; undos.addToUndo(CCreateSelection([note])); - FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARTER_NOTEPLACE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_CHARTER_NOTEPLACE_SOUND); } isSelecting = false; } @@ -1130,7 +1130,7 @@ class Charter extends UIState { if (selected == null) return selected; if (selected is CharterNote) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARTER_NOTEDELETE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_CHARTER_NOTEDELETE_SOUND); var note:CharterNote = cast selected; note.strumLineID = strumLines.members.indexOf(note.strumLine); note.strumLine = null; // For static undos :D @@ -1610,20 +1610,20 @@ class Charter extends UIState { else {undos = null; FlxG.switchState(new CharterSelection()); Charter.instance.__clearStatics();} } - function _file_save_all(_) {saveEverything(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_save(_) {saveChart(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_saveas(_) {saveChartAs(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_events_save(_) {saveEvents(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_events_saveas(_) {saveEventsAs(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_save_no_events(_) {saveChart(true, false); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_saveas_no_events(_) {saveChartAs(true, false); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_meta_save(_) {saveMeta(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_meta_saveas(_) {saveMetaAs(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_saveas_fnflegacy(_) {saveLegacyChartAs(); FlxG.sound.play(Paths.sound('editors/save'));} - function _file_saveas_psych(_) {savePsychChartAs(); FlxG.sound.play(Paths.sound('editors/save'));} + function _file_save_all(_) {saveEverything(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_save(_) {saveChart(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_saveas(_) {saveChartAs(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_events_save(_) {saveEvents(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_events_saveas(_) {saveEventsAs(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_save_no_events(_) {saveChart(true, false); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_saveas_no_events(_) {saveChartAs(true, false); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_meta_save(_) {saveMeta(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_meta_saveas(_) {saveMetaAs(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_saveas_fnflegacy(_) {saveLegacyChartAs(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} + function _file_saveas_psych(_) {savePsychChartAs(); UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND);} function _edit_copy(_, playSFX=true) { - if (playSFX) FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_COPY_SOUND)); + if (playSFX) UIState.playEditorSound(Flags.DEFAULT_EDITOR_COPY_SOUND); if(selection.length == 0) return; var minStep:Float = selection[0].step; @@ -1642,7 +1642,7 @@ class Charter extends UIState { ]; } function _edit_paste(_) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_PASTE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_PASTE_SOUND); if (clipboard.length <= 0) return; var minStep = curStep; @@ -1670,7 +1670,7 @@ class Charter extends UIState { } function _edit_cut(_) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_CUT_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_CUT_SOUND); if (selection == null || selection.length == 0) return; _edit_copy(_, false); @@ -1678,7 +1678,7 @@ class Charter extends UIState { } function _edit_delete(_) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_DELETE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_DELETE_SOUND); if (selection == null || selection.length == 0) return; selection.loop((n:CharterNote) -> { noteDeleteAnims.deleteNotes.push({note: n, time: noteDeleteAnims.deleteTime}); @@ -1687,7 +1687,7 @@ class Charter extends UIState { } function _undo(undo:CharterChange) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_UNDO_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_UNDO_SOUND); switch(undo) { case null: // do nothing case CDeleteStrumLine(strumLineID, strumLine): @@ -1748,7 +1748,7 @@ class Charter extends UIState { } function _redo(redo:CharterChange) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_REDO_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_REDO_SOUND); switch(redo) { case null: // do nothing case CDeleteStrumLine(strumLineID, strumLine): @@ -2159,8 +2159,8 @@ class Charter extends UIState { inline function _snap_decreasesnap(_) changequant(-1); inline function _snap_resetsnap(_) setquant(16); - inline function changequant(change:Int) {FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARTER_SNAPPINGCHANGE_SOUND)); quant = quants[FlxMath.wrap(quants.indexOf(quant) + change, 0, quants.length-1)]; buildSnapsUI();}; - inline function setquant(newQuant:Int) {FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARTER_SNAPPINGCHANGE_SOUND)); quant = newQuant; buildSnapsUI();} + inline function changequant(change:Int) {UIState.playEditorSound(Flags.DEFAULT_CHARTER_SNAPPINGCHANGE_SOUND); quant = quants[FlxMath.wrap(quants.indexOf(quant) + change, 0, quants.length-1)]; buildSnapsUI();}; + inline function setquant(newQuant:Int) {UIState.playEditorSound(Flags.DEFAULT_CHARTER_SNAPPINGCHANGE_SOUND); quant = newQuant; buildSnapsUI();} function buildSnapsUI():Array { var snapsTopButton:UITopMenuButton = topMenuSpr == null ? null : cast topMenuSpr.members[snapIndex]; @@ -2196,12 +2196,12 @@ class Charter extends UIState { } inline function _note_addsustain(t) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARTER_SUSTAINADD_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_CHARTER_SUSTAINADD_SOUND); changeNoteSustain(1); } inline function _note_subtractsustain(t) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_CHARTER_SUSTAINDELETE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_CHARTER_SUSTAINDELETE_SOUND); changeNoteSustain(-1); } diff --git a/source/funkin/editors/charter/CharterAutoSaveUI.hx b/source/funkin/editors/charter/CharterAutoSaveUI.hx index 901cba9a7..8ed1c177e 100644 --- a/source/funkin/editors/charter/CharterAutoSaveUI.hx +++ b/source/funkin/editors/charter/CharterAutoSaveUI.hx @@ -82,7 +82,7 @@ class CharterAutoSaveUI extends UISliceSprite { icon.animation.curAnim.curFrame = 1; for (member in [this, progressBar, progressBarBack, autosavingText]) member.color = 0xFFA3EC95; - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_AUTOSAVE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_AUTOSAVE_SOUND); (new FlxTimer()).start(1, (_) -> {disappearAnimation();}); }); diff --git a/source/funkin/editors/stage/StageEditor.hx b/source/funkin/editors/stage/StageEditor.hx index aa637834c..0c91a9d39 100644 --- a/source/funkin/editors/stage/StageEditor.hx +++ b/source/funkin/editors/stage/StageEditor.hx @@ -510,7 +510,7 @@ class StageEditor extends UIState { function _file_save(_) { #if sys - FlxG.sound.play(Paths.sound('editors/save')); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND); CoolUtil.safeSaveFile( '${Paths.getAssetsRoot()}/data/stages/${__stage}.xml', buildStage() @@ -522,7 +522,7 @@ class StageEditor extends UIState { } function _file_saveas(_) { - FlxG.sound.play(Paths.sound('editors/save')); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_SAVE_SOUND); openSubState(new SaveSubstate(buildStage(), { defaultSaveFile: '${__stage}.xml' })); @@ -734,7 +734,7 @@ class StageEditor extends UIState { } function _edit_undo(_) { - FlxG.sound.play(Flags.DEFAULT_EDITOR_UNDO_SOUND); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_UNDO_SOUND); var undo = undos.undo(); switch(undo) { case null: @@ -760,7 +760,7 @@ class StageEditor extends UIState { } function _edit_redo(_) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_REDO_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_REDO_SOUND); var redo = undos.redo(); switch(redo) { case null: diff --git a/source/funkin/editors/ui/UIButton.hx b/source/funkin/editors/ui/UIButton.hx index 2064e3d7c..017c53855 100644 --- a/source/funkin/editors/ui/UIButton.hx +++ b/source/funkin/editors/ui/UIButton.hx @@ -30,7 +30,7 @@ class UIButton extends UISliceSprite { super.onHovered(); if (FlxG.mouse.justPressed) { hasBeenPressed = true; - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_BUTTONCLICK_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_BUTTONCLICK_SOUND); } if (FlxG.mouse.justReleased && callback != null && shouldPress && hasBeenPressed) { callback(); diff --git a/source/funkin/editors/ui/UIDropDown.hx b/source/funkin/editors/ui/UIDropDown.hx index d90322494..1603f43a7 100644 --- a/source/funkin/editors/ui/UIDropDown.hx +++ b/source/funkin/editors/ui/UIDropDown.hx @@ -87,7 +87,7 @@ class UIDropDown extends UISliceSprite { } public function openContextMenu() { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_DROPDOWNAPPEAR_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_DROPDOWNAPPEAR_SOUND); var screenPos = getScreenPosition(null, __lastDrawCameras[0] == null ? FlxG.camera : __lastDrawCameras[0]); curMenu = UIState.state.openContextMenu([ for(k=>o in items) { diff --git a/source/funkin/editors/ui/UIState.hx b/source/funkin/editors/ui/UIState.hx index 97db4580a..f7db06b15 100644 --- a/source/funkin/editors/ui/UIState.hx +++ b/source/funkin/editors/ui/UIState.hx @@ -106,7 +106,7 @@ class UIState extends MusicBeatState { } if (FlxG.mouse.justPressed) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_CLICK_SOUND)); + playEditorSound(Flags.DEFAULT_EDITOR_CLICK_SOUND); } if (FlxG.mouse.justReleased) @@ -147,7 +147,7 @@ class UIState extends MusicBeatState { } public function closeCurrentContextMenu() { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_WINDOWCLOSE_SOUND)); + playEditorSound(Flags.DEFAULT_EDITOR_WINDOWCLOSE_SOUND); if(curContextMenu != null) { curContextMenu.close(); curContextMenu = null; @@ -155,7 +155,7 @@ class UIState extends MusicBeatState { } public function openContextMenu(options:Array, ?callback:UIContextMenuCallback, ?x:Float, ?y:Float, ?w:Int) { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_WINDOWAPPEAR_SOUND)); + playEditorSound(Flags.DEFAULT_EDITOR_WINDOWAPPEAR_SOUND); var state = FlxG.state; while(state.subState != null && !(state._requestSubStateReset && state._requestedSubState == null)) state = state.subState; @@ -191,4 +191,9 @@ class UIState extends MusicBeatState { resolutionAware = true; FlxG.scaleMode = uiScaleMode; } + + public static function playEditorSound(path:String) { + if (!Options.editorSFX) return; + FlxG.sound.play(Paths.sound(path)); + } } \ No newline at end of file diff --git a/source/funkin/editors/ui/UISubstateWindow.hx b/source/funkin/editors/ui/UISubstateWindow.hx index 61c9f5cae..e7e990760 100644 --- a/source/funkin/editors/ui/UISubstateWindow.hx +++ b/source/funkin/editors/ui/UISubstateWindow.hx @@ -86,7 +86,7 @@ class UISubstateWindow extends MusicBeatSubstate { } public override function destroy() { - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_WINDOWCLOSE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_WINDOWCLOSE_SOUND); super.destroy(); for(e in camShaders) e.removeShader(blurShader); diff --git a/source/funkin/editors/ui/UITextBox.hx b/source/funkin/editors/ui/UITextBox.hx index 371297f29..da4341b42 100644 --- a/source/funkin/editors/ui/UITextBox.hx +++ b/source/funkin/editors/ui/UITextBox.hx @@ -110,7 +110,7 @@ class UITextBox extends UISliceSprite implements IUIFocusable { case RIGHT: changeSelection(1); case BACKSPACE: - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_TEXTREMOVE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_TEXTREMOVE_SOUND); if (position > 0) { label.text = label.text.substr(0, position-1) + label.text.substr(position); changeSelection(-1); @@ -120,7 +120,7 @@ class UITextBox extends UISliceSprite implements IUIFocusable { case END: position = label.text.length; case V: - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_TEXTTYPE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_TEXTTYPE_SOUND); // Hey lj here, fixed copying because before we checked if the modifier was left or right ctrl // but somehow it gave a int outside of the KeyModifier's range :sob: // apparently there is a boolean that just checks for you. yw :D @@ -131,14 +131,14 @@ class UITextBox extends UISliceSprite implements IUIFocusable { var data:String = Clipboard.generalClipboard.getData(TEXT_FORMAT); if (data != null) onTextInput(data); case C: - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_TEXTTYPE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_TEXTTYPE_SOUND); // if we are not holding ctrl, ignore if (!modifier.ctrlKey) return; // copying Clipboard.generalClipboard.setData(TEXT_FORMAT, label.text); default: - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_TEXTTYPE_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_TEXTTYPE_SOUND); } } diff --git a/source/funkin/editors/ui/UIWindow.hx b/source/funkin/editors/ui/UIWindow.hx index e7b994e94..92f885e44 100644 --- a/source/funkin/editors/ui/UIWindow.hx +++ b/source/funkin/editors/ui/UIWindow.hx @@ -15,7 +15,7 @@ class UIWindow extends UISliceSprite { content = new FlxTypedGroup(); members.push(content); - FlxG.sound.play(Paths.sound(Flags.DEFAULT_EDITOR_WINDOWAPPEAR_SOUND)); + UIState.playEditorSound(Flags.DEFAULT_EDITOR_WINDOWAPPEAR_SOUND); } public override function update(elapsed:Float) { diff --git a/source/funkin/options/categories/GameplayOptions.hx b/source/funkin/options/categories/GameplayOptions.hx index 7d66f3511..868c3c4c9 100644 --- a/source/funkin/options/categories/GameplayOptions.hx +++ b/source/funkin/options/categories/GameplayOptions.hx @@ -4,7 +4,7 @@ import flixel.util.FlxTimer; import funkin.backend.system.Conductor; class GameplayOptions extends TreeMenuScreen { - var __metronome = FlxG.sound.load(Paths.sound('editors/charter/metronome')); + var __metronome = FlxG.sound.load(Paths.sound(Flags.DEFAULT_CHARTER_METRONOME_SOUND)); var offsetSetting:NumOption; public function new() { From 27a0291623473087bab1a197b53eae7fa047b0cb Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:06:32 +0100 Subject: [PATCH 08/10] fixed strumline vocals volume, fixed note type option keybinds and moved bookmarks and note types into submenus --- assets/languages/en/Editors.xml | 2 ++ source/funkin/editors/charter/Charter.hx | 36 ++++++++++++------- .../editors/charter/CharterStrumline.hx | 8 +++-- 3 files changed, 31 insertions(+), 15 deletions(-) diff --git a/assets/languages/en/Editors.xml b/assets/languages/en/Editors.xml index d2a168784..b2cad46c5 100644 --- a/assets/languages/en/Editors.xml +++ b/assets/languages/en/Editors.xml @@ -252,6 +252,7 @@ Bookmark List Edit Bookmarks New Bookmark + Bookmark List Note @@ -260,6 +261,7 @@ Subtract sustain length Select all Select measure + Note Types List Edit Note Types List Snap diff --git a/source/funkin/editors/charter/Charter.hx b/source/funkin/editors/charter/Charter.hx index 5806ad3ac..e776bd781 100644 --- a/source/funkin/editors/charter/Charter.hx +++ b/source/funkin/editors/charter/Charter.hx @@ -1859,7 +1859,7 @@ class Charter extends UIState { } function _song_voicesvolume(t) { vocals.volume = t.slider.value; - for (strumLine in strumLines.members) strumLine.vocals.volume = t.slider.value; //TODO: fix to multiply with other strumline specific volume + for (strumLine in strumLines.members) strumLine.vocals.volume = t.slider.value * strumLine.vocalsVolume; t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); } function _song_hitsoundvolume(t) { @@ -2061,14 +2061,19 @@ class Charter extends UIState { if (bookmarks.length > 0) { + var bookmarkOptions:Array = []; var goToBookmark = TU.getRaw("charter.bookmarks.goTo"); for (b in bookmarks) { - newChilds.push({ + bookmarkOptions.push({ label: goToBookmark.format([b.name]), onSelect: function(_) { Conductor.songPosition = Conductor.getTimeForStep(b.time); } }); } + newChilds.push({ + label: translate("bookmarks.bookmarkList"), + childs: bookmarkOptions + }); newChilds.push(null); } @@ -2278,16 +2283,18 @@ class Charter extends UIState { keybind: [CONTROL, SHIFT, A], onSelect: _note_selectmeasure }, - null, - { - label: "(0) " + translate("noteTypes.default"), - keybind: [ZERO], - onSelect: (_) -> {changeNoteType(0);}, - icon: this.noteType == 0 ? 1 : 0 - } + null ]; - var noteKeys:Array = [ZERO, ONE, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE]; + var noteTypeOptions:Array = [{ + label: "(0) " + translate("noteTypes.default"), + keybind: [ZERO], + onSelect: (_) -> {changeNoteType(0);}, + icon: this.noteType == 0 ? 1 : 0 + }]; + + final noteKeys:Array>> = [[[ZERO], [NUMPADZERO]], [[ONE], [NUMPADONE]], [[TWO], [NUMPADTWO]], [[THREE], [NUMPADTHREE]], [[FOUR], [NUMPADFOUR]], [[FIVE], [NUMPADFIVE]], + [[SIX], [NUMPADSIX]], [[SEVEN], [NUMPADSEVEN]], [[EIGHT], [NUMPADEIGHT]], [[NINE], [NUMPADNINE]]]; for (i=>type in noteTypes) { var realNoteID:Int = i+1; // Default Note not stored var newChild:UIContextMenuOption = { @@ -2296,9 +2303,13 @@ class Charter extends UIState { onSelect: (_) -> {changeNoteType(realNoteID);}, icon: this.noteType == realNoteID ? 1 : 0 }; - if (realNoteID <= 9) newChild.keybind = [noteKeys[realNoteID]]; - newChilds.push(newChild); + if (realNoteID <= 9) newChild.keybinds = noteKeys[realNoteID]; + noteTypeOptions.push(newChild); } + newChilds.push({ + label: translate("note.noteTypesList"), + childs: noteTypeOptions + }); newChilds.push({ label: translate("note.editNoteTypesList"), color: 0xFF959829, icon: 4, @@ -2306,6 +2317,7 @@ class Charter extends UIState { onSelect: editNoteTypesList }); if (noteTopButton != null) noteTopButton.contextMenu = newChilds; + if (topMenu != null && topMenu[noteIndex] != null) topMenu[noteIndex].childs = newChilds; return newChilds; } diff --git a/source/funkin/editors/charter/CharterStrumline.hx b/source/funkin/editors/charter/CharterStrumline.hx index 38c93942d..40f2bf369 100644 --- a/source/funkin/editors/charter/CharterStrumline.hx +++ b/source/funkin/editors/charter/CharterStrumline.hx @@ -12,7 +12,6 @@ import funkin.game.HealthIcon; class CharterStrumline extends UISprite { public var strumLine:ChartStrumLine; - public var hitsoundVolume:Float = 1; public var draggingSprite:UISprite; public var healthIcons:FlxSpriteGroup; @@ -26,6 +25,8 @@ class CharterStrumline extends UISprite { public var vocals:FlxSound; public var hasVocals:Bool = false; + public var vocalsVolume:Float = 1; + public var hitsoundVolume:Float = 1; public var keyCount:Int = 4; public var startingID(get, null):Int; @@ -220,9 +221,10 @@ class CharterStrumlineOptions extends UITopMenuButton { slider: { min: 0, max: 1, - value: strLine.vocals.volume, + value: strLine.vocalsVolume, onChange: function(t) { - strLine.vocals.volume = t.slider.value; + strLine.vocalsVolume = t.slider.value; + strLine.vocals.volume = Charter.instance.vocals.volume * strLine.vocalsVolume; t.icon = t.slider.value > 0.5 ? 7 : (t.slider.value > 0 ? 8 : 9); } }, From 15afdf46baf8c73b4208726cf8507bc7ba4f49ec Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Wed, 15 Oct 2025 19:45:11 +0100 Subject: [PATCH 09/10] fix for saving difficulty specific meta json --- source/funkin/backend/chart/Chart.hx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/source/funkin/backend/chart/Chart.hx b/source/funkin/backend/chart/Chart.hx index 3dbeceb82..fd82ec4be 100644 --- a/source/funkin/backend/chart/Chart.hx +++ b/source/funkin/backend/chart/Chart.hx @@ -278,9 +278,13 @@ class Chart { var filteredChart = filterChartForSaving(chart, saveSettings.saveMetaInChart, saveSettings.saveLocalEvents, saveSettings.saveGlobalEvents && saveSettings.seperateGlobalEvents != true); #if sys - var songPath = saveSettings.songFolder == null ? 'songs/${chart.meta.name}' : saveSettings.songFolder, variantSuffix = variant != null && variant != "" ? '-$variant' : ""; - var metaPath = 'meta$variantSuffix.json', prettyPrint = saveSettings.prettyPrint == true ? Flags.JSON_PRETTY_PRINT : null, temp:String; - if ((temp = Paths.assetsTree.getPath('assets/$songPath/$metaPath')) != null) { + var songPath = saveSettings.songFolder == null ? 'songs/${chart.meta.name}' : saveSettings.songFolder, variantSuffix = variant != null && variant != "" ? '-$variant' : "", difficultySuffix = difficulty != null && difficulty != "" ? '-$difficulty' : ""; + var metaPath = 'meta$variantSuffix.json', altMetaPath = 'meta${variantSuffix}${difficultySuffix}.json', prettyPrint = saveSettings.prettyPrint == true ? Flags.JSON_PRETTY_PRINT : null, temp:String; + if ((temp = Paths.assetsTree.getPath('assets/$songPath/$altMetaPath')) != null) { //check for difficulty specific + songPath = temp.substr(0, temp.length - altMetaPath.length - 1); + metaPath = temp; + } + else if ((temp = Paths.assetsTree.getPath('assets/$songPath/$metaPath')) != null) { songPath = temp.substr(0, temp.length - metaPath.length - 1); metaPath = temp; } From e58e9efe8aff02552a9c011b23c817e833d336c8 Mon Sep 17 00:00:00 2001 From: TheZoroForce240 <86524550+TheZoroForce240@users.noreply.github.com> Date: Thu, 16 Oct 2025 18:19:06 +0100 Subject: [PATCH 10/10] some extra misc changes fixed camera highlights not updating when zooming in/out, optimized some of the highlight draw code so it doesn't do a full loop, and added the note scale flag into the strumline preview --- .../editors/charter/CharterBackdropGroup.hx | 26 ++++++++++++++++--- .../charter/CharterPreviewStrumLine.hx | 6 ++--- 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/source/funkin/editors/charter/CharterBackdropGroup.hx b/source/funkin/editors/charter/CharterBackdropGroup.hx index 5c668789c..d021c66bc 100644 --- a/source/funkin/editors/charter/CharterBackdropGroup.hx +++ b/source/funkin/editors/charter/CharterBackdropGroup.hx @@ -321,16 +321,19 @@ class CharterGridSeperatorBase extends FlxSprite { private static var lastMaxMeasure:Float = -1; public static var lastConductorSprY:Float = Math.NEGATIVE_INFINITY; + public static var lastCameraZoom:Float = -1; private static var beatStepTimes:Array = []; private static var measureStepTimes:Array = []; private static var timeSignatureChangeGaps:Array = []; private function recalculateBeats() { + @:privateAccess + var currentZoom = Charter.instance.__camZoom; var conductorSprY = Charter.instance.gridBackdrops.conductorSprY; - if (conductorSprY == lastConductorSprY) return; + if (conductorSprY == lastConductorSprY && currentZoom == lastCameraZoom) return; //only update if song pos or camera zoom has changed - var zoomOffset = ((FlxG.height * (1/cameras[0].zoom)) * 0.5); + var zoomOffset = ((FlxG.height * (1/currentZoom)) * 0.5); minStep = (conductorSprY - zoomOffset)/40; maxStep = (conductorSprY + zoomOffset)/40; @@ -369,6 +372,7 @@ class CharterGridSeperatorBase extends FlxSprite { } lastConductorSprY = conductorSprY; + lastCameraZoom = currentZoom; } private inline function calculateTimeSignatureGaps() { @@ -459,6 +463,7 @@ class CharterGridSeperator extends CharterGridSeperatorBase { class CameraHighlight extends FlxSprite { private var grid:CharterBackdrop; + private var _currentCameraMovementIndex:Int = 0; public function new(grid:CharterBackdrop) { this.grid = grid; super(); @@ -484,8 +489,23 @@ class CameraHighlight extends FlxSprite { } } - for (change in Charter.instance.cameraMovementChanges) { + //update index if gone backwards + while(_currentCameraMovementIndex > 0) { + if (Charter.instance.cameraMovementChanges[_currentCameraMovementIndex] == null || Charter.instance.cameraMovementChanges[_currentCameraMovementIndex].endStep >= minStep) { + _currentCameraMovementIndex--; + } else { + break; + } + } + + var seenFirstVisible = false; + for (i in _currentCameraMovementIndex...Charter.instance.cameraMovementChanges.length) { + var change = Charter.instance.cameraMovementChanges[i]; if (change.endStep >= minStep) { + if (!seenFirstVisible) { + _currentCameraMovementIndex = i; //remember the index for the next frame, so we dont need to loop through everything every time + seenFirstVisible = true; + } if (change.strumLineID == strumLineID) { setupHighlight(change.step, change.endStep); super.draw(); setupLine(change.step); super.draw(); diff --git a/source/funkin/editors/charter/CharterPreviewStrumLine.hx b/source/funkin/editors/charter/CharterPreviewStrumLine.hx index 22e104683..d2d26edd8 100644 --- a/source/funkin/editors/charter/CharterPreviewStrumLine.hx +++ b/source/funkin/editors/charter/CharterPreviewStrumLine.hx @@ -21,7 +21,7 @@ class CharterPreviewStrumLine extends FlxTypedGroup for (i in 0...keyCount){ var strum = new FlxSprite(); strum.frames = Paths.getFrames("game/notes/default"); - strum.setGraphicSize(Std.int((strum.width * 0.7) * scale)); + strum.setGraphicSize(Std.int((strum.width * Flags.DEFAULT_NOTE_SCALE) * scale)); strum.updateHitbox(); var animPrefix = strumAnimPrefix[i % 4]; @@ -33,7 +33,7 @@ class CharterPreviewStrumLine extends FlxTypedGroup note = new FlxSprite(); note.frames = Paths.getFrames("game/notes/default"); - note.setGraphicSize(Std.int((note.width * 0.7) * scale)); + note.setGraphicSize(Std.int((note.width * Flags.DEFAULT_NOTE_SCALE) * scale)); note.updateHitbox(); note.animation.addByPrefix('purple', 'purple0'); note.animation.play('purple'); @@ -53,7 +53,7 @@ class CharterPreviewStrumLine extends FlxTypedGroup strum.x = CoolUtil.fpsLerp(strum.x, x + (Note.swagWidth * scale * spacing * i), 0.2); strum.y = CoolUtil.fpsLerp(strum.y, y + (Note.swagWidth*0.5) - (Note.swagWidth * scale * 0.5), 0.2); - strum.scale.x = strum.scale.y = CoolUtil.fpsLerp(strum.scale.x, 0.7 * scale, 0.2); + strum.scale.x = strum.scale.y = CoolUtil.fpsLerp(strum.scale.x, Flags.DEFAULT_NOTE_SCALE * scale, 0.2); strum.updateHitbox(); }