diff --git a/ApplicationView/ApplicationController.cs b/ApplicationView/ApplicationController.cs index 5bcef76e5..2a4767fbb 100644 --- a/ApplicationView/ApplicationController.cs +++ b/ApplicationView/ApplicationController.cs @@ -280,16 +280,21 @@ namespace MatterHackers.MatterControl () => "Subtract".Localize(), (scene) => { - var difference = new MeshWrapperOperation(scene.SelectedItem.Children) + var children = scene.SelectedItem.Children; + scene.SelectedItem = null; + + var difference = new MeshWrapperOperation(new List (children.Select((i) => i.Clone()))) { ActiveEditor = nameof(SubtractEditor), Name = "Subtract", }; - scene.SelectedItem.Children.Modify((list) => - { - list.Clear(); - }); - scene.Children.Add(difference); + + scene.UndoBuffer.AddAndDo( + new ReplaceCommand( + new List(children), + new List { difference })); + + difference.MakeNameNonColliding(); scene.SelectedItem = difference; } }, @@ -297,17 +302,21 @@ namespace MatterHackers.MatterControl () => "Intersect".Localize(), (scene) => { - var intersection = new MeshWrapperOperation(scene.SelectedItem.Children) + var selectedItems = scene.SelectedItem.Children; + scene.SelectedItem = null; + + var intersection = new MeshWrapperOperation(new List (selectedItems.Select((i) => i.Clone()))) { ActiveEditor = nameof(IntersectionEditor), Name = "Intersect", }; - scene.SelectedItem.Children.Modify((list) => - { - list.Clear(); - }); - scene.Children.Add(intersection); + scene.UndoBuffer.AddAndDo( + new ReplaceCommand( + new List(selectedItems), + new List { intersection })); + + intersection.MakeNameNonColliding(); scene.SelectedItem = intersection; } }, @@ -316,16 +325,21 @@ namespace MatterHackers.MatterControl () => "Paint Material".Localize(), (scene) => { - var materialPaint = new MeshWrapperOperation(scene.SelectedItem.Children) + var selectedItems = scene.SelectedItem.Children; + scene.SelectedItem = null; + + var materialPaint = new MeshWrapperOperation(new List (selectedItems.Select((i) => i.Clone()))) { ActiveEditor = nameof(PaintMaterialEditor), Name = "Material Paint", }; - scene.SelectedItem.Children.Modify((list) => - { - list.Clear(); - }); - scene.Children.Add(materialPaint); + + scene.UndoBuffer.AddAndDo( + new ReplaceCommand( + new List(selectedItems), + new List { materialPaint })); + + materialPaint.MakeNameNonColliding(); scene.SelectedItem = materialPaint; } }, diff --git a/Library/Providers/FileSystem/FileSystemContainer.cs b/Library/Providers/FileSystem/FileSystemContainer.cs index 34f459f51..6ff61ab3f 100644 --- a/Library/Providers/FileSystem/FileSystemContainer.cs +++ b/Library/Providers/FileSystem/FileSystemContainer.cs @@ -34,6 +34,7 @@ using System.IO; using System.Linq; using System.Text.RegularExpressions; using System.Threading.Tasks; +using MatterHackers.Agg; using MatterHackers.Agg.Platform; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; @@ -49,8 +50,6 @@ namespace MatterHackers.MatterControl.Library private bool isActiveContainer; private bool isDirty; - private static Regex fileNameNumberMatch = new Regex("\\(\\d+\\)", RegexOptions.Compiled); - public FileSystemContainer(string path) { this.fullPath = path; @@ -205,29 +204,14 @@ namespace MatterHackers.MatterControl.Library private string GetNonCollidingName(string fileName) { - string incrementedFilePath; - string fileExtension = Path.GetExtension(fileName); - // Switching from .stl, .obj or similar to AMF. Save the file and update the // the filename with an incremented (n) value to reflect the extension change in the UI - fileName = Path.GetFileNameWithoutExtension(fileName); + var similarFileNames = Directory.GetFiles(this.fullPath, $"{Path.GetFileNameWithoutExtension(fileName)}.*"); - // Drop bracketed number sections from our source filename to ensure we don't generate something like "file (1) (1).amf" - if (fileName.Contains("(")) - { - fileName = fileNameNumberMatch.Replace(fileName, "").Trim(); - } + // ; + var validName = agg_basics.GetNonCollidingName(fileName, (testName) => !File.Exists(testName)); - // Generate and search for an incremented file name until no match is found at the target directory - int foundCount = 1; - do - { - incrementedFilePath = Path.Combine(this.fullPath, $"{fileName} ({foundCount++}){fileExtension}"); - - // Continue incrementing while any matching file exists - } while (File.Exists(incrementedFilePath)); - - return incrementedFilePath; + return validName; } public async override void Add(IEnumerable items) diff --git a/Library/Widgets/InsertionGroup.cs b/Library/Widgets/InsertionGroup.cs index 19e7a2017..ffe34c9b3 100644 --- a/Library/Widgets/InsertionGroup.cs +++ b/Library/Widgets/InsertionGroup.cs @@ -121,6 +121,8 @@ namespace MatterHackers.MatterControl.PrintLibrary this.Children.Add(loadedItem); + loadedItem.MakeNameNonColliding(); + // Wait for content to load // Adjust next item position diff --git a/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs b/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs index 3c9c60d54..c0887efdd 100644 --- a/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs +++ b/PartPreviewWindow/View3D/Actions/MeshWrapperOperation.cs @@ -27,6 +27,7 @@ of the authors and should not be interpreted as representing official policies, either expressed or implied, of the FreeBSD Project. */ +using System.Collections.Generic; using System.Linq; using MatterHackers.DataConverters3D; using MatterHackers.PolygonMesh; @@ -39,7 +40,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { } - public MeshWrapperOperation(SafeList children) + public MeshWrapperOperation(List children) { Children.Modify((list) => { diff --git a/PartPreviewWindow/View3D/Actions/PaintMaterialEditor.cs b/PartPreviewWindow/View3D/Actions/PaintMaterialEditor.cs index 71ea02cf5..735cb976a 100644 --- a/PartPreviewWindow/View3D/Actions/PaintMaterialEditor.cs +++ b/PartPreviewWindow/View3D/Actions/PaintMaterialEditor.cs @@ -153,26 +153,23 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D { foreach (var keep in keepObjects) { - if (paint.MaterialIndex != keep.MaterialIndex) - { - var transformedPaint = Mesh.Copy(paint.Mesh, CancellationToken.None); - transformedPaint.Transform(paint.WorldMatrix()); + var transformedPaint = Mesh.Copy(paint.Mesh, CancellationToken.None); + transformedPaint.Transform(paint.WorldMatrix()); - var transformedKeep = Mesh.Copy(keep.Mesh, CancellationToken.None); - transformedKeep.Transform(keep.WorldMatrix()); + var transformedKeep = Mesh.Copy(keep.Mesh, CancellationToken.None); + transformedKeep.Transform(keep.WorldMatrix()); - // remove the paint from the original - var intersectAndSubtract = PolygonMesh.Csg.CsgOperations.IntersectAndSubtract(transformedKeep, transformedPaint); - var inverseKeep = keep.WorldMatrix(); - inverseKeep.Invert(); - intersectAndSubtract.subtract.Transform(inverseKeep); - keep.Mesh = intersectAndSubtract.subtract; + // remove the paint from the original + var intersectAndSubtract = PolygonMesh.Csg.CsgOperations.IntersectAndSubtract(transformedKeep, transformedPaint); + var inverseKeep = keep.WorldMatrix(); + inverseKeep.Invert(); + intersectAndSubtract.subtract.Transform(inverseKeep); + keep.Mesh = intersectAndSubtract.subtract; - var inverseRemove = paint.WorldMatrix(); - inverseRemove.Invert(); - intersectAndSubtract.intersect.Transform(inverseRemove); - paint.Mesh = intersectAndSubtract.intersect; - } + var inverseRemove = paint.WorldMatrix(); + inverseRemove.Invert(); + intersectAndSubtract.intersect.Transform(inverseRemove); + paint.Mesh = intersectAndSubtract.intersect; } // now set it to the new solid color diff --git a/PartPreviewWindow/View3D/SceneActions.cs b/PartPreviewWindow/View3D/SceneActions.cs index df510508f..2e2ac4e29 100644 --- a/PartPreviewWindow/View3D/SceneActions.cs +++ b/PartPreviewWindow/View3D/SceneActions.cs @@ -32,10 +32,12 @@ using System.Globalization; using System.Linq; using System.Threading; using System.Threading.Tasks; +using MatterHackers.Agg; using MatterHackers.Agg.UI; using MatterHackers.DataConverters3D; using MatterHackers.Localizations; using MatterHackers.MeshVisualizer; +using MatterHackers.PolygonMesh; using MatterHackers.VectorMath; namespace MatterHackers.MatterControl.PartPreviewWindow @@ -157,14 +159,24 @@ namespace MatterHackers.MatterControl.PartPreviewWindow // Copy selected item IObject3D newItem = await Task.Run(() => { - // new item can be null by the time this task kicks off - var clonedItem = Scene.SelectedItem?.Clone(); + var originalItem = Scene.SelectedItem; + if (originalItem != null) + { + // new item can be null by the time this task kicks off + var clonedItem = originalItem.Clone(); - // More usefull if it creates the part in the exact positon and then the user can move it. - // Consistent with othre software as well. LBB 2017-12-02 - //PlatingHelper.MoveToOpenPositionRelativeGroup(clonedItem, Scene.Children); + // make the name unique + var newName = agg_basics.GetNonCollidingName(originalItem.Name, Scene.Descendants().Select((d) => d.Name)); + clonedItem.Name = newName; - return clonedItem; + // More usefull if it creates the part in the exact positon and then the user can move it. + // Consistent with othre software as well. LBB 2017-12-02 + //PlatingHelper.MoveToOpenPositionRelativeGroup(clonedItem, Scene.Children); + + return clonedItem; + } + + return null; }); if (view3DWidget.HasBeenClosed) diff --git a/PartPreviewWindow/ViewControls3D.cs b/PartPreviewWindow/ViewControls3D.cs index 99ab18c0d..bbae4a96a 100644 --- a/PartPreviewWindow/ViewControls3D.cs +++ b/PartPreviewWindow/ViewControls3D.cs @@ -316,6 +316,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow { var button = new TextButton(namedAction.Title, theme) { + Name = namedAction.Title + " Button", VAnchor = VAnchor.Center, Margin = theme.ButtonSpacing, BackgroundColor = theme.MinimalShade diff --git a/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs b/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs index c5d0070cb..8a9b791b2 100644 --- a/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs +++ b/PrinterControls/PrinterConnections/SetupStepMakeModelName.cs @@ -259,7 +259,7 @@ namespace MatterHackers.MatterControl.PrinterControls.PrinterConnections string mappedMakeText = printerManufacturerSelector.SelectedLabel; var existingPrinterNames = ProfileManager.Instance.ActiveProfiles.Select(p => p.Name); - printerNameInput.Text = agg_basics.GetNonCollidingName(existingPrinterNames, $"{mappedMakeText} {activeModel}"); + printerNameInput.Text = agg_basics.GetNonCollidingName($"{mappedMakeText} {activeModel}", existingPrinterNames); } }); } diff --git a/SlicerConfiguration/Settings/ProfileManager.cs b/SlicerConfiguration/Settings/ProfileManager.cs index f0c29a883..6840a5745 100644 --- a/SlicerConfiguration/Settings/ProfileManager.cs +++ b/SlicerConfiguration/Settings/ProfileManager.cs @@ -350,7 +350,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration var printerInfo = new PrinterInfo { - Name = agg_basics.GetNonCollidingName(existingPrinterNames, fileName), + Name = agg_basics.GetNonCollidingName(fileName, existingPrinterNames), ID = Guid.NewGuid().ToString(), Make = "Other", Model = "Other", diff --git a/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs b/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs index be8b43062..c3b3e6ed4 100644 --- a/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs +++ b/SlicerConfiguration/SlicePresetsWindow/SlicePresetsWindow.cs @@ -161,26 +161,6 @@ namespace MatterHackers.MatterControl.SlicerConfiguration }; } - private string GetNonCollidingName(string profileName, IEnumerable existingNames) - { - if (!existingNames.Contains(profileName)) - { - return profileName; - } - else - { - int currentIndex = 1; - string possiblePrinterName; - - do - { - possiblePrinterName = String.Format("{0} ({1})", profileName, currentIndex++); - } while (existingNames.Contains(possiblePrinterName)); - - return possiblePrinterName; - } - } - private FlowLayoutWidget GetBottomRow(TextImageButtonFactory buttonFactory) { var container = new FlowLayoutWidget() @@ -195,7 +175,7 @@ namespace MatterHackers.MatterControl.SlicerConfiguration UiThread.RunOnIdle(() => { string sanitizedName = numberMatch.Replace(presetNameInput.Text, "").Trim(); - string newProfileName = GetNonCollidingName(sanitizedName, presetsContext.PresetLayers.Select(preset => preset.ValueOrDefault(SettingsKey.layer_name))); + string newProfileName = agg_basics.GetNonCollidingName(sanitizedName, presetsContext.PresetLayers.Select(preset => preset.ValueOrDefault(SettingsKey.layer_name))); var clonedLayer = presetsContext.PersistenceLayer.Clone(); clonedLayer.Name = newProfileName; diff --git a/Submodules/agg-sharp b/Submodules/agg-sharp index 207215ac2..612f60db0 160000 --- a/Submodules/agg-sharp +++ b/Submodules/agg-sharp @@ -1 +1 @@ -Subproject commit 207215ac28662e4e370a6f71c114a28904974686 +Subproject commit 612f60db00c94d3338ec44389f5643ef09b7316f