-
-
Notifications
You must be signed in to change notification settings - Fork 8
Custom animation #199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Custom animation #199
Changes from 19 commits
949a671
6d5eb1b
de42ade
f06f619
7cb2323
32cd086
4ad4474
c026e39
484e557
fcccf4d
c7253d1
dfff735
db33de8
7b12074
f7c0e24
35b2585
9c7ddcf
5e63c8e
26c0e2f
1a5e6d3
01aa821
e87ed76
07c131f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| using Newtonsoft.Json; | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text; | ||
| using System.Threading.Tasks; | ||
|
|
||
| namespace Winleafs.Models.Models.Effects | ||
| { | ||
| public class CustomEffectCommand | ||
| { | ||
| [JsonProperty("command")] | ||
| public string Command { get; set; } // add, update, display | ||
|
|
||
| [JsonProperty("version")] | ||
| public string Version { get; } = "1.0"; | ||
|
|
||
| [JsonProperty("animName")] | ||
| public string AnimName { get; set; } | ||
|
|
||
| [JsonProperty("animType")] | ||
| public string AnimType { get; set; } //custom, static | ||
|
JasonBSteele marked this conversation as resolved.
Outdated
|
||
|
|
||
| [JsonProperty("animData")] | ||
| public string AnimData { get; set; } | ||
|
|
||
| [JsonProperty("loop")] | ||
| public bool Loop { get; set; } | ||
|
|
||
| [JsonProperty("palette")] | ||
| public IList<Palette> Palette { get; set; } = new List<Palette>(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| using System.Collections.Generic; | ||
|
|
||
| namespace Winleafs.Models.Models.Layouts | ||
| { | ||
| /// <summary> | ||
| /// A user created Custom Effect which specifies a static pattern or animation | ||
| /// </summary> | ||
| public class CustomEffect | ||
| { | ||
| /// <summary> | ||
| /// True if this is just one Frame to set each panel's color | ||
| /// </summary> | ||
| public bool IsStatic { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// True if the animation is played repeatedly | ||
| /// </summary> | ||
| public bool IsLoop { get; set; } | ||
|
|
||
| /// <summary> | ||
| /// A series of frames each specifying the color for each panel | ||
| /// </summary> | ||
| public IList<Frame> Frames { get; set; } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Personally prefer using either
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So IMHO IList The same is true for I'll see what I break if I change to
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is a lot of use of indexing, so it has to be |
||
|
|
||
| public CustomEffect() | ||
| { | ||
| Frames = new List<Frame>(); | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| using System.Collections.Generic; | ||
|
|
||
| namespace Winleafs.Models.Models.Layouts | ||
| { | ||
| public class Frame | ||
| { | ||
| public IDictionary<int, uint> PanelColors { get; set; } | ||
|
|
||
| public Frame() | ||
| { | ||
| PanelColors = new Dictionary<int, uint>(); | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| using Winleafs.Models.Models.Layouts; | ||
|
|
||
| namespace Winleafs.Models.Models.Layouts | ||
| { | ||
| public class FrameListItem | ||
| { | ||
| public FrameListItem(Frame frame, string name) | ||
| { | ||
| Frame = frame; | ||
| Name = name; | ||
| } | ||
|
|
||
| public string Name { get; set; } | ||
| public Frame Frame { get; set; } | ||
| } | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using System.Text; | ||
| using System.Threading.Tasks; | ||
| using Winleafs.Models.Models.Effects; | ||
| using Winleafs.Models.Models.Layouts; | ||
| using Winleafs.Wpf.Helpers; | ||
|
|
||
| namespace Winleafs.Wpf.Api.Effects | ||
| { | ||
| /// <summary> | ||
| /// Used to build a CustomEffectCommand to send to the API | ||
| /// </summary> | ||
| public class CustomEffectCommandBuilder | ||
| { | ||
| private CustomEffect _customEffect; | ||
|
JasonBSteele marked this conversation as resolved.
Outdated
|
||
| private int _transitionTime; | ||
|
|
||
| public CustomEffectCommandBuilder(CustomEffect customEffect) | ||
| { | ||
| _customEffect = customEffect; | ||
| } | ||
|
|
||
| public CustomEffectCommand BuildAddCommand(float transitionTime, string Name) | ||
|
JasonBSteele marked this conversation as resolved.
Outdated
|
||
| { | ||
| //If a name has been passed the custom effect will be added to the device | ||
| var customEffectCommand = new CustomEffectCommand(); | ||
| customEffectCommand.Command = "add"; | ||
| customEffectCommand.AnimName = Name; | ||
| _transitionTime = (int)Math.Floor(transitionTime * 10); | ||
|
JasonBSteele marked this conversation as resolved.
Outdated
|
||
|
|
||
| BuildBody(customEffectCommand); | ||
|
|
||
| return customEffectCommand; | ||
| } | ||
|
|
||
| public CustomEffectCommand BuildDisplayCommand(float transitionTime) | ||
| { | ||
| //If no name has been passed the custom effect will just be dispayed on the device | ||
| var customEffectCommand = new CustomEffectCommand(); | ||
| customEffectCommand.Command = "display"; | ||
| _transitionTime = (int)Math.Floor(transitionTime * 10); | ||
|
|
||
| BuildBody(customEffectCommand); | ||
|
|
||
| return customEffectCommand; | ||
| } | ||
|
|
||
| private void BuildBody(CustomEffectCommand customEffectCommand) | ||
| { | ||
|
|
||
|
JasonBSteele marked this conversation as resolved.
Outdated
|
||
| if (_customEffect.IsStatic) | ||
| { | ||
| customEffectCommand.AnimType = "static"; | ||
| } | ||
| else | ||
| { | ||
| customEffectCommand.AnimType = "custom"; | ||
| customEffectCommand.Loop = _customEffect.IsLoop; | ||
| } | ||
|
|
||
| var animData = new StringBuilder(); | ||
| animData.Append(_customEffect.Frames[0].PanelColors.Count); | ||
|
|
||
| foreach (var panelId in _customEffect.Frames[0].PanelColors.Keys) | ||
| { | ||
| animData.Append(BuildPanelAnimData(panelId)); | ||
| } | ||
|
|
||
| customEffectCommand.AnimData = animData.ToString(); | ||
|
|
||
| //Set pallete so used colurs are displayed in apps (docs say max of 20) | ||
| var rgbs = _customEffect.Frames.SelectMany(f => f.PanelColors.Values).Distinct().Take(20); | ||
| foreach(var rgb in rgbs) | ||
| { | ||
| customEffectCommand.Palette.Add(ColorFormatConverter.ToPalette(rgb)); | ||
| } | ||
| } | ||
|
|
||
| private string BuildPanelAnimData(int panelId) | ||
| { | ||
| //Example taken from docs. This method returns one of the panel rows | ||
| //(semicolons and newlines added for clarity only): | ||
| //numPanels; | ||
| //panelId0; numFrames0; RGBWT01; RGBWT02; ... RGBWT0n(0); | ||
| //panelId1; numFrames1; RGBWT11; RGBWT12; ... RGBWT1n(1); ... ... | ||
| //panelIdN; numFramesN; RGBWTN1; RGBWTN2; ... RGBWTNn(N); | ||
| //RGB=color, W=0, Txx is transition time is tenths of a second | ||
|
|
||
| var sb = new StringBuilder(); | ||
| uint? prevRgb = null; | ||
|
|
||
| var totalFrames = 0; | ||
| var sameColorFrameCount = 0; | ||
|
|
||
| foreach (var rgb in _customEffect.Frames.Select(f => f.PanelColors[panelId])) | ||
| { | ||
| if (prevRgb == null || rgb != prevRgb.Value) | ||
| { | ||
| if (prevRgb != null && sameColorFrameCount > 0) | ||
| { | ||
| sb.AppendFormat(" {0} {1} {2} 0 {3}", | ||
| (prevRgb >> 16) & 255, | ||
|
JasonBSteele marked this conversation as resolved.
Outdated
|
||
| (prevRgb >> 8) & 255, | ||
| prevRgb & 255, | ||
| sameColorFrameCount * _transitionTime); | ||
|
|
||
| totalFrames++; | ||
| } | ||
|
|
||
| sb.AppendFormat(" {0} {1} {2} 0 {3}", | ||
| (rgb >> 16) & 255, | ||
| (rgb >> 8) & 255, | ||
| rgb & 255, | ||
| _transitionTime); | ||
|
|
||
| sameColorFrameCount = 0; | ||
| totalFrames++; | ||
| } | ||
| else | ||
| { | ||
| sameColorFrameCount++; | ||
| } | ||
|
|
||
| prevRgb = rgb; | ||
| } | ||
|
|
||
| //Prepend panelId numframes | ||
| return string.Format(" {0} {1}{2}", panelId, totalFrames, sb); | ||
| } | ||
|
|
||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.