mirror of
https://github.com/riegera2412/UVtools.git
synced 2026-07-31 21:02:15 +02:00
* (Upgrade) EmguCV/OpenCV to v4.5.1
* (Upgrade) AvaloniaUI to 1.0
* (Improvement) GUI re-touched
* (Improvement) Make pixel editor tab to disappear when pixel editor is disabled
* (Improvement) Simplify the output filename from PrusaSlicer profiles
* (Improvement) All operations require a slicer file at constructor rather than on execute, this allow exposure the open file to the operation before run it
* (Improvement) Calibrations: Auto set "Mirror Output" if open file have MirrorDisplay set
* (Change) Tool - Redraw model/supports icon
* (Change) photon and cbddlp to use version 3 by default
* (Add) Tool - Dynamic layer height: Analyze and optimize the model with dynamic layer heights, larger angles will slice at lower layer height
while more straight angles will slice larger layer height. (#131)
* (Add) Calibration - Exposure time finder: Generates test models with various strategies and increments to verify the best exposure time for a given layer height
* (Add) File load checks, trigger error when a file have critical errors and attempt to fix non-critical errors
* Layers must have an valid image, otherwise trigger an error
* Layers must have a incremental or equal position Z than it previous, otherwise trigger an error
* If layer 0 starts at 0mm it will auto fix all layers, it will add Layer Height to the current z at every layer
* (Add) Tool - Edit print parameters: Allow set parameters to each x layers and skip n layers inside the given range.
This allow the use of optimizations in a layer pattern, for example, to set 3s for a layer but 2.5s for the next.
* (Add) Layer height property to "Layer Data" table: Shows layer height for the slice
* (Fix) When automations applied and file is saved, it will not warn user about file overwrite for the first time save
* (Fix) Tool - Redraw model/supports: Disable apply button when no file selected
* (Fix) Tool - Infill: Lack of equality member to test if same infill profile already exists
* (Fix) Auto converted files from SL1 where clipping filename at first dot (.), now it only strips known extensions
* (Fix) SL1 encoded files wasn't generating the right information and lead to printer crash
* (Fix) PrusaSlicer printer "Anycubic Photon S" LiftSpeed was missing and contains a typo (#135)
* (Fix) PrusaSlicer profile manager wasnt marking missing profiles to be installed (#135)
* (Fix) PrusaSlicer folder search on linux to also look at %HOME%/.config/PrusaSlicer (#135, #136)
* (Fix) Operations were revised and some bug fixed, most about can't cancel the progress
* (Fix) Some typos on tooltips
* (Fix) Prevent PhotonS from enconding, it will trigger error now as this format is read-only
* **(Fix) Ctrl + Shift + Z to redo the last operation:**
* The layer range is reseted instead of pull the used values
* Tool - Arithmetic always disabled
* Action - Layer import didn't generate info and always disabled
293 lines
10 KiB
C#
293 lines
10 KiB
C#
/*
|
|
* GNU AFFERO GENERAL PUBLIC LICENSE
|
|
* Version 3, 19 November 2007
|
|
* Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
|
* Everyone is permitted to copy and distribute verbatim copies
|
|
* of this license document, but changing it is not allowed.
|
|
*/
|
|
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using Avalonia;
|
|
using Avalonia.Controls.ApplicationLifetimes;
|
|
using Avalonia.Markup.Xaml;
|
|
using Avalonia.Media.Imaging;
|
|
using Avalonia.Platform;
|
|
using Avalonia.ThemeManager;
|
|
using Emgu.CV;
|
|
using UVtools.Core;
|
|
using UVtools.Core.FileFormats;
|
|
using UVtools.WPF.Extensions;
|
|
using UVtools.WPF.Structures;
|
|
|
|
namespace UVtools.WPF
|
|
{
|
|
public class App : Application
|
|
{
|
|
public static ThemeSelector ThemeSelector { get; set; }
|
|
public static MainWindow MainWindow;
|
|
public static FileFormat SlicerFile = null;
|
|
|
|
public static AppVersionChecker VersionChecker { get; } = new AppVersionChecker();
|
|
|
|
public override void Initialize()
|
|
{
|
|
AvaloniaXamlLoader.Load(this);
|
|
}
|
|
|
|
public override async void OnFrameworkInitializationCompleted()
|
|
{
|
|
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
|
|
{
|
|
CultureInfo.DefaultThreadCurrentCulture = CultureInfo.InvariantCulture;
|
|
CultureInfo.DefaultThreadCurrentUICulture = CultureInfo.InvariantCulture;
|
|
|
|
UserSettings.Load();
|
|
UserSettings.SetVersion();
|
|
|
|
OperationProfiles.Load();
|
|
|
|
/*ThemeSelector = ThemeSelector.Create(Path.Combine(ApplicationPath, "Assets", "Themes"));
|
|
ThemeSelector.LoadSelectedTheme(Path.Combine(UserSettings.SettingsFolder, "selected.theme"));
|
|
if (ThemeSelector.SelectedTheme.Name == "UVtoolsDark" || ThemeSelector.SelectedTheme.Name == "Light")
|
|
{
|
|
foreach (var theme in ThemeSelector.Themes)
|
|
{
|
|
if (theme.Name != "UVtoolsLight") continue;
|
|
theme.ApplyTheme();
|
|
break;
|
|
}
|
|
}*/
|
|
|
|
MainWindow = new MainWindow();
|
|
try
|
|
{
|
|
if(!CvInvoke.Init())
|
|
await MainWindow.MessageBoxError("UVtools can not init OpenCV library\n" +
|
|
"Please build or install this dependencies in order to run UVtools\n" +
|
|
"Check manual or page at 'Requirements' section for help",
|
|
"UVtools can not run");
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
await MainWindow.MessageBoxError("UVtools can not run due lack of dependencies from cvextern/OpenCV\n" +
|
|
"Please build or install this dependencies in order to run UVtools\n" +
|
|
"Check manual or page at 'Requirements' section for help\n\n" +
|
|
"Additional information:\n" +
|
|
$"{e}", "UVtools can not run");
|
|
return;
|
|
}
|
|
|
|
desktop.MainWindow = MainWindow;
|
|
//desktop.Exit += (sender, e) => ThemeSelector.SaveSelectedTheme(Path.Combine(UserSettings.SettingsFolder, "selected.theme"));
|
|
}
|
|
|
|
base.OnFrameworkInitializationCompleted();
|
|
}
|
|
|
|
#region Utilities
|
|
|
|
public static string AppExecutable = Path.Combine(ApplicationPath, About.Software);
|
|
public static string AppExecutableQuoted = $"\"{AppExecutable}\"";
|
|
public static void NewInstance(string filePath)
|
|
{
|
|
try
|
|
{
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
{
|
|
StartProcess($"{AppExecutable}.exe", $"\"{filePath}\"");
|
|
}
|
|
else if(File.Exists(AppExecutable)) // Direct execute
|
|
{
|
|
StartProcess(AppExecutable, $"\"{filePath}\"");
|
|
}
|
|
else
|
|
{
|
|
StartProcess("dotnet", $"UVtools.dll \"{filePath}\"");
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.WriteLine(e);
|
|
}
|
|
}
|
|
|
|
public static void OpenBrowser(string url)
|
|
{
|
|
try
|
|
{
|
|
if (OperatingSystem.IsWindows())
|
|
{
|
|
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }).Dispose();
|
|
}
|
|
else if (OperatingSystem.IsLinux())
|
|
{
|
|
Process.Start("xdg-open", url).Dispose();
|
|
}
|
|
else if (OperatingSystem.IsMacOS())
|
|
{
|
|
Process.Start("open", url).Dispose();
|
|
}
|
|
else
|
|
{
|
|
// throw
|
|
}
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.WriteLine(e);
|
|
}
|
|
|
|
}
|
|
|
|
public static void StartProcess(string name, string arguments = null)
|
|
{
|
|
try
|
|
{
|
|
using (Process.Start(new ProcessStartInfo(name, arguments)
|
|
{
|
|
UseShellExecute = true
|
|
})) { }
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Debug.WriteLine(e);
|
|
}
|
|
}
|
|
|
|
public static Stream GetAsset(string url)
|
|
{
|
|
Uri uri;
|
|
|
|
// Allow for assembly overrides
|
|
if (url.StartsWith("avares://"))
|
|
{
|
|
uri = new Uri(url);
|
|
}
|
|
else
|
|
{
|
|
var assemblyName = Assembly.GetEntryAssembly().GetName().Name;
|
|
uri = new Uri($"avares://{assemblyName}{url}");
|
|
}
|
|
|
|
var res = AvaloniaLocator.Current.GetService<IAssetLoader>().Open(uri);
|
|
return res;
|
|
}
|
|
|
|
public static Bitmap GetBitmapFromAsset(string url) => new Bitmap(GetAsset(url));
|
|
|
|
public static string ApplicationPath => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
|
|
|
|
public static string GetPrusaSlicerDirectory()
|
|
{
|
|
if (OperatingSystem.IsWindows())
|
|
{
|
|
return $"{Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)}{Path.DirectorySeparatorChar}PrusaSlicer";
|
|
}
|
|
|
|
if (OperatingSystem.IsLinux())
|
|
{
|
|
var folder1 = $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}{Path.DirectorySeparatorChar}.config{Path.DirectorySeparatorChar}PrusaSlicer";
|
|
if (Directory.Exists(folder1)) return folder1;
|
|
return $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}{Path.DirectorySeparatorChar}.PrusaSlicer";
|
|
}
|
|
|
|
if (OperatingSystem.IsMacOS())
|
|
{
|
|
return string.Format("{0}{1}Library{1}Application Support{1}PrusaSlicer",
|
|
Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), Path.DirectorySeparatorChar);
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Assembly Attribute Accessors
|
|
|
|
public static Version Version => Assembly.GetExecutingAssembly().GetName().Version;
|
|
public static string VersionStr => Version.ToString(3);
|
|
|
|
public static string AssemblyTitle
|
|
{
|
|
get
|
|
{
|
|
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
|
|
if (attributes.Length > 0)
|
|
{
|
|
AssemblyTitleAttribute titleAttribute = (AssemblyTitleAttribute)attributes[0];
|
|
if (titleAttribute.Title != "")
|
|
{
|
|
return titleAttribute.Title;
|
|
}
|
|
}
|
|
return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
|
|
}
|
|
}
|
|
|
|
public static string AssemblyVersion => Assembly.GetExecutingAssembly().GetName().Version.ToString();
|
|
|
|
public static string AssemblyDescription
|
|
{
|
|
get
|
|
{
|
|
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
|
|
if (attributes.Length == 0)
|
|
{
|
|
return "";
|
|
}
|
|
|
|
string description = ((AssemblyDescriptionAttribute)attributes[0]).Description + $"{Environment.NewLine}{Environment.NewLine}Available File Formats:";
|
|
|
|
return FileFormat.AvailableFormats.SelectMany(fileFormat => fileFormat.FileExtensions).Aggregate(description, (current, fileExtension) => current + $"{Environment.NewLine}- {fileExtension.Description} (.{fileExtension.Extension})");
|
|
}
|
|
}
|
|
|
|
public static string AssemblyProduct
|
|
{
|
|
get
|
|
{
|
|
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
|
|
if (attributes.Length == 0)
|
|
{
|
|
return "";
|
|
}
|
|
return ((AssemblyProductAttribute)attributes[0]).Product;
|
|
}
|
|
}
|
|
|
|
public static string AssemblyCopyright
|
|
{
|
|
get
|
|
{
|
|
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
|
|
if (attributes.Length == 0)
|
|
{
|
|
return "";
|
|
}
|
|
return ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
|
|
}
|
|
}
|
|
|
|
public static string AssemblyCompany
|
|
{
|
|
get
|
|
{
|
|
object[] attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
|
|
if (attributes.Length == 0)
|
|
{
|
|
return "";
|
|
}
|
|
return ((AssemblyCompanyAttribute)attributes[0]).Company;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
}
|