Skip to content
Merged
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
75 changes: 73 additions & 2 deletions src/game_ineluki.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,40 @@ bool Game_Ineluki::Execute(StringView ini_file) {
// no-op
} else if (cmd.name == "registercheatevent") {
cheatlist.emplace_back(Utils::LowerCase(cmd.arg), atoi(cmd.arg2.c_str()));
} else if (cmd.name == "setmouseasreturn") {
Comment thread
florianessl marked this conversation as resolved.
// This command is only found in a few uncommon versions of the patch
if (!mouse_support) {
return true;
}
std::string arg_lower = Utils::LowerCase(cmd.arg);
if (arg_lower == "left") {
mouse_decision_binding = MouseReturnMode::Left;
} else if (arg_lower == "right") {
mouse_decision_binding = MouseReturnMode::Right;
} else if (arg_lower == "both") {
mouse_decision_binding = MouseReturnMode::Both;
} else if (arg_lower == "none") {
mouse_decision_binding = MouseReturnMode::None;
} else {
Output::Warning("Ineluki: Invalid value for setMouseAsReturn");
mouse_decision_binding = MouseReturnMode::None;
}
} else if (cmd.name == "setmousewheelaskeys") {
// This command is only found in a few uncommon versions of the patch
if (!mouse_support) {
return true;
}
std::string arg_lower = Utils::LowerCase(cmd.arg);
if (arg_lower == "updown") {
mouse_wheel_binding = MouseWheelMode::UpDown;
} else if (arg_lower == "leftright") {
mouse_wheel_binding = MouseWheelMode::LeftRight;
} else if (arg_lower == "none") {
mouse_wheel_binding = MouseWheelMode::None;
} else {
Output::Warning("Ineluki: Invalid value for setMouseWheelAsKeys");
mouse_wheel_binding = MouseWheelMode::None;
}
}
}

Expand Down Expand Up @@ -263,6 +297,10 @@ bool Game_Ineluki::Parse(StringView ini_file) {
} else if (cmd.name == "registercheatevent") {
cmd.arg = ini.Get(section, "cheat", std::string());
cmd.arg2 = ini.Get(section, "value", std::string());
} else if (cmd.name == "setmouseasreturn") {
cmd.arg = ini.Get(section, "value", std::string());
} else if (cmd.name == "setmousewheelaskeys") {
cmd.arg = ini.Get(section, "value", std::string());
} else {
Output::Debug("Ineluki: Unknown command {}", cmd.name);
valid = false;
Expand Down Expand Up @@ -294,10 +332,15 @@ int Game_Ineluki::GetMidiTicks() {
}

void Game_Ineluki::Update() {
if (!key_support) {
return;
if (key_support) {
UpdateKeys();
}
if (mouse_support) {
UpdateMouse();
}
}

void Game_Ineluki::UpdateKeys() {
for (const auto& key : keylist_down) {
if (Input::IsRawKeyTriggered(key.key)) {
output_list.push_back(key.value);
Expand Down Expand Up @@ -332,6 +375,34 @@ void Game_Ineluki::Update() {
}
}

void Game_Ineluki::UpdateMouse() {
#if defined(USE_MOUSE) && defined(SUPPORT_MOUSE)
if (Input::IsRawKeyTriggered(Input::Keys::MOUSE_LEFT)) {
if ((mouse_decision_binding == MouseReturnMode::Left || mouse_decision_binding == MouseReturnMode::Both)) {
Input::SimulateButtonPress(Input::DECISION);
}
} else if (Input::IsRawKeyTriggered(Input::Keys::MOUSE_RIGHT)) {
if ((mouse_decision_binding == MouseReturnMode::Right || mouse_decision_binding == MouseReturnMode::Both)) {
Input::SimulateButtonPress(Input::DECISION);
}
}

if (Input::IsRawKeyTriggered(Input::Keys::MOUSE_SCROLLUP)) {
if (mouse_wheel_binding == MouseWheelMode::UpDown) {
Input::SimulateButtonPress(Input::UP);
} else if (mouse_wheel_binding == MouseWheelMode::LeftRight) {
Input::SimulateButtonPress(Input::LEFT);
}
} else if (Input::IsRawKeyTriggered(Input::Keys::MOUSE_SCROLLDOWN)) {
if (mouse_wheel_binding == MouseWheelMode::UpDown) {
Input::SimulateButtonPress(Input::DOWN);
} else if (mouse_wheel_binding == MouseWheelMode::LeftRight) {
Input::SimulateButtonPress(Input::RIGHT);
}
}
#endif
}

void Game_Ineluki::OnScriptFileReady(FileRequestResult* result) {
auto it = std::find_if(async_scripts.begin(), async_scripts.end(), [&](const auto& a) {
return a.script_name == result->file;
Expand Down
28 changes: 27 additions & 1 deletion src/game_ineluki.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,21 @@ class Game_Ineluki {
int GetMidiTicks();

/**
* Updates the key up/down list. Must be called once per update frame.
* Updates the configured input patches. Must be called once per update frame.
*/
void Update();

private:
/**
* Updates the key up/down list.
*/
void UpdateKeys();

/**
* Handles virtual key bindings for mouse buttons.
*/
void UpdateMouse();

/**
* Parses and caches the script.
*
Expand Down Expand Up @@ -123,6 +133,22 @@ class Game_Ineluki {
bool mouse_support = false;
int mouse_id_prefix = 0;

enum class MouseReturnMode {
None,
Left,
Right,
Both
};

enum class MouseWheelMode {
None,
UpDown,
LeftRight
};

MouseReturnMode mouse_decision_binding = MouseReturnMode::None;
MouseWheelMode mouse_wheel_binding = MouseWheelMode::None;

struct Mapping {
Input::Keys::InputKey key;
const char* name;
Expand Down
24 changes: 24 additions & 0 deletions src/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -408,3 +408,27 @@ void Input::ResetMask() {
SetMask(source->GetMask());
}

void Input::SimulateButtonPress(Input::InputButton button) {
switch (button) {
case Input::UP:
case Input::DOWN:
case Input::LEFT:
case Input::RIGHT:
{
// Directional movement has its own input handling
// These buttons need to be simulated on a lower level,
// or else those movement actions will be overwritten
auto& cfg = source->GetConfig();
for (auto& bm : cfg.buttons) {
if (bm.first == button) {
source->SimulateKeyPress(bm.second);
break;
}
}
break;
}
default:
break;
}
UpdateButton(button, true);
}
9 changes: 9 additions & 0 deletions src/input.h
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,15 @@ namespace Input {
*/
Source* GetInputSource();

/**
* Used to simulate a button press. This is used for
* emulating the behavior of some runtime patches.
* Buttons for directional movement will be delegated
* to the underlying low level input source.
* @param button The input button which should be registered as being 'pressed'
*/
void SimulateButtonPress(Input::InputButton button);

/** Buttons press time (in frames). */
extern std::array<int, BUTTON_COUNT> press_time;

Expand Down
7 changes: 6 additions & 1 deletion src/input_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ void Input::UiSource::DoUpdate(bool system_only) {
}

if (!system_only || Input::IsSystemButton(bm.first)) {
pressed_buttons[bm.first] = pressed_buttons[bm.first] || keystates[bm.second];
pressed_buttons[bm.first] = pressed_buttons[bm.first] || keystates[bm.second] || keystates_virtual[bm.second];
}
}
keystates_virtual = {};

Record();

Expand Down Expand Up @@ -330,6 +331,10 @@ void Input::Source::AddRecordingData(Input::RecordingData type, StringView data)
}
}

void Input::Source::SimulateKeyPress(Input::Keys::InputKey key) {
keystates_virtual[key] = true;
}

void Input::LogSource::UpdateSystem() {
// input log does not record actions outside of logical frames.
}
Expand Down
7 changes: 7 additions & 0 deletions src/input_source.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,12 @@ namespace Input {
const KeyStatus& GetMask() const { return keymask; }
KeyStatus& GetMask() { return keymask; }

/**
* Emulate a key being pressed.
* @param key
*/
void SimulateKeyPress(Input::Keys::InputKey key);

protected:
void Record();
void UpdateGamepad();
Expand All @@ -152,6 +158,7 @@ namespace Input {

KeyStatus keystates;
KeyStatus keymask;
KeyStatus keystates_virtual;
Point mouse_pos;
AnalogInput analog_input;

Expand Down