Add extension source
This commit is contained in:
parent
9469f5432f
commit
76ce3161ec
|
@ -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<ClockData>(extInfoFileString);
|
||||
if(cd != null)
|
||||
{
|
||||
cd.FilePath = extInfoFile;
|
||||
FontFamily[] fam = coll.Families.ToArray();
|
||||
for(int i = 0;i<fam.Length;i++)
|
||||
{
|
||||
if(fam[i].Name.Equals(cd.FontName,StringComparison.Ordinal))
|
||||
{
|
||||
cd.FontIndex=i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return cd;
|
||||
}
|
||||
}
|
||||
return new ClockData {FilePath=extInfoFile};
|
||||
}
|
||||
public ClockData()
|
||||
{
|
||||
EnableClock=true;
|
||||
DateFormat = "yyyy/MM/dd HH:mm:ss";
|
||||
FontIndex=0;
|
||||
FilePath="";
|
||||
FontSize = 24;
|
||||
ForeColor=Eto.Drawing.Colors.White;
|
||||
X=16;
|
||||
Y=16;
|
||||
}
|
||||
[JsonIgnore]
|
||||
public int FontIndex {get;set;}
|
||||
[JsonIgnore]
|
||||
public string FilePath {get;private set;}
|
||||
public bool EnableClock {get;set;}
|
||||
|
||||
public int X {get;set;}
|
||||
public int Y {get;set;}
|
||||
|
||||
public string? FontName {get;set;}
|
||||
|
||||
public float FontSize {get;set;}
|
||||
|
||||
public string DateFormat {get;set;}
|
||||
|
||||
public Rgb ForeColor {get;set;}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
string data=JsonConvert.SerializeObject(this);
|
||||
File.WriteAllText(FilePath,data);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
using System.Collections.ObjectModel;
|
||||
using Eto.Forms;
|
||||
using SixLabors.Fonts;
|
||||
|
||||
namespace ClockExtension
|
||||
{
|
||||
public class ClockDialog : Dialog
|
||||
{
|
||||
public ClockDialog(ClockData data,FontCollection collection,string extPath)
|
||||
{
|
||||
Button changeColor = new Button {Text="Change Color"};
|
||||
changeColor.Click+=(sender,e)=>{
|
||||
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<string> fonts = new ObservableCollection<string>();
|
||||
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<string>)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<string> fonts,DropDown dd)
|
||||
{
|
||||
dd.SelectedIndexChanged-=SelectFont;
|
||||
fonts.Clear();
|
||||
foreach(var font in collection.Families)
|
||||
{
|
||||
fonts.Add(font.Name);
|
||||
}
|
||||
dd.SelectedIndexChanged+=SelectFont;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta17" />
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
|
||||
<PackageReference Include="Tesses.TimelapseApi" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -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<Rgb24> 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<Rgb24>();
|
||||
}
|
||||
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};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "Clock Extension",
|
||||
"author": "Tesses",
|
||||
"version": "1.0.0",
|
||||
"description": "Draws clock on screen"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
timelapsepack install
|
||||
cd ~/TimelapseNow/Timelapse.Linux
|
||||
dotnet run
|
|
@ -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<Color,int,IImageProcessingContext> 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<Color,int,IImageProcessingContext> 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<Color,int,IImageProcessingContext> 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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Library</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="SixLabors.ImageSharp.Drawing" Version="1.0.0-beta14" />
|
||||
|
||||
<PackageReference Include="Tesses.TimelapseApi" Version="1.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"name": "Test Pattern",
|
||||
"author": "Tesses",
|
||||
"version": "1.0.0",
|
||||
"description": "Draws test pattern when timelapse webcam is not available"
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/bash
|
||||
timelapsepack install
|
||||
cd ~/TimelapseNow/Timelapse.Linux
|
||||
dotnet run
|
Loading…
Reference in New Issue