Advanced Scene Switcher

Advanced Scene Switcher 1.32.5

Warmuptill

Active Member
Hi @Warmuptill ,

Version 1.32.4 resolved the issue I described earlier. However, I have now detected that it is no longer possible to correctly save "scene item visibility" actions when the item is a vertical scene inserted as a source in another vertical scene.

I have also detected that when creating actions to enable/disable filters in vertical scenes, the Advanced Scene Switcher does not relate the filters to the respective vertical scene.

I performed the tests on Windows 11 Pro 25H2 and also on Linux Mint 22.2 XFCE, and the results were identical.
Thanks for letting me know!
I will look into it.

Is there any possibility to save the login with twitch permanently? in streamer.bot it works. but in adv scene switcher, I need every 1 or 2 month renew the login.
Hm .. interesting.
I wasn't aware of that.
I will investigate the problem and try to resolve it.

Thanks for letting me know about this!
 
Same thing: I installed it. When I opened it, everything froze in Obs. Nothing worked. I opened it again in safe mode, clicked a few things then reopened it in normal mode. It works fine! Thanks!
 

Warmuptill

Active Member
Hi @Warmuptill ,

Version 1.32.4 resolved the issue I described earlier. However, I have now detected that it is no longer possible to correctly save "scene item visibility" actions when the item is a vertical scene inserted as a source in another vertical scene.

I have also detected that when creating actions to enable/disable filters in vertical scenes, the Advanced Scene Switcher does not relate the filters to the respective vertical scene.

I performed the tests on Windows 11 Pro 25H2 and also on Linux Mint 22.2 XFCE, and the results were identical.
A build with a fix will be available here in a few minutes:
Note that you will have to be logged into GitHub to be able to download it at the bottom of the page.
If that should be a problem feel free to reach out and I can try to share the build some other way.

Let me know if you face any issues with this test build! :)
 

FabioElizeu

New Member
A build with a fix will be available here in a few minutes:
Note that you will have to be logged into GitHub to be able to download it at the bottom of the page.
If that should be a problem feel free to reach out and I can try to share the build some other way.

Let me know if you face any issues with this test build! :)
I tested the Linux and Windows versions, and both worked.

Thank you very much!!!
 

Akinraze

New Member
Is Advanced Scene Switcher capable of doing what this guy has (<--- Link) in the bottom left corner of his streams? I looked for a Push To Talk type plugin that can manage multiple button presses simultaneously and the only one I found (<--- Link) requires Python coding (which is way over my head).

I tried the built in hotkey feature and that only enabled the source (would required two hotkeys to then turn off). I tried a basic macro, but that was a Push to start only or a push toggle on then again to toggle off.

Here is an example what I am trying to achieve. The left controller I will have on screen and same for mouse. As I depress buttons, they will turn red.

example.gif


Like this
Untitled2.png


Then revert to unilluminated state once the button is released.
 

Attachments

  • example.jpg
    example.jpg
    239 KB · Views: 7

Akinraze

New Member
Grok is the best. I asked it to rewrite that Python script to accommodate 27 buttons and within 20 seconds I had what I was looking for. I just had to troubleshoot a few minutes to determine how to resolve some conflict issues, ask Grok to adjust the script and now I am set!

Here is the new Python script for anyone hung-up on one button. If you need more, ask Grok to rewrite it for you and mention how many you need it to be.

Python:
import obspython as obs
import ntpath

NUM_BUTTONS = 27

# Per-button configuration
button_sources = [None] * NUM_BUTTONS        # Source name for each button
button_inverts = [False] * NUM_BUTTONS       # Invert flag per button
hotkey_ids = [obs.OBS_INVALID_HOTKEY_ID] * NUM_BUTTONS
hotkey_names = [""] * NUM_BUTTONS

# Global state for reference counting
active_counts = {}       # source_name -> int: number of pressed hotkeys affecting it
target_visibility = {}   # source_name -> bool: desired visibility when count > 0
rest_visibility = {}     # source_name -> bool: desired visibility when count == 0


def script_description():
    return "<b>Push to Enable - 27 Buttons (with Reference Counting)</b>\n\n" \
           "Each hotkey enables (or disables if inverted) its assigned source while held.\n" \
           "Multiple hotkeys can control the same source — it stays active as long as " \
           "at least one assigned hotkey is pressed.\n\n" \
           "Settings can be changed without interrupting active hotkeys."


def script_load(settings):
    print("--- " + ntpath.basename(__file__) + " loaded ---")

    for i in range(NUM_BUTTONS):
        hk_name = f"push_to_enable_button_{i+1}"
        hk_desc = f"Push to Enable Button {i+1}"
        hotkey_names[i] = hk_name

        hotkey_ids[i] = obs.obs_hotkey_register_frontend(
            hk_name, hk_desc,
            lambda pressed, idx=i: hotkey_callback(pressed, idx)
        )

        saved_array = obs.obs_data_get_array(settings, hk_name)
        if saved_array is not None:
            obs.obs_hotkey_load(hotkey_ids[i], saved_array)
            obs.obs_data_array_release(saved_array)


def script_save(settings):
    for i in range(NUM_BUTTONS):
        save_array = obs.obs_hotkey_save(hotkey_ids[i])
        obs.obs_data_set_array(settings, hotkey_names[i], save_array)
        obs.obs_data_array_release(save_array)


def script_properties():
    props = obs.obs_properties_create()

    for i in range(NUM_BUTTONS):
        # Source dropdown
        list_prop = obs.obs_properties_add_list(
            props, f"source_{i}", f"Button {i+1} Source",
            obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_STRING
        )
        obs.obs_property_list_add_string(list_prop, "(none)", "")

        sources_list = obs.obs_enum_sources()
        if sources_list:
            for src in sources_list:
                name = obs.obs_source_get_name(src)
                obs.obs_property_list_add_string(list_prop, name, name)
            obs.source_list_release(sources_list)

        # Invert checkbox
        obs.obs_properties_add_bool(props, f"invert_{i}", f"Invert Button {i+1} (hide while pressed)")

    return props


def script_update(settings):
    global button_sources, button_inverts
    global active_counts, target_visibility, rest_visibility

    # Read new configuration
    new_sources = []
    new_inverts = []
    for i in range(NUM_BUTTONS):
        src_name = obs.obs_data_get_string(settings, f"source_{i}")
        src_name = None if src_name == "" or src_name == "(none)" else src_name
        new_sources.append(src_name)
        new_inverts.append(obs.obs_data_get_bool(settings, f"invert_{i}"))

    # Track old sources for cleanup
    old_sources = set(active_counts.keys())

    # Update button config
    button_sources = new_sources
    button_inverts = new_inverts

    # Rebuild visibility mappings
    target_visibility.clear()
    rest_visibility.clear()

    for i in range(NUM_BUTTONS):
        src = button_sources[i]
        if src is None:
            continue
        invert = button_inverts[i]
        target_visibility[src] = not invert   # Visible when active (normal), hidden if inverted
        rest_visibility[src] = invert         # Hidden at rest (normal), visible if inverted

    # Update active_counts for currently assigned sources
    current_sources = set(target_visibility.keys())
    for src in current_sources:
        if src not in active_counts:
            active_counts[src] = 0  # New source, start at 0

    # Clean up sources no longer assigned to any button
    removed_sources = old_sources - current_sources
    for src in removed_sources:
        # If count is already 0, force rest state (safe to hide)
        if active_counts[src] == 0:
            set_source_visibility(src, False)
        # If count > 0, leave it alone — some hotkey is still conceptually held
        del active_counts[src]

    # IMPORTANT: Do NOT force visibility changes on currently assigned sources
    # This preserves visibility when holding hotkeys while changing settings


def hotkey_callback(pressed, idx):
    src_name = button_sources[idx]
    if src_name is None:
        return

    # Ensure source is in our tracking dicts (in case config changed mid-use)
    if src_name not in active_counts:
        active_counts[src_name] = 0
        # Use current button's invert setting as fallback
        target_visibility[src_name] = not button_inverts[idx]
        rest_visibility[src_name] = button_inverts[idx]

    if pressed:
        prev_count = active_counts[src_name]
        active_counts[src_name] += 1
        # Only change visibility if transitioning from 0 to 1
        if prev_count == 0:
            set_source_visibility(src_name, target_visibility.get(src_name, False))
    else:
        if active_counts[src_name] > 0:
            active_counts[src_name] -= 1
        # Only change visibility if dropping to 0
        if active_counts[src_name] == 0:
            set_source_visibility(src_name, rest_visibility.get(src_name, False))


def set_source_visibility(source_name, visible):
    if source_name is None:
        return

    scene_sources = obs.obs_frontend_get_scenes()
    if scene_sources is None:
        return

    for scn_src in scene_sources:
        scene = obs.obs_scene_from_source(scn_src)
        items = obs.obs_scene_enum_items(scene)
        if items:
            for item in items:
                item_src = obs.obs_sceneitem_get_source(item)
                if obs.obs_source_get_name(item_src) == source_name:
                    if obs.obs_sceneitem_visible(item) != visible:
                        obs.obs_sceneitem_set_visible(item, visible)
            obs.sceneitem_list_release(items)
    obs.source_list_release(scene_sources)
 

Warmuptill

Active Member
Is Advanced Scene Switcher capable of doing what this guy has (<--- Link) in the bottom left corner of his streams? I looked for a Push To Talk type plugin that can manage multiple button presses simultaneously and the only one I found (<--- Link) requires Python coding (which is way over my head).

I tried the built in hotkey feature and that only enabled the source (would required two hotkeys to then turn off). I tried a basic macro, but that was a Push to start only or a push toggle on then again to toggle off.

Here is an example what I am trying to achieve. The left controller I will have on screen and same for mouse. As I depress buttons, they will turn red.

View attachment 117279

Like this
View attachment 117283

Then revert to unilluminated state once the button is released.
In case you still need it a "push to show" style macro can be set up like this:
1765993824748.png

It translates to:
If the hotkey with the name "Push to show" is pressed show the source named "Browser" on the current scene, else hide it.
 

Akinraze

New Member
In case you still need it a "push to show" style macro can be set up like this:
View attachment 117287
It translates to:
If the hotkey with the name "Push to show" is pressed show the source named "Browser" on the current scene, else hide it.
I needed 30 and couldn't figure out how to do that without the Python Plugin (Which I got working). Thanks for following up. I do appreciate it!
 
Top