diff --git a/assets/opensb/scripts/opensb/universeclient/voicemanager.lua b/assets/opensb/scripts/opensb/universeclient/voicemanager.lua index 2f19f6a..0a93c3f 100644 --- a/assets/opensb/scripts/opensb/universeclient/voicemanager.lua +++ b/assets/opensb/scripts/opensb/universeclient/voicemanager.lua @@ -80,17 +80,18 @@ local function drawSpeakerBar(mouse, pos, speaker, i) hoveredSpeaker = speaker hoveredSpeakerIndex = i hoveredSpeakerPosition = pos - --if input.key("LShift") then - -- textPositioning.position = {pos[1] + 288, pos[2] + 24} - -- textPositioning.horizontalAnchor = "right" - -- canvas:drawText("^#fff7;" .. tostring(speaker.speakerId), textPositioning, 16, nil, nil, nil, FONT_DIRECTIVES) - --end --- - --if input.mouseDown("MouseLeft") then - -- local muted = not voice.muted(speaker.speakerId) - -- interface.queueMessage((muted and "^#f43030;Muted^reset; " or "^#31d2f7;Unmuted^reset; ") .. speaker.name, 4, 0.5) - -- voice.setMuted(speaker.speakerId, muted) - --end + if input.keyHeld("LShift") then + textPositioning.position = {pos[1] + 288, pos[2] + 24} + textPositioning.horizontalAnchor = "right" + canvas:drawText("^#fff7,font=iosevka-semibold;" .. tostring(speaker.speakerId), textPositioning, 16, nil, nil, nil, FONT_DIRECTIVES) + end + + if input.mouseDown("MouseLeft") then + local muted = not voice.speakerMuted(speaker.speakerId) + interface.queueMessage((muted and "^#f43030;Muted^reset; " or "^#31d2f7;Unmuted^reset; ") .. speaker.name, 4, 0.5) + voice.setSpeakerMuted(speaker.speakerId, muted) + speaker.muted = muted + end end end diff --git a/source/game/StarInput.cpp b/source/game/StarInput.cpp index 7c50d4b..7f0c09c 100644 --- a/source/game/StarInput.cpp +++ b/source/game/StarInput.cpp @@ -316,10 +316,6 @@ Input::InputState* Input::bindStatePtr(String const& categoryId, String const& b return nullptr; } -Input::InputState* Input::inputStatePtr(InputVariant key) { - return m_inputStates.ptr(key); -} - Input* Input::s_singleton; Input* Input::singletonPtr() { @@ -361,28 +357,17 @@ List> const& Input::inputEventsThisFrame() const { void Input::reset() { - m_inputEvents.resize(0); // keeps reserved memory - { - auto it = m_inputStates.begin(); - while (it != m_inputStates.end()) { - if (it->second.held) { - it->second.reset(); - ++it; - } - else it = m_inputStates.erase(it); - } - } + m_inputEvents.clear(); + auto eraseCond = [](auto& p) { + if (p.second.held) + p.second.reset(); + return !p.second.held; + }; - { - auto it = m_bindStates.begin(); - while (it != m_bindStates.end()) { - if (it->second.held) { - it->second.reset(); - ++it; - } - else it = m_bindStates.erase(it); - } - } + eraseWhere(m_keyStates, eraseCond); + eraseWhere(m_mouseStates, eraseCond); + eraseWhere(m_controllerStates, eraseCond); + eraseWhere(m_bindStates, eraseCond); } void Input::update() { @@ -397,7 +382,10 @@ bool Input::handleInput(InputEvent const& input, bool gameProcessed) { m_pressedMods |= *keyToMod; if (!gameProcessed && !m_textInputActive) { - m_inputStates[keyDown->key].press(); + auto& state = m_keyStates[keyDown->key]; + if (keyToMod) + state.mods |= *keyToMod; + state.press(); if (auto binds = m_bindMappings.ptr(keyDown->key)) { for (auto bind : filterBindEntries(*binds, keyDown->mods)) @@ -410,8 +398,11 @@ bool Input::handleInput(InputEvent const& input, bool gameProcessed) { m_pressedMods &= ~*keyToMod; // We need to be able to release input even when gameProcessed is true, but only if it's already down. - if (auto state = m_inputStates.ptr(keyUp->key)) + if (auto state = m_keyStates.ptr(keyUp->key)) { + if (keyToMod) + state->mods &= ~*keyToMod; state->release(); + } if (auto binds = m_bindMappings.ptr(keyUp->key)) { for (auto& bind : *binds) { @@ -421,7 +412,9 @@ bool Input::handleInput(InputEvent const& input, bool gameProcessed) { } } else if (auto mouseDown = input.ptr()) { if (!gameProcessed) { - m_inputStates[mouseDown->mouseButton].press(); + auto& state = m_mouseStates[mouseDown->mouseButton]; + state.pressPositions.append(mouseDown->mousePosition); + state.press(); if (auto binds = m_bindMappings.ptr(mouseDown->mouseButton)) { for (auto bind : filterBindEntries(*binds, m_pressedMods)) @@ -429,8 +422,10 @@ bool Input::handleInput(InputEvent const& input, bool gameProcessed) { } } } else if (auto mouseUp = input.ptr()) { - if (auto state = m_inputStates.ptr(mouseUp->mouseButton)) + if (auto state = m_mouseStates.ptr(mouseUp->mouseButton)) { + state->releasePositions.append(mouseUp->mousePosition); state->release(); + } if (auto binds = m_bindMappings.ptr(mouseUp->mouseButton)) { for (auto& bind : *binds) { @@ -497,10 +492,10 @@ void Input::setTextInputActive(bool active) { } Maybe Input::bindDown(String const& categoryId, String const& bindId) { - if (auto state = bindStatePtr(categoryId, bindId)) + if (auto state = bindStatePtr(categoryId, bindId)) { if (state->presses) return state->presses; - + } return {}; } @@ -512,10 +507,52 @@ bool Input::bindHeld(String const& categoryId, String const& bindId) { } Maybe Input::bindUp(String const& categoryId, String const& bindId) { - if (auto state = bindStatePtr(categoryId, bindId)) + if (auto state = bindStatePtr(categoryId, bindId)) { if (state->releases) return state->releases; + } + return {}; +} +Maybe Input::keyDown(Key key, Maybe keyMod) { + if (auto state = m_keyStates.ptr(key)) { + if (state->presses && (!keyMod || compareKeyMod(*keyMod, state->mods))) + return state->presses; + } + return {}; +} + +bool Input::keyHeld(Key key) { + auto state = m_keyStates.ptr(key); + return state && state->held; +} + +Maybe Input::keyUp(Key key) { + if (auto state = m_keyStates.ptr(key)) { + if (state->releases) + return state->releases; + } + return {}; +} + +Maybe> Input::mouseDown(MouseButton button) { + if (auto state = m_mouseStates.ptr(button)) { + if (state->presses) + return state->pressPositions; + } + return {}; +} + +bool Input::mouseHeld(MouseButton button) { + auto state = m_mouseStates.ptr(button); + return state && state->held; +} + +Maybe> Input::mouseUp(MouseButton button) { + if (auto state = m_mouseStates.ptr(button)) { + if (state->releases) + return state->releasePositions; + } return {}; } diff --git a/source/game/StarInput.hpp b/source/game/StarInput.hpp index 96d4cc6..e4355ce 100644 --- a/source/game/StarInput.hpp +++ b/source/game/StarInput.hpp @@ -117,6 +117,17 @@ public: inline void release() { released = ++releases; held = false; } }; + struct KeyInputState : InputState { + KeyMod mods = KeyMod::NoMod; + }; + + struct MouseInputState : InputState { + List pressPositions; + List releasePositions; + }; + + typedef InputState ControllerInputState; + // Get pointer to the singleton Input instance, if it exists. Otherwise, // returns nullptr. static Input* singletonPtr(); @@ -152,6 +163,14 @@ public: bool bindHeld(String const& categoryId, String const& bindId); Maybe bindUp (String const& categoryId, String const& bindId); + Maybe keyDown(Key key, Maybe keyMod); + bool keyHeld(Key key); + Maybe keyUp (Key key); + + Maybe> mouseDown(MouseButton button); + bool mouseHeld(MouseButton button); + Maybe> mouseUp (MouseButton button); + void resetBinds(String const& categoryId, String const& bindId); void setBinds(String const& categoryId, String const& bindId, Json const& binds); Json getDefaultBinds(String const& categoryId, String const& bindId); @@ -163,7 +182,6 @@ private: BindEntry& bindEntry(String const& categoryId, String const& bindId); InputState* bindStatePtr(String const& categoryId, String const& bindId); - InputState* inputStatePtr(InputVariant key); static Input* s_singleton; @@ -179,7 +197,9 @@ private: // Per-frame input state maps. //Input states - HashMap m_inputStates; + HashMap m_keyStates; + HashMap m_mouseStates; + HashMap m_controllerStates; //Bind states HashMap m_bindStates; diff --git a/source/game/scripting/StarInputLuaBindings.cpp b/source/game/scripting/StarInputLuaBindings.cpp index 5195e31..9f58a40 100644 --- a/source/game/scripting/StarInputLuaBindings.cpp +++ b/source/game/scripting/StarInputLuaBindings.cpp @@ -13,6 +13,23 @@ LuaCallbacks LuaBindings::makeInputCallbacks() { callbacks.registerCallbackWithSignature("bindHeld", bind(mem_fn(&Input::bindHeld), input, _1, _2)); callbacks.registerCallbackWithSignature, String, String>("bindUp", bind(mem_fn(&Input::bindUp), input, _1, _2)); + callbacks.registerCallback("keyDown", [input](String const& keyName, Maybe& const modNames) -> Maybe { + Key key = KeyNames.getLeft(keyName); + Maybe mod; + if (modNames) { + mod = KeyMod::NoMod; + for (auto& modName : *modNames) + *mod |= KeyModNames.getLeft(modName); + } + return input->keyDown(key, mod); + }); + callbacks.registerCallback("keyHeld", [input](String const& keyName) -> bool { return input->keyHeld(KeyNames.getLeft(keyName)); }); + callbacks.registerCallback("keyUp", [input](String const& keyName) -> Maybe { return input->keyUp( KeyNames.getLeft(keyName)); }); + + callbacks.registerCallback("mouseDown", [input](String const& buttonName) -> Maybe> { return input->mouseDown(MouseButtonNames.getLeft(buttonName)); }); + callbacks.registerCallback("mouseHeld", [input](String const& buttonName) -> bool { return input->mouseHeld(MouseButtonNames.getLeft(buttonName)); }); + callbacks.registerCallback("mouseUp", [input](String const& buttonName) -> Maybe> { return input->mouseUp( MouseButtonNames.getLeft(buttonName)); }); + callbacks.registerCallbackWithSignature("resetBinds", bind(mem_fn(&Input::resetBinds), input, _1, _2)); callbacks.registerCallbackWithSignature("setBinds", bind(mem_fn(&Input::setBinds), input, _1, _2, _3)); callbacks.registerCallbackWithSignature("getDefaultBinds", bind(mem_fn(&Input::getDefaultBinds), input, _1, _2));