mirror of https://github.com/PCSX2/pcsx2.git
InputManager: Fix chord bindings when activating in reverse
This commit is contained in:
parent
b20e5a1e01
commit
14181ec70d
|
@ -952,7 +952,7 @@ SysMtgsThread& GetMTGS()
|
|||
// ------------------------------------------------------------------------
|
||||
|
||||
BEGIN_HOTKEY_LIST(g_host_hotkeys)
|
||||
DEFINE_HOTKEY("ShutdownVM", "System", "Shut Down Virtual Machine", [](bool pressed) {
|
||||
DEFINE_HOTKEY("ShutdownVM", "System", "Shut Down Virtual Machine", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
// run it on the host thread, that way we get the confirm prompt (if enabled)
|
||||
|
@ -960,16 +960,16 @@ DEFINE_HOTKEY("ShutdownVM", "System", "Shut Down Virtual Machine", [](bool press
|
|||
Q_ARG(bool, true), Q_ARG(bool, true), Q_ARG(bool, true));
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("TogglePause", "System", "Toggle Pause", [](bool pressed) {
|
||||
DEFINE_HOTKEY("TogglePause", "System", "Toggle Pause", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
g_emu_thread->setVMPaused(VMManager::GetState() != VMState::Paused);
|
||||
})
|
||||
DEFINE_HOTKEY("ToggleFullscreen", "General", "Toggle Fullscreen", [](bool pressed) {
|
||||
DEFINE_HOTKEY("ToggleFullscreen", "General", "Toggle Fullscreen", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
g_emu_thread->toggleFullscreen();
|
||||
})
|
||||
// Input Recording Hot Keys
|
||||
DEFINE_HOTKEY("InputRecToggleMode", "Input Recording", "Toggle Recording Mode", [](bool pressed) {
|
||||
DEFINE_HOTKEY("InputRecToggleMode", "Input Recording", "Toggle Recording Mode", [](s32 pressed) {
|
||||
if (!pressed) // ?? - not pressed so it is on key up?
|
||||
{
|
||||
g_InputRecordingControls.RecordModeToggle();
|
||||
|
|
|
@ -622,51 +622,20 @@ bool InputManager::IsAxisHandler(const InputEventHandler& handler)
|
|||
|
||||
bool InputManager::InvokeEvents(InputBindingKey key, float value, GenericInputBinding generic_key)
|
||||
{
|
||||
if (PreprocessEvent(key, value, generic_key))
|
||||
if (DoEventHook(key, value))
|
||||
return true;
|
||||
|
||||
// If imgui ate the event, don't fire our handlers.
|
||||
const bool skip_button_handlers = PreprocessEvent(key, value, generic_key);
|
||||
|
||||
// find all the bindings associated with this key
|
||||
const InputBindingKey masked_key = key.MaskDirection();
|
||||
const auto range = s_binding_map.equal_range(masked_key);
|
||||
if (range.first == s_binding_map.end())
|
||||
return false;
|
||||
|
||||
// Workaround for modifier keys. Basically, if we bind say, F1 and Shift+F1, and press shift
|
||||
// and then F1, we'll fire bindings for both F1 and Shift+F1, when we really only want to fire
|
||||
// the binding for Shift+F1. So, let's search through the binding list, and see if there's a
|
||||
// "longer" binding (more keys), and if so, only activate that and not the shorter binding(s).
|
||||
const InputBinding* longest_hotkey_binding = nullptr;
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
InputBinding* binding = it->second.get();
|
||||
if (IsAxisHandler(binding->handler))
|
||||
continue;
|
||||
|
||||
// find the key which matches us
|
||||
for (u32 i = 0; i < binding->num_keys; i++)
|
||||
{
|
||||
if (binding->keys[i].MaskDirection() != masked_key)
|
||||
continue;
|
||||
|
||||
const u8 bit = static_cast<u8>(1) << i;
|
||||
const bool negative = binding->keys[i].negative;
|
||||
const bool new_state = (negative ? (value < 0.0f) : (value > 0.0f));
|
||||
const u8 new_mask = (new_state ? (binding->current_mask | bit) : (binding->current_mask & ~bit));
|
||||
const bool prev_full_state = (binding->current_mask == binding->full_mask);
|
||||
const bool new_full_state = (new_mask == binding->full_mask);
|
||||
|
||||
// If we're activating this chord, block activation of other bindings with fewer keys.
|
||||
if (prev_full_state || new_full_state)
|
||||
{
|
||||
if (!longest_hotkey_binding || longest_hotkey_binding->num_keys < binding->num_keys)
|
||||
longest_hotkey_binding = binding;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we can actually fire/activate bindings.
|
||||
u32 min_num_keys = 0;
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
InputBinding* binding = it->second.get();
|
||||
|
@ -681,20 +650,6 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value, GenericInputBi
|
|||
const bool negative = binding->keys[i].negative;
|
||||
const bool new_state = (negative ? (value < 0.0f) : (value > 0.0f));
|
||||
|
||||
// Don't register the key press when we're part of a longer chord. That way,
|
||||
// the state won't change, and it won't get the released event either.
|
||||
if (longest_hotkey_binding && new_state && !IsAxisHandler(binding->handler) &&
|
||||
binding->num_keys != longest_hotkey_binding->num_keys)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// update state based on whether the whole chord was activated
|
||||
const u8 new_mask = (new_state ? (binding->current_mask | bit) : (binding->current_mask & ~bit));
|
||||
const bool prev_full_state = (binding->current_mask == binding->full_mask);
|
||||
const bool new_full_state = (new_mask == binding->full_mask);
|
||||
binding->current_mask = new_mask;
|
||||
|
||||
// invert if we're negative, since the handler expects 0..1
|
||||
const float value_to_pass = (negative ? ((value < 0.0f) ? -value : 0.0f) : (value > 0.0f) ? value : 0.0f);
|
||||
|
||||
|
@ -704,13 +659,60 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value, GenericInputBi
|
|||
// and 0 on release (when the full state changes).
|
||||
if (IsAxisHandler(binding->handler))
|
||||
{
|
||||
if (prev_full_state != new_full_state || value_to_pass >= 0.0f)
|
||||
if (value_to_pass >= 0.0f)
|
||||
std::get<InputAxisEventHandler>(binding->handler)(value_to_pass);
|
||||
}
|
||||
else
|
||||
else if (binding->num_keys >= min_num_keys)
|
||||
{
|
||||
if (prev_full_state != new_full_state)
|
||||
std::get<InputButtonEventHandler>(binding->handler)(value_to_pass > 0.0f);
|
||||
// update state based on whether the whole chord was activated
|
||||
const u8 new_mask = (new_state ? (binding->current_mask | bit) : (binding->current_mask & ~bit));
|
||||
const bool prev_full_state = (binding->current_mask == binding->full_mask);
|
||||
const bool new_full_state = (new_mask == binding->full_mask);
|
||||
binding->current_mask = new_mask;
|
||||
|
||||
// Workaround for multi-key bindings that share the same keys.
|
||||
if (binding->num_keys > 1 && new_full_state && prev_full_state != new_full_state &&
|
||||
range.first != range.second)
|
||||
{
|
||||
// Because the binding map isn't ordered, we could iterate in the order of Shift+F1 and then
|
||||
// F1, which would mean that F1 wouldn't get cancelled and still activate. So, to handle this
|
||||
// case, we skip activating any future bindings with a fewer number of keys.
|
||||
min_num_keys = std::max<u32>(min_num_keys, binding->num_keys);
|
||||
|
||||
// Basically, if we bind say, F1 and Shift+F1, and press shift and then F1, we'll fire bindings
|
||||
// for both F1 and Shift+F1, when we really only want to fire the binding for Shift+F1. So,
|
||||
// when we activate a multi-key chord (key press), we go through the binding map for all the
|
||||
// other keys in the chord, and cancel them if they have a shorter chord. If they're longer,
|
||||
// they could still activate and take precedence over us, so we leave them alone.
|
||||
for (u32 i = 0; i < binding->num_keys; i++)
|
||||
{
|
||||
const auto range = s_binding_map.equal_range(binding->keys[i].MaskDirection());
|
||||
for (auto it = range.first; it != range.second; ++it)
|
||||
{
|
||||
InputBinding* other_binding = it->second.get();
|
||||
if (other_binding == binding || IsAxisHandler(other_binding->handler) ||
|
||||
other_binding->num_keys >= binding->num_keys)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// We only need to cancel the binding if it was fully active before. Which in the above
|
||||
// case of Shift+F1 / F1, it will be.
|
||||
if (other_binding->current_mask == other_binding->full_mask)
|
||||
std::get<InputButtonEventHandler>(other_binding->handler)(-1);
|
||||
|
||||
// Zero out the current bits so that we don't release this binding, if the other part
|
||||
// of the chord releases first.
|
||||
other_binding->current_mask = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_full_state != new_full_state && binding->num_keys >= min_num_keys)
|
||||
{
|
||||
const s32 pressed = skip_button_handlers ? -1 : static_cast<s32>(value_to_pass > 0.0f);
|
||||
std::get<InputButtonEventHandler>(binding->handler)(pressed);
|
||||
}
|
||||
}
|
||||
|
||||
// bail out, since we shouldn't have the same key twice in the chord
|
||||
|
@ -723,9 +725,6 @@ bool InputManager::InvokeEvents(InputBindingKey key, float value, GenericInputBi
|
|||
|
||||
bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInputBinding generic_key)
|
||||
{
|
||||
if (DoEventHook(key, value))
|
||||
return true;
|
||||
|
||||
// does imgui want the event?
|
||||
if (key.source_type == InputSourceType::Keyboard)
|
||||
{
|
||||
|
@ -739,7 +738,7 @@ bool InputManager::PreprocessEvent(InputBindingKey key, float value, GenericInpu
|
|||
}
|
||||
else if (generic_key != GenericInputBinding::Unknown)
|
||||
{
|
||||
if (ImGuiManager::ProcessGenericInputEvent(generic_key, value))
|
||||
if (ImGuiManager::ProcessGenericInputEvent(generic_key, value) && value != 0.0f)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -90,7 +90,7 @@ struct InputBindingKeyHash
|
|||
};
|
||||
|
||||
/// Callback type for a binary event. Usually used for hotkeys.
|
||||
using InputButtonEventHandler = std::function<void(bool value)>;
|
||||
using InputButtonEventHandler = std::function<void(s32 value)>;
|
||||
|
||||
/// Callback types for a normalized event. Usually used for pads.
|
||||
using InputAxisEventHandler = std::function<void(float value)>;
|
||||
|
@ -110,12 +110,15 @@ struct InputInterceptHook
|
|||
};
|
||||
|
||||
/// Hotkeys are actions (e.g. toggle frame limit) which can be bound to keys or chords.
|
||||
/// The handler is called with an integer representing the key state, where 0 means that
|
||||
/// one or more keys were released, 1 means all the keys were pressed, and -1 means that
|
||||
/// the hotkey was cancelled due to a chord with more keys being activated.
|
||||
struct HotkeyInfo
|
||||
{
|
||||
const char* name;
|
||||
const char* category;
|
||||
const char* display_name;
|
||||
void (*handler)(bool pressed);
|
||||
void (*handler)(s32 pressed);
|
||||
};
|
||||
#define DECLARE_HOTKEY_LIST(name) extern const HotkeyInfo name[]
|
||||
#define BEGIN_HOTKEY_LIST(name) const HotkeyInfo name[] = {
|
||||
|
|
|
@ -1623,7 +1623,7 @@ static void HotkeyAdjustZoom(double delta)
|
|||
}
|
||||
|
||||
BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
||||
{"Screenshot", "Graphics", "Save Screenshot", [](bool pressed) {
|
||||
{"Screenshot", "Graphics", "Save Screenshot", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
GetMTGS().RunOnGSThread([]() {
|
||||
|
@ -1631,7 +1631,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
});
|
||||
}
|
||||
}},
|
||||
{"GSDumpSingleFrame", "Graphics", "Save Single Frame GS Dump", [](bool pressed) {
|
||||
{"GSDumpSingleFrame", "Graphics", "Save Single Frame GS Dump", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
GetMTGS().RunOnGSThread([]() {
|
||||
|
@ -1639,27 +1639,27 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
});
|
||||
}
|
||||
}},
|
||||
{"GSDumpMultiFrame", "Graphics", "Save Multi Frame GS Dump", [](bool pressed) {
|
||||
{"GSDumpMultiFrame", "Graphics", "Save Multi Frame GS Dump", [](s32 pressed) {
|
||||
GetMTGS().RunOnGSThread([pressed]() {
|
||||
if (pressed)
|
||||
if (pressed > 0)
|
||||
GSQueueSnapshot(std::string(), std::numeric_limits<u32>::max());
|
||||
else
|
||||
GSStopGSDump();
|
||||
});
|
||||
}},
|
||||
{"ToggleSoftwareRendering", "Graphics", "Toggle Software Rendering", [](bool pressed) {
|
||||
{"ToggleSoftwareRendering", "Graphics", "Toggle Software Rendering", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
GetMTGS().ToggleSoftwareRendering();
|
||||
}},
|
||||
{"IncreaseUpscaleMultiplier", "Graphics", "Increase Upscale Multiplier", [](bool pressed) {
|
||||
{"IncreaseUpscaleMultiplier", "Graphics", "Increase Upscale Multiplier", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyAdjustUpscaleMultiplier(1);
|
||||
}},
|
||||
{"DecreaseUpscaleMultiplier", "Graphics", "Decrease Upscale Multiplier", [](bool pressed) {
|
||||
{"DecreaseUpscaleMultiplier", "Graphics", "Decrease Upscale Multiplier", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyAdjustUpscaleMultiplier(-1);
|
||||
}},
|
||||
{"CycleAspectRatio", "Graphics", "Cycle Aspect Ratio", [](bool pressed) {
|
||||
{"CycleAspectRatio", "Graphics", "Cycle Aspect Ratio", [](s32 pressed) {
|
||||
if (pressed)
|
||||
return;
|
||||
|
||||
|
@ -1667,7 +1667,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
EmuConfig.CurrentAspectRatio = static_cast<AspectRatioType>((static_cast<int>(EmuConfig.CurrentAspectRatio) + 1) % static_cast<int>(AspectRatioType::MaxCount));
|
||||
Host::AddKeyedFormattedOSDMessage("CycleAspectRatio", 10.0f, "Aspect ratio set to '%s'.", Pcsx2Config::GSOptions::AspectRatioNames[static_cast<int>(EmuConfig.CurrentAspectRatio)]);
|
||||
}},
|
||||
{"CycleMipmapMode", "Graphics", "Cycle Hardware Mipmapping", [](bool pressed) {
|
||||
{"CycleMipmapMode", "Graphics", "Cycle Hardware Mipmapping", [](s32 pressed) {
|
||||
if (pressed)
|
||||
return;
|
||||
|
||||
|
@ -1684,7 +1684,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
g_gs_renderer->PurgePool();
|
||||
});
|
||||
}},
|
||||
{"CycleInterlaceMode", "Graphics", "Cycle Deinterlace Mode", [](bool pressed) {
|
||||
{"CycleInterlaceMode", "Graphics", "Cycle Deinterlace Mode", [](s32 pressed) {
|
||||
if (pressed)
|
||||
return;
|
||||
|
||||
|
@ -1705,15 +1705,15 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
|
||||
GetMTGS().RunOnGSThread([new_mode]() { GSConfig.InterlaceMode = new_mode; });
|
||||
}},
|
||||
{"ZoomIn", "Graphics", "Zoom In", [](bool pressed) {
|
||||
{"ZoomIn", "Graphics", "Zoom In", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyAdjustZoom(1.0);
|
||||
}},
|
||||
{"ZoomOut", "Graphics", "Zoom Out", [](bool pressed) {
|
||||
{"ZoomOut", "Graphics", "Zoom Out", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyAdjustZoom(-1.0);
|
||||
}},
|
||||
{"ToggleTextureDumping", "Graphics", "Toggle Texture Dumping", [](bool pressed) {
|
||||
{"ToggleTextureDumping", "Graphics", "Toggle Texture Dumping", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
EmuConfig.GS.DumpReplaceableTextures = !EmuConfig.GS.DumpReplaceableTextures;
|
||||
|
@ -1721,7 +1721,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
GetMTGS().ApplySettings();
|
||||
}
|
||||
}},
|
||||
{"ToggleTextureReplacements", "Graphics", "Toggle Texture Replacements", [](bool pressed) {
|
||||
{"ToggleTextureReplacements", "Graphics", "Toggle Texture Replacements", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
EmuConfig.GS.LoadTextureReplacements = !EmuConfig.GS.LoadTextureReplacements;
|
||||
|
@ -1729,7 +1729,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys)
|
|||
GetMTGS().ApplySettings();
|
||||
}
|
||||
}},
|
||||
{"ReloadTextureReplacements", "Graphics", "Reload Texture Replacements", [](bool pressed) {
|
||||
{"ReloadTextureReplacements", "Graphics", "Reload Texture Replacements", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
if (!EmuConfig.GS.LoadTextureReplacements)
|
||||
|
|
|
@ -1713,7 +1713,7 @@ static void HotkeySaveStateSlot(s32 slot)
|
|||
}
|
||||
|
||||
BEGIN_HOTKEY_LIST(g_vm_manager_hotkeys)
|
||||
DEFINE_HOTKEY("ToggleFrameLimit", "System", "Toggle Frame Limit", [](bool pressed) {
|
||||
DEFINE_HOTKEY("ToggleFrameLimit", "System", "Toggle Frame Limit", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Unlimited) ?
|
||||
|
@ -1721,7 +1721,7 @@ DEFINE_HOTKEY("ToggleFrameLimit", "System", "Toggle Frame Limit", [](bool presse
|
|||
LimiterModeType::Nominal);
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("ToggleTurbo", "System", "Toggle Turbo", [](bool pressed) {
|
||||
DEFINE_HOTKEY("ToggleTurbo", "System", "Toggle Turbo", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Turbo) ?
|
||||
|
@ -1729,21 +1729,21 @@ DEFINE_HOTKEY("ToggleTurbo", "System", "Toggle Turbo", [](bool pressed) {
|
|||
LimiterModeType::Nominal);
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("HoldTurbo", "System", "Turbo (Hold)", [](bool pressed) {
|
||||
if (pressed && !s_limiter_mode_prior_to_hold_interaction.has_value())
|
||||
DEFINE_HOTKEY("HoldTurbo", "System", "Turbo (Hold)", [](s32 pressed) {
|
||||
if (pressed > 0 && !s_limiter_mode_prior_to_hold_interaction.has_value())
|
||||
{
|
||||
s_limiter_mode_prior_to_hold_interaction = VMManager::GetLimiterMode();
|
||||
VMManager::SetLimiterMode((s_limiter_mode_prior_to_hold_interaction.value() != LimiterModeType::Turbo) ?
|
||||
LimiterModeType::Turbo :
|
||||
LimiterModeType::Nominal);
|
||||
}
|
||||
else if (!pressed && s_limiter_mode_prior_to_hold_interaction.has_value())
|
||||
else if (pressed >= 0 && s_limiter_mode_prior_to_hold_interaction.has_value())
|
||||
{
|
||||
VMManager::SetLimiterMode(s_limiter_mode_prior_to_hold_interaction.value());
|
||||
s_limiter_mode_prior_to_hold_interaction.reset();
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("ToggleSlowMotion", "System", "Toggle Slow Motion", [](bool pressed) {
|
||||
DEFINE_HOTKEY("ToggleSlowMotion", "System", "Toggle Slow Motion", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
{
|
||||
VMManager::SetLimiterMode((EmuConfig.LimiterMode != LimiterModeType::Slomo) ?
|
||||
|
@ -1751,42 +1751,42 @@ DEFINE_HOTKEY("ToggleSlowMotion", "System", "Toggle Slow Motion", [](bool presse
|
|||
LimiterModeType::Nominal);
|
||||
}
|
||||
})
|
||||
DEFINE_HOTKEY("IncreaseSpeed", "System", "Increase Target Speed", [](bool pressed) {
|
||||
DEFINE_HOTKEY("IncreaseSpeed", "System", "Increase Target Speed", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyAdjustTargetSpeed(0.1);
|
||||
})
|
||||
DEFINE_HOTKEY("DecreaseSpeed", "System", "Decrease Target Speed", [](bool pressed) {
|
||||
DEFINE_HOTKEY("DecreaseSpeed", "System", "Decrease Target Speed", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyAdjustTargetSpeed(-0.1);
|
||||
})
|
||||
DEFINE_HOTKEY("ResetVM", "System", "Reset Virtual Machine", [](bool pressed) {
|
||||
DEFINE_HOTKEY("ResetVM", "System", "Reset Virtual Machine", [](s32 pressed) {
|
||||
if (!pressed && VMManager::HasValidVM())
|
||||
VMManager::Reset();
|
||||
})
|
||||
DEFINE_HOTKEY("FrameAdvance", "System", "Frame Advance", [](bool pressed) {
|
||||
DEFINE_HOTKEY("FrameAdvance", "System", "Frame Advance", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
VMManager::FrameAdvance(1);
|
||||
})
|
||||
|
||||
DEFINE_HOTKEY("PreviousSaveStateSlot", "Save States", "Select Previous Save Slot", [](bool pressed) {
|
||||
DEFINE_HOTKEY("PreviousSaveStateSlot", "Save States", "Select Previous Save Slot", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyCycleSaveSlot(-1);
|
||||
})
|
||||
DEFINE_HOTKEY("NextSaveStateSlot", "Save States", "Select Next Save Slot", [](bool pressed) {
|
||||
DEFINE_HOTKEY("NextSaveStateSlot", "Save States", "Select Next Save Slot", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyCycleSaveSlot(1);
|
||||
})
|
||||
DEFINE_HOTKEY("SaveStateToSlot", "Save States", "Save State To Selected Slot", [](bool pressed) {
|
||||
DEFINE_HOTKEY("SaveStateToSlot", "Save States", "Save State To Selected Slot", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
VMManager::SaveStateToSlot(s_current_save_slot);
|
||||
})
|
||||
DEFINE_HOTKEY("LoadStateFromSlot", "Save States", "Load State From Selected Slot", [](bool pressed) {
|
||||
DEFINE_HOTKEY("LoadStateFromSlot", "Save States", "Load State From Selected Slot", [](s32 pressed) {
|
||||
if (!pressed)
|
||||
HotkeyLoadStateSlot(s_current_save_slot);
|
||||
})
|
||||
|
||||
#define DEFINE_HOTKEY_SAVESTATE_X(slotnum, slotnumstr) DEFINE_HOTKEY("SaveStateToSlot" #slotnum, \
|
||||
"Save States", "Save State To Slot " #slotnumstr, [](bool pressed) { if (!pressed) HotkeySaveStateSlot(slotnum); })
|
||||
"Save States", "Save State To Slot " #slotnumstr, [](s32 pressed) { if (!pressed) HotkeySaveStateSlot(slotnum); })
|
||||
DEFINE_HOTKEY_SAVESTATE_X(1, 01)
|
||||
DEFINE_HOTKEY_SAVESTATE_X(2, 02)
|
||||
DEFINE_HOTKEY_SAVESTATE_X(3, 03)
|
||||
|
@ -1798,7 +1798,7 @@ DEFINE_HOTKEY_SAVESTATE_X(8, 08)
|
|||
DEFINE_HOTKEY_SAVESTATE_X(9, 09)
|
||||
DEFINE_HOTKEY_SAVESTATE_X(10, 10)
|
||||
#define DEFINE_HOTKEY_LOADSTATE_X(slotnum, slotnumstr) DEFINE_HOTKEY("LoadStateFromSlot" #slotnum, \
|
||||
"Save States", "Load State From Slot " #slotnumstr, [](bool pressed) { \
|
||||
"Save States", "Load State From Slot " #slotnumstr, [](s32 pressed) { \
|
||||
if (!pressed) \
|
||||
HotkeyLoadStateSlot(slotnum); \
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue