obs-powershell.types.ps1xml
<?xml version="1.0" encoding="utf-16"?> <!-- Generated with EZOut 2.0.6: Install-Module EZOut or https://github.com/StartAutomating/EZOut --> <Types> <Type> <Name>OBS.Beat</Name> <Members> <ScriptMethod> <Name>TapBPM</Name> <Script> <# .SYNOPSIS Tap BPM .DESCRIPTION Tap out a BPM by pressing ENTER on N beats. The BPM will be set to the average time between taps, and the beat will be started. #> param( # The number of taps. [int] $TapCount = 8 ) Write-Host "Press ENTER on the next..." $beatTimes = @() $beatTimeStart = [datetime]::Now $lastBeatTime = [timespan]::FromMilliseconds(0) $beatTimes = do { Write-Host "$($TapCount -$beatTimes.Length) beats:" -NoNewline $readNothing = Read-Host $beatTimes += [datetime]::Now $lastBeatTime = $beatTimes[-1] - $beatTimeStart $beatTimeStart = [datetime]::Now $lastBeatTime } while ($beatTimes.Length -lt $TapCount) $averageTimeBetweenBeats = $beatTimes.TotalMilliseconds | Measure-Object -Average | Select-Object -ExpandProperty Average $this.Duration = [Timespan]::FromMilliseconds($averageTimeBetweenBeats) $this.BeatStart = $beatTimeStart $this.BPM </Script> </ScriptMethod> <ScriptProperty> <Name>Angle</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Beat Angle .DESCRIPTION Gets the Angle of the Beat. If we imagine that as the beat is moving, we are rotating around a circle, this should be the angle at any given moment. #> $this.BeatCount * 180/[Math]::PI </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>BeatCount</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Beat Count .DESCRIPTION Gets the number of beats since the beat started. .EXAMPLE $obs.Beat.BeatCount #> if ($this.'.BPM' -and $this.'.BeatStart') { ([DateTime]::Now - $this.'.BeatStart').TotalMilliseconds / ((60 * 1000) / $this.'.BPM') } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>BeatStart</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Beat Start Time .DESCRIPTION Gets the time when the beat started. #> return $this.'.BeatStart' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the Beat Start Time .DESCRIPTION Sets the time when the beat started. #> param( # The Beat Start Time [DateTime]$BeatStartTime ) if ($this.'.BPM') { $this | Add-Member NoteProperty ".BeatStart" ( $BeatStartTime ) -Force $this.Timer.Start() } </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>BPM</Name> <GetScriptBlock> <# .SYNOPSIS Gets the BPM .DESCRIPTION Gets the Beats Per Minute (BPM) of obs-powershell. This can be used to time effects to a beat. #> return $this.'.BPM' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the BPM .DESCRIPTION Set the Beats Per Minute (BPM) of obs-powershell. This can be used to time effects to a beat. #> param( # The new BPM [double] $BPM ) $this | Add-Member NoteProperty ".BPM" $BPM -Force -PassThru $duration = [Timespan]::FromMilliseconds( (60 * 1000) / $this.'.BPM' ) $this.Timer = $duration </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Cosine</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Beat Cosine .DESCRIPTION Gets the Cosine of the BeatCount. Since this starts at 1, this would be at its highest value during the top of the beat. #> [Math]::Cos($this.BeatCount * ([Math]::PI/2)) </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Duration</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Duration .DESCRIPTION Gets the Duration of a Beat .OUTPUTS [TimeSpan] #> if ($this.'.BPM') { [Timespan]::FromMilliseconds((60 * 1000) / $this.'.BPM') } </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Gets the Duration .DESCRIPTION Gets the Duration of a Beat .OUTPUTS [TimeSpan] #> param( # The new duration. [timespan] $Duration ) $this.BPM = ( 60000 / $Duration.TotalMilliseconds ) </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Sine</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Beat Sine .DESCRIPTION Gets the Sine of the BeatCount. Since this starts at 0, this would be at its highest value during the middle of the beat. #> [Math]::Cos($this.BeatCount * [Math]::PI/2) </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Timer</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Beat Timer .DESCRIPTION Gets the Timer object that should elapse every beat. This can be used to Register-ObjectEvent to run on a beat. #> return $this.'.Timer' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets the Beat Timer .DESCRIPTION Sets the Beat Timer. If no timer exists, one is created. Otherwise, the interval is updated. .OUTPUTS [TimeSpan] #> param( # The new timer interval. [timespan] $Interval ) if (-not $this.'.Timer') { $this | Add-Member NoteProperty '.Timer' ([Timers.Timer]::new($Interval.TotalMilliseconds)) -Force } else { $this.'.Timer'.Interval = $Interval.TotalMilliseconds } </SetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.GetSourceFilterList.Response</Name> <Members> <ScriptMethod> <Name>Disable</Name> <Script> <# .SYNOPSIS Disables a filter .DESCRIPTION Disables an OBS filter. .LINK Set-OBSSourceFilterEnabled #> param( # If set, will return the request that would enable a filter. [switch] $PassThru ) $this | Add-Member filterEnabled $false -Force -PassThru | Set-OBSSourceFilterEnabled -FilterEnabled:$false -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Enable</Name> <Script> <# .SYNOPSIS Enables a filter .DESCRIPTION Enables an OBS filter. .LINK Set-OBSSourceFilterEnabled #> param( # If set, will return the request that would enable a filter. [switch] $PassThru ) $this | Set-OBSSourceFilterEnabled -FilterEnabled:$true -PassThru:$PassThru if (-not $PassThru) { $this | Add-Member filterEnabled $true -Force -PassThru } </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> <# .SYNOPSIS Removes a filter .DESCRIPTION Removes a filter from an OBS source. .LINK Remove-OBSSourceFilter .LINK Get-OBSSourceFilterList #> $this | Remove-OBSSourceFilter </Script> </ScriptMethod> <ScriptMethod> <Name>Set</Name> <Script> <# .SYNOPSIS Sets a filter .DESCRIPTION Changes a filter's settings. #> param( # The settings that can be changed. [Alias('Setting')] $Settings, # Return the message that would be sent to OBS, rather than changing the filter settings. [switch] $PassThru ) $this | Set-OBSSourceFilterSettings -FilterSettings $Settings -PassThru:$PassThru </Script> </ScriptMethod> <ScriptProperty> <Name>Enabled</Name> <GetScriptBlock> return $this.filterEnabled </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Index</Name> <GetScriptBlock> return $this.filterIndex </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Kind</Name> <GetScriptBlock> return $this.filterKind </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Settings</Name> <GetScriptBlock> ,$this.filterSettings </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.GetSourceFilter.Response</Name> <Members> <ScriptMethod> <Name>Disable</Name> <Script> <# .SYNOPSIS Disables a filter .DESCRIPTION Disables an OBS filter. .LINK Set-OBSSourceFilterEnabled #> param( # If set, will return the request that would enable a filter. [switch] $PassThru ) $this | Add-Member filterEnabled $false -Force -PassThru | Set-OBSSourceFilterEnabled -FilterEnabled:$false -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Enable</Name> <Script> <# .SYNOPSIS Enables a filter .DESCRIPTION Enables an OBS filter. .LINK Set-OBSSourceFilterEnabled #> param( # If set, will return the request that would enable a filter. [switch] $PassThru ) $this | Set-OBSSourceFilterEnabled -FilterEnabled:$true -PassThru:$PassThru if (-not $PassThru) { $this | Add-Member filterEnabled $true -Force -PassThru } </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> <# .SYNOPSIS Removes a filter .DESCRIPTION Removes a filter from an OBS source. .LINK Remove-OBSSourceFilter .LINK Get-OBSSourceFilterList #> $this | Remove-OBSSourceFilter </Script> </ScriptMethod> <ScriptMethod> <Name>Set</Name> <Script> <# .SYNOPSIS Sets a filter .DESCRIPTION Changes a filter's settings. #> param( # The settings that can be changed. [Alias('Setting')] $Settings, # Return the message that would be sent to OBS, rather than changing the filter settings. [switch] $PassThru ) $this | Set-OBSSourceFilterSettings -FilterSettings $Settings -PassThru:$PassThru </Script> </ScriptMethod> <ScriptProperty> <Name>Enabled</Name> <GetScriptBlock> return $this.filterEnabled </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Index</Name> <GetScriptBlock> return $this.filterIndex </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Kind</Name> <GetScriptBlock> return $this.filterKind </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Settings</Name> <GetScriptBlock> ,$this.filterSettings </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.Filter</Name> <Members> <ScriptMethod> <Name>Disable</Name> <Script> <# .SYNOPSIS Disables a filter .DESCRIPTION Disables an OBS filter. .LINK Set-OBSSourceFilterEnabled #> param( # If set, will return the request that would enable a filter. [switch] $PassThru ) $this | Add-Member filterEnabled $false -Force -PassThru | Set-OBSSourceFilterEnabled -FilterEnabled:$false -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Enable</Name> <Script> <# .SYNOPSIS Enables a filter .DESCRIPTION Enables an OBS filter. .LINK Set-OBSSourceFilterEnabled #> param( # If set, will return the request that would enable a filter. [switch] $PassThru ) $this | Set-OBSSourceFilterEnabled -FilterEnabled:$true -PassThru:$PassThru if (-not $PassThru) { $this | Add-Member filterEnabled $true -Force -PassThru } </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> <# .SYNOPSIS Removes a filter .DESCRIPTION Removes a filter from an OBS source. .LINK Remove-OBSSourceFilter .LINK Get-OBSSourceFilterList #> $this | Remove-OBSSourceFilter </Script> </ScriptMethod> <ScriptMethod> <Name>Set</Name> <Script> <# .SYNOPSIS Sets a filter .DESCRIPTION Changes a filter's settings. #> param( # The settings that can be changed. [Alias('Setting')] $Settings, # Return the message that would be sent to OBS, rather than changing the filter settings. [switch] $PassThru ) $this | Set-OBSSourceFilterSettings -FilterSettings $Settings -PassThru:$PassThru </Script> </ScriptMethod> <ScriptProperty> <Name>Enabled</Name> <GetScriptBlock> return $this.filterEnabled </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Index</Name> <GetScriptBlock> return $this.filterIndex </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Kind</Name> <GetScriptBlock> return $this.filterKind </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Settings</Name> <GetScriptBlock> ,$this.filterSettings </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.GetCurrentProgramScene.Response</Name> <Members> <ScriptMethod> <Name>ToString</Name> <Script> $this.currentProgramSceneName </Script> </ScriptMethod> </Members> </Type> <Type> <Name>OBS.GetInputList.Response</Name> <Members> <AliasProperty> <Name>DisableAllFilters</Name> <ReferencedMemberName>DisableAllFilter</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>EnableAllFilters</Name> <ReferencedMemberName>EnableAllFilter</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>SourceName</Name> <ReferencedMemberName>inputName</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>DisableAllFilter</Name> <Script> <# .SYNOPSIS Quickly disables all filters .DESCRIPTION Quickly disables all filters, except for a list of provided names #> param( # A list of filter names to leave disabled. [string[]] $ExceptFilterName ) $this.Filters | Where-Object FilterName -NotIn $ExceptFilterName | Foreach-Object { $_.Disable($true) } | Send-OBS </Script> </ScriptMethod> <ScriptMethod> <Name>EnableAllFilter</Name> <Script> <# .SYNOPSIS Quickly enables all filters .DESCRIPTION Quickly enables all filters, except for a list of provided names #> param( # A list of filter names to leave disabled. [string[]] $ExceptFilterName ) $this.Filters | Where-Object FilterName -NotIn $ExceptFilterName | Foreach-Object { $_.Enable($true) } | Send-OBS </Script> </ScriptMethod> <ScriptMethod> <Name>Mute</Name> <Script> <# .SYNOPSIS Mutes an input .DESCRIPTION Mutes the audio of an OBS Input .LINK Set-OBSInputMute #> param( # If set, returns the message used to mute [switch] $PassThru ) $this | Set-OBSInputMute -InputMuted -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Next</Name> <Script> <# .SYNOPSIS Nexts an input .DESCRIPTION Sends a "Next" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Pause</Name> <Script> <# .SYNOPSIS Pauses an input .DESCRIPTION Sends a "Pause" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Play</Name> <Script> <# .SYNOPSIS Plays an input .DESCRIPTION Sends a "Play" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Previous</Name> <Script> <# .SYNOPSIS Previouss an input .DESCRIPTION Sends a "Previous" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> <# .SYNOPSIS Removes an input .DESCRIPTION Removes an OBS Input .LINK Remove-OBSInput #> $this | Remove-OBSInput </Script> </ScriptMethod> <ScriptMethod> <Name>Restart</Name> <Script> <# .SYNOPSIS Restarts an input .DESCRIPTION Sends a "Restart" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Stop</Name> <Script> <# .SYNOPSIS Stops an input .DESCRIPTION Sends a "Stop" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Unmute</Name> <Script> <# .SYNOPSIS Mutes an input .DESCRIPTION Mutes the audio of an OBS Input .LINK Set-OBSInputMute #> param( # If set, returns the message used to unmute. [switch] $PassThru ) $this | Set-OBSInputMute -InputMuted:$false -PassThru:$PassThru </Script> </ScriptMethod> <ScriptProperty> <Name>CurrentTime</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's current time .DESCRIPTION Gets an input's current time, if applicable .LINK Get-OBSMediaInputStatus #> param() $mediaCursor = ($this | Get-OBSMediaInputStatus).mediaCursor -as [double] if (-not $mediaCursor) { $mediaCursor = [double]0} [timespan]::FromMilliseconds($mediaCursor) </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an input's current time .DESCRIPTION Sets an input's current time. .LINK Send-OBSMediaInputCursor #> param() $mediaCursor = 0 $PassThru = $false foreach ($arg in $args) { if ($arg -is [double]) { $mediaCursor = $arg } elseif ($arg -as [timespan]) { $mediaCursor = $arg -as [timespan].TotalMilliseconds } if ($arg -is [bool]) { $PassThru = $true } } $this | Set-OBSMediaInputCursor -MediaCursor $mediaCursor -PassThru:$PassThru </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Filters</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's filters .DESCRIPTION Gets the filters related to an OBS input. .EXAMPLE $obsPowerShellIcon = Show-OBS -Uri https://obs-powershell.start-automating.com/Assets/obs-powershell-animated-icon.svg $obsPowerShellIcon | Set-OBSColorFilter -Opacity .5 $obsPowerShellIcon.Input.Filters .LINK Get-OBSSourceFilterList #> Get-OBSSourceFilterList -SourceName $this.InputName </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>MonitorType</Name> <GetScriptBlock> $this | Get-OBSInputAudioMonitorType </GetScriptBlock> <SetScriptBlock> param( [string] $MonitorType ) $validValues = "Monitor", "MonitorAndOutput", "None","Off","OBS_MONITORING_TYPE_MONITOR_ONLY","OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT","OBS_MONITORING_TYPE_MONITOR_ONLY" if ($MonitorType -notin $validValues) { throw "Invalid Value: '$MonitorType' is not in '$($validValues -join "','")'" } $realMonitorType = if ($MonitorType -like 'obs*') { $MonitorType.ToUpper() } elseif ($MonitorType -eq 'Monitor') { "OBS_MONITORING_TYPE_MONITOR_ONLY" } elseif ($MonitorType -eq 'MonitorAndOutput') { "OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT" } else { "OBS_MONITORING_TYPE_NONE" } $this | Set-OBSInputAudioMonitorType -MonitorType $realMonitorType </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>SceneItem</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's scene items .DESCRIPTION Gets the scene items associated with an input. #> Get-obsscene | Select-Object -ExpandProperty Scenes | Get-OBSSceneItem | Where-Object SourceName -EQ $this.InputName | Where-Object InputKind -EQ $this.InputKind </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Settings</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's settings .DESCRIPTION Gets the current settings for an OBS input. .EXAMPLE $obsPowerShellIcon = Show-OBS -Uri https://obs-powershell.start-automating.com/Assets/obs-powershell-animated-icon.svg $obsPowerShellIcon.Input.Settings .LINK Get-OBSInputSettings #> (Get-OBSInputSettings -InputName $this.InputName).inputSettings </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an input's settings .DESCRIPTION Changes the settings for an OBS input. .LINK Set-OBSInputSettings #> param() Set-OBSInputSettings -InputName $this.InputName -InputSettings $args[0] </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Status</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's status .DESCRIPTION Gets the media status of an OBS input. .LINK Get-OBSMediaInputStatus #> param() $this | Get-OBSMediaInputStatus </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Volume</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's volume .DESCRIPTION Gets an OBS input's volume mulitplier .LINK Get-OBSInputVolume #> ($this | Get-OBSInputVolume).inputVolumeMul </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an input's volume .DESCRIPTION Sets an OBS input's volume mulitplier. This is normally between 0 (no sound) and 1 (normal levels). A source can be made up to 20 times the original volume. .LINK Set-OBSInputVolume #> param( [double] $Multiple ) # If multiple is less than zero, clamp it to avoid errors if ($Multiple -lt 0) { $Multiple = 0} # If multiple is greater than 20, claim it to avoid errors (and check your hearing) if ($Multiple -gt 20) { $Multiple = 20} $this | Set-OBSInputVolume -InputVolumeMul $Multiple </SetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.Input</Name> <Members> <AliasProperty> <Name>DisableAllFilters</Name> <ReferencedMemberName>DisableAllFilter</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>EnableAllFilters</Name> <ReferencedMemberName>EnableAllFilter</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>SourceName</Name> <ReferencedMemberName>inputName</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>DisableAllFilter</Name> <Script> <# .SYNOPSIS Quickly disables all filters .DESCRIPTION Quickly disables all filters, except for a list of provided names #> param( # A list of filter names to leave disabled. [string[]] $ExceptFilterName ) $this.Filters | Where-Object FilterName -NotIn $ExceptFilterName | Foreach-Object { $_.Disable($true) } | Send-OBS </Script> </ScriptMethod> <ScriptMethod> <Name>EnableAllFilter</Name> <Script> <# .SYNOPSIS Quickly enables all filters .DESCRIPTION Quickly enables all filters, except for a list of provided names #> param( # A list of filter names to leave disabled. [string[]] $ExceptFilterName ) $this.Filters | Where-Object FilterName -NotIn $ExceptFilterName | Foreach-Object { $_.Enable($true) } | Send-OBS </Script> </ScriptMethod> <ScriptMethod> <Name>Mute</Name> <Script> <# .SYNOPSIS Mutes an input .DESCRIPTION Mutes the audio of an OBS Input .LINK Set-OBSInputMute #> param( # If set, returns the message used to mute [switch] $PassThru ) $this | Set-OBSInputMute -InputMuted -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Next</Name> <Script> <# .SYNOPSIS Nexts an input .DESCRIPTION Sends a "Next" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_NEXT" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Pause</Name> <Script> <# .SYNOPSIS Pauses an input .DESCRIPTION Sends a "Pause" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PAUSE" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Play</Name> <Script> <# .SYNOPSIS Plays an input .DESCRIPTION Sends a "Play" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PLAY" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Previous</Name> <Script> <# .SYNOPSIS Previouss an input .DESCRIPTION Sends a "Previous" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_PREVIOUS" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> <# .SYNOPSIS Removes an input .DESCRIPTION Removes an OBS Input .LINK Remove-OBSInput #> $this | Remove-OBSInput </Script> </ScriptMethod> <ScriptMethod> <Name>Restart</Name> <Script> <# .SYNOPSIS Restarts an input .DESCRIPTION Sends a "Restart" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_RESTART" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Stop</Name> <Script> <# .SYNOPSIS Stops an input .DESCRIPTION Sends a "Stop" message to an input. .LINK Send-OBSTriggerMediaInputAction #> param( # If set, will return the message instead of sending it now. [switch] $PassThru ) $this | Send-OBSTriggerMediaInputAction -MediaAction "OBS_WEBSOCKET_MEDIA_INPUT_ACTION_STOP" -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>Unmute</Name> <Script> <# .SYNOPSIS Mutes an input .DESCRIPTION Mutes the audio of an OBS Input .LINK Set-OBSInputMute #> param( # If set, returns the message used to unmute. [switch] $PassThru ) $this | Set-OBSInputMute -InputMuted:$false -PassThru:$PassThru </Script> </ScriptMethod> <ScriptProperty> <Name>CurrentTime</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's current time .DESCRIPTION Gets an input's current time, if applicable .LINK Get-OBSMediaInputStatus #> param() $mediaCursor = ($this | Get-OBSMediaInputStatus).mediaCursor -as [double] if (-not $mediaCursor) { $mediaCursor = [double]0} [timespan]::FromMilliseconds($mediaCursor) </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an input's current time .DESCRIPTION Sets an input's current time. .LINK Send-OBSMediaInputCursor #> param() $mediaCursor = 0 $PassThru = $false foreach ($arg in $args) { if ($arg -is [double]) { $mediaCursor = $arg } elseif ($arg -as [timespan]) { $mediaCursor = $arg -as [timespan].TotalMilliseconds } if ($arg -is [bool]) { $PassThru = $true } } $this | Set-OBSMediaInputCursor -MediaCursor $mediaCursor -PassThru:$PassThru </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Filters</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's filters .DESCRIPTION Gets the filters related to an OBS input. .EXAMPLE $obsPowerShellIcon = Show-OBS -Uri https://obs-powershell.start-automating.com/Assets/obs-powershell-animated-icon.svg $obsPowerShellIcon | Set-OBSColorFilter -Opacity .5 $obsPowerShellIcon.Input.Filters .LINK Get-OBSSourceFilterList #> Get-OBSSourceFilterList -SourceName $this.InputName </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>MonitorType</Name> <GetScriptBlock> $this | Get-OBSInputAudioMonitorType </GetScriptBlock> <SetScriptBlock> param( [string] $MonitorType ) $validValues = "Monitor", "MonitorAndOutput", "None","Off","OBS_MONITORING_TYPE_MONITOR_ONLY","OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT","OBS_MONITORING_TYPE_MONITOR_ONLY" if ($MonitorType -notin $validValues) { throw "Invalid Value: '$MonitorType' is not in '$($validValues -join "','")'" } $realMonitorType = if ($MonitorType -like 'obs*') { $MonitorType.ToUpper() } elseif ($MonitorType -eq 'Monitor') { "OBS_MONITORING_TYPE_MONITOR_ONLY" } elseif ($MonitorType -eq 'MonitorAndOutput') { "OBS_MONITORING_TYPE_MONITOR_AND_OUTPUT" } else { "OBS_MONITORING_TYPE_NONE" } $this | Set-OBSInputAudioMonitorType -MonitorType $realMonitorType </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>SceneItem</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's scene items .DESCRIPTION Gets the scene items associated with an input. #> Get-obsscene | Select-Object -ExpandProperty Scenes | Get-OBSSceneItem | Where-Object SourceName -EQ $this.InputName | Where-Object InputKind -EQ $this.InputKind </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Settings</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's settings .DESCRIPTION Gets the current settings for an OBS input. .EXAMPLE $obsPowerShellIcon = Show-OBS -Uri https://obs-powershell.start-automating.com/Assets/obs-powershell-animated-icon.svg $obsPowerShellIcon.Input.Settings .LINK Get-OBSInputSettings #> (Get-OBSInputSettings -InputName $this.InputName).inputSettings </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an input's settings .DESCRIPTION Changes the settings for an OBS input. .LINK Set-OBSInputSettings #> param() Set-OBSInputSettings -InputName $this.InputName -InputSettings $args[0] </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Status</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's status .DESCRIPTION Gets the media status of an OBS input. .LINK Get-OBSMediaInputStatus #> param() $this | Get-OBSMediaInputStatus </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Volume</Name> <GetScriptBlock> <# .SYNOPSIS Gets an input's volume .DESCRIPTION Gets an OBS input's volume mulitplier .LINK Get-OBSInputVolume #> ($this | Get-OBSInputVolume).inputVolumeMul </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets an input's volume .DESCRIPTION Sets an OBS input's volume mulitplier. This is normally between 0 (no sound) and 1 (normal levels). A source can be made up to 20 times the original volume. .LINK Set-OBSInputVolume #> param( [double] $Multiple ) # If multiple is less than zero, clamp it to avoid errors if ($Multiple -lt 0) { $Multiple = 0} # If multiple is greater than 20, claim it to avoid errors (and check your hearing) if ($Multiple -gt 20) { $Multiple = 20} $this | Set-OBSInputVolume -InputVolumeMul $Multiple </SetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.Input.Color.Source.V3</Name> <Members> <ScriptMethod> <Name>SetColor</Name> <Script> <# .SYNOPSIS Sets the color. .DESCRIPTION Changes the color of a color source. #> param( [ValidatePattern('\#(?>[0-9a-f]{8}|[0-9a-f]{6}|[0-9a-f]{4}|[0-9a-f]{3})')] [string] $Color ) $hexChar = [Regex]::new('[0-9a-f]') $hexColors = @($hexChar.Matches($Color)) switch ($hexColors.Length) { 8 { #full rgba $alpha = [byte]::Parse($hexColors[0..1] -join '', 'HexNumber') $red = [byte]::Parse($hexColors[2..3] -join '', 'HexNumber') $green = [byte]::Parse($hexColors[4..5] -join '', 'HexNumber') $blue = [byte]::Parse($hexColors[6..7] -join '', 'HexNumber') } 6 { #rgb only, assume ff for alpha $alpha = 0xff $red = [byte]::Parse($hexColors[0..1] -join '', 'HexNumber') $green = [byte]::Parse($hexColors[2..3] -join '', 'HexNumber') $blue = [byte]::Parse($hexColors[4..5] -join '', 'HexNumber') } 4 { #short rgba $alpha = [byte]::Parse(($hexColors[0],$hexColors[0] -join ''), 'HexNumber') $red = [byte]::Parse(($hexColors[1],$hexColors[1] -join ''), 'HexNumber') $green = [byte]::Parse(($hexColors[2],$hexColors[2] -join ''), 'HexNumber') $blue = [byte]::Parse(($hexColors[3],$hexColors[3] -join ''), 'HexNumber') } 3 { #short rgb, assume f for alpha $alpha = 0xff $red = [byte]::Parse(($hexColors[0],$hexColors[0] -join ''), 'HexNumber') $green = [byte]::Parse(($hexColors[1],$hexColors[1] -join ''), 'HexNumber') $blue = [byte]::Parse(($hexColors[2],$hexColors[2] -join ''), 'HexNumber') } 0 { # No color provided, default to transparent black $alpha = 0 $red = 0 $green = 0 $blue = 0 } } $hexColor = ("{0:x2}{1:x2}{2:x2}{3:x2}" -f $alpha, $blue, $green, $red) $realColor = [uint32]::Parse($hexColor,'HexNumber') $this | Set-OBSInputSettings -InputSettings ([Ordered]@{color=$realColor}) </Script> </ScriptMethod> </Members> </Type> <Type> <Name>OBS.PowerShell</Name> <Members> <AliasProperty> <Name>Stats</Name> <ReferencedMemberName>Statistics</ReferencedMemberName> </AliasProperty> <ScriptProperty> <Name>Beat</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Beat .DESCRIPTION Gets the Beat Controller for obs-powershell. The beat controller allows you to control effects on a beat. #> if (-not $this.'.Beat') { $this | Add-Member NoteProperty '.Beat' ([PSCustomObject]@{ PSTypeName = "OBS.Beat" }) -Force } return $this.'.Beat' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Commands</Name> <GetScriptBlock> <# .SYNOPSIS Gets obs-powershell commands .DESCRIPTION Gets the commands in obs-powershell. .EXAMPLE (Get-OBS).Commands #> if (-not $this.'.Commands') { $this | Add-Member NoteProperty '.Commands' (Get-Command -Module obs-powershell) } $this.'.Commands' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Connection</Name> <GetScriptBlock> & $this { $script:OBSConnections } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>CurrentScene</Name> <GetScriptBlock> <# .SYNOPSIS Gets the current scene .DESCRIPTION Gets the current scene in OBS. .EXAMPLE Get-OBS | Select-Object -ExpandProperty CurrentScene #> Get-OBSCurrentProgramScene </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Inputs</Name> <GetScriptBlock> <# .SYNOPSIS Gets the loaded OBS inputs. .DESCRIPTION Gets the currently loaded inputs in OBS. .LINK Get-OBSInput #> Get-OBSInput </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>OBSPowerShellVersion</Name> <GetScriptBlock> <# .SYNOPSIS Gets the obs-powershell version. .DESCRIPTION Gets the version of obs-powershell. .EXAMPLE Get-OBS | Select-Object -ExpandProperty OBSPowerShellVersion #> Get-Module obs-powershell | Select-Object -ExpandProperty Version </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>OBSVersion</Name> <GetScriptBlock> <# .SYNOPSIS Gets the obs version. .DESCRIPTION Gets the version of obs. .EXAMPLE Get-OBS | Select-Object -ExpandProperty OBSVersion #> if (-not $this.'.OBSVersionInfo') { $this | Add-Member NoteProperty '.OBSVersionInfo' (Get-OBSVersion) -Force } $this.'.OBSVersionInfo'.OBSVersion -as [version] </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>OBSWebSocketVersion</Name> <GetScriptBlock> <# .SYNOPSIS Gets the obs version. .DESCRIPTION Gets the version of obs. .EXAMPLE Get-OBS | Select-Object -ExpandProperty OBSVersion #> if (-not $this.'.OBSVersionInfo') { $this | Add-Member NoteProperty '.OBSVersionInfo' (Get-OBSVersion) -Force } $this.'.OBSVersionInfo'.OBSWebSocketVersion -as [version] </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Outputs</Name> <GetScriptBlock> <# .SYNOPSIS Gets the loaded OBS outputs. .DESCRIPTION Gets the currently loaded outputs in OBS. .LINK Get-OBSOutput #> Get-OBSOutput </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Process</Name> <GetScriptBlock> Get-Process obs* | Sort-Object { $_.Name -in 'obs', 'obs64', 'obs32' } | Where-Object Name -in 'obs', 'obs64', 'obs32' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>RandomExample</Name> <GetScriptBlock> <# .SYNOPSIS .DESCRIPTION #> $foundAnExample = $false do { $helpObject = $this.Commands | Get-Random | Get-Help if (-not $helpObject.Examples) { continue } $foundAnExample = $helpObject.Examples[0] | Get-Random | Select-Object -ExpandProperty Example } until ($foundAnExample) $foundAnExample </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>RecordStatus</Name> <GetScriptBlock> <# .SYNOPSIS Gets OBS record status. .DESCRIPTION Gets the record status of OBS. .LINK Get-OBSRecordStatus #> Get-OBSRecordStatus </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>SceneItems</Name> <GetScriptBlock> <# .SYNOPSIS Gets all obs scene items. .DESCRIPTION Gets every item in every scene in OBS. .LINK Get-OBSScene .LINK Get-OBSSceneItem #> $this.Scenes | Get-OBSSceneItem </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Scenes</Name> <GetScriptBlock> <# .SYNOPSIS Gets the loaded OBS scenes. .DESCRIPTION Gets the currently loaded scenes in OBS. .LINK Get-OBSScene #> (Get-OBSScene).Scenes </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Statistics</Name> <GetScriptBlock> <# .SYNOPSIS Gets OBS stats. .DESCRIPTION Gets OBS statistics .LINK Get-OBSStats #> Get-OBSStats </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>StreamStatus</Name> <GetScriptBlock> <# .SYNOPSIS Gets OBS stream status. .DESCRIPTION Gets the stream status of OBS. .LINK Get-OBSStreamStatus #> Get-OBSStreamStatus </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.PowerShell.Effect</Name> <Members> <AliasProperty> <Name>Play</Name> <ReferencedMemberName>Start</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Reverse</Name> <Script> <# .SYNOPSIS Toggles Reversed and Starts an Effect .DESCRIPTION Toggles an Effect's Reversed bool, and starts the effect. #> $this.Reversed = -not $this.Reversed $this.Start() </Script> </ScriptMethod> <ScriptMethod> <Name>Start</Name> <Script> <# .SYNOPSIS Stars an Effect .DESCRIPTION Stars an Effect in obs-powershell. #> # If the effect has no messages if (-not $this.Messages -and # and it is a command $this.pstypenames -like '*Command*') { # then get read to run it. $null = New-Event -SourceIdentifier "OBS.PowerShell.Effect.Command.Started" -MessageData $this $thisOutput = # If this method had args if ($args) { $splat = [Ordered]@{} $argSplat = @( foreach ($arg in $args) { # find and join all of the dictionaries into a splat if ($arg -is [Collections.IDictionary]) { try { $splat += $arg} catch { foreach ($kv in $arg.GetEnumerator()) { if (-not $splat.Contains($kv.Key)) { $splat[$kv.Key] = $kv.Value } } } } else { # and pass everything else positionally $arg } } ) # Cache these values $This | Add-Member -MemberType NoteProperty LastParameters $splat -Force $This | Add-Member -MemberType NoteProperty LastArguments $argSplat -Force # and run this & $this @Splat @argSplat } else { # If we had no args, use the last parameters. $lastParameters = if ($this.LastParameters) { $this.LastParameters } else { @{} } $lastArguments = if ($this.LastArguments) { @($this.LastArguments) } else { @() } & $this @LastParameters @lastArguments } $null = New-Event -SourceIdentifier "OBS.PowerShell.Effect.Command.Completed" -MessageData $this if ($thisOutput) { $this | Add-Member -MemberType NoteProperty Messages $thisOutput -Force $this | Add-Member -MemberType NoteProperty '.Changes' $null -Force } } if ($this.Messages) { $totalMS = [double]0 $messages = @($This.Messages) if ($this.Reversed) { [Array]::Reverse($messages) } foreach ($msg in $messages) { if ($msg.RequestType -eq 'Sleep') { $totalMS += $msg.RequestData.sleepMillis } } $null = New-Event -SourceIdentifier "OBS.PowerShell.Effect.Started" -MessageData $this $messages | Send-OBS -NoResponse $this | Add-Member NoteProperty Status "Started" -Force if ($totalMS) { $Timer = [Timers.Timer]::new($totalMS) $Timer.AutoReset = $false Add-Member -MemberType NoteProperty -InputObject $this -Name Subscription -Value ( Register-ObjectEvent -InputObject $timer -EventName Elapsed -Action { $null = New-Event -SourceIdentifier "OBS.PowerShell.Effect.Ended" -MessageData $event.MessageData $effectInfo = $event.MessageData if ($effectInfo.LoopCount -is [int] -and $effectInfo.LoopCount -ge 1) { $effectInfo.LoopCount = $effectInfo.LoopCount - 1 } $effectInfo | Add-Member -MemberType NoteProperty Status 'Ended' -Force if ($effectInfo.Mode -match 'Bounce' -and $effectInfo.Mode -match 'Loop') { $effectInfo.Reversed = -not $effectInfo.Reversed $effectInfo.Start() } elseif ($effectInfo.Mode -match 'Loop') { if ($effectInfo.LoopCount -is [int] -and $effectInfo.LoopCount -ge 1) { $effectInfo.Start() } elseif ($effectInfo.LoopCount -isnot [int] -or $effectInfo.LoopCount -lt 0) { $effectInfo.Start() } } elseif ($effectInfo.Mode -match 'Bounce') { $effectInfo.Reversed = -not $effectInfo.Reversed $effectInfo.Mode = 'Twice' $effectInfo.Start() } else { $effectInfo | Add-Member -MemberType NoteProperty Mode 'Once' -Force } } -MessageData $this -MaxTriggerCount 1 ) $Timer.Start() } else { $this | Add-Member -MemberType NoteProperty Status "Ended" -Force New-Event -SourceIdentifier "OBS.PowerShell.EffectEnded" -MessageData $this } } </Script> </ScriptMethod> <ScriptMethod> <Name>Step</Name> <Script> <# .SYNOPSIS Steps thru an effect .DESCRIPTION Steps thru an effect. This will send individual messages from an effect, without sleeps. #> param( # The step count [Alias('Ticks')] [int] $StepCount = 1 ) if (-not $this.Messages) { return } $currentIndex = $this.Index $messages = @($this.Messages) $stepToIndex = $currentIndex + $StepCount if ($stepToIndex -lt 0) { $messages[0] | Send-OBS -NoResponse $this.Index = 0 } elseif ($stepToIndex -gt $messages.Length) { $messages[-1] | Send-OBS -NoResponse $this.Index = $messages.Length - 1 } else { while ( $stepToIndex -ge 0 -and $messages[$stepToIndex] -and $messages[$stepToIndex].RequestType -eq 'Sleep') { if ($StepCount -gt 0) { $stepToIndex++ } else { $stepToIndex-- } } if ($messages[$stepToIndex]) { $messages[$stepToIndex] | Send-obs -NoResponse } $this.Index = $stepToIndex } </Script> </ScriptMethod> <ScriptMethod> <Name>Stop</Name> <Script> <# .SYNOPSIS Stops an effect .DESCRIPTION Stops an effect, or more properly, prevents an effect from looping #> $this | Add-Member -MemberType NoteProperty Mode "Stopped" -Force </Script> </ScriptMethod> <ScriptProperty> <Name>Changes</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Effect's Changes .DESCRIPTION Gets the changes the effect will make, without a timespan. #> ,@(if ($this.Messages) { foreach ($msg in $this.Messages) { if ($msg.RequestType -eq 'Sleep') { continue } $msg } }) </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Duration</Name> <GetScriptBlock> <# .SYNOPSIS Gets an Effect's Duration .DESCRIPTION Gets the total time the effect will sleep. #> $totalMS = [double]0 foreach ($msg in $this.Messages) { if ($msg.RequestType -eq 'Sleep') { $totalMS += $msg.RequestData.sleepMillis } } [timespan]::FromMilliseconds($totalMS) </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>EffectType</Name> <GetScriptBlock> <# .SYNOPSIS Gets an obs-powershell effect's type .DESCRIPTION Gets the type of an obs-powershell effect. Current can be either 'Command' or 'Messages' #> if ($this.pstypenames -like 'OBS.PowerShell.Effect.Command*') { 'Command' } else { 'Messages' } </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Index</Name> <GetScriptBlock> <# .SYNOPSIS Gets the index of the effect .DESCRIPTION Gets the current index of the effect. This is only used for to .Step thru an effect. #> if (-not $this.'.Index') { Add-Member -MemberType NoteProperty -Name '.Index' -Value 0 -InputObject $this -Force } $this.'.Index' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Updates the Effect's Index .DESCRIPTION Updates an effect's index. This is only used to .Step() #> Add-Member -MemberType NoteProperty -Name '.Index' -Value ($args[0] -as [int]) -InputObject $this -Force </SetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Reversed</Name> <GetScriptBlock> <# .SYNOPSIS Gets if an effect is reversed. .DESCRIPTION Gets if an effect is currently set to Reverse. Whenever reverse is set, effect messages will be reversed before being sent. #> if (-not $this.'.Reversed') { $this | Add-Member NoteProperty '.Reversed' $false -Force } $this.'.Reversed' </GetScriptBlock> <SetScriptBlock> <# .SYNOPSIS Sets if an effect should be reversed. .DESCRIPTION Sets if an effect should be played in reverse. #> $this | Add-Member NoteProperty '.Reversed' ($args[0] -as [bool]) -Force </SetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.Powershell.Effect.Command</Name> <Members> <ScriptProperty> <Name>EffectName</Name> <GetScriptBlock> <# .SYNOPSIS Gets the Effect Name .DESCRIPTION Gets the name of an Effect. #> $obsEffectsPattern = [Regex]::new(' (?> ^OBS.(?>fx|effects?)\p{P} | [\p{P}-[-]]OBS\.(?>fx|effects?)$ | \p{P}OBS.(?>fx|effects?)\.(?>ps1|json) ) ','IgnoreCase,IgnorePatternWhitespace') $this.Name -replace $obsEffectsPattern </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.GetSceneItemList.Response</Name> <Members> <AliasProperty> <Name>Hide</Name> <ReferencedMemberName>Disable</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Show</Name> <ReferencedMemberName>Enable</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Animate</Name> <Script> <# .SYNOPSIS Animates scene items .DESCRIPTION Animates the motion of scene items within a frame. .EXAMPLE $stars = Add-OBSBrowserSource -URI https://pssvg.start-automating.com/Examples/Stars.svg $stars.FitToScreen() $stars.Animate(@{ scale = 0.1 },"00:00:01") #> param( ) filter ToPosition { param( [switch] $Width, [switch] $Height ) if ($_ -is [string] -and $_ -match '%$') { $_ = $_ -replace '%$' -as [double] if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings if ($Width) { $_/100 * $videoSettings.baseWidth } if ($Height) { $_/100 * $videoSettings.baseHeight } } elseif ($_ -is [double] -or $_ -is [int]) { if ($_ -is [double] -and $_ -ge 0 -and $_ -lt 1) { if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings if ($Width) { $_ * $videoSettings.baseWidth } if ($Height) { $_ * $videoSettings.baseHeight } } else { [int]$_ } } } filter ToScale { if ($_ -is [string] -and $_ -match '%$') { $_ = $_ -replace '%$' -as [double] $_/100 } elseif ($_ -is [double] -or $_ -is [int]) { if ($_ -is [double] -and $_ -ge 0 -and $_ -le 1) { $_ } else { [double]$_/100 } } } $nextTimeSpan = [timespan]0 $keyNames = 'boundsWidth','boundsHeight','positionX', 'positionY', 'scaleX','scaleY', 'cropBottom', 'cropLeft', 'cropRight', 'cropTop', 'rotation' $keyAliases = [Ordered]@{'Rotate'='rotation'} $duplicatedKeyAliases = [Ordered]@{ 'position' = 'positionX', 'positionY' 'scale' = 'scaleX', 'scaleY' 'crop' = 'cropBottom', 'cropLeft', 'cropRight', 'cropTop' } foreach ($position in 'X','Y') { $keyAliases[$position] = "position$position" } foreach ($cropType in 'Bottom','Left', 'Right', 'Top') { $keyAliases[$cropType] = "crop$cropType" } $allSteps = @() $originalTransform = $this | Get-OBSSceneItemTransform $lastFrom = if ($originalTransform -is [Collections.IDictionary]) { [Ordered]@{} + $from } else { $newFrom = [Ordered]@{} foreach ($property in $originalTransform.psobject.properties) { $newFrom[$property.Name] = $property.Value } $newFrom } $totalTimeSpan = [timespan]0 # We want to walk over every argument and turn them into a series of animations $PassThru = $false $AllArgs = @($args) $allSteps = @( :NextArgument for ($argIndex = 0 ; $argIndex -lt $allArgs.Length; $argIndex++) { $arg = $allArgs[$argIndex] # If the arg is a timespan, we want to track this if ($arg -as [timespan]) { $nextTimeSpan = $arg -as [timespan] } elseif ($arg -is [double] -or $arg -is [int]) { $nextTimeSpan = [timespan]::fromSeconds($arg) } elseif ($arg -is [bool]) { if ($arg) { $PassThru = $true } } else { $currentTo = if ($arg -isnot [Collections.IDictionary]) { $newTo = [Ordered]@{} foreach ($property in $arg.psobject.properties) { $newTo[$property.Name] = $property.Value } $newTo } else { [Ordered]@{} + $arg } $badKey = @(foreach ($k in @($currentTo.Keys)) { if ($k -notin $keyNames) { if ($keyAliases[$k]) { $currentTo[$keyAliases[$k]] = $currentTo[$k] $currentTo.Remove($k) } elseif ($duplicatedKeyAliases[$k]) { foreach ($duplicateKey in $duplicatedKeyAliases[$k]) { $currentTo[$duplicateKey] = $currentTo[$k] } $currentTo.Remove($k) } else { $k } } }) foreach ($checkKeyValue in @($currentTo.GetEnumerator())) { $newValue = switch ($checkKeyValue.Key) { positionX { $checkKeyValue.Value | ToPosition -Width } positionY { $checkKeyValue.Value | ToPosition -Height } cropLeft { $checkKeyValue.Value | ToPosition -Width } cropRight { $checkKeyValue.Value | ToPosition -Width } cropTop { $checkKeyValue.Value | ToPosition -Height } cropBottom { $checkKeyValue.Value | ToPosition -Height } scaleX { $checkKeyValue.Value | ToScale } scaleY { $checkKeyValue.Value | ToScale } } if ($null -ne $newValue) { $currentTo[$checkKeyValue.Key] = $newValue } } if ($badKey) { throw "Cannot animate '$($badKey -join "','")' : Can only animate $($keyNames -join ',')" } if (-not $nextTimeSpan.TotalMilliseconds -and ($argIndex -lt ($AllArgs.Length - 1)) -and $AllArgs[$argIndex + 1] -as [timespan] ) { $nextTimeSpan = $AllArgs[$argIndex + 1] -as [timespan] $argIndex++ } if ($lastFrom -and $nextTimeSpan) { $StepCount = [Math]::Ceiling($NextTimeSpan.TotalMilliseconds / ([timespan]::fromSeconds(1/30).TotalMilliseconds)) * 2 if (-not $StepCount) { $this | Set-OBSSceneItemTransform -SceneItemTransform $currentTo -PassThru $newLastFrom = [Ordered]@{} + $currentTo foreach ($kv in $lastFrom.GetEnumerator()) { if ($currentTo.Contains($kv.Key)) { continue } $newLastFrom[$kv.Key] = $kv.Value } $lastFrom = $newLastFrom # May need to join this with the remaining properties in from $totalTimeSpan += $nextTimeSpan $nextTimeSpan = [timespan]0 continue NextArgument } $stepMilliseconds = $nextTimeSpan.TotalMilliseconds / $StepCount # Compare the two sets of keys to determine the base data object $BaseObject = [Ordered]@{} foreach ($key in $currentTo.Keys) { if (-not $BaseObject[$key]) { $BaseObject[$key] = if ($null -ne $lastFrom[$key]) { $lastFrom[$key] } else { $currentTo[$key] } } } # Determine the animation change per step. $eachStepValue = [Ordered]@{} foreach ($key in $baseObject.Keys) { $distance = try { $currentTo[$key] - $baseObject[$key] } catch { $null } if ($null -ne $distance) { $eachStepValue[$key] = [float]$distance / $StepCount } } foreach ($stepNumber in 1..($stepCount)) { $stepObject = [Ordered]@{} foreach ($key in $BaseObject.Keys) { $stepObject[$key] = $BaseObject[$key] + ($eachStepValue[$key] * $stepNumber) } $this | Set-OBSSceneItemTransform -SceneItemTransform $stepObject -PassThru Send-OBSSleep -SleepMillis $stepMilliseconds -PassThru } } else { $this | Set-OBSSceneItemTransform -SceneItemTransform $currentTo -PassThru } $newLastFrom = [Ordered]@{} + $currentTo foreach ($kv in $lastFrom.GetEnumerator()) { if ($currentTo.Contains($kv.Key)) { continue } $newLastFrom[$kv.Key] = $kv.Value } $lastFrom = $newLastFrom # May need to join this with the remaining properties in from $totalTimeSpan += $nextTimeSpan $nextTimeSpan = [timespan]0 if (($argIndex -lt ($AllArgs.Length - 1)) -and $AllArgs[$argIndex + 1] -as [timespan] ) { Send-OBSSleep -SleepMillis ($AllArgs[$argIndex + 1] -as [timespan]).TotalMilliseconds -PassThru } } $IsFirstArg = $false } ) if ($allSteps) { # If any boolean true was in the arguments, we're passing thru if ($PassThru) { $allSteps } else { # Send all of the steps to OBS. $allSteps | Send-OBS } } </Script> </ScriptMethod> <ScriptMethod> <Name>Blend</Name> <Script> param([string]$BlendMode) if ($blendMode -cnotmatch '^OBS_BLEND_') { $blendMode = "OBS_BLEND_$($blendMode.ToUpper())" } $this | Set-OBSSceneItemBlendMode -SceneItemBlendMode $blendMode </Script> </ScriptMethod> <ScriptMethod> <Name>Center</Name> <Script> <# .SYNOPSIS Centers a scene item .DESCRIPTION Sets the scene item alignment to center .NOTES Also corrects the position so that the image does not only appear in a quadrant. If a boolean argument is passed, and it is true, then this will PassThru instead of run. (this can be used for animations) If an explicit null argument is passed, then the command will not wait for an OBS response. (this will be slightly faster) #> param() $passingThru = $false $NoResponse = $false foreach ($arg in $args) { if ($arg -is [bool]) { if ($arg) { $passingThru= $true } } if ($null -eq $arg) { $NoResponse = $true } } $sceneItemTransform = $this | Get-OBSSceneItemTransform $sceneItemTransform.alignment = 0 # 0 means center $sceneItemTransform.positionX = $sceneItemTransform.boundsWidth/2 $sceneItemTransform.positionY = $sceneItemTransform.boundsHeight/2 $this | Set-OBSSceneItemTransform -SceneItemTransform $sceneItemTransform -PassThru:$passingThru -NoResponse:$NoResponse </Script> </ScriptMethod> <ScriptMethod> <Name>Crop</Name> <Script> $cropTable = [Ordered]@{ cropBottom = 0 cropLeft = 0 cropRight = 0 cropTop = 0 } $MatchingKey = [Regex]::new("(?>$( @($cropTable.Keys -join '|' '|' $cropTable.Keys -replace '^crop' -join '|') -join '' ))", 'IgnoreCase') $currentKey = '' foreach ($arg in $args) { if ($arg -is [Collections.IDictionary]) { foreach ($keyValue in $arg.GetEnumerator()) { if ($keyValue.Key -match $MatchingKey) { $cropTable[$matches.0 -replace '^crop' -replace '^', 'crop'] = $keyValue.Value } } } if ($arg -is [string] -and $arg -match $MatchingKey) { $currentKey = $matches.0 -replace '^crop' -replace '^', 'crop' } if ($arg -is [int] -and $currentKey) { $cropTable[$currentKey] = $arg $currentKey = '' } } $this | Set-OBSSceneItemTransform -SceneItemTransform $cropTable </Script> </ScriptMethod> <ScriptMethod> <Name>Delete</Name> <Script> $this.Remove() </Script> </ScriptMethod> <ScriptMethod> <Name>Disable</Name> <Script> $this | Set-OBSSceneItemEnabled -sceneItemEnabled:$false </Script> </ScriptMethod> <ScriptMethod> <Name>Enable</Name> <Script> param( [switch] $PassThru ) $this | Set-OBSSceneItemEnabled -sceneItemEnabled -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>FitToScreen</Name> <Script> <# .SYNOPSIS Fits an item to the screen .DESCRIPTION Centers an item and makes it fit to the screen. .LINK Get-OBSVideoSettings .LINK Get-OBSSceneItemTransform .LINK Set-OBSSceneItemTransform #> param() if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings $thisTransform = $this | Get-OBSSceneItemTransform $sceneItemTransform = ([Ordered]@{ alignment = 0 scaleX = ([double]$videoSettings.outputWidth / $thisTransform.sourceWidth ) positionX = [int]($videoSettings.outputWidth / 2) positionY = [int]($videoSettings.outputHeight / 2) scaleY = ([double]$videoSettings.outputHeight / $thisTransform.sourceHeight ) }) $this | Set-OBSSceneItemTransform -SceneItemTransform $sceneItemTransform </Script> </ScriptMethod> <ScriptMethod> <Name>Lock</Name> <Script> $this | Set-OBSSceneItemLocked -sceneItemLocked </Script> </ScriptMethod> <ScriptMethod> <Name>Move</Name> <Script> <# .SYNOPSIS Moves a scene item .DESCRIPTION Moves a scene item throughout the screen. This converts it's arguments to .Animate arguments. Any single values will be assumed to be positionX/positionY .EXAMPLE # Load a source $stars = Add-OBSBrowserSource -URI https://pssvg.start-automating.com/Examples/Stars.svg # fit it to the screen $stars.FitToScreen() # Move it diagonally across the screen $stars.Move("-50%","150%", "00:00:05") .LINK OBS.GetSceneItemList.Response.Animate #> param() $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ( $arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $positionTransform = @{ positionX = $arg positionY = $arg } $positionTransform } elseif ($arg.X,$arg.Y -ne $null) { $scaleInfo = @{} if ($null -ne $arg.X) { $scaleInfo.positionX = $arg.X } if ($null -ne $arg.Y) { $scaleInfo.positionY = $arg.Y } $scaleInfo } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { $arg } else { $arg } }) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> $this | Remove-OBSSceneItem </Script> </ScriptMethod> <ScriptMethod> <Name>Rotate</Name> <Script> param() $allArguments = @($args) $animateArguments = @( foreach ($argument in $allArguments) { if ($argument -is [double] -or $argument -is [int]) { @{ rotation = $argument } } elseif ($argument -as [timespan]) { $argument } elseif ($argument -is [bool]) { $argument } } ) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Scale</Name> <Script> param() $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ($arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $scale = $arg @{scaleX=$scale;scaleY=$scale} } elseif ($null -ne $arg.X -or $null -ne $arg.Y) { $scaleInfo = @{} if ($null -ne $arg.X) { $scaleInfo.scaleX = $arg.X } elseif ($null -ne $arg.scaleX) { $scaleInfo.scaleX = $arg.scaleX } if ($null -ne $arg.Y) { $scaleInfo.scaleY = $arg.Y } elseif ($null -ne $arg.scaleY) { $scaleInfo.scaleY = $arg.scaleY } $scaleInfo } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { $arg } else { $arg } }) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>SetZIndex</Name> <Script> $this | Set-OBSSceneItemIndex -SceneItemIndex ($args[0]) $this | Add-Member NoteProperty "sceneItemIndex" $args[0] -Force </Script> </ScriptMethod> <ScriptMethod> <Name>Stretch</Name> <Script> <# .SYNOPSIS Stretches a scene item .DESCRIPTION Stretches a scene item by changing it's bounds. #> param() $PassingThru = $false $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ($arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $scale = $arg @{scaleX=$scale;scaleY=$scale} } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { if ($arg) { $PassingThru = $true } $arg } else { $scaleInfo = @{} if ($null -ne $arg.Width) { $scaleInfo.boundsWidth = $arg.Width } elseif ($null -ne $arg.X) { $scaleInfo.boundsWidth = $arg.X } if ($null -ne $arg.Height) { $scaleInfo.boundsHeight = $arg.Height } elseif ($null -ne $arg.Y) { $scaleInfo.boundsHeight = $arg.Y } if ($scaleInfo.Count) { $scaleInfo } else { $arg } } }) $this | Set-OBSSceneItemTransform -SceneItemTransform @{boundsType='OBS_BOUNDS_STRETCH'} -NoResponse -PassThru:$PassingThru $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Unlock</Name> <Script> $this | Set-OBSSceneItemLocked -sceneItemLocked:$false </Script> </ScriptMethod> <ScriptProperty> <Name>BlendMode</Name> <GetScriptBlock> $this.sceneItemBlendMode -replace '^OBS_BLEND_' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Enabled</Name> <GetScriptBlock> return $this.sceneItemEnabled </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Filters</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Scene Item's filters .DESCRIPTION Gets the filters related to an OBS input. .EXAMPLE $obsPowerShellIcon = Show-OBS -Uri https://obs-powershell.start-automating.com/Assets/obs-powershell-animated-icon.svg $obsPowerShellIcon | Set-OBSColorFilter -Opacity .5 $obsPowerShellIcon.Filters .LINK Get-OBSSourceFilterList #> Get-OBSSourceFilterList -SourceName $this.SourceName </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ImageHeight</Name> <GetScriptBlock> $this.sceneItemTransform.sourceHeight </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ImageWidth</Name> <GetScriptBlock> $this.sceneItemTransform.sourceWidth </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Input</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Scene Item's Input .DESCRIPTION Gets the OBS Input related to the current scene item. This value is cached upon first request, as it will never change as long as the source item exists. .EXAMPLE $stars = Show-OBS -Uri https://pssvg.start-automating.com/Examples/Stars.svg $stars.Input #> if (-not $this.'.Input') { $this | Add-Member NoteProperty '.Input' ( $this | Get-OBSInput | Where-Object InputName -eq $this.SourceName ) -Force } $this.'.Input' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Layer</Name> <GetScriptBlock> return $this.sceneItemIndex </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ZIndex</Name> <GetScriptBlock> $indexInfo = $this | Get-OBSSceneItemIndex if ($indexInfo.SceneItemIndex) { $indexInfo.SceneItemIndex } elseif ($indexInfo -is [int]) { $indexInfo } </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.GetSceneItemId.Response</Name> <Members> <AliasProperty> <Name>Hide</Name> <ReferencedMemberName>Disable</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Show</Name> <ReferencedMemberName>Enable</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Animate</Name> <Script> <# .SYNOPSIS Animates scene items .DESCRIPTION Animates the motion of scene items within a frame. .EXAMPLE $stars = Add-OBSBrowserSource -URI https://pssvg.start-automating.com/Examples/Stars.svg $stars.FitToScreen() $stars.Animate(@{ scale = 0.1 },"00:00:01") #> param( ) filter ToPosition { param( [switch] $Width, [switch] $Height ) if ($_ -is [string] -and $_ -match '%$') { $_ = $_ -replace '%$' -as [double] if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings if ($Width) { $_/100 * $videoSettings.baseWidth } if ($Height) { $_/100 * $videoSettings.baseHeight } } elseif ($_ -is [double] -or $_ -is [int]) { if ($_ -is [double] -and $_ -ge 0 -and $_ -lt 1) { if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings if ($Width) { $_ * $videoSettings.baseWidth } if ($Height) { $_ * $videoSettings.baseHeight } } else { [int]$_ } } } filter ToScale { if ($_ -is [string] -and $_ -match '%$') { $_ = $_ -replace '%$' -as [double] $_/100 } elseif ($_ -is [double] -or $_ -is [int]) { if ($_ -is [double] -and $_ -ge 0 -and $_ -le 1) { $_ } else { [double]$_/100 } } } $nextTimeSpan = [timespan]0 $keyNames = 'boundsWidth','boundsHeight','positionX', 'positionY', 'scaleX','scaleY', 'cropBottom', 'cropLeft', 'cropRight', 'cropTop', 'rotation' $keyAliases = [Ordered]@{'Rotate'='rotation'} $duplicatedKeyAliases = [Ordered]@{ 'position' = 'positionX', 'positionY' 'scale' = 'scaleX', 'scaleY' 'crop' = 'cropBottom', 'cropLeft', 'cropRight', 'cropTop' } foreach ($position in 'X','Y') { $keyAliases[$position] = "position$position" } foreach ($cropType in 'Bottom','Left', 'Right', 'Top') { $keyAliases[$cropType] = "crop$cropType" } $allSteps = @() $originalTransform = $this | Get-OBSSceneItemTransform $lastFrom = if ($originalTransform -is [Collections.IDictionary]) { [Ordered]@{} + $from } else { $newFrom = [Ordered]@{} foreach ($property in $originalTransform.psobject.properties) { $newFrom[$property.Name] = $property.Value } $newFrom } $totalTimeSpan = [timespan]0 # We want to walk over every argument and turn them into a series of animations $PassThru = $false $AllArgs = @($args) $allSteps = @( :NextArgument for ($argIndex = 0 ; $argIndex -lt $allArgs.Length; $argIndex++) { $arg = $allArgs[$argIndex] # If the arg is a timespan, we want to track this if ($arg -as [timespan]) { $nextTimeSpan = $arg -as [timespan] } elseif ($arg -is [double] -or $arg -is [int]) { $nextTimeSpan = [timespan]::fromSeconds($arg) } elseif ($arg -is [bool]) { if ($arg) { $PassThru = $true } } else { $currentTo = if ($arg -isnot [Collections.IDictionary]) { $newTo = [Ordered]@{} foreach ($property in $arg.psobject.properties) { $newTo[$property.Name] = $property.Value } $newTo } else { [Ordered]@{} + $arg } $badKey = @(foreach ($k in @($currentTo.Keys)) { if ($k -notin $keyNames) { if ($keyAliases[$k]) { $currentTo[$keyAliases[$k]] = $currentTo[$k] $currentTo.Remove($k) } elseif ($duplicatedKeyAliases[$k]) { foreach ($duplicateKey in $duplicatedKeyAliases[$k]) { $currentTo[$duplicateKey] = $currentTo[$k] } $currentTo.Remove($k) } else { $k } } }) foreach ($checkKeyValue in @($currentTo.GetEnumerator())) { $newValue = switch ($checkKeyValue.Key) { positionX { $checkKeyValue.Value | ToPosition -Width } positionY { $checkKeyValue.Value | ToPosition -Height } cropLeft { $checkKeyValue.Value | ToPosition -Width } cropRight { $checkKeyValue.Value | ToPosition -Width } cropTop { $checkKeyValue.Value | ToPosition -Height } cropBottom { $checkKeyValue.Value | ToPosition -Height } scaleX { $checkKeyValue.Value | ToScale } scaleY { $checkKeyValue.Value | ToScale } } if ($null -ne $newValue) { $currentTo[$checkKeyValue.Key] = $newValue } } if ($badKey) { throw "Cannot animate '$($badKey -join "','")' : Can only animate $($keyNames -join ',')" } if (-not $nextTimeSpan.TotalMilliseconds -and ($argIndex -lt ($AllArgs.Length - 1)) -and $AllArgs[$argIndex + 1] -as [timespan] ) { $nextTimeSpan = $AllArgs[$argIndex + 1] -as [timespan] $argIndex++ } if ($lastFrom -and $nextTimeSpan) { $StepCount = [Math]::Ceiling($NextTimeSpan.TotalMilliseconds / ([timespan]::fromSeconds(1/30).TotalMilliseconds)) * 2 if (-not $StepCount) { $this | Set-OBSSceneItemTransform -SceneItemTransform $currentTo -PassThru $newLastFrom = [Ordered]@{} + $currentTo foreach ($kv in $lastFrom.GetEnumerator()) { if ($currentTo.Contains($kv.Key)) { continue } $newLastFrom[$kv.Key] = $kv.Value } $lastFrom = $newLastFrom # May need to join this with the remaining properties in from $totalTimeSpan += $nextTimeSpan $nextTimeSpan = [timespan]0 continue NextArgument } $stepMilliseconds = $nextTimeSpan.TotalMilliseconds / $StepCount # Compare the two sets of keys to determine the base data object $BaseObject = [Ordered]@{} foreach ($key in $currentTo.Keys) { if (-not $BaseObject[$key]) { $BaseObject[$key] = if ($null -ne $lastFrom[$key]) { $lastFrom[$key] } else { $currentTo[$key] } } } # Determine the animation change per step. $eachStepValue = [Ordered]@{} foreach ($key in $baseObject.Keys) { $distance = try { $currentTo[$key] - $baseObject[$key] } catch { $null } if ($null -ne $distance) { $eachStepValue[$key] = [float]$distance / $StepCount } } foreach ($stepNumber in 1..($stepCount)) { $stepObject = [Ordered]@{} foreach ($key in $BaseObject.Keys) { $stepObject[$key] = $BaseObject[$key] + ($eachStepValue[$key] * $stepNumber) } $this | Set-OBSSceneItemTransform -SceneItemTransform $stepObject -PassThru Send-OBSSleep -SleepMillis $stepMilliseconds -PassThru } } else { $this | Set-OBSSceneItemTransform -SceneItemTransform $currentTo -PassThru } $newLastFrom = [Ordered]@{} + $currentTo foreach ($kv in $lastFrom.GetEnumerator()) { if ($currentTo.Contains($kv.Key)) { continue } $newLastFrom[$kv.Key] = $kv.Value } $lastFrom = $newLastFrom # May need to join this with the remaining properties in from $totalTimeSpan += $nextTimeSpan $nextTimeSpan = [timespan]0 if (($argIndex -lt ($AllArgs.Length - 1)) -and $AllArgs[$argIndex + 1] -as [timespan] ) { Send-OBSSleep -SleepMillis ($AllArgs[$argIndex + 1] -as [timespan]).TotalMilliseconds -PassThru } } $IsFirstArg = $false } ) if ($allSteps) { # If any boolean true was in the arguments, we're passing thru if ($PassThru) { $allSteps } else { # Send all of the steps to OBS. $allSteps | Send-OBS } } </Script> </ScriptMethod> <ScriptMethod> <Name>Blend</Name> <Script> param([string]$BlendMode) if ($blendMode -cnotmatch '^OBS_BLEND_') { $blendMode = "OBS_BLEND_$($blendMode.ToUpper())" } $this | Set-OBSSceneItemBlendMode -SceneItemBlendMode $blendMode </Script> </ScriptMethod> <ScriptMethod> <Name>Center</Name> <Script> <# .SYNOPSIS Centers a scene item .DESCRIPTION Sets the scene item alignment to center .NOTES Also corrects the position so that the image does not only appear in a quadrant. If a boolean argument is passed, and it is true, then this will PassThru instead of run. (this can be used for animations) If an explicit null argument is passed, then the command will not wait for an OBS response. (this will be slightly faster) #> param() $passingThru = $false $NoResponse = $false foreach ($arg in $args) { if ($arg -is [bool]) { if ($arg) { $passingThru= $true } } if ($null -eq $arg) { $NoResponse = $true } } $sceneItemTransform = $this | Get-OBSSceneItemTransform $sceneItemTransform.alignment = 0 # 0 means center $sceneItemTransform.positionX = $sceneItemTransform.boundsWidth/2 $sceneItemTransform.positionY = $sceneItemTransform.boundsHeight/2 $this | Set-OBSSceneItemTransform -SceneItemTransform $sceneItemTransform -PassThru:$passingThru -NoResponse:$NoResponse </Script> </ScriptMethod> <ScriptMethod> <Name>Crop</Name> <Script> $cropTable = [Ordered]@{ cropBottom = 0 cropLeft = 0 cropRight = 0 cropTop = 0 } $MatchingKey = [Regex]::new("(?>$( @($cropTable.Keys -join '|' '|' $cropTable.Keys -replace '^crop' -join '|') -join '' ))", 'IgnoreCase') $currentKey = '' foreach ($arg in $args) { if ($arg -is [Collections.IDictionary]) { foreach ($keyValue in $arg.GetEnumerator()) { if ($keyValue.Key -match $MatchingKey) { $cropTable[$matches.0 -replace '^crop' -replace '^', 'crop'] = $keyValue.Value } } } if ($arg -is [string] -and $arg -match $MatchingKey) { $currentKey = $matches.0 -replace '^crop' -replace '^', 'crop' } if ($arg -is [int] -and $currentKey) { $cropTable[$currentKey] = $arg $currentKey = '' } } $this | Set-OBSSceneItemTransform -SceneItemTransform $cropTable </Script> </ScriptMethod> <ScriptMethod> <Name>Delete</Name> <Script> $this.Remove() </Script> </ScriptMethod> <ScriptMethod> <Name>Disable</Name> <Script> $this | Set-OBSSceneItemEnabled -sceneItemEnabled:$false </Script> </ScriptMethod> <ScriptMethod> <Name>Enable</Name> <Script> param( [switch] $PassThru ) $this | Set-OBSSceneItemEnabled -sceneItemEnabled -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>FitToScreen</Name> <Script> <# .SYNOPSIS Fits an item to the screen .DESCRIPTION Centers an item and makes it fit to the screen. .LINK Get-OBSVideoSettings .LINK Get-OBSSceneItemTransform .LINK Set-OBSSceneItemTransform #> param() if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings $thisTransform = $this | Get-OBSSceneItemTransform $sceneItemTransform = ([Ordered]@{ alignment = 0 scaleX = ([double]$videoSettings.outputWidth / $thisTransform.sourceWidth ) positionX = [int]($videoSettings.outputWidth / 2) positionY = [int]($videoSettings.outputHeight / 2) scaleY = ([double]$videoSettings.outputHeight / $thisTransform.sourceHeight ) }) $this | Set-OBSSceneItemTransform -SceneItemTransform $sceneItemTransform </Script> </ScriptMethod> <ScriptMethod> <Name>Lock</Name> <Script> $this | Set-OBSSceneItemLocked -sceneItemLocked </Script> </ScriptMethod> <ScriptMethod> <Name>Move</Name> <Script> <# .SYNOPSIS Moves a scene item .DESCRIPTION Moves a scene item throughout the screen. This converts it's arguments to .Animate arguments. Any single values will be assumed to be positionX/positionY .EXAMPLE # Load a source $stars = Add-OBSBrowserSource -URI https://pssvg.start-automating.com/Examples/Stars.svg # fit it to the screen $stars.FitToScreen() # Move it diagonally across the screen $stars.Move("-50%","150%", "00:00:05") .LINK OBS.GetSceneItemList.Response.Animate #> param() $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ( $arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $positionTransform = @{ positionX = $arg positionY = $arg } $positionTransform } elseif ($arg.X,$arg.Y -ne $null) { $scaleInfo = @{} if ($null -ne $arg.X) { $scaleInfo.positionX = $arg.X } if ($null -ne $arg.Y) { $scaleInfo.positionY = $arg.Y } $scaleInfo } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { $arg } else { $arg } }) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> $this | Remove-OBSSceneItem </Script> </ScriptMethod> <ScriptMethod> <Name>Rotate</Name> <Script> param() $allArguments = @($args) $animateArguments = @( foreach ($argument in $allArguments) { if ($argument -is [double] -or $argument -is [int]) { @{ rotation = $argument } } elseif ($argument -as [timespan]) { $argument } elseif ($argument -is [bool]) { $argument } } ) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Scale</Name> <Script> param() $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ($arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $scale = $arg @{scaleX=$scale;scaleY=$scale} } elseif ($null -ne $arg.X -or $null -ne $arg.Y) { $scaleInfo = @{} if ($null -ne $arg.X) { $scaleInfo.scaleX = $arg.X } elseif ($null -ne $arg.scaleX) { $scaleInfo.scaleX = $arg.scaleX } if ($null -ne $arg.Y) { $scaleInfo.scaleY = $arg.Y } elseif ($null -ne $arg.scaleY) { $scaleInfo.scaleY = $arg.scaleY } $scaleInfo } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { $arg } else { $arg } }) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>SetZIndex</Name> <Script> $this | Set-OBSSceneItemIndex -SceneItemIndex ($args[0]) $this | Add-Member NoteProperty "sceneItemIndex" $args[0] -Force </Script> </ScriptMethod> <ScriptMethod> <Name>Stretch</Name> <Script> <# .SYNOPSIS Stretches a scene item .DESCRIPTION Stretches a scene item by changing it's bounds. #> param() $PassingThru = $false $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ($arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $scale = $arg @{scaleX=$scale;scaleY=$scale} } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { if ($arg) { $PassingThru = $true } $arg } else { $scaleInfo = @{} if ($null -ne $arg.Width) { $scaleInfo.boundsWidth = $arg.Width } elseif ($null -ne $arg.X) { $scaleInfo.boundsWidth = $arg.X } if ($null -ne $arg.Height) { $scaleInfo.boundsHeight = $arg.Height } elseif ($null -ne $arg.Y) { $scaleInfo.boundsHeight = $arg.Y } if ($scaleInfo.Count) { $scaleInfo } else { $arg } } }) $this | Set-OBSSceneItemTransform -SceneItemTransform @{boundsType='OBS_BOUNDS_STRETCH'} -NoResponse -PassThru:$PassingThru $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Unlock</Name> <Script> $this | Set-OBSSceneItemLocked -sceneItemLocked:$false </Script> </ScriptMethod> <ScriptProperty> <Name>BlendMode</Name> <GetScriptBlock> $this.sceneItemBlendMode -replace '^OBS_BLEND_' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Enabled</Name> <GetScriptBlock> return $this.sceneItemEnabled </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Filters</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Scene Item's filters .DESCRIPTION Gets the filters related to an OBS input. .EXAMPLE $obsPowerShellIcon = Show-OBS -Uri https://obs-powershell.start-automating.com/Assets/obs-powershell-animated-icon.svg $obsPowerShellIcon | Set-OBSColorFilter -Opacity .5 $obsPowerShellIcon.Filters .LINK Get-OBSSourceFilterList #> Get-OBSSourceFilterList -SourceName $this.SourceName </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ImageHeight</Name> <GetScriptBlock> $this.sceneItemTransform.sourceHeight </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ImageWidth</Name> <GetScriptBlock> $this.sceneItemTransform.sourceWidth </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Input</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Scene Item's Input .DESCRIPTION Gets the OBS Input related to the current scene item. This value is cached upon first request, as it will never change as long as the source item exists. .EXAMPLE $stars = Show-OBS -Uri https://pssvg.start-automating.com/Examples/Stars.svg $stars.Input #> if (-not $this.'.Input') { $this | Add-Member NoteProperty '.Input' ( $this | Get-OBSInput | Where-Object InputName -eq $this.SourceName ) -Force } $this.'.Input' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Layer</Name> <GetScriptBlock> return $this.sceneItemIndex </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ZIndex</Name> <GetScriptBlock> $indexInfo = $this | Get-OBSSceneItemIndex if ($indexInfo.SceneItemIndex) { $indexInfo.SceneItemIndex } elseif ($indexInfo -is [int]) { $indexInfo } </GetScriptBlock> </ScriptProperty> </Members> </Type> <Type> <Name>OBS.SceneItem</Name> <Members> <AliasProperty> <Name>Hide</Name> <ReferencedMemberName>Disable</ReferencedMemberName> </AliasProperty> <AliasProperty> <Name>Show</Name> <ReferencedMemberName>Enable</ReferencedMemberName> </AliasProperty> <ScriptMethod> <Name>Animate</Name> <Script> <# .SYNOPSIS Animates scene items .DESCRIPTION Animates the motion of scene items within a frame. .EXAMPLE $stars = Add-OBSBrowserSource -URI https://pssvg.start-automating.com/Examples/Stars.svg $stars.FitToScreen() $stars.Animate(@{ scale = 0.1 },"00:00:01") #> param( ) filter ToPosition { param( [switch] $Width, [switch] $Height ) if ($_ -is [string] -and $_ -match '%$') { $_ = $_ -replace '%$' -as [double] if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings if ($Width) { $_/100 * $videoSettings.baseWidth } if ($Height) { $_/100 * $videoSettings.baseHeight } } elseif ($_ -is [double] -or $_ -is [int]) { if ($_ -is [double] -and $_ -ge 0 -and $_ -lt 1) { if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings if ($Width) { $_ * $videoSettings.baseWidth } if ($Height) { $_ * $videoSettings.baseHeight } } else { [int]$_ } } } filter ToScale { if ($_ -is [string] -and $_ -match '%$') { $_ = $_ -replace '%$' -as [double] $_/100 } elseif ($_ -is [double] -or $_ -is [int]) { if ($_ -is [double] -and $_ -ge 0 -and $_ -le 1) { $_ } else { [double]$_/100 } } } $nextTimeSpan = [timespan]0 $keyNames = 'boundsWidth','boundsHeight','positionX', 'positionY', 'scaleX','scaleY', 'cropBottom', 'cropLeft', 'cropRight', 'cropTop', 'rotation' $keyAliases = [Ordered]@{'Rotate'='rotation'} $duplicatedKeyAliases = [Ordered]@{ 'position' = 'positionX', 'positionY' 'scale' = 'scaleX', 'scaleY' 'crop' = 'cropBottom', 'cropLeft', 'cropRight', 'cropTop' } foreach ($position in 'X','Y') { $keyAliases[$position] = "position$position" } foreach ($cropType in 'Bottom','Left', 'Right', 'Top') { $keyAliases[$cropType] = "crop$cropType" } $allSteps = @() $originalTransform = $this | Get-OBSSceneItemTransform $lastFrom = if ($originalTransform -is [Collections.IDictionary]) { [Ordered]@{} + $from } else { $newFrom = [Ordered]@{} foreach ($property in $originalTransform.psobject.properties) { $newFrom[$property.Name] = $property.Value } $newFrom } $totalTimeSpan = [timespan]0 # We want to walk over every argument and turn them into a series of animations $PassThru = $false $AllArgs = @($args) $allSteps = @( :NextArgument for ($argIndex = 0 ; $argIndex -lt $allArgs.Length; $argIndex++) { $arg = $allArgs[$argIndex] # If the arg is a timespan, we want to track this if ($arg -as [timespan]) { $nextTimeSpan = $arg -as [timespan] } elseif ($arg -is [double] -or $arg -is [int]) { $nextTimeSpan = [timespan]::fromSeconds($arg) } elseif ($arg -is [bool]) { if ($arg) { $PassThru = $true } } else { $currentTo = if ($arg -isnot [Collections.IDictionary]) { $newTo = [Ordered]@{} foreach ($property in $arg.psobject.properties) { $newTo[$property.Name] = $property.Value } $newTo } else { [Ordered]@{} + $arg } $badKey = @(foreach ($k in @($currentTo.Keys)) { if ($k -notin $keyNames) { if ($keyAliases[$k]) { $currentTo[$keyAliases[$k]] = $currentTo[$k] $currentTo.Remove($k) } elseif ($duplicatedKeyAliases[$k]) { foreach ($duplicateKey in $duplicatedKeyAliases[$k]) { $currentTo[$duplicateKey] = $currentTo[$k] } $currentTo.Remove($k) } else { $k } } }) foreach ($checkKeyValue in @($currentTo.GetEnumerator())) { $newValue = switch ($checkKeyValue.Key) { positionX { $checkKeyValue.Value | ToPosition -Width } positionY { $checkKeyValue.Value | ToPosition -Height } cropLeft { $checkKeyValue.Value | ToPosition -Width } cropRight { $checkKeyValue.Value | ToPosition -Width } cropTop { $checkKeyValue.Value | ToPosition -Height } cropBottom { $checkKeyValue.Value | ToPosition -Height } scaleX { $checkKeyValue.Value | ToScale } scaleY { $checkKeyValue.Value | ToScale } } if ($null -ne $newValue) { $currentTo[$checkKeyValue.Key] = $newValue } } if ($badKey) { throw "Cannot animate '$($badKey -join "','")' : Can only animate $($keyNames -join ',')" } if (-not $nextTimeSpan.TotalMilliseconds -and ($argIndex -lt ($AllArgs.Length - 1)) -and $AllArgs[$argIndex + 1] -as [timespan] ) { $nextTimeSpan = $AllArgs[$argIndex + 1] -as [timespan] $argIndex++ } if ($lastFrom -and $nextTimeSpan) { $StepCount = [Math]::Ceiling($NextTimeSpan.TotalMilliseconds / ([timespan]::fromSeconds(1/30).TotalMilliseconds)) * 2 if (-not $StepCount) { $this | Set-OBSSceneItemTransform -SceneItemTransform $currentTo -PassThru $newLastFrom = [Ordered]@{} + $currentTo foreach ($kv in $lastFrom.GetEnumerator()) { if ($currentTo.Contains($kv.Key)) { continue } $newLastFrom[$kv.Key] = $kv.Value } $lastFrom = $newLastFrom # May need to join this with the remaining properties in from $totalTimeSpan += $nextTimeSpan $nextTimeSpan = [timespan]0 continue NextArgument } $stepMilliseconds = $nextTimeSpan.TotalMilliseconds / $StepCount # Compare the two sets of keys to determine the base data object $BaseObject = [Ordered]@{} foreach ($key in $currentTo.Keys) { if (-not $BaseObject[$key]) { $BaseObject[$key] = if ($null -ne $lastFrom[$key]) { $lastFrom[$key] } else { $currentTo[$key] } } } # Determine the animation change per step. $eachStepValue = [Ordered]@{} foreach ($key in $baseObject.Keys) { $distance = try { $currentTo[$key] - $baseObject[$key] } catch { $null } if ($null -ne $distance) { $eachStepValue[$key] = [float]$distance / $StepCount } } foreach ($stepNumber in 1..($stepCount)) { $stepObject = [Ordered]@{} foreach ($key in $BaseObject.Keys) { $stepObject[$key] = $BaseObject[$key] + ($eachStepValue[$key] * $stepNumber) } $this | Set-OBSSceneItemTransform -SceneItemTransform $stepObject -PassThru Send-OBSSleep -SleepMillis $stepMilliseconds -PassThru } } else { $this | Set-OBSSceneItemTransform -SceneItemTransform $currentTo -PassThru } $newLastFrom = [Ordered]@{} + $currentTo foreach ($kv in $lastFrom.GetEnumerator()) { if ($currentTo.Contains($kv.Key)) { continue } $newLastFrom[$kv.Key] = $kv.Value } $lastFrom = $newLastFrom # May need to join this with the remaining properties in from $totalTimeSpan += $nextTimeSpan $nextTimeSpan = [timespan]0 if (($argIndex -lt ($AllArgs.Length - 1)) -and $AllArgs[$argIndex + 1] -as [timespan] ) { Send-OBSSleep -SleepMillis ($AllArgs[$argIndex + 1] -as [timespan]).TotalMilliseconds -PassThru } } $IsFirstArg = $false } ) if ($allSteps) { # If any boolean true was in the arguments, we're passing thru if ($PassThru) { $allSteps } else { # Send all of the steps to OBS. $allSteps | Send-OBS } } </Script> </ScriptMethod> <ScriptMethod> <Name>Blend</Name> <Script> param([string]$BlendMode) if ($blendMode -cnotmatch '^OBS_BLEND_') { $blendMode = "OBS_BLEND_$($blendMode.ToUpper())" } $this | Set-OBSSceneItemBlendMode -SceneItemBlendMode $blendMode </Script> </ScriptMethod> <ScriptMethod> <Name>Center</Name> <Script> <# .SYNOPSIS Centers a scene item .DESCRIPTION Sets the scene item alignment to center .NOTES Also corrects the position so that the image does not only appear in a quadrant. If a boolean argument is passed, and it is true, then this will PassThru instead of run. (this can be used for animations) If an explicit null argument is passed, then the command will not wait for an OBS response. (this will be slightly faster) #> param() $passingThru = $false $NoResponse = $false foreach ($arg in $args) { if ($arg -is [bool]) { if ($arg) { $passingThru= $true } } if ($null -eq $arg) { $NoResponse = $true } } $sceneItemTransform = $this | Get-OBSSceneItemTransform $sceneItemTransform.alignment = 0 # 0 means center $sceneItemTransform.positionX = $sceneItemTransform.boundsWidth/2 $sceneItemTransform.positionY = $sceneItemTransform.boundsHeight/2 $this | Set-OBSSceneItemTransform -SceneItemTransform $sceneItemTransform -PassThru:$passingThru -NoResponse:$NoResponse </Script> </ScriptMethod> <ScriptMethod> <Name>Crop</Name> <Script> $cropTable = [Ordered]@{ cropBottom = 0 cropLeft = 0 cropRight = 0 cropTop = 0 } $MatchingKey = [Regex]::new("(?>$( @($cropTable.Keys -join '|' '|' $cropTable.Keys -replace '^crop' -join '|') -join '' ))", 'IgnoreCase') $currentKey = '' foreach ($arg in $args) { if ($arg -is [Collections.IDictionary]) { foreach ($keyValue in $arg.GetEnumerator()) { if ($keyValue.Key -match $MatchingKey) { $cropTable[$matches.0 -replace '^crop' -replace '^', 'crop'] = $keyValue.Value } } } if ($arg -is [string] -and $arg -match $MatchingKey) { $currentKey = $matches.0 -replace '^crop' -replace '^', 'crop' } if ($arg -is [int] -and $currentKey) { $cropTable[$currentKey] = $arg $currentKey = '' } } $this | Set-OBSSceneItemTransform -SceneItemTransform $cropTable </Script> </ScriptMethod> <ScriptMethod> <Name>Delete</Name> <Script> $this.Remove() </Script> </ScriptMethod> <ScriptMethod> <Name>Disable</Name> <Script> $this | Set-OBSSceneItemEnabled -sceneItemEnabled:$false </Script> </ScriptMethod> <ScriptMethod> <Name>Enable</Name> <Script> param( [switch] $PassThru ) $this | Set-OBSSceneItemEnabled -sceneItemEnabled -PassThru:$PassThru </Script> </ScriptMethod> <ScriptMethod> <Name>FitToScreen</Name> <Script> <# .SYNOPSIS Fits an item to the screen .DESCRIPTION Centers an item and makes it fit to the screen. .LINK Get-OBSVideoSettings .LINK Get-OBSSceneItemTransform .LINK Set-OBSSceneItemTransform #> param() if (-not $script:CachedOBSVideoSettings) { $script:CachedOBSVideoSettings = Get-OBSVideoSettings } $videoSettings = $script:CachedOBSVideoSettings $thisTransform = $this | Get-OBSSceneItemTransform $sceneItemTransform = ([Ordered]@{ alignment = 0 scaleX = ([double]$videoSettings.outputWidth / $thisTransform.sourceWidth ) positionX = [int]($videoSettings.outputWidth / 2) positionY = [int]($videoSettings.outputHeight / 2) scaleY = ([double]$videoSettings.outputHeight / $thisTransform.sourceHeight ) }) $this | Set-OBSSceneItemTransform -SceneItemTransform $sceneItemTransform </Script> </ScriptMethod> <ScriptMethod> <Name>Lock</Name> <Script> $this | Set-OBSSceneItemLocked -sceneItemLocked </Script> </ScriptMethod> <ScriptMethod> <Name>Move</Name> <Script> <# .SYNOPSIS Moves a scene item .DESCRIPTION Moves a scene item throughout the screen. This converts it's arguments to .Animate arguments. Any single values will be assumed to be positionX/positionY .EXAMPLE # Load a source $stars = Add-OBSBrowserSource -URI https://pssvg.start-automating.com/Examples/Stars.svg # fit it to the screen $stars.FitToScreen() # Move it diagonally across the screen $stars.Move("-50%","150%", "00:00:05") .LINK OBS.GetSceneItemList.Response.Animate #> param() $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ( $arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $positionTransform = @{ positionX = $arg positionY = $arg } $positionTransform } elseif ($arg.X,$arg.Y -ne $null) { $scaleInfo = @{} if ($null -ne $arg.X) { $scaleInfo.positionX = $arg.X } if ($null -ne $arg.Y) { $scaleInfo.positionY = $arg.Y } $scaleInfo } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { $arg } else { $arg } }) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Remove</Name> <Script> $this | Remove-OBSSceneItem </Script> </ScriptMethod> <ScriptMethod> <Name>Rotate</Name> <Script> param() $allArguments = @($args) $animateArguments = @( foreach ($argument in $allArguments) { if ($argument -is [double] -or $argument -is [int]) { @{ rotation = $argument } } elseif ($argument -as [timespan]) { $argument } elseif ($argument -is [bool]) { $argument } } ) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Scale</Name> <Script> param() $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ($arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $scale = $arg @{scaleX=$scale;scaleY=$scale} } elseif ($null -ne $arg.X -or $null -ne $arg.Y) { $scaleInfo = @{} if ($null -ne $arg.X) { $scaleInfo.scaleX = $arg.X } elseif ($null -ne $arg.scaleX) { $scaleInfo.scaleX = $arg.scaleX } if ($null -ne $arg.Y) { $scaleInfo.scaleY = $arg.Y } elseif ($null -ne $arg.scaleY) { $scaleInfo.scaleY = $arg.scaleY } $scaleInfo } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { $arg } else { $arg } }) $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>SetZIndex</Name> <Script> $this | Set-OBSSceneItemIndex -SceneItemIndex ($args[0]) $this | Add-Member NoteProperty "sceneItemIndex" $args[0] -Force </Script> </ScriptMethod> <ScriptMethod> <Name>Stretch</Name> <Script> <# .SYNOPSIS Stretches a scene item .DESCRIPTION Stretches a scene item by changing it's bounds. #> param() $PassingThru = $false $allArguments = @($args) $animateArguments = @( foreach ($arg in $allArguments) { if ($arg -is [double] -or $arg -is [int] -or ($arg -is [string] -and $arg -match '\%$') ) { $scale = $arg @{scaleX=$scale;scaleY=$scale} } elseif ($arg -as [timespan]) { $arg } elseif ($arg -is [bool]) { if ($arg) { $PassingThru = $true } $arg } else { $scaleInfo = @{} if ($null -ne $arg.Width) { $scaleInfo.boundsWidth = $arg.Width } elseif ($null -ne $arg.X) { $scaleInfo.boundsWidth = $arg.X } if ($null -ne $arg.Height) { $scaleInfo.boundsHeight = $arg.Height } elseif ($null -ne $arg.Y) { $scaleInfo.boundsHeight = $arg.Y } if ($scaleInfo.Count) { $scaleInfo } else { $arg } } }) $this | Set-OBSSceneItemTransform -SceneItemTransform @{boundsType='OBS_BOUNDS_STRETCH'} -NoResponse -PassThru:$PassingThru $this.Animate.Invoke($animateArguments) </Script> </ScriptMethod> <ScriptMethod> <Name>Unlock</Name> <Script> $this | Set-OBSSceneItemLocked -sceneItemLocked:$false </Script> </ScriptMethod> <ScriptProperty> <Name>BlendMode</Name> <GetScriptBlock> $this.sceneItemBlendMode -replace '^OBS_BLEND_' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Enabled</Name> <GetScriptBlock> return $this.sceneItemEnabled </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Filters</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Scene Item's filters .DESCRIPTION Gets the filters related to an OBS input. .EXAMPLE $obsPowerShellIcon = Show-OBS -Uri https://obs-powershell.start-automating.com/Assets/obs-powershell-animated-icon.svg $obsPowerShellIcon | Set-OBSColorFilter -Opacity .5 $obsPowerShellIcon.Filters .LINK Get-OBSSourceFilterList #> Get-OBSSourceFilterList -SourceName $this.SourceName </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ImageHeight</Name> <GetScriptBlock> $this.sceneItemTransform.sourceHeight </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ImageWidth</Name> <GetScriptBlock> $this.sceneItemTransform.sourceWidth </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Input</Name> <GetScriptBlock> <# .SYNOPSIS Gets a Scene Item's Input .DESCRIPTION Gets the OBS Input related to the current scene item. This value is cached upon first request, as it will never change as long as the source item exists. .EXAMPLE $stars = Show-OBS -Uri https://pssvg.start-automating.com/Examples/Stars.svg $stars.Input #> if (-not $this.'.Input') { $this | Add-Member NoteProperty '.Input' ( $this | Get-OBSInput | Where-Object InputName -eq $this.SourceName ) -Force } $this.'.Input' </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>Layer</Name> <GetScriptBlock> return $this.sceneItemIndex </GetScriptBlock> </ScriptProperty> <ScriptProperty> <Name>ZIndex</Name> <GetScriptBlock> $indexInfo = $this | Get-OBSSceneItemIndex if ($indexInfo.SceneItemIndex) { $indexInfo.SceneItemIndex } elseif ($indexInfo -is [int]) { $indexInfo } </GetScriptBlock> </ScriptProperty> </Members> </Type> </Types> |