[OBS-Plugin] Get active scene object

jip

New Member
Hey guys,

I need some help.

I want to check if my source intersects with other sources in the scene. I got it almost done, but 2 really important parts are missing.

1) How do i get the current active obs_scene_t object?
2) How do i detect the order position of an obs_sceneitem_t object?

The method is part of a class. The two issues are marked in the code.

Code:
bool MySource::Intersects() {
   struct enumSceneItem {
     obs_sceneitem_t* item;
     bool result;
   };

   bool isVisible = false;
   if (!IsActive())
     return false;

   /*
     ISSUE 1: Find a way to get the current active scene
   */
   obs_source_t* sceneSource = obs_get_source_by_name("scene");
   obs_scene_t* scene = obs_scene_from_source(sceneSource);
   if (scene == nullptr)
     return false;

   obs_sceneitem_t* sceneItem = obs_scene_find_source(scene, obs_source_get_name(GetSource()));
   if (sceneItem == nullptr)
     return false;

   bool itemVisible = obs_sceneitem_visible(sceneItem);
   if (itemVisible) {
     enumSceneItem enumItem;
     enumItem.item = sceneItem;
     enumItem.result = false;

     obs_scene_enum_items(scene, [](obs_scene_t *scene, obs_sceneitem_t *currentItem, void *param) {       
       enumSceneItem* enumItem = static_cast<enumSceneItem *>(param);
       if (currentItem == enumItem->item)
          return true;

       vec2 itemPos;
       vec2 itemBounds;
       obs_sceneitem_get_pos(enumItem->item, &itemPos);
       obs_sceneitem_get_bounds(enumItem->item, &itemBounds);

       vec2 itPos;
       vec2 itBounds;
       obs_sceneitem_get_pos(currentItem, &itPos);
       obs_sceneitem_get_bounds(currentItem, &itBounds);

       bool xOverlap = (itemPos.x >= itPos.x && itemPos.x <= itPos.x + itBounds.x)
                       || (itPos.x >= itemPos.x && itPos.x <= itemPos.x + itemBounds.x);
       bool yOverlap = (itemPos.y >= itPos.y && itemPos.y <= itPos.y + itBounds.y)
                       || (itPos.y >= itemPos.y && itPos.y <= itemPos.y + itemBounds.y);

       bool higherOrderPos = false;
       if (xOverlap && yOverlap) {
         /*
           ISSUE 2: if overlap than figure out if our source has the higher order position.
           If so, than higherOrderPos = true;
         */
       }

       if ((xOverlap && yOverlap) && !higherOrderPos)
         enumItem->result = true;

       return !enumItem->result;
     }, &enumItem);

     isVisible = !enumItem.result;
   }

   if (isVisible)
     this->interSectionState = OK;
   else
     this->interSectionState = INTERSECT;

   return isVisible;
}

Thanks in advance.

I am not sure, if that is the right place to post such stuff, if not please move the thread or tell me where i should ask these kind of questions. :-)

Have a nice day.

Jip
 
Last edited:

jip

New Member
I had some time today, so i looked again and i think i got the solution.

Here is the method body, which works for me. Change description in code comments.

Code:
struct enumSceneItem {
    obs_sceneitem_t* item;
    vec2 size;
    vec2 pos;
    int currentIndex;
    int sourceItemIndex;
    bool result;
};

if (!IsActive())
    return false;

// Get the scene object
// include <obs-frontend-api.h> in header file
obs_source_t* sceneSource = obs_frontend_get_current_scene();
obs_scene_t* scene = obs_scene_from_source(sceneSource);
if (scene == nullptr)
    return false;

// Get the scene item object of our source
obs_sceneitem_t* sceneItem = obs_scene_find_source(scene, obs_source_get_name(GetSource()));
if (sceneItem == nullptr)
    return false;
bool isVisible = obs_sceneitem_visible(sceneItem);

if (isVisible) {
    enumSceneItem enumItem;
    enumItem.item = sceneItem;
    obs_sceneitem_get_pos(sceneItem, &enumItem.pos);
    enumItem.size.x = obs_source_get_width(GetSource());
    enumItem.size.y = obs_source_get_height(GetSource());
    enumItem.result = false;
    enumItem.currentIndex = 0;
    enumItem.sourceItemIndex = -1;
    obs_scene_enum_items(scene, [](obs_scene_t *scene, obs_sceneitem_t *currentItem, void *param) {
        // We can detect the order position, because this iteration
        // gives you the reversed order position.
        // first iteration: item with the lowest order pos
        // ....
        // last iteration: item with the highest order pos
        enumSceneItem* enumItem = static_cast<enumSceneItem *>(param);
        if (currentItem == enumItem->item) {
            enumItem->sourceItemIndex = enumItem->currentIndex;
            enumItem->currentIndex++;
            return true;
        } else if (!obs_sceneitem_visible(currentItem)) {
            enumItem->currentIndex++;
            return true;
        }

        vec2 itPos;
        obs_sceneitem_get_pos(currentItem, &itPos);
        obs_source_t* itSource = obs_sceneitem_get_source(currentItem);
        vec2 itSize;
        itSize.x = obs_source_get_width(itSource);
        itSize.y = obs_source_get_height(itSource);
        bool xOverlap = (enumItem->pos.x >= itPos.x && enumItem->pos.x <= itPos.x + itSize.x) || (itPos.x >= enumItem->pos.x && itPos.x <= enumItem->pos.x + enumItem->size.x);
        bool yOverlap = (enumItem->pos.y >= itPos.y && enumItem->pos.y <= itPos.y + itSize.y) || (itPos.y >= enumItem->pos.y && itPos.y <= enumItem->pos.y + enumItem->size.y);

        bool higherOrderPos = (enumItem->sourceItemIndex == -1);

        if ((xOverlap && yOverlap) && !higherOrderPos)
            enumItem->result = true;
        enumItem->currentIndex++;
        return !enumItem->result;
    }, &enumItem);
    isVisible = !enumItem.result
}
 
Top