Created
January 1, 2023 19:41
-
-
Save Dramacydal/8804c7d2cc48575169beda18e3de7773 to your computer and use it in GitHub Desktop.
obs script to update scene items positions with actual window positions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import obspython as obs | |
import re | |
import win32gui | |
import win32api | |
# Global variables holding the values of data settings / properties | |
update_frequency = 50 # Update frequency in msec | |
# Global animation activity flag | |
is_active = True | |
# Identifier of the hotkey set by OBS | |
hotkey_id = obs.OBS_INVALID_HOTKEY_ID | |
def walk_scene_items_in_current_source(walker): | |
current_scene_as_source = obs.obs_frontend_get_current_scene() | |
if not current_scene_as_source: | |
return | |
current_scene = obs.obs_scene_from_source(current_scene_as_source) | |
items = obs.obs_scene_enum_items(current_scene) | |
for i, s in enumerate(items): | |
walker(s, items) | |
obs.sceneitem_list_release(items) | |
obs.obs_source_release(current_scene_as_source) | |
# Called at script load | |
def script_load(settings): | |
# global hotkey_id | |
# hotkey_id = obs.obs_hotkey_register_frontend(script_path(), "Source Shake", on_shake_hotkey) | |
# hotkey_save_array = obs.obs_data_get_array(settings, "shake_hotkey") | |
# obs.obs_hotkey_load(hotkey_id, hotkey_save_array) | |
# obs.obs_data_array_release(hotkey_save_array) | |
return | |
def script_save(settings): | |
obs.obs_save_sources() | |
# Hotkey save | |
# hotkey_save_array = obs.obs_hotkey_save(hotkey_id) | |
# obs.obs_data_set_array(settings, "shake_hotkey", hotkey_save_array) | |
# obs.obs_data_array_release(hotkey_save_array) | |
def script_unload(): | |
return | |
def script_description(): | |
return """Source Shake!! | |
Shake a source in the current scene when a hotkey is pressed. Go to Settings | |
then Hotkeys to select the key combination.Check the | |
Source Shake Scripting Tutorial on the OBS Wiki for more information.""" | |
def sync_scene_item(scene_item, scene_items): | |
hwndMain = get_scene_item_hwnd(scene_item) | |
if not hwndMain: | |
return | |
order = obs.obs_sceneitem_get_order_position(scene_item) | |
is_visible = obs.obs_sceneitem_visible(scene_item) | |
if win32gui.IsIconic(hwndMain): | |
if is_visible: | |
obs.obs_sceneitem_set_visible(scene_item, False) | |
return | |
else: | |
if not is_visible: | |
obs.obs_sceneitem_set_visible(scene_item, True) | |
if win32gui.GetForegroundWindow() == hwndMain: | |
if (order != len(scene_items)): | |
obs.obs_sceneitem_set_order_position(scene_item, len(scene_items)) | |
# print(hwndMain) | |
sync_scene_item_pos(scene_item, hwndMain) | |
return | |
def sync_scene_items(): | |
walk_scene_items_in_current_source(sync_scene_item) | |
def get_scene_item_hwnd(scene_item): | |
source = obs.obs_sceneitem_get_source(scene_item) | |
settings = obs.obs_source_get_settings(source) | |
window = obs.obs_data_get_string(settings, 'window') | |
obs.obs_data_release(settings) | |
windowParts = window.split(":") | |
windowClassName = unescape_window_name(windowParts[1]) | |
windowName = unescape_window_name(windowParts[0]) | |
return win32gui.FindWindow(windowClassName, windowName) | |
def sync_scene_item_pos(sceneitem, hwnd): | |
if not hwnd: | |
return | |
rect = win32gui.GetWindowRect(hwnd) | |
# print(rect) | |
hMonitor = win32api.MonitorFromWindow(hwnd, 0) | |
if not hMonitor: | |
return | |
monitorInfo = win32api.GetMonitorInfo(hMonitor) | |
if not monitorInfo: | |
return | |
newPos = obs.vec2() | |
oldPos = obs.vec2() | |
newPos.x = rect[0] - monitorInfo['Monitor'][0] | |
newPos.y = rect[1] - monitorInfo['Monitor'][1] | |
obs.obs_sceneitem_get_pos(sceneitem, oldPos) | |
if oldPos.x != newPos.x or oldPos.y != newPos.y: | |
obs.obs_sceneitem_set_pos(sceneitem, newPos) | |
def unescape_window_name(str): | |
def repl(m): | |
# print(m.group(1)) | |
ch = chr(int(m.group(1), 16)) | |
return ch | |
return re.sub('#([A-Z0-9]{2})', repl, str) | |
total_seconds = 0.0 | |
# Called every frame | |
def script_tick(seconds): | |
global total_seconds, update_frequency | |
total_seconds += seconds | |
if total_seconds < update_frequency / 1000.0: | |
return | |
total_seconds = 0.0 | |
sync_scene_items() | |
# Callback for the hotkey | |
def on_shake_hotkey(pressed): | |
global is_active | |
is_active = pressed | |
# Called to set default values of data settings | |
def script_defaults(settings): | |
obs.obs_data_set_default_double(settings, "update_frequency", 50.0) | |
# Called to display the properties GUI | |
def script_properties(): | |
props = obs.obs_properties_create() | |
obs.obs_properties_add_float_slider(props, "update_frequency", "Update frequency", 20, 1000, 10) | |
return props | |
# Called after change of settings including once after script load | |
def script_update(settings): | |
global update_frequency | |
update_frequency = obs.obs_data_get_double(settings, "update_frequency") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment