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

Implemented profile default loading and rendering without the editor

Changed edit tool rotation to allow rotation past 360 degrees
This commit is contained in:
SpoinkyNL 2020-01-26 11:35:39 +01:00
parent f8fc30ace2
commit fabb385556
13 changed files with 116 additions and 41 deletions

View File

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.Linq; using System.Linq;
using Artemis.Core.Exceptions; using Artemis.Core.Exceptions;
using Artemis.Core.Models.Profile.LayerProperties; using Artemis.Core.Models.Profile.LayerProperties;
@ -77,8 +78,7 @@ namespace Artemis.Core.Models.Profile.KeyframeEngines
return; return;
var keyframes = LayerProperty.UntypedKeyframes.ToList(); var keyframes = LayerProperty.UntypedKeyframes.ToList();
Progress = Progress.Add(TimeSpan.FromMilliseconds(deltaTime)); Progress = Progress.Add(TimeSpan.FromSeconds(deltaTime));
// The current keyframe is the last keyframe before the current time // The current keyframe is the last keyframe before the current time
CurrentKeyframe = keyframes.LastOrDefault(k => k.Position <= Progress); CurrentKeyframe = keyframes.LastOrDefault(k => k.Position <= Progress);
// The next keyframe is the first keyframe that's after the current time // The next keyframe is the first keyframe that's after the current time
@ -112,7 +112,7 @@ namespace Artemis.Core.Models.Profile.KeyframeEngines
public void OverrideProgress(TimeSpan progress) public void OverrideProgress(TimeSpan progress)
{ {
Progress = TimeSpan.Zero; Progress = TimeSpan.Zero;
Update(progress.TotalMilliseconds); Update(progress.TotalSeconds);
} }
/// <summary> /// <summary>

View File

@ -135,7 +135,7 @@ namespace Artemis.Core.Models.Profile
/// <summary> /// <summary>
/// The rotation property of this layer range 0 - 360, also found in <see cref="Properties" /> /// The rotation property of this layer range 0 - 360, also found in <see cref="Properties" />
/// </summary> /// </summary>
public LayerProperty<int> RotationProperty { get; private set; } public LayerProperty<float> RotationProperty { get; private set; }
/// <summary> /// <summary>
/// The opacity property of this layer range 0 - 100, also found in <see cref="Properties" /> /// The opacity property of this layer range 0 - 100, also found in <see cref="Properties" />
@ -153,11 +153,8 @@ namespace Artemis.Core.Models.Profile
{ {
property.KeyframeEngine?.Update(deltaTime); property.KeyframeEngine?.Update(deltaTime);
// This is a placeholder method of repeating the animation until repeat modes are implemented // This is a placeholder method of repeating the animation until repeat modes are implemented
if (property.KeyframeEngine != null && property.IsUsingKeyframes && property.KeyframeEngine.NextKeyframe == null) if (property.KeyframeEngine != null && property.IsUsingKeyframes && property.KeyframeEngine.NextKeyframe == null)
{
Debug.WriteLine($"Reset {property} progress");
property.KeyframeEngine.OverrideProgress(TimeSpan.Zero); property.KeyframeEngine.OverrideProgress(TimeSpan.Zero);
}
} }
LayerBrush?.Update(deltaTime); LayerBrush?.Update(deltaTime);
@ -421,7 +418,7 @@ namespace Artemis.Core.Models.Profile
AnchorPointProperty = new LayerProperty<SKPoint>(this, transformProperty, "Core.AnchorPoint", "Anchor Point", "The point at which the shape is attached to its position."); AnchorPointProperty = new LayerProperty<SKPoint>(this, transformProperty, "Core.AnchorPoint", "Anchor Point", "The point at which the shape is attached to its position.");
PositionProperty = new LayerProperty<SKPoint>(this, transformProperty, "Core.Position", "Position", "The position of the shape."); PositionProperty = new LayerProperty<SKPoint>(this, transformProperty, "Core.Position", "Position", "The position of the shape.");
SizeProperty = new LayerProperty<SKSize>(this, transformProperty, "Core.Size", "Size", "The size of the shape.") {InputAffix = "%"}; SizeProperty = new LayerProperty<SKSize>(this, transformProperty, "Core.Size", "Size", "The size of the shape.") {InputAffix = "%"};
RotationProperty = new LayerProperty<int>(this, transformProperty, "Core.Rotation", "Rotation", "The rotation of the shape in degrees.") {InputAffix = "°"}; RotationProperty = new LayerProperty<float>(this, transformProperty, "Core.Rotation", "Rotation", "The rotation of the shape in degrees.") {InputAffix = "°"};
OpacityProperty = new LayerProperty<float>(this, transformProperty, "Core.Opacity", "Opacity", "The opacity of the shape.") {InputAffix = "%"}; OpacityProperty = new LayerProperty<float>(this, transformProperty, "Core.Opacity", "Opacity", "The opacity of the shape.") {InputAffix = "%"};
transformProperty.Children.Add(AnchorPointProperty); transformProperty.Children.Add(AnchorPointProperty);
transformProperty.Children.Add(PositionProperty); transformProperty.Children.Add(PositionProperty);

View File

@ -222,6 +222,8 @@ namespace Artemis.Core.Models.Profile.LayerProperties
currentKeyframe.BaseValue = value; currentKeyframe.BaseValue = value;
} }
OnValueChanged();
} }
/// <summary> /// <summary>

View File

@ -13,6 +13,11 @@ namespace Artemis.Core.Plugins.Abstract
{ {
} }
public override void EnablePlugin()
{
throw new NotImplementedException();
}
public Profile ActiveProfile { get; private set; } public Profile ActiveProfile { get; private set; }
/// <inheritdoc /> /// <inheritdoc />

View File

@ -23,17 +23,19 @@ namespace Artemis.Core.Services
private readonly IPluginService _pluginService; private readonly IPluginService _pluginService;
private readonly IRgbService _rgbService; private readonly IRgbService _rgbService;
private readonly ISurfaceService _surfaceService; private readonly ISurfaceService _surfaceService;
private readonly IProfileService _profileService;
private List<Module> _modules; private List<Module> _modules;
internal CoreService(ILogger logger, IPluginService pluginService, IRgbService rgbService, ISurfaceService surfaceService) internal CoreService(ILogger logger, IPluginService pluginService, IRgbService rgbService, ISurfaceService surfaceService, IProfileService profileService)
{ {
_logger = logger; _logger = logger;
_pluginService = pluginService; _pluginService = pluginService;
_rgbService = rgbService; _rgbService = rgbService;
_surfaceService = surfaceService; _surfaceService = surfaceService;
_profileService = profileService;
_rgbService.Surface.Updating += SurfaceOnUpdating; _rgbService.Surface.Updating += SurfaceOnUpdating;
_rgbService.Surface.Updated += SurfaceOnUpdated; _rgbService.Surface.Updated += SurfaceOnUpdated;
_modules = _pluginService.GetPluginsOfType<Module>(); _modules = _pluginService.GetPluginsOfType<Module>();
_pluginService.PluginEnabled += (sender, args) => _modules = _pluginService.GetPluginsOfType<Module>(); _pluginService.PluginEnabled += (sender, args) => _modules = _pluginService.GetPluginsOfType<Module>();
_pluginService.PluginDisabled += (sender, args) => _modules = _pluginService.GetPluginsOfType<Module>(); _pluginService.PluginDisabled += (sender, args) => _modules = _pluginService.GetPluginsOfType<Module>();
@ -42,6 +44,9 @@ namespace Artemis.Core.Services
Task.Run(Initialize); Task.Run(Initialize);
} }
public bool ModuleUpdatingDisabled { get; set; }
public bool ModuleRenderingDisabled { get; set; }
public void Dispose() public void Dispose()
{ {
// Dispose services // Dispose services
@ -75,6 +80,8 @@ namespace Artemis.Core.Services
else else
_logger.Information("Initialized without an active surface entity"); _logger.Information("Initialized without an active surface entity");
await Task.Run(() => _profileService.ActivateDefaultProfiles());
OnInitialized(); OnInitialized();
} }
@ -82,11 +89,14 @@ namespace Artemis.Core.Services
{ {
try try
{ {
lock (_modules) if (!ModuleUpdatingDisabled)
{ {
// Update all active modules lock (_modules)
foreach (var module in _modules) {
module.Update(args.DeltaTime); // Update all active modules
foreach (var module in _modules)
module.Update(args.DeltaTime);
}
} }
// If there is no ready bitmap brush, skip the frame // If there is no ready bitmap brush, skip the frame
@ -102,10 +112,13 @@ namespace Artemis.Core.Services
using (var canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap)) using (var canvas = new SKCanvas(_rgbService.BitmapBrush.Bitmap))
{ {
canvas.Clear(new SKColor(0, 0, 0)); canvas.Clear(new SKColor(0, 0, 0));
lock (_modules) if (!ModuleRenderingDisabled)
{ {
foreach (var module in _modules) lock (_modules)
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas); {
foreach (var module in _modules)
module.Render(args.DeltaTime, _surfaceService.ActiveSurface, canvas);
}
} }
OnFrameRendering(new FrameRenderingEventArgs(_modules, canvas, args.DeltaTime, _rgbService.Surface)); OnFrameRendering(new FrameRenderingEventArgs(_modules, canvas, args.DeltaTime, _rgbService.Surface));

View File

@ -6,9 +6,18 @@ namespace Artemis.Core.Services.Interfaces
public interface ICoreService : IArtemisService, IDisposable public interface ICoreService : IArtemisService, IDisposable
{ {
/// <summary> /// <summary>
/// Indicates wether or not the core has been initialized /// Gets whether the or not the core has been initialized
/// </summary> /// </summary>
bool IsInitialized { get; set; } bool IsInitialized { get; }
/// <summary>
/// Gets or sets whether modules are updated each frame by calling their Update method
/// </summary>
bool ModuleUpdatingDisabled { get; set; }
/// <summary>
/// Gets or sets whether modules are rendered each frame by calling their Render method
/// </summary>
bool ModuleRenderingDisabled { get; set; }
/// <summary> /// <summary>
/// Occurs the core has finished initializing /// Occurs the core has finished initializing

View File

@ -7,6 +7,7 @@ namespace Artemis.Core.Services.Storage.Interfaces
{ {
public interface IProfileService : IArtemisService public interface IProfileService : IArtemisService
{ {
void ActivateDefaultProfiles();
Profile CreateProfile(ProfileModule module, string name); Profile CreateProfile(ProfileModule module, string name);
List<Profile> GetProfiles(ProfileModule module); List<Profile> GetProfiles(ProfileModule module);
Profile GetActiveProfile(ProfileModule module); Profile GetActiveProfile(ProfileModule module);

View File

@ -14,7 +14,7 @@ using Newtonsoft.Json;
namespace Artemis.Core.Services.Storage namespace Artemis.Core.Services.Storage
{ {
/// <summary> /// <summary>
/// Provides access to profile storage /// Provides access to profile storage and is responsible for activating default profiles
/// </summary> /// </summary>
public class ProfileService : IProfileService public class ProfileService : IProfileService
{ {
@ -35,6 +35,14 @@ namespace Artemis.Core.Services.Storage
_pluginService.PluginLoaded += OnPluginLoaded; _pluginService.PluginLoaded += OnPluginLoaded;
} }
public void ActivateDefaultProfiles()
{
foreach (var profileModule in _pluginService.GetPluginsOfType<ProfileModule>())
{
var activeProfile = GetActiveProfile(profileModule);
ActivateProfile(profileModule, activeProfile);
}
}
public List<Profile> GetProfiles(ProfileModule module) public List<Profile> GetProfiles(ProfileModule module)
{ {
@ -204,6 +212,11 @@ namespace Artemis.Core.Services.Storage
ActiveProfilesInstantiateProfileLayerBrushes(); ActiveProfilesInstantiateProfileLayerBrushes();
ActiveProfilesInstantiateKeyframeEngines(); ActiveProfilesInstantiateKeyframeEngines();
} }
else if (e.PluginInfo.Instance is ProfileModule profileModule)
{
var activeProfile = GetActiveProfile(profileModule);
ActivateProfile(profileModule, activeProfile);
}
} }
#endregion #endregion

View File

@ -34,6 +34,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.LayerProperties.PropertyTree.P
throw new ArtemisUIException($"This input VM does not support the provided type {layerPropertyViewModel.LayerProperty.Type.Name}"); throw new ArtemisUIException($"This input VM does not support the provided type {layerPropertyViewModel.LayerProperty.Type.Name}");
LayerPropertyViewModel = layerPropertyViewModel; LayerPropertyViewModel = layerPropertyViewModel;
layerPropertyViewModel.LayerProperty.ValueChanged += (sender, args) => Update();
Update(); Update();
Initialized = true; Initialized = true;

View File

@ -146,6 +146,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
protected override void OnActivate() protected override void OnActivate()
{ {
LoadWorkspaceSettings(); LoadWorkspaceSettings();
_profileEditorService.StopRegularRender();
Task.Run(LoadProfiles); Task.Run(LoadProfiles);
base.OnActivate(); base.OnActivate();
} }
@ -153,6 +154,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor
protected override void OnDeactivate() protected override void OnDeactivate()
{ {
SaveWorkspaceSettings(); SaveWorkspaceSettings();
_profileEditorService.ResumeRegularRender();
base.OnDeactivate(); base.OnDeactivate();
} }

View File

@ -20,8 +20,7 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
private SKPoint _dragOffset; private SKPoint _dragOffset;
private SKPoint _dragStart; private SKPoint _dragStart;
private SKPoint _dragStartAnchor; private SKPoint _dragStartAnchor;
private double _dragStartAngle; private float _previousDragAngle;
private double _dragAngleOffset;
private SKSize _dragStartScale; private SKSize _dragStartScale;
private bool _isDragging; private bool _isDragging;
@ -111,8 +110,8 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
// The path starts at 0,0 so there's no simple way to get the position relative to the top-left of the path // The path starts at 0,0 so there's no simple way to get the position relative to the top-left of the path
_dragStart = GetRelativePosition(sender, e).ToSKPoint(); _dragStart = GetRelativePosition(sender, e).ToSKPoint();
_dragStartScale = layer.SizeProperty.CurrentValue; _dragStartScale = layer.SizeProperty.CurrentValue;
_dragStartAngle = layer.RotationProperty.CurrentValue; _previousDragAngle = CalculateAngle(_layerEditorService.GetLayerAnchor(layer, true), _dragStart);
_dragAngleOffset = _dragStartAngle - CalculateAngle(_layerEditorService.GetLayerAnchor(layer, true), _dragStart);
// Store the original position and do a test to figure out the mouse offset // Store the original position and do a test to figure out the mouse offset
var originalPosition = layer.PositionProperty.CurrentValue; var originalPosition = layer.PositionProperty.CurrentValue;
var scaledDragStart = _layerEditorService.GetScaledPoint(layer, _dragStart, true); var scaledDragStart = _layerEditorService.GetScaledPoint(layer, _dragStart, true);
@ -358,15 +357,30 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
{ {
if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer)) if (!_isDragging || !(ProfileEditorService.SelectedProfileElement is Layer layer))
return; return;
var newRotation = CalculateAngle(_layerEditorService.GetLayerAnchor(layer, true), GetRelativePosition(sender, e).ToSKPoint()) + _dragAngleOffset;
if (newRotation < 0)
newRotation = 360 + newRotation;
var current = layer.RotationProperty.CurrentValue;
layer.RotationProperty.SetCurrentValue((int) Math.Round(newRotation, MidpointRounding.AwayFromZero), ProfileEditorService.CurrentTime); var previousDragAngle = _previousDragAngle;
Debug.WriteLine($"New rotation: {layer.RotationProperty.CurrentValue} Difference: {(layer.RotationProperty.CurrentValue - current)}"); var newRotation = CalculateAngle(_layerEditorService.GetLayerAnchor(layer, true), GetRelativePosition(sender, e).ToSKPoint());
_previousDragAngle = newRotation;
// Allow the user to rotate the shape in increments of 5
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
newRotation = (float)Math.Round(newRotation / 5f) * 5f;
var difference = newRotation - previousDragAngle;
if (difference < -350)
difference += 360;
else if (difference > 350)
difference -= 360;
newRotation = layer.RotationProperty.CurrentValue + difference;
// Round the end-result to increments of 5 as well, to avoid staying on an offset
if (Keyboard.IsKeyDown(Key.LeftShift) || Keyboard.IsKeyDown(Key.RightShift))
newRotation = (float)Math.Round(newRotation / 5f) * 5f;
else
newRotation = (float)Math.Round(newRotation, 2, MidpointRounding.AwayFromZero);
Debug.WriteLine(newRotation);
layer.RotationProperty.SetCurrentValue(newRotation, ProfileEditorService.CurrentTime);
ProfileEditorService.UpdateProfilePreview(); ProfileEditorService.UpdateProfilePreview();
} }
@ -459,12 +473,12 @@ namespace Artemis.UI.Screens.Module.ProfileEditor.Visualization.Tools
return Math.Max(0.001f, _dragStartScale.Height + scaleToAdd); return Math.Max(0.001f, _dragStartScale.Height + scaleToAdd);
} }
private double CalculateAngle(SKPoint start, SKPoint arrival) private float CalculateAngle(SKPoint start, SKPoint arrival)
{ {
var radian = Math.Atan2(start.Y - arrival.Y, start.X - arrival.X); var radian = (float) Math.Atan2(start.Y - arrival.Y, start.X - arrival.X);
var angle = radian * (180 / Math.PI); var angle = radian * (180f / (float) Math.PI);
if (angle < 0.0) if (angle < 0f)
angle += 360.0; angle += 360f;
return angle; return angle;
} }

View File

@ -47,5 +47,8 @@ namespace Artemis.UI.Services.Interfaces
/// Occurs when the profile preview has been updated /// Occurs when the profile preview has been updated
/// </summary> /// </summary>
event EventHandler ProfilePreviewUpdated; event EventHandler ProfilePreviewUpdated;
void StopRegularRender();
void ResumeRegularRender();
} }
} }

View File

@ -2,6 +2,7 @@
using System.Linq; using System.Linq;
using Artemis.Core.Models.Profile; using Artemis.Core.Models.Profile;
using Artemis.Core.Plugins.Abstract; using Artemis.Core.Plugins.Abstract;
using Artemis.Core.Services.Interfaces;
using Artemis.Core.Services.Storage.Interfaces; using Artemis.Core.Services.Storage.Interfaces;
using Artemis.UI.Services.Interfaces; using Artemis.UI.Services.Interfaces;
@ -9,12 +10,14 @@ namespace Artemis.UI.Services
{ {
public class ProfileEditorService : IProfileEditorService public class ProfileEditorService : IProfileEditorService
{ {
private readonly ICoreService _coreService;
private readonly IProfileService _profileService; private readonly IProfileService _profileService;
private TimeSpan _currentTime; private TimeSpan _currentTime;
private TimeSpan _lastUpdateTime; private TimeSpan _lastUpdateTime;
public ProfileEditorService(IProfileService profileService) public ProfileEditorService(ICoreService coreService, IProfileService profileService)
{ {
_coreService = coreService;
_profileService = profileService; _profileService = profileService;
} }
@ -75,8 +78,10 @@ namespace Artemis.UI.Services
// Force layer shape to redraw // Force layer shape to redraw
layer.LayerShape?.CalculateRenderProperties(); layer.LayerShape?.CalculateRenderProperties();
// Update the brush with the delta (which can now be negative ^^) // Manually update the layer's engine and brush
layer.Update(delta.TotalSeconds); foreach (var property in layer.Properties)
property.KeyframeEngine?.Update(delta.TotalSeconds);
layer.LayerBrush?.Update(delta.TotalSeconds);
} }
_lastUpdateTime = CurrentTime; _lastUpdateTime = CurrentTime;
@ -122,6 +127,16 @@ namespace Artemis.UI.Services
public event EventHandler CurrentTimeChanged; public event EventHandler CurrentTimeChanged;
public event EventHandler ProfilePreviewUpdated; public event EventHandler ProfilePreviewUpdated;
public void StopRegularRender()
{
_coreService.ModuleUpdatingDisabled = true;
}
public void ResumeRegularRender()
{
_coreService.ModuleUpdatingDisabled = false;
}
protected virtual void OnSelectedProfileElementUpdated() protected virtual void OnSelectedProfileElementUpdated()
{ {
SelectedProfileElementUpdated?.Invoke(this, EventArgs.Empty); SelectedProfileElementUpdated?.Invoke(this, EventArgs.Empty);