mirror of
https://github.com/brunoherbelin/vimix.git
synced 2025-12-14 19:59:59 +01:00
New Timer input mapping
First working implementation of metronome events mapping to source callbacks
This commit is contained in:
@@ -321,7 +321,7 @@ Control::Control() : receiver_(nullptr)
|
||||
|
||||
for (size_t i = 0; i < INPUT_MAX; ++i) {
|
||||
input_active[i] = false;
|
||||
input_values[i] = 0.f;
|
||||
input_values[i] = 1.f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -464,24 +464,27 @@ bool Control::init()
|
||||
|
||||
void Control::update()
|
||||
{
|
||||
if (glfwJoystickPresent(GLFW_JOYSTICK_1) == GLFW_TRUE) {
|
||||
// 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) {
|
||||
input_access_.lock();
|
||||
for (int b = 0; b < MIN(num_buttons, INPUT_JOYSTICK_COUNT_BUTTON); ++b) {
|
||||
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();
|
||||
}
|
||||
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) {
|
||||
input_access_.lock();
|
||||
for (int a = 0; a < MIN(num_axis, INPUT_JOYSTICK_COUNT_AXIS); ++a) {
|
||||
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();
|
||||
}
|
||||
|
||||
@@ -498,21 +501,17 @@ void Control::update()
|
||||
}
|
||||
}
|
||||
|
||||
// draft : react to metronome
|
||||
// int p = (int) Metronome::manager().phase();
|
||||
// static bool bip = false;
|
||||
// static int t = 2;
|
||||
// if (!bip) {
|
||||
// if (p + 1 == t){
|
||||
// g_print("bip");
|
||||
// bip = true;
|
||||
// }
|
||||
// }
|
||||
// else {
|
||||
// if (p + 1 != t){
|
||||
// bip = false;
|
||||
// }
|
||||
// }
|
||||
// React to metronome
|
||||
uint p = (uint) Metronome::manager().phase();
|
||||
static uint prev_p = UINT_MAX;
|
||||
input_access_.lock();
|
||||
if (prev_p != p) {
|
||||
input_active[INPUT_TIMER_FIRST + (prev_p > INPUT_TIMER_COUNT ? 0 : prev_p) ] = false;
|
||||
input_active[INPUT_TIMER_FIRST + p] = true;
|
||||
prev_p = p;
|
||||
}
|
||||
input_access_.unlock();
|
||||
|
||||
}
|
||||
|
||||
void Control::listen()
|
||||
@@ -1613,9 +1612,9 @@ std::string Control::inputLabel(uint id)
|
||||
{
|
||||
label = std::string( "Multitouch ") + std::to_string(id - INPUT_MULTITOUCH_FIRST);
|
||||
}
|
||||
else if ( id >= INPUT_CUSTOM_FIRST && id <= INPUT_CUSTOM_LAST )
|
||||
else if ( id >= INPUT_TIMER_FIRST && id <= INPUT_TIMER_LAST )
|
||||
{
|
||||
label = std::string( "Custom ") + std::to_string(id - INPUT_CUSTOM_FIRST);
|
||||
label = std::string( "Beat ") + std::to_string(id - INPUT_TIMER_FIRST + 1);
|
||||
}
|
||||
|
||||
return label;
|
||||
|
||||
@@ -97,14 +97,17 @@
|
||||
#define INPUT_JOYSTICK_COUNT 20
|
||||
#define INPUT_JOYSTICK_LAST 64
|
||||
#define INPUT_JOYSTICK_FIRST_BUTTON 44
|
||||
#define INPUT_JOYSTICK_COUNT_BUTTON 15
|
||||
#define INPUT_JOYSTICK_LAST_BUTTON 58
|
||||
#define INPUT_JOYSTICK_FIRST_AXIS 59
|
||||
#define INPUT_JOYSTICK_COUNT_AXIS 6
|
||||
#define INPUT_JOYSTICK_LAST_AXIS 64
|
||||
#define INPUT_MULTITOUCH_FIRST 65
|
||||
#define INPUT_MULTITOUCH_COUNT 16
|
||||
#define INPUT_MULTITOUCH_LAST 81
|
||||
#define INPUT_CUSTOM_FIRST 82
|
||||
#define INPUT_CUSTOM_LAST 99
|
||||
#define INPUT_TIMER_FIRST 82
|
||||
#define INPUT_TIMER_COUNT 17
|
||||
#define INPUT_TIMER_LAST 99
|
||||
#define INPUT_MAX 100
|
||||
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ InputMappingWindow::InputMappingWindow() : WorkspaceWindow("InputMappingInterfac
|
||||
ICON_FA_TABLET_ALT " TouchOSC" ,
|
||||
ICON_FA_GAMEPAD " Gamepad",
|
||||
ICON_FA_CLOCK " Timer" };
|
||||
current_input_for_mode = { INPUT_KEYBOARD_FIRST, INPUT_NUMPAD_FIRST, INPUT_MULTITOUCH_FIRST, INPUT_JOYSTICK_FIRST };
|
||||
current_input_for_mode = { INPUT_KEYBOARD_FIRST, INPUT_NUMPAD_FIRST, INPUT_MULTITOUCH_FIRST, INPUT_JOYSTICK_FIRST, INPUT_TIMER_FIRST };
|
||||
current_input_ = current_input_for_mode[Settings::application.mapping.mode];
|
||||
}
|
||||
|
||||
@@ -734,14 +734,15 @@ void InputMappingWindow::Render()
|
||||
|
||||
// Options for current key
|
||||
const std::string key = (current_input_ < INPUT_NUMPAD_LAST) ? " Key " : " ";
|
||||
const std::string keymenu = ICON_FA_HAND_POINT_RIGHT + key + Control::manager().inputLabel(current_input_);
|
||||
const std::string keymenu = ICON_FA_ARROW_RIGHT + key + Control::manager().inputLabel(current_input_);
|
||||
if (ImGui::BeginMenu(keymenu.c_str()) )
|
||||
{
|
||||
if ( ImGui::MenuItem( ICON_FA_WINDOW_CLOSE " Reset mapping", NULL, false, S->inputAssigned(current_input_) ) )
|
||||
if ( ImGui::MenuItem(ICON_FA_TIMES " Reset", NULL, false, S->inputAssigned(current_input_) ) )
|
||||
// remove all source callback of this input
|
||||
S->deleteInputCallbacks(current_input_);
|
||||
|
||||
if (ImGui::BeginMenu(ICON_FA_CLOCK " Metronome", S->inputAssigned(current_input_)))
|
||||
if (ImGui::BeginMenu(ICON_FA_CLOCK " Metronome",
|
||||
S->inputAssigned(current_input_) && Settings::application.mapping.mode < 4 ))
|
||||
{
|
||||
Metronome::Synchronicity sync = S->inputSynchrony(current_input_);
|
||||
bool active = sync == Metronome::SYNC_NONE;
|
||||
@@ -760,7 +761,10 @@ void InputMappingWindow::Render()
|
||||
}
|
||||
|
||||
std::list<uint> models = S->assignedInputs();
|
||||
if (ImGui::BeginMenu(ICON_FA_COPY " Duplicate", models.size() > 0) )
|
||||
if (models.empty())
|
||||
ImGui::TextDisabled(ICON_FA_COPY " Copy from");
|
||||
else {
|
||||
if (ImGui::BeginMenu(ICON_FA_COPY " Copy from", models.size() > 0) )
|
||||
{
|
||||
for (auto m = models.cbegin(); m != models.cend(); ++m) {
|
||||
if ( *m != current_input_ ) {
|
||||
@@ -771,7 +775,7 @@ void InputMappingWindow::Render()
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
}
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
ImGui::EndMenuBar();
|
||||
@@ -783,7 +787,7 @@ void InputMappingWindow::Render()
|
||||
ImVec2 frame_top = ImGui::GetCursorScreenPos();
|
||||
|
||||
// change mode if a key is pressed
|
||||
for (uint k = INPUT_KEYBOARD_FIRST; k < INPUT_MAX; ++k) {
|
||||
for (uint k = INPUT_KEYBOARD_FIRST; k < INPUT_TIMER_FIRST; ++k) {
|
||||
if (Control::manager().inputActive(k)) {
|
||||
if (k < INPUT_NUMPAD_FIRST)
|
||||
Settings::application.mapping.mode = 0;
|
||||
@@ -811,6 +815,7 @@ void InputMappingWindow::Render()
|
||||
color = ImGui::GetStyle().Colors[ImGuiCol_Text];
|
||||
color.w /= Settings::application.mapping.disabled ? 2.f : 1.0f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiCol_Header, 0.4f));
|
||||
|
||||
for (uint ik = INPUT_KEYBOARD_FIRST; ik < INPUT_KEYBOARD_LAST; ++ik){
|
||||
int i = ik - INPUT_KEYBOARD_FIRST;
|
||||
@@ -861,7 +866,7 @@ void InputMappingWindow::Render()
|
||||
draw_list->AddRect(pos, pos + keyLetterIconSize, ImGui::GetColorU32(ImGuiCol_Button), 6.f, ImDrawCornerFlags_All, 0.1f);
|
||||
|
||||
}
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopFont();
|
||||
|
||||
@@ -887,6 +892,7 @@ void InputMappingWindow::Render()
|
||||
color = ImGui::GetStyle().Colors[ImGuiCol_Text];
|
||||
color.w /= Settings::application.mapping.disabled ? 2.f : 1.0f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiCol_Header, 0.4f));
|
||||
|
||||
for (size_t p = 0; p < numpad_inputs.size(); ++p){
|
||||
uint ik = numpad_inputs[p];
|
||||
@@ -939,7 +945,7 @@ void InputMappingWindow::Render()
|
||||
draw_list->AddRect(pos, pos + iconsize, ImGui::GetColorU32(ImGuiCol_Button), 6.f, ImDrawCornerFlags_All, 0.1f);
|
||||
|
||||
}
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopFont();
|
||||
|
||||
@@ -959,6 +965,7 @@ void InputMappingWindow::Render()
|
||||
color = ImGui::GetStyle().Colors[ImGuiCol_Text];
|
||||
color.w /= Settings::application.mapping.disabled ? 2.f : 1.0f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiCol_Header, 0.4f));
|
||||
|
||||
const ImVec2 touch_bar_size = keyNumpadItemSize * ImVec2(0.65f, 0.2f);
|
||||
const ImVec2 touch_bar_pos = keyNumpadItemSize * ImVec2(0.125f, 0.6f);
|
||||
@@ -1018,7 +1025,7 @@ void InputMappingWindow::Render()
|
||||
|
||||
}
|
||||
|
||||
ImGui::PopStyleColor(2);
|
||||
ImGui::PopStyleColor(3);
|
||||
ImGui::PopStyleVar(2);
|
||||
ImGui::PopFont();
|
||||
|
||||
@@ -1055,6 +1062,7 @@ void InputMappingWindow::Render()
|
||||
color = ImGui::GetStyle().Colors[ImGuiCol_Text];
|
||||
color.w /= Settings::application.mapping.disabled ? 2.f : 1.0f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiCol_Header, 0.4f));
|
||||
|
||||
// CENTER text for button
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_SelectableTextAlign, ImVec2(0.5f, 0.5f));
|
||||
@@ -1184,8 +1192,8 @@ void InputMappingWindow::Render()
|
||||
|
||||
ImGui::PopStyleVar(2);
|
||||
|
||||
// Done with color and font change
|
||||
ImGui::PopStyleColor(2);
|
||||
// Done with color change
|
||||
ImGui::PopStyleColor(3);
|
||||
|
||||
}
|
||||
//
|
||||
@@ -1199,37 +1207,43 @@ void InputMappingWindow::Render()
|
||||
const glm::vec2 mpo = glm::vec2 (io.MousePos.x - circle_center.x, io.MousePos.y - circle_center.y);
|
||||
const float angle = - glm::orientedAngle( glm::normalize(mpo), glm::vec2(1.f,0.f));
|
||||
const float lenght = glm::length(mpo);
|
||||
const float cm = 0.02f ; // circle margin
|
||||
const float cm = 0.03f ; // circle margin
|
||||
|
||||
// color palette
|
||||
static ImU32 colorbg = ImGui::GetColorU32(ImGuiCol_FrameBgActive, 0.6f);
|
||||
static ImU32 colorfg = ImGui::GetColorU32(ImGuiCol_FrameBg, 2.5f);
|
||||
static ImU32 colorover = ImGui::GetColorU32(ImGuiCol_Header);
|
||||
ImVec4 color = ImGui::GetStyle().Colors[ImGuiCol_Header];
|
||||
color.w /= Settings::application.mapping.disabled ? 2.f : 0.9f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, color);
|
||||
color = ImGui::GetStyle().Colors[ImGuiCol_Text];
|
||||
color.w /= Settings::application.mapping.disabled ? 2.f : 1.0f;
|
||||
ImGui::PushStyleColor(ImGuiCol_Text, color);
|
||||
ImGui::PushStyleColor(ImGuiCol_Header, ImGui::GetColorU32(ImGuiCol_Header, 0.4f));
|
||||
|
||||
// draw background ring
|
||||
static ImU32 colorbg = ImGui::GetColorU32(ImGuiCol_FrameBgActive, 0.6f);
|
||||
draw_list->AddCircleFilled(circle_center, circle_radius, colorbg, PLOT_CIRCLE_SEGMENTS);
|
||||
|
||||
// draw slices
|
||||
// metronome timer info
|
||||
char text_buf[24] = {0};
|
||||
const double q = Metronome::manager().quantum();
|
||||
static const float resolution = PLOT_CIRCLE_SEGMENTS / (2.f * M_PI);
|
||||
static ImVec2 buffer[PLOT_CIRCLE_SEGMENTS];
|
||||
|
||||
for (int p = 0.0 ; p < (int) floor(q) ; p++) {
|
||||
float a0 = cm + - M_PI_2 + (float(p)/floor(q)) * (2.f * M_PI);
|
||||
float a1 = (-2.f * 0.02) + a0 + (1.f / floor(q)) * (2.f * M_PI);
|
||||
// draw all slices of metronome ring
|
||||
for (uint ip = 0 ; ip < (uint) floor(q) ; ++ip) {
|
||||
float a0 = cm - M_PI_2 + (float(ip) * (2.f * M_PI)) / floor(q);
|
||||
float a1 = (-2.f * cm) + a0 + (2.f * M_PI) / floor(q);
|
||||
int n = ImMax(3, (int)((a1 - a0) * resolution));
|
||||
double da = (a1 - a0) / (n - 1);
|
||||
int index = 0;
|
||||
|
||||
float a01 = -cm + a0 + (0.5f / floor(q)) * (2.f * M_PI);
|
||||
buffer[index++] = circle_center + ImVec2(circle_radius * cm * cos(a01), circle_radius * cm * sin(a01));
|
||||
// start drawing at center point of slice
|
||||
float a01 = (a0 + a1) / 2.f;
|
||||
buffer[index++] = ImVec2(circle_center.x + cm * circle_radius * cos(a01), circle_center.y + cm * circle_radius * sin(a01));
|
||||
// draw round external border of slice
|
||||
for (int i = 0; i < n; ++i) {
|
||||
double a = a0 + i * da;
|
||||
buffer[index++] = ImVec2(circle_center.x + circle_radius * cos(a), circle_center.y + circle_radius * sin(a));
|
||||
}
|
||||
|
||||
// test mouse over in slices of the circle
|
||||
// Test mouse over in slices of the circle
|
||||
// 1) test if mouse is inside area
|
||||
if (ImGui::IsMouseHoveringRect(frame_top, frame_top + ImVec2(inputarea_width, inputarea_width), true))
|
||||
{
|
||||
@@ -1237,30 +1251,45 @@ void InputMappingWindow::Render()
|
||||
if (lenght < circle_radius && ( ( angle > a0 && angle < a1) || (angle + (2.f * M_PI) > a0 && angle + (2.f * M_PI) < a1) ) )
|
||||
{
|
||||
// draw the mouse-over slice
|
||||
draw_list->AddConvexPolyFilled(buffer, index, colorover);
|
||||
draw_list->AddConvexPolyFilled(buffer, index, ImGui::GetColorU32(ImGuiCol_HeaderHovered));
|
||||
// indicate tempo of mouse-over slice
|
||||
snprintf(text_buf, 24, "%d/%d", p + 1, (int) floor(q) );
|
||||
snprintf(text_buf, 24, "%d/%d", ip + 1, (int) floor(q) );
|
||||
|
||||
// mouse clic
|
||||
if (ImGui::IsMouseClicked(0)) {
|
||||
current_input_ = ip + INPUT_TIMER_FIRST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
float border = 1.f;
|
||||
// TODO : currently edited slice has a large border
|
||||
// draw the slice showing its assigned in this session
|
||||
if (S->inputAssigned(ip + INPUT_TIMER_FIRST))
|
||||
draw_list->AddConvexPolyFilled(buffer, index, ImGui::GetColorU32(ImGuiCol_Header));
|
||||
|
||||
// draw the border of the slice
|
||||
draw_list->AddPolyline(buffer, index, colorfg, true, border);
|
||||
if (ip + INPUT_TIMER_FIRST == current_input_)
|
||||
// current active slice has bold white border
|
||||
draw_list->AddPolyline(buffer, index, ImGui::GetColorU32(ImGuiCol_Text), true, 3.f);
|
||||
else
|
||||
draw_list->AddPolyline(buffer, index, ImGui::GetColorU32(ImGuiCol_Button), true, 0.5f);
|
||||
|
||||
}
|
||||
|
||||
// centered indicator 'x / N' on mouse over
|
||||
draw_list->AddCircleFilled(circle_center, circle_radius * 0.25f, colorfg, PLOT_CIRCLE_SEGMENTS);
|
||||
// draw clock hand
|
||||
float a = -M_PI_2 + (Metronome::manager().phase()/q) * (2.f * M_PI);
|
||||
draw_list->AddLine(ImVec2(circle_center.x + cos(a), circle_center.y + sin(a)),
|
||||
ImVec2(circle_center.x + circle_radius * cos(a), circle_center.y + circle_radius * sin(a)),
|
||||
ImGui::GetColorU32(ImGuiCol_PlotHistogram), 2.f);
|
||||
|
||||
// display text indication in the center
|
||||
// display text indication 'x / N' on mouse over in a central circle
|
||||
draw_list->AddCircleFilled(circle_center, circle_radius * 0.25f, ImGui::GetColorU32(ImGuiCol_Button, 10.f), PLOT_CIRCLE_SEGMENTS);
|
||||
ImGuiToolkit::PushFont(ImGuiToolkit::FONT_MONO);
|
||||
ImVec2 label_size = ImGui::CalcTextSize(text_buf, NULL);
|
||||
ImGui::SetCursorScreenPos(circle_center - label_size/2);
|
||||
ImGui::Text("%s", text_buf);
|
||||
ImGui::PopFont();
|
||||
|
||||
ImGui::PopStyleColor(3);
|
||||
}
|
||||
|
||||
// Draw child Window (right) to list reactions to input
|
||||
|
||||
@@ -1594,8 +1594,9 @@ void SourceControlWindow::RenderSelectedSources()
|
||||
{
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0.f, 2.f * v_space_));
|
||||
|
||||
// area horizontal pack
|
||||
int numcolumns = CLAMP( int(ceil(1.0f * rendersize.x / rendersize.y)), 1, numsources );
|
||||
// area horizontal
|
||||
rendersize.y -= buttons_height_ + 2.f * v_space_;
|
||||
int numcolumns = CLAMP( int(ceil(rendersize.x / rendersize.y)), 1, numsources );
|
||||
ImGui::Columns( numcolumns, "##selectiongrid", false);
|
||||
float widthcolumn = rendersize.x / static_cast<float>(numcolumns);
|
||||
widthcolumn -= scrollbar_;
|
||||
|
||||
@@ -901,7 +901,7 @@ void UserInterface::NewFrame()
|
||||
}
|
||||
}
|
||||
|
||||
// overlay to ensure file color dialog is closed after use
|
||||
// overlay to ensure color dialog is closed after use
|
||||
if (DialogToolkit::ColorPickerDialog::instance().busy()){
|
||||
if (!ImGui::IsPopupOpen("##ColorBusy"))
|
||||
ImGui::OpenPopup("##ColorBusy");
|
||||
|
||||
Reference in New Issue
Block a user