|
@@ -24,7 +24,7 @@
|
|
|
|
|
|
const struct obs_source_info group_info;
|
|
|
|
|
|
-static void resize_group(obs_sceneitem_t *group);
|
|
|
+static void resize_group(obs_sceneitem_t *group, bool scene_resize);
|
|
|
static void resize_scene(obs_scene_t *scene);
|
|
|
static void signal_parent(obs_scene_t *parent, const char *name,
|
|
|
calldata_t *params);
|
|
@@ -353,6 +353,109 @@ void add_alignment(struct vec2 *v, uint32_t align, int cx, int cy)
|
|
|
v->y += (float)(cy / 2);
|
|
|
}
|
|
|
|
|
|
+static uint32_t scene_getwidth(void *data);
|
|
|
+static uint32_t scene_getheight(void *data);
|
|
|
+
|
|
|
+static inline void get_scene_dimensions(const obs_sceneitem_t *item, float *x,
|
|
|
+ float *y)
|
|
|
+{
|
|
|
+ obs_scene_t *parent = item->parent;
|
|
|
+ if (!parent || parent->is_group) {
|
|
|
+ *x = (float)obs->video.main_mix->ovi.base_width;
|
|
|
+ *y = (float)obs->video.main_mix->ovi.base_height;
|
|
|
+ } else {
|
|
|
+ *x = (float)scene_getwidth(parent);
|
|
|
+ *y = (float)scene_getheight(parent);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+/* Rounds absolute pixel values to next .5. */
|
|
|
+static inline void nudge_abs_values(struct vec2 *dst, const struct vec2 *v)
|
|
|
+{
|
|
|
+ dst->x = floorf(v->x * 2.0f + 0.5f) / 2.0f;
|
|
|
+ dst->y = floorf(v->y * 2.0f + 0.5f) / 2.0f;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void pos_from_absolute(struct vec2 *dst, const struct vec2 *v,
|
|
|
+ const obs_sceneitem_t *item)
|
|
|
+{
|
|
|
+ float x, y;
|
|
|
+ get_scene_dimensions(item, &x, &y);
|
|
|
+ /* Scaled so that height (y) is [-1, 1]. */
|
|
|
+ dst->x = (2 * v->x - x) / y;
|
|
|
+ dst->y = 2 * v->y / y - 1.0f;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void pos_to_absolute(struct vec2 *dst, const struct vec2 *v,
|
|
|
+ const obs_sceneitem_t *item)
|
|
|
+{
|
|
|
+ float x, y;
|
|
|
+ get_scene_dimensions(item, &x, &y);
|
|
|
+ dst->x = (v->x * y + x) / 2;
|
|
|
+ dst->y = (v->y * y + y) / 2;
|
|
|
+
|
|
|
+ /* In order for group resizing to behave properly they need all the precision
|
|
|
+ * they can get, so do not nudge their values. */
|
|
|
+ if (!item->is_group && !(item->parent && item->parent->is_group))
|
|
|
+ nudge_abs_values(dst, dst);
|
|
|
+}
|
|
|
+
|
|
|
+static inline void size_from_absolute(struct vec2 *dst, const struct vec2 *v,
|
|
|
+ const obs_sceneitem_t *item)
|
|
|
+{
|
|
|
+ float x, y;
|
|
|
+ get_scene_dimensions(item, &x, &y);
|
|
|
+ /* The height of the canvas is from [-1, 1], so 2.0f * aspect is the
|
|
|
+ * full width (depending on aspect ratio). */
|
|
|
+ dst->x = (2 * v->x) / y;
|
|
|
+ dst->y = 2 * v->y / y;
|
|
|
+}
|
|
|
+
|
|
|
+static inline void size_to_absolute(struct vec2 *dst, const struct vec2 *v,
|
|
|
+ const obs_sceneitem_t *item)
|
|
|
+{
|
|
|
+ float x, y;
|
|
|
+ get_scene_dimensions(item, &x, &y);
|
|
|
+ dst->x = (v->x * y) / 2;
|
|
|
+ dst->y = (v->y * y) / 2;
|
|
|
+
|
|
|
+ if (!item->is_group && !(item->parent && item->parent->is_group))
|
|
|
+ nudge_abs_values(dst, dst);
|
|
|
+}
|
|
|
+
|
|
|
+/* Return item's scale value scaled from original to current canvas size. */
|
|
|
+static inline void item_canvas_scale(struct vec2 *dst,
|
|
|
+ const obs_sceneitem_t *item)
|
|
|
+{
|
|
|
+ /* Groups will themselves resize so their items do not need to be
|
|
|
+ * rescaled manually. Nested scenes will use the updated canvas
|
|
|
+ * resolution, so they also don't need manual adjustment. */
|
|
|
+ if (item->is_group || item->is_scene) {
|
|
|
+ vec2_copy(dst, &item->scale);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ float x, y;
|
|
|
+ get_scene_dimensions(item, &x, &y);
|
|
|
+ float scale_factor = y / item->scale_ref.y;
|
|
|
+ vec2_mulf(dst, &item->scale, scale_factor);
|
|
|
+}
|
|
|
+
|
|
|
+/* Return scale value scaled to original canvas size. */
|
|
|
+static inline void item_relative_scale(struct vec2 *dst, const struct vec2 *v,
|
|
|
+ const obs_sceneitem_t *item)
|
|
|
+{
|
|
|
+ if (item->is_group || item->is_scene) {
|
|
|
+ vec2_copy(dst, v);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ float x, y;
|
|
|
+ get_scene_dimensions(item, &x, &y);
|
|
|
+ float scale_factor = item->scale_ref.y / y;
|
|
|
+ vec2_mulf(dst, v, scale_factor);
|
|
|
+}
|
|
|
+
|
|
|
static inline bool crop_to_bounds(const struct obs_scene_item *item)
|
|
|
{
|
|
|
return item->crop_to_bounds &&
|
|
@@ -365,15 +468,17 @@ static void calculate_bounds_data(struct obs_scene_item *item,
|
|
|
struct vec2 *origin, struct vec2 *scale,
|
|
|
uint32_t *cx, uint32_t *cy)
|
|
|
{
|
|
|
+ struct vec2 bounds;
|
|
|
+ size_to_absolute(&bounds, &item->bounds, item);
|
|
|
float width = (float)(*cx) * fabsf(scale->x);
|
|
|
float height = (float)(*cy) * fabsf(scale->y);
|
|
|
float item_aspect = width / height;
|
|
|
- float bounds_aspect = item->bounds.x / item->bounds.y;
|
|
|
+ float bounds_aspect = bounds.x / bounds.y;
|
|
|
uint32_t bounds_type = item->bounds_type;
|
|
|
float width_diff, height_diff;
|
|
|
|
|
|
if (item->bounds_type == OBS_BOUNDS_MAX_ONLY)
|
|
|
- if (width > item->bounds.x || height > item->bounds.y)
|
|
|
+ if (width > bounds.x || height > bounds.y)
|
|
|
bounds_type = OBS_BOUNDS_SCALE_INNER;
|
|
|
|
|
|
if (bounds_type == OBS_BOUNDS_SCALE_INNER ||
|
|
@@ -384,30 +489,29 @@ static void calculate_bounds_data(struct obs_scene_item *item,
|
|
|
if (item->bounds_type == OBS_BOUNDS_SCALE_OUTER)
|
|
|
use_width = !use_width;
|
|
|
|
|
|
- mul = use_width ? item->bounds.x / width
|
|
|
- : item->bounds.y / height;
|
|
|
+ mul = use_width ? bounds.x / width : bounds.y / height;
|
|
|
|
|
|
vec2_mulf(scale, scale, mul);
|
|
|
|
|
|
} else if (bounds_type == OBS_BOUNDS_SCALE_TO_WIDTH) {
|
|
|
- vec2_mulf(scale, scale, item->bounds.x / width);
|
|
|
+ vec2_mulf(scale, scale, bounds.x / width);
|
|
|
|
|
|
} else if (bounds_type == OBS_BOUNDS_SCALE_TO_HEIGHT) {
|
|
|
- vec2_mulf(scale, scale, item->bounds.y / height);
|
|
|
+ vec2_mulf(scale, scale, bounds.y / height);
|
|
|
|
|
|
} else if (bounds_type == OBS_BOUNDS_STRETCH) {
|
|
|
- scale->x = copysignf(item->bounds.x / (float)(*cx), scale->x);
|
|
|
- scale->y = copysignf(item->bounds.y / (float)(*cy), scale->y);
|
|
|
+ scale->x = copysignf(bounds.x / (float)(*cx), scale->x);
|
|
|
+ scale->y = copysignf(bounds.y / (float)(*cy), scale->y);
|
|
|
}
|
|
|
|
|
|
width = (float)(*cx) * scale->x;
|
|
|
height = (float)(*cy) * scale->y;
|
|
|
|
|
|
/* Disregards flip when calculating size diff */
|
|
|
- width_diff = item->bounds.x - fabsf(width);
|
|
|
- height_diff = item->bounds.y - fabsf(height);
|
|
|
- *cx = (uint32_t)item->bounds.x;
|
|
|
- *cy = (uint32_t)item->bounds.y;
|
|
|
+ width_diff = bounds.x - fabsf(width);
|
|
|
+ height_diff = bounds.y - fabsf(height);
|
|
|
+ *cx = (uint32_t)bounds.x;
|
|
|
+ *cy = (uint32_t)bounds.y;
|
|
|
|
|
|
add_alignment(origin, item->bounds_align, (int)-width_diff,
|
|
|
(int)-height_diff);
|
|
@@ -490,6 +594,34 @@ static inline uint32_t calc_cy(const struct obs_scene_item *item,
|
|
|
return (crop_cy > height) ? 2 : (height - crop_cy);
|
|
|
}
|
|
|
|
|
|
+#ifdef _DEBUG
|
|
|
+static inline void log_matrix(const struct matrix4 *mat, const char *name)
|
|
|
+{
|
|
|
+ blog(LOG_DEBUG,
|
|
|
+ "Matrix \"%s\":\n"
|
|
|
+ "┏ %9.4f %9.4f %9.4f %9.4f ┓\n"
|
|
|
+ "┃ %9.4f %9.4f %9.4f %9.4f ┃\n"
|
|
|
+ "┃ %9.4f %9.4f %9.4f %9.4f ┃\n"
|
|
|
+ "┗ %9.4f %9.4f %9.4f %9.4f ┛",
|
|
|
+ name, mat->x.x, mat->x.y, mat->x.z, mat->x.w, mat->y.x, mat->y.y,
|
|
|
+ mat->y.z, mat->y.w, mat->z.x, mat->z.y, mat->z.z, mat->z.w,
|
|
|
+ mat->t.x, mat->t.y, mat->t.z, mat->t.w);
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static inline void update_nested_scene_crop(struct obs_scene_item *item,
|
|
|
+ uint32_t width, uint32_t height)
|
|
|
+{
|
|
|
+ /* Use last size and new size to calculate factor to adjust crop by. */
|
|
|
+ float scale_x = (float)width / (float)item->last_width;
|
|
|
+ float scale_y = (float)height / (float)item->last_height;
|
|
|
+
|
|
|
+ item->crop.left = (int)((float)item->crop.left * scale_x);
|
|
|
+ item->crop.right = (int)((float)item->crop.right * scale_x);
|
|
|
+ item->crop.top = (int)((float)item->crop.top * scale_y);
|
|
|
+ item->crop.bottom = (int)((float)item->crop.bottom * scale_y);
|
|
|
+}
|
|
|
+
|
|
|
static void update_item_transform(struct obs_scene_item *item, bool update_tex)
|
|
|
{
|
|
|
uint32_t width;
|
|
@@ -499,6 +631,7 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)
|
|
|
struct vec2 base_origin;
|
|
|
struct vec2 origin;
|
|
|
struct vec2 scale;
|
|
|
+ struct vec2 position;
|
|
|
struct calldata params;
|
|
|
uint8_t stack[128];
|
|
|
|
|
@@ -510,9 +643,13 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)
|
|
|
|
|
|
width = obs_source_get_width(item->source);
|
|
|
height = obs_source_get_height(item->source);
|
|
|
+
|
|
|
+ /* Adjust crop on nested scenes (if any) */
|
|
|
+ if (update_tex && item->is_scene)
|
|
|
+ update_nested_scene_crop(item, width, height);
|
|
|
+
|
|
|
cx = calc_cx(item, width);
|
|
|
cy = calc_cy(item, height);
|
|
|
- scale = item->scale;
|
|
|
item->last_width = width;
|
|
|
item->last_height = height;
|
|
|
|
|
@@ -522,6 +659,9 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)
|
|
|
vec2_zero(&base_origin);
|
|
|
vec2_zero(&origin);
|
|
|
|
|
|
+ item_canvas_scale(&scale, item);
|
|
|
+ pos_to_absolute(&position, &item->pos, item);
|
|
|
+
|
|
|
/* ----------------------- */
|
|
|
|
|
|
if (item->bounds_type != OBS_BOUNDS_NONE) {
|
|
@@ -541,17 +681,23 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)
|
|
|
matrix4_rotate_aa4f(&item->draw_transform, &item->draw_transform, 0.0f,
|
|
|
0.0f, 1.0f, RAD(item->rot));
|
|
|
matrix4_translate3f(&item->draw_transform, &item->draw_transform,
|
|
|
- item->pos.x, item->pos.y, 0.0f);
|
|
|
+ position.x, position.y, 0.0f);
|
|
|
+
|
|
|
+#ifdef _DEBUG
|
|
|
+ blog(LOG_DEBUG, "Transform updated for \"%s\":",
|
|
|
+ obs_source_get_name(item->source));
|
|
|
+ log_matrix(&item->draw_transform, "draw_transform");
|
|
|
+#endif
|
|
|
|
|
|
item->output_scale = scale;
|
|
|
|
|
|
/* ----------------------- */
|
|
|
|
|
|
if (item->bounds_type != OBS_BOUNDS_NONE) {
|
|
|
- vec2_copy(&scale, &item->bounds);
|
|
|
+ size_to_absolute(&scale, &item->bounds, item);
|
|
|
} else {
|
|
|
- scale.x = (float)width * item->scale.x;
|
|
|
- scale.y = (float)height * item->scale.y;
|
|
|
+ scale.x *= (float)width;
|
|
|
+ scale.y *= (float)height;
|
|
|
}
|
|
|
|
|
|
item->box_scale = scale;
|
|
@@ -566,7 +712,11 @@ static void update_item_transform(struct obs_scene_item *item, bool update_tex)
|
|
|
matrix4_rotate_aa4f(&item->box_transform, &item->box_transform, 0.0f,
|
|
|
0.0f, 1.0f, RAD(item->rot));
|
|
|
matrix4_translate3f(&item->box_transform, &item->box_transform,
|
|
|
- item->pos.x, item->pos.y, 0.0f);
|
|
|
+ position.x, position.y, 0.0f);
|
|
|
+
|
|
|
+#ifdef _DEBUG
|
|
|
+ log_matrix(&item->draw_transform, "box_transform");
|
|
|
+#endif
|
|
|
|
|
|
/* ----------------------- */
|
|
|
|
|
@@ -966,7 +1116,7 @@ static void update_transforms_and_prune_sources(
|
|
|
}
|
|
|
|
|
|
if (rebuild_group && group_sceneitem)
|
|
|
- resize_group(group_sceneitem);
|
|
|
+ resize_group(group_sceneitem, scene_size_changed);
|
|
|
}
|
|
|
|
|
|
static inline bool scene_size_changed(obs_scene_t *scene)
|
|
@@ -1106,8 +1256,18 @@ static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data)
|
|
|
item->align = (uint32_t)obs_data_get_int(item_data, "align");
|
|
|
visible = obs_data_get_bool(item_data, "visible");
|
|
|
lock = obs_data_get_bool(item_data, "locked");
|
|
|
- obs_data_get_vec2(item_data, "pos", &item->pos);
|
|
|
- obs_data_get_vec2(item_data, "scale", &item->scale);
|
|
|
+
|
|
|
+ if (obs_data_has_user_value(item_data, "pos_rel") &&
|
|
|
+ obs_data_has_user_value(item_data, "scale_rel") &&
|
|
|
+ obs_data_has_user_value(item_data, "scale_ref")) {
|
|
|
+ obs_data_get_vec2(item_data, "pos_rel", &item->pos);
|
|
|
+ obs_data_get_vec2(item_data, "scale_rel", &item->scale);
|
|
|
+ obs_data_get_vec2(item_data, "scale_ref", &item->scale_ref);
|
|
|
+ } else {
|
|
|
+ obs_data_get_vec2(item_data, "pos", &item->pos);
|
|
|
+ pos_from_absolute(&item->pos, &item->pos, item);
|
|
|
+ obs_data_get_vec2(item_data, "scale", &item->scale);
|
|
|
+ }
|
|
|
|
|
|
obs_data_release(item->private_settings);
|
|
|
item->private_settings =
|
|
@@ -1125,6 +1285,13 @@ static void scene_load_item(struct obs_scene *scene, obs_data_t *item_data)
|
|
|
item->crop_to_bounds = obs_data_get_bool(item_data, "bounds_crop");
|
|
|
obs_data_get_vec2(item_data, "bounds", &item->bounds);
|
|
|
|
|
|
+ if (obs_data_has_user_value(item_data, "bounds_rel")) {
|
|
|
+ obs_data_get_vec2(item_data, "bounds_rel", &item->bounds);
|
|
|
+ } else {
|
|
|
+ obs_data_get_vec2(item_data, "bounds", &item->bounds);
|
|
|
+ size_from_absolute(&item->bounds, &item->bounds, item);
|
|
|
+ }
|
|
|
+
|
|
|
item->crop.left = (uint32_t)obs_data_get_int(item_data, "crop_left");
|
|
|
item->crop.top = (uint32_t)obs_data_get_int(item_data, "crop_top");
|
|
|
item->crop.right = (uint32_t)obs_data_get_int(item_data, "crop_right");
|
|
@@ -1241,18 +1408,29 @@ static void scene_save_item(obs_data_array_t *array,
|
|
|
get_ungrouped_transform(backup_group, &pos, &scale, &rot);
|
|
|
}
|
|
|
|
|
|
+ /* For backwards compatibility, also store absolute values. */
|
|
|
+ struct vec2 tmp_abs;
|
|
|
+
|
|
|
obs_data_set_string(item_data, "name", name);
|
|
|
obs_data_set_string(item_data, "source_uuid", src_uuid);
|
|
|
obs_data_set_bool(item_data, "visible", item->user_visible);
|
|
|
obs_data_set_bool(item_data, "locked", item->locked);
|
|
|
obs_data_set_double(item_data, "rot", rot);
|
|
|
- obs_data_set_vec2(item_data, "pos", &pos);
|
|
|
- obs_data_set_vec2(item_data, "scale", &scale);
|
|
|
+ pos_to_absolute(&tmp_abs, &pos, item);
|
|
|
+ obs_data_set_vec2(item_data, "pos", &tmp_abs);
|
|
|
+ obs_data_set_vec2(item_data, "pos_rel", &pos);
|
|
|
+ item_canvas_scale(&tmp_abs, item);
|
|
|
+ obs_data_set_vec2(item_data, "scale", &tmp_abs);
|
|
|
+ obs_data_set_vec2(item_data, "scale_rel", &scale);
|
|
|
+ obs_data_set_vec2(item_data, "scale_ref", &item->scale_ref);
|
|
|
obs_data_set_int(item_data, "align", (int)item->align);
|
|
|
obs_data_set_int(item_data, "bounds_type", (int)item->bounds_type);
|
|
|
obs_data_set_int(item_data, "bounds_align", (int)item->bounds_align);
|
|
|
obs_data_set_bool(item_data, "bounds_crop", item->crop_to_bounds);
|
|
|
obs_data_set_vec2(item_data, "bounds", &item->bounds);
|
|
|
+ size_to_absolute(&tmp_abs, &item->bounds, item);
|
|
|
+ obs_data_set_vec2(item_data, "bounds", &tmp_abs);
|
|
|
+ obs_data_set_vec2(item_data, "bounds_rel", &item->bounds);
|
|
|
obs_data_set_int(item_data, "crop_left", (int)item->crop.left);
|
|
|
obs_data_set_int(item_data, "crop_top", (int)item->crop.top);
|
|
|
obs_data_set_int(item_data, "crop_right", (int)item->crop.right);
|
|
@@ -2339,10 +2517,13 @@ static obs_sceneitem_t *obs_scene_add_internal(obs_scene_t *scene,
|
|
|
item->user_visible = true;
|
|
|
item->locked = false;
|
|
|
item->is_group = strcmp(source->info.id, group_info.id) == 0;
|
|
|
+ item->is_scene = strcmp(source->info.id, scene_info.id) == 0;
|
|
|
item->private_settings = obs_data_create();
|
|
|
item->toggle_visibility = OBS_INVALID_HOTKEY_PAIR_ID;
|
|
|
os_atomic_set_long(&item->active_refs, 1);
|
|
|
vec2_set(&item->scale, 1.0f, 1.0f);
|
|
|
+ vec2_set(&item->scale_ref, (float)scene_getwidth(scene),
|
|
|
+ (float)scene_getheight(scene));
|
|
|
matrix4_identity(&item->draw_transform);
|
|
|
matrix4_identity(&item->box_transform);
|
|
|
|
|
@@ -2721,6 +2902,15 @@ bool obs_sceneitem_selected(const obs_sceneitem_t *item)
|
|
|
} while (false)
|
|
|
|
|
|
void obs_sceneitem_set_pos(obs_sceneitem_t *item, const struct vec2 *pos)
|
|
|
+{
|
|
|
+ if (item) {
|
|
|
+ pos_from_absolute(&item->pos, pos, item);
|
|
|
+ do_update_transform(item);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void obs_sceneitem_set_relative_pos(obs_sceneitem_t *item,
|
|
|
+ const struct vec2 *pos)
|
|
|
{
|
|
|
if (item) {
|
|
|
vec2_copy(&item->pos, pos);
|
|
@@ -2739,7 +2929,7 @@ void obs_sceneitem_set_rot(obs_sceneitem_t *item, float rot)
|
|
|
void obs_sceneitem_set_scale(obs_sceneitem_t *item, const struct vec2 *scale)
|
|
|
{
|
|
|
if (item) {
|
|
|
- vec2_copy(&item->scale, scale);
|
|
|
+ item_relative_scale(&item->scale, scale, item);
|
|
|
do_update_transform(item);
|
|
|
}
|
|
|
}
|
|
@@ -2903,12 +3093,28 @@ void obs_sceneitem_set_bounds_crop(obs_sceneitem_t *item, bool crop)
|
|
|
void obs_sceneitem_set_bounds(obs_sceneitem_t *item, const struct vec2 *bounds)
|
|
|
{
|
|
|
if (item) {
|
|
|
- item->bounds = *bounds;
|
|
|
+ size_from_absolute(&item->bounds, bounds, item);
|
|
|
+ do_update_transform(item);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void obs_sceneitem_set_relative_bounds(obs_sceneitem_t *item,
|
|
|
+ const struct vec2 *bounds)
|
|
|
+{
|
|
|
+ if (item) {
|
|
|
+ vec2_copy(&item->bounds, bounds);
|
|
|
do_update_transform(item);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void obs_sceneitem_get_pos(const obs_sceneitem_t *item, struct vec2 *pos)
|
|
|
+{
|
|
|
+ if (item)
|
|
|
+ pos_to_absolute(pos, &item->pos, item);
|
|
|
+}
|
|
|
+
|
|
|
+void obs_sceneitem_get_relative_pos(const obs_sceneitem_t *item,
|
|
|
+ struct vec2 *pos)
|
|
|
{
|
|
|
if (item)
|
|
|
vec2_copy(pos, &item->pos);
|
|
@@ -2922,7 +3128,7 @@ float obs_sceneitem_get_rot(const obs_sceneitem_t *item)
|
|
|
void obs_sceneitem_get_scale(const obs_sceneitem_t *item, struct vec2 *scale)
|
|
|
{
|
|
|
if (item)
|
|
|
- vec2_copy(scale, &item->scale);
|
|
|
+ item_canvas_scale(scale, item);
|
|
|
}
|
|
|
|
|
|
uint32_t obs_sceneitem_get_alignment(const obs_sceneitem_t *item)
|
|
@@ -2948,19 +3154,27 @@ bool obs_sceneitem_get_bounds_crop(const obs_sceneitem_t *item)
|
|
|
void obs_sceneitem_get_bounds(const obs_sceneitem_t *item, struct vec2 *bounds)
|
|
|
{
|
|
|
if (item)
|
|
|
- *bounds = item->bounds;
|
|
|
+ size_to_absolute(bounds, &item->bounds, item);
|
|
|
+}
|
|
|
+
|
|
|
+void obs_sceneitem_get_relative_bounds(const obs_sceneitem_t *item,
|
|
|
+ struct vec2 *bounds)
|
|
|
+{
|
|
|
+ if (item)
|
|
|
+ vec2_copy(bounds, &item->bounds);
|
|
|
}
|
|
|
|
|
|
void obs_sceneitem_get_info(const obs_sceneitem_t *item,
|
|
|
struct obs_transform_info *info)
|
|
|
{
|
|
|
if (item && info) {
|
|
|
- info->pos = item->pos;
|
|
|
+ pos_to_absolute(&info->pos, &item->pos, item);
|
|
|
info->rot = item->rot;
|
|
|
- info->scale = item->scale;
|
|
|
+ item_canvas_scale(&info->scale, item);
|
|
|
info->alignment = item->align;
|
|
|
info->bounds_type = item->bounds_type;
|
|
|
info->bounds_alignment = item->bounds_align;
|
|
|
+ size_to_absolute(&info->bounds, &item->bounds, item);
|
|
|
info->bounds = item->bounds;
|
|
|
}
|
|
|
}
|
|
@@ -2969,29 +3183,45 @@ void obs_sceneitem_get_info2(const obs_sceneitem_t *item,
|
|
|
struct obs_transform_info *info)
|
|
|
{
|
|
|
if (item && info) {
|
|
|
- info->pos = item->pos;
|
|
|
+ pos_to_absolute(&info->pos, &item->pos, item);
|
|
|
info->rot = item->rot;
|
|
|
- info->scale = item->scale;
|
|
|
+ item_canvas_scale(&info->scale, item);
|
|
|
info->alignment = item->align;
|
|
|
info->bounds_type = item->bounds_type;
|
|
|
info->bounds_alignment = item->bounds_align;
|
|
|
+ size_to_absolute(&info->bounds, &item->bounds, item);
|
|
|
info->bounds = item->bounds;
|
|
|
info->crop_to_bounds = item->crop_to_bounds;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void obs_sceneitem_get_info3(const obs_sceneitem_t *item,
|
|
|
+ struct obs_transform_info *info)
|
|
|
+{
|
|
|
+ if (item && info) {
|
|
|
+ info->pos = item->pos;
|
|
|
+ info->rot = item->rot;
|
|
|
+ item_canvas_scale(&info->scale, item);
|
|
|
+ info->alignment = item->align;
|
|
|
+ info->bounds_type = item->bounds_type;
|
|
|
+ info->bounds_alignment = item->bounds_align;
|
|
|
+ info->bounds = item->bounds;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void obs_sceneitem_set_info(obs_sceneitem_t *item,
|
|
|
const struct obs_transform_info *info)
|
|
|
{
|
|
|
if (item && info) {
|
|
|
- item->pos = info->pos;
|
|
|
+ pos_from_absolute(&item->pos, &info->pos, item);
|
|
|
item->rot = info->rot;
|
|
|
if (isfinite(info->scale.x) && isfinite(info->scale.y)) {
|
|
|
- item->scale = info->scale;
|
|
|
+ item_relative_scale(&item->scale, &info->scale, item);
|
|
|
}
|
|
|
item->align = info->alignment;
|
|
|
item->bounds_type = info->bounds_type;
|
|
|
item->bounds_align = info->bounds_alignment;
|
|
|
+ size_from_absolute(&item->bounds, &info->bounds, item);
|
|
|
item->bounds = info->bounds;
|
|
|
do_update_transform(item);
|
|
|
}
|
|
@@ -3001,20 +3231,38 @@ void obs_sceneitem_set_info2(obs_sceneitem_t *item,
|
|
|
const struct obs_transform_info *info)
|
|
|
{
|
|
|
if (item && info) {
|
|
|
- item->pos = info->pos;
|
|
|
+ pos_from_absolute(&item->pos, &info->pos, item);
|
|
|
item->rot = info->rot;
|
|
|
if (isfinite(info->scale.x) && isfinite(info->scale.y)) {
|
|
|
- item->scale = info->scale;
|
|
|
+ item_relative_scale(&item->scale, &info->scale, item);
|
|
|
}
|
|
|
item->align = info->alignment;
|
|
|
item->bounds_type = info->bounds_type;
|
|
|
item->bounds_align = info->bounds_alignment;
|
|
|
+ size_from_absolute(&item->bounds, &info->bounds, item);
|
|
|
item->bounds = info->bounds;
|
|
|
item->crop_to_bounds = info->crop_to_bounds;
|
|
|
do_update_transform(item);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+void obs_sceneitem_set_info3(obs_sceneitem_t *item,
|
|
|
+ const struct obs_transform_info *info)
|
|
|
+{
|
|
|
+ if (item && info) {
|
|
|
+ item->pos = info->pos;
|
|
|
+ item->rot = info->rot;
|
|
|
+ if (isfinite(info->scale.x) && isfinite(info->scale.y)) {
|
|
|
+ item_relative_scale(&item->scale, &info->scale, item);
|
|
|
+ }
|
|
|
+ item->align = info->alignment;
|
|
|
+ item->bounds_type = info->bounds_type;
|
|
|
+ item->bounds_align = info->bounds_alignment;
|
|
|
+ item->bounds = info->bounds;
|
|
|
+ do_update_transform(item);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
void obs_sceneitem_get_draw_transform(const obs_sceneitem_t *item,
|
|
|
struct matrix4 *transform)
|
|
|
{
|
|
@@ -3483,10 +3731,15 @@ static bool resize_scene_base(obs_scene_t *scene, struct vec2 *minv,
|
|
|
}
|
|
|
|
|
|
item = scene->first_item;
|
|
|
- while (item) {
|
|
|
- vec2_sub(&item->pos, &item->pos, minv);
|
|
|
- update_item_transform(item, false);
|
|
|
- item = item->next;
|
|
|
+ if (item) {
|
|
|
+ struct vec2 minv_rel;
|
|
|
+ size_from_absolute(&minv_rel, minv, item);
|
|
|
+
|
|
|
+ while (item) {
|
|
|
+ vec2_sub(&item->pos, &item->pos, &minv_rel);
|
|
|
+ update_item_transform(item, false);
|
|
|
+ item = item->next;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
vec2_sub(scale, maxv, minv);
|
|
@@ -3504,7 +3757,7 @@ static void resize_scene(obs_scene_t *scene)
|
|
|
}
|
|
|
|
|
|
/* assumes group scene and parent scene is locked */
|
|
|
-static void resize_group(obs_sceneitem_t *group)
|
|
|
+static void resize_group(obs_sceneitem_t *group, bool scene_resize)
|
|
|
{
|
|
|
obs_scene_t *scene = group->source->context.data;
|
|
|
struct vec2 minv;
|
|
@@ -3517,7 +3770,7 @@ static void resize_group(obs_sceneitem_t *group)
|
|
|
if (!resize_scene_base(scene, &minv, &maxv, &scale))
|
|
|
return;
|
|
|
|
|
|
- if (group->bounds_type == OBS_BOUNDS_NONE) {
|
|
|
+ if (group->bounds_type == OBS_BOUNDS_NONE && !scene_resize) {
|
|
|
struct vec2 new_pos;
|
|
|
|
|
|
if ((group->align & OBS_ALIGN_LEFT) != 0)
|
|
@@ -3535,6 +3788,7 @@ static void resize_group(obs_sceneitem_t *group)
|
|
|
new_pos.y = (maxv.y - minv.y) * 0.5f + minv.y;
|
|
|
|
|
|
transform_val(&new_pos, &group->draw_transform);
|
|
|
+ pos_from_absolute(&new_pos, &new_pos, group);
|
|
|
vec2_copy(&group->pos, &new_pos);
|
|
|
}
|
|
|
|
|
@@ -3602,7 +3856,7 @@ obs_sceneitem_t *obs_scene_insert_group(obs_scene_t *scene, const char *name,
|
|
|
apply_group_transform(items[idx], item);
|
|
|
}
|
|
|
items[0]->prev = NULL;
|
|
|
- resize_group(item);
|
|
|
+ resize_group(item, false);
|
|
|
full_unlock(sub_scene);
|
|
|
full_unlock(scene);
|
|
|
|
|
@@ -3749,7 +4003,7 @@ void obs_sceneitem_group_add_item(obs_sceneitem_t *group, obs_sceneitem_t *item)
|
|
|
|
|
|
apply_group_transform(item, group);
|
|
|
|
|
|
- resize_group(group);
|
|
|
+ resize_group(group, false);
|
|
|
|
|
|
full_unlock(groupscene);
|
|
|
full_unlock(scene);
|
|
@@ -3778,7 +4032,7 @@ void obs_sceneitem_group_remove_item(obs_sceneitem_t *group,
|
|
|
detach_sceneitem(item);
|
|
|
attach_sceneitem(scene, item, NULL);
|
|
|
|
|
|
- resize_group(group);
|
|
|
+ resize_group(group, false);
|
|
|
|
|
|
full_unlock(groupscene);
|
|
|
full_unlock(scene);
|
|
@@ -3961,7 +4215,7 @@ bool obs_scene_reorder_items2(obs_scene_t *scene,
|
|
|
sub_prev = sub_item;
|
|
|
}
|
|
|
|
|
|
- resize_group(info->item);
|
|
|
+ resize_group(info->item, false);
|
|
|
full_unlock(sub_scene);
|
|
|
obs_scene_release(sub_scene);
|
|
|
}
|