1
0
mirror of https://github.com/Artemis-RGB/Artemis synced 2025-12-13 05:48:35 +00:00

Profile modules - Encapsulation fixes

Data bindings - Abstracted the data model selection
This commit is contained in:
SpoinkyNL 2020-09-04 20:24:34 +02:00
parent 76dcbaf6d7
commit d03ca9c84a
20 changed files with 502 additions and 189 deletions

View File

@ -164,6 +164,16 @@ namespace Artemis.Core.Modules
/// </param>
public abstract void ModuleDeactivated(bool isOverride);
internal virtual void InternalUpdate(double deltaTime)
{
Update(deltaTime);
}
internal virtual void InternalRender(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
{
Render(deltaTime, surface, canvas, canvasInfo);
}
/// <summary>
/// Evaluates the activation requirements following the <see cref="ActivationRequirementMode" /> and returns the result
/// </summary>

View File

@ -118,15 +118,7 @@ namespace Artemis.Core.Modules
/// Indicates whether or not a profile change is being animated
/// </summary>
public bool AnimatingProfileChange { get; private set; }
/// <summary>
/// Called before the profile updates, this is the best place to perform data model updates
/// </summary>
/// <param name="deltaTime">Time in seconds since the last update</param>
public virtual void ProfileUpdate(double deltaTime)
{
}
/// <summary>
/// Called after the profile has updated
/// </summary>
@ -135,17 +127,6 @@ namespace Artemis.Core.Modules
{
}
/// <summary>
/// Called before the profile renders
/// </summary>
/// <param name="deltaTime">Time since the last render</param>
/// <param name="surface">The RGB Surface to render to</param>
/// <param name="canvas"></param>
/// <param name="canvasInfo"></param>
public virtual void ProfileRender(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
{
}
/// <summary>
/// Called after the profile has rendered
/// </summary>
@ -157,10 +138,9 @@ namespace Artemis.Core.Modules
{
}
/// <inheritdoc />
public sealed override void Update(double deltaTime)
internal override void InternalUpdate(double deltaTime)
{
ProfileUpdate(deltaTime);
Update(deltaTime);
lock (this)
{
@ -176,10 +156,9 @@ namespace Artemis.Core.Modules
ProfileUpdated(deltaTime);
}
/// <inheritdoc />
public sealed override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
internal override void InternalRender(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
{
ProfileRender(deltaTime, surface, canvas, canvasInfo);
Render(deltaTime, surface, canvas, canvasInfo);
lock (this)
{

View File

@ -174,7 +174,7 @@ namespace Artemis.Core.Services
// Update all active modules
foreach (var module in modules)
module.Update(args.DeltaTime);
module.InternalUpdate(args.DeltaTime);
// If there is no ready bitmap brush, skip the frame
if (_rgbService.BitmapBrush == null)
@ -192,7 +192,7 @@ namespace Artemis.Core.Services
{
// While non-activated modules may be updated above if they expand the main data model, they may never render
foreach (var module in modules.Where(m => m.IsActivated))
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info);
module.InternalRender(args.DeltaTime, _surfaceService.ActiveSurface, canvas, _rgbService.BitmapBrush.Bitmap.Info);
}
OnFrameRendering(new FrameRenderingEventArgs(modules, canvas, args.DeltaTime, _rgbService.Surface));

View File

@ -77,6 +77,16 @@ namespace Artemis.Core
throw new NotImplementedException();
}
public override void Update(double deltaTime)
{
throw new NotImplementedException();
}
public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
{
throw new NotImplementedException();
}
public override void ModuleActivated(bool isOverride)
{
throw new NotImplementedException();

View File

@ -0,0 +1,41 @@
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace Artemis.UI.Shared
{
public class NullToVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
Parameters direction;
if (parameter == null)
direction = Parameters.Normal;
else
direction = (Parameters) Enum.Parse(typeof(Parameters), (string) parameter);
if (direction == Parameters.Normal)
{
if (value == null)
return Visibility.Collapsed;
return Visibility.Visible;
}
if (value == null)
return Visibility.Visible;
return Visibility.Collapsed;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
private enum Parameters
{
Normal,
Inverted
}
}
}

View File

@ -0,0 +1,60 @@
<UserControl x:Class="Artemis.UI.Shared.DataModelSelectionView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:shared="clr-namespace:Artemis.UI.Shared"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
d:DataContext="{d:DesignInstance shared:DataModelSelectionViewModel}">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Artemis.UI.Shared;component/ResourceDictionaries/DisplayConditions.xaml" />
<ResourceDictionary>
<shared:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<shared:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
<DataTemplate x:Key="DataModelDataTemplate">
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Button Background="{Binding ButtonBrush}"
BorderBrush="{Binding ButtonBrush}"
Style="{StaticResource DisplayConditionButton}"
ToolTip="{Binding SelectedPropertyViewModel.DisplayPropertyPath}"
IsEnabled="{Binding IsEnabled}"
HorizontalAlignment="Left"
Click="PropertyButton_OnClick">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding DataModelViewModel.Children}" IsOpen="{Binding IsDataModelViewModelOpen, Mode=OneWayToSource}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Command" Value="{Binding Data.SelectPropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<TextBlock Text="{Binding SelectedPropertyViewModel.PropertyDescription.Name}"
Visibility="{Binding SelectedPropertyViewModel, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock FontStyle="Italic"
Visibility="{Binding SelectedPropertyViewModel, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}">
<Run Text="« "/><Run Text="{Binding Placeholder}"/><Run Text=" »"/>
</TextBlock>
</Grid>
</Button>
</UserControl>

View File

@ -0,0 +1,26 @@
using System.Windows;
using System.Windows.Controls;
namespace Artemis.UI.Shared
{
/// <summary>
/// Interaction logic for DataModelSelectionView.xaml
/// </summary>
public partial class DataModelSelectionView : UserControl
{
public DataModelSelectionView()
{
InitializeComponent();
}
private void PropertyButton_OnClick(object sender, RoutedEventArgs e)
{
// DataContext is not set when using left button, I don't know why but there it is
if (sender is Button button && button.ContextMenu != null)
{
button.ContextMenu.DataContext = button.DataContext;
button.ContextMenu.IsOpen = true;
}
}
}
}

View File

@ -0,0 +1,134 @@
using System;
using System.Timers;
using System.Windows.Media;
using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Artemis.UI.Shared.Services;
using Stylet;
// Remove, annoying while working on it
#pragma warning disable 1591
namespace Artemis.UI.Shared
{
public class DataModelSelectionViewModel : PropertyChangedBase
{
private readonly IDataModelUIService _dataModelUIService;
private readonly Module _module;
private readonly Timer _updateTimer;
private Brush _buttonBrush = new SolidColorBrush(Color.FromRgb(171, 71, 188));
private DataModelPropertiesViewModel _dataModelViewModel;
private bool _isDataModelViewModelOpen;
private bool _isEnabled;
private string _placeholder = "Select a property";
private DataModelVisualizationViewModel _selectedPropertyViewModel;
public DataModelSelectionViewModel(Module module, ISettingsService settingsService, IDataModelUIService dataModelUIService)
{
_module = module;
_dataModelUIService = dataModelUIService;
_updateTimer = new Timer(500);
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
SelectPropertyCommand = new DelegateCommand(ExecuteSelectPropertyCommand);
Initialize();
}
public string Placeholder
{
get => _placeholder;
set => SetAndNotify(ref _placeholder, value);
}
public Brush ButtonBrush
{
get => _buttonBrush;
set => SetAndNotify(ref _buttonBrush, value);
}
public DelegateCommand SelectPropertyCommand { get; }
public Type[] FilterTypes { get; set; }
public PluginSetting<bool> ShowDataModelValues { get; }
public bool IsEnabled
{
get => _isEnabled;
set => SetAndNotify(ref _isEnabled, value);
}
public DataModelPropertiesViewModel DataModelViewModel
{
get => _dataModelViewModel;
private set => SetAndNotify(ref _dataModelViewModel, value);
}
public bool IsDataModelViewModelOpen
{
get => _isDataModelViewModelOpen;
set => SetAndNotify(ref _isDataModelViewModelOpen, value);
}
public DataModelVisualizationViewModel SelectedPropertyViewModel
{
get => _selectedPropertyViewModel;
private set => SetAndNotify(ref _selectedPropertyViewModel, value);
}
public void PopulateSelectedPropertyViewModel(DataModel datamodel, string path)
{
if (datamodel == null)
SelectedPropertyViewModel = null;
else
SelectedPropertyViewModel = DataModelViewModel.GetChildByPath(datamodel.PluginInfo.Guid, path);
}
private void Initialize()
{
// Get the data models
DataModelViewModel = _dataModelUIService.GetMainDataModelVisualization();
if (!_dataModelUIService.GetPluginExtendsDataModel(_module))
DataModelViewModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_module));
DataModelViewModel.UpdateRequested += DataModelOnUpdateRequested;
_updateTimer.Start();
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
}
private void DataModelOnUpdateRequested(object sender, EventArgs e)
{
DataModelViewModel.ApplyTypeFilter(true, FilterTypes);
}
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
{
if (IsDataModelViewModelOpen)
DataModelViewModel.Update(_dataModelUIService);
}
private void ExecuteSelectPropertyCommand(object context)
{
if (!(context is DataModelVisualizationViewModel selected))
return;
SelectedPropertyViewModel = selected;
OnPropertySelected(new DataModelPropertySelectedEventArgs(selected));
}
#region Events
public event EventHandler<DataModelPropertySelectedEventArgs> PropertySelected;
protected virtual void OnPropertySelected(DataModelPropertySelectedEventArgs e)
{
PropertySelected?.Invoke(this, e);
}
#endregion
}
}

View File

@ -0,0 +1,14 @@
using System;
namespace Artemis.UI.Shared
{
public class DataModelPropertySelectedEventArgs : EventArgs
{
public DataModelVisualizationViewModel DataModelVisualizationViewModel { get; }
public DataModelPropertySelectedEventArgs(DataModelVisualizationViewModel dataModelVisualizationViewModel)
{
DataModelVisualizationViewModel = dataModelVisualizationViewModel;
}
}
}

View File

@ -0,0 +1,99 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:s="https://github.com/canton7/Stylet"
xmlns:dataModel="clr-namespace:Artemis.UI.Shared">
<Style x:Key="DisplayConditionButton" TargetType="{x:Type Button}" BasedOn="{StaticResource MaterialDesignFlatAccentBgButton}">
<Setter Property="Margin" Value="3 0" />
<Setter Property="Padding" Value="6 4" />
<Setter Property="Height" Value="22" />
<Setter Property="Foreground" Value="{DynamicResource PrimaryHueMidForegroundBrush}" />
<Setter Property="FontSize" Value="12" />
</Style>
<Style x:Key="DisplayConditionButtonLeftClickMenu" TargetType="{x:Type Button}" BasedOn="{StaticResource DisplayConditionButton}">
<Style.Triggers>
<EventTrigger RoutedEvent="Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames Storyboard.TargetProperty="ContextMenu.IsOpen">
<DiscreteBooleanKeyFrame KeyTime="0:0:0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
<ControlTemplate x:Key="DataModelSelectionTemplate">
<StackPanel>
<StackPanel.Resources>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertiesViewModel}">
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelListViewModel}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="FormatListBulleted" VerticalAlignment="Center" Margin="0 0 5 0" />
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
<Grid>
<!-- Value description -->
<TextBlock Grid.Column="0" Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
</Grid>
</DataTemplate>
</StackPanel.Resources>
<ContentPresenter Content="{Binding}" />
</StackPanel>
</ControlTemplate>
<ControlTemplate x:Key="DataModelSelectionTemplateWithValues">
<StackPanel>
<StackPanel.Resources>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertiesViewModel}">
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelListViewModel}">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon Kind="FormatListBulleted" VerticalAlignment="Center" Margin="0 0 5 0" />
<TextBlock Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" VerticalAlignment="Center" />
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type dataModel:DataModelPropertyViewModel}">
<Grid ToolTip="{Binding PropertyDescription.Description}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<!-- Value description -->
<TextBlock Grid.Column="0" Text="{Binding PropertyDescription.Name}" ToolTip="{Binding PropertyDescription.Description}" />
<!-- Value display -->
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding DisplayValue, Mode=OneWay}"
FontFamily="Consolas"
HorizontalAlignment="Right"
Visibility="{Binding ShowToString, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}"
Margin="15 0.5 0 0" />
<TextBlock Text="null"
FontFamily="Consolas"
HorizontalAlignment="Right"
Foreground="{DynamicResource MaterialDesignCheckBoxDisabled}"
Margin="15 0.5 0 0"
Visibility="{Binding ShowNull, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
<ContentControl s:View.Model="{Binding DisplayViewModel}"
FontFamily="Consolas"
Margin="15 0.5 0 0"
Visibility="{Binding ShowViewModel, Converter={x:Static s:BoolToVisibilityConverter.Instance}, Mode=OneWay}" />
</StackPanel>
</Grid>
</DataTemplate>
</StackPanel.Resources>
<ContentPresenter Content="{Binding}" />
</StackPanel>
</ControlTemplate>
</ResourceDictionary>

View File

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
using Artemis.Core.Services;
using Ninject;
using Ninject.Parameters;
@ -178,6 +179,11 @@ namespace Artemis.UI.Shared.Services
}
}
public DataModelSelectionViewModel GetDataModelSelectionViewModel(Module module)
{
return _kernel.Get<DataModelSelectionViewModel>(new ConstructorArgument("module", module));
}
private DataModelInputViewModel InstantiateDataModelInputViewModel(DataModelVisualizationRegistration registration, DataModelPropertyAttribute description, object initialValue)
{
// The view models expecting value types shouldn't be given null, avoid that

View File

@ -2,6 +2,7 @@
using System.Collections.Generic;
using Artemis.Core;
using Artemis.Core.DataModelExpansions;
using Artemis.Core.Modules;
namespace Artemis.UI.Shared.Services
{
@ -26,5 +27,7 @@ namespace Artemis.UI.Shared.Services
DataModelDisplayViewModel GetDataModelDisplayViewModel(Type propertyType);
DataModelInputViewModel GetDataModelInputViewModel(Type propertyType, DataModelPropertyAttribute description, object initialValue, Action<object, bool> updateCallback);
DataModelSelectionViewModel GetDataModelSelectionViewModel(Module module);
}
}

View File

@ -201,7 +201,7 @@ namespace Artemis.UI.Shared.Services
if (existing != null)
{
if (existing.PluginInfo != pluginInfo)
throw new ArtemisPluginException($"Cannot register property editor for type {supportedType.Name} because an editor was already registered by {pluginInfo.Name}");
throw new ArtemisPluginException($"Cannot register property editor for type {supportedType.Name} because an editor was already registered by {existing.PluginInfo.Name}");
return existing;
}

View File

@ -0,0 +1,26 @@
using System.Windows;
namespace Artemis.UI.Shared
{
internal class BindingProxy : Freezable
{
// Using a DependencyProperty as the backing store for Data. This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
public object Data
{
get => GetValue(DataProperty);
set => SetValue(DataProperty, value);
}
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
}
}

View File

@ -1,7 +1,7 @@
using System;
using System.Windows.Input;
namespace Artemis.UI.Utilities
namespace Artemis.UI.Shared
{
public class DelegateCommand : ICommand
{

View File

@ -1,11 +1,8 @@
using System;
using System.Threading.Tasks;
using System.Timers;
using System.Threading.Tasks;
using Artemis.Core;
using Artemis.Core.Services;
using Artemis.UI.Shared;
using Artemis.UI.Shared.Services;
using Artemis.UI.Utilities;
using Stylet;
namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
@ -15,11 +12,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private readonly IDataBindingService _dataBindingService;
private readonly IDataModelUIService _dataModelUIService;
private readonly IProfileEditorService _profileEditorService;
private readonly Timer _updateTimer;
private DataModelPropertiesViewModel _parameterDataModel;
private bool _parameterDataModelOpen;
private DataBindingModifierType _selectedModifierType;
private DataModelVisualizationViewModel _selectedParameterProperty;
public DataBindingModifierViewModel(DataBindingModifier modifier,
IDataBindingService dataBindingService,
@ -30,7 +23,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
_dataBindingService = dataBindingService;
_dataModelUIService = dataModelUIService;
_profileEditorService = profileEditorService;
_updateTimer = new Timer(500);
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
@ -55,37 +47,20 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
set => SetAndNotify(ref _selectedModifierType, value);
}
public DataModelPropertiesViewModel ParameterDataModel
{
get => _parameterDataModel;
set => SetAndNotify(ref _parameterDataModel, value);
}
public bool ParameterDataModelOpen
{
get => _parameterDataModelOpen;
set => SetAndNotify(ref _parameterDataModelOpen, value);
}
public DataModelVisualizationViewModel SelectedParameterProperty
{
get => _selectedParameterProperty;
set => SetAndNotify(ref _selectedParameterProperty, value);
}
public DataModelSelectionViewModel ParameterSelectionViewModel { get; private set; }
private void Initialize()
{
// Get the data models
ParameterDataModel = _dataModelUIService.GetMainDataModelVisualization();
if (!_dataModelUIService.GetPluginExtendsDataModel(_profileEditorService.GetCurrentModule()))
ParameterDataModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule()));
ParameterDataModel.UpdateRequested += ParameterDataModelOnUpdateRequested;
ParameterSelectionViewModel = _dataModelUIService.GetDataModelSelectionViewModel(_profileEditorService.GetCurrentModule());
ParameterSelectionViewModel.PropertySelected += ParameterSelectionViewModelOnPropertySelected;
ParameterSelectionViewModel.FilterTypes = new[] {Modifier.DataBinding.TargetProperty.PropertyType};
Update();
}
_updateTimer.Start();
_updateTimer.Elapsed += OnUpdateTimerOnElapsed;
private void ParameterSelectionViewModelOnPropertySelected(object sender, DataModelPropertySelectedEventArgs e)
{
Modifier.UpdateParameter(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
}
private void Update()
@ -95,11 +70,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
ModifierTypes.AddRange(_dataBindingService.GetCompatibleModifierTypes(Modifier.DataBinding.TargetProperty.PropertyType));
SelectedModifierType = Modifier.ModifierType;
// Determine the parameter property
if (Modifier.ParameterDataModel == null)
SelectedParameterProperty = null;
else
SelectedParameterProperty = ParameterDataModel.GetChildByPath(Modifier.ParameterDataModel.PluginInfo.Guid, Modifier.ParameterPropertyPath);
ParameterSelectionViewModel.PopulateSelectedPropertyViewModel(Modifier.ParameterDataModel, Modifier.ParameterPropertyPath);
}
private void ExecuteSelectModifierTypeCommand(object context)
@ -112,16 +83,5 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
Update();
}
private void ParameterDataModelOnUpdateRequested(object sender, EventArgs e)
{
ParameterDataModel.ApplyTypeFilter(true, Modifier.DataBinding.TargetProperty.PropertyType);
}
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
{
if (ParameterDataModelOpen)
ParameterDataModel.Update(_dataModelUIService);
}
}
}

View File

@ -16,18 +16,6 @@
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/Artemis.UI;component/ResourceDictionaries/DisplayConditions.xaml" />
<ResourceDictionary>
<converters:NullToVisibilityConverter x:Key="NullToVisibilityConverter" />
<utilities:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
<DataTemplate x:Key="DataModelDataTemplate">
<Control x:Name="TemplateControl" Focusable="False" Template="{StaticResource DataModelSelectionTemplate}" />
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Data.ShowDataModelValues.Value, Source={StaticResource DataContextProxy}}" Value="True">
<Setter TargetName="TemplateControl" Property="Template" Value="{StaticResource DataModelSelectionTemplateWithValues}" />
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ResourceDictionary>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
@ -49,36 +37,7 @@
<StackPanel Grid.Row="0" Margin="-3 0 0 0">
<Label FontSize="10" Foreground="{StaticResource MaterialDesignNavigationItemSubheader}" Margin="0 0 0 2">Source</Label>
<Button Background="#ab47bc"
BorderBrush="#ab47bc"
Style="{StaticResource DisplayConditionButton}"
ToolTip="{Binding SelectedSourceProperty.DisplayPropertyPath}"
IsEnabled="{Binding IsDataBindingEnabled}"
HorizontalAlignment="Left"
Click="PropertyButton_OnClick">
<Button.ContextMenu>
<ContextMenu ItemsSource="{Binding SourceDataModel.Children}" IsOpen="{Binding SourceDataModelOpen, Mode=OneWayToSource}">
<ContextMenu.ItemContainerStyle>
<Style TargetType="{x:Type MenuItem}" BasedOn="{StaticResource MaterialDesignMenuItem}">
<Setter Property="ItemsSource" Value="{Binding Children}" />
<Setter Property="Command" Value="{Binding Data.SelectSourcePropertyCommand, Source={StaticResource DataContextProxy}}" />
<Setter Property="CommandParameter" Value="{Binding}" />
<Setter Property="CommandTarget" Value="{Binding}" />
<Setter Property="IsEnabled" Value="{Binding IsMatchingFilteredTypes}" />
<Setter Property="IsSubmenuOpen" Value="{Binding IsVisualizationExpanded, Mode=TwoWay}" />
<Setter Property="HeaderTemplate" Value="{StaticResource DataModelDataTemplate}" />
</Style>
</ContextMenu.ItemContainerStyle>
</ContextMenu>
</Button.ContextMenu>
<Grid>
<TextBlock Text="{Binding SelectedSourceProperty.PropertyDescription.Name}"
Visibility="{Binding SelectedSourceProperty, Converter={StaticResource NullToVisibilityConverter}}" />
<TextBlock Text="« Select a property »"
FontStyle="Italic"
Visibility="{Binding SelectedSourceProperty, Converter={StaticResource NullToVisibilityConverter}, ConverterParameter=Inverted}" />
</Grid>
</Button>
<ContentControl s:View.Model="{Binding TargetSelectionViewModel}" VerticalContentAlignment="Stretch" HorizontalContentAlignment="Stretch" IsTabStop="False" />
</StackPanel>
<ComboBox Grid.Row="1"

View File

@ -27,12 +27,12 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private bool _sourceDataModelOpen;
private object _testInputValue;
private object _testResultValue;
private DataModelSelectionViewModel _targetSelectionViewModel;
public DataBindingViewModel(BaseLayerProperty layerProperty,
PropertyInfo targetProperty,
IProfileEditorService profileEditorService,
IDataModelUIService dataModelUIService,
ISettingsService settingsService,
IDataBindingsVmFactory dataBindingsVmFactory)
{
_profileEditorService = profileEditorService;
@ -40,47 +40,30 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
_dataBindingsVmFactory = dataBindingsVmFactory;
_updateTimer = new Timer(500);
DisplayName = targetProperty.Name.ToUpper();
LayerProperty = layerProperty;
TargetProperty = targetProperty;
DisplayName = TargetProperty.Name.ToUpper();
SelectSourcePropertyCommand = new DelegateCommand(ExecuteSelectSourceProperty);
ModifierViewModels = new BindableCollection<DataBindingModifierViewModel>();
DataBinding = layerProperty.DataBindings.FirstOrDefault(d => d.TargetProperty == targetProperty);
ShowDataModelValues = settingsService.GetSetting<bool>("ProfileEditor.ShowDataModelValues");
ModifierViewModels = new BindableCollection<DataBindingModifierViewModel>();
_isDataBindingEnabled = DataBinding != null;
// Initialize async, no need to wait for it
Task.Run(Initialize);
Execute.PostToUIThread(Initialize);
}
public DataModelPropertiesViewModel SourceDataModel
{
get => _sourceDataModel;
set => SetAndNotify(ref _sourceDataModel, value);
}
public bool SourceDataModelOpen
{
get => _sourceDataModelOpen;
set => SetAndNotify(ref _sourceDataModelOpen, value);
}
public DataModelVisualizationViewModel SelectedSourceProperty
{
get => _selectedSourceProperty;
set => SetAndNotify(ref _selectedSourceProperty, value);
}
public PluginSetting<bool> ShowDataModelValues { get; }
public BaseLayerProperty LayerProperty { get; }
public PropertyInfo TargetProperty { get; }
public string DisplayName { get; }
public BindableCollection<DataBindingModifierViewModel> ModifierViewModels { get; }
public DelegateCommand SelectSourcePropertyCommand { get; }
public DataModelSelectionViewModel TargetSelectionViewModel
{
get => _targetSelectionViewModel;
private set => SetAndNotify(ref _targetSelectionViewModel, value);
}
public bool IsDataBindingEnabled
{
@ -105,12 +88,25 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
}
}
public object TestInputValue
{
get => _testInputValue;
set => SetAndNotify(ref _testInputValue, value);
}
public object TestResultValue
{
get => _testResultValue;
set => SetAndNotify(ref _testResultValue, value);
}
public void EnableDataBinding()
{
if (DataBinding != null)
return;
DataBinding = LayerProperty.AddDataBinding(TargetProperty);
Update();
}
public void RemoveDataBinding()
@ -121,6 +117,7 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
var toRemove = DataBinding;
DataBinding = null;
LayerProperty.RemoveDataBinding(toRemove);
Update();
}
public void AddModifier()
@ -136,12 +133,8 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private void Initialize()
{
// Get the data models
SourceDataModel = _dataModelUIService.GetMainDataModelVisualization();
if (!_dataModelUIService.GetPluginExtendsDataModel(_profileEditorService.GetCurrentModule()))
SourceDataModel.Children.Add(_dataModelUIService.GetPluginDataModelVisualization(_profileEditorService.GetCurrentModule()));
SourceDataModel.UpdateRequested += SourceDataModelOnUpdateRequested;
TargetSelectionViewModel = _dataModelUIService.GetDataModelSelectionViewModel(_profileEditorService.GetCurrentModule());
TargetSelectionViewModel.PropertySelected += TargetSelectionViewModelOnPropertySelected;
Update();
@ -151,31 +144,30 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
private void Update()
{
if (DataBinding == null || SourceDataModel == null)
if (DataBinding == null)
{
TargetSelectionViewModel.IsEnabled = false;
return;
}
// Determine the source property
if (DataBinding.SourceDataModel == null)
SelectedSourceProperty = null;
else
SelectedSourceProperty = SourceDataModel.GetChildByPath(DataBinding.SourceDataModel.PluginInfo.Guid, DataBinding.SourcePropertyPath);
TargetSelectionViewModel.IsEnabled = true;
TargetSelectionViewModel.PopulateSelectedPropertyViewModel(DataBinding.SourceDataModel, DataBinding.SourcePropertyPath);
TargetSelectionViewModel.FilterTypes = new[] {DataBinding.TargetProperty.PropertyType};
}
private void SourceDataModelOnUpdateRequested(object sender, EventArgs e)
private void TargetSelectionViewModelOnPropertySelected(object sender, DataModelPropertySelectedEventArgs e)
{
SourceDataModel.ApplyTypeFilter(true, DataBinding.TargetProperty.PropertyType);
DataBinding.UpdateSource(e.DataModelVisualizationViewModel.DataModel, e.DataModelVisualizationViewModel.PropertyPath);
}
private void OnUpdateTimerOnElapsed(object sender, ElapsedEventArgs e)
{
UpdateTestResult();
if (SourceDataModelOpen)
SourceDataModel.Update(_dataModelUIService);
}
private void UpdateTestResult()
{
var currentValue = SelectedSourceProperty?.GetCurrentValue();
var currentValue = TargetSelectionViewModel.SelectedPropertyViewModel?.GetCurrentValue();
if (currentValue == null && TargetProperty.PropertyType.IsValueType)
currentValue = Activator.CreateInstance(TargetProperty.PropertyType);
@ -183,18 +175,6 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
TestResultValue = DataBinding?.GetValue(TestInputValue);
}
public object TestInputValue
{
get => _testInputValue;
set => SetAndNotify(ref _testInputValue, value);
}
public object TestResultValue
{
get => _testResultValue;
set => SetAndNotify(ref _testResultValue, value);
}
private void UpdateModifierViewModels()
{
ModifierViewModels.Clear();
@ -205,15 +185,5 @@ namespace Artemis.UI.Screens.ProfileEditor.LayerProperties.DataBindings
ModifierViewModels.Add(_dataBindingsVmFactory.DataBindingModifierViewModel(dataBindingModifier));
}
private void ExecuteSelectSourceProperty(object context)
{
if (!(context is DataModelVisualizationViewModel selected))
return;
DataBinding.UpdateSource(selected.DataModel, selected.PropertyPath);
_profileEditorService.UpdateSelectedProfileElement();
Update();
}
}
}

View File

@ -1,11 +1,13 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Artemis.Core;
using Artemis.Core.Modules;
using Artemis.Plugins.Modules.General.DataModels;
using Artemis.Plugins.Modules.General.DataModels.Windows;
using Artemis.Plugins.Modules.General.Utilities;
using Artemis.Plugins.Modules.General.ViewModels;
using SkiaSharp;
namespace Artemis.Plugins.Modules.General
{
@ -36,7 +38,7 @@ namespace Artemis.Plugins.Modules.General
{
}
public override void ProfileUpdate(double deltaTime)
public override void Update(double deltaTime)
{
DataModel.TimeDataModel.CurrentTime = DateTime.Now;
DataModel.TimeDataModel.CurrentTimeUTC = DateTime.UtcNow;
@ -44,6 +46,10 @@ namespace Artemis.Plugins.Modules.General
UpdateCurrentWindow();
}
public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
{
}
#region Open windows
public void UpdateCurrentWindow()

View File

@ -1,6 +1,8 @@
using System;
using System.IO;
using Artemis.Core;
using Artemis.Core.Modules;
using SkiaSharp;
namespace Artemis.Plugins.Modules.Overlay
{
@ -37,5 +39,13 @@ namespace Artemis.Plugins.Modules.Overlay
{
// When this gets called your activation requirements are no longer met and your module will stop displaying
}
public override void Update(double deltaTime)
{
}
public override void Render(double deltaTime, ArtemisSurface surface, SKCanvas canvas, SKImageInfo canvasInfo)
{
}
}
}