import obspython as obs import random # Internal variables direction_x = random.choice([-1, 1]) direction_y = random.choice([-1, 1]) video = obs.obs_video_info() obs.obs_get_video_info(video) print(video.base_height, video.base_width) # Initialize global position position_x = video.base_width/2 position_y = video.base_height/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, video 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 = video.base_width canvas_height = video.base_height #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)