Add voice muting, add input key and mouse functions

This commit is contained in:
Kae 2023-07-20 12:52:08 +10:00
parent db3d004d30
commit 3aa45ab799
4 changed files with 120 additions and 45 deletions

View File

@ -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

View File

@ -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<std::pair<InputEvent, bool>> 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<MouseButtonDownEvent>()) {
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<MouseButtonUpEvent>()) {
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<unsigned> 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<unsigned> 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<unsigned> Input::keyDown(Key key, Maybe<KeyMod> 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<unsigned> Input::keyUp(Key key) {
if (auto state = m_keyStates.ptr(key)) {
if (state->releases)
return state->releases;
}
return {};
}
Maybe<List<Vec2I>> 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<List<Vec2I>> Input::mouseUp(MouseButton button) {
if (auto state = m_mouseStates.ptr(button)) {
if (state->releases)
return state->releasePositions;
}
return {};
}

View File

@ -117,6 +117,17 @@ public:
inline void release() { released = ++releases; held = false; }
};
struct KeyInputState : InputState {
KeyMod mods = KeyMod::NoMod;
};
struct MouseInputState : InputState {
List<Vec2I> pressPositions;
List<Vec2I> 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<unsigned> bindUp (String const& categoryId, String const& bindId);
Maybe<unsigned> keyDown(Key key, Maybe<KeyMod> keyMod);
bool keyHeld(Key key);
Maybe<unsigned> keyUp (Key key);
Maybe<List<Vec2I>> mouseDown(MouseButton button);
bool mouseHeld(MouseButton button);
Maybe<List<Vec2I>> 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<InputVariant, InputState> m_inputStates;
HashMap<Key, KeyInputState> m_keyStates;
HashMap<MouseButton, MouseInputState> m_mouseStates;
HashMap<ControllerButton, ControllerInputState> m_controllerStates;
//Bind states
HashMap<BindEntry const*, InputState> m_bindStates;

View File

@ -13,6 +13,23 @@ LuaCallbacks LuaBindings::makeInputCallbacks() {
callbacks.registerCallbackWithSignature<bool, String, String>("bindHeld", bind(mem_fn(&Input::bindHeld), input, _1, _2));
callbacks.registerCallbackWithSignature<Maybe<unsigned>, String, String>("bindUp", bind(mem_fn(&Input::bindUp), input, _1, _2));
callbacks.registerCallback("keyDown", [input](String const& keyName, Maybe<StringList>& const modNames) -> Maybe<unsigned> {
Key key = KeyNames.getLeft(keyName);
Maybe<KeyMod> 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<unsigned> { return input->keyUp( KeyNames.getLeft(keyName)); });
callbacks.registerCallback("mouseDown", [input](String const& buttonName) -> Maybe<List<Vec2I>> { 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<List<Vec2I>> { return input->mouseUp( MouseButtonNames.getLeft(buttonName)); });
callbacks.registerCallbackWithSignature<void, String, String>("resetBinds", bind(mem_fn(&Input::resetBinds), input, _1, _2));
callbacks.registerCallbackWithSignature<void, String, String, Json>("setBinds", bind(mem_fn(&Input::setBinds), input, _1, _2, _3));
callbacks.registerCallbackWithSignature<Json, String, String>("getDefaultBinds", bind(mem_fn(&Input::getDefaultBinds), input, _1, _2));