Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion UI/window-basic-transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ OBSBasicTransform::OBSBasicTransform(OBSBasic *parent)
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->align, COMBO_CHANGED, SLOT(OnAlignmentChanged()));
HookWidget(ui->boundsType, COMBO_CHANGED, SLOT(OnBoundsType(int)));
HookWidget(ui->boundsAlign, COMBO_CHANGED, SLOT(OnControlChanged()));
HookWidget(ui->boundsWidth, DSCROLL_CHANGED, SLOT(OnControlChanged()));
Expand Down Expand Up @@ -251,6 +251,7 @@ void OBSBasicTransform::RefreshControls()
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);
Expand All @@ -267,6 +268,9 @@ void OBSBasicTransform::RefreshControls()
ui->cropRight->setValue(int(crop.right));
ui->cropTop->setValue(int(crop.top));
ui->cropBottom->setValue(int(crop.bottom));

oti_save = osi;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use a more informative variable name here and use camelCase instead (we tend to prefer camelCase for C++ and ObjC and snake_case for pure C).


ignoreItemChange = false;

std::string name = obs_source_get_name(source);
Expand Down Expand Up @@ -324,9 +328,30 @@ void OBSBasicTransform::OnControlChanged()

ignoreTransformSignal = true;
obs_sceneitem_set_info(item, &oti);
oti_save = oti;
ignoreTransformSignal = false;
}

void OBSBasicTransform::OnAlignmentChanged()
{
if (ignoreItemChange)
return;

uint32_t newAlignment = listToAlign[ui->align->currentIndex()];
struct vec2 offset;

obs_sceneitem_alignment_get_vecdiff(item, &offset, oti_save.alignment,
newAlignment);

ignoreItemChange = true;

ui->positionX->setValue(oti_save.pos.x + offset.x);
ui->positionY->setValue(oti_save.pos.y + offset.y);

ignoreItemChange = false;
OnControlChanged();
}

void OBSBasicTransform::OnCropChanged()
{
if (ignoreItemChange)
Expand Down
2 changes: 2 additions & 0 deletions UI/window-basic-transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class OBSBasicTransform : public QDialog {
OBSSignal deselectSignal;

std::string undo_data;
obs_transform_info oti_save;

bool ignoreTransformSignal = false;
bool ignoreItemChange = false;
Expand All @@ -44,6 +45,7 @@ private slots:
void SetItemQt(OBSSceneItem newItem);
void OnBoundsType(int index);
void OnControlChanged();
void OnAlignmentChanged();
void OnCropChanged();
void on_resetButton_clicked();

Expand Down
7 changes: 7 additions & 0 deletions docs/sphinx/reference-scenes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -458,6 +458,13 @@ Scene Item Functions

---------------------

.. function:: void obs_sceneitem_alignment_get_vecdiff(const obs_sceneitem_t *item, struct vec2 *offset, uint32_t align_from, uint32_t align_to)

Gets the positional difference when switching between different alignment
settings for the scene item.

---------------------

.. function:: void obs_sceneitem_get_draw_transform(const obs_sceneitem_t *item, struct matrix4 *transform)

Gets the transform matrix of the scene item used for drawing the
Expand Down
57 changes: 51 additions & 6 deletions libobs/obs-scene.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "graphics/math-defs.h"
#include "obs-scene.h"
#include "obs-internal.h"
#include <math.h>

const struct obs_source_info group_info;

Expand Down Expand Up @@ -358,7 +359,7 @@ void add_alignment(struct vec2 *v, uint32_t align, int cx, int cy)
v->y += (float)(cy / 2);
}

static void calculate_bounds_data(struct obs_scene_item *item,
static void calculate_bounds_data(const struct obs_scene_item *item,
struct vec2 *origin, struct vec2 *scale,
uint32_t *cx, uint32_t *cy)
{
Expand Down Expand Up @@ -431,8 +432,6 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)
struct vec2 base_origin;
struct vec2 origin;
struct vec2 scale;
struct calldata params;
uint8_t stack[128];

if (os_atomic_load_long(&item->defer_update) > 0)
return;
Expand Down Expand Up @@ -499,9 +498,13 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)

/* ----------------------- */

calldata_init_fixed(&params, stack, sizeof(stack));
calldata_set_ptr(&params, "item", item);
signal_parent(item->parent, "item_transform", &params);
if (item->parent) {
struct calldata params;
uint8_t stack[128];
calldata_init_fixed(&params, stack, sizeof(stack));
calldata_set_ptr(&params, "item", item);
signal_parent(item->parent, "item_transform", &params);
}

if (!update_tex)
return;
Expand Down Expand Up @@ -2733,6 +2736,48 @@ void obs_sceneitem_set_info(obs_sceneitem_t *item,
}
}

void obs_sceneitem_alignment_get_vecdiff(const obs_sceneitem_t *item,
struct vec2 *offset,
uint32_t align_from, uint32_t align_to)
{
if (!item || !offset)
return;

// Mathematical background based on update_item_transform:
// matrix4 children seen as rows (implied in matrix multiply function):
// T_i = Eye(4) * M_Scale * M_Align_i^(-1) * M_Rot * M_Pos_i
// Original alignment transformation:
// T_1 (stored in mat_T1)
// = Eye(4) * M_Scale * M_Align_1^(-1) * M_Rot * M_Pos_1
// New alignment transformation without position adaptation:
// T_2* (stored in mat_T2_star)
// = Eye(4) * M_Scale * M_Align_2^(-1) * M_Rot * M_Pos_1
// New whole transformation should be equal to previous
// T_2 = T_2* * M_pos_12 =? T_1
// ->
// M_pos_12 = (T_2*)^(-1) * T_1

struct matrix4 mat_T1, mat_T2_star, mat_t12;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not use comma-based declaration, you can also write out matrix in the variable names (using matrix_T1 itself is ok because it follows the formulas in the comment above).

I also think it should be ok to disable clang-format for that comment block to make the formulas more readable.


obs_sceneitem_t temp_item = *item;

// prevent signals to be sent to the scene
temp_item.parent = NULL;

temp_item.align = align_from;
update_item_transform(&temp_item, false);
obs_sceneitem_get_draw_transform(&temp_item, &mat_T1);

temp_item.align = align_to;
update_item_transform(&temp_item, false);
obs_sceneitem_get_draw_transform(&temp_item, &mat_T2_star);
matrix4_inv(&mat_T2_star, &mat_T2_star);

matrix4_mul(&mat_t12, &mat_T2_star, &mat_T1);

vec2_set(offset, mat_t12.t.x, mat_t12.t.y);
}

void obs_sceneitem_get_draw_transform(const obs_sceneitem_t *item,
struct matrix4 *transform)
{
Expand Down
5 changes: 4 additions & 1 deletion libobs/obs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1819,7 +1819,10 @@ EXPORT void obs_sceneitem_get_info(const obs_sceneitem_t *item,
struct obs_transform_info *info);
EXPORT void obs_sceneitem_set_info(obs_sceneitem_t *item,
const struct obs_transform_info *info);

EXPORT void obs_sceneitem_alignment_get_vecdiff(const obs_sceneitem_t *item,
struct vec2 *offset,
uint32_t align_from,
uint32_t align_to);
EXPORT void obs_sceneitem_get_draw_transform(const obs_sceneitem_t *item,
struct matrix4 *transform);
EXPORT void obs_sceneitem_get_box_transform(const obs_sceneitem_t *item,
Expand Down