yolobs-studio/UI/window-basic-transform.cpp

312 lines
8.9 KiB
C++
Raw Permalink Normal View History

2016-10-10 19:01:40 +00:00
#include <QMessageBox>
2016-02-23 23:16:51 +00:00
#include "window-basic-transform.hpp"
#include "window-basic-main.hpp"
Q_DECLARE_METATYPE(OBSSceneItem);
2018-12-16 16:14:58 +00:00
static bool find_sel(obs_scene_t *, obs_sceneitem_t *item, void *param)
2016-02-23 23:16:51 +00:00
{
2019-09-22 21:19:10 +00:00
OBSSceneItem &dst = *reinterpret_cast<OBSSceneItem *>(param);
2018-12-16 16:14:58 +00:00
if (obs_sceneitem_selected(item)) {
dst = item;
return false;
}
if (obs_sceneitem_is_group(item)) {
obs_sceneitem_group_enum_items(item, find_sel, param);
if (!!dst) {
2016-02-23 23:16:51 +00:00
return false;
}
2018-12-16 16:14:58 +00:00
}
2016-02-23 23:16:51 +00:00
2018-12-16 16:14:58 +00:00
return true;
};
2016-02-23 23:16:51 +00:00
2018-12-16 16:14:58 +00:00
static OBSSceneItem FindASelectedItem(OBSScene scene)
{
2016-02-23 23:16:51 +00:00
OBSSceneItem item;
2018-12-16 16:14:58 +00:00
obs_scene_enum_items(scene, find_sel, &item);
2016-02-23 23:16:51 +00:00
return item;
}
void OBSBasicTransform::HookWidget(QWidget *widget, const char *signal,
2019-09-22 21:19:10 +00:00
const char *slot)
2016-02-23 23:16:51 +00:00
{
QObject::connect(widget, signal, this, slot);
}
2019-09-22 21:19:10 +00:00
#define COMBO_CHANGED SIGNAL(currentIndexChanged(int))
2016-05-24 19:53:01 +00:00
#define ISCROLL_CHANGED SIGNAL(valueChanged(int))
2016-02-23 23:16:51 +00:00
#define DSCROLL_CHANGED SIGNAL(valueChanged(double))
OBSBasicTransform::OBSBasicTransform(OBSBasic *parent)
2019-09-22 21:19:10 +00:00
: QDialog(parent), ui(new Ui::OBSBasicTransform), main(parent)
2016-02-23 23:16:51 +00:00
{
2019-07-27 12:47:10 +00:00
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
2020-03-25 08:07:22 +00:00
ui->setupUi(this);
2019-09-22 21:19:10 +00:00
HookWidget(ui->positionX, DSCROLL_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->positionY, DSCROLL_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->rotation, DSCROLL_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->sizeX, DSCROLL_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->sizeY, DSCROLL_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->align, COMBO_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->boundsType, COMBO_CHANGED, SLOT(OnBoundsType(int)));
HookWidget(ui->boundsAlign, COMBO_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->boundsWidth, DSCROLL_CHANGED, SLOT(OnControlChanged()));
2016-02-23 23:16:51 +00:00
HookWidget(ui->boundsHeight, DSCROLL_CHANGED, SLOT(OnControlChanged()));
2019-09-22 21:19:10 +00:00
HookWidget(ui->cropLeft, ISCROLL_CHANGED, SLOT(OnCropChanged()));
HookWidget(ui->cropRight, ISCROLL_CHANGED, SLOT(OnCropChanged()));
HookWidget(ui->cropTop, ISCROLL_CHANGED, SLOT(OnCropChanged()));
HookWidget(ui->cropBottom, ISCROLL_CHANGED, SLOT(OnCropChanged()));
2016-02-23 23:16:51 +00:00
2017-04-19 19:54:15 +00:00
ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
2016-10-10 19:01:40 +00:00
connect(ui->buttonBox->button(QDialogButtonBox::Reset),
SIGNAL(clicked()), this, SLOT(on_resetButton_clicked()));
2016-02-23 23:16:51 +00:00
installEventFilter(CreateShortcutFilter());
2018-12-16 16:14:58 +00:00
OBSSceneItem item = FindASelectedItem(main->GetCurrentScene());
OBSScene scene = obs_sceneitem_get_scene(item);
SetScene(scene);
SetItem(item);
2016-02-23 23:16:51 +00:00
channelChangedSignal.Connect(obs_get_signal_handler(), "channel_change",
2019-09-22 21:19:10 +00:00
OBSChannelChanged, this);
2016-02-23 23:16:51 +00:00
}
void OBSBasicTransform::SetScene(OBSScene scene)
{
transformSignal.Disconnect();
selectSignal.Disconnect();
deselectSignal.Disconnect();
removeSignal.Disconnect();
if (scene) {
OBSSource source = obs_scene_get_source(scene);
2019-09-22 21:19:10 +00:00
signal_handler_t *signal =
obs_source_get_signal_handler(source);
2016-02-23 23:16:51 +00:00
transformSignal.Connect(signal, "item_transform",
2019-09-22 21:19:10 +00:00
OBSSceneItemTransform, this);
removeSignal.Connect(signal, "item_remove", OBSSceneItemRemoved,
this);
selectSignal.Connect(signal, "item_select", OBSSceneItemSelect,
this);
2016-02-23 23:16:51 +00:00
deselectSignal.Connect(signal, "item_deselect",
2019-09-22 21:19:10 +00:00
OBSSceneItemDeselect, this);
2016-02-23 23:16:51 +00:00
}
}
void OBSBasicTransform::SetItem(OBSSceneItem newItem)
{
QMetaObject::invokeMethod(this, "SetItemQt",
2019-09-22 21:19:10 +00:00
Q_ARG(OBSSceneItem, OBSSceneItem(newItem)));
2016-02-23 23:16:51 +00:00
}
void OBSBasicTransform::SetItemQt(OBSSceneItem newItem)
{
item = newItem;
if (item)
RefreshControls();
setEnabled(!!item);
}
void OBSBasicTransform::OBSChannelChanged(void *param, calldata_t *data)
{
2019-09-22 21:19:10 +00:00
OBSBasicTransform *window =
reinterpret_cast<OBSBasicTransform *>(param);
2016-02-23 23:16:51 +00:00
uint32_t channel = (uint32_t)calldata_int(data, "channel");
2019-09-22 21:19:10 +00:00
OBSSource source = (obs_source_t *)calldata_ptr(data, "source");
2016-02-23 23:16:51 +00:00
if (channel == 0) {
OBSScene scene = obs_scene_from_source(source);
window->SetScene(scene);
if (!scene)
window->SetItem(nullptr);
else
window->SetItem(FindASelectedItem(scene));
}
}
void OBSBasicTransform::OBSSceneItemTransform(void *param, calldata_t *data)
{
2019-09-22 21:19:10 +00:00
OBSBasicTransform *window =
reinterpret_cast<OBSBasicTransform *>(param);
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
2016-02-23 23:16:51 +00:00
if (item == window->item && !window->ignoreTransformSignal)
QMetaObject::invokeMethod(window, "RefreshControls");
}
void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t *data)
{
2019-09-22 21:19:10 +00:00
OBSBasicTransform *window =
reinterpret_cast<OBSBasicTransform *>(param);
OBSScene scene = (obs_scene_t *)calldata_ptr(data, "scene");
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
2016-02-23 23:16:51 +00:00
if (item == window->item)
window->SetItem(FindASelectedItem(scene));
}
void OBSBasicTransform::OBSSceneItemSelect(void *param, calldata_t *data)
{
2019-09-22 21:19:10 +00:00
OBSBasicTransform *window =
reinterpret_cast<OBSBasicTransform *>(param);
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
2016-02-23 23:16:51 +00:00
if (item != window->item)
window->SetItem(item);
}
void OBSBasicTransform::OBSSceneItemDeselect(void *param, calldata_t *data)
{
2019-09-22 21:19:10 +00:00
OBSBasicTransform *window =
reinterpret_cast<OBSBasicTransform *>(param);
OBSScene scene = (obs_scene_t *)calldata_ptr(data, "scene");
OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
2016-02-23 23:16:51 +00:00
if (item == window->item)
window->SetItem(FindASelectedItem(scene));
}
2019-09-22 21:19:10 +00:00
static const uint32_t listToAlign[] = {OBS_ALIGN_TOP | OBS_ALIGN_LEFT,
OBS_ALIGN_TOP,
OBS_ALIGN_TOP | OBS_ALIGN_RIGHT,
OBS_ALIGN_LEFT,
OBS_ALIGN_CENTER,
OBS_ALIGN_RIGHT,
OBS_ALIGN_BOTTOM | OBS_ALIGN_LEFT,
OBS_ALIGN_BOTTOM,
OBS_ALIGN_BOTTOM | OBS_ALIGN_RIGHT};
2016-02-23 23:16:51 +00:00
static int AlignToList(uint32_t align)
{
int index = 0;
for (uint32_t curAlign : listToAlign) {
if (curAlign == align)
return index;
index++;
}
return 0;
}
void OBSBasicTransform::RefreshControls()
{
if (!item)
return;
obs_transform_info osi;
2016-05-24 19:53:01 +00:00
obs_sceneitem_crop crop;
2016-02-23 23:16:51 +00:00
obs_sceneitem_get_info(item, &osi);
2016-05-24 19:53:01 +00:00
obs_sceneitem_get_crop(item, &crop);
2016-02-23 23:16:51 +00:00
obs_source_t *source = obs_sceneitem_get_source(item);
2019-09-22 21:19:10 +00:00
float width = float(obs_source_get_width(source));
2016-02-23 23:16:51 +00:00
float height = float(obs_source_get_height(source));
2019-09-22 21:19:10 +00:00
int alignIndex = AlignToList(osi.alignment);
2016-02-23 23:16:51 +00:00
int boundsAlignIndex = AlignToList(osi.bounds_alignment);
ignoreItemChange = true;
ui->positionX->setValue(osi.pos.x);
ui->positionY->setValue(osi.pos.y);
ui->rotation->setValue(osi.rot);
ui->sizeX->setValue(osi.scale.x * width);
ui->sizeY->setValue(osi.scale.y * height);
ui->align->setCurrentIndex(alignIndex);
ui->boundsType->setCurrentIndex(int(osi.bounds_type));
ui->boundsAlign->setCurrentIndex(boundsAlignIndex);
ui->boundsWidth->setValue(osi.bounds.x);
ui->boundsHeight->setValue(osi.bounds.y);
2016-05-24 19:53:01 +00:00
ui->cropLeft->setValue(int(crop.left));
ui->cropRight->setValue(int(crop.right));
ui->cropTop->setValue(int(crop.top));
ui->cropBottom->setValue(int(crop.bottom));
2016-02-23 23:16:51 +00:00
ignoreItemChange = false;
}
void OBSBasicTransform::OnBoundsType(int index)
{
if (index == -1)
return;
2019-09-22 21:19:10 +00:00
obs_bounds_type type = (obs_bounds_type)index;
bool enable = (type != OBS_BOUNDS_NONE);
2016-02-23 23:16:51 +00:00
ui->boundsAlign->setEnabled(enable);
ui->boundsWidth->setEnabled(enable);
ui->boundsHeight->setEnabled(enable);
if (!ignoreItemChange) {
obs_bounds_type lastType = obs_sceneitem_get_bounds_type(item);
if (lastType == OBS_BOUNDS_NONE) {
OBSSource source = obs_sceneitem_get_source(item);
2019-09-22 21:19:10 +00:00
int width = (int)obs_source_get_width(source);
2016-02-23 23:16:51 +00:00
int height = (int)obs_source_get_height(source);
ui->boundsWidth->setValue(width);
ui->boundsHeight->setValue(height);
}
}
OnControlChanged();
}
void OBSBasicTransform::OnControlChanged()
{
if (ignoreItemChange)
return;
obs_source_t *source = obs_sceneitem_get_source(item);
2019-09-22 21:19:10 +00:00
double width = double(obs_source_get_width(source));
2016-02-23 23:16:51 +00:00
double height = double(obs_source_get_height(source));
obs_transform_info oti;
2019-09-22 21:19:10 +00:00
oti.pos.x = float(ui->positionX->value());
oti.pos.y = float(ui->positionY->value());
oti.rot = float(ui->rotation->value());
oti.scale.x = float(ui->sizeX->value() / width);
oti.scale.y = float(ui->sizeY->value() / height);
oti.alignment = listToAlign[ui->align->currentIndex()];
oti.bounds_type = (obs_bounds_type)ui->boundsType->currentIndex();
2016-02-23 23:16:51 +00:00
oti.bounds_alignment = listToAlign[ui->boundsAlign->currentIndex()];
2019-09-22 21:19:10 +00:00
oti.bounds.x = float(ui->boundsWidth->value());
oti.bounds.y = float(ui->boundsHeight->value());
2016-02-23 23:16:51 +00:00
ignoreTransformSignal = true;
obs_sceneitem_set_info(item, &oti);
ignoreTransformSignal = false;
}
2016-05-24 19:53:01 +00:00
void OBSBasicTransform::OnCropChanged()
{
if (ignoreItemChange)
return;
obs_sceneitem_crop crop;
2019-09-22 21:19:10 +00:00
crop.left = uint32_t(ui->cropLeft->value());
crop.right = uint32_t(ui->cropRight->value());
crop.top = uint32_t(ui->cropTop->value());
2016-05-24 19:53:01 +00:00
crop.bottom = uint32_t(ui->cropBottom->value());
ignoreTransformSignal = true;
obs_sceneitem_set_crop(item, &crop);
ignoreTransformSignal = false;
}
2016-10-10 19:01:40 +00:00
void OBSBasicTransform::on_resetButton_clicked()
{
main->on_actionResetTransform_triggered();
}