diff --git a/UVtools.Core/FileFormats/ChituboxFile.cs b/UVtools.Core/FileFormats/ChituboxFile.cs index ead41c9..6ff4e23 100644 --- a/UVtools.Core/FileFormats/ChituboxFile.cs +++ b/UVtools.Core/FileFormats/ChituboxFile.cs @@ -867,15 +867,15 @@ namespace UVtools.Core.FileFormats { } - public LayerDataEx(LayerData layerData) + public LayerDataEx(LayerData layerData, uint layerIndex) { LayerData = layerData; if (!ReferenceEquals(layerData.Parent, null)) { - LiftHeight = layerData.Parent.LiftHeight; - LiftSpeed = layerData.Parent.LiftSpeed; - RetractSpeed = layerData.Parent.RetractSpeed; - LightPWM = layerData.Parent.HeaderSettings.LightPWM; + LiftHeight = layerData.Parent.GetInitialLayerValueOrNormal(layerIndex, layerData.Parent.PrintParametersSettings.BottomLiftHeight, layerData.Parent.PrintParametersSettings.LiftHeight); + LiftSpeed = layerData.Parent.GetInitialLayerValueOrNormal(layerIndex, layerData.Parent.PrintParametersSettings.BottomLiftSpeed, layerData.Parent.PrintParametersSettings.LiftSpeed); + RetractSpeed = layerData.Parent.PrintParametersSettings.RetractSpeed; + LightPWM = layerData.Parent.GetInitialLayerValueOrNormal(layerIndex, layerData.Parent.HeaderSettings.BottomLightPWM, layerData.Parent.HeaderSettings.LightPWM); } if (layerData.DataSize > 0) @@ -1096,7 +1096,8 @@ namespace UVtools.Core.FileFormats if(SlicerInfoSettings.MysteriousId == 0) SlicerInfoSettings.MysteriousId = 0x12345678; - SlicerInfoSettings.Unknown1 = HeaderSettings.Version == 3 ? 0u : 0x200; + if(SlicerInfoSettings.Unknown1 == 0) + SlicerInfoSettings.Unknown1 = HeaderSettings.Version == 3 ? 0u : 0x200; if (HeaderSettings.EncryptionKey == 0) { @@ -1166,7 +1167,7 @@ namespace UVtools.Core.FileFormats HeaderSettings.LayersDefinitionOffsetAddress = currentOffset; uint layerDataCurrentOffset = currentOffset + (uint)Helpers.Serializer.SizeOf(new LayerData()) * HeaderSettings.LayerCount * HeaderSettings.AntiAliasLevel; - + progress.ItemCount *= 2 * HeaderSettings.AntiAliasLevel; for (byte aaIndex = 0; aaIndex < HeaderSettings.AntiAliasLevel; aaIndex++) @@ -1208,11 +1209,18 @@ namespace UVtools.Core.FileFormats } } - if (ReferenceEquals(layerDataHash, null)) + if (layerDataHash is null) { layerData.DataAddress = layerDataCurrentOffset; outputFile.Seek(layerDataCurrentOffset, SeekOrigin.Begin); + + if (HeaderSettings.Version >= 3) + { + var layerDataEx = new LayerDataEx(layerData, layerIndex); + layerData.DataAddress = layerDataCurrentOffset += Helpers.SerializeWriteFileStream(outputFile, layerDataEx); + } + layerDataCurrentOffset += outputFile.WriteBytes(layerData.EncodedRle); } diff --git a/UVtools.Core/Operations/Operation.cs b/UVtools.Core/Operations/Operation.cs index 8b20d86..4824a10 100644 --- a/UVtools.Core/Operations/Operation.cs +++ b/UVtools.Core/Operations/Operation.cs @@ -5,6 +5,9 @@ * Everyone is permitted to copy and distribute verbatim copies * of this license document, but changing it is not allowed. */ + +using UVtools.Core.Obects; + namespace UVtools.Core.Operations { public class Operation @@ -16,8 +19,30 @@ namespace UVtools.Core.Operations /// public string Id => GetType().Name.Remove(0, ClassNameLength); + /// + /// Gets the title of this operation + /// + public virtual string Title => Id; + + /// + /// Gets a descriptive text of this operation + /// + public virtual string Description => Id; + + /// + /// Gets the Ok button text + /// + public virtual string ButtonOkText => Title; + + /// + /// Gets the confirmation text for the operation + /// public virtual string ConfirmationText => $"Are you sure you want to {Id}"; - public virtual string Validate() => null; + /// + /// Validates the operation + /// + /// null or empty if validates, or else, return a string with error message + public virtual StringTag Validate(params object[] parameters) => null; } } diff --git a/UVtools.Core/Operations/OperationChangeResolution.cs b/UVtools.Core/Operations/OperationChangeResolution.cs index e022b68..c2580ba 100644 --- a/UVtools.Core/Operations/OperationChangeResolution.cs +++ b/UVtools.Core/Operations/OperationChangeResolution.cs @@ -1,10 +1,12 @@ using System.Drawing; using System.Text; +using UVtools.Core.Obects; namespace UVtools.Core.Operations { public sealed class OperationChangeResolution : Operation { + #region Subclasses public class Resolution { public uint ResolutionX { get; } @@ -28,7 +30,41 @@ namespace UVtools.Core.Operations return str; } } + #endregion + #region Overrides + + public override string Title => "Change Resolution"; + public override string Description => + "Crops or resizes all layer images to fit an alternate print area\n" + + "Useful to make files printable on a different printer than they were originally sliced for without the need to re-slice.\n" + + "NOTE: Please ensure that the actual object will fit within the new print resolution. The operation will be aborted if it will result in any of the actual model being clipped."; + + public override string ConfirmationText => + "Are you sure you want change file resolution?\n" + + $"From: {OldResolutionX} x {OldResolutionY}\n" + + $"To: {NewResolutionX} x {NewResolutionY}"; + + public override StringTag Validate(params object[] parameters) + { + var sb = new StringBuilder(); + if (OldResolutionX == NewResolutionX && OldResolutionY == NewResolutionY) + { + sb.AppendLine($"The new resolution must be different from current resolution ({OldResolutionX} x {OldResolutionY})."); + } + + if (NewResolutionX < VolumeBonds.Width || NewResolutionY < VolumeBonds.Height) + { + sb.AppendLine($"The new resolution ({NewResolutionX} x {NewResolutionY}) is not enough to accommodate the object volume ({VolumeBonds.Width} x {VolumeBonds.Height}), continuing operation would cut the object"); + sb.AppendLine("To fix this, try to rotate the object and/or resize to fit on this new resolution."); + } + + return new StringTag(sb.ToString()); + } + + #endregion + + #region Properties public uint OldResolutionX { get; } public uint OldResolutionY { get; } @@ -36,17 +72,16 @@ namespace UVtools.Core.Operations public uint NewResolutionY { get; set; } public Rectangle VolumeBonds { get; } - public override string ConfirmationText => "Are you sure you want change file resolution?\n" + - $"From: {OldResolutionX} x {OldResolutionY}\n" + - $"To: {NewResolutionX} x {NewResolutionY}"; + #endregion + #region Constructor public OperationChangeResolution(uint oldResolutionX, uint oldResolutionY, Rectangle volumeBonds) { OldResolutionX = oldResolutionX; OldResolutionY = oldResolutionY; VolumeBonds = volumeBonds; } - + #endregion public static Resolution[] GetResolutions() { @@ -68,21 +103,6 @@ namespace UVtools.Core.Operations }; } - public override string Validate() - { - var sb = new StringBuilder(); - if (OldResolutionX == NewResolutionX && OldResolutionY == NewResolutionY) - { - sb.AppendLine($"The new resolution must be different from current resolution ({OldResolutionX} x {OldResolutionY})."); - } - - if (NewResolutionX < VolumeBonds.Width || NewResolutionY < VolumeBonds.Height) - { - sb.AppendLine($"The new resolution ({NewResolutionX} x {NewResolutionY}) is not enough to accommodate the object volume ({VolumeBonds.Width} x {VolumeBonds.Height}), continuing operation would cut the object"); - sb.AppendLine("To fix this, try to rotate the object and/or resize to fit on this new resolution."); - } - - return sb.ToString(); - } + } } diff --git a/UVtools.Core/Operations/OperationLayerImport.cs b/UVtools.Core/Operations/OperationLayerImport.cs index a60407a..9547dcf 100644 --- a/UVtools.Core/Operations/OperationLayerImport.cs +++ b/UVtools.Core/Operations/OperationLayerImport.cs @@ -4,14 +4,18 @@ using System.Collections.Generic; using System.Diagnostics; using System.Drawing; using System.IO; +using System.Text; using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.CvEnum; +using Emgu.CV.Ocl; +using UVtools.Core.Obects; namespace UVtools.Core.Operations { public sealed class OperationLayerImport : Operation { + public Size FileResolution { get; } public uint InsertAfterLayerIndex { get; set; } public bool ReplaceStartLayer { get; set; } public bool ReplaceSubsequentLayers { get; set; } @@ -21,27 +25,55 @@ namespace UVtools.Core.Operations public int Count => Files.Count; + public override string Title => "Import Layer(s)"; + + public override string Description => + "Import layer(s) from local file(s) into the model at a selected height.\n" + + "NOTE: Images must respect file resolution and in greyscale color."; + public override string ConfirmationText => $"import {Count} layer(s)?"; + public OperationLayerImport(Size fileResolution) + { + FileResolution = fileResolution; + } + public void Sort() { Files.Sort((file1, file2) => string.Compare(Path.GetFileNameWithoutExtension(file1), Path.GetFileNameWithoutExtension(file2), StringComparison.Ordinal)); } - public ConcurrentBag Validate(Size resolution) + public override StringTag Validate(params object[] parameters) { var result = new ConcurrentBag(); Parallel.ForEach(Files, file => { using (Mat mat = CvInvoke.Imread(file, ImreadModes.AnyColor)) { - if (mat.Size != resolution) + if (mat.Size != FileResolution) { result.Add(file); } } }); - return result; + + if (result.IsEmpty) return null; + var message = new StringBuilder(); + message.AppendLine($"The following {result.Count} files mismatched the slice resolution of {FileResolution.Width} x {FileResolution.Height}:"); + message.AppendLine(); + uint count = 0; + foreach (var file in result) + { + count++; + if (count == 20) + { + message.AppendLine("... To many to show ..."); + break; + } + message.AppendLine(Path.GetFileNameWithoutExtension(file)); + } + + return new StringTag(message.ToString(), result); } public uint CalculateTotalLayers(uint totalLayers) diff --git a/UVtools.GUI/Controls/CtrlToolWindowContent.cs b/UVtools.GUI/Controls/CtrlToolWindowContent.cs index 470c846..0c3a213 100644 --- a/UVtools.GUI/Controls/CtrlToolWindowContent.cs +++ b/UVtools.GUI/Controls/CtrlToolWindowContent.cs @@ -10,6 +10,8 @@ using System.Drawing.Design; using System.Runtime.CompilerServices; using System.Windows.Forms; using UVtools.Core.Extensions; +using UVtools.Core.Obects; +using UVtools.Core.Operations; using UVtools.GUI.Annotations; using UVtools.GUI.Forms; @@ -71,9 +73,10 @@ namespace UVtools.GUI.Controls } #endregion - #region Properties + [ReadOnly(true)] [Browsable(false)] public Operation BaseOperation { get; private set; } + [ReadOnly(true)] [Browsable(false)] public FrmToolWindow ParentToolWindow => ParentForm as FrmToolWindow; [Editor("System.ComponentModel.Design.MultilineStringEditor", typeof(UITypeEditor))] @@ -108,7 +111,18 @@ namespace UVtools.GUI.Controls [ReadOnly(true)] [Browsable(false)] - public virtual string ConfirmationText => $"{Text}?"; + public virtual string ConfirmationText + { + get + { + if (BaseOperation is null || string.IsNullOrEmpty(BaseOperation.ConfirmationText)) + { + return $"{Text}?"; + } + + return BaseOperation.ConfirmationText; + } + } #endregion @@ -121,8 +135,35 @@ namespace UVtools.GUI.Controls #region Methods - public virtual bool ValidateForm() => true; + public void SetOperation(Operation operation) + { + BaseOperation = operation; + if(!string.IsNullOrEmpty(operation.Title)) Text = operation.Title; + if (!string.IsNullOrEmpty(operation.Description)) Description = operation.Description; + if (!string.IsNullOrEmpty(operation.ButtonOkText)) ButtonOkText = operation.ButtonOkText; + } + /// + /// Updates operation object with items retrieved from form fields + /// + public virtual void UpdateOperation(){} + + /// + /// Validates if is safe to continue with operation + /// + /// + public virtual bool ValidateForm() + { + if (BaseOperation is null) return true; + UpdateOperation(); + return ValidateFormFromString(BaseOperation.Validate()); + } + + /// + /// Validates if is safe to continue with operation, if not shows a message box with the error + /// + /// + /// public bool ValidateFormFromString(string text) { if (string.IsNullOrEmpty(text)) return true; @@ -130,6 +171,19 @@ namespace UVtools.GUI.Controls return false; } + /// + /// Validates if is safe to continue with operation, if not shows a message box with the error + /// + /// + /// + public bool ValidateFormFromString(StringTag text) + { + if (text is null) return true; + if (string.IsNullOrEmpty(text.ToString())) return true; + MessageBoxError(text.ToString()); + return false; + } + public DialogResult MessageBoxError(string message, MessageBoxButtons buttons = MessageBoxButtons.OK) => GUIExtensions.MessageErrorBox($"{Text} Error", message, buttons); public DialogResult MessageQuestionBox(string message, string title = null, MessageBoxButtons buttons = MessageBoxButtons.YesNo) => GUIExtensions.MessageQuestionBox($"{title ?? Text}", message, buttons); diff --git a/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.Designer.cs index 3ddaa2a..656e578 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.Designer.cs +++ b/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.Designer.cs @@ -28,7 +28,6 @@ /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(CtrlToolChangeResolution)); this.lbObjectVolume = new System.Windows.Forms.Label(); this.nmNewY = new System.Windows.Forms.NumericUpDown(); this.label3 = new System.Windows.Forms.Label(); @@ -149,7 +148,6 @@ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.ButtonOkText = "Change Resolution"; this.Controls.Add(this.lbObjectVolume); this.Controls.Add(this.nmNewY); this.Controls.Add(this.label3); @@ -158,7 +156,7 @@ this.Controls.Add(this.cbPreset); this.Controls.Add(this.label2); this.Controls.Add(this.lbCurrent); - this.Description = resources.GetString("$this.Description"); + this.Description = ""; this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.LayerRangeVisible = false; this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); diff --git a/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.cs b/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.cs index 898d11e..3398aa8 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.cs +++ b/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.cs @@ -18,13 +18,11 @@ namespace UVtools.GUI.Controls.Tools public uint NewResolutionX => (uint) nmNewX.Value; public uint NewResolutionY => (uint) nmNewY.Value; - public override string ConfirmationText => Operation.ConfirmationText; - public CtrlToolChangeResolution(uint oldResolutionX, uint oldResolutionY, Rectangle volumeBonds) { InitializeComponent(); - Text = "Change Resolution"; Operation = new OperationChangeResolution(oldResolutionX, oldResolutionY, volumeBonds); + SetOperation(Operation); lbCurrent.Text = $"Current resolution (X/Y): {oldResolutionX} x {oldResolutionY}"; lbObjectVolume.Text = $"Object volume (X/Y): {volumeBonds.Width} x {volumeBonds.Height}"; @@ -58,11 +56,10 @@ namespace UVtools.GUI.Controls.Tools } } - public override bool ValidateForm() + public override void UpdateOperation() { Operation.NewResolutionX = NewResolutionX; Operation.NewResolutionY = NewResolutionY; - return ValidateFormFromString(Operation.Validate()); } } } diff --git a/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.resx b/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.resx index fdaf0d0..8766f29 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.resx +++ b/UVtools.GUI/Controls/Tools/CtrlToolChangeResolution.resx @@ -120,10 +120,4 @@ 17, 17 - - Changes images resolution (X/Y). -Usefull to make files printable under a different printer resolution without have to reslice. -Note 1: Before run this tool, ensure object rotatation and volume fits new resolution. -Note 2: Object will auto-center on new resolution. - \ No newline at end of file diff --git a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs index 9b53b62..e831616 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs +++ b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.Designer.cs @@ -281,7 +281,6 @@ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.ButtonOkText = "Import"; this.Controls.Add(this.cbDiscardRemainingLayers); this.Controls.Add(this.cbReplaceSubsequentLayers); this.Controls.Add(this.lbResult); @@ -292,8 +291,6 @@ this.Controls.Add(this.nmInsertAfterLayer); this.Controls.Add(this.label1); this.Controls.Add(this.splitContainer); - this.Description = "Import layer(s) from local file(s) into the model at a selected height.\r\nNOTE: Im" + - "ages must respect file resolution and in greyscale color."; this.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); this.LayerRangeVisible = false; this.Margin = new System.Windows.Forms.Padding(4, 5, 4, 5); diff --git a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs index d72a757..b1d8512 100644 --- a/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs +++ b/UVtools.GUI/Controls/Tools/CtrlToolLayerImport.cs @@ -7,6 +7,7 @@ */ using System; +using System.Collections.Concurrent; using System.Diagnostics; using System.Drawing; using System.IO; @@ -19,12 +20,13 @@ namespace UVtools.GUI.Controls.Tools { public partial class CtrlToolLayerImport : CtrlToolWindowContent { - public OperationLayerImport Operation { get; } = new OperationLayerImport(); + public OperationLayerImport Operation { get; } public CtrlToolLayerImport(uint currentLayer = 0) { InitializeComponent(); - Text = "Import Layer(s)"; + Operation = new OperationLayerImport(Program.FrmMain.ActualLayerImage.Size); + SetOperation(Operation); nmInsertAfterLayer.Maximum = Program.SlicerFile.LayerCount-1; @@ -32,9 +34,7 @@ namespace UVtools.GUI.Controls.Tools nmInsertAfterLayer_ValueChanged(nmInsertAfterLayer, EventArgs.Empty); } - public override string ConfirmationText => Operation.ConfirmationText; - - public void UpdateOperation() + public override void UpdateOperation() { Operation.InsertAfterLayerIndex = (uint)nmInsertAfterLayer.Value; Operation.ReplaceStartLayer = cbReplaceStartLayer.Checked; @@ -46,29 +46,14 @@ namespace UVtools.GUI.Controls.Tools public override bool ValidateForm() { UpdateOperation(); - var result = Operation.Validate(Program.FrmMain.ActualLayerImage.Size); - if (result.Count == 0) return true; + var message = Operation.Validate(); + if (message is null) return true; - var message = new StringBuilder(); - message.AppendLine($"The following {result.Count} files mismatched the slice resolution of {Program.FrmMain.ActualLayerImage.Size.Width}x{Program.FrmMain.ActualLayerImage.Size.Height}:"); - message.AppendLine(); - uint count = 0; - foreach (var file in result) - { - count++; - if (count == 20) - { - message.AppendLine("... To many to show ..."); - break; - } - message.AppendLine(Path.GetFileNameWithoutExtension(file)); - - } - message.AppendLine(); - message.AppendLine("Do you want to remove all invalid files from list?"); + message.Content += "\nDo you want to remove all invalid files from list?"; if (MessageBoxError(message.ToString(), MessageBoxButtons.YesNo) == DialogResult.Yes) { + ConcurrentBag result = (ConcurrentBag)message.Tag; foreach (var file in result) { Operation.Files.Remove(file);