Skip to content
This repository has been archived by the owner on Jun 4, 2024. It is now read-only.

Commit

Permalink
Feature: Sets
Browse files Browse the repository at this point in the history
- Applies settings to multiple scenes and only triggers when the group is entered/left
- Useful when having multiple scenes with the same camera angle. When manually
adjusting the camera, the camera will not be controlled until you enter
a new Group
- Neutral groups behave as if they are of the same group as the previously active slot
  • Loading branch information
CShark committed May 28, 2022
1 parent 32f7008 commit 7a4d792
Show file tree
Hide file tree
Showing 32 changed files with 1,030 additions and 206 deletions.
24 changes: 18 additions & 6 deletions BetterMultiview/ObsMultiview/Controls/SceneSlot.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,16 @@
d:DesignHeight="450" d:DesignWidth="800">
<UserControl.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis" />
<converters:StringToVis x:Key="StringToVis" />
<converters:NullToVis x:Key="StringToVis" />
</UserControl.Resources>
<Grid DataContext="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl}}">

<Border Background="#4CFF0000" Visibility="{Binding IsInvalid, Converter={StaticResource BoolToVis}}">
<TextBlock FontFamily="Segoe MDL2 Assets" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="150" Foreground="DarkRed">&#xE7BA;</TextBlock>
</Border>

<Border Background="#4CFF0000" Visibility="{Binding IsInvalid, Converter={StaticResource BoolToVis}}">
<TextBlock FontFamily="Segoe MDL2 Assets" VerticalAlignment="Center" HorizontalAlignment="Center"
FontSize="150" Foreground="DarkRed">
&#xE7BA;
</TextBlock>
</Border>

<Rectangle Fill="#254682B4" Visibility="{Binding Unconfigured, Converter={StaticResource BoolToVis}}" />
<Rectangle Stroke="DarkGray" StrokeThickness="6" Margin="-6" />
Expand All @@ -36,6 +39,15 @@
Background="#83000000" VerticalAlignment="Top" Padding="5" FontSize="20"
Visibility="{Binding Name, Converter={StaticResource StringToVis}}" />


<TextBlock HorizontalAlignment="Center" Margin="20" Foreground="White" Background="#83000000"
VerticalAlignment="Bottom" Padding="5" FontSize="20"
Visibility="{Binding Set, Converter={StaticResource StringToVis}}">
<Rectangle Width="20" Height="20" Margin="-2">
<Rectangle.Fill>
<SolidColorBrush Color="{Binding Set.Color}"></SolidColorBrush>
</Rectangle.Fill>
</Rectangle>
<Run Text="{Binding Set.Name}"></Run>
</TextBlock>
</Grid>
</UserControl>
14 changes: 13 additions & 1 deletion BetterMultiview/ObsMultiview/Controls/SceneSlot.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using System.Linq;
using System.Printing;
using System.Windows;
using System.Windows.Controls;
Expand Down Expand Up @@ -67,6 +68,14 @@ public partial class SceneSlot : UserControl {
set { SetValue(SlotConfiguringProperty, value); }
}

public static readonly DependencyProperty SetProperty = DependencyProperty.Register(
nameof(Set), typeof(Set), typeof(SceneSlot), new PropertyMetadata(default(Set)));

public Set Set {
get { return (Set)GetValue(SetProperty); }
set { SetValue(SetProperty, value); }
}

public SceneSlot(UserProfile.DSlot slot, StreamView owner) {
_slot = slot;
_owner = owner;
Expand Down Expand Up @@ -113,10 +122,13 @@ public partial class SceneSlot : UserControl {
private void LoadSlot() {
Unconfigured = string.IsNullOrEmpty(_slot.Obs.Scene);
Name = _slot.Name;
Set = _profile.ActiveProfile?.SceneView?.Sets.FirstOrDefault(x => x.Id == _slot.SetId);
}

private void SceneSlot_OnMouseRightButtonUp(object sender, MouseButtonEventArgs e) {
var config = new SlotConfig(_slot);
if (_profile.ActiveProfile == null) return;

var config = new SlotConfig(_slot, _profile.ActiveProfile.SceneView);
config.Owner = Window.GetWindow(this);

_plugins.PausePlugins(null, true);
Expand Down
2 changes: 1 addition & 1 deletion BetterMultiview/ObsMultiview/Converters/StringToVis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace ObsMultiview.Converters {
/// <summary>
/// Convert a string to visibility (null or whitespace => hidden)
/// </summary>
public class StringToVis : IValueConverter {
public class NullToVis : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
if (value is string s) {
return string.IsNullOrWhiteSpace(s) ? Visibility.Collapsed : Visibility.Visible;
Expand Down
19 changes: 19 additions & 0 deletions BetterMultiview/ObsMultiview/Data/IPluginSettingsProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;

namespace ObsMultiview.Data {
public interface IPluginSettingsProvider {
JObject GetPluginSettings(string pluginId);

void SetPluginSettings(string pluginId, JObject pluginSettings);

Guid Id { get; }

string Name { get; set; }
}
}
63 changes: 63 additions & 0 deletions BetterMultiview/ObsMultiview/Data/Set.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using JetBrains.Annotations;
using Newtonsoft.Json.Linq;

namespace ObsMultiview.Data {
public class Set : INotifyPropertyChanged, IPluginSettingsProvider {
private Color _color;
public string Name { get; set; }

/// <summary>
/// Plugin configs
/// </summary>
public Dictionary<string, JObject> PluginConfigs { get; set; } = new();

public void SetPluginSettings(string pluginId, JObject pluginSettings) {
if (pluginSettings == null) {
PluginConfigs.Remove(pluginId);
} else {
PluginConfigs[pluginId] = pluginSettings;
}
}

public Guid? Id { get; set; }

Guid IPluginSettingsProvider.Id => Id ?? Guid.Empty;

public Color Color {
get => _color;
set {
if (value.Equals(_color)) return;
_color = value;
OnPropertyChanged();
}
}

public Set() {
Id = Guid.NewGuid();
PluginConfigs = new Dictionary<string, JObject>();
}

public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public JObject GetPluginSettings(string pluginId) {
if (PluginConfigs.ContainsKey(pluginId)) {
return PluginConfigs[pluginId];
} else {
return null;
}
}
}
}
67 changes: 64 additions & 3 deletions BetterMultiview/ObsMultiview/Data/UserProfile.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Windows.Media;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

Expand All @@ -11,18 +17,40 @@ public class UserProfile {
/// <summary>
/// Config options for a single slot
/// </summary>
public class DSlot {
public class DSlot : INotifyPropertyChanged, IPluginSettingsProvider {
private string _name;

/// <summary>
/// Name of the slot
/// </summary>
public string Name { get; set; }
public string Name {
get => _name;
set {
if (value == _name) return;
_name = value;
OnPropertyChanged();
}
}

public void SetPluginSettings(string pluginId, JObject pluginSettings) {
if (pluginSettings == null) {
PluginConfigs.Remove(pluginId);
} else {
PluginConfigs[pluginId] = pluginSettings;
}
}

/// <summary>
/// internal id of the slot. Not persistent during restarts
/// </summary>
[JsonIgnore]
public Guid Id { get; }

/// <summary>
/// The id of the set this slot belongs to
/// </summary>
public Guid? SetId { get; set; }

/// <summary>
/// OBS config
/// </summary>
Expand All @@ -36,6 +64,12 @@ public class DSlot {
public DSlot() {
Obs = new DSlotObs();
Id = Guid.NewGuid();
PluginConfigs = new();
}

[OnDeserialized]
private void OnDeserialized(StreamingContext context) {
if (PluginConfigs == null) PluginConfigs = new();
}

public static bool operator ==(DSlot a, DSlot b) {
Expand All @@ -45,6 +79,21 @@ public class DSlot {
public static bool operator !=(DSlot a, DSlot b) {
return !(a == b);
}

public event PropertyChangedEventHandler PropertyChanged;

[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) {
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}

public JObject GetPluginSettings(string pluginId) {
if (PluginConfigs.ContainsKey(pluginId)) {
return PluginConfigs[pluginId];
} else {
return null;
}
}
}

/// <summary>
Expand Down Expand Up @@ -72,9 +121,21 @@ public class DSceneViewConfig {
public int Columns { get; set; } = 6;

public List<DSlot> Slots { get; set; }
public List<Set> Sets { get; set; }

public DSceneViewConfig() {
Slots = new List<DSlot>();
Sets = new List<Set>();
Sets.Add(new Set {
Color = Colors.DarkGray,
Name = "Neutral",
Id = Guid.Empty
});
}

[OnDeserialized]
internal void OnDeserialized(StreamingContext context) {
Sets = Sets.DistinctBy(x => x.Id).ToList();
}
}

Expand Down Expand Up @@ -102,7 +163,7 @@ public class DObsProfile {

public DObsProfile(string id, int rows, int columns) {
Id = id;
SceneView = new DSceneViewConfig {Rows = rows, Columns = columns};
SceneView = new DSceneViewConfig { Rows = rows, Columns = columns };
}
}

Expand Down
61 changes: 61 additions & 0 deletions BetterMultiview/ObsMultiview/Dialogs/SetConfig.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
<Window x:Class="ObsMultiview.Dialogs.SetConfig"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:ObsMultiview"
xmlns:lex="http://wpflocalizeextension.codeplex.com"
xmlns:data="clr-namespace:ObsMultiview.Data"
xmlns:converters="clr-namespace:ObsMultiview.Converters"
mc:Ignorable="d"
Icon="pack://application:,,,/ObsMultiview;component/Images/Icon.png"
Closing="SlotConfig_OnClosing"
MinWidth="345"
WindowStartupLocation="CenterOwner"
lex:LocalizeDictionary.DesignCulture="en"
lex:ResxLocalizationProvider.DefaultAssembly="ObsMultiview"
lex:ResxLocalizationProvider.DefaultDictionary="Dialogs"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="{lex:Loc SetConfig}" Height="450" Width="345">
<Grid>
<Grid.Resources>
<converters:NullToVis x:Key="NullToVis" />

<Style TargetType="TextBlock">
<Setter Property="Margin" Value="2" />
</Style>

<Style TargetType="TextBox">
<Setter Property="Margin" Value="2" />
</Style>

<Style TargetType="Rectangle">
<Setter Property="Margin" Value="0,5" />
</Style>

<Style TargetType="ComboBox">
<Setter Property="Margin" Value="2" />
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<ScrollViewer HorizontalScrollBarVisibility="Disabled" VerticalScrollBarVisibility="Auto">
<StackPanel Margin="5" x:Name="ConfigPanel">
<TextBlock Text="{lex:Loc Name}" />
<TextBox Text="{Binding Set.Name}" x:Name="input" />
<Rectangle Height="2" Fill="LightGray" />
</StackPanel>
</ScrollViewer>
<StackPanel Orientation="Horizontal" Grid.Row="1">
<Button Width="100" Margin="5" Padding="2" Click="Ok_OnClick" Content="{lex:Loc Ok}" />
<Button Width="100" Margin="5" Padding="2" Click="Cancel_OnClick" Content="{lex:Loc Cancel}" />
<Button Margin="5" Padding="2" Width="100" FontFamily="Segoe MDL2 Assets" FontWeight="Bold"
Foreground="Red" Click="Unlink_OnClick">
&#xE711;
</Button>
</StackPanel>
</Grid>
</Window>
Loading

0 comments on commit 7a4d792

Please sign in to comment.