From 0098c3d660e2eefd3fc09f00ac7bdda25dc1d0d1 Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 28 Mar 2024 03:18:01 -0500 Subject: [PATCH 01/24] Made saves be stored in Userpath\Saves. Ability to rename save files in game. --- .../Controls/Nintendo Switch/renamefile.png | Bin 0 -> 515 bytes Content/Sprites/Controls/PC/renamefile.png | Bin 0 -> 2116 bytes .../Controls/PlayStation 4/renamefile.png | Bin 0 -> 453 bytes .../Controls/PlayStation 5/renamefile.png | Bin 0 -> 453 bytes .../Controls/Xbox Series/renamefile.png | Bin 0 -> 560 bytes Content/Text/English.json | 2 + Source/Data/Controls.cs | 7 ++ .../Data/PersistedData/ControlsConfig_V01.cs | 4 + Source/Data/Save.cs | 6 +- Source/Helpers/Menu.cs | 21 ++++ Source/Mod/Data/SaveManager.cs | 54 ++++++-- Source/Mod/Menu/GameOptionsMenu.cs | 2 + Source/Mod/Menu/SaveSelectionMenu.cs | 43 ++++++- Source/Mod/Patches/KeyboardHandler.cs | 119 ++++++++++++++++++ Source/Scenes/Overworld.cs | 8 +- 15 files changed, 248 insertions(+), 18 deletions(-) create mode 100644 Content/Sprites/Controls/Nintendo Switch/renamefile.png create mode 100644 Content/Sprites/Controls/PC/renamefile.png create mode 100644 Content/Sprites/Controls/PlayStation 4/renamefile.png create mode 100644 Content/Sprites/Controls/PlayStation 5/renamefile.png create mode 100644 Content/Sprites/Controls/Xbox Series/renamefile.png create mode 100644 Source/Mod/Patches/KeyboardHandler.cs diff --git a/Content/Sprites/Controls/Nintendo Switch/renamefile.png b/Content/Sprites/Controls/Nintendo Switch/renamefile.png new file mode 100644 index 0000000000000000000000000000000000000000..737632d430e900dc55644e6a382345bb80581d39 GIT binary patch literal 515 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!SkfJR9T^xl_H+M9WCik#1AIbU z|C0iMnt;khw>EtPvII(k{DS@S?eELi_pg7ie}4ab{&)tpH+iNE42IE--pT!8KjS>7zhMgbtUoq< za?Jj~=CF<@WV6r)_jelaq!?7+X8pWNczjZXV-4Fia)5Rzn}Ye#)pq( z-VSbgKY!&o%AIB^NdDqhIqz5Jd2_~&3;DlimA$yA!65ouH~q~;Ee7S|O8wdl>oXTg zEoZdhW!GKBWWy&c&MDh)+@G%@g?Y(O!#>7O60>OMkDP^MOg99_Re`{a=Mcnc8<;e!GryLd7Hg|?=$+aE+Z`0+LUi^B#gt6@x!-c3% V4q^4rY=P0h;OXk;vd$@?2>>1K_dfst literal 0 HcmV?d00001 diff --git a/Content/Sprites/Controls/PC/renamefile.png b/Content/Sprites/Controls/PC/renamefile.png new file mode 100644 index 0000000000000000000000000000000000000000..8d4371c8d02240feb89a4284e8d63657ee3d4218 GIT binary patch literal 2116 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 FindAction(ControlsConfig_V01? config, st it.BindTo(DeleteFile); foreach (var it in FindAction(config, "CreateFile")) it.BindTo(CreateFile); + foreach (var it in FindAction(config, "RenameFile")) + it.BindTo(RenameFile); } @@ -114,6 +117,7 @@ public static void Clear() CopyFile.Clear(); DeleteFile.Clear(); CreateFile.Clear(); + RenameFile.Clear(); } public static void Consume() @@ -130,6 +134,7 @@ public static void Consume() CopyFile.Consume(); DeleteFile.Consume(); CreateFile.Consume(); + RenameFile.Consume(); } private static readonly Dictionary> prompts = []; @@ -172,6 +177,8 @@ public static string GetPromptLocation(VirtualButton button) return GetPromptLocation("deletefile"); else if (button == CopyFile) return GetPromptLocation("copyfile"); + else if (button == RenameFile) + return GetPromptLocation("renamefile"); else return GetPromptLocation("pause"); } diff --git a/Source/Data/PersistedData/ControlsConfig_V01.cs b/Source/Data/PersistedData/ControlsConfig_V01.cs index a66250d9..9400e4b2 100644 --- a/Source/Data/PersistedData/ControlsConfig_V01.cs +++ b/Source/Data/PersistedData/ControlsConfig_V01.cs @@ -63,6 +63,10 @@ public class ControlsConfig_V01 : PersistedData new(Keys.B), new(Buttons.North) ], + ["RenameFile"] = [ + new(Keys.R), + new(Buttons.West) + ], }, Sticks = new() diff --git a/Source/Data/Save.cs b/Source/Data/Save.cs index 7f619bac..d1fe1ccc 100644 --- a/Source/Data/Save.cs +++ b/Source/Data/Save.cs @@ -114,8 +114,8 @@ public static SkinInfo GetSkin() public static void SaveToFile() { - var savePath = Path.Join(App.UserPath, DefaultFileName); - var tempPath = Path.Join(App.UserPath, DefaultFileName + ".backup"); + var savePath = Path.Join(App.UserPath, "Saves", DefaultFileName); + var tempPath = Path.Join(App.UserPath, "Saves", DefaultFileName + ".backup"); // first save to a temporary file { @@ -135,7 +135,7 @@ public static void SaveToFile() internal static void LoadSaveByFileName(string fileName) { if (fileName == string.Empty) fileName = DefaultFileName; - var saveFile = Path.Join(App.UserPath, fileName); + var saveFile = Path.Join(App.UserPath, "Saves", fileName); if (File.Exists(saveFile)) Instance = Instance.Deserialize(File.ReadAllText(saveFile)) ?? new(); diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index 6aee868b..888c1ed7 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -1,3 +1,5 @@ +using Celeste64.Mod; + namespace Celeste64; public class Menu @@ -12,6 +14,7 @@ public abstract class Item public virtual bool Selectable { get; } = true; public virtual bool Pressed() => false; public virtual void Slide(int dir) { } + public virtual void GetKeyPress(Keys? key) { } // LocString is the base localized string object, before any changes. // This is kept separate from the label so we can get substrings from the LocString like the Description. @@ -203,6 +206,19 @@ private static List GetEnumOptions() } } + public class InputField(Loc.Localized locString, Action set, Func get) : Item + { + public override Loc.Localized LocString => locString; + public override string Label => $"{LocString} : {get()}"; + public override void GetKeyPress(Keys? key) + { + Controls.Confirm.ConsumePress(); + Controls.Cancel.ConsumePress(); + if (key != null) + set(key); + } + } + public int Index; public string Title = string.Empty; public bool Focused = true; @@ -354,6 +370,9 @@ public void CloseSubMenus() protected virtual void HandleInput() { + KeyboardHandler.Instance.ReadKeys(); + Keys? key = KeyboardHandler.Instance.GetPressedKey(); + if (items.Count > 0) { var was = Index; @@ -385,6 +404,8 @@ protected virtual void HandleInput() if (was != Index) Audio.Play(step < 0 ? UpSound : DownSound); + items[Index].GetKeyPress(key); + if (Controls.Menu.Horizontal.Negative.Pressed) items[Index].Slide(-1); if (Controls.Menu.Horizontal.Positive.Pressed) diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index b88dbf92..85609a76 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -7,11 +7,11 @@ internal sealed class SaveManager [DisallowHooks] internal string GetLastLoadedSave() { - if (File.Exists(Path.Join(App.UserPath, "save.metadata"))) - return File.ReadAllText(Path.Join(App.UserPath, "save.metadata")); + if (File.Exists(Path.Join(App.UserPath, "Saves", "save.metadata"))) + return File.ReadAllText(Path.Join(App.UserPath, "Saves", "save.metadata")); else { - File.WriteAllText(Path.Join(App.UserPath, "save.metadata"), Save.DefaultFileName); + File.WriteAllText(Path.Join(App.UserPath, "Saves", "save.metadata"), Save.DefaultFileName); return Save.DefaultFileName; } } @@ -19,8 +19,8 @@ internal string GetLastLoadedSave() [DisallowHooks] internal void SetLastLoadedSave(string save_name) { - if (File.Exists(Path.Join(App.UserPath, "save.metadata"))) - File.WriteAllText(Path.Join(App.UserPath, "save.metadata"), save_name); + if (File.Exists(Path.Join(App.UserPath, "Saves", "save.metadata"))) + File.WriteAllText(Path.Join(App.UserPath, "Saves", "save.metadata"), save_name); } [DisallowHooks] @@ -28,10 +28,22 @@ internal List GetSaves() { List saves = new List(); - foreach (string savefile in Directory.GetFiles(App.UserPath)) + foreach (string file in Directory.GetFiles(Path.Join(App.UserPath))) + { + string saveFileName = Path.GetFileName(file); + if (saveFileName.StartsWith("save") && saveFileName.EndsWith(".json")) + { + if (saveFileName == "save.json" && !Path.Exists(Path.Join(App.UserPath, "Saves", saveFileName))) + File.Copy(Path.Join(App.UserPath, saveFileName), Path.Join(App.UserPath, "Saves", saveFileName)); + else if (!Path.Exists(Path.Join(App.UserPath, "Saves", saveFileName))) + File.Move(Path.Join(App.UserPath, saveFileName), Path.Join(App.UserPath, "Saves", saveFileName)); + } + } + + foreach (string savefile in Directory.GetFiles(Path.Join(App.UserPath, "Saves"))) { var saveFileName = Path.GetFileName(savefile); - if (saveFileName.EndsWith(".json") && saveFileName.StartsWith("save")) + if (saveFileName.EndsWith(".json")) saves.Add(saveFileName); } @@ -41,10 +53,10 @@ internal List GetSaves() [DisallowHooks] internal void CopySave(string filename) { - if (File.Exists(Path.Join(App.UserPath, filename))) + if (File.Exists(Path.Join(App.UserPath, "Saves", filename))) { string new_file_name = $"{filename.Split(".json")[0]}(copy).json"; - File.Copy(Path.Join(App.UserPath, filename), Path.Join(App.UserPath, new_file_name)); + File.Copy(Path.Join(App.UserPath, "Saves", filename), Path.Join(App.UserPath, "Saves", new_file_name)); } } @@ -52,8 +64,8 @@ internal void CopySave(string filename) internal void NewSave(string? name = null) { if (string.IsNullOrEmpty(name)) name = $"save_{GetSaveCount()}.json"; - var savePath = Path.Join(App.UserPath, name); - var tempPath = Path.Join(App.UserPath, name + ".backup"); + var savePath = Path.Join(App.UserPath, "Saves", name); + var tempPath = Path.Join(App.UserPath, "Saves", name + ".backup"); // first save to a temporary file { @@ -69,6 +81,22 @@ internal void NewSave(string? name = null) } } + [DisallowHooks] + internal void ChangeFileName(string orignalFileName, string newFileName) + { + foreach (string file in GetSaves()) + { + if (file == orignalFileName) + { + if (!newFileName.EndsWith(".json")) + newFileName += ".json"; + File.Move(Path.Join(App.UserPath, "Saves", file), Path.Join(App.UserPath, "Saves", newFileName)); + if (file == Save.Instance.FileName) + LoadSaveByFileName(newFileName); + } + } + } + [DisallowHooks] internal int GetSaveCount() { @@ -78,9 +106,9 @@ internal int GetSaveCount() [DisallowHooks] internal void DeleteSave(string save) { - if (File.Exists(Path.Join(App.UserPath, save))) + if (File.Exists(Path.Join(App.UserPath, "Saves", save))) { - File.Delete(Path.Join(App.UserPath, save)); + File.Delete(Path.Join(App.UserPath, "Saves", save)); } if (save == Save.DefaultFileName) diff --git a/Source/Mod/Menu/GameOptionsMenu.cs b/Source/Mod/Menu/GameOptionsMenu.cs index fa1582f0..d2855b32 100644 --- a/Source/Mod/Menu/GameOptionsMenu.cs +++ b/Source/Mod/Menu/GameOptionsMenu.cs @@ -1,3 +1,5 @@ +using Celeste64.Mod; + namespace Celeste64; public class GameOptionsMenu : Menu diff --git a/Source/Mod/Menu/SaveSelectionMenu.cs b/Source/Mod/Menu/SaveSelectionMenu.cs index f89c68dd..b6620b07 100644 --- a/Source/Mod/Menu/SaveSelectionMenu.cs +++ b/Source/Mod/Menu/SaveSelectionMenu.cs @@ -1,4 +1,6 @@ -using Celeste64.Mod.Data; +using Celeste64.Mod; +using Celeste64.Mod.Data; +using System.Diagnostics; namespace Celeste64; @@ -21,6 +23,7 @@ public class SaveSelectionMenu : Menu private Subtexture strawberryImage; private List saves; + private string renamedFileName = string.Empty; internal SaveSelectionMenu(Menu? rootMenu) { @@ -123,6 +126,22 @@ private void RenderSaves(Batcher batch) } } + void SetRename(Keys? key) + { + if (key == Keys.Backspace || key == Keys.KeypadBackspace) + { + if (renamedFileName.Length > 0) + renamedFileName = renamedFileName.Remove(renamedFileName.Length - 1); + } + else + renamedFileName += KeyboardHandler.GetKeyName(key).ToLower(); + } + + string GetRename() + { + return renamedFileName; + } + protected override void HandleInput() { @@ -250,6 +269,24 @@ protected override void HandleInput() PushSubMenu(newMenu); newMenu.Add(new Option("OptionsNo", () => PopSubMenu())); } + + if (Controls.RenameFile.Pressed) + { + Menu newMenu = new Menu(this); + newMenu.Title = $"Rename this file: {saves[CurrentPageStart + CurrentIndex]}"; + newMenu.Add(new InputField("NewName", (k) => SetRename(k), GetRename)); + newMenu.Add(new Option("OptionsYes", () => { + SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], GetRename()); + ResetSaves(); + PopSubMenu(); + renamedFileName = string.Empty; + })); + PushSubMenu(newMenu); + newMenu.Add(new Option("OptionsNo", () => { + renamedFileName = string.Empty; + PopSubMenu(); + })); + } } protected override void RenderItems(Batcher batch) @@ -280,6 +317,10 @@ protected override void RenderItems(Batcher batch) at.X -= width + 8 * Game.RelativeScale; UI.Prompt(batch, Controls.CopyFile, Loc.Str("Copy"), at, out width, 1.0f); + at.X -= width + 8 * Game.RelativeScale; + + UI.Prompt(batch, Controls.RenameFile, Loc.Str("Rename"), at, out _, 1.0f); + batch.PopMatrix(); } } diff --git a/Source/Mod/Patches/KeyboardHandler.cs b/Source/Mod/Patches/KeyboardHandler.cs new file mode 100644 index 00000000..13fdd809 --- /dev/null +++ b/Source/Mod/Patches/KeyboardHandler.cs @@ -0,0 +1,119 @@ +using System.Runtime.InteropServices; + +namespace Celeste64.Mod; + +class KeyboardHandler +{ + public static readonly Dictionary KeyValues = new Dictionary + { + { "A", "A" }, + { "B", "B" }, + { "C", "C" }, + { "D", "D" }, + { "E", "E" }, + { "F", "F" }, + { "G", "G" }, + { "H", "H" }, + { "I", "I" }, + { "J", "J" }, + { "K", "K" }, + { "L", "L" }, + { "M", "M" }, + { "N", "N" }, + { "O", "O" }, + { "P", "P" }, + { "Q", "Q" }, + { "R", "R" }, + { "S", "S" }, + { "T", "T" }, + { "U", "U" }, + { "V", "V" }, + { "W", "W" }, + { "X", "X" }, + { "Y", "Y" }, + { "Z", "Z" }, + { "D1", "1" }, + { "D2", "2" }, + { "D3", "3" }, + { "D4", "4" }, + { "D5", "5" }, + { "D6", "6" }, + { "D7", "7" }, + { "D8", "8" }, + { "D9", "9" }, + { "D0", "0" }, + { "Space", "_" }, + { "Minus", "-" }, + { "Equals", "=" }, + { "LeftBracket", "[" }, + { "RightBracket", "]" }, + { "Backslash", "\\" }, + { "Semicolon", ";" }, + { "Apostrophe", "'" }, + { "Tilde", "~" }, + { "Comma", "," }, + { "Period", "." }, + { "Slash", "/" }, + { "Keypad0", "0" }, + { "Keypad00", "00" }, + { "Keypad000", "000" }, + { "Keypad1", "1" }, + { "Keypad2", "2" }, + { "Keypad3", "3" }, + { "Keypad4", "4" }, + { "Keypad5", "5" }, + { "Keypad6", "6" }, + { "Keypad7", "7" }, + { "Keypad8", "8" }, + { "Keypad9", "9" }, + { "KeypadDivide", "/" }, + { "KeypadMultiply", "*" }, + { "KeypadMinus", "-" }, + { "KeypadPlus", "+" }, + { "KeypadPeroid", "." }, + { "KeypadEquals", "=" }, + { "KeypadComma", "," }, + { "KeypadLeftParen", "(" }, + { "KeypadRightParen", ")" }, + { "KeypadLeftBrace", "{" }, + { "KeypadRightBrace", "}" }, + { "KeypadTab", "\t" }, + { "KeypadA", "A" }, + { "KeypadB", "B" }, + { "KeypadC", "C" }, + { "KeypadD", "D" }, + { "KeypadE", "E" }, + { "KeypadF", "F" } + }; + private Keys? previousKey; + public static KeyboardHandler Instance = new(); + + public static string GetKeyName(Keys? key) + { + if (KeyValues.ContainsKey(key.ToString())) + return KeyValues[key.ToString()]; + else + return string.Empty; + } + + public Keys? GetLastKey() + { + return previousKey; + } + + public Keys? GetPressedKey() + { + Keys? key = Input.Keyboard.FirstPressed(); + return key; + } + + public void ReadKeys() + { + Keys? key = Input.Keyboard.FirstPressed(); + if (key == null) + key = previousKey; + else + previousKey = key; + } + +} diff --git a/Source/Scenes/Overworld.cs b/Source/Scenes/Overworld.cs index eac59334..027cd2fb 100644 --- a/Source/Scenes/Overworld.cs +++ b/Source/Scenes/Overworld.cs @@ -1,5 +1,6 @@ using Celeste64.Mod; - +using ImGuiNET; +using System.Diagnostics; namespace Celeste64; public class Overworld : Scene @@ -267,6 +268,7 @@ public void SlideSelectedMod(int dir) } #endregion + string SomethingFun = string.Empty; #region Update & Render public override void Update() { @@ -605,6 +607,8 @@ public override void Render(Target target) pauseMenu.Render(batch, bounds.Center); } + + // show version number on Overworld as well // Logic breakdown: // If paused @@ -615,6 +619,8 @@ public override void Render(Target target) { UI.Text(batch, Game.VersionString, bounds.BottomLeft + new Vec2(4, -4) * Game.RelativeScale, new Vec2(0, 1), Color.CornflowerBlue * 0.75f); UI.Text(batch, Game.LoaderVersion, bounds.BottomLeft + new Vec2(4, -24) * Game.RelativeScale, new Vec2(0, 1), new Color(12326399) * 0.75f); + UI.Text(batch, SomethingFun, bounds.BottomLeft + new Vec2(4, -44) * Game.RelativeScale, new Vec2(0, 1), new Color(12326399) * 0.75f); + if (ModLoader.FailedToLoadMods.Any()) { From 443e76f5a5708f3dd6cac20e76b53b3c6d667255 Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 28 Mar 2024 14:11:55 -0500 Subject: [PATCH 02/24] Better keyboard functionality. Made InputField more portable --- Source/Helpers/Menu.cs | 31 ++++-- Source/Mod/Data/SaveManager.cs | 7 +- Source/Mod/Menu/SaveSelectionMenu.cs | 18 +-- Source/Mod/Patches/KeyboardHandler.cs | 155 ++++++++++++++++++++------ 4 files changed, 158 insertions(+), 53 deletions(-) diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index 888c1ed7..2a444a4c 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -14,7 +14,7 @@ public abstract class Item public virtual bool Selectable { get; } = true; public virtual bool Pressed() => false; public virtual void Slide(int dir) { } - public virtual void GetKeyPress(Keys? key) { } + public virtual void GetKeyPress() { } // LocString is the base localized string object, before any changes. // This is kept separate from the label so we can get substrings from the LocString like the Description. @@ -206,16 +206,32 @@ private static List GetEnumOptions() } } - public class InputField(Loc.Localized locString, Action set, Func get) : Item + public class InputField(Loc.Localized locString, Action set, Func get) : Item { public override Loc.Localized LocString => locString; - public override string Label => $"{LocString} : {get()}"; - public override void GetKeyPress(Keys? key) + + private string fieldText = get(); + public override string Label => $"{LocString} : {fieldText}"; + + private Keys? key; + public override void GetKeyPress() { + KeyboardHandler.Instance.ReadKeys(); + key = KeyboardHandler.Instance.GetPressedKey(); + Controls.Confirm.ConsumePress(); Controls.Cancel.ConsumePress(); if (key != null) - set(key); + { + if (key == Keys.Backspace || key == Keys.KeypadBackspace) + { + if (fieldText.Length > 0) + fieldText = fieldText.Remove(fieldText.Length - 1); + } + else + fieldText += KeyboardHandler.GetKeyName(key); + set(fieldText); + } } } @@ -370,9 +386,6 @@ public void CloseSubMenus() protected virtual void HandleInput() { - KeyboardHandler.Instance.ReadKeys(); - Keys? key = KeyboardHandler.Instance.GetPressedKey(); - if (items.Count > 0) { var was = Index; @@ -404,7 +417,7 @@ protected virtual void HandleInput() if (was != Index) Audio.Play(step < 0 ? UpSound : DownSound); - items[Index].GetKeyPress(key); + items[Index].GetKeyPress(); if (Controls.Menu.Horizontal.Negative.Pressed) items[Index].Slide(-1); diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index 85609a76..e6b34abd 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -1,4 +1,6 @@ -namespace Celeste64.Mod.Data; +using System.Text.RegularExpressions; + +namespace Celeste64.Mod.Data; internal sealed class SaveManager { @@ -84,12 +86,15 @@ internal void NewSave(string? name = null) [DisallowHooks] internal void ChangeFileName(string orignalFileName, string newFileName) { + string invalidCharsPattern = "[\\/:*?\"<>|{}]"; + foreach (string file in GetSaves()) { if (file == orignalFileName) { if (!newFileName.EndsWith(".json")) newFileName += ".json"; + newFileName = Regex.Replace(newFileName, invalidCharsPattern, "_"); File.Move(Path.Join(App.UserPath, "Saves", file), Path.Join(App.UserPath, "Saves", newFileName)); if (file == Save.Instance.FileName) LoadSaveByFileName(newFileName); diff --git a/Source/Mod/Menu/SaveSelectionMenu.cs b/Source/Mod/Menu/SaveSelectionMenu.cs index b6620b07..9361ba67 100644 --- a/Source/Mod/Menu/SaveSelectionMenu.cs +++ b/Source/Mod/Menu/SaveSelectionMenu.cs @@ -111,30 +111,24 @@ private void RenderSaves(Batcher batch) { for (int j = 0; j < columns && CurrentPageStart + index < saves.Count; j++) { - if (saves[CurrentPageStart + index] == Save.Instance.FileName && index == currentRow * columns + currentColumn) RenderCurrentSelectedSave(batch, saves[CurrentPageStart + index], new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); - else if (saves[CurrentPageStart + index] == Save.Instance.FileName) RenderSelectedSave(batch, saves[CurrentPageStart + index], new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); + if (saves[CurrentPageStart + index] == Save.Instance.FileName && index == currentRow * columns + currentColumn) RenderCurrentSelectedSave(batch, saves[CurrentPageStart + index].Replace(".json", string.Empty), new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); + else if (saves[CurrentPageStart + index] == Save.Instance.FileName) RenderSelectedSave(batch, saves[CurrentPageStart + index].Replace(".json", string.Empty), new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); else if (index == currentRow * columns + currentColumn) { - RenderCurrentSave(batch, saves[CurrentPageStart + index], new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); + RenderCurrentSave(batch, saves[CurrentPageStart + index].Replace(".json", string.Empty), new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); } else { - RenderSave(batch, saves[CurrentPageStart + index], new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); + RenderSave(batch, saves[CurrentPageStart + index].Replace(".json", string.Empty), new Vec2(sizeMin * j * 1.1f, sizeMin * i * 1.1f) + offset, size); } index++; } } } - void SetRename(Keys? key) + void SetRename(string name) { - if (key == Keys.Backspace || key == Keys.KeypadBackspace) - { - if (renamedFileName.Length > 0) - renamedFileName = renamedFileName.Remove(renamedFileName.Length - 1); - } - else - renamedFileName += KeyboardHandler.GetKeyName(key).ToLower(); + renamedFileName = name; } string GetRename() diff --git a/Source/Mod/Patches/KeyboardHandler.cs b/Source/Mod/Patches/KeyboardHandler.cs index 13fdd809..4d1e54d3 100644 --- a/Source/Mod/Patches/KeyboardHandler.cs +++ b/Source/Mod/Patches/KeyboardHandler.cs @@ -1,4 +1,5 @@ -using System.Runtime.InteropServices; +using System.Diagnostics; +using System.Runtime.InteropServices; namespace Celeste64.Mod; @@ -6,32 +7,32 @@ class KeyboardHandler { public static readonly Dictionary KeyValues = new Dictionary { - { "A", "A" }, - { "B", "B" }, - { "C", "C" }, - { "D", "D" }, - { "E", "E" }, - { "F", "F" }, - { "G", "G" }, - { "H", "H" }, - { "I", "I" }, - { "J", "J" }, - { "K", "K" }, - { "L", "L" }, - { "M", "M" }, - { "N", "N" }, - { "O", "O" }, - { "P", "P" }, - { "Q", "Q" }, - { "R", "R" }, - { "S", "S" }, - { "T", "T" }, - { "U", "U" }, - { "V", "V" }, - { "W", "W" }, - { "X", "X" }, - { "Y", "Y" }, - { "Z", "Z" }, + { "A", "a" }, + { "B", "b" }, + { "C", "c" }, + { "D", "d" }, + { "E", "e" }, + { "F", "f" }, + { "G", "g" }, + { "H", "h" }, + { "I", "i" }, + { "J", "j" }, + { "K", "k" }, + { "L", "l" }, + { "M", "m" }, + { "N", "n" }, + { "O", "o" }, + { "P", "p" }, + { "Q", "q" }, + { "R", "r" }, + { "S", "s" }, + { "T", "t" }, + { "U", "u" }, + { "V", "v" }, + { "W", "w" }, + { "X", "x" }, + { "Y", "y" }, + { "Z", "z" }, { "D1", "1" }, { "D2", "2" }, { "D3", "3" }, @@ -42,7 +43,7 @@ class KeyboardHandler { "D8", "8" }, { "D9", "9" }, { "D0", "0" }, - { "Space", "_" }, + { "Space", " " }, { "Minus", "-" }, { "Equals", "=" }, { "LeftBracket", "[" }, @@ -78,6 +79,87 @@ class KeyboardHandler { "KeypadLeftBrace", "{" }, { "KeypadRightBrace", "}" }, { "KeypadTab", "\t" }, + { "KeypadA", "a" }, + { "KeypadB", "b" }, + { "KeypadC", "c" }, + { "KeypadD", "d" }, + { "KeypadE", "e" }, + { "KeypadF", "f" } + }; + public static readonly Dictionary KeyValuesWithModifiers = new Dictionary + { + { "A", "A" }, + { "B", "B" }, + { "C", "C" }, + { "D", "D" }, + { "E", "E" }, + { "F", "F" }, + { "G", "G" }, + { "H", "H" }, + { "I", "I" }, + { "J", "J" }, + { "K", "K" }, + { "L", "L" }, + { "M", "M" }, + { "N", "N" }, + { "O", "O" }, + { "P", "P" }, + { "Q", "Q" }, + { "R", "R" }, + { "S", "S" }, + { "T", "T" }, + { "U", "U" }, + { "V", "V" }, + { "W", "W" }, + { "X", "X" }, + { "Y", "Y" }, + { "Z", "Z" }, + { "D1", "!" }, + { "D2", "@" }, + { "D3", "#" }, + { "D4", "$" }, + { "D5", "%" }, + { "D6", "^" }, + { "D7", "&" }, + { "D8", "*" }, + { "D9", "(" }, + { "D0", ")" }, + { "Space", " " }, + { "Minus", "_" }, + { "Equals", "+" }, + { "LeftBracket", "{" }, + { "RightBracket", "}" }, + { "Backslash", "|" }, + { "Semicolon", ":" }, + { "Apostrophe", "\"" }, + { "Tilde", "~" }, + { "Comma", "<" }, + { "Period", ">" }, + { "Slash", "?" }, + { "Keypad0", ")" }, + { "Keypad00", ")" }, + { "Keypad000", ")" }, + { "Keypad1", "!" }, + { "Keypad2", "@" }, + { "Keypad3", "#" }, + { "Keypad4", "$" }, + { "Keypad5", "%" }, + { "Keypad6", "^" }, + { "Keypad7", "&" }, + { "Keypad8", "*" }, + { "Keypad9", "(" }, + { "KeypadDivide", "/" }, + { "KeypadMultiply", "*" }, + { "KeypadMinus", "_" }, + { "KeypadPlus", "+" }, + { "KeypadPeroid", ">" }, + { "KeypadEquals", "+" }, + { "KeypadComma", "<" }, + { "KeypadLeftParen", "(" }, + { "KeypadRightParen", ")" }, + { "KeypadLeftBrace", "{" }, + { "KeypadRightBrace", "}" }, + { "KeypadTab", "\t" }, { "KeypadA", "A" }, { "KeypadB", "B" }, { "KeypadC", "C" }, @@ -85,15 +167,26 @@ class KeyboardHandler { "KeypadE", "E" }, { "KeypadF", "F" } }; + private Keys? previousKey; public static KeyboardHandler Instance = new(); public static string GetKeyName(Keys? key) { - if (KeyValues.ContainsKey(key.ToString())) - return KeyValues[key.ToString()]; + if (Input.Keyboard.Shift) + { + if (KeyValuesWithModifiers.ContainsKey(key.ToString())) + return KeyValuesWithModifiers[key.ToString()]; + else + return string.Empty; + } else - return string.Empty; + { + if (KeyValues.ContainsKey(key.ToString())) + return KeyValues[key.ToString()]; + else + return string.Empty; + } } public Keys? GetLastKey() From 2afc94d02b539648c9c0b4566eea232fae637a0c Mon Sep 17 00:00:00 2001 From: = <=> Date: Thu, 28 Mar 2024 18:47:15 -0500 Subject: [PATCH 03/24] Added on screen keyboard for renaming saves --- Source/Data/Controls.cs | 7 +- .../Data/PersistedData/ControlsConfig_V01.cs | 4 + Source/Helpers/Menu.cs | 23 ++- Source/Mod/Menu/OnScreenKeyboardMenu.cs | 180 ++++++++++++++++++ Source/Mod/Menu/SaveSelectionMenu.cs | 4 +- Source/Mod/Patches/KeyboardHandler.cs | 41 ++-- Source/Scenes/Overworld.cs | 5 +- 7 files changed, 239 insertions(+), 25 deletions(-) create mode 100644 Source/Mod/Menu/OnScreenKeyboardMenu.cs diff --git a/Source/Data/Controls.cs b/Source/Data/Controls.cs index 0e4c4cf8..c1ac6fba 100644 --- a/Source/Data/Controls.cs +++ b/Source/Data/Controls.cs @@ -12,6 +12,7 @@ public static class Controls public static readonly VirtualButton Dash = new("Dash", .1f); public static readonly VirtualButton Climb = new("Climb"); public static readonly VirtualButton Confirm = new("Confirm"); + public static readonly VirtualButton ControlerConfirm = new("ControlerConfirm"); public static readonly VirtualButton Cancel = new("Cancel"); public static readonly VirtualButton Pause = new("Pause"); public static readonly VirtualButton CopyFile = new("CopyFile"); @@ -100,6 +101,8 @@ static List FindAction(ControlsConfig_V01? config, st it.BindTo(CreateFile); foreach (var it in FindAction(config, "RenameFile")) it.BindTo(RenameFile); + foreach (var it in FindAction(config, "ControlerConfirm")) + it.BindTo(ControlerConfirm); } @@ -118,6 +121,7 @@ public static void Clear() DeleteFile.Clear(); CreateFile.Clear(); RenameFile.Clear(); + ControlerConfirm.Clear(); } public static void Consume() @@ -135,6 +139,7 @@ public static void Consume() DeleteFile.Consume(); CreateFile.Consume(); RenameFile.Consume(); + ControlerConfirm.Consume(); } private static readonly Dictionary> prompts = []; @@ -167,7 +172,7 @@ public static string GetPromptLocation(VirtualButton button) { // TODO: instead, query the button's actual bindings and look up a // texture based on that! no time tho - if (button == Confirm) + if (button == Confirm || button == ControlerConfirm) return GetPromptLocation("confirm"); else if (button == Cancel) return GetPromptLocation("cancel"); diff --git a/Source/Data/PersistedData/ControlsConfig_V01.cs b/Source/Data/PersistedData/ControlsConfig_V01.cs index 9400e4b2..a2f685c6 100644 --- a/Source/Data/PersistedData/ControlsConfig_V01.cs +++ b/Source/Data/PersistedData/ControlsConfig_V01.cs @@ -39,6 +39,10 @@ public class ControlsConfig_V01 : PersistedData new(Buttons.South) { NotFor = Gamepads.Nintendo }, new(Buttons.East) { OnlyFor = Gamepads.Nintendo }, ], + ["ControlerConfirm"] = [ + new(Buttons.South) { NotFor = Gamepads.Nintendo }, + new(Buttons.East) { OnlyFor = Gamepads.Nintendo }, + ], ["Cancel"] = [ new(Keys.X), new(Buttons.East) { NotFor = Gamepads.Nintendo }, diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index 2a444a4c..a29b9de2 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -206,7 +206,7 @@ private static List GetEnumOptions() } } - public class InputField(Loc.Localized locString, Action set, Func get) : Item + public class InputField(Loc.Localized locString, Action set, Func get, Menu rootMenu) : Item { public override Loc.Localized LocString => locString; @@ -216,7 +216,6 @@ public class InputField(Loc.Localized locString, Action set, Func SetFieldText(s), GetFieldText); + rootMenu.PushSubMenu(keyboardMenu); + return true; + } } public int Index; @@ -424,7 +441,7 @@ protected virtual void HandleInput() if (Controls.Menu.Horizontal.Positive.Pressed) items[Index].Slide(1); - if (Controls.Confirm.Pressed && items[Index].Pressed()) + if (Controls.Confirm.Pressed && items[Index].Pressed() || Controls.ControlerConfirm.Pressed && items[Index].Pressed()) Controls.Consume(); } } diff --git a/Source/Mod/Menu/OnScreenKeyboardMenu.cs b/Source/Mod/Menu/OnScreenKeyboardMenu.cs new file mode 100644 index 00000000..e96952c2 --- /dev/null +++ b/Source/Mod/Menu/OnScreenKeyboardMenu.cs @@ -0,0 +1,180 @@ +using System; + +namespace Celeste64.Mod; + +public class OnScreenKeyboardMenu : Menu +{ + public Target Target; + public Target GameTarget; + + private int currentPage = 0; + private int currentRow = 0; + private int currentColumn = 0; + + private const int rows = 7; + private const int columns = 9; + + private int CurrentPageStart => currentPage * columns * rows; + private int CurrentIndex => currentRow * columns + currentColumn; + bool shiftMode; + Action setter; + Func getter; + + string setText = string.Empty; + + internal OnScreenKeyboardMenu(Menu? rootMenu, Action set, Func get) + { + Target = new Target(Overworld.CardWidth, Overworld.CardHeight); + Game.OnResolutionChanged += () => Target = new Target(Overworld.CardWidth, Overworld.CardHeight); + GameTarget = new Target(Game.Width, Game.Height); + RootMenu = rootMenu; + setter = set; + getter = get; + setText = get(); + } + + public override void Initialized() + { + base.Initialized(); + currentColumn = 0; + currentRow = 0; + currentPage = 0; + } + + private void RenderCharacter(Batcher batch, string character, Vec2 pos, Vec2 size) + { + batch.PushMatrix(Matrix3x2.CreateScale(1.1f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); + batch.Text(Language.Current.SpriteFont, character, Vec2.Zero, new Vec2(0.5f, 0), Color.Black); + + batch.PopMatrix(); + + batch.PushMatrix(Matrix3x2.CreateScale(0.9f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); + batch.Text(Language.Current.SpriteFont, character, Vec2.Zero, new Vec2(0.5f, 0), Color.White); + + batch.PopMatrix(); + } + + private void RenderCurrentCharacter(Batcher batch, string character, Vec2 pos, Vec2 size) + { + batch.PushMatrix(Matrix3x2.CreateScale(1.1f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); + batch.Text(Language.Current.SpriteFont, character, Vec2.Zero, new Vec2(0.5f, 0), Color.Black); + + batch.PopMatrix(); + + batch.PushMatrix(Matrix3x2.CreateScale(0.9f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); + batch.Text(Language.Current.SpriteFont, character, Vec2.Zero, new Vec2(0.5f, 0), (Time.BetweenInterval(0.1f) ? 0x84FF54 : 0xFCFF59)); + + batch.PopMatrix(); + } + + private void RenderCharacters(Batcher batch) + { + var bounds = GameTarget.Bounds; + Vec2 size = new Vec2(bounds.Width, bounds.Height); + Vec2 offset = new Vec2(20, 20); + + int index = 0; + for (int i = 0; i < rows && CurrentPageStart + index < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count); i++) + { + for (int j = 0; j < columns && CurrentPageStart + index < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count); j++) + { + if (index == currentRow * columns + currentColumn) + { + RenderCurrentCharacter(batch, !shiftMode ? KeyboardHandler.TrimKeysList()[CurrentPageStart + index] : KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + index], new Vec2(j, i) * offset, size); + } + else + { + RenderCharacter(batch, !shiftMode ? KeyboardHandler.TrimKeysList()[CurrentPageStart + index] : KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + index], new Vec2(j, i) * offset, size); + } + index++; + } + } + } + + protected override void HandleInput() + { + if (Controls.Menu.Horizontal.Positive.Pressed) + { + if (currentColumn == columns - 1) + { + if (((currentPage + 1) * columns * rows) + (currentRow * columns) < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + { + currentPage++; + currentColumn = 0; + } + else if ((currentPage + 1) * columns * rows < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + { + currentPage++; + currentColumn = 0; + currentRow = 0; + } + } + else if (CurrentPageStart + CurrentIndex + 1 < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + { + currentColumn += 1; + } + Audio.Play(DownSound); + } + if (Controls.Menu.Horizontal.Negative.Pressed) + { + if (currentColumn == 0) + { + if (currentPage > 0) + { + currentPage--; + currentColumn = columns - 1; + } + } + else + { + currentColumn -= 1; + } + Audio.Play(DownSound); + } + + if (Controls.Menu.Vertical.Positive.Pressed && (currentRow + 1) < rows && CurrentPageStart + CurrentIndex + columns < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + { + currentRow += 1; + Audio.Play(DownSound); + } + if (Controls.Menu.Vertical.Negative.Pressed && (currentRow - 1) >= 0) + { + currentRow -= 1; + Audio.Play(DownSound); + } + if (Controls.CopyFile.Pressed) + shiftMode = !shiftMode; + + if (Controls.RenameFile.Pressed && setText.Length > 0) + { + setText = setText.Remove(setText.Length - 1); + setter(setText); + } + + if (Controls.Confirm.Pressed) + { + if (shiftMode) + { + setText += KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + CurrentIndex]; + setter(setText); + } + else + { + setText += KeyboardHandler.TrimKeysList()[CurrentPageStart + CurrentIndex]; + setter(setText); + } + Audio.Play(UpSound); + } + } + + protected override void RenderItems(Batcher batch) + { + batch.PushMatrix(new Vec2(GameTarget.Bounds.TopLeft.X, GameTarget.Bounds.TopLeft.Y), false); + + if (getter().Length == 0) + batch.Text(Language.Current.SpriteFont, "Enter text", new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf("Enter text") / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue * 0.6f); + + batch.Text(Language.Current.SpriteFont, getter(), new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(getter()) / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue); + RenderCharacters(batch); + } +} diff --git a/Source/Mod/Menu/SaveSelectionMenu.cs b/Source/Mod/Menu/SaveSelectionMenu.cs index 9361ba67..43d88e09 100644 --- a/Source/Mod/Menu/SaveSelectionMenu.cs +++ b/Source/Mod/Menu/SaveSelectionMenu.cs @@ -268,9 +268,9 @@ protected override void HandleInput() { Menu newMenu = new Menu(this); newMenu.Title = $"Rename this file: {saves[CurrentPageStart + CurrentIndex]}"; - newMenu.Add(new InputField("NewName", (k) => SetRename(k), GetRename)); + newMenu.Add(new InputField("NewName", (k) => SetRename(k), GetRename, newMenu)); newMenu.Add(new Option("OptionsYes", () => { - SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], GetRename()); + SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], renamedFileName); ResetSaves(); PopSubMenu(); renamedFileName = string.Empty; diff --git a/Source/Mod/Patches/KeyboardHandler.cs b/Source/Mod/Patches/KeyboardHandler.cs index 4d1e54d3..503d1ced 100644 --- a/Source/Mod/Patches/KeyboardHandler.cs +++ b/Source/Mod/Patches/KeyboardHandler.cs @@ -168,9 +168,35 @@ class KeyboardHandler { "KeypadF", "F" } }; + public static readonly List KeyValuesList = KeyValues.Values.ToList(); + public static readonly List KeyValuesWithModifiersList = KeyValuesWithModifiers.Values.ToList(); + + private Keys? previousKey; public static KeyboardHandler Instance = new(); + public static List TrimKeysList() + { + List newKeysList = new List(); + foreach (string key in KeyValuesList) + { + if (key.Length == 1 && !newKeysList.Contains(key) && key != " " && key != "" && key != "\t") + newKeysList.Add(key); + } + return newKeysList; + } + + public static List TrimModifiedKeysList() + { + List newKeysList = new List(); + foreach (string key in KeyValuesWithModifiersList) + { + if (key.Length == 1 && !newKeysList.Contains(key) && key != " " && key != "" && key != "\t") + newKeysList.Add(key); + } + return newKeysList; + } + public static string GetKeyName(Keys? key) { if (Input.Keyboard.Shift) @@ -189,24 +215,9 @@ public static string GetKeyName(Keys? key) } } - public Keys? GetLastKey() - { - return previousKey; - } - public Keys? GetPressedKey() { Keys? key = Input.Keyboard.FirstPressed(); return key; } - - public void ReadKeys() - { - Keys? key = Input.Keyboard.FirstPressed(); - if (key == null) - key = previousKey; - else - previousKey = key; - } - } diff --git a/Source/Scenes/Overworld.cs b/Source/Scenes/Overworld.cs index 027cd2fb..f63dce32 100644 --- a/Source/Scenes/Overworld.cs +++ b/Source/Scenes/Overworld.cs @@ -268,7 +268,6 @@ public void SlideSelectedMod(int dir) } #endregion - string SomethingFun = string.Empty; #region Update & Render public override void Update() { @@ -356,7 +355,7 @@ public override void Update() { Title = Loc.Str("PauseModsMenu") }; - + pauseMenu.Add(new Menu.Submenu("PauseOptions", pauseMenu, optionsMenu)); pauseMenu.Add(new Menu.Submenu("PauseSaves", pauseMenu, savesMenu)); pauseMenu.Add(new Menu.Submenu("PauseModsMenu", pauseMenu, modMenu)); @@ -619,8 +618,6 @@ public override void Render(Target target) { UI.Text(batch, Game.VersionString, bounds.BottomLeft + new Vec2(4, -4) * Game.RelativeScale, new Vec2(0, 1), Color.CornflowerBlue * 0.75f); UI.Text(batch, Game.LoaderVersion, bounds.BottomLeft + new Vec2(4, -24) * Game.RelativeScale, new Vec2(0, 1), new Color(12326399) * 0.75f); - UI.Text(batch, SomethingFun, bounds.BottomLeft + new Vec2(4, -44) * Game.RelativeScale, new Vec2(0, 1), new Color(12326399) * 0.75f); - if (ModLoader.FailedToLoadMods.Any()) { From 084d84be0710018290f4024c5668f7aabb5ed552 Mon Sep 17 00:00:00 2001 From: = <=> Date: Sat, 30 Mar 2024 14:22:27 -0500 Subject: [PATCH 04/24] Fixed crash when renaming file to one that already exists --- Source/Mod/Data/SaveManager.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index e6b34abd..5be68724 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -95,6 +95,8 @@ internal void ChangeFileName(string orignalFileName, string newFileName) if (!newFileName.EndsWith(".json")) newFileName += ".json"; newFileName = Regex.Replace(newFileName, invalidCharsPattern, "_"); + if (File.Exists(Path.Join(App.UserPath, "Saves", newFileName))) + return; File.Move(Path.Join(App.UserPath, "Saves", file), Path.Join(App.UserPath, "Saves", newFileName)); if (file == Save.Instance.FileName) LoadSaveByFileName(newFileName); From ceeffb30e9d22287db96547a974247ffbd687e49 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:25:32 +0200 Subject: [PATCH 05/24] Fix spelling of ControllerConfirm --- Source/Data/Controls.cs | 12 ++++++------ Source/Data/PersistedData/ControlsConfig_V01.cs | 2 +- Source/Helpers/Menu.cs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Data/Controls.cs b/Source/Data/Controls.cs index c1ac6fba..65b5cf4c 100644 --- a/Source/Data/Controls.cs +++ b/Source/Data/Controls.cs @@ -12,7 +12,7 @@ public static class Controls public static readonly VirtualButton Dash = new("Dash", .1f); public static readonly VirtualButton Climb = new("Climb"); public static readonly VirtualButton Confirm = new("Confirm"); - public static readonly VirtualButton ControlerConfirm = new("ControlerConfirm"); + public static readonly VirtualButton ControllerConfirm = new("ControllerConfirm"); public static readonly VirtualButton Cancel = new("Cancel"); public static readonly VirtualButton Pause = new("Pause"); public static readonly VirtualButton CopyFile = new("CopyFile"); @@ -101,8 +101,8 @@ static List FindAction(ControlsConfig_V01? config, st it.BindTo(CreateFile); foreach (var it in FindAction(config, "RenameFile")) it.BindTo(RenameFile); - foreach (var it in FindAction(config, "ControlerConfirm")) - it.BindTo(ControlerConfirm); + foreach (var it in FindAction(config, "ControllerConfirm")) + it.BindTo(ControllerConfirm); } @@ -121,7 +121,7 @@ public static void Clear() DeleteFile.Clear(); CreateFile.Clear(); RenameFile.Clear(); - ControlerConfirm.Clear(); + ControllerConfirm.Clear(); } public static void Consume() @@ -139,7 +139,7 @@ public static void Consume() DeleteFile.Consume(); CreateFile.Consume(); RenameFile.Consume(); - ControlerConfirm.Consume(); + ControllerConfirm.Consume(); } private static readonly Dictionary> prompts = []; @@ -172,7 +172,7 @@ public static string GetPromptLocation(VirtualButton button) { // TODO: instead, query the button's actual bindings and look up a // texture based on that! no time tho - if (button == Confirm || button == ControlerConfirm) + if (button == Confirm || button == ControllerConfirm) return GetPromptLocation("confirm"); else if (button == Cancel) return GetPromptLocation("cancel"); diff --git a/Source/Data/PersistedData/ControlsConfig_V01.cs b/Source/Data/PersistedData/ControlsConfig_V01.cs index a2f685c6..cdd8fdb4 100644 --- a/Source/Data/PersistedData/ControlsConfig_V01.cs +++ b/Source/Data/PersistedData/ControlsConfig_V01.cs @@ -39,7 +39,7 @@ public class ControlsConfig_V01 : PersistedData new(Buttons.South) { NotFor = Gamepads.Nintendo }, new(Buttons.East) { OnlyFor = Gamepads.Nintendo }, ], - ["ControlerConfirm"] = [ + ["ControllerConfirm"] = [ new(Buttons.South) { NotFor = Gamepads.Nintendo }, new(Buttons.East) { OnlyFor = Gamepads.Nintendo }, ], diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index a29b9de2..b436c9d7 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -441,7 +441,7 @@ protected virtual void HandleInput() if (Controls.Menu.Horizontal.Positive.Pressed) items[Index].Slide(1); - if (Controls.Confirm.Pressed && items[Index].Pressed() || Controls.ControlerConfirm.Pressed && items[Index].Pressed()) + if (Controls.Confirm.Pressed && items[Index].Pressed() || Controls.ControllerConfirm.Pressed && items[Index].Pressed()) Controls.Consume(); } } From 0d2176d730ce68d1b5bb4f296861f28e608a1496 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Sun, 31 Mar 2024 23:36:02 +0200 Subject: [PATCH 06/24] Fix missing directory error for first launch --- Source/Mod/Data/SaveManager.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index e6b34abd..42373610 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -13,6 +13,7 @@ internal string GetLastLoadedSave() return File.ReadAllText(Path.Join(App.UserPath, "Saves", "save.metadata")); else { + Directory.CreateDirectory(Path.Join(App.UserPath, "Saves")); // Perform upgrade path for first-time launch File.WriteAllText(Path.Join(App.UserPath, "Saves", "save.metadata"), Save.DefaultFileName); return Save.DefaultFileName; } From a6a327d75347741126d5fcdebe590098ba776df4 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:15:31 +0200 Subject: [PATCH 07/24] Refactor: Centralize text input handling in OnScreenKeyboardMenu --- Source/Helpers/Menu.cs | 53 ++++++++++----------- Source/Mod/Menu/OnScreenKeyboardMenu.cs | 63 ++++++++++++++++++------- Source/Scenes/Overworld.cs | 11 ++++- 3 files changed, 81 insertions(+), 46 deletions(-) diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index b436c9d7..d7007dd3 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -206,50 +206,45 @@ private static List GetEnumOptions() } } - public class InputField(Loc.Localized locString, Action set, Func get, Menu rootMenu) : Item + public class InputField : Item { - public override Loc.Localized LocString => locString; + public OnScreenKeyboardMenu keyboardMenu; - private string fieldText = get(); - public override string Label => $"{LocString} : {fieldText}"; + private Action setter; + private Func getter; - private Keys? key; - public override void GetKeyPress() - { - key = KeyboardHandler.Instance.GetPressedKey(); + public Menu RootMenu { get; protected set; } - Controls.Confirm.ConsumePress(); - Controls.Cancel.ConsumePress(); - if (key != null) - { - if (key == Keys.Backspace || key == Keys.KeypadBackspace) - { - if (fieldText.Length > 0) - fieldText = fieldText.Remove(fieldText.Length - 1); - } - else - fieldText += KeyboardHandler.GetKeyName(key); - set(fieldText); - } - } + private string fieldText; + public override string Label => $"{LocString} : {getter()}"; - private void SetFieldText(string text) + public void SetFieldText(string text) { fieldText = text; - set(fieldText); + setter(fieldText); } - private string GetFieldText() + public string GetFieldText() { - return fieldText; + return getter(); } public override bool Pressed() { - OnScreenKeyboardMenu keyboardMenu = new OnScreenKeyboardMenu(rootMenu, (s) => SetFieldText(s), GetFieldText); - rootMenu.PushSubMenu(keyboardMenu); + RootMenu.PushSubMenu(keyboardMenu); return true; } + + public InputField(Loc.Localized locString, Action set, Func get, Menu rootMenu) + { + LocString = locString; + setter = set; + getter = get; + RootMenu = rootMenu; + fieldText = getter(); + + keyboardMenu = new OnScreenKeyboardMenu(rootMenu, this); + } } public int Index; @@ -264,7 +259,7 @@ public override bool Pressed() public string DownSound = Sfx.ui_move; public bool IsInMainMenu => submenus.Count <= 0; - protected Menu CurrentMenu => GetDeepestActiveSubmenu(this); + public Menu CurrentMenu => GetDeepestActiveSubmenu(this); protected virtual int maxItemsCount { get; set; } = 12; protected int scrolledAmount = 0; diff --git a/Source/Mod/Menu/OnScreenKeyboardMenu.cs b/Source/Mod/Menu/OnScreenKeyboardMenu.cs index e96952c2..c83548a3 100644 --- a/Source/Mod/Menu/OnScreenKeyboardMenu.cs +++ b/Source/Mod/Menu/OnScreenKeyboardMenu.cs @@ -17,20 +17,19 @@ public class OnScreenKeyboardMenu : Menu private int CurrentPageStart => currentPage * columns * rows; private int CurrentIndex => currentRow * columns + currentColumn; bool shiftMode; - Action setter; - Func getter; string setText = string.Empty; - internal OnScreenKeyboardMenu(Menu? rootMenu, Action set, Func get) + InputField Owner; + + internal OnScreenKeyboardMenu(Menu? rootMenu, InputField owner) { Target = new Target(Overworld.CardWidth, Overworld.CardHeight); Game.OnResolutionChanged += () => Target = new Target(Overworld.CardWidth, Overworld.CardHeight); GameTarget = new Target(Game.Width, Game.Height); RootMenu = rootMenu; - setter = set; - getter = get; - setText = get(); + + Owner = owner; } public override void Initialized() @@ -39,6 +38,13 @@ public override void Initialized() currentColumn = 0; currentRow = 0; currentPage = 0; + + setText = Owner.GetFieldText(); + } + + public override void Closed() + { + Owner.SetFieldText(setText); } private void RenderCharacter(Batcher batch, string character, Vec2 pos, Vec2 size) @@ -58,7 +64,7 @@ private void RenderCurrentCharacter(Batcher batch, string character, Vec2 pos, V { batch.PushMatrix(Matrix3x2.CreateScale(1.1f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); batch.Text(Language.Current.SpriteFont, character, Vec2.Zero, new Vec2(0.5f, 0), Color.Black); - + batch.PopMatrix(); batch.PushMatrix(Matrix3x2.CreateScale(0.9f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); @@ -81,7 +87,7 @@ private void RenderCharacters(Batcher batch) if (index == currentRow * columns + currentColumn) { RenderCurrentCharacter(batch, !shiftMode ? KeyboardHandler.TrimKeysList()[CurrentPageStart + index] : KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + index], new Vec2(j, i) * offset, size); - } + } else { RenderCharacter(batch, !shiftMode ? KeyboardHandler.TrimKeysList()[CurrentPageStart + index] : KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + index], new Vec2(j, i) * offset, size); @@ -142,39 +148,64 @@ protected override void HandleInput() currentRow -= 1; Audio.Play(DownSound); } - if (Controls.CopyFile.Pressed) + /* + * The next three controls are only relevant to gamepads. + * We check if a keyboard key is pressed to avoid conflicts. + */ + if (Controls.CopyFile.Pressed && KeyboardHandler.Instance.GetPressedKey() == null) shiftMode = !shiftMode; - if (Controls.RenameFile.Pressed && setText.Length > 0) + if (Controls.RenameFile.Pressed && setText.Length > 0 && KeyboardHandler.Instance.GetPressedKey() == null) { setText = setText.Remove(setText.Length - 1); - setter(setText); } - if (Controls.Confirm.Pressed) + if (Controls.Confirm.Pressed && KeyboardHandler.Instance.GetPressedKey() == null) { if (shiftMode) { setText += KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + CurrentIndex]; - setter(setText); } else { setText += KeyboardHandler.TrimKeysList()[CurrentPageStart + CurrentIndex]; - setter(setText); } Audio.Play(UpSound); } + + if (KeyboardHandler.Instance.GetPressedKey() is Keys.Enter or Keys.Enter2 or Keys.KeypadEnter) + { + Owner.RootMenu.PopSubMenu(); + } + + ReadKey(); } protected override void RenderItems(Batcher batch) { batch.PushMatrix(new Vec2(GameTarget.Bounds.TopLeft.X, GameTarget.Bounds.TopLeft.Y), false); - if (getter().Length == 0) + if (setText.Length == 0) batch.Text(Language.Current.SpriteFont, "Enter text", new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf("Enter text") / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue * 0.6f); - batch.Text(Language.Current.SpriteFont, getter(), new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(getter()) / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue); + batch.Text(Language.Current.SpriteFont, setText, new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(setText) / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue); RenderCharacters(batch); } + + private Keys? key; + public void ReadKey() + { + key = KeyboardHandler.Instance.GetPressedKey(); + + if (key != null) + { + if (key == Keys.Backspace || key == Keys.KeypadBackspace) + { + if (setText.Length > 0) + setText = setText.Remove(setText.Length - 1); + } + else + setText += KeyboardHandler.GetKeyName(key); + } + } } diff --git a/Source/Scenes/Overworld.cs b/Source/Scenes/Overworld.cs index 01bb8fc0..c6bed779 100644 --- a/Source/Scenes/Overworld.cs +++ b/Source/Scenes/Overworld.cs @@ -355,7 +355,7 @@ public override void Update() { Title = Loc.Str("PauseModsMenu") }; - + pauseMenu.Add(new Menu.Submenu("PauseOptions", pauseMenu, optionsMenu)); pauseMenu.Add(new Menu.Submenu("PauseSaves", pauseMenu, savesMenu)); pauseMenu.Add(new Menu.Submenu("PauseModsMenu", pauseMenu, modMenu)); @@ -432,6 +432,15 @@ public override void Update() } else if (Paused) { + /* + * Edge case handler for the OSK, since it has a special case for pressing Enter. + * Enter also happens to be a default binding for pausing. I wish I was kidding. + */ + if ((KeyboardHandler.Instance.GetPressedKey() is Keys.Enter or Keys.Enter2 or Keys.KeypadEnter) && pauseMenu?.CurrentMenu is OnScreenKeyboardMenu) + { + return; + } + if (Controls.Pause.ConsumePress() || (pauseMenu is { IsInMainMenu: true } && Controls.Cancel.ConsumePress())) { if (pauseMenu != null) From a81e471599f17f380c714bc2fae9cd0663094eb7 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:17:47 +0200 Subject: [PATCH 08/24] Reorder pushing and adding menu items, also format --- Source/Mod/Menu/SaveSelectionMenu.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/Mod/Menu/SaveSelectionMenu.cs b/Source/Mod/Menu/SaveSelectionMenu.cs index 43d88e09..acd61bf5 100644 --- a/Source/Mod/Menu/SaveSelectionMenu.cs +++ b/Source/Mod/Menu/SaveSelectionMenu.cs @@ -260,8 +260,8 @@ protected override void HandleInput() ResetSaves(); PopSubMenu(); })); - PushSubMenu(newMenu); newMenu.Add(new Option("OptionsNo", () => PopSubMenu())); + PushSubMenu(newMenu); } if (Controls.RenameFile.Pressed) @@ -269,17 +269,19 @@ protected override void HandleInput() Menu newMenu = new Menu(this); newMenu.Title = $"Rename this file: {saves[CurrentPageStart + CurrentIndex]}"; newMenu.Add(new InputField("NewName", (k) => SetRename(k), GetRename, newMenu)); - newMenu.Add(new Option("OptionsYes", () => { + newMenu.Add(new Option("OptionsYes", () => + { SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], renamedFileName); ResetSaves(); PopSubMenu(); renamedFileName = string.Empty; })); - PushSubMenu(newMenu); - newMenu.Add(new Option("OptionsNo", () => { + newMenu.Add(new Option("OptionsNo", () => + { renamedFileName = string.Empty; PopSubMenu(); })); + PushSubMenu(newMenu); } } From 5fe86be2d07cff2b5b2222f20ee965d371f181ff Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:22:20 +0200 Subject: [PATCH 09/24] Fix typo, catch errors during file rename --- Source/Mod/Data/SaveManager.cs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index 42373610..b2fe3806 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -85,20 +85,28 @@ internal void NewSave(string? name = null) } [DisallowHooks] - internal void ChangeFileName(string orignalFileName, string newFileName) + internal void ChangeFileName(string originalFileName, string newFileName) { string invalidCharsPattern = "[\\/:*?\"<>|{}]"; foreach (string file in GetSaves()) { - if (file == orignalFileName) + if (file == originalFileName) { - if (!newFileName.EndsWith(".json")) - newFileName += ".json"; - newFileName = Regex.Replace(newFileName, invalidCharsPattern, "_"); - File.Move(Path.Join(App.UserPath, "Saves", file), Path.Join(App.UserPath, "Saves", newFileName)); - if (file == Save.Instance.FileName) - LoadSaveByFileName(newFileName); + try + { + if (!newFileName.EndsWith(".json")) + newFileName += ".json"; + newFileName = Regex.Replace(newFileName, invalidCharsPattern, "_"); + File.Move(Path.Join(App.UserPath, "Saves", file), Path.Join(App.UserPath, "Saves", newFileName)); + if (file == Save.Instance.FileName) + LoadSaveByFileName(newFileName); + } + catch (Exception e) + { + Log.Error($"Failed to rename save file {originalFileName} to {newFileName}"); + Log.Error(e.ToString()); + } } } } From 4c20d3ebdf8dcbb52581ca0b67b3111f99c94a5d Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:33:22 +0200 Subject: [PATCH 10/24] Show user-friendly error message for rename failure. Handle deletion cases better --- Source/Mod/Data/SaveManager.cs | 7 ++++++- Source/Mod/Menu/SaveSelectionMenu.cs | 12 ++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index b2fe3806..2fa4ec31 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -85,8 +85,9 @@ internal void NewSave(string? name = null) } [DisallowHooks] - internal void ChangeFileName(string originalFileName, string newFileName) + internal bool ChangeFileName(string originalFileName, string newFileName) { + bool success = true; string invalidCharsPattern = "[\\/:*?\"<>|{}]"; foreach (string file in GetSaves()) @@ -106,9 +107,13 @@ internal void ChangeFileName(string originalFileName, string newFileName) { Log.Error($"Failed to rename save file {originalFileName} to {newFileName}"); Log.Error(e.ToString()); + + success = false; } } } + + return success; } [DisallowHooks] diff --git a/Source/Mod/Menu/SaveSelectionMenu.cs b/Source/Mod/Menu/SaveSelectionMenu.cs index acd61bf5..0ccdebc0 100644 --- a/Source/Mod/Menu/SaveSelectionMenu.cs +++ b/Source/Mod/Menu/SaveSelectionMenu.cs @@ -217,7 +217,7 @@ protected override void HandleInput() if (Controls.DeleteFile.Pressed) { Menu newMenu = new Menu(this); - if (saves[CurrentPageStart + CurrentIndex] == Save.DefaultFileName) + if (saves.Count == 1 || saves[CurrentPageStart + CurrentIndex] == Save.Instance.FileName) { newMenu.Title = string.Format(Loc.Str("SaveDeleteDefaultFile"), saves[CurrentPageStart + CurrentIndex]); } @@ -229,9 +229,9 @@ protected override void HandleInput() { if (Game.Instance.IsMidTransition) return; SaveManager.Instance.DeleteSave(saves[CurrentPageStart + CurrentIndex]); - if (saves[CurrentPageStart + CurrentIndex] == Save.Instance.FileName) + if ((saves[CurrentPageStart + CurrentIndex] == Save.Instance.FileName) || (saves.Count == 1)) { - // If we delete the current save, load default and force a reload + // If we delete the current save or the last remaining save, load default and force a reload SaveManager.Instance.LoadSaveByFileName(Save.DefaultFileName); Game.Instance.Goto(new Transition() { @@ -271,7 +271,11 @@ protected override void HandleInput() newMenu.Add(new InputField("NewName", (k) => SetRename(k), GetRename, newMenu)); newMenu.Add(new Option("OptionsYes", () => { - SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], renamedFileName); + bool renameSuccess = SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], renamedFileName); + if (!renameSuccess) + { + Title = "Failed to rename... Check your log file for details\n(does the file already exist?)"; + } ResetSaves(); PopSubMenu(); renamedFileName = string.Empty; From 1fd2406ea9dff0357351ee94ad41078dc7bd3b85 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:38:43 +0200 Subject: [PATCH 11/24] Adjust loc strings, make files when loading if they don't exist yet --- Content/Text/English.json | 14 ++++++-------- Source/Mod/Data/SaveManager.cs | 4 ++++ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Content/Text/English.json b/Content/Text/English.json index 42e8d319..792e23b9 100644 --- a/Content/Text/English.json +++ b/Content/Text/English.json @@ -28,8 +28,8 @@ "PauseSaveQuit.desc": "Save & Quit to the Title Screen", "PauseSaves": "Saves", "PauseSaves.desc": "Open the Save Select Menu", - "PauseModsMenu" : "Mods", - "PauseModsMenu.desc" : "Open the Mods Menu", + "PauseModsMenu": "Mods", + "PauseModsMenu.desc": "Open the Mods Menu", "OptionsTitle": "Options", "OptionsFullscreen": "Fullscreen", "OptionsFullscreen.desc": "Control if the Game is Fullscreen or Windowed", @@ -47,14 +47,12 @@ "OptionsToggleOff": "OFF", "OptionsYes": "Yes", "OptionsNo": "No", - "Skin": "Skin", "Skin.desc": "Choose a Skin to Wear", - - "SaveCreateFile": "Create new file?" , - "SaveDeleteFile": "Delete this file?" , - "SaveDeleteDefaultFile": "Cannot fully delete default save file:'{0}'. Reset it to default instead?", - "SaveCopyFile": "Copy this file?" , + "SaveCreateFile": "Create new file?", + "SaveDeleteFile": "Delete this file?", + "SaveDeleteDefaultFile": "The file {0} cannot be deleted.\n\nThis may happen because the file is the only existing file,\nor because it is currently loaded.\n\nDo you want to reset it to default instead?", + "SaveCopyFile": "Copy this file?", "FujiOptions": "Fuji Options...", "FujiOptions.desc": "Configure Options for the Fuji Mod Loader", "FujiWriteLog": "Write Log File", diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index 2fa4ec31..636e26f6 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -139,6 +139,10 @@ internal void DeleteSave(string save) [DisallowHooks] internal void LoadSaveByFileName(string fileName) { + if (!GetSaves().Contains(fileName)) // Make file if it doesn't exist yet + { + NewSave(fileName); + } Save.LoadSaveByFileName(fileName); Instance.SetLastLoadedSave(fileName); } From 63d5c731cec57d81bd49c26e2a9e84e578ca20a5 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:40:55 +0200 Subject: [PATCH 12/24] Adjust strings again --- Content/Text/English.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Content/Text/English.json b/Content/Text/English.json index 792e23b9..a1bafe7b 100644 --- a/Content/Text/English.json +++ b/Content/Text/English.json @@ -51,7 +51,7 @@ "Skin.desc": "Choose a Skin to Wear", "SaveCreateFile": "Create new file?", "SaveDeleteFile": "Delete this file?", - "SaveDeleteDefaultFile": "The file {0} cannot be deleted.\n\nThis may happen because the file is the only existing file,\nor because it is currently loaded.\n\nDo you want to reset it to default instead?", + "SaveDeleteDefaultFile": "The file {0} cannot be deleted.\n\nThis may happen because the file is the only existing file,\nor because it is currently loaded.\n\nDo you want to reset to the default file instead?", "SaveCopyFile": "Copy this file?", "FujiOptions": "Fuji Options...", "FujiOptions.desc": "Configure Options for the Fuji Mod Loader", From 56c4b1d829cf4277f5bfb8232dde17139a3f64d8 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:45:45 +0200 Subject: [PATCH 13/24] Convert some hard-coded strings to loc keys --- Content/Text/English.json | 2 ++ Source/Mod/Menu/SaveSelectionMenu.cs | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Content/Text/English.json b/Content/Text/English.json index a1bafe7b..61f1fdc2 100644 --- a/Content/Text/English.json +++ b/Content/Text/English.json @@ -53,6 +53,8 @@ "SaveDeleteFile": "Delete this file?", "SaveDeleteDefaultFile": "The file {0} cannot be deleted.\n\nThis may happen because the file is the only existing file,\nor because it is currently loaded.\n\nDo you want to reset to the default file instead?", "SaveCopyFile": "Copy this file?", + "SaveRenameFile": "Renaming file: {0}", + "SaveRenameFailed": "Failed to rename... Check your log file for details\n(does the file already exist?)", "FujiOptions": "Fuji Options...", "FujiOptions.desc": "Configure Options for the Fuji Mod Loader", "FujiWriteLog": "Write Log File", diff --git a/Source/Mod/Menu/SaveSelectionMenu.cs b/Source/Mod/Menu/SaveSelectionMenu.cs index 0ccdebc0..bfd01858 100644 --- a/Source/Mod/Menu/SaveSelectionMenu.cs +++ b/Source/Mod/Menu/SaveSelectionMenu.cs @@ -267,14 +267,14 @@ protected override void HandleInput() if (Controls.RenameFile.Pressed) { Menu newMenu = new Menu(this); - newMenu.Title = $"Rename this file: {saves[CurrentPageStart + CurrentIndex]}"; + newMenu.Title = string.Format(Loc.Str("SaveRenameFile"), saves[CurrentPageStart + CurrentIndex]); newMenu.Add(new InputField("NewName", (k) => SetRename(k), GetRename, newMenu)); newMenu.Add(new Option("OptionsYes", () => { bool renameSuccess = SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], renamedFileName); if (!renameSuccess) { - Title = "Failed to rename... Check your log file for details\n(does the file already exist?)"; + Title = new Loc.Localized("SaveRenameFailed"); } ResetSaves(); PopSubMenu(); From 4900f238a6e3a4f1f5c380e984e995f7cc241370 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 01:54:47 +0200 Subject: [PATCH 14/24] Resolve warnings in keyboard handler --- Source/Mod/Patches/KeyboardHandler.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Source/Mod/Patches/KeyboardHandler.cs b/Source/Mod/Patches/KeyboardHandler.cs index 503d1ced..2d2951d8 100644 --- a/Source/Mod/Patches/KeyboardHandler.cs +++ b/Source/Mod/Patches/KeyboardHandler.cs @@ -171,8 +171,6 @@ class KeyboardHandler public static readonly List KeyValuesList = KeyValues.Values.ToList(); public static readonly List KeyValuesWithModifiersList = KeyValuesWithModifiers.Values.ToList(); - - private Keys? previousKey; public static KeyboardHandler Instance = new(); public static List TrimKeysList() @@ -199,17 +197,21 @@ public static List TrimModifiedKeysList() public static string GetKeyName(Keys? key) { + string? keyString = key.ToString(); + + if (keyString == null) return string.Empty; + if (Input.Keyboard.Shift) { - if (KeyValuesWithModifiers.ContainsKey(key.ToString())) - return KeyValuesWithModifiers[key.ToString()]; + if (KeyValuesWithModifiers.ContainsKey(keyString)) + return KeyValuesWithModifiers[keyString]; else return string.Empty; } else { - if (KeyValues.ContainsKey(key.ToString())) - return KeyValues[key.ToString()]; + if (KeyValues.ContainsKey(keyString)) + return KeyValues[keyString]; else return string.Empty; } From 311ac91a303c5081df832eaa2ec447c8d9a9fd20 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 02:25:18 +0200 Subject: [PATCH 15/24] quick fix: prevent cancel button from interrupting --- Source/Mod/Menu/OnScreenKeyboardMenu.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Mod/Menu/OnScreenKeyboardMenu.cs b/Source/Mod/Menu/OnScreenKeyboardMenu.cs index c83548a3..732a0226 100644 --- a/Source/Mod/Menu/OnScreenKeyboardMenu.cs +++ b/Source/Mod/Menu/OnScreenKeyboardMenu.cs @@ -149,7 +149,7 @@ protected override void HandleInput() Audio.Play(DownSound); } /* - * The next three controls are only relevant to gamepads. + * The next four controls are only relevant to gamepads. * We check if a keyboard key is pressed to avoid conflicts. */ if (Controls.CopyFile.Pressed && KeyboardHandler.Instance.GetPressedKey() == null) @@ -173,6 +173,11 @@ protected override void HandleInput() Audio.Play(UpSound); } + if (Controls.Cancel.ConsumePress() && KeyboardHandler.Instance.GetPressedKey() == null) + { + Owner.RootMenu.PopSubMenu(); + } + if (KeyboardHandler.Instance.GetPressedKey() is Keys.Enter or Keys.Enter2 or Keys.KeypadEnter) { Owner.RootMenu.PopSubMenu(); From 84d5ccae744e6fd5ce87bfed72e192ba9894da37 Mon Sep 17 00:00:00 2001 From: Axi <98420477+axiand@users.noreply.github.com> Date: Mon, 1 Apr 2024 02:44:38 +0200 Subject: [PATCH 16/24] Add basic instructions for the keyboard --- Content/Text/English.json | 1 + Source/Mod/Menu/OnScreenKeyboardMenu.cs | 1 + 2 files changed, 2 insertions(+) diff --git a/Content/Text/English.json b/Content/Text/English.json index 61f1fdc2..22363616 100644 --- a/Content/Text/English.json +++ b/Content/Text/English.json @@ -55,6 +55,7 @@ "SaveCopyFile": "Copy this file?", "SaveRenameFile": "Renaming file: {0}", "SaveRenameFailed": "Failed to rename... Check your log file for details\n(does the file already exist?)", + "OSKUserInstructions": "Press Enter on keyboard, or Back on controller to confirm.", "FujiOptions": "Fuji Options...", "FujiOptions.desc": "Configure Options for the Fuji Mod Loader", "FujiWriteLog": "Write Log File", diff --git a/Source/Mod/Menu/OnScreenKeyboardMenu.cs b/Source/Mod/Menu/OnScreenKeyboardMenu.cs index 732a0226..d37b3990 100644 --- a/Source/Mod/Menu/OnScreenKeyboardMenu.cs +++ b/Source/Mod/Menu/OnScreenKeyboardMenu.cs @@ -194,6 +194,7 @@ protected override void RenderItems(Batcher batch) batch.Text(Language.Current.SpriteFont, "Enter text", new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf("Enter text") / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue * 0.6f); batch.Text(Language.Current.SpriteFont, setText, new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(setText) / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue); + batch.Text(Language.Current.SpriteFont, Loc.Str("OSKUserInstructions"), new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(Loc.Str("OSKUserInstructions")) / 2, GameTarget.Bounds.TopCenter.Y + 284), Color.CornflowerBlue); RenderCharacters(batch); } From 0c8c57ca626e6c51f6a038040b9f00b3a19c25c0 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 1 Apr 2024 09:41:16 -0500 Subject: [PATCH 17/24] Fixed problem with level card moving while paused Removed ContollerConfirm --- Source/Data/Controls.cs | 8 +------- Source/Data/PersistedData/ControlsConfig_V01.cs | 4 ---- Source/Helpers/Menu.cs | 2 +- Source/Scenes/Overworld.cs | 6 +++++- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/Source/Data/Controls.cs b/Source/Data/Controls.cs index 65b5cf4c..66a42049 100644 --- a/Source/Data/Controls.cs +++ b/Source/Data/Controls.cs @@ -12,7 +12,6 @@ public static class Controls public static readonly VirtualButton Dash = new("Dash", .1f); public static readonly VirtualButton Climb = new("Climb"); public static readonly VirtualButton Confirm = new("Confirm"); - public static readonly VirtualButton ControllerConfirm = new("ControllerConfirm"); public static readonly VirtualButton Cancel = new("Cancel"); public static readonly VirtualButton Pause = new("Pause"); public static readonly VirtualButton CopyFile = new("CopyFile"); @@ -101,9 +100,6 @@ static List FindAction(ControlsConfig_V01? config, st it.BindTo(CreateFile); foreach (var it in FindAction(config, "RenameFile")) it.BindTo(RenameFile); - foreach (var it in FindAction(config, "ControllerConfirm")) - it.BindTo(ControllerConfirm); - } public static void Clear() @@ -121,7 +117,6 @@ public static void Clear() DeleteFile.Clear(); CreateFile.Clear(); RenameFile.Clear(); - ControllerConfirm.Clear(); } public static void Consume() @@ -139,7 +134,6 @@ public static void Consume() DeleteFile.Consume(); CreateFile.Consume(); RenameFile.Consume(); - ControllerConfirm.Consume(); } private static readonly Dictionary> prompts = []; @@ -172,7 +166,7 @@ public static string GetPromptLocation(VirtualButton button) { // TODO: instead, query the button's actual bindings and look up a // texture based on that! no time tho - if (button == Confirm || button == ControllerConfirm) + if (button == Confirm) return GetPromptLocation("confirm"); else if (button == Cancel) return GetPromptLocation("cancel"); diff --git a/Source/Data/PersistedData/ControlsConfig_V01.cs b/Source/Data/PersistedData/ControlsConfig_V01.cs index cdd8fdb4..9400e4b2 100644 --- a/Source/Data/PersistedData/ControlsConfig_V01.cs +++ b/Source/Data/PersistedData/ControlsConfig_V01.cs @@ -39,10 +39,6 @@ public class ControlsConfig_V01 : PersistedData new(Buttons.South) { NotFor = Gamepads.Nintendo }, new(Buttons.East) { OnlyFor = Gamepads.Nintendo }, ], - ["ControllerConfirm"] = [ - new(Buttons.South) { NotFor = Gamepads.Nintendo }, - new(Buttons.East) { OnlyFor = Gamepads.Nintendo }, - ], ["Cancel"] = [ new(Keys.X), new(Buttons.East) { NotFor = Gamepads.Nintendo }, diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index d7007dd3..7d88ad1b 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -436,7 +436,7 @@ protected virtual void HandleInput() if (Controls.Menu.Horizontal.Positive.Pressed) items[Index].Slide(1); - if (Controls.Confirm.Pressed && items[Index].Pressed() || Controls.ControllerConfirm.Pressed && items[Index].Pressed()) + if (Controls.Confirm.Pressed && items[Index].Pressed()) Controls.Consume(); } } diff --git a/Source/Scenes/Overworld.cs b/Source/Scenes/Overworld.cs index c6bed779..7c2f85a6 100644 --- a/Source/Scenes/Overworld.cs +++ b/Source/Scenes/Overworld.cs @@ -272,7 +272,11 @@ public void SlideSelectedMod(int dir) public override void Update() { slide += (index - slide) * (1 - MathF.Pow(.001f, Time.Delta)); - wobble += (Controls.Camera.Value - wobble) * (1 - MathF.Pow(.1f, Time.Delta)); + + if (!Paused) + wobble += (Controls.Camera.Value - wobble) * (1 - MathF.Pow(.1f, Time.Delta)); + else + wobble = new Vec2(0, 0); Calc.Approach(ref cameraCloseUpEase, state == States.Entering ? 1 : 0, Time.Delta); Calc.Approach(ref selectedEase, state != States.Selecting ? 1 : 0, 8 * Time.Delta); From f4be3428d458abde4291c5369d70c386a6f00066 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 1 Apr 2024 11:42:37 -0500 Subject: [PATCH 18/24] Added more dictionaries for keys.Allows onscreenkeybaord to have more options --- Source/Helpers/Menu.cs | 2 +- Source/Mod/Menu/OnScreenKeyboardMenu.cs | 57 ++++++---- Source/Mod/Patches/KeyboardHandler.cs | 136 +++++++++++++++++++++--- 3 files changed, 156 insertions(+), 39 deletions(-) diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index 7d88ad1b..693322ab 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -243,7 +243,7 @@ public InputField(Loc.Localized locString, Action set, Func get, RootMenu = rootMenu; fieldText = getter(); - keyboardMenu = new OnScreenKeyboardMenu(rootMenu, this); + keyboardMenu = new OnScreenKeyboardMenu(rootMenu, this, KeyboardHandler.NumberWithKeypadValues); } } diff --git a/Source/Mod/Menu/OnScreenKeyboardMenu.cs b/Source/Mod/Menu/OnScreenKeyboardMenu.cs index d37b3990..ec339968 100644 --- a/Source/Mod/Menu/OnScreenKeyboardMenu.cs +++ b/Source/Mod/Menu/OnScreenKeyboardMenu.cs @@ -1,4 +1,5 @@ -using System; +using Celeste64.Mod.Patches; +using System; namespace Celeste64.Mod; @@ -16,19 +17,36 @@ public class OnScreenKeyboardMenu : Menu private int CurrentPageStart => currentPage * columns * rows; private int CurrentIndex => currentRow * columns + currentColumn; - bool shiftMode; + + private bool shiftMode; + private bool allowShift; string setText = string.Empty; - InputField Owner; + private InputField Owner; + + private Dictionary KeyValueType; + private Dictionary KeyValueShiftType; + + private List KeyValueTypeList; + private List KeyValueShiftTypeList; + - internal OnScreenKeyboardMenu(Menu? rootMenu, InputField owner) + internal OnScreenKeyboardMenu(Menu? rootMenu, InputField owner, Dictionary keyboardType, bool allowShiftMode=true) { Target = new Target(Overworld.CardWidth, Overworld.CardHeight); Game.OnResolutionChanged += () => Target = new Target(Overworld.CardWidth, Overworld.CardHeight); GameTarget = new Target(Game.Width, Game.Height); RootMenu = rootMenu; + KeyValueType = keyboardType; + KeyValueShiftType = KeyboardHandler.GetShiftDict(KeyValueType); + + KeyValueTypeList = KeyboardHandler.KeyValuesToList(KeyValueType); + KeyValueShiftTypeList = KeyboardHandler.KeyValuesToList(KeyValueShiftType); + + allowShift = allowShiftMode; + Owner = owner; } @@ -80,17 +98,17 @@ private void RenderCharacters(Batcher batch) Vec2 offset = new Vec2(20, 20); int index = 0; - for (int i = 0; i < rows && CurrentPageStart + index < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count); i++) + for (int i = 0; i < rows && CurrentPageStart + index < (KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList).Count); i++) { - for (int j = 0; j < columns && CurrentPageStart + index < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count); j++) + for (int j = 0; j < columns && CurrentPageStart + index < (KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList).Count); j++) { if (index == currentRow * columns + currentColumn) { - RenderCurrentCharacter(batch, !shiftMode ? KeyboardHandler.TrimKeysList()[CurrentPageStart + index] : KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + index], new Vec2(j, i) * offset, size); + RenderCurrentCharacter(batch, KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + index], new Vec2(j, i) * offset, size); } else { - RenderCharacter(batch, !shiftMode ? KeyboardHandler.TrimKeysList()[CurrentPageStart + index] : KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + index], new Vec2(j, i) * offset, size); + RenderCharacter(batch, KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + index], new Vec2(j, i) * offset, size); } index++; } @@ -103,19 +121,19 @@ protected override void HandleInput() { if (currentColumn == columns - 1) { - if (((currentPage + 1) * columns * rows) + (currentRow * columns) < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + if (((currentPage + 1) * columns * rows) + (currentRow * columns) < KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList).Count) { currentPage++; currentColumn = 0; } - else if ((currentPage + 1) * columns * rows < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + else if ((currentPage + 1) * columns * rows < KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList).Count) { currentPage++; currentColumn = 0; currentRow = 0; } } - else if (CurrentPageStart + CurrentIndex + 1 < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + else if (CurrentPageStart + CurrentIndex + 1 < KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList).Count) { currentColumn += 1; } @@ -138,7 +156,7 @@ protected override void HandleInput() Audio.Play(DownSound); } - if (Controls.Menu.Vertical.Positive.Pressed && (currentRow + 1) < rows && CurrentPageStart + CurrentIndex + columns < (!shiftMode ? KeyboardHandler.TrimKeysList().Count : KeyboardHandler.TrimModifiedKeysList().Count)) + if (Controls.Menu.Vertical.Positive.Pressed && (currentRow + 1) < rows && CurrentPageStart + CurrentIndex + columns < KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList).Count) { currentRow += 1; Audio.Play(DownSound); @@ -152,7 +170,7 @@ protected override void HandleInput() * The next four controls are only relevant to gamepads. * We check if a keyboard key is pressed to avoid conflicts. */ - if (Controls.CopyFile.Pressed && KeyboardHandler.Instance.GetPressedKey() == null) + if (Controls.CopyFile.Pressed && KeyboardHandler.Instance.GetPressedKey() == null && allowShift) shiftMode = !shiftMode; if (Controls.RenameFile.Pressed && setText.Length > 0 && KeyboardHandler.Instance.GetPressedKey() == null) @@ -162,14 +180,7 @@ protected override void HandleInput() if (Controls.Confirm.Pressed && KeyboardHandler.Instance.GetPressedKey() == null) { - if (shiftMode) - { - setText += KeyboardHandler.TrimModifiedKeysList()[CurrentPageStart + CurrentIndex]; - } - else - { - setText += KeyboardHandler.TrimKeysList()[CurrentPageStart + CurrentIndex]; - } + setText += KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + CurrentIndex]; Audio.Play(UpSound); } @@ -210,8 +221,10 @@ public void ReadKey() if (setText.Length > 0) setText = setText.Remove(setText.Length - 1); } - else + else if (KeyValueTypeList.Contains(KeyboardHandler.GetKeyName(key))) + { setText += KeyboardHandler.GetKeyName(key); + } } } } diff --git a/Source/Mod/Patches/KeyboardHandler.cs b/Source/Mod/Patches/KeyboardHandler.cs index 2d2951d8..f90372a2 100644 --- a/Source/Mod/Patches/KeyboardHandler.cs +++ b/Source/Mod/Patches/KeyboardHandler.cs @@ -5,7 +5,7 @@ namespace Celeste64.Mod; class KeyboardHandler { - public static readonly Dictionary KeyValues = new Dictionary + public static readonly Dictionary AllCharachtersList = new Dictionary { { "A", "a" }, { "B", "b" }, @@ -86,7 +86,7 @@ class KeyboardHandler { "KeypadE", "e" }, { "KeypadF", "f" } }; - public static readonly Dictionary KeyValuesWithModifiers = new Dictionary + private static readonly Dictionary AllCharactersShiftList = new Dictionary { { "A", "A" }, { "B", "B" }, @@ -168,26 +168,130 @@ class KeyboardHandler { "KeypadF", "F" } }; - public static readonly List KeyValuesList = KeyValues.Values.ToList(); - public static readonly List KeyValuesWithModifiersList = KeyValuesWithModifiers.Values.ToList(); + public static readonly Dictionary AlphabetValues = new Dictionary + { + { "A", "a" }, + { "B", "b" }, + { "C", "c" }, + { "D", "d" }, + { "E", "e" }, + { "F", "f" }, + { "G", "g" }, + { "H", "h" }, + { "I", "i" }, + { "J", "j" }, + { "K", "k" }, + { "L", "l" }, + { "M", "m" }, + { "N", "n" }, + { "O", "o" }, + { "P", "p" }, + { "Q", "q" }, + { "R", "r" }, + { "S", "s" }, + { "T", "t" }, + { "U", "u" }, + { "V", "v" }, + { "W", "w" }, + { "X", "x" }, + { "Y", "y" }, + { "Z", "z" }, + }; + public static readonly Dictionary NumberRowValues = new Dictionary + { + { "D1", "1" }, + { "D2", "2" }, + { "D3", "3" }, + { "D4", "4" }, + { "D5", "5" }, + { "D6", "6" }, + { "D7", "7" }, + { "D8", "8" }, + { "D9", "9" }, + { "D0", "0" } + }; + + public static readonly Dictionary AlphabetKeypadValues = new Dictionary + { + { "A", "a" }, + { "B", "b" }, + { "C", "c" }, + { "D", "d" }, + { "E", "e" }, + { "F", "f" }, + { "G", "g" }, + { "H", "h" }, + { "I", "i" }, + { "J", "j" }, + { "K", "k" }, + { "L", "l" }, + { "M", "m" }, + { "N", "n" }, + { "O", "o" }, + { "P", "p" }, + { "Q", "q" }, + { "R", "r" }, + { "S", "s" }, + { "T", "t" }, + { "U", "u" }, + { "V", "v" }, + { "W", "w" }, + { "X", "x" }, + { "Y", "y" }, + { "Z", "z" }, + { "KeypadA", "a" }, + { "KeypadB", "b" }, + { "KeypadC", "c" }, + { "KeypadD", "d" }, + { "KeypadE", "e" }, + { "KeypadF", "f" } + }; + public static readonly Dictionary NumberWithKeypadValues = new Dictionary + { + { "D1", "1" }, + { "D2", "2" }, + { "D3", "3" }, + { "D4", "4" }, + { "D5", "5" }, + { "D6", "6" }, + { "D7", "7" }, + { "D8", "8" }, + { "D9", "9" }, + { "D0", "0" }, + { "Keypad0", "0" }, + { "Keypad1", "1" }, + { "Keypad2", "2" }, + { "Keypad3", "3" }, + { "Keypad4", "4" }, + { "Keypad5", "5" }, + { "Keypad6", "6" }, + { "Keypad7", "7" }, + { "Keypad8", "8" }, + { "Keypad9", "9" } + }; public static KeyboardHandler Instance = new(); - public static List TrimKeysList() + public static Dictionary GetShiftDict(Dictionary dict) { - List newKeysList = new List(); - foreach (string key in KeyValuesList) + Dictionary shiftDict = new Dictionary(); + foreach (string key in dict.Keys) { - if (key.Length == 1 && !newKeysList.Contains(key) && key != " " && key != "" && key != "\t") - newKeysList.Add(key); + if (AllCharactersShiftList.ContainsKey(key)) + shiftDict.Add(key, AllCharactersShiftList[key]); } - return newKeysList; + return shiftDict; + } + + public static List KeyValuesToList(Dictionary dict) + { + return dict.Values.ToList(); } - public static List TrimModifiedKeysList() + public static List TrimKeyList(List keysList) { List newKeysList = new List(); - foreach (string key in KeyValuesWithModifiersList) + foreach (string key in keysList) { if (key.Length == 1 && !newKeysList.Contains(key) && key != " " && key != "" && key != "\t") newKeysList.Add(key); @@ -203,15 +307,15 @@ public static string GetKeyName(Keys? key) if (Input.Keyboard.Shift) { - if (KeyValuesWithModifiers.ContainsKey(keyString)) - return KeyValuesWithModifiers[keyString]; + if (AllCharactersShiftList.ContainsKey(keyString)) + return AllCharactersShiftList[keyString]; else return string.Empty; } else { - if (KeyValues.ContainsKey(keyString)) - return KeyValues[keyString]; + if (AllCharachtersList.ContainsKey(keyString)) + return AllCharachtersList[keyString]; else return string.Empty; } From 3a0b66d1ebe46e9a5fdf1409cb0de2bcf012fb47 Mon Sep 17 00:00:00 2001 From: = <=> Date: Mon, 1 Apr 2024 11:43:55 -0500 Subject: [PATCH 19/24] Changed defualt keyboard type back to all keys --- Source/Helpers/Menu.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index 693322ab..fde97970 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -243,7 +243,7 @@ public InputField(Loc.Localized locString, Action set, Func get, RootMenu = rootMenu; fieldText = getter(); - keyboardMenu = new OnScreenKeyboardMenu(rootMenu, this, KeyboardHandler.NumberWithKeypadValues); + keyboardMenu = new OnScreenKeyboardMenu(rootMenu, this, KeyboardHandler.AllCharachtersList); } } From cdeb70ae9bf83c6304d79b8dcc3dcefa55cbabd7 Mon Sep 17 00:00:00 2001 From: axiand Date: Tue, 2 Apr 2024 02:13:43 +0200 Subject: [PATCH 20/24] fix save file bug, also im making this commit on the site so someone should probably test this --- Source/Data/Save.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Data/Save.cs b/Source/Data/Save.cs index d1fe1ccc..7d8e0dfa 100644 --- a/Source/Data/Save.cs +++ b/Source/Data/Save.cs @@ -114,8 +114,8 @@ public static SkinInfo GetSkin() public static void SaveToFile() { - var savePath = Path.Join(App.UserPath, "Saves", DefaultFileName); - var tempPath = Path.Join(App.UserPath, "Saves", DefaultFileName + ".backup"); + var savePath = Path.Join(App.UserPath, "Saves", Instance.FileName); + var tempPath = Path.Join(App.UserPath, "Saves", Instance.FileName + ".backup"); // first save to a temporary file { From cdc91287d19d10e88ec507e4e81f5b830995f8dd Mon Sep 17 00:00:00 2001 From: Jasmine Stephens Date: Mon, 1 Apr 2024 20:25:17 -0700 Subject: [PATCH 21/24] Changing save rename keyboard to restrict to alphanumeric keys Also some misc additional cleanup. --- Source/Helpers/Menu.cs | 9 +++---- Source/Mod/Data/SaveManager.cs | 14 +--------- Source/Mod/Menu/GameOptionsMenu.cs | 2 -- Source/Mod/Menu/OnScreenKeyboardMenu.cs | 35 +++++++++++-------------- Source/Mod/Menu/SaveSelectionMenu.cs | 13 ++++++--- Source/Mod/Patches/KeyboardHandler.cs | 34 +++++++++++++++++------- Source/Scenes/Overworld.cs | 7 +---- 7 files changed, 54 insertions(+), 60 deletions(-) diff --git a/Source/Helpers/Menu.cs b/Source/Helpers/Menu.cs index fde97970..8a25ec28 100644 --- a/Source/Helpers/Menu.cs +++ b/Source/Helpers/Menu.cs @@ -14,7 +14,6 @@ public abstract class Item public virtual bool Selectable { get; } = true; public virtual bool Pressed() => false; public virtual void Slide(int dir) { } - public virtual void GetKeyPress() { } // LocString is the base localized string object, before any changes. // This is kept separate from the label so we can get substrings from the LocString like the Description. @@ -235,15 +234,15 @@ public override bool Pressed() return true; } - public InputField(Loc.Localized locString, Action set, Func get, Menu rootMenu) + public InputField(Loc.Localized locString, Action set, Func get, Menu rootMenu, Dictionary? characters = null) { LocString = locString; setter = set; getter = get; RootMenu = rootMenu; fieldText = getter(); - - keyboardMenu = new OnScreenKeyboardMenu(rootMenu, this, KeyboardHandler.AllCharachtersList); + if (characters == null) characters = KeyboardHandler.AllCharactersList; + keyboardMenu = new OnScreenKeyboardMenu(rootMenu, this, characters); } } @@ -429,8 +428,6 @@ protected virtual void HandleInput() if (was != Index) Audio.Play(step < 0 ? UpSound : DownSound); - items[Index].GetKeyPress(); - if (Controls.Menu.Horizontal.Negative.Pressed) items[Index].Slide(-1); if (Controls.Menu.Horizontal.Positive.Pressed) diff --git a/Source/Mod/Data/SaveManager.cs b/Source/Mod/Data/SaveManager.cs index 636e26f6..c9aa553f 100644 --- a/Source/Mod/Data/SaveManager.cs +++ b/Source/Mod/Data/SaveManager.cs @@ -1,12 +1,9 @@ -using System.Text.RegularExpressions; - -namespace Celeste64.Mod.Data; +namespace Celeste64.Mod.Data; internal sealed class SaveManager { internal static SaveManager Instance = new(); - [DisallowHooks] internal string GetLastLoadedSave() { if (File.Exists(Path.Join(App.UserPath, "Saves", "save.metadata"))) @@ -26,7 +23,6 @@ internal void SetLastLoadedSave(string save_name) File.WriteAllText(Path.Join(App.UserPath, "Saves", "save.metadata"), save_name); } - [DisallowHooks] internal List GetSaves() { List saves = new List(); @@ -53,7 +49,6 @@ internal List GetSaves() return saves; } - [DisallowHooks] internal void CopySave(string filename) { if (File.Exists(Path.Join(App.UserPath, "Saves", filename))) @@ -63,7 +58,6 @@ internal void CopySave(string filename) } } - [DisallowHooks] internal void NewSave(string? name = null) { if (string.IsNullOrEmpty(name)) name = $"save_{GetSaveCount()}.json"; @@ -84,11 +78,9 @@ internal void NewSave(string? name = null) } } - [DisallowHooks] internal bool ChangeFileName(string originalFileName, string newFileName) { bool success = true; - string invalidCharsPattern = "[\\/:*?\"<>|{}]"; foreach (string file in GetSaves()) { @@ -98,7 +90,6 @@ internal bool ChangeFileName(string originalFileName, string newFileName) { if (!newFileName.EndsWith(".json")) newFileName += ".json"; - newFileName = Regex.Replace(newFileName, invalidCharsPattern, "_"); File.Move(Path.Join(App.UserPath, "Saves", file), Path.Join(App.UserPath, "Saves", newFileName)); if (file == Save.Instance.FileName) LoadSaveByFileName(newFileName); @@ -116,13 +107,11 @@ internal bool ChangeFileName(string originalFileName, string newFileName) return success; } - [DisallowHooks] internal int GetSaveCount() { return GetSaves().Count; } - [DisallowHooks] internal void DeleteSave(string save) { if (File.Exists(Path.Join(App.UserPath, "Saves", save))) @@ -136,7 +125,6 @@ internal void DeleteSave(string save) } } - [DisallowHooks] internal void LoadSaveByFileName(string fileName) { if (!GetSaves().Contains(fileName)) // Make file if it doesn't exist yet diff --git a/Source/Mod/Menu/GameOptionsMenu.cs b/Source/Mod/Menu/GameOptionsMenu.cs index d2855b32..fa1582f0 100644 --- a/Source/Mod/Menu/GameOptionsMenu.cs +++ b/Source/Mod/Menu/GameOptionsMenu.cs @@ -1,5 +1,3 @@ -using Celeste64.Mod; - namespace Celeste64; public class GameOptionsMenu : Menu diff --git a/Source/Mod/Menu/OnScreenKeyboardMenu.cs b/Source/Mod/Menu/OnScreenKeyboardMenu.cs index ec339968..76d0418b 100644 --- a/Source/Mod/Menu/OnScreenKeyboardMenu.cs +++ b/Source/Mod/Menu/OnScreenKeyboardMenu.cs @@ -1,7 +1,4 @@ -using Celeste64.Mod.Patches; -using System; - -namespace Celeste64.Mod; +namespace Celeste64.Mod; public class OnScreenKeyboardMenu : Menu { @@ -21,7 +18,7 @@ public class OnScreenKeyboardMenu : Menu private bool shiftMode; private bool allowShift; - string setText = string.Empty; + private string textValue = string.Empty; private InputField Owner; @@ -31,8 +28,7 @@ public class OnScreenKeyboardMenu : Menu private List KeyValueTypeList; private List KeyValueShiftTypeList; - - internal OnScreenKeyboardMenu(Menu? rootMenu, InputField owner, Dictionary keyboardType, bool allowShiftMode=true) + internal OnScreenKeyboardMenu(Menu? rootMenu, InputField owner, Dictionary keyboardType, bool allowShiftMode = true) { Target = new Target(Overworld.CardWidth, Overworld.CardHeight); Game.OnResolutionChanged += () => Target = new Target(Overworld.CardWidth, Overworld.CardHeight); @@ -41,7 +37,7 @@ internal OnScreenKeyboardMenu(Menu? rootMenu, InputField owner, Dictionary 0 && KeyboardHandler.Instance.GetPressedKey() == null) + if (Controls.RenameFile.Pressed && textValue.Length > 0 && KeyboardHandler.Instance.GetPressedKey() == null) { - setText = setText.Remove(setText.Length - 1); + textValue = textValue.Remove(textValue.Length - 1); } if (Controls.Confirm.Pressed && KeyboardHandler.Instance.GetPressedKey() == null) { - setText += KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + CurrentIndex]; + textValue += KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + CurrentIndex]; Audio.Play(UpSound); } @@ -201,29 +197,28 @@ protected override void RenderItems(Batcher batch) { batch.PushMatrix(new Vec2(GameTarget.Bounds.TopLeft.X, GameTarget.Bounds.TopLeft.Y), false); - if (setText.Length == 0) + if (textValue.Length == 0) batch.Text(Language.Current.SpriteFont, "Enter text", new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf("Enter text") / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue * 0.6f); - batch.Text(Language.Current.SpriteFont, setText, new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(setText) / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue); + batch.Text(Language.Current.SpriteFont, textValue, new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(textValue) / 2, GameTarget.Bounds.TopCenter.Y + 96), Color.CornflowerBlue); batch.Text(Language.Current.SpriteFont, Loc.Str("OSKUserInstructions"), new Vec2(GameTarget.Bounds.TopCenter.X - Language.Current.SpriteFont.WidthOf(Loc.Str("OSKUserInstructions")) / 2, GameTarget.Bounds.TopCenter.Y + 284), Color.CornflowerBlue); RenderCharacters(batch); } - private Keys? key; public void ReadKey() { - key = KeyboardHandler.Instance.GetPressedKey(); + Keys? key = KeyboardHandler.Instance.GetPressedKey(); if (key != null) { if (key == Keys.Backspace || key == Keys.KeypadBackspace) { - if (setText.Length > 0) - setText = setText.Remove(setText.Length - 1); + if (textValue.Length > 0) + textValue = textValue.Remove(textValue.Length - 1); } else if (KeyValueTypeList.Contains(KeyboardHandler.GetKeyName(key))) { - setText += KeyboardHandler.GetKeyName(key); + textValue += KeyboardHandler.GetKeyName(key); } } } diff --git a/Source/Mod/Menu/SaveSelectionMenu.cs b/Source/Mod/Menu/SaveSelectionMenu.cs index bfd01858..de84edbc 100644 --- a/Source/Mod/Menu/SaveSelectionMenu.cs +++ b/Source/Mod/Menu/SaveSelectionMenu.cs @@ -1,6 +1,5 @@ using Celeste64.Mod; using Celeste64.Mod.Data; -using System.Diagnostics; namespace Celeste64; @@ -126,12 +125,12 @@ private void RenderSaves(Batcher batch) } } - void SetRename(string name) + private void SetRename(string name) { renamedFileName = name; } - string GetRename() + private string GetRename() { return renamedFileName; } @@ -268,7 +267,13 @@ protected override void HandleInput() { Menu newMenu = new Menu(this); newMenu.Title = string.Format(Loc.Str("SaveRenameFile"), saves[CurrentPageStart + CurrentIndex]); - newMenu.Add(new InputField("NewName", (k) => SetRename(k), GetRename, newMenu)); + Dictionary characters = KeyboardHandler.AlphabetValues.Concat(KeyboardHandler.NumberRowValues).ToDictionary(); + characters.Add("Space", " "); + newMenu.Add(new InputField( + "NewName", + (k) => SetRename(k), + GetRename, + newMenu, characters)); newMenu.Add(new Option("OptionsYes", () => { bool renameSuccess = SaveManager.Instance.ChangeFileName(saves[CurrentPageStart + CurrentIndex], renamedFileName); diff --git a/Source/Mod/Patches/KeyboardHandler.cs b/Source/Mod/Patches/KeyboardHandler.cs index f90372a2..12beb4f5 100644 --- a/Source/Mod/Patches/KeyboardHandler.cs +++ b/Source/Mod/Patches/KeyboardHandler.cs @@ -1,11 +1,8 @@ -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace Celeste64.Mod; +namespace Celeste64.Mod; class KeyboardHandler { - public static readonly Dictionary AllCharachtersList = new Dictionary + public static readonly Dictionary AllCharactersList = new Dictionary { { "A", "a" }, { "B", "b" }, @@ -71,7 +68,7 @@ class KeyboardHandler { "KeypadMultiply", "*" }, { "KeypadMinus", "-" }, { "KeypadPlus", "+" }, - { "KeypadPeroid", "." }, + { "KeypadPeriod", "." }, { "KeypadEquals", "=" }, { "KeypadComma", "," }, { "KeypadLeftParen", "(" }, @@ -86,6 +83,7 @@ class KeyboardHandler { "KeypadE", "e" }, { "KeypadF", "f" } }; + private static readonly Dictionary AllCharactersShiftList = new Dictionary { { "A", "A" }, @@ -152,7 +150,7 @@ class KeyboardHandler { "KeypadMultiply", "*" }, { "KeypadMinus", "_" }, { "KeypadPlus", "+" }, - { "KeypadPeroid", ">" }, + { "KeypadPeriod", ">" }, { "KeypadEquals", "+" }, { "KeypadComma", "<" }, { "KeypadLeftParen", "(" }, @@ -197,6 +195,7 @@ class KeyboardHandler { "Y", "y" }, { "Z", "z" }, }; + public static readonly Dictionary NumberRowValues = new Dictionary { { "D1", "1" }, @@ -246,6 +245,7 @@ class KeyboardHandler { "KeypadE", "e" }, { "KeypadF", "f" } }; + public static readonly Dictionary NumberWithKeypadValues = new Dictionary { { "D1", "1" }, @@ -270,6 +270,22 @@ class KeyboardHandler { "Keypad9", "9" } }; + public static readonly Dictionary SpecialCharacterKeyValues = new Dictionary + { + { "Space", " " }, + { "Minus", "-" }, + { "Equals", "=" }, + { "LeftBracket", "[" }, + { "RightBracket", "]" }, + { "Backslash", "\\" }, + { "Semicolon", ";" }, + { "Apostrophe", "'" }, + { "Tilde", "~" }, + { "Comma", "," }, + { "Period", "." }, + { "Slash", "/" }, + }; + public static KeyboardHandler Instance = new(); public static Dictionary GetShiftDict(Dictionary dict) @@ -314,8 +330,8 @@ public static string GetKeyName(Keys? key) } else { - if (AllCharachtersList.ContainsKey(keyString)) - return AllCharachtersList[keyString]; + if (AllCharactersList.ContainsKey(keyString)) + return AllCharactersList[keyString]; else return string.Empty; } diff --git a/Source/Scenes/Overworld.cs b/Source/Scenes/Overworld.cs index 7c2f85a6..591a06af 100644 --- a/Source/Scenes/Overworld.cs +++ b/Source/Scenes/Overworld.cs @@ -1,6 +1,4 @@ using Celeste64.Mod; -using ImGuiNET; -using System.Diagnostics; namespace Celeste64; public class Overworld : Scene @@ -275,8 +273,7 @@ public override void Update() if (!Paused) wobble += (Controls.Camera.Value - wobble) * (1 - MathF.Pow(.1f, Time.Delta)); - else - wobble = new Vec2(0, 0); + Calc.Approach(ref cameraCloseUpEase, state == States.Entering ? 1 : 0, Time.Delta); Calc.Approach(ref selectedEase, state != States.Selecting ? 1 : 0, 8 * Time.Delta); @@ -619,8 +616,6 @@ public override void Render(Target target) pauseMenu.Render(batch, bounds.Center); } - - // show version number on Overworld as well // Logic breakdown: // If paused From 85b080656eb32bd5028209f0c7df962fe828b503 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 2 Apr 2024 20:36:00 -0500 Subject: [PATCH 22/24] Fixed problem with space showing " " instead of word Space --- Content/Text/English.json | 3 ++- Source/Mod/Menu/OnScreenKeyboardMenu.cs | 14 +++++++++++--- Source/Mod/Patches/KeyboardHandler.cs | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/Content/Text/English.json b/Content/Text/English.json index 936b8198..678614e3 100644 --- a/Content/Text/English.json +++ b/Content/Text/English.json @@ -81,7 +81,8 @@ "ModOptions": "Mod Options", "ConfirmDisableMod": "Continue & Disable Mod", "ModSafeDisableErrorMessage": "This mod can't be disabled because it would disable the level you're currently in.\nTry going to the main menu first.", - "QuitToMainMenu": "Quit to Main Menu" + "QuitToMainMenu": "Quit to Main Menu", + "KeyboardSpace": "Space" }, "Dialog": { "Granny1": [ diff --git a/Source/Mod/Menu/OnScreenKeyboardMenu.cs b/Source/Mod/Menu/OnScreenKeyboardMenu.cs index 76d0418b..0775b72d 100644 --- a/Source/Mod/Menu/OnScreenKeyboardMenu.cs +++ b/Source/Mod/Menu/OnScreenKeyboardMenu.cs @@ -1,4 +1,6 @@ -namespace Celeste64.Mod; +using System.ComponentModel; + +namespace Celeste64.Mod; public class OnScreenKeyboardMenu : Menu { @@ -63,6 +65,8 @@ public override void Closed() private void RenderCharacter(Batcher batch, string character, Vec2 pos, Vec2 size) { + if (character == " ") + character = Loc.Str("KeyboardSpace"); batch.PushMatrix(Matrix3x2.CreateScale(1.1f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); batch.Text(Language.Current.SpriteFont, character, Vec2.Zero, new Vec2(0.5f, 0), Color.Black); @@ -76,6 +80,8 @@ private void RenderCharacter(Batcher batch, string character, Vec2 pos, Vec2 siz private void RenderCurrentCharacter(Batcher batch, string character, Vec2 pos, Vec2 size) { + if (character == " ") + character = Loc.Str("KeyboardSpace"); batch.PushMatrix(Matrix3x2.CreateScale(1.1f) * Matrix3x2.CreateTranslation((pos + new Vec2(size.X * 0.4f - 20, size.Y * 0.4f - 20)) * Game.RelativeScale)); batch.Text(Language.Current.SpriteFont, character, Vec2.Zero, new Vec2(0.5f, 0), Color.Black); @@ -100,11 +106,13 @@ private void RenderCharacters(Batcher batch) { if (index == currentRow * columns + currentColumn) { - RenderCurrentCharacter(batch, KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + index], new Vec2(j, i) * offset, size); + string keyName = KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + index]; + RenderCurrentCharacter(batch, keyName, new Vec2(j, i) * offset, size); } else { - RenderCharacter(batch, KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + index], new Vec2(j, i) * offset, size); + string keyName = KeyboardHandler.TrimKeyList(!shiftMode ? KeyValueTypeList : KeyValueShiftTypeList)[CurrentPageStart + index]; + RenderCharacter(batch, keyName, new Vec2(j, i) * offset, size); } index++; } diff --git a/Source/Mod/Patches/KeyboardHandler.cs b/Source/Mod/Patches/KeyboardHandler.cs index 12beb4f5..6662fe9b 100644 --- a/Source/Mod/Patches/KeyboardHandler.cs +++ b/Source/Mod/Patches/KeyboardHandler.cs @@ -309,7 +309,7 @@ public static List TrimKeyList(List keysList) List newKeysList = new List(); foreach (string key in keysList) { - if (key.Length == 1 && !newKeysList.Contains(key) && key != " " && key != "" && key != "\t") + if (!newKeysList.Contains(key) && key != "" && key != "\t") newKeysList.Add(key); } return newKeysList; From dc15d9e06e77943463f2e93e9ccb63607a74e5f6 Mon Sep 17 00:00:00 2001 From: Jasmine Stephens Date: Tue, 30 Apr 2024 23:48:59 -0700 Subject: [PATCH 23/24] Deleting extra icons --- .../Controls/Nintendo Switch/renamefile.png | Bin 515 -> 0 bytes Content/Sprites/Controls/PC/renamefile.png | Bin 2116 -> 0 bytes .../Controls/PlayStation 5/renamefile.png | Bin 453 -> 0 bytes .../Sprites/Controls/Xbox Series/renamefile.png | Bin 560 -> 0 bytes 4 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 Content/Sprites/Controls/Nintendo Switch/renamefile.png delete mode 100644 Content/Sprites/Controls/PC/renamefile.png delete mode 100644 Content/Sprites/Controls/PlayStation 5/renamefile.png delete mode 100644 Content/Sprites/Controls/Xbox Series/renamefile.png diff --git a/Content/Sprites/Controls/Nintendo Switch/renamefile.png b/Content/Sprites/Controls/Nintendo Switch/renamefile.png deleted file mode 100644 index 737632d430e900dc55644e6a382345bb80581d39..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 515 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!SkfJR9T^xl_H+M9WCik#1AIbU z|C0iMnt;khw>EtPvII(k{DS@S?eELi_pg7ie}4ab{&)tpH+iNE42IE--pT!8KjS>7zhMgbtUoq< za?Jj~=CF<@WV6r)_jelaq!?7+X8pWNczjZXV-4Fia)5Rzn}Ye#)pq( z-VSbgKY!&o%AIB^NdDqhIqz5Jd2_~&3;DlimA$yA!65ouH~q~;Ee7S|O8wdl>oXTg zEoZdhW!GKBWWy&c&MDh)+@G%@g?Y(O!#>7O60>OMkDP^MOg99_Re`{a=Mcnc8<;e!GryLd7Hg|?=$+aE+Z`0+LUi^B#gt6@x!-c3% V4q^4rY=P0h;OXk;vd$@?2>>1K_dfst diff --git a/Content/Sprites/Controls/PC/renamefile.png b/Content/Sprites/Controls/PC/renamefile.png deleted file mode 100644 index 8d4371c8d02240feb89a4284e8d63657ee3d4218..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2116 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 Date: Mon, 24 Jun 2024 17:51:37 -0700 Subject: [PATCH 24/24] Updating to work with new controls system --- Source/Data/Controls.cs | 11 +++++------ Source/Mod/Menu/ControlsMenu.cs | 1 + 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/Data/Controls.cs b/Source/Data/Controls.cs index ec3dbc51..9a288ae7 100644 --- a/Source/Data/Controls.cs +++ b/Source/Data/Controls.cs @@ -93,11 +93,11 @@ public static class Controls [DefaultBinding(Keys.N)] [DefaultBinding(Buttons.RightShoulder)] public static VirtualButton CreateFile { get; private set; } = new("CreateFile"); - - - [DefaultBinding(Keys.R] - [DefaultBinding(Buttons.West - public static readonly VirtualButton RenameFile = new("RenameFile"); + + + [DefaultBinding(Keys.R)] + [DefaultBinding(Buttons.West)] + public static VirtualButton RenameFile { get; private set; } = new("RenameFile"); [DefaultBinding(Keys.V)] [DefaultBinding(Buttons.LeftShoulder)] @@ -507,7 +507,6 @@ internal static void ResetBinding(VirtualButton virtualButton, bool forControlle internal static void ResetAllBindings(bool forController, GameMod? mod = null) { ControlsConfig_V01 config; - IEnumerable defaultBindings; Type settingsType; object? settingsObject; diff --git a/Source/Mod/Menu/ControlsMenu.cs b/Source/Mod/Menu/ControlsMenu.cs index a4b10ff2..1cbea5ee 100644 --- a/Source/Mod/Menu/ControlsMenu.cs +++ b/Source/Mod/Menu/ControlsMenu.cs @@ -46,6 +46,7 @@ public ControlsMenu(Menu? rootMenu, bool isForController) Add(new InputBind(Controls.CopyFile.Name, Controls.CopyFile, rootMenu, isForController) { RequiresBinding = true }); Add(new InputBind(Controls.CreateFile.Name, Controls.CreateFile, rootMenu, isForController) { RequiresBinding = true }); Add(new InputBind(Controls.DeleteFile.Name, Controls.DeleteFile, rootMenu, isForController) { RequiresBinding = true }); + Add(new InputBind(Controls.RenameFile.Name, Controls.RenameFile, rootMenu, isForController) { RequiresBinding = true }); Add(new InputBind(Controls.ResetBindings.Name, Controls.ResetBindings, rootMenu, isForController) { RequiresBinding = true }); Add(new InputBind(Controls.ClearBindings.Name, Controls.ClearBindings, rootMenu, isForController) { RequiresBinding = true }); Add(new InputBind(Controls.Menu.Name + "Up", Controls.Menu.Vertical.Negative, rootMenu, isForController) { DeadZone = 0.5f, RequiresBinding = true });