|
25 | 25 | #include "settings.hpp" |
26 | 26 | #include "ptz.h" |
27 | 27 |
|
| 28 | +QStringList ptz_joy_action_names = { |
| 29 | + "None", |
| 30 | + "Pan", |
| 31 | + "Tilt", |
| 32 | + "Zoom", |
| 33 | + "Previous Camera", |
| 34 | + "Next Camera", |
| 35 | + "Previous Preset", |
| 36 | + "Next Preset", |
| 37 | + "Recall Preset" |
| 38 | +}; |
| 39 | + |
28 | 40 | void ptz_load_controls(void) |
29 | 41 | { |
30 | 42 | const auto main_window = static_cast<QMainWindow *>(obs_frontend_get_main_window()); |
@@ -324,10 +336,11 @@ void PTZControls::joystickAxesChanged(const QJoystickDevice *jd, uint32_t update |
324 | 336 | { |
325 | 337 | if (isLocked() || !m_joystick_enable || !jd || jd->id != m_joystick_id) |
326 | 338 | return; |
327 | | - if (updated & 0b0011) |
328 | | - setPanTilt(readAxis(jd, 0), -readAxis(jd, 1)); |
329 | | - if (updated & 0b1000) |
330 | | - setZoom(-readAxis(jd, 3)); |
| 339 | + int panTiltMask = (1 << joystick_pan_axis) | (1 << joystick_tilt_axis); |
| 340 | + if (updated & panTiltMask) |
| 341 | + setPanTilt(readAxis(jd, joystick_pan_axis), -readAxis(jd, joystick_tilt_axis)); |
| 342 | + if (updated & (1 << joystick_zoom_axis)) |
| 343 | + setZoom(-readAxis(jd, joystick_zoom_axis)); |
331 | 344 | } |
332 | 345 |
|
333 | 346 | void PTZControls::joystickAxisEvent(const QJoystickAxisEvent evt) |
@@ -356,22 +369,68 @@ void PTZControls::joystickButtonEvent(const QJoystickButtonEvent evt) |
356 | 369 | return; |
357 | 370 | if (!evt.pressed) |
358 | 371 | return; |
359 | | - switch (evt.button) { |
360 | | - case 0: /* A button; activate preset */ |
| 372 | + switch (joystick_button_actions[evt.button]) { |
| 373 | + case PTZ_JOY_ACTION_CAMERA_PREV: |
| 374 | + ui->cameraList->cursorUp(); |
| 375 | + break; |
| 376 | + case PTZ_JOY_ACTION_CAMERA_NEXT: |
| 377 | + ui->cameraList->cursorDown(); |
| 378 | + break; |
| 379 | + case PTZ_JOY_ACTION_PRESET_PREV: |
| 380 | + ui->presetListView->cursorUp(); |
| 381 | + break; |
| 382 | + case PTZ_JOY_ACTION_PRESET_NEXT: |
| 383 | + ui->presetListView->cursorDown(); |
| 384 | + break; |
| 385 | + case PTZ_JOY_ACTION_PRESET_RECALL: |
361 | 386 | index = ui->presetListView->currentIndex(); |
362 | 387 | if (index.isValid() && !isLocked()) |
363 | 388 | ui->presetListView->activated(index); |
364 | 389 | break; |
365 | | - case 4: /* left shoulder; previous camera */ |
366 | | - ui->cameraList->cursorUp(); |
367 | | - break; |
368 | | - case 5: /* right shoulder; next camera */ |
369 | | - ui->cameraList->cursorDown(); |
| 390 | + default: |
370 | 391 | break; |
371 | 392 | } |
372 | 393 | } |
373 | 394 | #endif /* ENABLE_JOYSTICK */ |
374 | 395 |
|
| 396 | +void PTZControls::setJoystickAxisAction(size_t axis, ptz_joy_action_id action) |
| 397 | +{ |
| 398 | + if (joystick_axis_actions[axis] == action) |
| 399 | + return; |
| 400 | + joystick_axis_actions[axis] = action; |
| 401 | + |
| 402 | + // Clear if this is an axis already used |
| 403 | + if (joystick_pan_axis == (int)axis) |
| 404 | + joystick_pan_axis = -1; |
| 405 | + if (joystick_tilt_axis == (int)axis) |
| 406 | + joystick_tilt_axis = -1; |
| 407 | + if (joystick_zoom_axis == (int)axis) |
| 408 | + joystick_zoom_axis = -1; |
| 409 | + |
| 410 | + int old_axis = -1; |
| 411 | + if (action == PTZ_JOY_ACTION_PAN && joystick_pan_axis != (int)axis) { |
| 412 | + old_axis = joystick_pan_axis; |
| 413 | + joystick_pan_axis = (int)axis; |
| 414 | + } else if (action == PTZ_JOY_ACTION_TILT && joystick_tilt_axis != (int)axis) { |
| 415 | + old_axis = joystick_tilt_axis; |
| 416 | + joystick_tilt_axis = (int)axis; |
| 417 | + } else if (action == PTZ_JOY_ACTION_ZOOM && joystick_zoom_axis != (int)axis) { |
| 418 | + old_axis = joystick_zoom_axis; |
| 419 | + joystick_zoom_axis = (int)axis; |
| 420 | + } |
| 421 | + if (old_axis != -1) |
| 422 | + emit joystickAxisActionChanged(old_axis, PTZ_JOY_ACTION_NONE); |
| 423 | + emit joystickAxisActionChanged(axis, action); |
| 424 | +} |
| 425 | + |
| 426 | +void PTZControls::setJoystickButtonAction(size_t button, ptz_joy_action_id action) |
| 427 | +{ |
| 428 | + if (joystick_button_actions[button] == action) |
| 429 | + return; |
| 430 | + joystick_button_actions[button] = action; |
| 431 | + emit joystickButtonActionChanged(button, action); |
| 432 | +} |
| 433 | + |
375 | 434 | void PTZControls::copyActionsDynamicProperties() |
376 | 435 | { |
377 | 436 | // Themes need the QAction dynamic properties |
@@ -405,6 +464,29 @@ void PTZControls::SaveConfig() |
405 | 464 | obs_data_set_int(savedata, "joystick_id", m_joystick_id); |
406 | 465 | obs_data_set_double(savedata, "joystick_speed", m_joystick_speed); |
407 | 466 | obs_data_set_double(savedata, "joystick_deadzone", m_joystick_deadzone); |
| 467 | + |
| 468 | + OBSDataArrayAutoRelease axis_actions = obs_data_array_create(); |
| 469 | + for (auto axis : joystick_axis_actions.keys()) { |
| 470 | + if (joystick_axis_actions[axis] == PTZ_JOY_ACTION_NONE) |
| 471 | + continue; |
| 472 | + OBSDataAutoRelease d = obs_data_create(); |
| 473 | + obs_data_set_int(d, "axis", axis); |
| 474 | + obs_data_set_int(d, "action", joystick_axis_actions[axis]); |
| 475 | + obs_data_array_push_back(axis_actions, d); |
| 476 | + } |
| 477 | + obs_data_set_array(savedata, "joystick_axis_actions", axis_actions); |
| 478 | + |
| 479 | + OBSDataArrayAutoRelease button_actions = obs_data_array_create(); |
| 480 | + for (auto button : joystick_button_actions.keys()) { |
| 481 | + if (joystick_button_actions[button] == PTZ_JOY_ACTION_NONE) |
| 482 | + continue; |
| 483 | + OBSDataAutoRelease d = obs_data_create(); |
| 484 | + obs_data_set_int(d, "button", button); |
| 485 | + obs_data_set_int(d, "action", joystick_button_actions[button]); |
| 486 | + obs_data_array_push_back(button_actions, d); |
| 487 | + } |
| 488 | + obs_data_set_array(savedata, "joystick_button_actions", button_actions); |
| 489 | + |
408 | 490 | if (auto ptz = currCamera()) |
409 | 491 | obs_data_set_int(savedata, "current_selected", ptz->getId()); |
410 | 492 |
|
@@ -460,6 +542,22 @@ void PTZControls::LoadConfig() |
460 | 542 | m_joystick_speed = obs_data_get_double(loaddata, "joystick_speed"); |
461 | 543 | m_joystick_deadzone = obs_data_get_double(loaddata, "joystick_deadzone"); |
462 | 544 |
|
| 545 | + OBSDataArrayAutoRelease axis_actions = obs_data_get_array(loaddata, "joystick_axis_actions"); |
| 546 | + for (size_t i = 0; i < obs_data_array_count(axis_actions); i++) { |
| 547 | + OBSDataAutoRelease d = obs_data_array_item(axis_actions, i); |
| 548 | + auto axis = obs_data_get_int(d, "axis"); |
| 549 | + auto action = obs_data_get_int(d, "action"); |
| 550 | + setJoystickAxisAction(axis, action); |
| 551 | + } |
| 552 | + |
| 553 | + OBSDataArrayAutoRelease button_actions = obs_data_get_array(loaddata, "joystick_button_actions"); |
| 554 | + for (size_t i = 0; i < obs_data_array_count(button_actions); i++) { |
| 555 | + OBSDataAutoRelease d = obs_data_array_item(button_actions, i); |
| 556 | + auto button = obs_data_get_int(d, "button"); |
| 557 | + auto action = obs_data_get_int(d, "action"); |
| 558 | + setJoystickButtonAction(button, action); |
| 559 | + } |
| 560 | + |
463 | 561 | const char *splitterStateStr = obs_data_get_string(loaddata, "splitter_state"); |
464 | 562 | if (splitterStateStr) { |
465 | 563 | QByteArray splitterState = QByteArray::fromBase64(QByteArray(splitterStateStr)); |
|
0 commit comments