Kaynağa Gözat

frontend: Update transform dialog

Warchamp7 8 ay önce
ebeveyn
işleme
6fa1a35ad4

+ 20 - 13
frontend/data/locale/en-US.ini

@@ -63,6 +63,8 @@ Left="Left"
 Right="Right"
 Top="Top"
 Bottom="Bottom"
+Width="Width"
+Height="Height"
 Reset="Reset"
 Hours="Hours"
 Minutes="Minutes"
@@ -699,24 +701,26 @@ Basic.Filters.AddFilter.Text="Please specify the name of the filter"
 # transform window
 Basic.TransformWindow="Scene Item Transform"
 Basic.TransformWindow.Position="Position"
-Basic.TransformWindow.PositionX="Position X"
-Basic.TransformWindow.PositionY="Position Y"
+Basic.TransformWindow.PositionX="X"
+Basic.TransformWindow.PositionY="Y"
 Basic.TransformWindow.Rotation="Rotation"
 Basic.TransformWindow.Size="Size"
 Basic.TransformWindow.Width="Width"
 Basic.TransformWindow.Height="Height"
-Basic.TransformWindow.Alignment="Positional Alignment"
-Basic.TransformWindow.BoundsType="Bounding Box Type"
-Basic.TransformWindow.BoundsAlignment="Alignment in Bounding Box"
-Basic.TransformWindow.Bounds="Bounding Box Size"
+Basic.TransformWindow.Alignment="Alignment"
+Basic.TransformWindow.BoundsType="Bounds Type"
+Basic.TransformWindow.BoundsAlignment="Bounds Alignment"
+Basic.TransformWindow.Bounds="Bounds"
 Basic.TransformWindow.BoundsWidth="Bounding Box Width"
 Basic.TransformWindow.BoundsHeight="Bounding Box Height"
-Basic.TransformWindow.CropToBounds="Crop to Bounding Box"
+Basic.TransformWindow.CropToBounds="Crop Bounds"
 Basic.TransformWindow.Crop="Crop"
 Basic.TransformWindow.CropLeft="Crop Left"
 Basic.TransformWindow.CropRight="Crop Right"
 Basic.TransformWindow.CropTop="Crop Top"
 Basic.TransformWindow.CropBottom="Crop Bottom"
+Basic.TransformWindow.Accessible.PositionX="X Position"
+Basic.TransformWindow.Accessible.PositionY="Y Position"
 
 Basic.TransformWindow.Alignment.TopLeft="Top Left"
 Basic.TransformWindow.Alignment.TopCenter="Top Center"
@@ -728,13 +732,13 @@ Basic.TransformWindow.Alignment.BottomLeft="Bottom Left"
 Basic.TransformWindow.Alignment.BottomCenter="Bottom Center"
 Basic.TransformWindow.Alignment.BottomRight="Bottom Right"
 
-Basic.TransformWindow.BoundsType.None="No bounds"
+Basic.TransformWindow.BoundsType.None="Automatic"
 Basic.TransformWindow.BoundsType.MaxOnly="Maximum size only"
-Basic.TransformWindow.BoundsType.ScaleInner="Scale to inner bounds"
-Basic.TransformWindow.BoundsType.ScaleOuter="Scale to outer bounds"
-Basic.TransformWindow.BoundsType.ScaleToWidth="Scale to width of bounds"
-Basic.TransformWindow.BoundsType.ScaleToHeight="Scale to height of bounds"
-Basic.TransformWindow.BoundsType.Stretch="Stretch to bounds"
+Basic.TransformWindow.BoundsType.ScaleInner="Fit"
+Basic.TransformWindow.BoundsType.ScaleOuter="Cover"
+Basic.TransformWindow.BoundsType.ScaleToWidth="Fill Width"
+Basic.TransformWindow.BoundsType.ScaleToHeight="Fill Height"
+Basic.TransformWindow.BoundsType.Stretch="Stretch"
 
 Basic.TransformWindow.Title="Edit Transform for '%1'"
 Basic.TransformWindow.NoSelectedSource="No source selected"
@@ -1635,3 +1639,6 @@ PluginManager.Section.Discover="Browse"
 PluginManager.Section.Manage="Installed"
 PluginManager.Section.Updates="Updates"
 PluginManager.Section.Manage.Title="Manage Enabled Plugins"
+
+# Custom Widget Localization
+Accessible.Widget.Name.AlignmentSelector="Alignment Selector"

+ 6 - 0
frontend/data/themes/Yami.obt

@@ -335,6 +335,12 @@
     margin: var(--spacing_base) 0;
 }
 
+.subtitle {
+    font-size: var(--font_small);
+    font-weight: bold;
+    color: var(--text_muted);
+}
+
 .button-primary {
     background-color: var(--primary_dark);
     border-color: var(--primary);

+ 194 - 71
frontend/dialogs/OBSBasicTransform.cpp

@@ -4,6 +4,7 @@
 
 #include "moc_OBSBasicTransform.cpp"
 
+namespace {
 static bool find_sel(obs_scene_t *, obs_sceneitem_t *item, void *param)
 {
 	OBSSceneItem &dst = *static_cast<OBSSceneItem *>(param);
@@ -28,8 +29,28 @@ static OBSSceneItem FindASelectedItem(obs_scene_t *scene)
 	obs_scene_enum_items(scene, find_sel, &item);
 	return item;
 }
+static vec2 getAlignmentConversion(uint32_t alignment)
+{
+	vec2 ratio = {0.5f, 0.5f};
+	if (alignment & OBS_ALIGN_RIGHT) {
+		ratio.x = 1.0f;
+	}
+	if (alignment & OBS_ALIGN_LEFT) {
+		ratio.x = 0.0f;
+	}
+	if (alignment & OBS_ALIGN_BOTTOM) {
+		ratio.y = 1.0f;
+	}
+	if (alignment & OBS_ALIGN_TOP) {
+		ratio.y = 0.0f;
+	}
+
+	return ratio;
+}
+} // namespace
 
 #define COMBO_CHANGED &QComboBox::currentIndexChanged
+#define ALIGN_CHANGED &AlignmentSelector::currentIndexChanged
 #define ISCROLL_CHANGED &QSpinBox::valueChanged
 #define DSCROLL_CHANGED &QDoubleSpinBox::valueChanged
 
@@ -42,24 +63,38 @@ OBSBasicTransform::OBSBasicTransform(OBSSceneItem item, OBSBasic *parent)
 
 	ui->setupUi(this);
 
-	HookWidget(ui->positionX, DSCROLL_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->positionY, DSCROLL_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->rotation, DSCROLL_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->sizeX, DSCROLL_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->sizeY, DSCROLL_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->align, COMBO_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->boundsType, COMBO_CHANGED, &OBSBasicTransform::OnBoundsType);
-	HookWidget(ui->boundsAlign, COMBO_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->boundsWidth, DSCROLL_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->boundsHeight, DSCROLL_CHANGED, &OBSBasicTransform::OnControlChanged);
-	HookWidget(ui->cropLeft, ISCROLL_CHANGED, &OBSBasicTransform::OnCropChanged);
-	HookWidget(ui->cropRight, ISCROLL_CHANGED, &OBSBasicTransform::OnCropChanged);
-	HookWidget(ui->cropTop, ISCROLL_CHANGED, &OBSBasicTransform::OnCropChanged);
-	HookWidget(ui->cropBottom, ISCROLL_CHANGED, &OBSBasicTransform::OnCropChanged);
+	positionAlignment = new AlignmentSelector(this);
+	positionAlignment->setAccessibleName(QTStr("Basic.TransformWindow.Alignment"));
+	ui->alignmentLayout->addWidget(positionAlignment);
+	positionAlignment->setAlignment(Qt::AlignTop | Qt::AlignLeft);
+
+	boundsAlignment = new AlignmentSelector(this);
+	boundsAlignment->setAccessibleName(QTStr("Basic.TransformWindow.BoundsAlignment"));
+	boundsAlignment->setEnabled(false);
+	ui->boundsAlignmentLayout->addWidget(boundsAlignment);
+	boundsAlignment->setAlignment(Qt::AlignTop | Qt::AlignLeft);
+
+	setTabOrder(ui->rotation, positionAlignment);
+	setTabOrder(ui->boundsType, boundsAlignment);
+
+	hookWidget(ui->positionX, DSCROLL_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(ui->positionY, DSCROLL_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(ui->rotation, DSCROLL_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(ui->sizeX, DSCROLL_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(ui->sizeY, DSCROLL_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(positionAlignment.get(), ALIGN_CHANGED, &OBSBasicTransform::onAlignChanged);
+	hookWidget(ui->boundsType, COMBO_CHANGED, &OBSBasicTransform::onBoundsType);
+	hookWidget(boundsAlignment.get(), ALIGN_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(ui->boundsWidth, DSCROLL_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(ui->boundsHeight, DSCROLL_CHANGED, &OBSBasicTransform::onControlChanged);
+	hookWidget(ui->cropLeft, ISCROLL_CHANGED, &OBSBasicTransform::onCropChanged);
+	hookWidget(ui->cropRight, ISCROLL_CHANGED, &OBSBasicTransform::onCropChanged);
+	hookWidget(ui->cropTop, ISCROLL_CHANGED, &OBSBasicTransform::onCropChanged);
+	hookWidget(ui->cropBottom, ISCROLL_CHANGED, &OBSBasicTransform::onCropChanged);
 #if QT_VERSION >= QT_VERSION_CHECK(6, 7, 0)
-	HookWidget(ui->cropToBounds, &QCheckBox::checkStateChanged, &OBSBasicTransform::OnControlChanged);
+	hookWidget(ui->cropToBounds, &QCheckBox::checkStateChanged, &OBSBasicTransform::onControlChanged);
 #else
-	HookWidget(ui->cropToBounds, &QCheckBox::stateChanged, &OBSBasicTransform::OnControlChanged);
+	hookWidget(ui->cropToBounds, &QCheckBox::stateChanged, &OBSBasicTransform::onControlChanged);
 #endif
 	ui->buttonBox->button(QDialogButtonBox::Close)->setDefault(true);
 
@@ -69,14 +104,18 @@ OBSBasicTransform::OBSBasicTransform(OBSSceneItem item, OBSBasic *parent)
 	installEventFilter(CreateShortcutFilter());
 
 	OBSScene scene = obs_sceneitem_get_scene(item);
-	SetScene(scene);
-	SetItem(item);
+	setScene(scene);
+	setItem(item);
 
 	std::string name = obs_source_get_name(obs_sceneitem_get_source(item));
 	setWindowTitle(QTStr("Basic.TransformWindow.Title").arg(name.c_str()));
 
 	OBSDataAutoRelease wrapper = obs_scene_save_transform_states(main->GetCurrentScene(), false);
 	undo_data = std::string(obs_data_get_json(wrapper));
+
+	adjustSize();
+	setMinimumSize(size());
+	setMaximumSize(size());
 }
 
 OBSBasicTransform::~OBSBasicTransform()
@@ -97,7 +136,7 @@ OBSBasicTransform::~OBSBasicTransform()
 			undo_redo, undo_redo, undo_data, redo_data);
 }
 
-void OBSBasicTransform::SetScene(OBSScene scene)
+void OBSBasicTransform::setScene(OBSScene scene)
 {
 	sigs.clear();
 
@@ -113,25 +152,27 @@ void OBSBasicTransform::SetScene(OBSScene scene)
 	}
 }
 
-void OBSBasicTransform::SetItem(OBSSceneItem newItem)
+void OBSBasicTransform::setItem(OBSSceneItem newItem)
 {
-	QMetaObject::invokeMethod(this, "SetItemQt", Q_ARG(OBSSceneItem, OBSSceneItem(newItem)));
+	QMetaObject::invokeMethod(this, "setItemQt", Q_ARG(OBSSceneItem, OBSSceneItem(newItem)));
 }
 
-void OBSBasicTransform::SetEnabled(bool enable)
+void OBSBasicTransform::setEnabled(bool enable)
 {
-	ui->container->setEnabled(enable);
+	ui->transformSettings->setEnabled(enable);
+	ui->boundsSettings->setEnabled(enable);
+	ui->cropSettings->setEnabled(enable);
 	ui->buttonBox->button(QDialogButtonBox::Reset)->setEnabled(enable);
 }
 
-void OBSBasicTransform::SetItemQt(OBSSceneItem newItem)
+void OBSBasicTransform::setItemQt(OBSSceneItem newItem)
 {
 	item = newItem;
 	if (item)
-		RefreshControls();
+		refreshControls();
 
 	bool enable = !!item && !obs_sceneitem_locked(item);
-	SetEnabled(enable);
+	setEnabled(enable);
 }
 
 void OBSBasicTransform::OBSSceneItemTransform(void *param, calldata_t *data)
@@ -140,7 +181,7 @@ void OBSBasicTransform::OBSSceneItemTransform(void *param, calldata_t *data)
 	OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
 
 	if (item == window->item && !window->ignoreTransformSignal)
-		QMetaObject::invokeMethod(window, "RefreshControls");
+		QMetaObject::invokeMethod(window, "refreshControls");
 }
 
 void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t *data)
@@ -150,7 +191,7 @@ void OBSBasicTransform::OBSSceneItemRemoved(void *param, calldata_t *data)
 	obs_sceneitem_t *item = (obs_sceneitem_t *)calldata_ptr(data, "item");
 
 	if (item == window->item)
-		window->SetItem(FindASelectedItem(scene));
+		window->setItem(FindASelectedItem(scene));
 }
 
 void OBSBasicTransform::OBSSceneItemSelect(void *param, calldata_t *data)
@@ -159,7 +200,7 @@ void OBSBasicTransform::OBSSceneItemSelect(void *param, calldata_t *data)
 	OBSSceneItem item = (obs_sceneitem_t *)calldata_ptr(data, "item");
 
 	if (item != window->item)
-		window->SetItem(item);
+		window->setItem(item);
 }
 
 void OBSBasicTransform::OBSSceneItemDeselect(void *param, calldata_t *data)
@@ -170,7 +211,7 @@ void OBSBasicTransform::OBSSceneItemDeselect(void *param, calldata_t *data)
 
 	if (item == window->item) {
 		window->setWindowTitle(QTStr("Basic.TransformWindow.NoSelectedSource"));
-		window->SetItem(FindASelectedItem(scene));
+		window->setItem(FindASelectedItem(scene));
 	}
 }
 
@@ -179,23 +220,23 @@ void OBSBasicTransform::OBSSceneItemLocked(void *param, calldata_t *data)
 	OBSBasicTransform *window = static_cast<OBSBasicTransform *>(param);
 	bool locked = calldata_bool(data, "locked");
 
-	QMetaObject::invokeMethod(window, "SetEnabled", Q_ARG(bool, !locked));
+	QMetaObject::invokeMethod(window, "setEnabled", Q_ARG(bool, !locked));
 }
 
-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};
-
-static int AlignToList(uint32_t align)
+static const uint32_t indexToAlign[] = {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};
+
+static int alignToIndex(uint32_t align)
 {
 	int index = 0;
-	for (uint32_t curAlign : listToAlign) {
+	for (uint32_t curAlign : indexToAlign) {
 		if (curAlign == align)
 			return index;
 
@@ -205,14 +246,14 @@ static int AlignToList(uint32_t align)
 	return 0;
 }
 
-void OBSBasicTransform::RefreshControls()
+void OBSBasicTransform::refreshControls()
 {
 	if (!item)
 		return;
 
-	obs_transform_info osi;
+	obs_transform_info oti;
 	obs_sceneitem_crop crop;
-	obs_sceneitem_get_info2(item, &osi);
+	obs_sceneitem_get_info2(item, &oti);
 	obs_sceneitem_get_crop(item, &crop);
 
 	obs_source_t *source = obs_sceneitem_get_source(item);
@@ -221,26 +262,26 @@ void OBSBasicTransform::RefreshControls()
 	float width = float(source_cx);
 	float height = float(source_cy);
 
-	int alignIndex = AlignToList(osi.alignment);
-	int boundsAlignIndex = AlignToList(osi.bounds_alignment);
+	int alignIndex = alignToIndex(oti.alignment);
+	int boundsAlignIndex = alignToIndex(oti.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->positionX->setValue(oti.pos.x);
+	ui->positionY->setValue(oti.pos.y);
+	ui->rotation->setValue(oti.rot);
+	ui->sizeX->setValue(oti.scale.x * width);
+	ui->sizeY->setValue(oti.scale.y * height);
+	positionAlignment->setCurrentIndex(alignIndex);
 
 	bool valid_size = source_cx != 0 && source_cy != 0;
 	ui->sizeX->setEnabled(valid_size);
 	ui->sizeY->setEnabled(valid_size);
 
-	ui->boundsType->setCurrentIndex(int(osi.bounds_type));
-	ui->boundsAlign->setCurrentIndex(boundsAlignIndex);
-	ui->boundsWidth->setValue(osi.bounds.x);
-	ui->boundsHeight->setValue(osi.bounds.y);
-	ui->cropToBounds->setChecked(osi.crop_to_bounds);
+	ui->boundsType->setCurrentIndex(int(oti.bounds_type));
+	boundsAlignment->setCurrentIndex(boundsAlignIndex);
+	ui->boundsWidth->setValue(oti.bounds.x);
+	ui->boundsHeight->setValue(oti.bounds.y);
+	ui->cropToBounds->setChecked(oti.crop_to_bounds);
 
 	ui->cropLeft->setValue(int(crop.left));
 	ui->cropRight->setValue(int(crop.right));
@@ -252,7 +293,45 @@ void OBSBasicTransform::RefreshControls()
 	setWindowTitle(QTStr("Basic.TransformWindow.Title").arg(name.c_str()));
 }
 
-void OBSBasicTransform::OnBoundsType(int index)
+void OBSBasicTransform::onAlignChanged(int index)
+{
+	uint32_t alignment = indexToAlign[index];
+
+	vec2 flipRatio = getAlignmentConversion(alignment);
+
+	obs_transform_info oti;
+	obs_sceneitem_crop crop;
+	obs_sceneitem_get_info2(item, &oti);
+	obs_sceneitem_get_crop(item, &crop);
+
+	obs_source_t *source = obs_sceneitem_get_source(item);
+	uint32_t sourceWidth = obs_source_get_width(source);
+	uint32_t sourceHeight = obs_source_get_height(source);
+
+	uint32_t widthForFlip = sourceWidth - crop.left - crop.right;
+	uint32_t heightForFlip = sourceHeight - crop.top - crop.bottom;
+
+	if (oti.bounds_type != OBS_BOUNDS_NONE) {
+		widthForFlip = oti.bounds.x;
+		heightForFlip = oti.bounds.y;
+	}
+
+	vec2 currentRatio = getAlignmentConversion(oti.alignment);
+
+	float shiftX = (currentRatio.x - flipRatio.x) * widthForFlip * oti.scale.x;
+	float shiftY = (currentRatio.y - flipRatio.y) * heightForFlip * oti.scale.y;
+
+	bool previousIgnoreState = ignoreItemChange;
+
+	ignoreItemChange = true;
+	ui->positionX->setValue(oti.pos.x - shiftX);
+	ui->positionY->setValue(oti.pos.y - shiftY);
+	ignoreItemChange = previousIgnoreState;
+
+	onControlChanged();
+}
+
+void OBSBasicTransform::onBoundsType(int index)
 {
 	if (index == -1)
 		return;
@@ -260,10 +339,13 @@ void OBSBasicTransform::OnBoundsType(int index)
 	obs_bounds_type type = (obs_bounds_type)index;
 	bool enable = (type != OBS_BOUNDS_NONE);
 
-	ui->boundsAlign->setEnabled(enable);
+	boundsAlignment->setEnabled(enable && type != OBS_BOUNDS_STRETCH);
 	ui->boundsWidth->setEnabled(enable);
 	ui->boundsHeight->setEnabled(enable);
-	ui->cropToBounds->setEnabled(enable);
+
+	bool isCoverBounds = type == OBS_BOUNDS_SCALE_OUTER || type == OBS_BOUNDS_SCALE_TO_WIDTH ||
+			     type == OBS_BOUNDS_SCALE_TO_HEIGHT;
+	ui->cropToBounds->setEnabled(isCoverBounds);
 
 	if (!ignoreItemChange) {
 		obs_bounds_type lastType = obs_sceneitem_get_bounds_type(item);
@@ -272,15 +354,56 @@ void OBSBasicTransform::OnBoundsType(int index)
 			int width = (int)obs_source_get_width(source);
 			int height = (int)obs_source_get_height(source);
 
-			ui->boundsWidth->setValue(width);
-			ui->boundsHeight->setValue(height);
+			vec2 scale;
+			obs_sceneitem_get_scale(item, &scale);
+
+			obs_sceneitem_crop crop;
+			obs_sceneitem_get_crop(item, &crop);
+
+			ui->sizeX->setValue(width);
+			ui->sizeY->setValue(height);
+
+			ui->boundsWidth->setValue((width - crop.left - crop.right) * scale.x);
+			ui->boundsHeight->setValue((height - crop.top - crop.bottom) * scale.y);
+		} else if (type == OBS_BOUNDS_NONE) {
+			OBSSource source = obs_sceneitem_get_source(item);
+			int width = (int)obs_source_get_width(source);
+			int height = (int)obs_source_get_height(source);
+
+			matrix4 draw;
+			obs_sceneitem_get_draw_transform(item, &draw);
+
+			ui->sizeX->setValue(width * draw.x.x);
+			ui->sizeY->setValue(height * draw.y.y);
+
+			obs_transform_info oti;
+			obs_sceneitem_get_info2(item, &oti);
+
+			// We use the draw transform values here which is always a top left coordinate origin.
+			vec2 currentRatio = getAlignmentConversion(OBS_ALIGN_TOP | OBS_ALIGN_LEFT);
+			vec2 flipRatio = getAlignmentConversion(oti.alignment);
+
+			float drawX = draw.t.x;
+			float drawY = draw.t.y;
+
+			obs_sceneitem_crop crop;
+			obs_sceneitem_get_crop(item, &crop);
+
+			uint32_t widthForFlip = width - crop.left - crop.right;
+			uint32_t heightForFlip = height - crop.top - crop.bottom;
+
+			float shiftX = (currentRatio.x - flipRatio.x) * (widthForFlip * draw.x.x);
+			float shiftY = (currentRatio.y - flipRatio.y) * (heightForFlip * draw.y.y);
+
+			ui->positionX->setValue(oti.pos.x - (oti.pos.x - drawX) - shiftX);
+			ui->positionY->setValue(oti.pos.y - (oti.pos.y - drawY) - shiftY);
 		}
 	}
 
-	OnControlChanged();
+	onControlChanged();
 }
 
-void OBSBasicTransform::OnControlChanged()
+void OBSBasicTransform::onControlChanged()
 {
 	if (ignoreItemChange)
 		return;
@@ -303,10 +426,10 @@ void OBSBasicTransform::OnControlChanged()
 	oti.pos.x = float(ui->positionX->value());
 	oti.pos.y = float(ui->positionY->value());
 	oti.rot = float(ui->rotation->value());
-	oti.alignment = listToAlign[ui->align->currentIndex()];
+	oti.alignment = indexToAlign[positionAlignment->currentIndex()];
 
 	oti.bounds_type = (obs_bounds_type)ui->boundsType->currentIndex();
-	oti.bounds_alignment = listToAlign[ui->boundsAlign->currentIndex()];
+	oti.bounds_alignment = indexToAlign[boundsAlignment->currentIndex()];
 	oti.bounds.x = float(ui->boundsWidth->value());
 	oti.bounds.y = float(ui->boundsHeight->value());
 	oti.crop_to_bounds = ui->cropToBounds->isChecked();
@@ -316,7 +439,7 @@ void OBSBasicTransform::OnControlChanged()
 	ignoreTransformSignal = false;
 }
 
-void OBSBasicTransform::OnCropChanged()
+void OBSBasicTransform::onCropChanged()
 {
 	if (ignoreItemChange)
 		return;
@@ -332,11 +455,11 @@ void OBSBasicTransform::OnCropChanged()
 	ignoreTransformSignal = false;
 }
 
-void OBSBasicTransform::OnSceneChanged(QListWidgetItem *current, QListWidgetItem *)
+void OBSBasicTransform::onSceneChanged(QListWidgetItem *current, QListWidgetItem *)
 {
 	if (!current)
 		return;
 
 	OBSScene scene = GetOBSRef<OBSScene>(current);
-	this->SetScene(scene);
+	this->setScene(scene);
 }

+ 16 - 10
frontend/dialogs/OBSBasicTransform.hpp

@@ -3,8 +3,10 @@
 #include "ui_OBSBasicTransform.h"
 
 #include <obs.hpp>
+#include <components/AlignmentSelector.hpp>
 
 #include <QDialog>
+#include <QPointer>
 
 class OBSBasic;
 class QListWidgetItem;
@@ -15,6 +17,9 @@ class OBSBasicTransform : public QDialog {
 private:
 	std::unique_ptr<Ui::OBSBasicTransform> ui;
 
+	QPointer<AlignmentSelector> positionAlignment;
+	QPointer<AlignmentSelector> boundsAlignment;
+
 	OBSBasic *main;
 	OBSSceneItem item;
 	std::vector<OBSSignal> sigs;
@@ -25,14 +30,14 @@ private:
 	bool ignoreItemChange = false;
 
 	template<typename Widget, typename WidgetParent, typename... SignalArgs, typename... SlotArgs>
-	void HookWidget(Widget *widget, void (WidgetParent::*signal)(SignalArgs...),
+	void hookWidget(Widget *widget, void (WidgetParent::*signal)(SignalArgs...),
 			void (OBSBasicTransform::*slot)(SlotArgs...))
 	{
 		QObject::connect(widget, signal, this, slot);
 	}
 
-	void SetScene(OBSScene scene);
-	void SetItem(OBSSceneItem newItem);
+	void setScene(OBSScene scene);
+	void setItem(OBSSceneItem newItem);
 
 	static void OBSSceneItemTransform(void *param, calldata_t *data);
 	static void OBSSceneItemRemoved(void *param, calldata_t *data);
@@ -41,17 +46,18 @@ private:
 	static void OBSSceneItemLocked(void *param, calldata_t *data);
 
 private slots:
-	void RefreshControls();
-	void SetItemQt(OBSSceneItem newItem);
-	void OnBoundsType(int index);
-	void OnControlChanged();
-	void OnCropChanged();
-	void SetEnabled(bool enable);
+	void refreshControls();
+	void setItemQt(OBSSceneItem newItem);
+	void onAlignChanged(int index);
+	void onBoundsType(int index);
+	void onControlChanged();
+	void onCropChanged();
+	void setEnabled(bool enable);
 
 public:
 	OBSBasicTransform(OBSSceneItem item, OBSBasic *parent);
 	~OBSBasicTransform();
 
 public slots:
-	void OnSceneChanged(QListWidgetItem *current, QListWidgetItem *prev);
+	void onSceneChanged(QListWidgetItem *current, QListWidgetItem *prev);
 };

Dosya farkı çok büyük olduğundan ihmal edildi
+ 682 - 606
frontend/forms/OBSBasicTransform.ui


+ 1 - 1
frontend/widgets/OBSBasic_MainControls.cpp

@@ -489,7 +489,7 @@ void OBSBasic::CreateEditTransformWindow(obs_sceneitem_t *item)
 	if (transformWindow)
 		transformWindow->close();
 	transformWindow = new OBSBasicTransform(item, this);
-	connect(ui->scenes, &QListWidget::currentItemChanged, transformWindow, &OBSBasicTransform::OnSceneChanged);
+	connect(ui->scenes, &QListWidget::currentItemChanged, transformWindow, &OBSBasicTransform::onSceneChanged);
 	transformWindow->show();
 	transformWindow->setAttribute(Qt::WA_DeleteOnClose, true);
 }

Bu fark içinde çok fazla dosya değişikliği olduğu için bazı dosyalar gösterilmiyor