window-basic-transform.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. #include "window-basic-transform.hpp"
  2. #include "window-basic-main.hpp"
  3. Q_DECLARE_METATYPE(OBSSceneItem);
  4. static OBSSceneItem FindASelectedItem(OBSScene scene)
  5. {
  6. auto func = [] (obs_scene_t scene, obs_sceneitem_t item, void *param)
  7. {
  8. OBSSceneItem &dst = *reinterpret_cast<OBSSceneItem*>(param);
  9. if (obs_sceneitem_selected(item)) {
  10. dst = item;
  11. return false;
  12. }
  13. return true;
  14. };
  15. OBSSceneItem item;
  16. obs_scene_enum_items(scene, func, &item);
  17. return item;
  18. }
  19. void OBSBasicTransform::HookWidget(QWidget *widget, const char *signal,
  20. const char *slot)
  21. {
  22. QObject::connect(widget, signal, this, slot);
  23. }
  24. #define COMBO_CHANGED SIGNAL(currentIndexChanged(int))
  25. #define DSCROLL_CHANGED SIGNAL(valueChanged(double))
  26. OBSBasicTransform::OBSBasicTransform(OBSBasic *parent)
  27. : QDialog (parent),
  28. ui (new Ui::OBSBasicTransform),
  29. main (parent)
  30. {
  31. setAttribute(Qt::WA_DeleteOnClose);
  32. ui->setupUi(this);
  33. HookWidget(ui->positionX, DSCROLL_CHANGED, SLOT(OnControlChanged()));
  34. HookWidget(ui->positionY, DSCROLL_CHANGED, SLOT(OnControlChanged()));
  35. HookWidget(ui->rotation, DSCROLL_CHANGED, SLOT(OnControlChanged()));
  36. HookWidget(ui->scaleX, DSCROLL_CHANGED, SLOT(OnControlChanged()));
  37. HookWidget(ui->scaleY, DSCROLL_CHANGED, SLOT(OnControlChanged()));
  38. HookWidget(ui->align, COMBO_CHANGED, SLOT(OnControlChanged()));
  39. HookWidget(ui->boundsType, COMBO_CHANGED, SLOT(OnBoundsType(int)));
  40. HookWidget(ui->boundsAlign, COMBO_CHANGED, SLOT(OnControlChanged()));
  41. HookWidget(ui->boundsWidth, DSCROLL_CHANGED, SLOT(OnControlChanged()));
  42. HookWidget(ui->boundsHeight, DSCROLL_CHANGED, SLOT(OnControlChanged()));
  43. OBSScene curScene = main->GetCurrentScene();
  44. SetScene(curScene);
  45. SetItem(FindASelectedItem(curScene));
  46. channelChangedSignal.Connect(obs_signalhandler(), "channel_change",
  47. OBSChannelChanged, this);
  48. }
  49. void OBSBasicTransform::SetScene(OBSScene scene)
  50. {
  51. transformSignal.Disconnect();
  52. selectSignal.Disconnect();
  53. deselectSignal.Disconnect();
  54. removeSignal.Disconnect();
  55. if (scene) {
  56. OBSSource source = obs_scene_getsource(scene);
  57. signal_handler_t signal = obs_source_signalhandler(source);
  58. transformSignal.Connect(signal, "item_transform",
  59. OBSSceneItemTransform, this);
  60. removeSignal.Connect(signal, "item_remove",
  61. OBSSceneItemRemoved, this);
  62. selectSignal.Connect(signal, "item_select",
  63. OBSSceneItemSelect, this);
  64. deselectSignal.Connect(signal, "item_deselect",
  65. OBSSceneItemDeselect, this);
  66. }
  67. }
  68. void OBSBasicTransform::SetItem(OBSSceneItem newItem)
  69. {
  70. QMetaObject::invokeMethod(this, "SetItemQt",
  71. Q_ARG(OBSSceneItem, OBSSceneItem(newItem)));
  72. }
  73. void OBSBasicTransform::SetItemQt(OBSSceneItem newItem)
  74. {
  75. item = newItem;
  76. if (item)
  77. RefreshControls();
  78. setEnabled(!!item);
  79. }
  80. void OBSBasicTransform::OBSChannelChanged(void *param, calldata_t data)
  81. {
  82. OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
  83. uint32_t channel = (uint32_t)calldata_int(data, "channel");
  84. OBSSource source = (obs_source_t)calldata_ptr(data, "source");
  85. if (channel == 0) {
  86. OBSScene scene = obs_scene_fromsource(source);
  87. window->SetScene(scene);
  88. if (!scene)
  89. window->SetItem(nullptr);
  90. else
  91. window->SetItem(FindASelectedItem(scene));
  92. }
  93. }
  94. void OBSBasicTransform::OBSSceneItemTransform(void *param, calldata_t data)
  95. {
  96. OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
  97. OBSSceneItem item = (obs_sceneitem_t)calldata_ptr(data, "item");
  98. if (item == window->item && !window->ignoreTransformSignal)
  99. QMetaObject::invokeMethod(window, "RefreshControls");
  100. }
  101. void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t data)
  102. {
  103. OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
  104. OBSScene scene = (obs_scene_t)calldata_ptr(data, "scene");
  105. OBSSceneItem item = (obs_sceneitem_t)calldata_ptr(data, "item");
  106. if (item == window->item)
  107. window->SetItem(FindASelectedItem(scene));
  108. }
  109. void OBSBasicTransform::OBSSceneItemSelect(void *param, calldata_t data)
  110. {
  111. OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
  112. OBSSceneItem item = (obs_sceneitem_t)calldata_ptr(data, "item");
  113. if (item != window->item)
  114. window->SetItem(item);
  115. }
  116. void OBSBasicTransform::OBSSceneItemDeselect(void *param, calldata_t data)
  117. {
  118. OBSBasicTransform *window = reinterpret_cast<OBSBasicTransform*>(param);
  119. OBSScene scene = (obs_scene_t)calldata_ptr(data, "scene");
  120. OBSSceneItem item = (obs_sceneitem_t)calldata_ptr(data, "item");
  121. if (item == window->item)
  122. window->SetItem(FindASelectedItem(scene));
  123. }
  124. static const uint32_t listToAlign[] = {
  125. OBS_ALIGN_TOP | OBS_ALIGN_LEFT,
  126. OBS_ALIGN_TOP,
  127. OBS_ALIGN_TOP | OBS_ALIGN_RIGHT,
  128. OBS_ALIGN_LEFT,
  129. OBS_ALIGN_CENTER,
  130. OBS_ALIGN_RIGHT,
  131. OBS_ALIGN_BOTTOM | OBS_ALIGN_LEFT,
  132. OBS_ALIGN_BOTTOM,
  133. OBS_ALIGN_BOTTOM | OBS_ALIGN_RIGHT
  134. };
  135. static int AlignToList(uint32_t align)
  136. {
  137. int index = 0;
  138. for (uint32_t curAlign : listToAlign) {
  139. if (curAlign == align)
  140. return index;
  141. index++;
  142. }
  143. return 0;
  144. }
  145. void OBSBasicTransform::RefreshControls()
  146. {
  147. if (!item)
  148. return;
  149. obs_sceneitem_info osi;
  150. obs_sceneitem_get_info(item, &osi);
  151. int alignIndex = AlignToList(osi.alignment);
  152. int boundsAlignIndex = AlignToList(osi.bounds_alignment);
  153. ignoreItemChange = true;
  154. ui->positionX->setValue(osi.pos.x);
  155. ui->positionY->setValue(osi.pos.y);
  156. ui->rotation->setValue(osi.rot);
  157. ui->scaleX->setValue(osi.scale.x);
  158. ui->scaleY->setValue(osi.scale.y);
  159. ui->align->setCurrentIndex(alignIndex);
  160. ui->boundsType->setCurrentIndex(int(osi.bounds_type));
  161. ui->boundsAlign->setCurrentIndex(boundsAlignIndex);
  162. ui->boundsWidth->setValue(osi.bounds.x);
  163. ui->boundsHeight->setValue(osi.bounds.y);
  164. ignoreItemChange = false;
  165. }
  166. void OBSBasicTransform::OnBoundsType(int index)
  167. {
  168. if (index == -1)
  169. return;
  170. obs_bounds_type type = (obs_bounds_type)index;
  171. bool enable = (type != OBS_BOUNDS_NONE);
  172. ui->boundsAlign->setEnabled(enable);
  173. ui->boundsWidth->setEnabled(enable);
  174. ui->boundsHeight->setEnabled(enable);
  175. if (!ignoreItemChange) {
  176. obs_bounds_type lastType = obs_sceneitem_get_bounds_type(item);
  177. if (lastType == OBS_BOUNDS_NONE) {
  178. OBSSource source = obs_sceneitem_getsource(item);
  179. int width = (int)obs_source_getwidth(source);
  180. int height = (int)obs_source_getheight(source);
  181. ui->boundsWidth->setValue(width);
  182. ui->boundsHeight->setValue(height);
  183. }
  184. }
  185. OnControlChanged();
  186. }
  187. void OBSBasicTransform::OnControlChanged()
  188. {
  189. if (ignoreItemChange)
  190. return;
  191. obs_sceneitem_info osi;
  192. osi.pos.x = float(ui->positionX->value());
  193. osi.pos.y = float(ui->positionY->value());
  194. osi.rot = float(ui->rotation->value());
  195. osi.scale.x = float(ui->scaleX->value());
  196. osi.scale.y = float(ui->scaleY->value());
  197. osi.alignment = listToAlign[ui->align->currentIndex()];
  198. osi.bounds_type = (obs_bounds_type)ui->boundsType->currentIndex();
  199. osi.bounds_alignment = listToAlign[ui->boundsAlign->currentIndex()];
  200. osi.bounds.x = float(ui->boundsWidth->value());
  201. osi.bounds.y = float(ui->boundsHeight->value());
  202. ignoreTransformSignal = true;
  203. obs_sceneitem_set_info(item, &osi);
  204. ignoreTransformSignal = false;
  205. }