def getTransformationList(sceneitems): transformations = [] for sceneitem in sceneitems: pos = obs.vec2() obs.obs_sceneitem_get_pos(sceneitem, pos) rot = obs.obs_sceneitem_get_rot(sceneitem) scale = obs.vec2() obs.obs_sceneitem_get_scale(sceneitem, scale) alignment = obs.obs_sceneitem_get_alignment(sceneitem) bounds = obs.vec2() obs.obs_sceneitem_get_bounds(sceneitem, bounds) boundsType = obs.obs_sceneitem_get_bounds_type(sceneitem) boundsAlignment = obs.obs_sceneitem_get_bounds_alignment(sceneitem) crop = obs.obs_sceneitem_crop() obs.obs_sceneitem_get_crop(sceneitem, crop) transformations.append({ "pos": [pos.x, pos.y], "rot": rot, "scale": [scale.x, scale.y], "alignment": alignment, "bounds": [bounds.x, bounds.y], "boundsType": boundsType, "boundsAlignment": boundsAlignment, "crop": [crop.left, crop.right, crop.top, crop.bottom] }) obs.obs_sceneitem_release(sceneitem) return transformations
def SetDestinationPositionAndSize(props, p): global Animations # Base the index off of the name since callbacks don't work well. name = obs.obs_property_name(p) indexStr = re.sub("[^0-9]", "", name) animationIndex = int(indexStr) scene_item = getSceneItem() posV = obs.vec2() scaleV = obs.vec2() obs.obs_sceneitem_get_pos(scene_item, posV) obs.obs_sceneitem_get_scale(scene_item, scaleV) width, height = calculateSize(scene_item, scaleV.x, scaleV.y) Animations[animationIndex].destinationX = posV.x Animations[animationIndex].destinationY = posV.y Animations[animationIndex].destinationWidth = width Animations[animationIndex].destinationHeight = height obs.obs_data_set_int(settings, Animations[animationIndex].destinationXStorage, (int)(Animations[animationIndex].destinationX)) obs.obs_data_set_int(settings, Animations[animationIndex].destinationYStorage, (int)(Animations[animationIndex].destinationY)) obs.obs_data_set_int(settings, Animations[animationIndex].destinationWidthStorage, (int)(Animations[animationIndex].destinationWidth)) obs.obs_data_set_int(settings, Animations[animationIndex].destinationHeightStorage, (int)(Animations[animationIndex].destinationHeight))
def updateSettings(self, settings): """ Update the settings with the given obs_data_t settings object. """ # Update the owl source name newOwlName = obs.obs_data_get_string(settings, PROP_ID_OWL_SOURCE) if self.owlSourceName != newOwlName: for item in self.iterSceneItemsByName(newOwlName): pos = obs.vec2() obs.obs_sceneitem_get_pos(item, pos) self.owlBaseY = pos.y break self.owlSourceName = newOwlName # Update the label and counter source names self.labelSourceName = obs.obs_data_get_string(settings, PROP_ID_LABEL_SOURCE) newCounterSourceName = obs.obs_data_get_string(settings, PROP_ID_COUNTER_SOURCE) if self.counterSourceName != newCounterSourceName: with getSourceByName(newCounterSourceName) as source: if source is not None: with getSourceSettings(source) as settings: text = obs.obs_data_get_string(settings, 'text') try: self.textColor, self.outlineColor = \ colorsForNum(int(text)) self.setSourceTextColorByName( newCounterSourceName, self.textColor, self.outlineColor) except ValueError: pass self.counterSourceName = newCounterSourceName # Update the ding source names self.ding1SourceName = obs.obs_data_get_string(settings, PROP_ID_DING1_SOURCE) self.ding10SourceName = obs.obs_data_get_string( settings, PROP_ID_DING10_SOURCE) self.ding50SourceName = obs.obs_data_get_string( settings, PROP_ID_DING50_SOURCE) # Update the owl Y position and movement distance self.owlBaseX = obs.obs_data_get_double(settings, PROP_ID_OWL_X_POS) self.owlBaseY = obs.obs_data_get_double(settings, PROP_ID_OWL_Y_POS) self.owlXDistance = obs.obs_data_get_double(settings, PROP_ID_OWL_X_DISTANCE) self.owlYDistance = obs.obs_data_get_double(settings, PROP_ID_OWL_Y_DISTANCE)
def setSourcePosByName(self, sourceName, x=None, y=None): """ Set the position of the given source by name. If either coordinate is None, that coordinate will not be modified. """ if x == y == None: return for item in self.iterSceneItemsByName(sourceName): pos = obs.vec2() obs.obs_sceneitem_get_pos(item, pos) if x is not None: pos.x = x if y is not None: pos.y = y obs.obs_sceneitem_set_pos(item, pos)
def move_text_source(self): current_scene = obs.obs_frontend_get_current_scene() source = obs.obs_get_source_by_name("test_py") scene = obs.obs_scene_from_source(current_scene) scene_item = obs.obs_scene_find_source(scene, "test_py") if scene_item: dx, dy = 10, 10 print("old values", self.location.x) obs.obs_sceneitem_get_pos( scene_item, self.location ) # update to last position if its changed from OBS self.location.x += dx self.location.y += dy print("new values", self.location.x) obs.obs_sceneitem_set_pos(scene_item, self.location) obs.obs_scene_release(scene) obs.obs_source_release(source)
def update_position(): global source_name global counter source = obs.obs_frontend_get_current_scene() if source is not None: scene_object = obs.obs_scene_from_source(source) scene_item = obs.obs_scene_find_source(scene_object, source_name) pos = obs.vec2() obs.obs_sceneitem_get_pos(scene_item, pos) next_pos = obs.vec2() next_pos.x = pos.x y_adjust = math.sin(math.radians(counter)) next_pos.y = pos.y + y_adjust / 4 counter += 0.5 if counter == 360: counter = 0 obs.obs_sceneitem_set_pos(scene_item, next_pos) obs.obs_source_release(source)
def InitializeSource(animation, positionSpecified, sizeSpecified): #scene_item = None global source_name scene_item = getSceneItem() #scene_item = findSceneItem(source_name) print("InitializeSource::scene_item: %s" % (scene_item)) if scene_item != None: posV = obs.vec2() scaleV = obs.vec2() obs.obs_sceneitem_get_pos(scene_item, posV) obs.obs_sceneitem_get_scale(scene_item, scaleV) Source.scale.x = scaleV.x Source.scale.y = scaleV.y width, height = calculateSize(scene_item, Source.scale.x, Source.scale.y) Source.pos = posV Source.size.x = width Source.size.y = height Source.posSpeed = animation.posSpeed if positionSpecified: Source.targetPos.x = animation.destinationX Source.targetPos.y = animation.destinationY else: Source.targetPos.x = posV.x Source.targetPos.y = posV.y if sizeSpecified: Source.targetSize.x = animation.destinationWidth Source.targetSize.y = animation.destinationHeight scaleV.x, scaleV.y = calculateNewScale(scene_item, Source.targetSize.x, Source.targetSize.y) Source.targetScale.x = scaleV.x Source.targetScale.y = scaleV.y else: Source.targetSize.x = Source.size.x Source.targetSize.y = Source.size.y Source.targetScale.x = Source.scale.x Source.targetScale.y = Source.scale.y
def dumpSceneData(): scene = obs.obs_frontend_get_current_scene() sceneObject = obs.obs_scene_from_source(scene) items = obs.obs_scene_enum_items(sceneObject) itemArray = [] for item in items: sceneItem = obs.obs_sceneitem_get_source(item) name = obs.obs_source_get_name(sceneItem) if "tweentool:" not in name: pos = obs.vec2() obs.obs_sceneitem_get_pos(item, pos) rot = obs.obs_sceneitem_get_rot(item) scale = obs.vec2() obs.obs_sceneitem_get_scale(item, scale) alignment = obs.obs_sceneitem_get_alignment(item) bounds = obs.vec2() obs.obs_sceneitem_get_bounds(item, bounds) boundsType = obs.obs_sceneitem_get_bounds_type(item) boundsAlignment = obs.obs_sceneitem_get_bounds_alignment(item) crop = obs.obs_sceneitem_crop() obs.obs_sceneitem_get_crop(item, crop) itemArray.append({ "name": name, "pos": [pos.x, pos.y], "rot": rot, "scale": [scale.x, scale.y], "alignment": alignment, "bounds": [bounds.x, bounds.y], "boundsType": boundsType, "boundsAlignment": boundsAlignment, "crop": [crop.left, crop.right, crop.top, crop.bottom] }) return itemArray
def _obs_sceneitem_get_pos(self, scene_name, source_name): with self._sceneitem_by_name(scene_name, source_name) as si: p = _obs.vec2() _obs.obs_sceneitem_get_pos(si, p) return p.x, p.y
def tremor_effect(self): flag = next(self.position_swap) if flag: self.update_text(self.scripted_text) current_scene = obs.obs_frontend_get_current_scene() with source_ar(self.source_name) as source, scene_ar( current_scene) as scene: scene_item = obs.obs_scene_find_source(scene, self.source_name) pos = obs.vec2() self.location = pos obs.obs_sceneitem_get_pos( scene_item, self.location ) # update to last position if its changed from OBS if not self.last_jump_x == 0: if self.last_jump_x < 0: # minus minus self.location.x -= self.last_jump_x if self.last_jump_x > 0: self.location.x -= self.last_jump_x if not self.last_jump_y == 0: if self.last_jump_y < 0: self.location.y -= self.last_jump_y if self.last_jump_y > 0: self.location.y -= self.last_jump_y if scene_item: obs.obs_sceneitem_set_pos(scene_item, self.location) else: self.update_text(self.scripted_text) current_scene = obs.obs_frontend_get_current_scene() with source_ar(self.source_name) as source, scene_ar( current_scene) as scene: scene_item = obs.obs_scene_find_source(scene, self.source_name) pos = obs.vec2() self.location = pos obs.obs_sceneitem_get_pos( scene_item, self.location ) # update to last position if its changed from OBS if scene_item: # finish early , and set to default if self.duration // self.refresh_rate <= 3: self.duration = 0 obs.obs_sceneitem_set_pos(scene_item, self.location) else: next_pos = obs.vec2() withoutzero = list(range(-101, 0)) + list(range( 1, 101)) self.last_jump_x = choice(withoutzero) self.last_jump_y = choice(withoutzero) dx, dy = self.last_jump_x, self.last_jump_y next_pos.x, next_pos.y = ( self.location.x + dx, self.location.y + dy, ) obs.obs_sceneitem_set_pos(scene_item, next_pos)
def sad_threaded(props, prop): # 1. Make it grayscale cam_source = obs.obs_get_source_by_name("Shitty Webcam") grayscale_filter = obs.obs_source_get_filter_by_name(cam_source, "Gray") data = obs.obs_data_create() obs.obs_data_set_double(data, "clut_amount", 1.0) obs.obs_source_update(grayscale_filter, data) # 2. Save initial props current_scene_source = obs.obs_frontend_get_current_scene() obs.obs_frontend_set_current_preview_scene(current_scene_source) current_scene = obs.obs_scene_from_source(current_scene_source) cam_sceneitem = obs.obs_scene_find_source(current_scene, "Shitty Webcam") initial_scale = obs.vec2() obs.obs_sceneitem_get_scale(cam_sceneitem, initial_scale) initial_pos = obs.vec2() obs.obs_sceneitem_get_pos(cam_sceneitem, initial_pos) initial_box_transform = obs.matrix4() obs.obs_sceneitem_get_box_transform(cam_sceneitem, initial_box_transform) initial_crop = obs.obs_sceneitem_crop() obs.obs_sceneitem_get_crop(cam_sceneitem, initial_crop) # matrix4.x.x -> x size # matrix4.y.y -> y size # matrix4.t.x -> x position # matrix4.t.y -> y position # for prop in ["x", "y", "z", "t"]: # print(f"Matrix property {prop}") # vec = getattr(initial_box_transform, prop) # print(dir(vec)) # for vec_prop in ["m", "w", "x", "y", "z"]: # print(f"Vec Property {vec_prop}: {getattr(vec, vec_prop)}") size_x = initial_box_transform.x.x size_y = initial_box_transform.y.y initial_draw_transform = obs.matrix4() obs.obs_sceneitem_get_draw_transform(cam_sceneitem, initial_draw_transform) print(dir(initial_draw_transform)) # 3. Mute desktop audio, play sound of silence desktop_audio = obs.obs_get_output_source(4) obs.obs_source_set_muted(desktop_audio, True) song = obs.obs_source_create("ffmpeg_source", "Sound of Silence", None, None) song_settings = obs.obs_data_create() obs.obs_data_set_string( song_settings, "local_file", "C:\\Users\\avikn\\Downloads\\sound_of_silence.mp3") obs.obs_source_update(song, song_settings) obs.obs_data_release(song_settings) song_item = obs.obs_scene_add(current_scene, song) # 4. Scale up / reposition the camera. # It's gross but it works don't touch it. dynamic_scale = obs.vec2() obs.vec2_copy(dynamic_scale, initial_scale) increment = obs.vec2() increment.x = 0.0015 increment.y = 0.0015 crop = (initial_crop.top, initial_crop.right, initial_crop.bottom, initial_crop.left) size_x, size_y = get_size(cam_sceneitem) dynamic_crop = obs.obs_sceneitem_crop() bounds = obs.vec2() bounds.x = size_x bounds.y = size_y obs.obs_sceneitem_set_bounds(cam_sceneitem, bounds) for _ in range(240): obs.obs_sceneitem_set_bounds_type(cam_sceneitem, 0) obs.vec2_add(dynamic_scale, dynamic_scale, increment) obs.obs_sceneitem_set_scale(cam_sceneitem, dynamic_scale) nsize_x, nsize_y = get_size(cam_sceneitem) x_delta = nsize_x - size_x + (dynamic_crop.right * 2) y_delta = nsize_y - size_y + (dynamic_crop.top * 2) dynamic_crop.top = int(y_delta / 2) dynamic_crop.right = int(x_delta / 2) dynamic_crop.bottom = int(y_delta / 2) dynamic_crop.left = int(x_delta / 2) obs.obs_sceneitem_set_crop(cam_sceneitem, dynamic_crop) obs.obs_sceneitem_set_bounds_type(cam_sceneitem, 1) obs.obs_frontend_preview_program_trigger_transition() time.sleep(0.1) # 5. Cleanup obs.obs_source_set_muted(desktop_audio, False) obs.obs_sceneitem_set_scale(cam_sceneitem, initial_scale) obs.obs_sceneitem_set_crop(cam_sceneitem, initial_crop) obs.obs_data_set_double(data, "clut_amount", 0.0) obs.obs_source_update(grayscale_filter, data) obs.obs_sceneitem_remove(song_item) obs.obs_source_release(song) time.sleep(0.1) obs.obs_frontend_preview_program_trigger_transition()
def adjustCameraTick(): global source_name global source_pos global UpdatesPerSecond global scene_item # Do not control any aspect of the source if no animation is currently playing or if the server is not connected. if (not Source.processingAnimation) or ( not Server.run) or scene_item is None: return #scene_item = findSceneItem(source_name) # Only make adjustments if our server is currently running. #print("adjustCameraTick::scene_item: %s" % (scene_item)) posV = obs.vec2() scaleV = obs.vec2() obs.obs_sceneitem_get_pos(scene_item, posV) obs.obs_sceneitem_get_scale(scene_item, scaleV) width, height = calculateSize(scene_item, Source.scale.x, Source.scale.y) Source.pos = posV Source.size.x = width Source.size.y = height if Source.pos.x != Source.targetPos.x: fractionX = (float(Source.forceX) / float(UpdatesPerSecond)) + Source.posRemainder.x integerX = int(math.floor(fractionX)) Source.posRemainder.x = fractionX - integerX Source.pos.x += integerX if (integerX > 0 and Source.pos.x > Source.targetPos.x) or ( integerX < 0 and Source.pos.x < Source.targetPos.x): Source.pos.x = Source.targetPos.x if Source.pos.y != Source.targetPos.y: fractionY = (Source.forceY / UpdatesPerSecond) + Source.posRemainder.y integerY = int(math.floor(fractionY)) Source.posRemainder.y = fractionY - integerY Source.pos.y += integerY if (integerY > 0 and Source.pos.y > Source.targetPos.y) or ( integerY < 0 and Source.pos.y < Source.targetPos.y): Source.pos.y = Source.targetPos.y if Source.scale.x != Source.targetScale.x: fractionX = (float(Source.forceW) / float(UpdatesPerSecond)) Source.scale.x += fractionX if (fractionX > 0 and Source.scale.x > Source.targetScale.x) or ( fractionX < 0 and Source.scale.x < Source.targetScale.x): Source.scale.x = Source.targetScale.x if Source.scale.y != Source.targetScale.y: fractionY = (float(Source.forceH) / float(UpdatesPerSecond)) Source.scale.y += fractionY if (fractionY > 0 and Source.scale.y > Source.targetScale.y) or ( fractionY < 0 and Source.scale.y < Source.targetScale.y): Source.scale.y = Source.targetScale.y if Source.pos.x == Source.targetPos.x and Source.pos.y == Source.targetPos.y and Source.scale.x == Source.targetScale.x and Source.scale.y == Source.targetScale.y: Source.processingAnimation = False # Update the position and size of the source based on speed/ obs.obs_sceneitem_set_pos(scene_item, Source.pos) obs.obs_sceneitem_set_scale(scene_item, Source.scale)