Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 23 additions & 13 deletions src/BizHawk.Client.Common/config/Binding.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,13 @@ static HotkeyInfo()
var dict = new Dictionary<string, HotkeyInfo>();
var i = 0;
#if true
void Bind(string tabGroup, string displayName, string defaultBinding = "", string toolTip = "")
=> dict.Add(displayName, new(tabGroup: tabGroup, i++, displayName: displayName, toolTip: toolTip, defaultBinding: defaultBinding));
// Note (2025-10-23): Having bindings init with an intended scope would be better than merely marking overlaps with defaultBindingOverlaps
// e.g., for Ctrl+C overlaps (like MainForm vs. TAStudio), there's other code that checks which UI is focused, but consolidating such scope here on init would be better. --RetroEdit
void Bind(string tabGroup, string displayName, string defaultBinding = "", string toolTip = "", bool defaultBindingOverlaps = false)
=> dict.Add(displayName, new(tabGroup: tabGroup, i++, displayName: displayName, toolTip: toolTip, defaultBinding: defaultBinding, defaultBindingOverlaps: defaultBindingOverlaps));
#else //TODO switch to a sort key more resilient than the DisplayName, like with this example (need to update `Config.HotkeyBindings["A Hotkey"]` usages across codebase; please switch it to a `Config.GetHotkeyBindings` method so it can return "<not bound>")
void Bind(string tabGroup, string displayName, string defaultBinding = "", string toolTip = "")
=> dict.Add($"{tabGroup}__{displayName}".Replace(" ", ""), new(tabGroup: tabGroup, i++, displayName: displayName, toolTip: toolTip, defaultBinding: defaultBinding));
=> dict.Add($"{tabGroup}__{displayName}".Replace(" ", ""), new(tabGroup: tabGroup, i++, displayName: displayName, toolTip: toolTip, defaultBinding: defaultBinding, defaultBindingOverlaps: defaultBindingOverlaps));
#endif

Bind("General", "Frame Advance", "F");
Expand Down Expand Up @@ -61,7 +63,7 @@ void Bind(string tabGroup, string displayName, string defaultBinding = "", strin
Bind("General", "Reboot Core", "Ctrl+R");
Bind("General", "Toggle Sound");
Bind("General", "Exit Program");
Bind("General", "Screen Raw to Clipboard", "Ctrl+C");
Bind("General", "Screen Raw to Clipboard", "Ctrl+C", defaultBindingOverlaps: true);
Bind("General", "Screen Client to Clipboard", "Ctrl+Shift+C");
Bind("General", "Toggle Skip Lag Frame");
Bind("General", "Toggle Key Priority");
Expand Down Expand Up @@ -151,12 +153,17 @@ void Bind(string tabGroup, string displayName, string defaultBinding = "", strin
Bind("TAStudio", "Sel. bet. Markers", "Ctrl+A");
Bind("TAStudio", "Select All", "Ctrl+Shift+A");
Bind("TAStudio", "Reselect Clip.", "Ctrl+B");
Bind("TAStudio", "Copy Frames", "Ctrl+C", defaultBindingOverlaps: true);
Bind("TAStudio", "Paste Frames", "Ctrl+V");
Bind("TAStudio", "Paste Insert Frames", "Ctrl+Shift+V");
Bind("TAStudio", "Cut Frames", "Ctrl+X");
Bind("TAStudio", "Clear Frames", "Delete");
Bind("TAStudio", "Delete Frames", "Ctrl+Delete");
Bind("TAStudio", "Insert Frame", "Insert");
Bind("TAStudio", "Insert # Frames", "Shift+Insert");
Bind("TAStudio", "Clone Frames", "Ctrl+Insert");
Bind("TAStudio", "Clone # Times", "Ctrl+Shift+Insert");
Bind("TAStudio", "State Hist. Integrity Check", "Ctrl+Shift+I");
Bind("TAStudio", "Analog Increment", "Up");
Bind("TAStudio", "Analog Decrement", "Down");
Bind("TAStudio", "Analog Incr. by 10", "Shift+Up");
Expand Down Expand Up @@ -195,20 +202,20 @@ void Bind(string tabGroup, string displayName, string defaultBinding = "", strin
Bind("NDS", "Swap Screens");

Bind("RAIntegration", "Open RA Overlay", "Escape");
Bind("RAIntegration", "RA Up", "Up");
Bind("RAIntegration", "RA Down", "Down");
Bind("RAIntegration", "RA Left", "Left");
Bind("RAIntegration", "RA Right", "Right");
Bind("RAIntegration", "RA Confirm", "X");
Bind("RAIntegration", "RA Cancel", "Z");
Bind("RAIntegration", "RA Quit", "Backspace");
Bind("RAIntegration", "RA Up", "Up", defaultBindingOverlaps: true);
Bind("RAIntegration", "RA Down", "Down", defaultBindingOverlaps: true);
Bind("RAIntegration", "RA Left", "Left", defaultBindingOverlaps: true);
Bind("RAIntegration", "RA Right", "Right", defaultBindingOverlaps: true);
Bind("RAIntegration", "RA Confirm", "X", defaultBindingOverlaps: true);
Bind("RAIntegration", "RA Cancel", "Z", defaultBindingOverlaps: true);
Bind("RAIntegration", "RA Quit", "Backspace", defaultBindingOverlaps: true);

AllHotkeys = dict;
Groupings = dict.Values.Select(static info => info.TabGroup).Distinct().ToList();

#if DEBUG
var bindings = dict.Values
.Where(static info => !info.DisplayName.StartsWith("RA ") && !string.IsNullOrEmpty(info.DefaultBinding))
.Where(static info => !info.DefaultBindingOverlapCheckOverride && !string.IsNullOrEmpty(info.DefaultBinding))
.Select(static info => info.DefaultBinding)
.ToArray();
Debug.Assert(bindings.Distinct().CountIsExactly(bindings.Length), "Do not default bind multiple hotkeys to the same button combination.");
Expand All @@ -223,6 +230,8 @@ public static void ResolveWithDefaults(IDictionary<string, string> dict)

public readonly string DefaultBinding;

public readonly bool DefaultBindingOverlapCheckOverride;

public readonly string DisplayName;

public readonly int Ordinal;
Expand All @@ -231,13 +240,14 @@ public static void ResolveWithDefaults(IDictionary<string, string> dict)

public readonly string ToolTip;

private HotkeyInfo(string tabGroup, int ordinal, string displayName, string toolTip, string defaultBinding)
private HotkeyInfo(string tabGroup, int ordinal, string displayName, string toolTip, string defaultBinding, bool defaultBindingOverlaps)
{
DefaultBinding = defaultBinding;
DisplayName = displayName;
Ordinal = ordinal;
TabGroup = tabGroup;
ToolTip = toolTip;
DefaultBindingOverlapCheckOverride = defaultBindingOverlaps;
}
}
}
29 changes: 28 additions & 1 deletion src/BizHawk.Client.EmuHawk/MainForm.Hotkey.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ namespace BizHawk.Client.EmuHawk
{
public partial class MainForm
{
private bool TAStudioFocused()
{
return Tools.IsLoaded<TAStudio>() && Tools.Get<TAStudio>().ContainsFocus;
}

private bool CheckHotkey(string trigger)
{
void SelectAndSaveToSlot(int slot)
Expand Down Expand Up @@ -77,7 +82,7 @@ void SelectAndLoadFromSlot(int slot)
case "Screen Raw to Clipboard":
// Ctrl+C clash. any tool that has such acc must check this.
// maybe check if mainform has focus instead?
if (!(Tools.IsLoaded<TAStudio>() && Tools.Get<TAStudio>().ContainsFocus)) TakeScreenshotToClipboard();
if (!TAStudioFocused()) TakeScreenshotToClipboard();
break;
case "Screen Client to Clipboard":
TakeScreenshotClientToClipboard();
Expand Down Expand Up @@ -450,6 +455,24 @@ void SelectAndLoadFromSlot(int slot)
if (!Tools.IsLoaded<TAStudio>()) return false;
Tools.TAStudio.ReselectClipboardExternal();
break;
case "Copy Frames":
// This one at least *needs* to check for TAStudio focus,
// specifically to avoid Ctrl+C conflicts
if (!TAStudioFocused()) return false;
Tools.TAStudio.CopyFramesExternal();
break;
case "Paste Frames":
if (!TAStudioFocused()) return false;
Tools.TAStudio.PasteFramesExternal();
break;
case "Paste Insert Frames":
if (!TAStudioFocused()) return false;
Tools.TAStudio.PasteInsertFramesExternal();
break;
case "Cut Frames":
if (!TAStudioFocused()) return false;
Tools.TAStudio.CutFramesExternal();
break;
case "Clear Frames":
if (!Tools.IsLoaded<TAStudio>()) return false;
Tools.TAStudio.ClearFramesExternal();
Expand All @@ -474,6 +497,10 @@ void SelectAndLoadFromSlot(int slot)
if (!Tools.IsLoaded<TAStudio>()) return false;
Tools.TAStudio.CloneFramesXTimesExternal();
break;
case "State Hist. Integrity Check":
if (!TAStudioFocused()) return false;
Tools.TAStudio.StateHistoryIntegrityCheckExternal();
break;
case "Analog Increment":
if (!Tools.IsLoaded<TAStudio>()) return false;
Tools.TAStudio.AnalogIncrementByOne();
Expand Down
11 changes: 0 additions & 11 deletions src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

24 changes: 24 additions & 0 deletions src/BizHawk.Client.EmuHawk/tools/TAStudio/TAStudio.cs
Original file line number Diff line number Diff line change
Expand Up @@ -226,14 +226,23 @@ public override void HandleHotkeyUpdate()
SelectBetweenMarkersMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Sel. bet. Markers"];
SelectAllMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Select All"];
ReselectClipboardMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Reselect Clip."];
CopyMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Copy Frames"];
PasteMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Paste Frames"];
PasteInsertMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Paste Insert Frames"];
CutMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Cut Frames"];
ClearFramesMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Clear Frames"];
DeleteFramesMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Delete Frames"];
InsertFrameMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Insert Frame"];
InsertNumFramesMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Insert # Frames"];
CloneFramesMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Clone Frames"];
CloneFramesXTimesMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Clone # Times"];
StateHistoryIntegrityCheckMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["State Hist. Integrity Check"];

SelectBetweenMarkersContextMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Sel. bet. Markers"];
copyToolStripMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Copy Frames"];
pasteToolStripMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Paste Frames"];
pasteInsertToolStripMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Paste Insert Frames"];
cutToolStripMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Cut Frames"];
ClearContextMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Clear Frames"];
DeleteFramesContextMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Delete Frames"];
InsertFrameContextMenuItem.ShortcutKeyDisplayString = Config.HotkeyBindings["Insert Frame"];
Expand Down Expand Up @@ -485,6 +494,21 @@ public void AddColumn(string name, string text, int widthUnscaled)

public void LoadBranchByIndex(int index) => BookMarkControl.LoadBranchExternal(index);

public void CopyFramesExternal()
=> CopyMenuItem_Click(null, EventArgs.Empty);

public void PasteFramesExternal()
=> PasteMenuItem_Click(null, EventArgs.Empty);

public void PasteInsertFramesExternal()
=> PasteInsertMenuItem_Click(null, EventArgs.Empty);

public void CutFramesExternal()
=> CutMenuItem_Click(null, EventArgs.Empty);

public void StateHistoryIntegrityCheckExternal()
=> StateHistoryIntegrityCheckMenuItem_Click(null, EventArgs.Empty);

public void ClearFramesExternal()
=> ClearFramesMenuItem_Click(null, EventArgs.Empty);

Expand Down