Merge pull request #317 from Palakis/group-fixes

Groups fixes
This commit is contained in:
Stéphane Lepin 2019-05-19 10:06:08 +02:00 committed by GitHub
commit 061ab12b10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 99 additions and 25 deletions

View File

@ -97,6 +97,23 @@ obs_data_array_t* Utils::GetSceneItems(obs_source_t* source) {
return items; return items;
} }
/**
* @typedef {Object} `SceneItem` An OBS Scene Item.
* @property {Number} `cy`
* @property {Number} `cx`
* @property {String} `name` The name of this Scene Item.
* @property {int} `id` Scene item ID
* @property {Boolean} `render` Whether or not this Scene Item is set to "visible".
* @property {Boolean} `locked` Whether or not this Scene Item is locked and can't be moved around
* @property {Number} `source_cx`
* @property {Number} `source_cy`
* @property {String} `type` Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown"
* @property {Number} `volume`
* @property {Number} `x`
* @property {Number} `y`
* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
* @property {Array<SceneItem> (optional)} `groupChildren` List of children (if this item is a group)
*/
obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) { obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
if (!item) { if (!item) {
return nullptr; return nullptr;
@ -131,6 +148,28 @@ obs_data_t* Utils::GetSceneItemData(obs_sceneitem_t* item) {
obs_data_set_bool(data, "render", obs_sceneitem_visible(item)); obs_data_set_bool(data, "render", obs_sceneitem_visible(item));
obs_data_set_bool(data, "locked", obs_sceneitem_locked(item)); obs_data_set_bool(data, "locked", obs_sceneitem_locked(item));
obs_scene_t* parent = obs_sceneitem_get_scene(item);
if (parent) {
OBSSource parentSource = obs_scene_get_source(parent);
QString parentKind = obs_source_get_id(parentSource);
if (parentKind == "group") {
obs_data_set_string(data, "parentGroupName", obs_source_get_name(parentSource));
}
}
if (obs_sceneitem_is_group(item)) {
OBSDataArrayAutoRelease children = obs_data_array_create();
obs_sceneitem_group_enum_items(item, [](obs_scene_t*, obs_sceneitem_t* currentItem, void* param) {
obs_data_array_t* items = reinterpret_cast<obs_data_array_t*>(param);
OBSDataAutoRelease itemData = GetSceneItemData(currentItem);
obs_data_array_push_back(items, itemData);
return true;
}, children);
obs_data_set_array(data, "groupChildren", children);
}
return data; return data;
} }
@ -154,23 +193,32 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name)
struct current_search { struct current_search {
QString query; QString query;
obs_sceneitem_t* result; obs_sceneitem_t* result;
bool (*enumCallback)(obs_scene_t*, obs_sceneitem_t*, void*);
}; };
current_search search; current_search search;
search.query = name; search.query = name;
search.result = nullptr; search.result = nullptr;
search.enumCallback = nullptr;
OBSScene scene = obs_scene_from_source(source); OBSScene scene = obs_scene_from_source(source);
if (!scene) if (!scene)
return nullptr; return nullptr;
obs_scene_enum_items(scene, []( search.enumCallback = [](
obs_scene_t* scene, obs_scene_t* scene,
obs_sceneitem_t* currentItem, obs_sceneitem_t* currentItem,
void* param) void* param)
{ {
current_search* search = reinterpret_cast<current_search*>(param); current_search* search = reinterpret_cast<current_search*>(param);
if (obs_sceneitem_is_group(currentItem)) {
obs_sceneitem_group_enum_items(currentItem, search->enumCallback, search);
if (search->result) {
return false;
}
}
QString currentItemName = QString currentItemName =
obs_source_get_name(obs_sceneitem_get_source(currentItem)); obs_source_get_name(obs_sceneitem_get_source(currentItem));
@ -181,32 +229,44 @@ obs_sceneitem_t* Utils::GetSceneItemFromName(obs_source_t* source, QString name)
} }
return true; return true;
}, &search); };
obs_scene_enum_items(scene, search.enumCallback, &search);
return search.result; return search.result;
} }
// TODO refactor this to unify it with GetSceneItemFromName
obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) { obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) {
struct current_search { struct current_search {
size_t query; size_t query;
obs_sceneitem_t* result; obs_sceneitem_t* result;
bool (*enumCallback)(obs_scene_t*, obs_sceneitem_t*, void*);
}; };
current_search search; current_search search;
search.query = id; search.query = id;
search.result = nullptr; search.result = nullptr;
search.enumCallback = nullptr;
OBSScene scene = obs_scene_from_source(source); OBSScene scene = obs_scene_from_source(source);
if (!scene) if (!scene)
return nullptr; return nullptr;
obs_scene_enum_items(scene, []( search.enumCallback = [](
obs_scene_t* scene, obs_scene_t* scene,
obs_sceneitem_t* currentItem, obs_sceneitem_t* currentItem,
void* param) void* param)
{ {
current_search* search = reinterpret_cast<current_search*>(param); current_search* search = reinterpret_cast<current_search*>(param);
if (obs_sceneitem_is_group(currentItem)) {
obs_sceneitem_group_enum_items(currentItem, search->enumCallback, param);
if (search->result) {
return false;
}
}
if (obs_sceneitem_get_id(currentItem) == search->query) { if (obs_sceneitem_get_id(currentItem) == search->query) {
search->result = currentItem; search->result = currentItem;
obs_sceneitem_addref(search->result); obs_sceneitem_addref(search->result);
@ -214,7 +274,9 @@ obs_sceneitem_t* Utils::GetSceneItemFromId(obs_source_t* source, size_t id) {
} }
return true; return true;
}, &search); };
obs_scene_enum_items(scene, search.enumCallback, &search);
return search.result; return search.result;
} }
@ -593,6 +655,8 @@ bool Utils::SetFilenameFormatting(const char* filenameFormatting) {
* @property {int} `sourceHeight` Base source (without scaling) of the source * @property {int} `sourceHeight` Base source (without scaling) of the source
* @property {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor) * @property {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor)
* @property {double} `height` Scene item height (base source height multiplied by the vertical scaling factor) * @property {double} `height` Scene item height (base source height multiplied by the vertical scaling factor)
* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
* @property {Array<SceneItemTransform> (optional)} `groupChildren` List of children (if this item is a group)
*/ */
obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) { obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) {
if (!sceneItem) { if (!sceneItem) {
@ -655,6 +719,28 @@ obs_data_t* Utils::GetSceneItemPropertiesData(obs_sceneitem_t* sceneItem) {
obs_data_set_double(data, "width", baseSourceWidth * scale.x); obs_data_set_double(data, "width", baseSourceWidth * scale.x);
obs_data_set_double(data, "height", baseSourceHeight * scale.y); obs_data_set_double(data, "height", baseSourceHeight * scale.y);
obs_scene_t* parent = obs_sceneitem_get_scene(sceneItem);
if (parent) {
OBSSource parentSource = obs_scene_get_source(parent);
QString parentKind = obs_source_get_id(parentSource);
if (parentKind == "group") {
obs_data_set_string(data, "parentGroupName", obs_source_get_name(parentSource));
}
}
if (obs_sceneitem_is_group(sceneItem)) {
OBSDataArrayAutoRelease children = obs_data_array_create();
obs_sceneitem_group_enum_items(sceneItem, [](obs_scene_t*, obs_sceneitem_t* subItem, void* param) {
obs_data_array_t* items = reinterpret_cast<obs_data_array_t*>(param);
OBSDataAutoRelease itemData = GetSceneItemPropertiesData(subItem);
obs_data_array_push_back(items, itemData);
return true;
}, children);
obs_data_set_array(data, "groupChildren", children);
}
return data; return data;
} }

View File

@ -344,7 +344,7 @@ const char* WSEvents::GetRecordingTimecode() {
* Indicates a scene change. * Indicates a scene change.
* *
* @return {String} `scene-name` The new scene. * @return {String} `scene-name` The new scene.
* @return {Array<Source>} `sources` List of sources in the new scene. Same specification as [`GetCurrentScene`](#getcurrentscene). * @return {Array<SceneItem>} `sources` List of scene items in the new scene. Same specification as [`GetCurrentScene`](#getcurrentscene).
* *
* @api events * @api events
* @name SwitchScenes * @name SwitchScenes
@ -1435,7 +1435,7 @@ void WSEvents::OnSceneItemDeselected(void* param, calldata_t* data) {
* The selected preview scene has changed (only available in Studio Mode). * The selected preview scene has changed (only available in Studio Mode).
* *
* @return {String} `scene-name` Name of the scene being previewed. * @return {String} `scene-name` Name of the scene being previewed.
* @return {Array<Source>} `sources` List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene). * @return {Array<SceneItem>} `sources` List of sources composing the scene. Same specification as [`GetCurrentScene`](#getcurrentscene).
* *
* @api events * @api events
* @name PreviewSceneChanged * @name PreviewSceneChanged

View File

@ -2,24 +2,9 @@
#include "WSRequestHandler.h" #include "WSRequestHandler.h"
/**
* @typedef {Object} `Source` An OBS Scene Item.
* @property {Number} `cy`
* @property {Number} `cx`
* @property {String} `name` The name of this Scene Item.
* @property {int} `id` Scene item ID
* @property {Boolean} `render` Whether or not this Scene Item is set to "visible".
* @property {Boolean} `locked` Whether or not this Scene Item is locked and can't be moved around
* @property {Number} `source_cx`
* @property {Number} `source_cy`
* @property {String} `type` Source type. Value is one of the following: "input", "filter", "transition", "scene" or "unknown"
* @property {Number} `volume`
* @property {Number} `x`
* @property {Number} `y`
*/
/** /**
* Gets the scene specific properties of the specified source item. * Gets the scene specific properties of the specified source item.
* Coordinates are relative to the item's parent (the scene or group it belongs to).
* *
* @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene. * @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene.
* @param {String} `item` The name of the source. * @param {String} `item` The name of the source.
@ -45,6 +30,8 @@
* @return {int} `sourceHeight` Base source (without scaling) of the source * @return {int} `sourceHeight` Base source (without scaling) of the source
* @return {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor) * @return {double} `width` Scene item width (base source width multiplied by the horizontal scaling factor)
* @return {double} `height` Scene item height (base source height multiplied by the vertical scaling factor) * @return {double} `height` Scene item height (base source height multiplied by the vertical scaling factor)
* @property {String (optional)} `parentGroupName` Name of the item's parent (if this item belongs to a group)
* @property {Array<SceneItemTransform> (optional)} `groupChildren` List of children (if this item is a group)
* *
* @api requests * @api requests
* @name GetSceneItemProperties * @name GetSceneItemProperties
@ -81,6 +68,7 @@ HandlerResponse WSRequestHandler::HandleGetSceneItemProperties(WSRequestHandler*
/** /**
* Sets the scene specific properties of a source. Unspecified properties will remain unchanged. * Sets the scene specific properties of a source. Unspecified properties will remain unchanged.
* Coordinates are relative to the item's parent (the scene or group it belongs to).
* *
* @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene. * @param {String (optional)} `scene-name` the name of the scene that the source item belongs to. Defaults to the current scene.
* @param {String} `item` The name of the source. * @param {String} `item` The name of the source.

View File

@ -5,7 +5,7 @@
/** /**
* @typedef {Object} `Scene` * @typedef {Object} `Scene`
* @property {String} `name` Name of the currently active scene. * @property {String} `name` Name of the currently active scene.
* @property {Array<Source>} `sources` Ordered list of the current scene's source items. * @property {Array<SceneItem>} `sources` Ordered list of the current scene's source items.
*/ */
/** /**
@ -38,7 +38,7 @@ HandlerResponse WSRequestHandler::HandleSetCurrentScene(WSRequestHandler* req) {
* Get the current scene's name and source items. * Get the current scene's name and source items.
* *
* @return {String} `name` Name of the currently active scene. * @return {String} `name` Name of the currently active scene.
* @return {Array<Source>} `sources` Ordered list of the current scene's source items. * @return {Array<SceneItem>} `sources` Ordered list of the current scene's source items.
* *
* @api requests * @api requests
* @name GetCurrentScene * @name GetCurrentScene

View File

@ -26,7 +26,7 @@ HandlerResponse WSRequestHandler::HandleGetStudioModeStatus(WSRequestHandler* re
* Will return an `error` if Studio Mode is not enabled. * Will return an `error` if Studio Mode is not enabled.
* *
* @return {String} `name` The name of the active preview scene. * @return {String} `name` The name of the active preview scene.
* @return {Array<Source>} `sources` * @return {Array<SceneItem>} `sources`
* *
* @api requests * @api requests
* @name GetPreviewScene * @name GetPreviewScene