diff --git a/ControlManager.cpp b/ControlManager.cpp index 01b3325..5dd1c1f 100644 --- a/ControlManager.cpp +++ b/ControlManager.cpp @@ -48,8 +48,9 @@ #define CONTROL_OSC_MSG "OSC: " -bool Control::input_active[INPUT_MAX]{}; -float Control::input_values[INPUT_MAX]{}; +//bool Control::input_active[INPUT_MAX]{}; +//float Control::input_values[INPUT_MAX]{}; +//std::mutex Control::input_access_; void Control::RequestListener::ProcessMessage( const osc::ReceivedMessage& m, @@ -256,6 +257,11 @@ Control::Control() : receiver_(nullptr) multitouch_active[i] = false; multitouch_values[i] = glm::vec2(0.f); } + + for (size_t i = 0; i < INPUT_MAX; ++i) { + input_active[i] = false; + input_values[i] = 0.f; + } } Control::~Control() @@ -396,21 +402,26 @@ bool Control::init() void Control::update() { + // read joystick buttons int num_buttons = 0; const unsigned char *state_buttons = glfwGetJoystickButtons(GLFW_JOYSTICK_1, &num_buttons ); // map to Control input array for (int b = 0; b < num_buttons; ++b) { - Control::input_active[INPUT_JOYSTICK_FIRST_BUTTON + b] = state_buttons[b] == GLFW_PRESS; - Control::input_values[INPUT_JOYSTICK_FIRST_BUTTON + b] = state_buttons[b] == GLFW_PRESS ? 1.f : 0.f; + input_access_.lock(); + input_active[INPUT_JOYSTICK_FIRST_BUTTON + b] = state_buttons[b] == GLFW_PRESS; + input_values[INPUT_JOYSTICK_FIRST_BUTTON + b] = state_buttons[b] == GLFW_PRESS ? 1.f : 0.f; + input_access_.unlock(); } // read joystick axis int num_axis = 0; const float *state_axis = glfwGetJoystickAxes(GLFW_JOYSTICK_1, &num_axis ); for (int a = 0; a < num_axis; ++a) { - Control::input_active[INPUT_JOYSTICK_FIRST_AXIS + a] = ABS(state_axis[a]) > 0.02 ? true : false; - Control::input_values[INPUT_JOYSTICK_FIRST_AXIS + a] = state_axis[a]; + input_access_.lock(); + input_active[INPUT_JOYSTICK_FIRST_AXIS + a] = ABS(state_axis[a]) > 0.02 ? true : false; + input_values[INPUT_JOYSTICK_FIRST_AXIS + a] = state_axis[a]; + input_access_.unlock(); } // multitouch input needs to be cleared when no more OSC input comes in @@ -418,9 +429,11 @@ void Control::update() if ( multitouch_active[m] > 0 ) multitouch_active[m] -= 1; else { - Control::input_active[INPUT_MULTITOUCH_FIRST + m] = false; - Control::input_values[INPUT_MULTITOUCH_FIRST + m] = 0.f; + input_access_.lock(); + input_active[INPUT_MULTITOUCH_FIRST + m] = false; + input_values[INPUT_MULTITOUCH_FIRST + m] = 0.f; multitouch_values[m] = glm::vec2(0.f); + input_access_.unlock(); } } @@ -696,22 +709,26 @@ void Control::receiveMultitouchAttribute(const std::string &attribute, if ( !arguments.Eos()) arguments >> x >> y >> osc::EndMessage; + input_access_.lock(); + // if the touch was already pressed if ( multitouch_active[t] > 0 ) { // active value decreases with the distance from original press position - Control::input_values[INPUT_MULTITOUCH_FIRST + t] = 1.f - glm::distance(Control::multitouch_values[t], glm::vec2(x, y)) / M_SQRT2; + input_values[INPUT_MULTITOUCH_FIRST + t] = 1.f - glm::distance(Control::multitouch_values[t], glm::vec2(x, y)) / M_SQRT2; } // first time touch is pressed else { // store original press position multitouch_values[t] = glm::vec2(x, y); // active value is 1.f at first press (full) - Control::input_values[INPUT_MULTITOUCH_FIRST + t] = 1.f; + input_values[INPUT_MULTITOUCH_FIRST + t] = 1.f; } // keep track of button press multitouch_active[t] = 3; // set array of active input - Control::input_active[INPUT_MULTITOUCH_FIRST + t] = true; + input_active[INPUT_MULTITOUCH_FIRST + t] = true; + + input_access_.unlock(); } } catch (osc::MissingArgumentException &e) { @@ -858,13 +875,14 @@ void Control::keyboardCalback(GLFWwindow* window, int key, int, int action, int { if (UserInterface::manager().keyboardAvailable() && !mods ) { + Control::manager().input_access_.lock(); if (key >= GLFW_KEY_A && key <= GLFW_KEY_Z) { - Control::input_active[INPUT_KEYBOARD_FIRST + key - GLFW_KEY_A] = action > GLFW_RELEASE; - Control::input_values[INPUT_KEYBOARD_FIRST + key - GLFW_KEY_A] = action > GLFW_RELEASE ? 1.f : 0.f; + Control::manager().input_active[INPUT_KEYBOARD_FIRST + key - GLFW_KEY_A] = action > GLFW_RELEASE; + Control::manager().input_values[INPUT_KEYBOARD_FIRST + key - GLFW_KEY_A] = action > GLFW_RELEASE ? 1.f : 0.f; } else if (key >= GLFW_KEY_KP_0 && key <= GLFW_KEY_KP_EQUAL) { - Control::input_active[INPUT_NUMPAD_FIRST + key - GLFW_KEY_KP_0] = action > GLFW_RELEASE; - Control::input_values[INPUT_NUMPAD_FIRST + key - GLFW_KEY_KP_0] = action > GLFW_RELEASE ? 1.f : 0.f; + Control::manager().input_active[INPUT_NUMPAD_FIRST + key - GLFW_KEY_KP_0] = action > GLFW_RELEASE; + Control::manager().input_values[INPUT_NUMPAD_FIRST + key - GLFW_KEY_KP_0] = action > GLFW_RELEASE ? 1.f : 0.f; } else if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS ) { @@ -872,17 +890,26 @@ void Control::keyboardCalback(GLFWwindow* window, int key, int, int action, int if (window==output) Rendering::manager().outputWindow().exitFullscreen(); } + Control::manager().input_access_.unlock(); } } bool Control::inputActive(uint id) { - return Control::input_active[MIN(id,INPUT_MAX)] && !Settings::application.mapping.disabled; + input_access_.lock(); + const bool ret = input_active[MIN(id,INPUT_MAX)]; + input_access_.unlock(); + + return ret && !Settings::application.mapping.disabled; } float Control::inputValue(uint id) { - return Control::input_values[MIN(id,INPUT_MAX)]; + input_access_.lock(); + const float ret = input_values[MIN(id,INPUT_MAX)]; + input_access_.unlock(); + + return ret; } std::string Control::inputLabel(uint id) diff --git a/ControlManager.h b/ControlManager.h index 0a22c3f..23e6384 100644 --- a/ControlManager.h +++ b/ControlManager.h @@ -100,8 +100,8 @@ public: // OSC translation std::string translate (std::string addresspqattern); - static bool inputActive(uint id); - static float inputValue(uint id); + bool inputActive (uint id); + float inputValue (uint id); static std::string inputLabel(uint id); protected: @@ -139,8 +139,10 @@ private: void loadOscConfig(); void resetOscConfig(); - static bool input_active[INPUT_MAX]; - static float input_values[INPUT_MAX]; + bool input_active[INPUT_MAX]; + float input_values[INPUT_MAX]; + std::mutex input_access_; + int multitouch_active[INPUT_MULTITOUCH_COUNT]; glm::vec2 multitouch_values[INPUT_MULTITOUCH_COUNT]; diff --git a/Source.cpp b/Source.cpp index d20518d..0ce3e8f 100644 --- a/Source.cpp +++ b/Source.cpp @@ -764,7 +764,7 @@ void Source::updateCallbacks(float dt) // if the Reaction is valid if ( k->second.model_ != nullptr) { - bool activate = Control::inputActive(k->first); + bool activate = Control::manager().inputActive(k->first); // if the value referenced as pressed changed state // or repeat key if there is no reverse callback @@ -775,7 +775,7 @@ void Source::updateCallbacks(float dt) // generate a new callback from the model SourceCallback *C = k->second.model_->clone(); // apply value multiplyer from input - C->multiply( Control::inputValue(k->first) ); + C->multiply( Control::manager().inputValue(k->first) ); // add callback to the source (force override) call( C, true ); // delete the reverse if was not released diff --git a/UserInterfaceManager.cpp b/UserInterfaceManager.cpp index 355996a..8e0808e 100644 --- a/UserInterfaceManager.cpp +++ b/UserInterfaceManager.cpp @@ -4533,7 +4533,7 @@ void InputMappingInterface::Render() ImGui::EndMenuBar(); } - // current windowdraw parameters + // current window draw parameters const ImGuiWindow* window = ImGui::GetCurrentWindow(); ImDrawList* draw_list = window->DrawList; ImVec2 frame_top = ImGui::GetCursorScreenPos(); @@ -4554,10 +4554,13 @@ void InputMappingInterface::Render() } } + // tooltip declined for each mode + std::string _tooltip; // // KEYBOARD // if ( Settings::application.mapping.mode == 0 ) { + _tooltip = "Key press on computer keyboard."; // Draw table of letter keys [A] to [Y] ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); @@ -4572,7 +4575,7 @@ void InputMappingInterface::Render() for (uint ik = INPUT_KEYBOARD_FIRST; ik < INPUT_KEYBOARD_LAST; ++ik){ int i = ik - INPUT_KEYBOARD_FIRST; // draw overlay on active keys - if ( Control::inputActive(ik) ) { + if ( Control::manager().inputActive(ik) ) { ImVec2 pos = frame_top + keyLetterItemSize * ImVec2( i % 5, i / 5); draw_list->AddRectFilled(pos, pos + keyLetterIconSize, ImGui::GetColorU32(ImGuiCol_Border), 6.f); // set current @@ -4626,6 +4629,8 @@ void InputMappingInterface::Render() // NUMPAD // else if ( Settings::application.mapping.mode == 1 ) { + _tooltip = "Key press on computer numerical keypad."; + // custom layout of numerical keypad std::vector numpad_inputs = { INPUT_NUMPAD_FIRST+7, INPUT_NUMPAD_FIRST+8, INPUT_NUMPAD_FIRST+9, INPUT_NUMPAD_FIRST+11, INPUT_NUMPAD_FIRST+4, INPUT_NUMPAD_FIRST+5, INPUT_NUMPAD_FIRST+6, INPUT_NUMPAD_FIRST+12, @@ -4647,7 +4652,7 @@ void InputMappingInterface::Render() ImVec2 iconsize = p == 12 ? keyNumpadIconSize + ImVec2(keyNumpadIconSize.x+ g.Style.ItemSpacing.x, 0.f) : keyNumpadIconSize; ImVec2 itemsize = p == 12 ? keyNumpadItemSize + ImVec2(keyNumpadItemSize.x+ g.Style.ItemSpacing.x, 0.f) : keyNumpadItemSize; // draw overlay on active keys - if ( Control::inputActive(ik) ) { + if ( Control::manager().inputActive(ik) ) { ImVec2 pos = frame_top + itemsize * ImVec2( p % 4, p / 4); pos += p > 12 ? ImVec2(keyNumpadIconSize.x+ g.Style.ItemSpacing.x, 0.f) : ImVec2(0,0); draw_list->AddRectFilled(pos, pos + iconsize, ImGui::GetColorU32(ImGuiCol_Border), 6.f); @@ -4702,6 +4707,7 @@ void InputMappingInterface::Render() // MULTITOUCH OSC // else if ( Settings::application.mapping.mode == 2 ) { + _tooltip = "Press and hold in the 'Multitouch' panel of the vimix TouchOSC companion."; // Draw table of TouchOSC buttons ImGuiToolkit::PushFont(ImGuiToolkit::FONT_LARGE); @@ -4721,7 +4727,7 @@ void InputMappingInterface::Render() ImVec2 pos = frame_top + keyNumpadItemSize * ImVec2( t % 4, t / 4); // draw overlay on active keys - if ( Control::inputActive(it) ) { + if ( Control::manager().inputActive(it) ) { draw_list->AddRectFilled(pos, pos + keyNumpadIconSize, ImGui::GetColorU32(ImGuiCol_Border), 6.f); // set current current_input_ = it; @@ -4745,7 +4751,7 @@ void InputMappingInterface::Render() // Draw value bar ImVec2 prev = ImGui::GetCursorScreenPos(); ImGui::SetCursorScreenPos( pos + touch_bar_pos); - ImGui::ProgressBar(Control::inputValue(it), touch_bar_size, ""); + ImGui::ProgressBar(Control::manager().inputValue(it), touch_bar_size, ""); ImGui::SetCursorScreenPos( prev ); } @@ -4759,6 +4765,7 @@ void InputMappingInterface::Render() // JOYSTICK // else if ( Settings::application.mapping.mode == 3 ) { + _tooltip = "Button press and axis movements on a connected gamepad or joystick."; // custom layout of gamepad buttons std::vector gamepad_inputs = { INPUT_JOYSTICK_FIRST_BUTTON+11, INPUT_JOYSTICK_FIRST_BUTTON+13, @@ -4793,7 +4800,7 @@ void InputMappingInterface::Render() for (size_t b = 0; b < gamepad_inputs.size(); ++b ){ uint ig = gamepad_inputs[b]; // draw overlay on active keys - if ( Control::inputActive(ig) ) { + if ( Control::manager().inputActive(ig) ) { ImVec2 pos = frame_top + keyLetterItemSize * ImVec2( b % 5, b / 5); draw_list->AddRectFilled(pos, pos + keyLetterIconSize, ImGui::GetColorU32(ImGuiCol_Border), 6.f); // set current @@ -4852,7 +4859,7 @@ void InputMappingInterface::Render() ImVec2 pos = axis_top; // Draw a little bar showing activity on the gamepad axis ImGui::SetCursorScreenPos( pos + axis_bar_pos); - ImGuiToolkit::ValueBar(Control::inputValue(INPUT_JOYSTICK_FIRST_AXIS), axis_bar_size); + ImGuiToolkit::ValueBar(Control::manager().inputValue(INPUT_JOYSTICK_FIRST_AXIS), axis_bar_size); // Draw button to assign the axis to an action ImGui::SetCursorScreenPos( pos ); if (ImGui::Selectable("LX", input_assigned[INPUT_JOYSTICK_FIRST_AXIS], 0, axis_icon_size)) @@ -4863,7 +4870,7 @@ void InputMappingInterface::Render() pos = axis_top + ImVec2( 0, axis_item_size.y); ImGui::SetCursorScreenPos( pos + axis_bar_pos); - ImGuiToolkit::ValueBar(Control::inputValue(INPUT_JOYSTICK_FIRST_AXIS+1), axis_bar_size); + ImGuiToolkit::ValueBar(Control::manager().inputValue(INPUT_JOYSTICK_FIRST_AXIS+1), axis_bar_size); ImGui::SetCursorScreenPos( pos ); if (ImGui::Selectable("LY", input_assigned[INPUT_JOYSTICK_FIRST_AXIS+1], 0, axis_icon_size)) current_input_ = INPUT_JOYSTICK_FIRST_AXIS+1; @@ -4872,7 +4879,7 @@ void InputMappingInterface::Render() pos = axis_top + ImVec2( 0, 2.f * axis_item_size.y); ImGui::SetCursorScreenPos( pos + axis_bar_pos); - ImGuiToolkit::ValueBar(Control::inputValue(INPUT_JOYSTICK_FIRST_AXIS+2), axis_bar_size); + ImGuiToolkit::ValueBar(Control::manager().inputValue(INPUT_JOYSTICK_FIRST_AXIS+2), axis_bar_size); ImGui::SetCursorScreenPos( pos ); if (ImGui::Selectable("L2", input_assigned[INPUT_JOYSTICK_FIRST_AXIS+2], 0, axis_icon_size)) current_input_ = INPUT_JOYSTICK_FIRST_AXIS+2; @@ -4887,7 +4894,7 @@ void InputMappingInterface::Render() pos = axis_top + ImVec2( axis_item_size.x, 0.f); ImGui::SetCursorScreenPos( pos + axis_bar_pos); - ImGuiToolkit::ValueBar(Control::inputValue(INPUT_JOYSTICK_FIRST_AXIS+3), axis_bar_size); + ImGuiToolkit::ValueBar(Control::manager().inputValue(INPUT_JOYSTICK_FIRST_AXIS+3), axis_bar_size); ImGui::SetCursorScreenPos( pos ); if (ImGui::Selectable("RX", input_assigned[INPUT_JOYSTICK_FIRST_AXIS+3], 0, axis_icon_size)) current_input_ = INPUT_JOYSTICK_FIRST_AXIS+3; @@ -4896,7 +4903,7 @@ void InputMappingInterface::Render() pos = axis_top + ImVec2( axis_item_size.x, axis_item_size.y); ImGui::SetCursorScreenPos( pos + axis_bar_pos); - ImGuiToolkit::ValueBar(Control::inputValue(INPUT_JOYSTICK_FIRST_AXIS+4), axis_bar_size); + ImGuiToolkit::ValueBar(Control::manager().inputValue(INPUT_JOYSTICK_FIRST_AXIS+4), axis_bar_size); ImGui::SetCursorScreenPos( pos ); if (ImGui::Selectable("RY", input_assigned[INPUT_JOYSTICK_FIRST_AXIS+4], 0, axis_icon_size)) current_input_ = INPUT_JOYSTICK_FIRST_AXIS+4; @@ -4905,7 +4912,7 @@ void InputMappingInterface::Render() pos = axis_top + ImVec2( axis_item_size.x, 2.f * axis_item_size.y); ImGui::SetCursorScreenPos( pos + axis_bar_pos); - ImGuiToolkit::ValueBar(Control::inputValue(INPUT_JOYSTICK_FIRST_AXIS+5), axis_bar_size); + ImGuiToolkit::ValueBar(Control::manager().inputValue(INPUT_JOYSTICK_FIRST_AXIS+5), axis_bar_size); ImGui::SetCursorScreenPos( pos ); if (ImGui::Selectable("R2", input_assigned[INPUT_JOYSTICK_FIRST_AXIS+5], 0, axis_icon_size)) current_input_ = INPUT_JOYSTICK_FIRST_AXIS+5; @@ -5048,7 +5055,9 @@ void InputMappingInterface::Render() } // Custom popup menu for the current input actions (right aligned) - ImGui::SetCursorScreenPos(frame_top + ImVec2(window->Size.x - g.FontSize - g.Style.FramePadding.x * 2.0f - g.Style.WindowPadding.x, g.Style.FramePadding.y)); + ImGui::SetCursorScreenPos(frame_top + ImVec2(window->Size.x - 2.f * g.FontSize - g.Style.FramePadding.x * 3.0f - g.Style.WindowPadding.x, g.Style.FramePadding.y)); + ImGuiToolkit::HelpToolTip(_tooltip.c_str()); + ImGui::SameLine(0, g.Style.FramePadding.x); if (ImGuiToolkit::IconButton(5, 8)) ImGui::OpenPopup( "MenuInputMapping" ); if (ImGui::BeginPopup( "MenuInputMapping" ))