* (Add) About box: Primary screen identifier and open on screen identifier
* (Add) Calibrator - External tests
* (Change) Rewrite 'Action - Import Layer(s)' to support file formats and add the followig importation types:
  * **Insert:** Insert layers. (Requires images with bounds equal or less than file resolution)
  * **Replace:** Replace layers. (Requires images with bounds equal or less than file resolution)
  * **Stack:** Stack layers content. (Requires images with bounds equal or less than file resolution)
  * **Merge:** Merge/Sum layers content. (Requires images with same resolution)
  * **Subtract:** Subtract layers content. (Requires images with same resolution)
  * **BitwiseAnd:** Perform a 'bitwise and' operation over layer pixels. (Requires images with same resolution)
  * **BitwiseOr:** Perform a 'bitwise or' operation over layer pixels. (Requires images with same resolution)
  * **BitwiseXOr:** Perform a 'bitwise xor' operation over layer pixels. (Requires images with same resolution)
* (Change) Icon for Tool - Raft Relief
* (Change) Windows and dialogs max size are now calculated to where window is opened instead of use the primary or first screen all the time
This commit is contained in:
Tiago Conceição
2021-01-03 00:47:20 +00:00
parent 92588fd159
commit a7d15a24d0
25 changed files with 713 additions and 194 deletions
+16
View File
@@ -1,5 +1,21 @@
# Changelog
## 03/12/2020 - v2.1.1
* (Add) About box: Primary screen identifier and open on screen identifier
* (Add) Calibrator - External tests
* (Change) Rewrite 'Action - Import Layer(s)' to support file formats and add the followig importation types:
* **Insert:** Insert layers. (Requires images with bounds equal or less than file resolution)
* **Replace:** Replace layers. (Requires images with bounds equal or less than file resolution)
* **Stack:** Stack layers content. (Requires images with bounds equal or less than file resolution)
* **Merge:** Merge/Sum layers content. (Requires images with same resolution)
* **Subtract:** Subtract layers content. (Requires images with same resolution)
* **BitwiseAnd:** Perform a 'bitwise and' operation over layer pixels. (Requires images with same resolution)
* **BitwiseOr:** Perform a 'bitwise or' operation over layer pixels. (Requires images with same resolution)
* **BitwiseXOr:** Perform a 'bitwise xor' operation over layer pixels. (Requires images with same resolution)
* (Change) Icon for Tool - Raft Relief
* (Change) Windows and dialogs max size are now calculated to where window is opened instead of use the primary or first screen all the time
## 29/12/2020 - v2.1.0
* (Add) Tool - Redraw model/supports: Redraw the model or supports with a set brightness. This requires an extra sliced file from same object but without any supports and raft, straight to the build plate.
+6 -7
View File
@@ -193,15 +193,15 @@ sudo apt-get install -y libjpeg-dev libpng-dev libgeotiff-dev libdc1394-22 libav
**Arch/Manjaro/Similars**
```bash
sudo pacman -S openjpeg2 libjpeg-turbo libpng libgeotiff libdc1394 libdc1394 ffmpeg openexr tbb dotnet-runtime
sudo pacman -S openjpeg2 libjpeg-turbo libpng libgeotiff libdc1394 libdc1394 ffmpeg openexr tbb
```
To run UVtools open it folder on a terminal and call one of:
* Double-click UVtools file
* `./UVtools`
* `dotnet UVtools.dll` [For universal package only]
* `sh UVtools.sh` [For universal package only]
* `sh UVtools.sh`
* `dotnet UVtools.dll` [For universal package only, requires dotnet-runtime]
* As a pratical alternative you can create a shortcut on Desktop
### Mac
@@ -213,20 +213,19 @@ To run UVtools open it folder on a terminal and call one of:
<!---
* Donwload and install: https://dotnet.microsoft.com/download/dotnet/thank-you/sdk-5.0.101-macos-x64-installer
brew install libjpeg libpng libgeotiff libdc1394 ffmpeg openexr tbb
-->
```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
brew analytics off
brew cask install dotnet
```
-->
To run UVtools open it folder on a terminal and call one of:
* Double-click UVtools file
* `./UVtools`
* `dotnet UVtools.dll` [For universal package only]
* `sh UVtools.sh` [For universal package only]
* `sh UVtools.sh`
* `dotnet UVtools.dll` [For universal package only, requires dotnet-runtime]
* As a pratical alternative you can create a shortcut on Desktop
## How to use
+11
View File
@@ -255,5 +255,16 @@ namespace UVtools.Core.Extensions
return mat;
}
public static Mat RoiFromCenter(this Mat mat, Size size)
{
if (size == mat.Size) return mat;
return new Mat(mat, new Rectangle(
mat.Size.Width / 2 - size.Width / 2,
mat.Size.Height / 2 - size.Height / 2,
size.Width,
size.Height
));
}
}
}
+5 -5
View File
@@ -275,15 +275,15 @@ namespace UVtools.Core.FileFormats
#endregion
#region Properties
public Printer PrinterSettings { get; private set; }
public Printer PrinterSettings { get; private set; } = new();
public Material MaterialSettings { get; private set; }
public Material MaterialSettings { get; private set; } = new();
public Print PrintSettings { get; private set; }
public Print PrintSettings { get; private set; } = new();
public OutputConfig OutputConfigSettings { get; private set; }
public OutputConfig OutputConfigSettings { get; private set; } = new();
public Statistics Statistics { get; } = new Statistics();
public Statistics Statistics { get; } = new ();
public override FileFormatType FileType => FileFormatType.Archive;
+15 -12
View File
@@ -204,7 +204,7 @@ namespace UVtools.Core
{
get
{
Mat mat = new Mat();
Mat mat = new();
CvInvoke.Imdecode(CompressedBytes, ImreadModes.Grayscale, mat);
return mat;
}
@@ -246,26 +246,28 @@ namespace UVtools.Core
GetBoundingRectangle();
}*/
if (!(parentLayerManager is null))
{
_positionZ = SlicerFile.GetHeightFromLayer(index);
_exposureTime = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomExposureTime, SlicerFile.ExposureTime);
_liftHeight = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftHeight, SlicerFile.LiftHeight);
_liftSpeed = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftSpeed, SlicerFile.LiftSpeed);
_retractSpeed = SlicerFile.RetractSpeed;
_lightPwm = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLightPWM, SlicerFile.LightPWM);
}
if (parentLayerManager is null) return;
_positionZ = SlicerFile.GetHeightFromLayer(index);
_exposureTime = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomExposureTime, SlicerFile.ExposureTime);
_liftHeight = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftHeight, SlicerFile.LiftHeight);
_liftSpeed = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLiftSpeed, SlicerFile.LiftSpeed);
_retractSpeed = SlicerFile.RetractSpeed;
_lightPwm = SlicerFile.GetInitialLayerValueOrNormal(index, SlicerFile.BottomLightPWM, SlicerFile.LightPWM);
}
public Layer(uint index, byte[] compressedBytes, FileFormat slicerFile) : this(index, compressedBytes, slicerFile.LayerManager)
{}
public Layer(uint index, Mat layerMat, LayerManager parentLayerManager) : this(index, new byte[0], parentLayerManager)
{
LayerMat = layerMat;
IsModified = false;
}
public Layer(uint index, Mat layerMat, FileFormat slicerFile) : this(index, layerMat, slicerFile.LayerManager) { }
public Layer(uint index, Stream stream, LayerManager parentLayerManager) : this(index, stream.ToArray(), parentLayerManager)
{ }
public Layer(uint index, Stream stream, LayerManager parentLayerManager) : this(index, stream.ToArray(), parentLayerManager) { }
public Layer(uint index, Stream stream, FileFormat slicerFile) : this(index, stream.ToArray(), slicerFile.LayerManager) { }
#endregion
#region Equatables
@@ -366,6 +368,7 @@ namespace UVtools.Core
bool needDispose = false;
if (mat is null)
{
if (_compressedBytes is null || _compressedBytes.Length == 0) return Rectangle.Empty;
mat = LayerMat;
needDispose = true;
}
+68 -8
View File
@@ -203,17 +203,15 @@ namespace UVtools.Core
public Rectangle GetBoundingRectangle(OperationProgress progress = null)
{
progress ??= new OperationProgress(OperationProgress.StatusOptimizingBounds, Count-1);
if (!_boundingRectangle.IsEmpty || Count == 0 || this[0] is null) return _boundingRectangle;
_boundingRectangle = this[0].BoundingRectangle;
if (_boundingRectangle.IsEmpty) // Safe checking
{
progress?.Reset(OperationProgress.StatusOptimizingBounds, Count);
progress.Reset(OperationProgress.StatusOptimizingBounds, Count-1);
Parallel.For(0, Count, layerIndex =>
{
if (!ReferenceEquals(progress, null) && progress.Token.IsCancellationRequested)
{
return;
}
if (progress.Token.IsCancellationRequested) return;
this[layerIndex].GetBoundingRectangle();
@@ -233,12 +231,11 @@ namespace UVtools.Core
}
progress?.Reset(OperationProgress.StatusCalculatingBounds, Count);
progress.Reset(OperationProgress.StatusCalculatingBounds, Count-1);
for (int i = 1; i < Count; i++)
{
if(this[i].BoundingRectangle.IsEmpty) continue;
_boundingRectangle = Rectangle.Union(_boundingRectangle, this[i].BoundingRectangle);
if (ReferenceEquals(progress, null)) continue;
progress++;
}
@@ -1149,7 +1146,7 @@ namespace UVtools.Core
/// Reallocate with new size
/// </summary>
/// <returns></returns>
public LayerManager Reallocate(uint newLayerCount, bool makeClone = false)
public LayerManager ReallocateNew(uint newLayerCount, bool makeClone = false)
{
LayerManager layerManager = new LayerManager(newLayerCount, SlicerFile);
foreach (var layer in this)
@@ -1163,6 +1160,69 @@ namespace UVtools.Core
return layerManager;
}
/// <summary>
/// Reallocate with add size
/// </summary>
/// <returns></returns>
public void Reallocate(uint insertAtLayerIndex, uint layerCount, bool initBlack = false)
{
var layers = Layers;
Layers = new Layer[Count + layerCount];
// Rearrange
for (uint layerIndex = 0; layerIndex < insertAtLayerIndex; layerIndex++)
{
Layers[layerIndex] = layers[layerIndex];
}
// Rearrange
for (uint layerIndex = insertAtLayerIndex; layerIndex < layers.Length; layerIndex++)
{
Layers[layerCount + layerIndex] = layers[layerIndex];
Layers[layerCount + layerIndex].Index = layerCount + layerIndex;
}
// Allocate new layers
if (initBlack)
{
Parallel.For(insertAtLayerIndex, insertAtLayerIndex + layerCount, layerIndex =>
{
Layers[layerIndex] = new Layer((uint) layerIndex, EmguExtensions.InitMat(SlicerFile.Resolution), this);
});
}
/*for (uint layerIndex = insertAtLayerIndex; layerIndex < insertAtLayerIndex + layerCount; layerIndex++)
{
Layers[layerIndex] = initBlack ? new Layer(layerIndex, EmguExtensions.InitMat(SlicerFile.Resolution), this) : null;
}*/
}
public void ReallocateRange(uint startLayerIndex, uint endLayerIndex)
{
var layers = Layers;
if ((int)(endLayerIndex - startLayerIndex) < 0) return;
Layers = new Layer[1 + endLayerIndex - startLayerIndex];
uint currentLayerIndex = 0;
for (uint layerIndex = startLayerIndex; layerIndex <= endLayerIndex; layerIndex++)
{
Layers[currentLayerIndex++] = layers[layerIndex];
}
BoundingRectangle = Rectangle.Empty;
}
/// <summary>
/// Reallocate at start
/// </summary>
/// <returns></returns>
public void ReallocateStart(uint layerCount, bool initBlack = false) => Reallocate(0, layerCount, initBlack);
/// <summary>
/// Reallocate at end
/// </summary>
/// <returns></returns>
public void ReallocateEnd(uint layerCount, bool initBlack = false) => Reallocate(Count, layerCount, initBlack);
/// <summary>
/// Clone this object
/// </summary>
+1 -1
View File
@@ -122,7 +122,7 @@ namespace UVtools.Core.Managers
var clip = this[i];
if (layerManager.Count != clip.LayerCount) // Need resize layer manager
{
layerManager = layerManager.Reallocate(clip.LayerCount);
layerManager = layerManager.ReallocateNew(clip.LayerCount);
ReallocatedLayerCount = true;
}
@@ -0,0 +1,47 @@
/*
* 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.
*/
namespace UVtools.Core.Operations
{
public class OperationCalibrateExternalTests : Operation
{
#region Members
#endregion
#region Overrides
public override Enumerations.LayerRangeSelection StartLayerRangeSelection => Enumerations.LayerRangeSelection.None;
public override bool CanROI => false;
public override bool CanHaveProfiles => false;
public override string ButtonOkText => null;
public override string Title => "External tests";
public override string Description =>
"A set of useful external tests to run within your slicer.\nClick on a button to open website and instructions.";
public override string ConfirmationText => null;
public override string ProgressTitle => null;
public override string ProgressAction => null;
#endregion
#region Properties
#endregion
#region Equality
#endregion
#region Methods
#endregion
}
}
+324 -77
View File
@@ -6,15 +6,17 @@
* of this license document, but changing it is not allowed.
*/
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;
using Emgu.CV;
using Emgu.CV.CvEnum;
using UVtools.Core.Extensions;
using UVtools.Core.FileFormats;
using UVtools.Core.Objects;
@@ -23,12 +25,26 @@ namespace UVtools.Core.Operations
[Serializable]
public sealed class OperationLayerImport : Operation
{
private uint _insertAfterLayerIndex;
private bool _replaceStartLayer;
private bool _replaceSubsequentLayers;
private bool _discardRemainingLayers;
private bool _mergeImages;
private ObservableCollection<StringTag> _files = new ObservableCollection<StringTag>();
#region Enums
public enum ImportTypes : byte
{
Insert,
Replace,
Stack,
Merge,
Subtract,
BitwiseAnd,
BitwiseOr,
BitwiseXOr,
}
#endregion
private ImportTypes _importType = ImportTypes.Stack;
private uint _startLayerIndex;
private bool _extendBeyondLayerCount = true;
private bool _discardUnmodifiedLayers;
private ushort _stackMargin = 50;
private ObservableCollection<StringTag> _files = new();
#region Overrides
@@ -37,26 +53,25 @@ namespace UVtools.Core.Operations
public override string Title => "Import Layers";
public override string Description =>
"Import layers from local files into the model at a selected layer height.\n\n" +
"Import layers from local files into the model at a selected layer height.\n" +
"NOTE: Imported images must be greyscale and have the same resolution as the model.";
public override string ConfirmationText => $"import {Count} layer{(Count!=1?"s":"")}?";
public override string ConfirmationText => $"{_importType} import {Count} file{(Count>=1?"s":"")}?";
public override string ProgressTitle =>
$"Importing {Count} layer{(Count!=1 ? "s" : "")}";
$"{_importType} importing {Count} file{(Count>=1 ? "s" : "")}";
public override string ProgressAction => "Imported layers";
public override bool CanCancel => true;
public override uint LayerIndexStart => InsertAfterLayerIndex + (ReplaceStartLayer ? 0u : 1);
public override uint LayerIndexEnd => (uint)(LayerIndexStart + Count - 1);
public override uint LayerIndexEnd => _startLayerIndex + Count - 1;
public override bool CanHaveProfiles => false;
public override StringTag Validate(params object[] parameters)
{
var result = new ConcurrentBag<StringTag>();
/*var result = new ConcurrentBag<StringTag>();
Parallel.ForEach(Files, file =>
{
using (Mat mat = CvInvoke.Imread(file.TagString, ImreadModes.AnyColor))
@@ -83,52 +98,76 @@ namespace UVtools.Core.Operations
}
message.AppendLine(file.Content);
}
return new StringTag(message.ToString(), result);
return new StringTag(message.ToString(), result);*/
StringBuilder sb = new();
if (Files.Count == 0)
{
sb.AppendLine("No files to import.");
}
return new StringTag(sb.ToString());
}
#endregion
#region Properties
[XmlIgnore]
public Size FileResolution { get; }
public uint InsertAfterLayerIndex
public ImportTypes ImportType
{
get => _insertAfterLayerIndex;
set => RaiseAndSetIfChanged(ref _insertAfterLayerIndex, value);
get => _importType;
set
{
if(!RaiseAndSetIfChanged(ref _importType, value)) return;
RaisePropertyChanged(nameof(IsImportStackType));
RaisePropertyChanged(nameof(IsExtendBeyondLayerCountVisible));
}
}
public bool ReplaceStartLayer
public static Array ImportTypesItems => Enum.GetValues(typeof(ImportTypes));
public bool IsImportStackType => _importType == ImportTypes.Stack;
public uint StartLayerIndex
{
get => _replaceStartLayer;
set => RaiseAndSetIfChanged(ref _replaceStartLayer, value);
get => _startLayerIndex;
set => RaiseAndSetIfChanged(ref _startLayerIndex, value);
}
public bool ReplaceSubsequentLayers
public bool ExtendBeyondLayerCount
{
get => _replaceSubsequentLayers;
set => RaiseAndSetIfChanged(ref _replaceSubsequentLayers, value);
get => _extendBeyondLayerCount;
set => RaiseAndSetIfChanged(ref _extendBeyondLayerCount, value);
}
public bool DiscardRemainingLayers
public bool IsExtendBeyondLayerCountVisible => _importType == ImportTypes.Replace || _importType == ImportTypes.Stack || _importType == ImportTypes.Merge;
public bool DiscardUnmodifiedLayers
{
get => _discardRemainingLayers;
set => RaiseAndSetIfChanged(ref _discardRemainingLayers, value);
get => _discardUnmodifiedLayers;
set => RaiseAndSetIfChanged(ref _discardUnmodifiedLayers, value);
}
public bool MergeImages
public ushort StackMargin
{
get => _mergeImages;
set => RaiseAndSetIfChanged(ref _mergeImages, value);
get => _stackMargin;
set => RaiseAndSetIfChanged(ref _stackMargin, value);
}
[XmlIgnore]
public ObservableCollection<StringTag> Files
{
get => _files;
set => RaiseAndSetIfChanged(ref _files, value);
}
public int Count => Files.Count;
public uint Count => (uint) Files.Count;
#endregion
#region Constructor
@@ -163,7 +202,7 @@ namespace UVtools.Core.Operations
}
public uint CalculateTotalLayers(uint totalLayers)
/*public uint CalculateTotalLayers(uint totalLayers)
{
if (DiscardRemainingLayers)
{
@@ -176,7 +215,7 @@ namespace UVtools.Core.Operations
}
return (uint)(totalLayers + Files.Count - (ReplaceStartLayer ? 1 : 0));
}
}*/
public override string ToString()
{
@@ -188,56 +227,36 @@ namespace UVtools.Core.Operations
public override bool Execute(FileFormat slicerFile, OperationProgress progress = null)
{
progress ??= new OperationProgress();
progress.Reset(ProgressAction, (uint)Count);
slicerFile.SuppressRebuildProperties = true;
List<FileFormat> fileFormats = new();
List<KeyValuePair<uint, string>> keyImage = new();
int lastProcessedLayerIndex = -1;
var oldLayers = slicerFile.LayerManager.Layers;
uint newLayerCount = CalculateTotalLayers((uint)oldLayers.Length);
uint startIndex = LayerIndexStart;
var layers = new Layer[newLayerCount];
// Keep same layers up to InsertAfterLayerIndex
for (uint i = 0; i <= InsertAfterLayerIndex; i++)
// Order raw images
for (int i = 0; i < Count; i++)
{
layers[i] = oldLayers[i];
if (!Files[i].TagString.EndsWith(".png", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) &&
!Files[i].TagString.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) continue;
keyImage.Add(new KeyValuePair<uint, string>((uint) keyImage.Count, Files[i].TagString));
}
// Keep all old layers if not discarding them
if (ReplaceSubsequentLayers)
// Create virtual file format with images
if (keyImage.Count > 0)
{
if (!DiscardRemainingLayers)
{
for (uint i = InsertAfterLayerIndex + 1; i < oldLayers.Length; i++)
{
layers[i] = oldLayers[i];
}
}
}
else // Push remaining layers to the end of imported layers
{
uint oldLayerIndex = InsertAfterLayerIndex;
for (uint i = LayerIndexEnd + 1; i < newLayerCount; i++)
{
oldLayerIndex++;
layers[i] = oldLayers[oldLayerIndex];
}
}
progress.Reset("Packing images", (uint) keyImage.Count);
SL1File format = new SL1File();
format.LayerManager = new LayerManager((uint) keyImage.Count, format);
Parallel.For(0, Count,
//new ParallelOptions{MaxDegreeOfParallelism = 1},
i =>
Parallel.ForEach(keyImage, pair =>
{
var mat = CvInvoke.Imread(Files[i].TagString, ImreadModes.Grayscale);
uint layerIndex = (uint)(startIndex + i);
if (MergeImages)
{
if (layers[layerIndex] is not null)
{
using var oldMat = layers[layerIndex].LayerMat;
CvInvoke.Add(oldMat, mat, mat);
}
}
layers[layerIndex] = new Layer(layerIndex, mat, slicerFile.LayerManager);
if (progress.Token.IsCancellationRequested) return;
using var mat = CvInvoke.Imread(pair.Value, ImreadModes.Grayscale);
if (pair.Key == 0) format.Resolution = mat.Size;
format[pair.Key] = new Layer(pair.Key, mat, format);
lock (progress.Mutex)
{
@@ -245,11 +264,239 @@ namespace UVtools.Core.Operations
}
});
slicerFile.LayerManager.Layers = layers;
slicerFile.RequireFullEncode = true;
progress.Token.ThrowIfCancellationRequested();
fileFormats.Add(format);
}
// Order remaining possible file formats
for (int i = 0; i < Count; i++)
{
if (Files[i].TagString.EndsWith(".png", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) ||
Files[i].TagString.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) continue;
var fileFormat = FileFormat.FindByExtension(Files[i].TagString, true, true);
if(fileFormat is null) continue;
fileFormat.FileFullPath = Files[i].TagString;
fileFormats.Add(fileFormat);
}
progress.Token.ThrowIfCancellationRequested();
if (fileFormats.Count == 0) return false;
if (_importType == ImportTypes.Stack)
{
new OperationMove(slicerFile, Enumerations.Anchor.TopLeft){LayerIndexEnd = slicerFile.LastLayerIndex}.Execute(slicerFile, progress);
}
foreach (var fileFormat in fileFormats)
{
if (!string.IsNullOrEmpty(fileFormat.FileFullPath))
{
fileFormat.Decode(fileFormat.FileFullPath, progress);
}
var boundingRectangle = slicerFile.LayerManager.GetBoundingRectangle(progress);
var fileFormatBoundingRectangle = fileFormat.LayerManager.GetBoundingRectangle(progress);
var roiRectangle = Rectangle.Empty;
// Check if is possible to process this file
switch (_importType)
{
case ImportTypes.Insert:
if (slicerFile.Resolution != fileFormat.Resolution &&
(slicerFile.Resolution.Width < fileFormat.LayerManager.BoundingRectangle.Width ||
slicerFile.Resolution.Height < fileFormat.LayerManager.BoundingRectangle.Height)) continue;
slicerFile.LayerManager.Reallocate(_startLayerIndex, fileFormat.LayerCount);
break;
case ImportTypes.Replace:
case ImportTypes.Stack:
if (slicerFile.Resolution != fileFormat.Resolution &&
(slicerFile.Resolution.Width < fileFormat.LayerManager.BoundingRectangle.Width ||
slicerFile.Resolution.Height < fileFormat.LayerManager.BoundingRectangle.Height)) continue;
if(fileFormatBoundingRectangle.Width >= slicerFile.ResolutionX || fileFormatBoundingRectangle.Height >= slicerFile.ResolutionY)
continue;
int x = 0;
int y = 0;
if (boundingRectangle.Right + _stackMargin + fileFormatBoundingRectangle.Width <
slicerFile.ResolutionX)
{
x = boundingRectangle.Right + _stackMargin;
}
else
{
y = boundingRectangle.Bottom + _stackMargin;
}
if (y >= slicerFile.ResolutionY)
continue;
roiRectangle = new Rectangle(x, y, fileFormatBoundingRectangle.Width, fileFormatBoundingRectangle.Height);
if (_extendBeyondLayerCount)
{
int layerCountDifference = (int) (_startLayerIndex + fileFormat.LayerCount - slicerFile.LayerCount);
if (layerCountDifference > 0)
{
slicerFile.LayerManager.ReallocateEnd((uint) layerCountDifference, _importType == ImportTypes.Stack);
}
}
break;
case ImportTypes.Merge:
if (slicerFile.Resolution != fileFormat.Resolution) continue;
if (_extendBeyondLayerCount)
{
int layerCountDifference = (int)(_startLayerIndex + fileFormat.LayerCount - slicerFile.LayerCount);
if (layerCountDifference > 0)
{
slicerFile.LayerManager.ReallocateEnd((uint)layerCountDifference, true);
}
}
break;
case ImportTypes.Subtract:
case ImportTypes.BitwiseAnd:
case ImportTypes.BitwiseOr:
case ImportTypes.BitwiseXOr:
if (slicerFile.Resolution != fileFormat.Resolution) continue;
break;
}
progress.Reset(ProgressAction, fileFormat.LayerCount);
Parallel.For(0, fileFormat.LayerCount,
//new ParallelOptions{MaxDegreeOfParallelism = 1},
i =>
{
if (progress.Token.IsCancellationRequested) return;
uint layerIndex = (uint)(_startLayerIndex + i);
switch (_importType)
{
case ImportTypes.Insert:
{
if (layerIndex >= slicerFile.LayerCount) return;
if (slicerFile.Resolution == fileFormat.Resolution)
{
slicerFile[layerIndex] = fileFormat[i];
break;
}
using var layer = fileFormat[i].LayerMat;
using var layerRoi = layer.RoiFromCenter(slicerFile.Resolution);
slicerFile[layerIndex] = new Layer(layerIndex, layerRoi, slicerFile);
break;
}
case ImportTypes.Replace:
{
if (layerIndex >= slicerFile.LayerCount) return;
if (slicerFile.Resolution == fileFormat.Resolution)
{
slicerFile[layerIndex] = fileFormat[i];
break;
}
using var layer = fileFormat[i].LayerMat;
using var layerRoi = layer.RoiFromCenter(slicerFile.Resolution);
slicerFile[layerIndex] = new Layer(layerIndex, layerRoi, slicerFile);
break;
}
case ImportTypes.Stack:
{
if (layerIndex >= slicerFile.LayerCount) return;
using var mat = slicerFile[layerIndex].LayerMat;
using var importMat = fileFormat[i].LayerMat;
var matRoi = new Mat(mat, roiRectangle);
var importMatRoi = new Mat(importMat, fileFormatBoundingRectangle);
importMatRoi.CopyTo(matRoi);
slicerFile[layerIndex].LayerMat = mat;
break;
}
case ImportTypes.Merge:
{
if (layerIndex >= slicerFile.LayerCount) return;
using var originalMat = slicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.Add(originalMat, newMat, newMat);
slicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.Subtract:
{
if (layerIndex >= slicerFile.LayerCount) return;
using var originalMat = slicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.Subtract(originalMat, newMat, newMat);
slicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseAnd:
{
if (layerIndex >= slicerFile.LayerCount) return;
using var originalMat = slicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseAnd(originalMat, newMat, newMat);
slicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseOr:
{
if (layerIndex >= slicerFile.LayerCount) return;
using var originalMat = slicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseOr(originalMat, newMat, newMat);
slicerFile[layerIndex].LayerMat = newMat;
break;
}
case ImportTypes.BitwiseXOr:
{
if (layerIndex >= slicerFile.LayerCount) return;
using var originalMat = slicerFile[layerIndex].LayerMat;
using var newMat = fileFormat[i].LayerMat;
CvInvoke.BitwiseXor(originalMat, newMat, newMat);
slicerFile[layerIndex].LayerMat = newMat;
break;
}
default:
throw new ArgumentOutOfRangeException();
}
lock (progress.Mutex)
{
lastProcessedLayerIndex = Math.Max(lastProcessedLayerIndex, (int)layerIndex);
progress++;
}
});
fileFormat.Dispose();
progress.Token.ThrowIfCancellationRequested();
}
if (_importType == ImportTypes.Stack)
{
new OperationMove(slicerFile) { LayerIndexEnd = slicerFile.LastLayerIndex }.Execute(slicerFile, progress);
}
if (lastProcessedLayerIndex <= -1) return false;
if (lastProcessedLayerIndex + 1 < slicerFile.LayerCount && _discardUnmodifiedLayers)
{
slicerFile.LayerManager.ReallocateRange(0, (uint) lastProcessedLayerIndex);
}
slicerFile.LayerManager.RebuildLayersProperties();
slicerFile.SuppressRebuildProperties = false;
slicerFile.RequireFullEncode = true;
return true;
}
+8
View File
@@ -227,6 +227,14 @@ namespace UVtools.Core.Operations
{
}
public OperationMove(FileFormat slicerFile, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter)
{
ROI = slicerFile.LayerManager.BoundingRectangle;
ImageWidth = slicerFile.ResolutionX;
ImageHeight = slicerFile.ResolutionY;
Anchor = anchor;
}
public OperationMove(Rectangle srcRoi, uint imageWidth, uint imageHeight, Enumerations.Anchor anchor = Enumerations.Anchor.MiddleCenter)
{
ROI = srcRoi;
+1 -1
View File
@@ -10,7 +10,7 @@
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<PackageProjectUrl>https://github.com/sn4k3/UVtools</PackageProjectUrl>
<Description>MSLA/DLP, file analysis, repair, conversion and manipulation</Description>
<Version>2.1.0</Version>
<Version>2.1.1</Version>
<Copyright>Copyright © 2020 PTRTECH</Copyright>
<PackageIcon>UVtools.png</PackageIcon>
<Platforms>AnyCPU;x64</Platforms>
+3 -7
View File
@@ -13,9 +13,7 @@ using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
@@ -38,8 +36,6 @@ namespace UVtools.WPF
public static AppVersionChecker VersionChecker { get; } = new AppVersionChecker();
public static Size MaxWindowSize = Size.Empty;
public override void Initialize()
{
AvaloniaXamlLoader.Load(this);
@@ -124,15 +120,15 @@ namespace UVtools.WPF
{
try
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
if (OperatingSystem.IsWindows())
{
Process.Start(new ProcessStartInfo(url) { UseShellExecute = true }).Dispose();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
else if (OperatingSystem.IsLinux())
{
Process.Start("xdg-open", url).Dispose();
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
else if (OperatingSystem.IsMacOS())
{
Process.Start("open", url).Dispose();
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 114 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 183 B

@@ -0,0 +1,35 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="UVtools.WPF.Controls.Calibrators.CalibrateExternalTestsControl">
<Grid
RowDefinitions="Auto,Auto,Auto"
ColumnDefinitions="400">
<Button Grid.Row="0"
Padding="5"
Content="Photonsters Validation Matrix / Exposure finder"
Command="{Binding ButtonClicked}"
VerticalAlignment="Center"
CommandParameter="https://www.thingiverse.com/thing:4707289"/>
<Button Grid.Row="1"
Margin="0,5,0,0"
Padding="5"
Content="Support pull test"
Command="{Binding ButtonClicked}"
VerticalAlignment="Center"
CommandParameter="https://www.thingiverse.com/thing:4308175"/>
<Button Grid.Row="2"
Margin="0,5,0,0"
Padding="5"
Content="AmeraLabs town calibration part"
Command="{Binding ButtonClicked}"
VerticalAlignment="Center"
CommandParameter="https://www.thingiverse.com/thing:2810666"/>
</Grid>
</UserControl>
@@ -0,0 +1,30 @@
using System.Diagnostics;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using UVtools.Core.Operations;
using UVtools.WPF.Controls.Tools;
namespace UVtools.WPF.Controls.Calibrators
{
public class CalibrateExternalTestsControl : ToolControl
{
public OperationCalibrateExternalTests Operation => BaseOperation as OperationCalibrateExternalTests;
public CalibrateExternalTestsControl()
{
this.InitializeComponent();
BaseOperation = new OperationCalibrateExternalTests();
Debug.WriteLine("asdasdasdasd");
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public void ButtonClicked(string url)
{
App.OpenBrowser(url);
}
}
}
+1 -1
View File
@@ -13,7 +13,7 @@ namespace UVtools.WPF.Controls
{
public static class Helpers
{
public static readonly List<FileDialogFilter> ImagesFileFilter = new List<FileDialogFilter>
public static readonly List<FileDialogFilter> ImagesFileFilter = new()
{
new FileDialogFilter
{
@@ -6,42 +6,75 @@
x:Class="UVtools.WPF.Controls.Tools.ToolLayerImportControl">
<StackPanel Spacing="10">
<StackPanel Spacing="10" Orientation="Horizontal">
<TextBlock
VerticalAlignment="Center"
Text="Insert after layer:"/>
<NumericUpDown
Width="70"
Minimum="0"
Maximum="{Binding MaximumLayer}"
Value="{Binding Operation.InsertAfterLayerIndex}"
/>
<TextBlock
VerticalAlignment="Center"
Text="{Binding InfoLayerHeightStr}"/>
</StackPanel>
<Grid RowDefinitions="Auto,10,Auto,10,Auto,10,Auto"
ColumnDefinitions="Auto,10,100,5,Auto,20,Auto">
<StackPanel Spacing="10" Orientation="Horizontal">
<CheckBox
IsChecked="{Binding Operation.ReplaceStartLayer}"
Content="Replace this layer"/>
<TextBlock Grid.Row="0" Grid.Column="0"
VerticalAlignment="Center"
ToolTip.Tip="Insert: Insert layers. (Requires images with bounds equal or less than file resolution)
&#x0a;Replace: Replace layers. (Requires images with bounds equal or less than file resolution)
&#x0a;Stack: Stack layers content. (Requires images with bounds equal or less than file resolution)
&#x0a;Merge: Merge/Sum layers content. (Requires images with same resolution)
&#x0a;Subtract: Subtract layers content. (Requires images with same resolution)
&#x0a;BitwiseAnd: Perform a 'bitwise and' operation over layer pixels. (Requires images with same resolution)
&#x0a;BitwiseOr: Perform a 'bitwise or' operation over layer pixels. (Requires images with same resolution)
&#x0a;BitwiseXOr: Perform a 'bitwise xor' operation over layer pixels. (Requires images with same resolution)"
Text="Import type:"/>
<CheckBox
IsChecked="{Binding Operation.ReplaceSubsequentLayers}"
Content="Replace subsequent layers"/>
<ComboBox Grid.Row="0" Grid.Column="2"
VerticalAlignment="Center"
SelectedItem="{Binding Operation.ImportType}"
Items="{Binding Operation.ImportTypesItems}"/>
<TextBlock Grid.Row="0" Grid.Column="4"
VerticalAlignment="Center"
Text="layers"/>
<CheckBox Grid.Row="0" Grid.Column="6"
IsChecked="{Binding Operation.ExtendBeyondLayerCount}"
IsVisible="{Binding Operation.IsExtendBeyondLayerCountVisible}"
ToolTip.Tip="If enabled, imported images that go beyond last layer are appended. The file will grow in layer count if necessary to fit all imported layers.
&#x0a;If disabled, all imported images that go beyond last layer are discarded. The file will maintain same layer count."
Content="Extend beyond layer count"/>
<TextBlock Grid.Row="2" Grid.Column="0"
VerticalAlignment="Center"
Text="Start at layer:"/>
<NumericUpDown Grid.Row="2" Grid.Column="2"
ClipValueToMinMax="True"
Minimum="0"
Maximum="{Binding MaximumLayer}"
Value="{Binding Operation.StartLayerIndex}"/>
<TextBlock Grid.Row="2" Grid.Column="4"
VerticalAlignment="Center"
Text="{Binding InfoLayerHeightStr}"/>
<CheckBox Grid.Row="4" Grid.Column="2" Grid.ColumnSpan="5"
IsChecked="{Binding Operation.DiscardUnmodifiedLayers}"
ToolTip.Tip="If enabled, all unmodified layers forward the last inserted layer are discarded.
&#x0a;If disabled, the unmodified layers are kept."
Content="Discard unmodified layers"/>
<TextBlock Grid.Row="6" Grid.Column="0"
VerticalAlignment="Center"
IsVisible="{Binding Operation.IsImportStackType}"
Text="Stack margin:"/>
<NumericUpDown Grid.Row="6" Grid.Column="2"
ClipValueToMinMax="True"
IsVisible="{Binding Operation.IsImportStackType}"
Minimum="0"
Maximum="65535"
Value="{Binding Operation.StackMargin}"/>
<TextBlock Grid.Row="6" Grid.Column="4"
VerticalAlignment="Center"
IsVisible="{Binding Operation.IsImportStackType}"
Text="px"/>
</Grid>
<CheckBox
IsChecked="{Binding Operation.DiscardRemainingLayers}"
Content="Discard remaining layers"/>
<CheckBox
IsChecked="{Binding Operation.MergeImages}"
Content="Merge images"/>
</StackPanel>
<CheckBox
IsChecked="{Binding IsAutoSortLayersByFileNameChecked}"
Content="Auto sort layers by file name"/>
Content="Auto sort files by filename"/>
<TextBlock Text="{Binding InfoImportResult}" />
@@ -90,7 +123,7 @@
<TextBlock
VerticalAlignment="Center"
Text="{Binding Operation.Files.Count, StringFormat=Layers: \{0\}}"/>
Text="{Binding Operation.Files.Count, StringFormat=Files: \{0\}}"/>
</StackPanel>
</Grid>
</Border>
@@ -1,4 +1,6 @@
using System.Collections.Concurrent;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
@@ -7,6 +9,7 @@ using Avalonia.Markup.Xaml;
using Avalonia.Media.Imaging;
using DynamicData;
using MessageBox.Avalonia.Enums;
using UVtools.Core.FileFormats;
using UVtools.Core.Objects;
using UVtools.Core.Operations;
using UVtools.WPF.Extensions;
@@ -26,7 +29,7 @@ namespace UVtools.WPF.Controls.Tools
public uint MaximumLayer => App.SlicerFile.LastLayerIndex;
public string InfoLayerHeightStr => $"({App.SlicerFile.GetHeightFromLayer(Operation.InsertAfterLayerIndex)}mm)";
public string InfoLayerHeightStr => $"({App.SlicerFile.GetHeightFromLayer(Operation.StartLayerIndex)}mm)";
public bool IsAutoSortLayersByFileNameChecked
{
@@ -39,7 +42,7 @@ namespace UVtools.WPF.Controls.Tools
get
{
if (Operation.Files.Count <= 0) return null;
uint modelTotalLayers = Operation.CalculateTotalLayers(App.SlicerFile.LayerCount);
/*uint modelTotalLayers = (uint) Operation.Files.Count;//Operation.CalculateTotalLayers(App.SlicerFile.LayerCount);
string textFactor = "grow";
if (modelTotalLayers < App.SlicerFile.LayerCount)
{
@@ -48,10 +51,11 @@ namespace UVtools.WPF.Controls.Tools
else if (modelTotalLayers == App.SlicerFile.LayerCount)
{
textFactor = "keep";
}
return
$"{Operation.Files.Count} layers will be imported into model starting from layer {Operation.InsertAfterLayerIndex} {InfoLayerHeightStr}.\n" +
$"Model will {textFactor} from layers {App.SlicerFile.LayerCount} ({App.SlicerFile.TotalHeight}mm) to {modelTotalLayers} ({App.SlicerFile.GetHeightFromLayer(modelTotalLayers, false)}mm)";
}*/
return
$"{Operation.Files.Count} files will be imported into model starting from layer {Operation.StartLayerIndex} {InfoLayerHeightStr}.";
//$"Model will {textFactor} from layers {App.SlicerFile.LayerCount} ({App.SlicerFile.TotalHeight}mm) to {modelTotalLayers} ({App.SlicerFile.GetHeightFromLayer(modelTotalLayers, false)}mm)";
}
}
@@ -67,6 +71,11 @@ namespace UVtools.WPF.Controls.Tools
PreviewImage = null;
return;
}
if (!_selectedFile.TagString.EndsWith(".png", StringComparison.OrdinalIgnoreCase) &&
!_selectedFile.TagString.EndsWith(".bmp", StringComparison.OrdinalIgnoreCase) &&
!_selectedFile.TagString.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase) &&
!_selectedFile.TagString.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase) &&
!_selectedFile.TagString.EndsWith(".gif", StringComparison.OrdinalIgnoreCase)) return;
PreviewImage = new Bitmap(_selectedFile.TagString);
}
}
@@ -118,7 +127,7 @@ namespace UVtools.WPF.Controls.Tools
AvaloniaXamlLoader.Load(this);
}
public override async Task<bool> ValidateForm()
/*public override async Task<bool> ValidateForm()
{
UpdateOperation();
var message = Operation.Validate();
@@ -136,14 +145,14 @@ namespace UVtools.WPF.Controls.Tools
}
return false;
}
}*/
public override void Callback(ToolWindow.Callbacks callback)
{
switch (callback)
{
case ToolWindow.Callbacks.Init:
ParentWindow.ButtonOkEnabled = false;
RefreshGUI();
break;
}
}
@@ -157,10 +166,19 @@ namespace UVtools.WPF.Controls.Tools
public async void AddFiles()
{
var filters = Helpers.ToAvaloniaFileFilter(FileFormat.AllFileFiltersAvalonia);
var orderedFilters = new List<FileDialogFilter> { filters[UserSettings.Instance.General.DefaultOpenFileExtensionIndex] };
for (int i = 0; i < filters.Count; i++)
{
if (i == UserSettings.Instance.General.DefaultOpenFileExtensionIndex) continue;
orderedFilters.Add(filters[i]);
}
var dialog = new OpenFileDialog
{
AllowMultiple = true,
Filters = Helpers.ImagesFileFilter
Filters = orderedFilters,
Directory = UserSettings.Instance.General.DefaultDirectoryOpenFile
};
var files = await dialog.ShowAsync(ParentWindow);
+15 -1
View File
@@ -8,8 +8,10 @@
using System.Threading;
using System.Threading.Tasks;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Threading;
using Avalonia.VisualTree;
using MessageBox.Avalonia.DTO;
using MessageBox.Avalonia.Enums;
@@ -31,7 +33,7 @@ namespace UVtools.WPF.Extensions
WindowIcon = new WindowIcon(App.GetAsset("/Assets/Icons/UVtools.ico")),
WindowStartupLocation = location,
CanResize = false,
MaxWidth = App.MaxWindowSize.Width - UserSettings.Instance.General.WindowsHorizontalMargin,
MaxWidth = window.GetScreenWorkingArea().Width - UserSettings.Instance.General.WindowsHorizontalMargin,
ShowInCenter = true
});
@@ -76,6 +78,18 @@ namespace UVtools.WPF.Extensions
window.DataContext = new object();
window.DataContext = old;
}
public static System.Drawing.Size GetScreenWorkingArea(this Window window)
{
var screen = window.Screens.ScreenFromVisual(window) ??
window.Screens.ScreenFromVisual(App.MainWindow) ??
window.Screens.Primary ??
window.Screens.All[0];
return new System.Drawing.Size(
UserSettings.Instance.General.WindowsTakeIntoAccountScreenScaling ? (int)(screen.WorkingArea.Width / screen.PixelDensity) : screen.WorkingArea.Width,
UserSettings.Instance.General.WindowsTakeIntoAccountScreenScaling ? (int)(screen.WorkingArea.Height / screen.PixelDensity) : screen.WorkingArea.Height);
}
}
}
+20 -25
View File
@@ -127,7 +127,7 @@ namespace UVtools.WPF
Tag = new OperationRaftRelief(),
Icon = new Avalonia.Controls.Image
{
Source = new Bitmap(App.GetAsset("/Assets/Icons/dot-circle-16x16.png"))
Source = new Bitmap(App.GetAsset("/Assets/Icons/cookie-16x16.png"))
}
},
new MenuItem
@@ -254,6 +254,14 @@ namespace UVtools.WPF
Source = new Bitmap(App.GetAsset("/Assets/Icons/chart-pie-16x16.png"))
}
},
new()
{
Tag = new OperationCalibrateExternalTests(),
Icon = new Avalonia.Controls.Image
{
Source = new Bitmap(App.GetAsset("/Assets/Icons/bookmark-16x16.png"))
}
},
};
public static MenuItem[] LayerActionsMenu { get; } =
@@ -448,14 +456,6 @@ namespace UVtools.WPF
//PropertyChanged += OnPropertyChanged;
UpdateTitle();
UpdateMaxWindowsSize();
if (Settings.General.StartMaximized
|| ClientSize.Width > App.MaxWindowSize.Width
|| ClientSize.Height > App.MaxWindowSize.Height)
{
WindowState = WindowState.Maximized;
}
var clientSizeObs = this.GetObservable(ClientSizeProperty);
clientSizeObs.Subscribe(size => UpdateLayerTrackerHighlightIssues());
@@ -471,24 +471,20 @@ namespace UVtools.WPF
});
}
public void UpdateMaxWindowsSize()
{
/*Console.WriteLine($"Settings is null?: {Settings is null}");
Console.WriteLine($"Settings.General is null?: {Settings.General is null}");
Console.WriteLine($"Screens is null?: {Screens is null}");
Console.WriteLine($"ScreenCount: {Screens.ScreenCount}");
Console.WriteLine($"Screens.Primary is null?: {Screens.Primary is null}");*/
var screen = Screens.Primary ?? Screens.All[0];
App.MaxWindowSize = new System.Drawing.Size(
Settings.General.WindowsTakeIntoAccountScreenScaling ? (int)(screen.WorkingArea.Width / screen.PixelDensity) : screen.WorkingArea.Width,
Settings.General.WindowsTakeIntoAccountScreenScaling ? (int)(screen.WorkingArea.Height / screen.PixelDensity) : screen.WorkingArea.Height);
}
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
var windowSize = this.GetScreenWorkingArea();
if (Settings.General.StartMaximized
|| ClientSize.Width > windowSize.Width
|| ClientSize.Height > windowSize.Height)
{
WindowState = WindowState.Maximized;
}
AddLog($"{About.Software} start", Program.ProgramStartupTime.Elapsed.TotalSeconds);
if (Settings.General.CheckForUpdatesOnStartup)
@@ -768,7 +764,6 @@ namespace UVtools.WPF
{
SettingsWindow settingsWindow = new SettingsWindow();
await settingsWindow.ShowDialog(this);
UpdateMaxWindowsSize();
}
public void OpenWebsite()
+4 -1
View File
@@ -12,7 +12,7 @@
<PackageLicenseFile>LICENSE</PackageLicenseFile>
<RepositoryUrl>https://github.com/sn4k3/UVtools</RepositoryUrl>
<RepositoryType>Git</RepositoryType>
<Version>2.1.0</Version>
<Version>2.1.1</Version>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
@@ -82,6 +82,9 @@
<Compile Update="Controls\AdvancedImageBox.axaml.cs">
<DependentUpon>AdvancedImageBox.axaml</DependentUpon>
</Compile>
<Compile Update="Controls\Calibrators\CalibrateExternalTestsControl.axaml.cs">
<DependentUpon>CalibrateExternalTestsControl.axaml</DependentUpon>
</Compile>
<Compile Update="Controls\Tools\ToolLayerRemoveControl.axaml.cs">
<DependentUpon>ToolLayerRemoveControl.axaml</DependentUpon>
</Compile>
+8 -4
View File
@@ -20,9 +20,9 @@ namespace UVtools.WPF.Windows
public string FrameworkDescription => RuntimeInformation.FrameworkDescription;
public int ProcessorCount => Environment.ProcessorCount;
public int ScreenCount => Screens.ScreenCount;
public string ScreenResolution => $"{Screens.Primary.Bounds.Width} x {Screens.Primary.Bounds.Height} @ {Screens.Primary.PixelDensity*100}%";
public string WorkingArea => $"{Screens.Primary.WorkingArea.Width} x {Screens.Primary.WorkingArea.Height}";
public string RealWorkingArea => $"{App.MaxWindowSize.Width} x {App.MaxWindowSize.Height}";
//public string ScreenResolution => $"{Screens.Primary.Bounds.Width} x {Screens.Primary.Bounds.Height} @ {Screens.Primary.PixelDensity*100}%";
//public string WorkingArea => $"{Screens.Primary.WorkingArea.Width} x {Screens.Primary.WorkingArea.Height}";
//public string RealWorkingArea => $"{App.MaxWindowSize.Width} x {App.MaxWindowSize.Height}";
public string ScreensDescription
{
@@ -31,8 +31,12 @@ namespace UVtools.WPF.Windows
var result = new StringBuilder();
for (int i = 0; i < Screens.All.Count; i++)
{
var onScreen = Screens.ScreenFromVisual(App.MainWindow);
var screen = Screens.All[i];
result.AppendLine($"{i+1}: {screen.Bounds.Width} x {screen.Bounds.Height} @ {screen.PixelDensity * 100}%");
result.AppendLine($"{i+1}: {screen.Bounds.Width} x {screen.Bounds.Height} @ {screen.PixelDensity * 100}%" +
(screen.Primary ? " (Primary)" : string.Empty) +
(onScreen == screen ? " (On this)" : string.Empty)
);
result.AppendLine($" WA: {screen.WorkingArea.Width} x {screen.WorkingArea.Height} UA: {Math.Round(screen.WorkingArea.Width / screen.PixelDensity)} x {Math.Round(screen.WorkingArea.Height / screen.PixelDensity)}");
}
return result.ToString().TrimEnd();
+1 -1
View File
@@ -60,7 +60,7 @@ namespace UVtools.WPF.Windows
s => Convert.ToString(s / 100, CultureInfo.InvariantCulture) + "x").ToArray();
ScrollViewerMaxHeight = App.MaxWindowSize.Height - Settings.General.WindowsVerticalMargin;
ScrollViewerMaxHeight = this.GetScreenWorkingArea().Height - Settings.General.WindowsVerticalMargin;
DataContext = this;
+1 -1
View File
@@ -524,7 +524,7 @@ namespace UVtools.WPF.Windows
DispatcherTimer.Run(() =>
{
if (Bounds.Width == 0) return true;
ScrollViewerMaxHeight = App.MaxWindowSize.Height - Bounds.Height + ToolControl.Bounds.Height - UserSettings.Instance.General.WindowsVerticalMargin;
ScrollViewerMaxHeight = this.GetScreenWorkingArea().Height - Bounds.Height + ToolControl.Bounds.Height - UserSettings.Instance.General.WindowsVerticalMargin;
DescriptionMaxWidth = Math.Max(Bounds.Width, ToolControl.Bounds.Width) - 40;
Description = toolControl.BaseOperation.Description;
return false;