From 67bfdde1132ea346b8e1a2a202102f69deed8d19 Mon Sep 17 00:00:00 2001 From: Barry Carlyon Date: Sun, 20 Jan 2019 15:55:20 +0000 Subject: [PATCH 1/9] Update WSEvents.cpp Clone OnSceneItemAdd to a new function to support the `item_transform` signal. Emit as `SourceItemChanged` --- src/WSEvents.cpp | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 29aa8428..59738a7a 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -256,6 +256,8 @@ void WSEvents::connectSceneSignals(obs_source_t* scene) { "item_remove", OnSceneItemDelete, this); signal_handler_disconnect(sh, "item_visible", OnSceneItemVisibilityChanged, this); + signal_handler_disconnect(sh, + "item_transform", OnSceneItemTransform, this); } currentScene = scene; @@ -271,6 +273,8 @@ void WSEvents::connectSceneSignals(obs_source_t* scene) { "item_remove", OnSceneItemDelete, this); signal_handler_connect(sh, "item_visible", OnSceneItemVisibilityChanged, this); + signal_handler_connect(sh, + "item_transform ", OnSceneItemTransform, this); } } @@ -911,6 +915,38 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { instance->broadcastUpdate("SceneItemVisibilityChanged", fields); } +/** + * An item's transfrom has been changed. + * + * @return {String} `scene-name` Name of the scene. + * @return {String} `item-name` Name of the item in the scene. + * + * @api events + * @name OnSceneItemTransform + * @category sources + * @since 4.5.1 + */ +void WSEvents::OnSceneItemTransform(void* param, calldata_t* data) { + WSEvents* instance = static_cast(param); + + obs_scene_t* scene = nullptr; + calldata_get_ptr(data, "scene", &scene); + + obs_sceneitem_t* sceneItem = nullptr; + calldata_get_ptr(data, "item", &sceneItem); + + const char* sceneName = + obs_source_get_name(obs_scene_get_source(scene)); + const char* sceneItemName = + obs_source_get_name(obs_sceneitem_get_source(sceneItem)); + + OBSDataAutoRelease fields = obs_data_create(); + obs_data_set_string(fields, "scene-name", sceneName); + obs_data_set_string(fields, "item-name", sceneItemName); + + instance->broadcastUpdate("SourceItemChanged", fields); +} + /** * The selected preview scene has changed (only available in Studio Mode). * From c10c35e38ea7556870b2856d8333c6390ec6d26f Mon Sep 17 00:00:00 2001 From: Barry Carlyon Date: Sun, 20 Jan 2019 16:04:25 +0000 Subject: [PATCH 2/9] Forgot to declare the function --- src/WSEvents.h | 1 + 1 file changed, 1 insertion(+) diff --git a/src/WSEvents.h b/src/WSEvents.h index 48de519d..c9f370fd 100644 --- a/src/WSEvents.h +++ b/src/WSEvents.h @@ -116,4 +116,5 @@ private: static void OnSceneItemAdd(void* param, calldata_t* data); static void OnSceneItemDelete(void* param, calldata_t* data); static void OnSceneItemVisibilityChanged(void* param, calldata_t* data); + static void OnSceneItemTransform(void* param, calldata_t* data); }; From dfeb156da92d263bb8b95f9198001aff996a71da Mon Sep 17 00:00:00 2001 From: Barry Carlyon Date: Sun, 20 Jan 2019 16:07:58 +0000 Subject: [PATCH 3/9] Documentation/comment fix --- src/WSEvents.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 59738a7a..6965b136 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -922,7 +922,7 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { * @return {String} `item-name` Name of the item in the scene. * * @api events - * @name OnSceneItemTransform + * @name SourceItemChanged * @category sources * @since 4.5.1 */ From 8946e8997fc4fe89100fdb954dfa58cd6f5336d2 Mon Sep 17 00:00:00 2001 From: Barry Carlyon Date: Fri, 1 Feb 2019 17:27:42 +0000 Subject: [PATCH 4/9] Update WSEvents.cpp Requested changes. I swapped "obs_data_set_string(data, "name", itemName.toUtf8());" for scene-item and item-name as otherwise you don't know what scene the item was changed on (studio mode if you change items on a non active scene) --- src/WSEvents.cpp | 74 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 3 deletions(-) diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 6965b136..e9643e54 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -922,9 +922,9 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { * @return {String} `item-name` Name of the item in the scene. * * @api events - * @name SourceItemChanged + * @name SceneItemTransformChanged * @category sources - * @since 4.5.1 + * @since unreleased */ void WSEvents::OnSceneItemTransform(void* param, calldata_t* data) { WSEvents* instance = static_cast(param); @@ -944,7 +944,75 @@ void WSEvents::OnSceneItemTransform(void* param, calldata_t* data) { obs_data_set_string(fields, "scene-name", sceneName); obs_data_set_string(fields, "item-name", sceneItemName); - instance->broadcastUpdate("SourceItemChanged", fields); + OBSDataAutoRelease posData = obs_data_create(); + vec2 pos; + obs_sceneitem_get_pos(sceneItem, &pos); + obs_data_set_double(posData, "x", pos.x); + obs_data_set_double(posData, "y", pos.y); + obs_data_set_int(posData, "alignment", obs_sceneitem_get_alignment(sceneItem)); + obs_data_set_obj(fields, "position", posData); + + obs_data_set_double(fields, "rotation", obs_sceneitem_get_rot(sceneItem)); + + OBSDataAutoRelease scaleData = obs_data_create(); + vec2 scale; + obs_sceneitem_get_scale(sceneItem, &scale); + obs_data_set_double(scaleData, "x", scale.x); + obs_data_set_double(scaleData, "y", scale.y); + obs_data_set_obj(fields, "scale", scaleData); + + OBSDataAutoRelease cropData = obs_data_create(); + obs_sceneitem_crop crop; + obs_sceneitem_get_crop(sceneItem, &crop); + obs_data_set_int(cropData, "left", crop.left); + obs_data_set_int(cropData, "top", crop.top); + obs_data_set_int(cropData, "right", crop.right); + obs_data_set_int(cropData, "bottom", crop.bottom); + obs_data_set_obj(fields, "crop", cropData); + + obs_data_set_bool(fields, "visible", obs_sceneitem_visible(sceneItem)); + + OBSDataAutoRelease boundsData = obs_data_create(); + obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem); + if (boundsType == OBS_BOUNDS_NONE) { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_NONE"); + } + else { + switch (boundsType) { + case OBS_BOUNDS_STRETCH: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); + break; + } + case OBS_BOUNDS_SCALE_INNER: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); + break; + } + case OBS_BOUNDS_SCALE_OUTER: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); + break; + } + case OBS_BOUNDS_SCALE_TO_WIDTH: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); + break; + } + case OBS_BOUNDS_SCALE_TO_HEIGHT: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); + break; + } + case OBS_BOUNDS_MAX_ONLY: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); + break; + } + } + obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem)); + vec2 bounds; + obs_sceneitem_get_bounds(sceneItem, &bounds); + obs_data_set_double(boundsData, "x", bounds.x); + obs_data_set_double(boundsData, "y", bounds.y); + } + obs_data_set_obj(fields, "bounds", boundsData); + + instance->broadcastUpdate("SceneItemTransformChanged", fields); } /** From 1993596232142d0f735c725e7b6b14ecb6273250 Mon Sep 17 00:00:00 2001 From: Barry Carlyon Date: Tue, 5 Feb 2019 17:09:24 +0000 Subject: [PATCH 5/9] Requested changes to move the common code to a utils function. --- src/Utils.cpp | 74 +++++++++++++++++++++++++++++ src/Utils.h | 1 + src/WSEvents.cpp | 70 +-------------------------- src/WSRequestHandler_SceneItems.cpp | 70 +-------------------------- 4 files changed, 77 insertions(+), 138 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 570e676d..43263262 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -553,3 +553,77 @@ bool Utils::SetFilenameFormatting(const char* filenameFormatting) { config_save(profile); return true; } + +obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) { + OBSDataAutoRelease data = obs_data_create(); + + OBSDataAutoRelease posData = obs_data_create(); + vec2 pos; + obs_sceneitem_get_pos(sceneItem, &pos); + obs_data_set_double(posData, "x", pos.x); + obs_data_set_double(posData, "y", pos.y); + obs_data_set_int(posData, "alignment", obs_sceneitem_get_alignment(sceneItem)); + obs_data_set_obj(data, "position", posData); + + obs_data_set_double(data, "rotation", obs_sceneitem_get_rot(sceneItem)); + + OBSDataAutoRelease scaleData = obs_data_create(); + vec2 scale; + obs_sceneitem_get_scale(sceneItem, &scale); + obs_data_set_double(scaleData, "x", scale.x); + obs_data_set_double(scaleData, "y", scale.y); + obs_data_set_obj(data, "scale", scaleData); + + OBSDataAutoRelease cropData = obs_data_create(); + obs_sceneitem_crop crop; + obs_sceneitem_get_crop(sceneItem, &crop); + obs_data_set_int(cropData, "left", crop.left); + obs_data_set_int(cropData, "top", crop.top); + obs_data_set_int(cropData, "right", crop.right); + obs_data_set_int(cropData, "bottom", crop.bottom); + obs_data_set_obj(data, "crop", cropData); + + obs_data_set_bool(data, "visible", obs_sceneitem_visible(sceneItem)); + + OBSDataAutoRelease boundsData = obs_data_create(); + obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem); + if (boundsType == OBS_BOUNDS_NONE) { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_NONE"); + } + else { + switch (boundsType) { + case OBS_BOUNDS_STRETCH: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); + break; + } + case OBS_BOUNDS_SCALE_INNER: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); + break; + } + case OBS_BOUNDS_SCALE_OUTER: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); + break; + } + case OBS_BOUNDS_SCALE_TO_WIDTH: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); + break; + } + case OBS_BOUNDS_SCALE_TO_HEIGHT: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); + break; + } + case OBS_BOUNDS_MAX_ONLY: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); + break; + } + } + obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem)); + vec2 bounds; + obs_sceneitem_get_bounds(sceneItem, &bounds); + obs_data_set_double(boundsData, "x", bounds.x); + obs_data_set_double(boundsData, "y", bounds.y); + } + obs_data_set_obj(data, "bounds", boundsData); + + return data; +} diff --git a/src/Utils.h b/src/Utils.h index 040f6d01..3c2d1b5b 100644 --- a/src/Utils.h +++ b/src/Utils.h @@ -41,6 +41,7 @@ class Utils { static obs_sceneitem_t* GetSceneItemFromItem(obs_source_t* source, obs_data_t* item); static obs_source_t* GetTransitionFromName(QString transitionName); static obs_source_t* GetSceneFromNameOrCurrent(QString sceneName); + static obs_data_t* GetSceneItemPropertiesData(obs_sceneitem_t* item); static bool IsValidAlignment(const uint32_t alignment); diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index e9643e54..f6e18589 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -940,78 +940,10 @@ void WSEvents::OnSceneItemTransform(void* param, calldata_t* data) { const char* sceneItemName = obs_source_get_name(obs_sceneitem_get_source(sceneItem)); - OBSDataAutoRelease fields = obs_data_create(); + OBSDataAutoRelease fields = Utils::GetSceneItemPropertiesData(sceneItem); obs_data_set_string(fields, "scene-name", sceneName); obs_data_set_string(fields, "item-name", sceneItemName); - OBSDataAutoRelease posData = obs_data_create(); - vec2 pos; - obs_sceneitem_get_pos(sceneItem, &pos); - obs_data_set_double(posData, "x", pos.x); - obs_data_set_double(posData, "y", pos.y); - obs_data_set_int(posData, "alignment", obs_sceneitem_get_alignment(sceneItem)); - obs_data_set_obj(fields, "position", posData); - - obs_data_set_double(fields, "rotation", obs_sceneitem_get_rot(sceneItem)); - - OBSDataAutoRelease scaleData = obs_data_create(); - vec2 scale; - obs_sceneitem_get_scale(sceneItem, &scale); - obs_data_set_double(scaleData, "x", scale.x); - obs_data_set_double(scaleData, "y", scale.y); - obs_data_set_obj(fields, "scale", scaleData); - - OBSDataAutoRelease cropData = obs_data_create(); - obs_sceneitem_crop crop; - obs_sceneitem_get_crop(sceneItem, &crop); - obs_data_set_int(cropData, "left", crop.left); - obs_data_set_int(cropData, "top", crop.top); - obs_data_set_int(cropData, "right", crop.right); - obs_data_set_int(cropData, "bottom", crop.bottom); - obs_data_set_obj(fields, "crop", cropData); - - obs_data_set_bool(fields, "visible", obs_sceneitem_visible(sceneItem)); - - OBSDataAutoRelease boundsData = obs_data_create(); - obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem); - if (boundsType == OBS_BOUNDS_NONE) { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_NONE"); - } - else { - switch (boundsType) { - case OBS_BOUNDS_STRETCH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); - break; - } - case OBS_BOUNDS_SCALE_INNER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); - break; - } - case OBS_BOUNDS_SCALE_OUTER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); - break; - } - case OBS_BOUNDS_SCALE_TO_WIDTH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); - break; - } - case OBS_BOUNDS_SCALE_TO_HEIGHT: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); - break; - } - case OBS_BOUNDS_MAX_ONLY: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); - break; - } - } - obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem)); - vec2 bounds; - obs_sceneitem_get_bounds(sceneItem, &bounds); - obs_data_set_double(boundsData, "x", bounds.x); - obs_data_set_double(boundsData, "y", bounds.y); - } - obs_data_set_obj(fields, "bounds", boundsData); - instance->broadcastUpdate("SceneItemTransformChanged", fields); } diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp index ddc8d336..edd8e74a 100644 --- a/src/WSRequestHandler_SceneItems.cpp +++ b/src/WSRequestHandler_SceneItems.cpp @@ -53,77 +53,9 @@ HandlerResponse WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler* return req->SendErrorResponse("specified scene item doesn't exist"); } - OBSDataAutoRelease data = obs_data_create(); + OBSDataAutoRelease data = Utils::GetSceneItemPropertiesData(sceneItem); obs_data_set_string(data, "name", itemName.toUtf8()); - OBSDataAutoRelease posData = obs_data_create(); - vec2 pos; - obs_sceneitem_get_pos(sceneItem, &pos); - obs_data_set_double(posData, "x", pos.x); - obs_data_set_double(posData, "y", pos.y); - obs_data_set_int(posData, "alignment", obs_sceneitem_get_alignment(sceneItem)); - obs_data_set_obj(data, "position", posData); - - obs_data_set_double(data, "rotation", obs_sceneitem_get_rot(sceneItem)); - - OBSDataAutoRelease scaleData = obs_data_create(); - vec2 scale; - obs_sceneitem_get_scale(sceneItem, &scale); - obs_data_set_double(scaleData, "x", scale.x); - obs_data_set_double(scaleData, "y", scale.y); - obs_data_set_obj(data, "scale", scaleData); - - OBSDataAutoRelease cropData = obs_data_create(); - obs_sceneitem_crop crop; - obs_sceneitem_get_crop(sceneItem, &crop); - obs_data_set_int(cropData, "left", crop.left); - obs_data_set_int(cropData, "top", crop.top); - obs_data_set_int(cropData, "right", crop.right); - obs_data_set_int(cropData, "bottom", crop.bottom); - obs_data_set_obj(data, "crop", cropData); - - obs_data_set_bool(data, "visible", obs_sceneitem_visible(sceneItem)); - - OBSDataAutoRelease boundsData = obs_data_create(); - obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem); - if (boundsType == OBS_BOUNDS_NONE) { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_NONE"); - } - else { - switch (boundsType) { - case OBS_BOUNDS_STRETCH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); - break; - } - case OBS_BOUNDS_SCALE_INNER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); - break; - } - case OBS_BOUNDS_SCALE_OUTER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); - break; - } - case OBS_BOUNDS_SCALE_TO_WIDTH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); - break; - } - case OBS_BOUNDS_SCALE_TO_HEIGHT: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); - break; - } - case OBS_BOUNDS_MAX_ONLY: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); - break; - } - } - obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem)); - vec2 bounds; - obs_sceneitem_get_bounds(sceneItem, &bounds); - obs_data_set_double(boundsData, "x", bounds.x); - obs_data_set_double(boundsData, "y", bounds.y); - } - obs_data_set_obj(data, "bounds", boundsData); - return req->SendOKResponse(data); } From 2915690d229334562f4dabea3e76d01c0ccfeb61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Wed, 3 Apr 2019 13:05:00 +0200 Subject: [PATCH 6/9] utils: use obs_data_t for returned values --- src/Utils.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 43263262..893d90c9 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -555,7 +555,7 @@ bool Utils::SetFilenameFormatting(const char* filenameFormatting) { } obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) { - OBSDataAutoRelease data = obs_data_create(); + obs_data_t* data = obs_data_create(); OBSDataAutoRelease posData = obs_data_create(); vec2 pos; From 252dd7e09ff79495d2bbf637410e2cb5e7dad239 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Lepin?= Date: Wed, 3 Apr 2019 13:06:14 +0200 Subject: [PATCH 7/9] utils: indent fixes --- src/Utils.cpp | 48 ++++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 893d90c9..3f3013cc 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -592,30 +592,30 @@ obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) { } else { switch (boundsType) { - case OBS_BOUNDS_STRETCH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); - break; - } - case OBS_BOUNDS_SCALE_INNER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); - break; - } - case OBS_BOUNDS_SCALE_OUTER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); - break; - } - case OBS_BOUNDS_SCALE_TO_WIDTH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); - break; - } - case OBS_BOUNDS_SCALE_TO_HEIGHT: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); - break; - } - case OBS_BOUNDS_MAX_ONLY: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); - break; - } + case OBS_BOUNDS_STRETCH: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); + break; + } + case OBS_BOUNDS_SCALE_INNER: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); + break; + } + case OBS_BOUNDS_SCALE_OUTER: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); + break; + } + case OBS_BOUNDS_SCALE_TO_WIDTH: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); + break; + } + case OBS_BOUNDS_SCALE_TO_HEIGHT: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); + break; + } + case OBS_BOUNDS_MAX_ONLY: { + obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); + break; + } } obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem)); vec2 bounds; From 30df5f3558298e5190179d38f6ca92ab058a56d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Tue, 16 Apr 2019 23:55:41 +0200 Subject: [PATCH 8/9] events: fix typo --- src/WSEvents.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index f6e18589..99d5cf31 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -274,7 +274,7 @@ void WSEvents::connectSceneSignals(obs_source_t* scene) { signal_handler_connect(sh, "item_visible", OnSceneItemVisibilityChanged, this); signal_handler_connect(sh, - "item_transform ", OnSceneItemTransform, this); + "item_transform", OnSceneItemTransform, this); } } From 5e4d6fbd3f8d67efe069a911d2e90952e85a7dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20L?= Date: Wed, 17 Apr 2019 01:09:05 +0200 Subject: [PATCH 9/9] utils: refactored docs and impl of scene item properties --- src/Utils.cpp | 120 ++++++++++++++++------------ src/WSEvents.cpp | 6 +- src/WSRequestHandler_SceneItems.cpp | 10 +-- 3 files changed, 77 insertions(+), 59 deletions(-) diff --git a/src/Utils.cpp b/src/Utils.cpp index 3f3013cc..ecd6039f 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -28,6 +28,25 @@ with this program. If not, see Q_DECLARE_METATYPE(OBSScene); +const QHash boundTypeNames = { + { OBS_BOUNDS_STRETCH, "OBS_BOUNDS_STRETCH" }, + { OBS_BOUNDS_SCALE_INNER, "OBS_BOUNDS_SCALE_INNER" }, + { OBS_BOUNDS_SCALE_OUTER, "OBS_BOUNDS_SCALE_OUTER" }, + { OBS_BOUNDS_SCALE_TO_WIDTH, "OBS_BOUNDS_SCALE_TO_WIDTH" }, + { OBS_BOUNDS_SCALE_TO_HEIGHT, "OBS_BOUNDS_SCALE_TO_HEIGHT" }, + { OBS_BOUNDS_MAX_ONLY, "OBS_BOUNDS_MAX_ONLY" }, + { OBS_BOUNDS_NONE, "OBS_BOUNDS_NONE" }, +}; + +QString getBoundsNameFromType(obs_bounds_type type) { + QString fallback = boundTypeNames.value(OBS_BOUNDS_NONE); + return boundTypeNames.value(type, fallback); +} + +obs_bounds_type getBoundsTypeFromName(QString name) { + return boundTypeNames.key(name); +} + obs_data_array_t* Utils::StringListToArray(char** strings, char* key) { if (!strings) return obs_data_array_create(); @@ -110,7 +129,7 @@ obs_sceneitem_t* Utils::GetSceneItemFromItem(obs_source_t* source, obs_data_t* i if (obs_data_has_user_value(item, "name") && (QString)obs_source_get_name(obs_sceneitem_get_source(sceneItem)) != (QString)obs_data_get_string(item, "name")) { - return nullptr; + return nullptr; } } else if (obs_data_has_user_value(item, "name")) { @@ -554,75 +573,70 @@ bool Utils::SetFilenameFormatting(const char* filenameFormatting) { return true; } +// Transform properties copy-pasted from WSRequestHandler_SceneItems.cpp because typedefs can't be extended yet + +/** + * @typedef {Object} `SceneItemTransform` + * @property {int} `position.x` The x position of the scene item from the left. + * @property {int} `position.y` The y position of the scene item from the top. + * @property {int} `position.alignment` The point on the scene item that the item is manipulated from. + * @property {double} `rotation` The clockwise rotation of the scene item in degrees around the point of alignment. + * @property {double} `scale.x` The x-scale factor of the scene item. + * @property {double} `scale.y` The y-scale factor of the scene item. + * @property {int} `crop.top` The number of pixels cropped off the top of the scene item before scaling. + * @property {int} `crop.right` The number of pixels cropped off the right of the scene item before scaling. + * @property {int} `crop.bottom` The number of pixels cropped off the bottom of the scene item before scaling. + * @property {int} `crop.left` The number of pixels cropped off the left of the scene item before scaling. + * @property {bool} `visible` If the scene item is visible. + * @property {String} `bounds.type` Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". + * @property {int} `bounds.alignment` Alignment of the bounding box. + * @property {double} `bounds.x` Width of the bounding box. + * @property {double} `bounds.y` Height of the bounding box. + */ obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) { - obs_data_t* data = obs_data_create(); + vec2 pos, scale, bounds; + obs_sceneitem_crop crop; + + obs_sceneitem_get_pos(sceneItem, &pos); + obs_sceneitem_get_scale(sceneItem, &scale); + obs_sceneitem_get_crop(sceneItem, &crop); + obs_sceneitem_get_bounds(sceneItem, &bounds); + + uint32_t alignment = obs_sceneitem_get_alignment(sceneItem); + float rotation = obs_sceneitem_get_rot(sceneItem); + bool isVisible = obs_sceneitem_visible(sceneItem); + + obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem); + uint32_t boundsAlignment = obs_sceneitem_get_bounds_alignment(sceneItem); + QString boundsTypeName = getBoundsNameFromType(boundsType); OBSDataAutoRelease posData = obs_data_create(); - vec2 pos; - obs_sceneitem_get_pos(sceneItem, &pos); obs_data_set_double(posData, "x", pos.x); obs_data_set_double(posData, "y", pos.y); - obs_data_set_int(posData, "alignment", obs_sceneitem_get_alignment(sceneItem)); - obs_data_set_obj(data, "position", posData); - - obs_data_set_double(data, "rotation", obs_sceneitem_get_rot(sceneItem)); + obs_data_set_int(posData, "alignment", alignment); OBSDataAutoRelease scaleData = obs_data_create(); - vec2 scale; - obs_sceneitem_get_scale(sceneItem, &scale); obs_data_set_double(scaleData, "x", scale.x); obs_data_set_double(scaleData, "y", scale.y); - obs_data_set_obj(data, "scale", scaleData); OBSDataAutoRelease cropData = obs_data_create(); - obs_sceneitem_crop crop; - obs_sceneitem_get_crop(sceneItem, &crop); obs_data_set_int(cropData, "left", crop.left); obs_data_set_int(cropData, "top", crop.top); obs_data_set_int(cropData, "right", crop.right); obs_data_set_int(cropData, "bottom", crop.bottom); - obs_data_set_obj(data, "crop", cropData); - - obs_data_set_bool(data, "visible", obs_sceneitem_visible(sceneItem)); OBSDataAutoRelease boundsData = obs_data_create(); - obs_bounds_type boundsType = obs_sceneitem_get_bounds_type(sceneItem); - if (boundsType == OBS_BOUNDS_NONE) { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_NONE"); - } - else { - switch (boundsType) { - case OBS_BOUNDS_STRETCH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_STRETCH"); - break; - } - case OBS_BOUNDS_SCALE_INNER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_INNER"); - break; - } - case OBS_BOUNDS_SCALE_OUTER: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_OUTER"); - break; - } - case OBS_BOUNDS_SCALE_TO_WIDTH: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_WIDTH"); - break; - } - case OBS_BOUNDS_SCALE_TO_HEIGHT: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_SCALE_TO_HEIGHT"); - break; - } - case OBS_BOUNDS_MAX_ONLY: { - obs_data_set_string(boundsData, "type", "OBS_BOUNDS_MAX_ONLY"); - break; - } - } - obs_data_set_int(boundsData, "alignment", obs_sceneitem_get_bounds_alignment(sceneItem)); - vec2 bounds; - obs_sceneitem_get_bounds(sceneItem, &bounds); - obs_data_set_double(boundsData, "x", bounds.x); - obs_data_set_double(boundsData, "y", bounds.y); - } + obs_data_set_string(boundsData, "type", boundsTypeName.toUtf8()); + obs_data_set_int(boundsData, "alignment", boundsAlignment); + obs_data_set_double(boundsData, "x", bounds.x); + obs_data_set_double(boundsData, "y", bounds.y); + + obs_data_t* data = obs_data_create(); + obs_data_set_obj(data, "position", posData); + obs_data_set_double(data, "rotation", rotation); + obs_data_set_obj(data, "scale", scaleData); + obs_data_set_obj(data, "crop", cropData); + obs_data_set_bool(data, "visible", isVisible); obs_data_set_obj(data, "bounds", boundsData); return data; diff --git a/src/WSEvents.cpp b/src/WSEvents.cpp index 99d5cf31..ca3d496d 100644 --- a/src/WSEvents.cpp +++ b/src/WSEvents.cpp @@ -920,6 +920,7 @@ void WSEvents::OnSceneItemVisibilityChanged(void* param, calldata_t* data) { * * @return {String} `scene-name` Name of the scene. * @return {String} `item-name` Name of the item in the scene. + * @return {SceneItemProperties} `transform` Scene item transform properties * * @api events * @name SceneItemTransformChanged @@ -940,9 +941,12 @@ void WSEvents::OnSceneItemTransform(void* param, calldata_t* data) { const char* sceneItemName = obs_source_get_name(obs_sceneitem_get_source(sceneItem)); - OBSDataAutoRelease fields = Utils::GetSceneItemPropertiesData(sceneItem); + OBSDataAutoRelease transform = Utils::GetSceneItemPropertiesData(sceneItem); + + OBSDataAutoRelease fields = obs_data_create(); obs_data_set_string(fields, "scene-name", sceneName); obs_data_set_string(fields, "item-name", sceneItemName); + obs_data_set_obj(fields, "transform", transform); instance->broadcastUpdate("SceneItemTransformChanged", fields); } diff --git a/src/WSRequestHandler_SceneItems.cpp b/src/WSRequestHandler_SceneItems.cpp index edd8e74a..6b19ae97 100644 --- a/src/WSRequestHandler_SceneItems.cpp +++ b/src/WSRequestHandler_SceneItems.cpp @@ -21,7 +21,7 @@ * @return {int} `crop.bottom` The number of pixels cropped off the bottom of the source before scaling. * @return {int} `crop.left` The number of pixels cropped off the left of the source before scaling. * @return {bool} `visible` If the source is visible. -* @return {String} `bounds.type` Type of bounding box. +* @return {String} `bounds.type` Type of bounding box. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". * @return {int} `bounds.alignment` Alignment of the bounding box. * @return {double} `bounds.x` Width of the bounding box. * @return {double} `bounds.y` Height of the bounding box. @@ -75,7 +75,7 @@ HandlerResponse WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler* * @param {int} `crop.left` The new amount of pixels cropped off the left of the source before scaling. * @param {int} `crop.right` The new amount of pixels cropped off the right of the source before scaling. * @param {bool} `visible` The new visibility of the source. 'true' shows source, 'false' hides source. -* @param {String} `bounds.type` The new bounds type of the source. +* @param {String} `bounds.type` The new bounds type of the source. Can be "OBS_BOUNDS_STRETCH", "OBS_BOUNDS_SCALE_INNER", "OBS_BOUNDS_SCALE_OUTER", "OBS_BOUNDS_SCALE_TO_WIDTH", "OBS_BOUNDS_SCALE_TO_HEIGHT", "OBS_BOUNDS_MAX_ONLY" or "OBS_BOUNDS_NONE". * @param {int} `bounds.alignment` The new alignment of the bounding box. (0-2, 4-6, 8-10) * @param {double} `bounds.x` The new width of the bounding box. * @param {double} `bounds.y` The new height of the bounding box. @@ -238,7 +238,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemProperties(WSRequestHandler* if (badRequest) { return req->SendErrorResponse(errorMessage); } - + return req->SendOKResponse(); } @@ -363,7 +363,7 @@ HandlerResponse WSRequestHandler::HandleSetSceneItemPosition(WSRequestHandler* r if (!sceneItem) { return req->SendErrorResponse("specified scene item doesn't exist"); } - + vec2 item_position = { 0 }; item_position.x = obs_data_get_double(req->data, "x"); item_position.y = obs_data_get_double(req->data, "y"); @@ -530,7 +530,7 @@ static void DuplicateSceneItem(void *_data, obs_scene_t *scene) { * @return {Object} `item` New item info * @return {int} `̀€item.id` New item ID * @return {String} `item.name` New item name - * + * * @api requests * @name DuplicateSceneItem * @category scene items