209 lines
7.2 KiB
Python
209 lines
7.2 KiB
Python
import obspython as obs
|
|
import random
|
|
|
|
|
|
# Internal variables
|
|
direction_x = random.choice([-1, 1])
|
|
direction_y = random.choice([-1, 1])
|
|
|
|
# Initialize global position
|
|
position_x = 1920/2
|
|
position_y = 1080/2
|
|
|
|
# Global variables holding the values of data settings / properties
|
|
source_name = "Spaceship" # Name of the source to bounce
|
|
speed_x = 5.0 # Speed of movement in the X direction
|
|
speed_y = 3.0 # Speed of movement in the Y direction
|
|
|
|
# Called on script load
|
|
def script_load(settings):
|
|
global position_x, position_y
|
|
source = obs.obs_get_source_by_name(source_name)
|
|
if source is not None:
|
|
scene_item = get_scene_item_from_source(source)
|
|
if scene_item is not None:
|
|
pos = obs.vec2()
|
|
obs.obs_sceneitem_get_pos(scene_item, pos)
|
|
position_x = pos.x
|
|
position_y = pos.y
|
|
obs.obs_source_release(source)
|
|
|
|
# Set up timer
|
|
#obs.timer_add(update_position, 16) # Around 60 FPS
|
|
|
|
# Function to get scene item
|
|
def get_scene_item_from_source(source):
|
|
current_scene = obs.obs_frontend_get_current_scene()
|
|
scene = obs.obs_scene_from_source(current_scene)
|
|
obs.obs_source_release(current_scene)
|
|
|
|
scene_item = obs.obs_scene_find_source(scene, source_name)
|
|
return scene_item
|
|
|
|
|
|
# Function to update position
|
|
def update_position():
|
|
global position_x, position_y, direction_x, direction_y
|
|
|
|
source = obs.obs_get_source_by_name(source_name)
|
|
if source is None:
|
|
return
|
|
|
|
scene_item = get_scene_item_from_source(source)
|
|
if scene_item is None:
|
|
obs.obs_source_release(source)
|
|
return
|
|
|
|
# Get canvas size
|
|
source_crop = obs.obs_sceneitem_crop()
|
|
obs.obs_sceneitem_get_crop(scene_item,source_crop)
|
|
source_transform = obs.obs_transform_info()
|
|
obs.obs_sceneitem_get_info(scene_item, source_transform)
|
|
print(source_transform.alignment)
|
|
width = (obs.obs_source_get_width(source) - source_crop.left - source_crop.right) * source_transform.scale.x
|
|
height = (obs.obs_source_get_height(source) - source_crop.top - source_crop.bottom) * source_transform.scale.y
|
|
#print(width, height)
|
|
canvas_width = 1920
|
|
canvas_height = 1080
|
|
#print(width, height, canvas_width, canvas_height)
|
|
# Calculate new position
|
|
position_x += direction_x * speed_x
|
|
position_y += direction_y * speed_y
|
|
alignment = source_transform.alignment
|
|
#print(position_x, position_y)
|
|
#Alignment map top_left:5,top_center:4, top_right:6,center_left:1,center: 0, center_right: 2, bottom_left: 9, bottom_center: 8, bottom_right: 10
|
|
# Calculate position offsets based on alignment
|
|
if alignment == 5: # Top Left
|
|
position_x_offset = 0
|
|
position_y_offset = 0
|
|
elif alignment == 4: # Top Center
|
|
position_x_offset = width / 2
|
|
position_y_offset = 0
|
|
elif alignment == 6: # Top Right
|
|
position_x_offset = width
|
|
position_y_offset = 0
|
|
elif alignment == 1: # Center Left
|
|
position_x_offset = 0
|
|
position_y_offset = height / 2
|
|
elif alignment == 0: # Center
|
|
position_x_offset = width / 2
|
|
position_y_offset = height / 2
|
|
elif alignment == 2: # Center Right
|
|
position_x_offset = width
|
|
position_y_offset = height / 2
|
|
elif alignment == 9: # Bottom Left
|
|
position_x_offset = 0
|
|
position_y_offset = height
|
|
elif alignment == 8: # Bottom Center
|
|
position_x_offset = width / 2
|
|
position_y_offset = height
|
|
elif alignment == 10: # Bottom Right
|
|
position_x_offset = width
|
|
position_y_offset = height
|
|
else: # Default to top left if alignment is unknown
|
|
position_x_offset = 0
|
|
position_y_offset = 0
|
|
|
|
# Bounce off edges
|
|
if position_x - position_x_offset <= 0 or position_x + width - position_x_offset >= canvas_width:
|
|
print(
|
|
f"Bounce off left/right: {position_x} | {position_x+width} | {canvas_width} | {direction_x}")
|
|
direction_x *= -1
|
|
if position_y - position_y_offset <= 0 or position_y + height - position_y_offset >= canvas_height:
|
|
print(
|
|
f"Bounce off top/bottom: {position_y} | {position_y+height} | {canvas_height} | {direction_y}")
|
|
direction_y *= -1
|
|
|
|
# Apply new position
|
|
pos = obs.vec2()
|
|
pos.x = position_x
|
|
pos.y = position_y
|
|
obs.obs_sceneitem_set_pos(scene_item, pos)
|
|
|
|
obs.obs_source_release(source)
|
|
|
|
# Called to set default values of data settings
|
|
def script_defaults(settings):
|
|
obs.obs_data_set_default_string(settings, "source_name", "")
|
|
obs.obs_data_set_default_double(settings, "speed", 2)
|
|
|
|
# Fills the given list property object with the names of all sources plus an empty one
|
|
def populate_list_property_with_source_names(list_property):
|
|
sources = obs.obs_enum_sources()
|
|
obs.obs_property_list_clear(list_property)
|
|
obs.obs_property_list_add_string(list_property, "", "")
|
|
for source in sources:
|
|
name = obs.obs_source_get_name(source)
|
|
obs.obs_property_list_add_string(list_property, name, name)
|
|
obs.source_list_release(sources)
|
|
|
|
|
|
# Called to display the properties GUI
|
|
def script_properties():
|
|
props = obs.obs_properties_create()
|
|
|
|
# Drop-down list of sources
|
|
list_property = obs.obs_properties_add_list(props, "source_name", "Source name",
|
|
obs.OBS_COMBO_TYPE_LIST, obs.OBS_COMBO_FORMAT_STRING)
|
|
populate_list_property_with_source_names(list_property)
|
|
# obs.obs_properties_add_text(props, "source_name", "Source name", obs.OBS_TEXT_DEFAULT)
|
|
|
|
# Button to refresh the drop-down list
|
|
obs.obs_properties_add_button(props, "button", "Refresh list of sources",
|
|
lambda props, prop: True if populate_list_property_with_source_names(list_property) else True)
|
|
|
|
obs.obs_properties_add_float_slider(
|
|
props, "speed_x", "Speed in X direction", 0.1, 20, 0.1)
|
|
obs.obs_properties_add_float_slider(
|
|
props, "speed_y", "Speed in Y direction", 0.1, 20, 0.1)
|
|
return props
|
|
|
|
# Called after change of settings including once after script load
|
|
|
|
|
|
def script_update(settings):
|
|
global source_name, speed_x, speed_y
|
|
source_name = obs.obs_data_get_string(settings, "source_name")
|
|
speed_x = obs.obs_data_get_double(settings, "speed_x")
|
|
speed_y = obs.obs_data_get_double(settings, "speed_y")
|
|
|
|
|
|
# Global animation activity flag
|
|
is_active = False
|
|
|
|
# Called every frame
|
|
def script_tick(seconds):
|
|
if is_active:
|
|
update_position()
|
|
|
|
# Callback for the hotkey
|
|
def on_dvd_hotkey(pressed):
|
|
global is_active
|
|
if pressed and not is_active:
|
|
is_active = True
|
|
elif pressed and is_active:
|
|
is_active = False
|
|
|
|
|
|
# Identifier of the hotkey set by OBS
|
|
hotkey_id = obs.OBS_INVALID_HOTKEY_ID
|
|
|
|
# Called at script load
|
|
def script_load(settings):
|
|
global hotkey_id
|
|
hotkey_id = obs.obs_hotkey_register_frontend(
|
|
script_path(), "Source DVD", on_dvd_hotkey)
|
|
hotkey_save_array = obs.obs_data_get_array(settings, "dvd_hotkey")
|
|
obs.obs_hotkey_load(hotkey_id, hotkey_save_array)
|
|
obs.obs_data_array_release(hotkey_save_array)
|
|
|
|
# Called before data settings are saved
|
|
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, "dvd_hotkey", hotkey_save_array)
|
|
obs.obs_data_array_release(hotkey_save_array)
|