提交 7463c0db 编写于 作者: J Jeremiah Senkpiel 提交者: jp9000

UI: Add option to snap to edges of other sources

Allows the user to snap sources to the edges of other sources, on by
default.

Closes jp9000/obs-studio#530
上级 5911b265
......@@ -358,6 +358,7 @@ Basic.Settings.General.WarnBeforeStoppingStream="Show confirmation dialog when s
Basic.Settings.General.Snapping="Source Alignment Snapping"
Basic.Settings.General.ScreenSnapping="Snap Sources to edge of screen"
Basic.Settings.General.CenterSnapping="Snap Sources to horizontal and vertical center"
Basic.Settings.General.SourceSnapping="Snap Sources to other sources"
Basic.Settings.General.SnapDistance="Snap Sensitivity"
# basic mode 'stream' settings
......
......@@ -243,6 +243,16 @@
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QCheckBox" name="sourceSnapping">
<property name="text">
<string>Basic.Settings.General.SourceSnapping</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QDoubleSpinBox" name="snapDistance">
<property name="decimals">
......@@ -3626,6 +3636,22 @@
<x>476</x>
<y>202</y>
</hint>
<hint type="destinationlabel">
<x>466</x>
<y>253</y>
</hint>
</hints>
</connection>
<connection>
<sender>snappingEnabled</sender>
<signal>toggled(bool)</signal>
<receiver>sourceSnapping</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>518</x>
<y>204</y>
</hint>
<hint type="destinationlabel">
<x>515</x>
<y>277</y>
......
......@@ -343,6 +343,8 @@ bool OBSApp::InitGlobalConfigDefaults()
"SnappingEnabled", true);
config_set_default_bool(globalConfig, "BasicWindow",
"ScreenSnapping", true);
config_set_default_bool(globalConfig, "BasicWindow",
"SourceSnapping", true);
config_set_default_bool(globalConfig, "BasicWindow",
"CenterSnapping", false);
config_set_default_double(globalConfig, "BasicWindow",
......
......@@ -502,6 +502,66 @@ static bool AddItemBounds(obs_scene_t *scene, obs_sceneitem_t *item,
return true;
}
struct OffsetData {
float clampDist;
vec3 tl, br, offset;
};
static bool GetSourceSnapOffset(obs_scene_t *scene, obs_sceneitem_t *item,
void *param)
{
OffsetData *data = reinterpret_cast<OffsetData*>(param);
if (obs_sceneitem_selected(item))
return true;
matrix4 boxTransform;
obs_sceneitem_get_box_transform(item, &boxTransform);
vec3 t[4] = {
GetTransformedPos(0.0f, 0.0f, boxTransform),
GetTransformedPos(1.0f, 0.0f, boxTransform),
GetTransformedPos(0.0f, 1.0f, boxTransform),
GetTransformedPos(1.0f, 1.0f, boxTransform)
};
bool first = true;
vec3 tl, br;
vec3_zero(&tl);
vec3_zero(&br);
for (const vec3 &v : t) {
if (first) {
vec3_copy(&tl, &v);
vec3_copy(&br, &v);
first = false;
} else {
vec3_min(&tl, &tl, &v);
vec3_max(&br, &br, &v);
}
}
// Snap to other source edges
#define EDGE_SNAP(l, r, x, y) \
do { \
double dist = fabsf(l.x - data->r.x); \
if (dist < data->clampDist && \
fabsf(data->offset.x) < EPSILON && \
data->tl.y < br.y && \
data->br.y > tl.y && \
(fabsf(data->offset.x) > dist || data->offset.x < EPSILON)) \
data->offset.x = l.x - data->r.x; \
} while (false)
EDGE_SNAP(tl, br, x, y);
EDGE_SNAP(tl, br, y, x);
EDGE_SNAP(br, tl, x, y);
EDGE_SNAP(br, tl, y, x);
#undef EDGE_SNAP
UNUSED_PARAMETER(scene);
return true;
}
void OBSBasicPreview::SnapItemMovement(vec2 &offset)
{
OBSBasic *main = reinterpret_cast<OBSBasic*>(App()->GetMainWindow());
......@@ -519,11 +579,35 @@ void OBSBasicPreview::SnapItemMovement(vec2 &offset)
const bool snap = config_get_bool(GetGlobalConfig(),
"BasicWindow", "SnappingEnabled");
const bool sourcesSnap = config_get_bool(GetGlobalConfig(),
"BasicWindow", "SourceSnapping");
if (snap == false)
return;
if (sourcesSnap == false) {
offset.x += snapOffset.x;
offset.y += snapOffset.y;
return;
}
const float clampDist = config_get_double(GetGlobalConfig(),
"BasicWindow", "SnapDistance") / main->previewScale;
offset.x += snapOffset.x;
offset.y += snapOffset.y;
OffsetData offsetData;
offsetData.clampDist = clampDist;
offsetData.tl = data.tl;
offsetData.br = data.br;
vec3_copy(&offsetData.offset, &snapOffset);
obs_scene_enum_items(scene, GetSourceSnapOffset, &offsetData);
if (fabsf(offsetData.offset.x) > EPSILON ||
fabsf(offsetData.offset.y) > EPSILON) {
offset.x += offsetData.offset.x;
offset.y += offsetData.offset.y;
} else {
offset.x += snapOffset.x;
offset.y += snapOffset.y;
}
}
static bool move_items(obs_scene_t *scene, obs_sceneitem_t *item, void *param)
......
......@@ -269,6 +269,7 @@ OBSBasicSettings::OBSBasicSettings(QWidget *parent)
HookWidget(ui->snappingEnabled, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->screenSnapping, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->centerSnapping, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->sourceSnapping, CHECK_CHANGED, GENERAL_CHANGED);
HookWidget(ui->snapDistance, SCROLL_CHANGED, GENERAL_CHANGED);
HookWidget(ui->outputMode, COMBO_CHANGED, OUTPUTS_CHANGED);
HookWidget(ui->streamType, COMBO_CHANGED, STREAM1_CHANGED);
......@@ -779,6 +780,10 @@ void OBSBasicSettings::LoadGeneralSettings()
"BasicWindow", "CenterSnapping");
ui->centerSnapping->setChecked(centerSnapping);
bool sourceSnapping = config_get_bool(GetGlobalConfig(),
"BasicWindow", "SourceSnapping");
ui->sourceSnapping->setChecked(sourceSnapping);
double snapDistance = config_get_double(GetGlobalConfig(),
"BasicWindow", "SnapDistance");
ui->snapDistance->setValue(snapDistance);
......@@ -2071,6 +2076,10 @@ void OBSBasicSettings::SaveGeneralSettings()
config_set_bool(GetGlobalConfig(), "BasicWindow",
"CenterSnapping",
ui->centerSnapping->isChecked());
if (WidgetChanged(ui->sourceSnapping))
config_set_bool(GetGlobalConfig(), "BasicWindow",
"SourceSnapping",
ui->sourceSnapping->isChecked());
if (WidgetChanged(ui->snapDistance))
config_set_double(GetGlobalConfig(), "BasicWindow",
"SnapDistance",
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册