Finished Project Editor.

Builder now supports parallel building.
This commit is contained in:
Creeper Lv
2026-01-13 03:33:49 +11:00
parent f4b43abc08
commit 04e67074d2
16 changed files with 290 additions and 92 deletions

View File

@@ -1,19 +1,25 @@
using Progrart.Core.ProjectSystem; using Progrart.Core.ProjectSystem;
using Progrart.Core.Storage; using Progrart.Core.Storage;
using System.Diagnostics;
namespace Progrart.Cmd namespace Progrart.Cmd
{ {
internal class Program internal class Program
{ {
static void Main(string[] args) static async Task Main(string[] args)
{ {
Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
string? project_file = null; string? project_file = null;
bool isParallel = false;
string? configuration = null; string? configuration = null;
for (int i = 0; i < args.Length; i++) for (int i = 0; i < args.Length; i++)
{ {
string? item = args[i]; string? item = args[i];
switch (item) switch (item)
{ {
case "-j":
isParallel=true;
break;
case "-c": case "-c":
case "--config": case "--config":
case "--configuration": case "--configuration":
@@ -44,22 +50,24 @@ namespace Progrart.Cmd
using var sr = new StreamReader(fs); using var sr = new StreamReader(fs);
ClassicStorageProvider provider = new ClassicStorageProvider(di); ClassicStorageProvider provider = new ClassicStorageProvider(di);
Builder builder = new Builder(sr, provider); Builder builder = new Builder(sr, provider);
builder.OnProgressUpdate = (v, m) => builder.OnProgressUpdate = (max, index) =>
{ {
Console.WriteLine($"{v}/{m}"); Console.WriteLine($"Done {index}/{max}");
}; };
builder.OnCompleted = () => builder.OnCompleted = () =>
{ {
Environment.Exit(0); Environment.Exit(0);
}; };
Task.Run(async () => Console.WriteLine("Start build...");
{ //Task.Run(async () =>
await builder.Build(configuration); //{
}); //});
while (true) //while (true)
{ //{
Thread.Sleep(1000); // Thread.Sleep(1000);
} //}
await builder.Build(configuration, isParallel);
} }
} }
} }

View File

@@ -44,7 +44,15 @@ namespace Progrart.Core.JSExecution
JsObject _obj = new JsObject(Engine); JsObject _obj = new JsObject(Engine);
Engine.SetValue("math", _obj); Engine.SetValue("math", _obj);
Random r = new Random(); Random r = new Random();
Engine.SetValue("def", (string k) => { return Symbols.ContainsKey(k); });
Engine.SetValue("to_bool", (JsValue v) => { return bool.Parse(v.AsString().ToLower()); });
Engine.SetValue("to_float", (JsValue v) => { return float.Parse(v.AsString().ToLower()); });
Engine.SetValue("to_int", (JsValue v) => { return int.Parse(v.AsString().ToLower()); });
Engine.SetValue("query", (string k, string fallback) =>
{
if (Symbols.TryGetValue(k, out var val)) return val;
return fallback;
});
_obj.Set("random", JsObject.FromObject(Engine, new Func<double>(() => _obj.Set("random", JsObject.FromObject(Engine, new Func<double>(() =>
{ {
return r.NextDouble(); return r.NextDouble();

View File

@@ -55,7 +55,7 @@ namespace Progrart.Core.JSExecution
engine.Engine.SetValue("visual_root", visual_root); engine.Engine.SetValue("visual_root", visual_root);
engine.Engine.SetValue("line", line); engine.Engine.SetValue("line", line);
engine.Engine.SetValue("rectangle", rectangle); engine.Engine.SetValue("rectangle", rectangle);
engine.Engine.SetValue("rectangle", rectangle); engine.Engine.SetValue("roundrect", roundrect);
engine.Engine.SetValue("oval", oval); engine.Engine.SetValue("oval", oval);
engine.Engine.SetValue("triangle", triangle); engine.Engine.SetValue("triangle", triangle);
engine.Engine.SetValue("path", path); engine.Engine.SetValue("path", path);

View File

@@ -37,7 +37,6 @@ namespace Progrart.Core
{ {
Width = W; Width = W;
Height = H; Height = H;
Trace.WriteLine($"Createing Surface as: {W} x {H}");
info = new SKImageInfo(W, H); info = new SKImageInfo(W, H);
surface = SKSurface.Create(info); surface = SKSurface.Create(info);
canvas = surface.Canvas; canvas = surface.Canvas;

View File

@@ -1,6 +1,7 @@
using Newtonsoft.Json; using Newtonsoft.Json;
using Progrart.Core.JSExecution; using Progrart.Core.JSExecution;
using Progrart.Core.Storage; using Progrart.Core.Storage;
using System.Diagnostics;
namespace Progrart.Core.ProjectSystem namespace Progrart.Core.ProjectSystem
{ {
@@ -24,8 +25,6 @@ namespace Progrart.Core.ProjectSystem
} }
public async Task Execute(BuildConfiguration config, BuildItem item) public async Task Execute(BuildConfiguration config, BuildItem item)
{ {
//FileInfo src = new FileInfo(Path.Combine(basePath, item.Source));
//FileInfo tgt = new FileInfo(Path.Combine(basePath, project.OutputDir, item.Target ?? item.Source + ".png"));
var args = project.Arguments.Clone(); var args = project.Arguments.Clone();
args.MergeFrom(config.Arguments); args.MergeFrom(config.Arguments);
args.MergeFrom(item.Arguments); args.MergeFrom(item.Arguments);
@@ -41,23 +40,47 @@ namespace Progrart.Core.ProjectSystem
img.DrawingCore.ToData().SaveTo(img_stream); img.DrawingCore.ToData().SaveTo(img_stream);
img_stream.Flush(); img_stream.Flush();
} }
public async Task Build(string targetConfig) public async Task Build(string targetConfig, bool isParallel = false)
{ {
foreach (var config in project.Configurations) foreach (var config in project.Configurations)
{ {
Console.WriteLine(config.Name);
if (config.Name == targetConfig) if (config.Name == targetConfig)
{ {
int index = 0; int index = 0;
List<Task> tasks = new List<Task>();
foreach (var item in config.Items) foreach (var item in config.Items)
{ {
if (!isParallel)
{
await Execute(config, item); await Execute(config, item);
index++; index++;
OnProgressUpdate?.Invoke(config.Items.Count, index); OnProgressUpdate?.Invoke(config.Items.Count, index);
} }
else
{
var t = Task.Run(async () =>
{
index++;
int i = index;
await Execute(config, item);
OnProgressUpdate?.Invoke(config.Items.Count, i);
});
tasks.Add(t);
}
}
if (isParallel)
{
await Task.WhenAll(tasks);
}
OnCompleted?.Invoke(); OnCompleted?.Invoke();
return; return;
} }
} }
throw new Exception($"Configuration \"{targetConfig}\" not found!");
} }
} }
} }

View File

@@ -25,6 +25,13 @@
{ {
try try
{ {
FileInfo fi = new FileInfo(Path.Combine(BaseDirectory.FullName, path));
var di = fi.Directory;
if (di is not null)
{
if (!di.Exists)
di.Create();
}
return File.OpenWrite(Path.Combine(BaseDirectory.FullName, path)); return File.OpenWrite(Path.Combine(BaseDirectory.FullName, path));
} }
catch (Exception) catch (Exception)

View File

@@ -306,5 +306,11 @@
<Setter Property="Padding" Value="16,2"/> <Setter Property="Padding" Value="16,2"/>
<Setter Property="FontSize" Value="12"/> <Setter Property="FontSize" Value="12"/>
</Style> </Style>
<Style Selector="NumericUpDown">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="MinHeight" Value="0"/>
<Setter Property="Padding" Value="4,2"/>
</Style>
</Application.Styles> </Application.Styles>
</Application> </Application>

View File

@@ -6,7 +6,22 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Progrart.Controls.ConfigEditor" Margin="5"> x:Class="Progrart.Controls.ConfigEditor" Margin="5">
<StackPanel> <StackPanel>
<TextBlock Name="NameBlock" FontSize="18" Text="{Binding #NameBox.Text}"/> <Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<ToggleButton Name="NameButton" VerticalAlignment="Stretch" HorizontalAlignment="Stretch"
Padding="16,0"
IsCheckedChanged="NameButton_IsCheckedChanged">
<StackPanel Orientation="Horizontal">
<TextBlock Text="Configuration:" Opacity="0.75" VerticalAlignment="Center" HorizontalAlignment="Center"/>
<TextBlock Name="NameBlock" Text="{Binding #NameBox.Text}" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
</ToggleButton>
<Button Grid.Column="1" Content=" - " Name="RemoveButton"/>
</Grid>
<StackPanel Name="ConfigContent" IsVisible="False">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
@@ -21,7 +36,7 @@
<TextBlock Padding="8,2" Grid.Row="1" VerticalAlignment="Center">Output</TextBlock> <TextBlock Padding="8,2" Grid.Row="1" VerticalAlignment="Center">Output</TextBlock>
<TextBox Grid.Column="1" Grid.Row="1" Name="OutputDirBox"/> <TextBox Grid.Column="1" Grid.Row="1" Name="OutputDirBox"/>
</Grid> </Grid>
<local:ExecuteArgumentsEditor/> <local:ExecuteArgumentsEditor Name="Arguments"/>
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition/> <ColumnDefinition/>
@@ -33,4 +48,5 @@
<StackPanel Name="TargetHolder" Margin="5,0"> <StackPanel Name="TargetHolder" Margin="5,0">
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</StackPanel>
</UserControl> </UserControl>

View File

@@ -1,5 +1,6 @@
using Avalonia.Controls; using Avalonia.Controls;
using AvaloniaEdit.Editing; using AvaloniaEdit.Editing;
using Progrart.Core.ProjectSystem;
namespace Progrart.Controls; namespace Progrart.Controls;
@@ -12,5 +13,41 @@ public partial class ConfigEditor : UserControl
{ {
TargetHolder.Children.Add(new TargetEditor()); TargetHolder.Children.Add(new TargetEditor());
}; };
RemoveButton.Click += (_, _) =>
{
if (Parent is StackPanel panel)
{
panel.Children.Remove(this);
}
};
}
public void LoadConfig(BuildConfiguration config)
{
Arguments.LoadArguments(config.Arguments);
NameBox.Text = config.Name;
OutputDirBox.Text = config.OutputDir;
foreach (var item in config.Items)
{
TargetHolder.Children.Add(new TargetEditor(item));
}
}
public BuildConfiguration ObtainConfiguration()
{
BuildConfiguration configuration = new BuildConfiguration();
configuration.OutputDir = OutputDirBox.Text;
configuration.Name= NameBox.Text;
configuration.Arguments = Arguments.ObtainArguments();
foreach (var item in TargetHolder.Children)
{
if (item is TargetEditor editor)
{
configuration.Items.Add(editor.GetItem());
}
}
return configuration;
}
private void NameButton_IsCheckedChanged(object? sender, Avalonia.Interactivity.RoutedEventArgs e)
{
ConfigContent.IsVisible = NameButton.IsChecked ?? false;
} }
} }

View File

@@ -27,5 +27,5 @@ public partial class ExecuteArgumentItem : UserControl
} }
}; };
} }
public (string, string) GetItme() => (KeyBox.Text ?? "", ValueBox.Text ?? ""); public (string, string) GetItem() => (KeyBox.Text ?? "", ValueBox.Text ?? "");
} }

View File

@@ -22,4 +22,23 @@ public partial class ExecuteArgumentsEditor : UserControl
ItemHolder.Children.Add(new ExecuteArgumentItem(item.Key, item.Value)); ItemHolder.Children.Add(new ExecuteArgumentItem(item.Key, item.Value));
} }
} }
public void Clear()
{
ItemHolder.Children.Clear();
}
public ExecuteArguments ObtainArguments()
{
ExecuteArguments args = new ExecuteArguments();
foreach (var item in ItemHolder.Children)
{
if (item is ExecuteArgumentItem eaItem)
{
var (key, value) = eaItem.GetItem();
args.data[key] = value;
}
}
return args;
}
} }

View File

@@ -5,6 +5,7 @@
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Progrart.TargetEditor"> x:Class="Progrart.TargetEditor">
<Border Margin="5" Padding="5" Background="#1888" CornerRadius="5">
<Grid> <Grid>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition/> <ColumnDefinition/>
@@ -15,13 +16,21 @@
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition/> <RowDefinition/>
<RowDefinition/> <RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/> <ColumnDefinition Width="Auto"/>
<ColumnDefinition/> <ColumnDefinition/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock>Source</TextBlock>
<TextBlock Grid.Row="1">Output Name:</TextBlock>
<TextBox Grid.Column="1" Name="SourceFileBox"/>
<TextBox Grid.Column="1" Grid.Row="1" Name="OutputFileBox"/>
<NumericUpDown Grid.Column="1" Grid.Row="2" Name="SizeBox" HorizontalContentAlignment="Right" Minimum="1" Maximum="65535" />
</Grid> </Grid>
<controls:ExecuteArgumentsEditor/> <controls:ExecuteArgumentsEditor Name="Arguments"/>
</StackPanel> </StackPanel>
<Button Grid.Column="1" Content="-" VerticalAlignment="Top" Padding="8"/>
</Grid> </Grid>
</Border>
</UserControl> </UserControl>

View File

@@ -1,6 +1,7 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Progrart.Core.ProjectSystem;
namespace Progrart; namespace Progrart;
@@ -10,4 +11,21 @@ public partial class TargetEditor : UserControl
{ {
InitializeComponent(); InitializeComponent();
} }
public TargetEditor(Progrart.Core.ProjectSystem.BuildItem item)
{
InitializeComponent();
SourceFileBox.Text = item.Source;
OutputFileBox.Text = item.Target;
SizeBox.Value = item.Size;
this.Arguments.LoadArguments(item.Arguments);
}
public BuildItem GetItem()
{
BuildItem item = new BuildItem();
item.Source = SourceFileBox.Text ?? "";
item.Target = OutputFileBox.Text ?? "";
item.Size = (int)(SizeBox.Value ?? 0);
item.Arguments = this.Arguments.ObtainArguments();
return item;
}
} }

View File

@@ -10,6 +10,9 @@
<Setter Property="Padding" Value="4,2"/> <Setter Property="Padding" Value="4,2"/>
<Setter Property="MinHeight" Value="0"/> <Setter Property="MinHeight" Value="0"/>
</Style> </Style>
<Style Selector="TextBlock">
<Setter Property="Margin" Value="8,0"/>
</Style>
</UserControl.Styles> </UserControl.Styles>
<ScrollViewer> <ScrollViewer>
<StackPanel> <StackPanel>

View File

@@ -2,10 +2,14 @@ using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Avalonia.Platform.Storage; using Avalonia.Platform.Storage;
using Avalonia.Threading;
using Newtonsoft.Json;
using Progrart.Controls; using Progrart.Controls;
using Progrart.Controls.TabSystem; using Progrart.Controls.TabSystem;
using Progrart.Core; using Progrart.Core;
using Progrart.Core.ProjectSystem;
using System; using System;
using System.IO;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Progrart.Pages; namespace Progrart.Pages;
@@ -33,10 +37,53 @@ public partial class ProjectEditor : UserControl, ITabPage, IEditorPage
public void LoadDocument(IStorageFile file) public void LoadDocument(IStorageFile file)
{ {
this.file = file; this.file = file;
Task.Run(async () =>
{
using var stream = await file.OpenReadAsync();
using var sr = new StreamReader(stream);
Project? project = JsonConvert.DeserializeObject<Project>(sr.ReadToEnd());
if (project is null)
{
return;
}
Dispatcher.UIThread.Invoke(() =>
{
Load(project);
});
});
}
void Load(Project project)
{
this.OutputDirBox.Text = project.OutputDir;
ProjectWideArguments.LoadArguments(project.Arguments);
foreach (var config in project.Configurations)
{
var editor = new ConfigEditor();
editor.LoadConfig(config);
ConfigurationHolder.Children.Add(editor);
}
} }
public async Task Save() public async Task Save()
{ {
if (file is null) return;
Project project = new Project();
await Dispatcher.UIThread.InvokeAsync(() =>
{
project.OutputDir = this.OutputDirBox.Text ?? "";
project.Arguments = ProjectWideArguments.ObtainArguments();
foreach (var item in ConfigurationHolder.Children)
{
if (item is ConfigEditor editor)
{
project.Configurations.Add(editor.ObtainConfiguration());
}
}
});
using var stream = await file.OpenWriteAsync();
using var sw = new StreamWriter(stream);
sw.WriteLine(JsonConvert.SerializeObject(project, Formatting.Indented));
sw.Flush();
sw.Close();
} }
public void SetHost(TabHost host) public void SetHost(TabHost host)

View File

@@ -139,9 +139,7 @@
<Border Margin="4,6" Width="1" Background="#8888"></Border> <Border Margin="4,6" Width="1" Background="#8888"></Border>
<TextBlock Text="Size" Margin="8,0" IsHitTestVisible="False" VerticalAlignment="Center"/> <TextBlock Text="Size" Margin="8,0" IsHitTestVisible="False" VerticalAlignment="Center"/>
<NumericUpDown Name="SizeBox" Minimum="1" Maximum="65535" FormatString="00000" <NumericUpDown Name="SizeBox" Minimum="1" Maximum="65535" FormatString="00000"
Value="1024" VerticalAlignment="Center" Padding="4,2" Value="1024" Margin="5,0" ToolTip.Tip="Size of generated preview image"/>
Margin="5,0" ToolTip.Tip="Size of generated preview image"
VerticalContentAlignment="Center" MinHeight="0"/>
<CheckBox Name="IsDebugBox" Margin="7,0" Content="Is Debug" VerticalContentAlignment="Center"/> <CheckBox Name="IsDebugBox" Margin="7,0" Content="Is Debug" VerticalContentAlignment="Center"/>
<Button Name="RunButton" ToolTip.Tip="Preview"> <Button Name="RunButton" ToolTip.Tip="Preview">
<PathIcon Foreground="#0A0" Data="F1 M 17.24 10.48 C 17.453333 10.613333 17.633331 10.799999 17.779999 11.039999 C 17.926666 11.28 18 11.533333 18 11.799999 C 18 12.066667 17.926666 12.32 17.779999 12.559999 C 17.633331 12.799999 17.453333 12.986667 17.24 13.12 L 7.24 18.599998 C 7 18.733334 6.746666 18.799999 6.48 18.799999 C 6.213333 18.799999 5.966666 18.733334 5.74 18.599998 C 5.513333 18.466667 5.333333 18.279999 5.2 18.039999 C 5.066667 17.799999 5 17.546665 5 17.279999 L 5 6.32 C 5 6.053333 5.066667 5.799999 5.2 5.559999 C 5.333333 5.32 5.513333 5.133333 5.74 5 C 5.966666 4.866667 6.213333 4.799999 6.48 4.799999 C 6.746666 4.799999 7 4.866667 7.24 5 Z M 16.719999 12.24 C 16.906666 12.133333 17 11.986667 17 11.799999 C 17 11.613333 16.906666 11.466667 16.719999 11.36 L 6.76 5.879999 C 6.573333 5.773333 6.4 5.766666 6.24 5.86 C 6.08 5.953334 6 6.106668 6 6.32 L 6 17.279999 C 6 17.493332 6.08 17.646666 6.24 17.74 C 6.4 17.833332 6.573333 17.826666 6.76 17.719999 Z " VerticalAlignment="Center" HorizontalAlignment="Center" /> <PathIcon Foreground="#0A0" Data="F1 M 17.24 10.48 C 17.453333 10.613333 17.633331 10.799999 17.779999 11.039999 C 17.926666 11.28 18 11.533333 18 11.799999 C 18 12.066667 17.926666 12.32 17.779999 12.559999 C 17.633331 12.799999 17.453333 12.986667 17.24 13.12 L 7.24 18.599998 C 7 18.733334 6.746666 18.799999 6.48 18.799999 C 6.213333 18.799999 5.966666 18.733334 5.74 18.599998 C 5.513333 18.466667 5.333333 18.279999 5.2 18.039999 C 5.066667 17.799999 5 17.546665 5 17.279999 L 5 6.32 C 5 6.053333 5.066667 5.799999 5.2 5.559999 C 5.333333 5.32 5.513333 5.133333 5.74 5 C 5.966666 4.866667 6.213333 4.799999 6.48 4.799999 C 6.746666 4.799999 7 4.866667 7.24 5 Z M 16.719999 12.24 C 16.906666 12.133333 17 11.986667 17 11.799999 C 17 11.613333 16.906666 11.466667 16.719999 11.36 L 6.76 5.879999 C 6.573333 5.773333 6.4 5.766666 6.24 5.86 C 6.08 5.953334 6 6.106668 6 6.32 L 6 17.279999 C 6 17.493332 6.08 17.646666 6.24 17.74 C 6.4 17.833332 6.573333 17.826666 6.76 17.719999 Z " VerticalAlignment="Center" HorizontalAlignment="Center" />