From 76ce3161ecb93816f94e34aa72d5b26c62f8dab4 Mon Sep 17 00:00:00 2001 From: Mike Nolan Date: Sat, 21 May 2022 10:37:43 -0500 Subject: [PATCH] Add extension source --- .../ClockExtension/ClockData.cs | 75 +++++++++ .../ClockExtension/ClockDialog.cs | 154 ++++++++++++++++++ .../ClockExtension/ClockExtension.csproj | 17 ++ .../ClockExtension/Extension.cs | 52 ++++++ TimelapseExtensions/ClockExtension/README.md | 0 TimelapseExtensions/ClockExtension/Rgb.cs | 45 +++++ .../ClockExtension/extension_info.json | 6 + TimelapseExtensions/ClockExtension/test.sh | 4 + TimelapseExtensions/TestPattern/Extension.cs | 83 ++++++++++ .../TestPattern/TestPattern.csproj | 17 ++ .../TestPattern/extension_info.json | 6 + TimelapseExtensions/TestPattern/test.sh | 4 + 12 files changed, 463 insertions(+) create mode 100644 TimelapseExtensions/ClockExtension/ClockData.cs create mode 100644 TimelapseExtensions/ClockExtension/ClockDialog.cs create mode 100644 TimelapseExtensions/ClockExtension/ClockExtension.csproj create mode 100644 TimelapseExtensions/ClockExtension/Extension.cs create mode 100644 TimelapseExtensions/ClockExtension/README.md create mode 100644 TimelapseExtensions/ClockExtension/Rgb.cs create mode 100644 TimelapseExtensions/ClockExtension/extension_info.json create mode 100644 TimelapseExtensions/ClockExtension/test.sh create mode 100644 TimelapseExtensions/TestPattern/Extension.cs create mode 100644 TimelapseExtensions/TestPattern/TestPattern.csproj create mode 100644 TimelapseExtensions/TestPattern/extension_info.json create mode 100644 TimelapseExtensions/TestPattern/test.sh diff --git a/TimelapseExtensions/ClockExtension/ClockData.cs b/TimelapseExtensions/ClockExtension/ClockData.cs new file mode 100644 index 0000000..998c8a0 --- /dev/null +++ b/TimelapseExtensions/ClockExtension/ClockData.cs @@ -0,0 +1,75 @@ +using Newtonsoft.Json; +using SixLabors.Fonts; +using SixLabors.ImageSharp.PixelFormats; +namespace ClockExtension +{ + public class ClockData + { + public static ClockData Load(string extDir,FontCollection coll) + { + string fontDir = Path.Combine(extDir,"Fonts"); + if(Directory.Exists(fontDir)){ + foreach(var ttf in Directory.GetFiles(fontDir,"*.ttf")) + { + coll.Add(ttf); + } + } + string extInfoFile=Path.Combine(extDir,"ext_info.json"); + if(File.Exists(extInfoFile)) + { + + string extInfoFileString = File.ReadAllText(extInfoFile); + var cd=JsonConvert.DeserializeObject(extInfoFileString); + if(cd != null) + { + cd.FilePath = extInfoFile; + FontFamily[] fam = coll.Families.ToArray(); + for(int i = 0;i{ + using(var ccd = new ColorDialog()) + { + ccd.Color = data.ForeColor; + ccd.ColorChanged+=(sender,e)=>{ + data.ForeColor=ccd.Color; + }; + ccd.ShowDialog(this); + } + }; + Button saveBtn = new Button {Text="Save"}; + saveBtn.Click +=(sender,e)=>{ + data.Save(); + this.Close(); + }; + CheckBox enabled=new CheckBox{Text="Enable Clock"}; + enabled.Checked = data.EnableClock; + enabled.CheckedChanged+=(sender,e)=>{ + data.EnableClock=enabled.Checked.GetValueOrDefault(); + }; + NumericStepper fontSize=new NumericStepper{MinValue=6,MaxValue=65535,Value = data.FontSize,DecimalPlaces=2}; + + + + fontSize.ValueChanged+= (sender,e)=>{ + data.FontSize = (float)fontSize.Value; + }; + NumericStepper x=new NumericStepper {MinValue=0,MaxValue=65535,Value=data.X}; + x.ValueChanged +=(sender,e)=>{ + data.X=(int)x.Value; + }; + NumericStepper y=new NumericStepper {MinValue=0,MaxValue=65535,Value=data.Y}; + y.ValueChanged +=(sender,e)=>{ + data.Y=(int)y.Value; + }; + + GroupBox gbox=new GroupBox{Text="Clock Position"}; + DynamicLayout lytg=new DynamicLayout(); + lytg.BeginVertical(); + lytg.BeginHorizontal(); + lytg.Add(x,true); + lytg.Add(y,true); + lytg.EndHorizontal(); + lytg.EndVertical(); + + gbox.Content=lytg; + ObservableCollection fonts = new ObservableCollection(); + Title="Clock Settings"; + TextBox timeFormat=new TextBox(); + timeFormat.PlaceholderText="yyyy/MM/dd HH:mm:ss"; + timeFormat.Text=data.DateFormat; + timeFormat.TextChanged+=(sender,e)=>{ + if(string.IsNullOrWhiteSpace(timeFormat.Text)) + { + data.DateFormat=timeFormat.PlaceholderText; + }else{ + data.DateFormat=timeFormat.Text; + } + }; + DropDown down = new DropDown(); + down.Tag = data; + down.DataStore = fonts; + Button browseFont=new Button {Text="Add Font"}; + browseFont.Click +=(sender,e)=>{ + using(var ofd=new OpenFileDialog()) + { + ofd.MultiSelect=true; + ofd.Filters.Add(new FileFilter("True Type Font",".ttf")); + if(ofd.ShowDialog(this)==DialogResult.Ok) + { + foreach(var fname in ofd.Filenames){ + string fontDir = Path.Combine(extPath,"Fonts"); + Directory.CreateDirectory(fontDir); + string fontPath=Path.Combine(fontDir,Path.GetFileName(fname)); + File.Copy(fname,fontPath); + collection.Add(fontPath); + } + } + } + DropDownRefresh(collection,fonts,down); + }; + DynamicLayout lyt=new DynamicLayout(); + lyt.BeginVertical(); + lyt.BeginHorizontal(); + lyt.Add(enabled); + lyt.EndHorizontal(); + lyt.EndBeginVertical(); + lyt.BeginHorizontal(); + lyt.Add(down,true); + DropDownRefresh(collection,fonts,down); + if(data.FontIndex < fonts.Count) + { + down.SelectedIndex=data.FontIndex; + }else{ + down.SelectedIndex=0; + } + lyt.Add(fontSize); + lyt.Add(browseFont); + + lyt.EndHorizontal(); + lyt.EndBeginVertical(); + lyt.BeginHorizontal(); + lyt.Add(timeFormat,true); + lyt.EndHorizontal(); + lyt.EndBeginVertical(); + lyt.BeginHorizontal(); + lyt.Add(gbox,true); + lyt.EndHorizontal(); + lyt.EndBeginVertical(); + lyt.BeginHorizontal(); + lyt.Add(changeColor,true); + lyt.Add(saveBtn,true); + lyt.EndHorizontal(); + lyt.EndVertical(); + this.Content=lyt; + this.Resizable=true; + } + public void SelectFont(object? sender,EventArgs e) + { + if(sender ==null) + { + return; + } + var dd=(DropDown)sender; + var coll=(ObservableCollection)dd.DataStore; + var selectedFont=(ClockData)dd.Tag; + if(dd.SelectedIndex > -1){ + selectedFont.FontName = coll[dd.SelectedIndex]; + selectedFont.FontIndex=dd.SelectedIndex; + } + } + public void DropDownRefresh(FontCollection collection,ObservableCollection fonts,DropDown dd) + { + dd.SelectedIndexChanged-=SelectFont; + fonts.Clear(); + foreach(var font in collection.Families) + { + fonts.Add(font.Name); + } + dd.SelectedIndexChanged+=SelectFont; + } + } +} \ No newline at end of file diff --git a/TimelapseExtensions/ClockExtension/ClockExtension.csproj b/TimelapseExtensions/ClockExtension/ClockExtension.csproj new file mode 100644 index 0000000..e25ce23 --- /dev/null +++ b/TimelapseExtensions/ClockExtension/ClockExtension.csproj @@ -0,0 +1,17 @@ + + + + Library + net6.0 + enable + enable + + + + + + + + + + diff --git a/TimelapseExtensions/ClockExtension/Extension.cs b/TimelapseExtensions/ClockExtension/Extension.cs new file mode 100644 index 0000000..55a69cd --- /dev/null +++ b/TimelapseExtensions/ClockExtension/Extension.cs @@ -0,0 +1,52 @@ +using TimelapseApi; +using Eto.Forms; +using System; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Fonts; + +using SixLabors.ImageSharp.Drawing.Processing; + +namespace ClockExtension +{ + public class ClockExtension : TimelapseExtension + { + FontCollection collection = new FontCollection(); + public ClockExtension() + { + collection.AddSystemFonts(); + + Data=new ClockData(); + } + public ClockData Data {get;set;} + public override string Name => "Clock Extension"; + public override Guid Id => Guid.Parse("{1cb8b576-e2e8-44d5-a8e1-e25a47eb0564}"); //https://duckduckgo.com/?q=guid&t=ffab&ia=answer + + protected override void OnCreate(ExtensionFeatures features) + { + Data=ClockData.Load(GetExtensionFolder(),collection); + features.RegisterFrameHandler(ImageHandler,"Draw Clock").RegisterSettingsDialog(()=>{ + return new ClockDialog(Data,collection,GetExtensionFolder()); + },"Clock Settings"); + } + + + + private bool ImageHandler(Image arg) + { + if(Data.EnableClock) + { + string nowTime=DateTime.Now.ToString(Data.DateFormat.Replace("\\n","\n")); + arg.Mutate((e)=>{ + var font=collection.Families.Skip(Data.FontIndex).FirstOrDefault(); + + var f=font.CreateFont(Data.FontSize); + e.DrawText(nowTime,f,Data.ForeColor,new PointF(Data.X,Data.Y)); + + }); + } + return true; + } + } +} \ No newline at end of file diff --git a/TimelapseExtensions/ClockExtension/README.md b/TimelapseExtensions/ClockExtension/README.md new file mode 100644 index 0000000..e69de29 diff --git a/TimelapseExtensions/ClockExtension/Rgb.cs b/TimelapseExtensions/ClockExtension/Rgb.cs new file mode 100644 index 0000000..1ae8642 --- /dev/null +++ b/TimelapseExtensions/ClockExtension/Rgb.cs @@ -0,0 +1,45 @@ +using TimelapseApi; +using Eto.Forms; +using System; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.Fonts; +namespace ClockExtension +{ + public class Rgb + { + public byte Red {get;set;} + public byte Green {get;set;} + + public byte Blue {get;set;} + + public static implicit operator Rgb24(Rgb color) + { + return new Rgb24(color.Red,color.Green,color.Blue); + } + public static implicit operator Rgb(Color c) + { + return c.ToPixel(); + } + public static implicit operator Color(Rgb color) + { + return new Color(color); + } + public static implicit operator Rgb(Rgb24 color) + { + return new Rgb {Red=color.R,Green=color.G,Blue = color.B}; + } + public static implicit operator Eto.Drawing.Color(Rgb color) + { + return new Eto.Drawing.Color((float)(color.Red/255.0),(float)(color.Green/255.0),(float)(color.Blue/255.0)); + } + public static implicit operator Rgb(Eto.Drawing.Color color) + { + byte r=(byte)(color.R * 255); + byte g=(byte)(color.G * 255); + byte b=(byte)(color.B * 255); + return new Rgb{Red=r,Green=g,Blue=b}; + } + } +} \ No newline at end of file diff --git a/TimelapseExtensions/ClockExtension/extension_info.json b/TimelapseExtensions/ClockExtension/extension_info.json new file mode 100644 index 0000000..6c311d4 --- /dev/null +++ b/TimelapseExtensions/ClockExtension/extension_info.json @@ -0,0 +1,6 @@ +{ + "name": "Clock Extension", + "author": "Tesses", + "version": "1.0.0", + "description": "Draws clock on screen" +} \ No newline at end of file diff --git a/TimelapseExtensions/ClockExtension/test.sh b/TimelapseExtensions/ClockExtension/test.sh new file mode 100644 index 0000000..80e4d4d --- /dev/null +++ b/TimelapseExtensions/ClockExtension/test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +timelapsepack install +cd ~/TimelapseNow/Timelapse.Linux +dotnet run \ No newline at end of file diff --git a/TimelapseExtensions/TestPattern/Extension.cs b/TimelapseExtensions/TestPattern/Extension.cs new file mode 100644 index 0000000..97dbecf --- /dev/null +++ b/TimelapseExtensions/TestPattern/Extension.cs @@ -0,0 +1,83 @@ +using TimelapseApi; +using System; +using SixLabors.ImageSharp; +using SixLabors.ImageSharp.PixelFormats; +using SixLabors.ImageSharp.Processing; +using SixLabors.ImageSharp.Drawing; +using SixLabors.ImageSharp.Drawing.Processing; + +namespace TestPattern +{ + public class TestPattern : TimelapseExtension + { + public override string Name => "Test Pattern"; + public override Guid Id => Guid.Parse("{d918ac89-c07a-4ce4-a94b-c3e6c6f7a7e3}"); //https://duckduckgo.com/?q=guid&t=ffab&ia=answer + + + + protected override void OnCreate(ExtensionFeatures features) + { + + features.RegisterFrameHandler((e)=>{ + if(Instance == null) + { + return true; + } + if(Instance.HasCamera) + { + return true; + } + int colW=e.Width / 7; + int widthtotalBottom = (int)(colW* 3.80); + int colH=(int)(e.Height * 0.70); + int bottomY=(int)(e.Height*0.80); + int bottomW = widthtotalBottom/3; + + Action draw=(color,i,ipc)=>{ + ipc.FillPolygon(color,new PointF(0+(colW*i),0),new PointF(colW + (colW*i),0),new PointF(colW + (colW*i),colH),new PointF(0+(colW*i),colH),new PointF(0+(colW*i),0)); + }; + Action draw_middle = (color,i,ipc)=>{ + ipc.FillPolygon(color,new PointF(0+(colW*i),colH),new PointF(colW + (colW*i),colH),new PointF(colW + (colW*i),bottomY),new PointF(0+(colW*i),bottomY),new PointF(0+(colW*i),0)); + + }; + Action draw_bottom = (color,i,ipc)=>{ + ipc.FillPolygon(color,new PointF(0+(bottomW*i),bottomY),new PointF(bottomW + (bottomW*i),bottomY),new PointF(bottomW + (bottomW*i),e.Height),new PointF(0+(bottomW*i),e.Height),new PointF(0+(bottomW*i),bottomY)); + }; + + e.Mutate((e)=>{ + var white=Color.White; + var yellow = Color.Yellow; + var aqua = Color.Aqua; + + var magenta =Color.Magenta; + var red=Color.Red; + var blue = Color.Blue; + var black=Color.Black; + var navy=Color.Navy; + var lime=Color.Lime; + draw(white,0,e); + draw(yellow,1,e); + draw(aqua,2,e); + draw(lime,3,e); + draw(magenta,4,e); + draw(red,5,e); + draw(blue,6,e); + draw_middle(red,2,e); + draw_middle(blue,1,e); + draw_middle(magenta,3,e); + draw_middle(lime,4,e); + draw_middle(aqua,5,e); + draw_middle(yellow,6,e); + draw_bottom(navy,0,e); + draw_bottom(white,1,e); + draw_bottom(navy,2,e); + }); + + + return true; + },"Test Pattern",0); + } + + + } +} \ No newline at end of file diff --git a/TimelapseExtensions/TestPattern/TestPattern.csproj b/TimelapseExtensions/TestPattern/TestPattern.csproj new file mode 100644 index 0000000..ef68e93 --- /dev/null +++ b/TimelapseExtensions/TestPattern/TestPattern.csproj @@ -0,0 +1,17 @@ + + + + Library + net6.0 + enable + enable + + + + + + + + + + diff --git a/TimelapseExtensions/TestPattern/extension_info.json b/TimelapseExtensions/TestPattern/extension_info.json new file mode 100644 index 0000000..96dfa7a --- /dev/null +++ b/TimelapseExtensions/TestPattern/extension_info.json @@ -0,0 +1,6 @@ +{ + "name": "Test Pattern", + "author": "Tesses", + "version": "1.0.0", + "description": "Draws test pattern when timelapse webcam is not available" +} \ No newline at end of file diff --git a/TimelapseExtensions/TestPattern/test.sh b/TimelapseExtensions/TestPattern/test.sh new file mode 100644 index 0000000..80e4d4d --- /dev/null +++ b/TimelapseExtensions/TestPattern/test.sh @@ -0,0 +1,4 @@ +#!/bin/bash +timelapsepack install +cd ~/TimelapseNow/Timelapse.Linux +dotnet run \ No newline at end of file